1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
import { html, useState, useEffect } from './vendor/htm-preact.js';
import { t } from './i18n.js';
import { useSaver } from './settings-ui.js';
import { FolderPickerField } from './folder-tree.js';
/**
* HelloWorld's settings: one folder, and nothing else.
*
* This is the whole server-side surface an application needs — no op, no MNP
* message, no route, no roster accessor. `saveDirectories` is bound to this
* app's registry key by the page, and `ops.set_app_directories` stores the row
* under that name without knowing what it is.
*
* It takes the shared props and no others (`docs/MESHBAY_DESIGN.md` §9.2),
* which is what `test_app_settings_plugin.py` checks of every pane — including
* this one, so the reference implementation is held to the contract it
* demonstrates.
*/
function HelloWorldSettings({ roots, dirs, settings, saveDirectories }) {
const { busy, msg, run } = useSaver();
const [directories, setDirectories] = useState(
settings.helloworldDirectories || []);
useEffect(() => {
setDirectories(settings.helloworldDirectories || []);
}, [settings.helloworldDirectories]);
const current = settings.helloworldDirectories || [];
const dirty = directories.length !== current.length
|| directories.some((d, i) => d !== current[i]);
return html`
<div class="app-settings">
<${FolderPickerField}
label=${t('settings_app.helloworld_directory_label')}
hint=${t('settings_app.helloworld_directory_hint')}
roots=${roots} dirs=${dirs} mode="single"
value=${directories[0] || ''} disabled=${busy}
onChange=${(path) => setDirectories(path ? [path] : [])} />
<button class="btn btn-small btn-secondary" style="margin-top:4px"
disabled=${busy || !dirty}
onClick=${() => run(() => saveDirectories(directories))}>
${busy ? t('settings_app.saving') : t('settings_app.save')}
</button>
${msg && html`<p class="settings-hint">${msg}</p>`}
</div>
`;
}
export { HelloWorldSettings };
|