(folder, encrypted)
| 2942 | } |
| 2943 | |
| 2944 | async function setFolderEncryption(folder, encrypted) { |
| 2945 | try { |
| 2946 | const resp = await fetchWithCsrf('/api/folder/setFolderEncryption.php', { |
| 2947 | method: 'POST', |
| 2948 | headers: { 'Content-Type': 'application/json' }, |
| 2949 | body: JSON.stringify({ folder, encrypted: !!encrypted }) |
| 2950 | }); |
| 2951 | const data = await safeJson(resp); |
| 2952 | |
| 2953 | if (!data || data.ok !== true) { |
| 2954 | showToast((data && (data.error || data.message)) || t('folder_encryption_update_failed'), 'error'); |
| 2955 | return; |
| 2956 | } |
| 2957 | |
| 2958 | // Update local UI for this folder + any rendered descendants |
| 2959 | const esc = CSS.escape(folder); |
| 2960 | const sel = `.folder-option[data-folder="${esc}"], .folder-option[data-folder^="${esc}/"]`; |
| 2961 | document.querySelectorAll(sel).forEach(opt => { |
| 2962 | opt.classList.toggle('encrypted', !!encrypted); |
| 2963 | const iconEl = opt.querySelector('.folder-icon'); |
| 2964 | if (iconEl) { |
| 2965 | const kind = iconEl?.dataset?.kind || 'empty'; |
| 2966 | // nosemgrep: javascript.browser.security.dom-xss.innerhtml |
| 2967 | iconEl.innerHTML = folderSVG(kind, { locked: opt.classList.contains('locked'), encrypted: opt.classList.contains('encrypted') }); |
| 2968 | } |
| 2969 | }); |
| 2970 | |
| 2971 | invalidateFolderCaches(folder); |
| 2972 | await applyFolderCapabilities(folder); |
| 2973 | showToast(encrypted ? t('folder_encryption_enabled') : t('folder_encryption_disabled'), 'success'); |
| 2974 | } catch (e) { |
| 2975 | console.error('setFolderEncryption failed', e); |
| 2976 | showToast((e && e.message) ? e.message : t('folder_encryption_update_failed'), 'error'); |
| 2977 | } |
| 2978 | } |
| 2979 | |
| 2980 | /* ---------------------- |
| 2981 | Encryption v2: confirm + progress UI (minimizable) |
nothing calls this directly
no test coverage detected