diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/photo-sync-settings.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/photo-sync-settings.js | 97 |
1 files changed, 27 insertions, 70 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/photo-sync-settings.js b/packages/meshbay-hub/src/meshbay_hub/static/photo-sync-settings.js index b5e9a30..7809efa 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/photo-sync-settings.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/photo-sync-settings.js @@ -1,14 +1,14 @@ // The "Photo backup" section of the Android Sync page, on the Android // application only (docs/MESHBAY_DESIGN.md §9.12). Loaded on demand: no other -// client has it. +// client has it. Where the photos go is the page's destination section; +// this one chooses which. import { html, useState, useEffect, useCallback } from './vendor/htm-preact.js'; import { t } from './i18n.js'; import * as platform from './platform.js'; -import { hubFetch } from './hub-client.js'; import { formatSize } from './file-utils.js'; import { ask } from './ask.js'; -import { subscribe, runPhotoSync, probeGroup } from './photo-sync.js'; +import { subscribe, runPhotoSync } from './photo-sync.js'; function stateLine(st, status) { switch (st.phase) { @@ -30,10 +30,11 @@ const FAILURES = { no_such_directory: 'photosync.fail_no_folder', root_unavailable: 'photosync.fail_unavailable', not_a_member: 'photosync.fail_not_member', + not_private: 'photosync.fail_not_private', permission: 'photosync.fail_permission', }; -export function PhotoSyncSection({ user, groups }) { +export function PhotoSyncSection({ destination }) { const [status, setStatus] = useState(null); const [run, setRun] = useState({ phase: 'idle' }); const [editing, setEditing] = useState(false); @@ -51,6 +52,16 @@ export function PhotoSyncSection({ user, groups }) { if (!status) return null; const cfg = status.config; + if (!destination) { + return html` + <div class="settings-section"> + <h3 class="settings-heading">${t('photosync.heading')}</h3> + <p class="settings-hint">${t('photosync.intro')}</p> + <p class="settings-hint">${t('androidsync.dest_needed')}</p> + </div> + `; + } + const backUpNow = async () => { setError(''); try { @@ -82,11 +93,9 @@ export function PhotoSyncSection({ user, groups }) { ${cfg && !editing && html` <div class="settings-row"> <span class="settings-label settings-name"> - ${t('photosync.summary', { group: cfg.groupName, owner: cfg.owner, folder: cfg.folder })} + ${t('phonesync.summary', { group: destination.groupName, dir: status.dir })} </span> </div> - ${cfg.account !== user.username && html` - <p class="settings-hint">${t('photosync.other_account', { account: cfg.account })}</p>`} <p class="settings-hint"> ${t('photosync.sent_total', { n: status.sent })} ${' · '} @@ -107,7 +116,7 @@ export function PhotoSyncSection({ user, groups }) { </div> `} ${editing && html` - <${Setup} user=${user} groups=${groups} status=${status} + <${Setup} status=${status} onPermission=${setStatus} onDone=${(next) => { setEditing(false); if (next) { setStatus(next); runPhotoSync(); } }} />`} ${error && html`<p class="error-msg">${error}</p>`} @@ -115,12 +124,8 @@ export function PhotoSyncSection({ user, groups }) { `; } -function Setup({ user, groups, status, onPermission, onDone }) { - const cfg = status.config && status.config.account === user.username ? status.config : null; - const [groupId, setGroupId] = useState(cfg ? cfg.groupId : ''); - const [folders, setFolders] = useState(null); // null while unknown - const [probe, setProbe] = useState(''); // '', 'checking', 'offline' - const [folder, setFolder] = useState(cfg ? cfg.folder : ''); +function Setup({ status, onPermission, onDone }) { + const cfg = status.config; const [albums, setAlbums] = useState(null); const [chosen, setChosen] = useState(() => new Set(cfg ? cfg.albums : [])); const [existing, setExisting] = useState(cfg ? cfg.includeExisting : true); @@ -138,20 +143,6 @@ function Setup({ user, groups, status, onPermission, onDone }) { }).catch((e) => setError(e.message)); }, [permitted]); - useEffect(() => { - setFolders(null); - if (!groupId) return; - let gone = false; - setProbe('checking'); - probeGroup(groupId).then((r) => { - if (gone) return; - setProbe(''); - setFolders(r.folders); - setFolder((f) => (r.folders.includes(f) ? f : (r.folders[0] || ''))); - }).catch(() => { if (!gone) setProbe('offline'); }); - return () => { gone = true; }; - }, [groupId]); - const allow = async () => { setError(''); try { onPermission(await platform.photoSync.permit()); } catch (e) { setError(e.message); } @@ -164,30 +155,16 @@ function Setup({ user, groups, status, onPermission, onDone }) { }); const start = async () => { - const group = groups.find((g) => g.id === groupId); - if (!group || !folder || !chosen.size) return; + if (!chosen.size) return; setBusy(true); setError(''); try { - const settings = { - account: user.username, groupId, groupName: group.name, - owner: group.owner_username || '', folder, albums: [...chosen], includeExisting: existing, - }; - // Asked when the photos would go somewhere new, or from somewhere new in - // time — never for a change of albums alone, which the person just made. - const same = cfg && cfg.groupId === groupId && cfg.folder === folder - && cfg.includeExisting === existing; - if (!same) { - const [est, members] = await Promise.all([ - platform.photoSync.estimate(settings), - hubFetch(`/v1/groups/${groupId}/members`, { token: user.token }) - .then((r) => (r.members || []).length).catch(() => null), - ]); - const params = { - group: group.name, owner: group.owner_username || '', folder, - members: members == null ? '?' : members, - count: est.count, size: formatSize(est.bytes), - }; + const settings = { albums: [...chosen], includeExisting: existing }; + // Asked when the photos would come from somewhere new in time; never + // for a change of albums alone, which the person just made. + if (!cfg || cfg.includeExisting !== existing) { + const est = await platform.photoSync.estimate(settings); + const params = { count: est.count, size: formatSize(est.bytes), dir: status.dir }; const yes = await ask(t(existing && est.count > 0 ? 'photosync.confirm' : 'photosync.confirm_new', params)); if (!yes) { setBusy(false); return; } @@ -210,26 +187,6 @@ function Setup({ user, groups, status, onPermission, onDone }) { <button class="btn-secondary" onClick=${allow}>${t('photosync.permission_allow')}</button> `} ${permitted && html` - <div class="settings-row"> - <span class="settings-label">${t('photosync.group')}</span> - <select class="settings-select" value=${groupId} - onChange=${(e) => setGroupId(e.target.value)}> - <option value="">${t('photosync.choose_group')}</option> - ${groups.map((g) => html`<option key=${g.id} value=${g.id}> - ${g.owner_username ? `${g.name} (@${g.owner_username})` : g.name}</option>`)} - </select> - </div> - ${probe === 'checking' && html`<p class="settings-hint">${t('photosync.checking_group')}</p>`} - ${probe === 'offline' && html`<p class="settings-hint">${t('photosync.group_offline')}</p>`} - ${folders && !folders.length && html`<p class="settings-hint">${t('photosync.no_folder')}</p>`} - ${folders && folders.length > 0 && html` - <div class="settings-row"> - <span class="settings-label">${t('photosync.folder')}</span> - <select class="settings-select" value=${folder} onChange=${(e) => setFolder(e.target.value)}> - ${folders.map((f) => html`<option key=${f} value=${f}>${f}</option>`)} - </select> - </div> - `} <p class="settings-label" style="margin-top:10px">${t('photosync.albums')}</p> ${(albums || []).map((a) => html` <label class="settings-choice" key=${a.id}> @@ -253,7 +210,7 @@ function Setup({ user, groups, status, onPermission, onDone }) { </label> <div class="settings-row" style="gap:8px; justify-content:flex-start"> <button class="admin-btn" onClick=${start} - disabled=${busy || !groupId || !folder || !chosen.size}>${t('photosync.start')}</button> + disabled=${busy || !chosen.size}>${t('photosync.start')}</button> <button class="btn-secondary" onClick=${() => onDone(null)}>${t('dialog.cancel')}</button> </div> `} |