selfstore 1.8.15 → 1.8.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.d.ts +7 -7
- package/dist/advanced.js +1 -1
- package/dist/backups.d.ts +4 -4
- package/dist/{chunk-TXAMWBG5.js → chunk-3BPGPSPX.js} +22 -2
- package/dist/chunk-3BPGPSPX.js.map +1 -0
- package/dist/{connect-DaZFPJdt.d.ts → connect-BaWYvB1w.d.ts} +3 -3
- package/dist/{drive-B2fm71qD.d.ts → drive-BUPsPaIu.d.ts} +1 -1
- package/dist/flows.d.ts +5 -5
- package/dist/households.d.ts +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +2 -2
- package/dist/{local-CldSa9EY.d.ts → local-Dt1hYNG4.d.ts} +2 -2
- package/dist/{manager-BqzTVaep.d.ts → manager-CaMd6T1T.d.ts} +1 -1
- package/dist/{s3-DgyTwMRc.d.ts → s3-CCE6lc_U.d.ts} +1 -1
- package/dist/{store-CiLoRJmy.d.ts → store-CCe8b5Eg.d.ts} +18 -0
- package/dist/widgets.d.ts +45 -14
- package/dist/widgets.js +118 -26
- package/dist/widgets.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-TXAMWBG5.js.map +0 -1
package/dist/flows.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { b as ConnectKind, S as StoreLike, C as ConnectTargets } from './connect-
|
|
2
|
-
export { c as ConnectFlow, a as ConnectFlowOptions, d as ConnectFlowOutcome, e as ConnectResolution, f as ConnectSnapshot, g as ConnectStep, h as Connector, F as FlowHost, R as ResumeOffer, i as connectFlow } from './connect-
|
|
3
|
-
import { S as StoreError, k as ReplicaState, B as BackupTarget } from './store-
|
|
1
|
+
import { b as ConnectKind, S as StoreLike, C as ConnectTargets } from './connect-BaWYvB1w.js';
|
|
2
|
+
export { c as ConnectFlow, a as ConnectFlowOptions, d as ConnectFlowOutcome, e as ConnectResolution, f as ConnectSnapshot, g as ConnectStep, h as Connector, F as FlowHost, R as ResumeOffer, i as connectFlow } from './connect-BaWYvB1w.js';
|
|
3
|
+
import { S as StoreError, k as ReplicaState, B as BackupTarget } from './store-CCe8b5Eg.js';
|
|
4
4
|
import { F as FlowStore } from './machine-ALMkT3mk.js';
|
|
5
5
|
export { w as withDeadline } from './machine-ALMkT3mk.js';
|
|
6
|
-
import { W as WebdavConfig, S as S3Config } from './s3-
|
|
6
|
+
import { W as WebdavConfig, S as S3Config } from './s3-CCE6lc_U.js';
|
|
7
7
|
import './cache-ilsK3Tki.js';
|
|
8
|
-
import './drive-
|
|
8
|
+
import './drive-BUPsPaIu.js';
|
|
9
9
|
import './sync.js';
|
|
10
10
|
|
|
11
11
|
/** The one replica this flow manages, as its id on the engine. */
|
package/dist/households.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { o as Snapshot, E as EncodeOptions, H as Header, f as PasswordPolicy, B as BackupTarget, r as StatusDescriptor, S as StoreError, c as LocalStoreState, L as LocalStore } from './store-
|
|
2
|
-
export { d as Mode, e as PasswordCheck, g as PasswordRequirement, l as SelfstoreError, m as SelfstoreErrorCode, n as Severity, p as SnapshotFile, q as StatusAction, t as StorageState, T as TargetKind, x as checkPasswordPolicy, C as errorLabelKey, G as isSelfstoreError } from './store-
|
|
1
|
+
import { o as Snapshot, E as EncodeOptions, H as Header, f as PasswordPolicy, B as BackupTarget, r as StatusDescriptor, S as StoreError, c as LocalStoreState, L as LocalStore } from './store-CCe8b5Eg.js';
|
|
2
|
+
export { d as Mode, e as PasswordCheck, g as PasswordRequirement, l as SelfstoreError, m as SelfstoreErrorCode, n as Severity, p as SnapshotFile, q as StatusAction, t as StorageState, T as TargetKind, x as checkPasswordPolicy, C as errorLabelKey, G as isSelfstoreError } from './store-CCe8b5Eg.js';
|
|
3
3
|
import { L as LocalCache, K as KV } from './cache-ilsK3Tki.js';
|
|
4
4
|
import { SyncConfig } from './sync.js';
|
|
5
|
-
import { R as ResumeOffer, C as ConnectTargets } from './connect-
|
|
6
|
-
import { f as BackupsManager } from './manager-
|
|
7
|
-
import { a as DriveAuth } from './drive-
|
|
8
|
-
import { W as WebdavConfig, S as S3Config } from './s3-
|
|
9
|
-
export { f as changePassword, g as gisDriveAuth, p as pickFromDisk, s as saveToDisk } from './local-
|
|
5
|
+
import { R as ResumeOffer, C as ConnectTargets } from './connect-BaWYvB1w.js';
|
|
6
|
+
import { f as BackupsManager } from './manager-CaMd6T1T.js';
|
|
7
|
+
import { a as DriveAuth } from './drive-BUPsPaIu.js';
|
|
8
|
+
import { W as WebdavConfig, S as S3Config } from './s3-CCE6lc_U.js';
|
|
9
|
+
export { f as changePassword, g as gisDriveAuth, p as pickFromDisk, s as saveToDisk } from './local-Dt1hYNG4.js';
|
|
10
10
|
import './machine-ALMkT3mk.js';
|
|
11
11
|
|
|
12
12
|
declare const BACKUP_EXTENSION = ".zip";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { indexedDbCache, memoryCache, gisDriveAuth, isLockableCache, createLocalStore } from './chunk-
|
|
2
|
-
export { gisDriveAuth } from './chunk-
|
|
1
|
+
import { indexedDbCache, memoryCache, gisDriveAuth, isLockableCache, createLocalStore } from './chunk-3BPGPSPX.js';
|
|
2
|
+
export { gisDriveAuth } from './chunk-3BPGPSPX.js';
|
|
3
3
|
import './chunk-SKWHKM25.js';
|
|
4
4
|
import { saveToDisk } from './chunk-DCEXWSM6.js';
|
|
5
5
|
export { pickFromDisk, saveToDisk } from './chunk-DCEXWSM6.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { o as Snapshot, E as EncodeOptions, H as Header } from './store-
|
|
2
|
-
import { a as DriveAuth } from './drive-
|
|
1
|
+
import { o as Snapshot, E as EncodeOptions, H as Header } from './store-CCe8b5Eg.js';
|
|
2
|
+
import { a as DriveAuth } from './drive-BUPsPaIu.js';
|
|
3
3
|
|
|
4
4
|
/** Serialize a snapshot to a portable backup blob (compressed; encrypted if a password is given). */
|
|
5
5
|
declare function exportSnapshot(snapshot: Snapshot, opts: EncodeOptions): Promise<Blob>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { K as KV } from './cache-ilsK3Tki.js';
|
|
2
|
-
import { B as BackupTarget, L as LocalStore } from './store-
|
|
2
|
+
import { B as BackupTarget, L as LocalStore } from './store-CCe8b5Eg.js';
|
|
3
3
|
import { F as FlowStore } from './machine-ALMkT3mk.js';
|
|
4
4
|
|
|
5
5
|
/** What the destination reports about a listed file (one cheap metadata call). */
|
|
@@ -359,6 +359,24 @@ interface LocalStoreState {
|
|
|
359
359
|
locked: boolean;
|
|
360
360
|
saving: boolean;
|
|
361
361
|
lastSavedAt: number | null;
|
|
362
|
+
/**
|
|
363
|
+
* When a PORTABLE COPY was last written (an export the user asked for), or
|
|
364
|
+
* null if never. Distinct from `lastSavedAt`, which is the durable
|
|
365
|
+
* destination: a copy is a snapshot that leaves, a destination is kept up to
|
|
366
|
+
* date.
|
|
367
|
+
*/
|
|
368
|
+
lastCopyAt: number | null;
|
|
369
|
+
/**
|
|
370
|
+
* Entries have been recorded since that copy was written.
|
|
371
|
+
*
|
|
372
|
+
* The store knew this only in its download-only mode, where the copy IS the
|
|
373
|
+
* save. Everywhere else nobody followed it, so an app that let its user
|
|
374
|
+
* export could say nothing about a copy going stale - and one of them found
|
|
375
|
+
* out the hard way that a copy written in the morning was still announced as
|
|
376
|
+
* up to date in the evening. False while no copy was ever written: there is
|
|
377
|
+
* nothing to be stale.
|
|
378
|
+
*/
|
|
379
|
+
copyIsStale: boolean;
|
|
362
380
|
status: StatusDescriptor;
|
|
363
381
|
/** The last durable-target problem (upload/refresh), or null. */
|
|
364
382
|
lastError: StoreError | null;
|
package/dist/widgets.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { S as StoreLike, F as FlowHost, C as ConnectTargets, a as ConnectFlowOptions, b as ConnectKind, c as ConnectFlow } from './connect-
|
|
1
|
+
import { S as StoreLike, F as FlowHost, C as ConnectTargets, a as ConnectFlowOptions, b as ConnectKind, c as ConnectFlow } from './connect-BaWYvB1w.js';
|
|
2
2
|
import { ShareEngine, ShareLevel, ShareFlow, JoinEngine, JoinFlow, ReplicaFlow } from './flows.js';
|
|
3
|
-
import { f as BackupsManager } from './manager-
|
|
4
|
-
import './store-
|
|
3
|
+
import { f as BackupsManager } from './manager-CaMd6T1T.js';
|
|
4
|
+
import './store-CCe8b5Eg.js';
|
|
5
5
|
import './cache-ilsK3Tki.js';
|
|
6
6
|
import './sync.js';
|
|
7
|
-
import './drive-
|
|
8
|
-
import './s3-
|
|
7
|
+
import './drive-BUPsPaIu.js';
|
|
8
|
+
import './s3-CCE6lc_U.js';
|
|
9
9
|
import './machine-ALMkT3mk.js';
|
|
10
10
|
|
|
11
11
|
/** Flat key -> string map; widgets merge a partial override over EN defaults. */
|
|
@@ -356,9 +356,13 @@ declare class SelfstoreStatusElement extends FlowWidget {
|
|
|
356
356
|
static get observedAttributes(): string[];
|
|
357
357
|
protected defaults(): WidgetLabels;
|
|
358
358
|
protected packs(): Record<string, WidgetLabels>;
|
|
359
|
-
/**
|
|
360
|
-
|
|
361
|
-
|
|
359
|
+
/**
|
|
360
|
+
* 'row' (a tinted box: dot, text, action button - for a settings page),
|
|
361
|
+
* 'line' (one line and a link - for a menu, where a box eats the surface),
|
|
362
|
+
* or 'dot' (the dot alone, for a header corner). Also the attribute.
|
|
363
|
+
*/
|
|
364
|
+
get variant(): 'row' | 'line' | 'dot';
|
|
365
|
+
set variant(v: 'row' | 'line' | 'dot' | null);
|
|
362
366
|
attributeChangedCallback(name: string, _old: string | null, value: string | null): void;
|
|
363
367
|
connectedCallback(): void;
|
|
364
368
|
protected view(into: HTMLElement): void;
|
|
@@ -742,6 +746,7 @@ declare class SelfstoreStorageElement extends FlowWidget {
|
|
|
742
746
|
|
|
743
747
|
declare class SelfstoreAccountElement extends FlowWidget {
|
|
744
748
|
#private;
|
|
749
|
+
static get observedAttributes(): string[];
|
|
745
750
|
protected defaults(): WidgetLabels;
|
|
746
751
|
protected packs(): Record<string, WidgetLabels>;
|
|
747
752
|
constructor();
|
|
@@ -751,10 +756,23 @@ declare class SelfstoreAccountElement extends FlowWidget {
|
|
|
751
756
|
* the user picks one. Returns false (or throws) to stop. */
|
|
752
757
|
get confirmAction(): ((a: DestinationAction) => boolean | Promise<boolean>) | null;
|
|
753
758
|
set confirmAction(fn: ((a: DestinationAction) => boolean | Promise<boolean>) | null);
|
|
759
|
+
/**
|
|
760
|
+
* What the trigger says: the DESTINATION it goes to (default), or the STATE
|
|
761
|
+
* it is in.
|
|
762
|
+
*
|
|
763
|
+
* Naming the place is right when there is a choice - it makes local-first
|
|
764
|
+
* visible without opening anything. It says nothing at all when an app
|
|
765
|
+
* offers exactly one destination: "a file" where a file is the only thing it
|
|
766
|
+
* could ever be. Such an app states a condition instead - saved, unsaved,
|
|
767
|
+
* locked - which is the part that changes.
|
|
768
|
+
*/
|
|
769
|
+
get trigger(): 'destination' | 'status';
|
|
770
|
+
set trigger(v: 'destination' | 'status' | null);
|
|
754
771
|
/** Whether the menu is on screen. Settable, so a host can close it from its
|
|
755
772
|
* own router after the settings item navigated away. */
|
|
756
773
|
get open(): boolean;
|
|
757
774
|
set open(v: boolean);
|
|
775
|
+
attributeChangedCallback(name: string): void;
|
|
758
776
|
connectedCallback(): void;
|
|
759
777
|
disconnectedCallback(): void;
|
|
760
778
|
/** While the menu is open: a clock for the relative time, and the two ways
|
|
@@ -767,13 +785,19 @@ declare class SelfstoreAccountElement extends FlowWidget {
|
|
|
767
785
|
* shipped name: its own label is a better answer than the raw key. */
|
|
768
786
|
private named;
|
|
769
787
|
/**
|
|
770
|
-
* The one line
|
|
771
|
-
*
|
|
772
|
-
*
|
|
773
|
-
|
|
774
|
-
|
|
788
|
+
* The one line this element words itself: a plain "saved", the only state
|
|
789
|
+
* with nothing to do about it and the only one where WHEN is the whole
|
|
790
|
+
* information. Null in every other state.
|
|
791
|
+
*/
|
|
792
|
+
private saved;
|
|
793
|
+
/**
|
|
794
|
+
* Anything that is NOT a plain "saved" - reconnect, unlock, changes to
|
|
795
|
+
* export - belongs to <selfstore-status>, which owns both the wording and
|
|
796
|
+
* the gesture. It goes under the card and across the whole menu, never
|
|
797
|
+
* inside the card's text column: that column is sized for an address, and a
|
|
798
|
+
* sentence wrapping in 167 px turned a three-word notice into 247 px of box.
|
|
775
799
|
*/
|
|
776
|
-
private
|
|
800
|
+
private attention;
|
|
777
801
|
/** Ask for the settings. The host owns the route, so this only says that it
|
|
778
802
|
* was asked - and closes, because a menu that stays open behind a page
|
|
779
803
|
* transition reads as a failed click. */
|
|
@@ -781,6 +805,13 @@ declare class SelfstoreAccountElement extends FlowWidget {
|
|
|
781
805
|
/** Change backup: detach, and let the first-run screen take it from there.
|
|
782
806
|
* The data stays; only the destination is let go. */
|
|
783
807
|
private change;
|
|
808
|
+
/**
|
|
809
|
+
* What the trigger reads. The destination by default; the state when an app
|
|
810
|
+
* has only one destination to offer, where naming it says nothing that ever
|
|
811
|
+
* changes. The state comes from <selfstore-status>'s own words, so the two
|
|
812
|
+
* surfaces cannot drift.
|
|
813
|
+
*/
|
|
814
|
+
private said;
|
|
784
815
|
private card;
|
|
785
816
|
protected view(into: HTMLElement): void;
|
|
786
817
|
/**
|
package/dist/widgets.js
CHANGED
|
@@ -2071,14 +2071,14 @@ var EN4 = {
|
|
|
2071
2071
|
// and a backup is written only when the user asks for one. It is a mode the
|
|
2072
2072
|
// STORE itself falls back to, so the library owes it a name - without one, a
|
|
2073
2073
|
// panel showed the raw key to the user.
|
|
2074
|
-
"destination.kind.file-manual": "A file
|
|
2074
|
+
"destination.kind.file-manual": "A file"
|
|
2075
2075
|
};
|
|
2076
2076
|
var FR4 = {
|
|
2077
2077
|
"destination.kind.file": "Un fichier sur cet appareil",
|
|
2078
2078
|
"destination.kind.webdav": "Votre serveur",
|
|
2079
2079
|
"destination.kind.s3": "Votre bucket",
|
|
2080
2080
|
"destination.kind.device": "Cet appareil seulement",
|
|
2081
|
-
"destination.kind.file-manual": "Un fichier
|
|
2081
|
+
"destination.kind.file-manual": "Un fichier"
|
|
2082
2082
|
};
|
|
2083
2083
|
|
|
2084
2084
|
// src/widgets/status.ts
|
|
@@ -2125,12 +2125,16 @@ var SelfstoreStatusElement = class extends FlowWidget {
|
|
|
2125
2125
|
packs() {
|
|
2126
2126
|
return { fr: FR5 };
|
|
2127
2127
|
}
|
|
2128
|
-
/**
|
|
2128
|
+
/**
|
|
2129
|
+
* 'row' (a tinted box: dot, text, action button - for a settings page),
|
|
2130
|
+
* 'line' (one line and a link - for a menu, where a box eats the surface),
|
|
2131
|
+
* or 'dot' (the dot alone, for a header corner). Also the attribute.
|
|
2132
|
+
*/
|
|
2129
2133
|
get variant() {
|
|
2130
2134
|
return this.#variant;
|
|
2131
2135
|
}
|
|
2132
2136
|
set variant(v) {
|
|
2133
|
-
this.#variant = v === "dot"
|
|
2137
|
+
this.#variant = v === "dot" || v === "line" ? v : "row";
|
|
2134
2138
|
this.rerender();
|
|
2135
2139
|
}
|
|
2136
2140
|
attributeChangedCallback(name, _old, value) {
|
|
@@ -2138,7 +2142,8 @@ var SelfstoreStatusElement = class extends FlowWidget {
|
|
|
2138
2142
|
}
|
|
2139
2143
|
connectedCallback() {
|
|
2140
2144
|
super.connectedCallback();
|
|
2141
|
-
if (this.hasAttribute("variant"))
|
|
2145
|
+
if (this.hasAttribute("variant"))
|
|
2146
|
+
this.variant = this.getAttribute("variant");
|
|
2142
2147
|
this.follow(this.hostOf());
|
|
2143
2148
|
}
|
|
2144
2149
|
view(into) {
|
|
@@ -2150,12 +2155,20 @@ var SelfstoreStatusElement = class extends FlowWidget {
|
|
|
2150
2155
|
const copie = this.t(jumelle);
|
|
2151
2156
|
return copie === jumelle ? this.t(cle) : copie;
|
|
2152
2157
|
};
|
|
2158
|
+
const selonLeType = (cle) => {
|
|
2159
|
+
const jumelle = `${cle}.${targetKind}`;
|
|
2160
|
+
const copie = this.t(jumelle, { label: label ?? "" });
|
|
2161
|
+
return copie === jumelle ? null : copie;
|
|
2162
|
+
};
|
|
2153
2163
|
const { lastSavedAt } = host.engine.state;
|
|
2154
|
-
const text = label ? this.t(status.labelKey, { label }) : sansLieu(status.labelKey);
|
|
2164
|
+
const text = selonLeType(status.labelKey) ?? (label ? this.t(status.labelKey, { label }) : sansLieu(status.labelKey));
|
|
2155
2165
|
const dot = h("span", {
|
|
2156
2166
|
part: `status-dot sev-${status.severity}`,
|
|
2157
2167
|
"aria-hidden": "true"
|
|
2158
2168
|
});
|
|
2169
|
+
const GLYPH = { ok: "\u2713", warn: "!", danger: "!", info: "" };
|
|
2170
|
+
const glyph = GLYPH[status.severity];
|
|
2171
|
+
const sign = glyph ? h("span", { part: `status-glyph sev-${status.severity}`, "aria-hidden": "true" }, glyph) : dot;
|
|
2159
2172
|
if (this.#variant === "dot") {
|
|
2160
2173
|
into.append(
|
|
2161
2174
|
h(
|
|
@@ -2171,14 +2184,33 @@ var SelfstoreStatusElement = class extends FlowWidget {
|
|
|
2171
2184
|
);
|
|
2172
2185
|
return;
|
|
2173
2186
|
}
|
|
2187
|
+
if (this.#variant === "line") {
|
|
2188
|
+
put(
|
|
2189
|
+
into,
|
|
2190
|
+
h(
|
|
2191
|
+
"div",
|
|
2192
|
+
{ part: "row status-line" },
|
|
2193
|
+
sign,
|
|
2194
|
+
h("span", { part: "status-line-text" }, text),
|
|
2195
|
+
status.actionable && status.action ? h(
|
|
2196
|
+
"button",
|
|
2197
|
+
{
|
|
2198
|
+
part: "link status-action",
|
|
2199
|
+
type: "button",
|
|
2200
|
+
onclick: () => this.emit("selfstore-status-action", { action: status.action })
|
|
2201
|
+
},
|
|
2202
|
+
this.t(`status.action.${status.action}`)
|
|
2203
|
+
) : null
|
|
2204
|
+
)
|
|
2205
|
+
);
|
|
2206
|
+
return;
|
|
2207
|
+
}
|
|
2174
2208
|
const TINT = {
|
|
2175
2209
|
ok: "status-ok",
|
|
2176
2210
|
warn: "status-warn",
|
|
2177
2211
|
danger: "status-error",
|
|
2178
2212
|
info: ""
|
|
2179
2213
|
};
|
|
2180
|
-
const GLYPH = { ok: "\u2713", warn: "!", danger: "!", info: "" };
|
|
2181
|
-
const glyph = GLYPH[status.severity];
|
|
2182
2214
|
const icon = this.icons[targetKind];
|
|
2183
2215
|
const where = this.t(`status.where.${targetKind}`);
|
|
2184
2216
|
const kindName = this.t(`destination.kind.${targetKind}`);
|
|
@@ -2187,15 +2219,15 @@ var SelfstoreStatusElement = class extends FlowWidget {
|
|
|
2187
2219
|
const place = where !== `status.where.${targetKind}` ? where : own ?? named ?? label ?? "";
|
|
2188
2220
|
const when = lastSavedAt ? this.since(lastSavedAt, this.t("status.justNow")) : "";
|
|
2189
2221
|
const sub = [place, status.state === "saved" ? when : ""].filter(Boolean).join(", ");
|
|
2190
|
-
const title = sub ? sansLieu(status.labelKey) : text;
|
|
2222
|
+
const title = selonLeType(status.labelKey) ?? (sub ? sansLieu(status.labelKey) : text);
|
|
2191
2223
|
put(
|
|
2192
2224
|
into,
|
|
2193
2225
|
h(
|
|
2194
2226
|
"div",
|
|
2195
2227
|
{ part: `status row status-row ${TINT[status.severity] ?? ""}` },
|
|
2196
|
-
// The severity colors the
|
|
2228
|
+
// The severity colors the sign, not the box: tinting the whole line
|
|
2197
2229
|
// turns a title into a warning about itself.
|
|
2198
|
-
|
|
2230
|
+
sign,
|
|
2199
2231
|
icon ? h("img", { part: "icon", src: icon, alt: "" }) : null,
|
|
2200
2232
|
h(
|
|
2201
2233
|
"div",
|
|
@@ -4096,6 +4128,9 @@ var ACCOUNT_STYLES = `
|
|
|
4096
4128
|
of ZERO - the pill collapsed to its dot in a flex header, with the label
|
|
4097
4129
|
overflowing off screen. Nothing here queries its own width. */
|
|
4098
4130
|
[part~='stack'] { container-type: normal; display: block; }
|
|
4131
|
+
/* A state in the trigger is a line already: no dot of its own, no action - the
|
|
4132
|
+
press opens the menu, where the gesture lives. */
|
|
4133
|
+
[part~='account-trigger-status'] [part~='status-action'] { display: none; }
|
|
4099
4134
|
[part~='account-trigger'] {
|
|
4100
4135
|
display: inline-flex;
|
|
4101
4136
|
align-items: center;
|
|
@@ -4196,11 +4231,16 @@ var ACCOUNT_STYLES = `
|
|
|
4196
4231
|
[part~='account-change'] { color: var(--_danger); }
|
|
4197
4232
|
[part~='account-change']:hover { background: color-mix(in srgb, var(--_danger) 10%, transparent); }
|
|
4198
4233
|
[part~='account-sep'] { height: 1px; background: var(--_border); margin: 0.2rem 0.3rem; }
|
|
4234
|
+
[part~='account-status'] { display: block; padding: 0 0.6rem 0.2rem; font-size: 0.8125rem; }
|
|
4199
4235
|
[part~='account-error'] { margin: 0.15rem 0.55rem 0.3rem; font-size: 0.8125rem; color: var(--_danger); }
|
|
4200
4236
|
`;
|
|
4201
4237
|
var TICK_MS = 3e4;
|
|
4202
4238
|
var SelfstoreAccountElement = class extends FlowWidget {
|
|
4239
|
+
static get observedAttributes() {
|
|
4240
|
+
return ["trigger"];
|
|
4241
|
+
}
|
|
4203
4242
|
#confirm = null;
|
|
4243
|
+
#trigger = "destination";
|
|
4204
4244
|
#open = false;
|
|
4205
4245
|
#error = null;
|
|
4206
4246
|
#timer = null;
|
|
@@ -4233,6 +4273,23 @@ var SelfstoreAccountElement = class extends FlowWidget {
|
|
|
4233
4273
|
set confirmAction(fn) {
|
|
4234
4274
|
this.#confirm = fn;
|
|
4235
4275
|
}
|
|
4276
|
+
/**
|
|
4277
|
+
* What the trigger says: the DESTINATION it goes to (default), or the STATE
|
|
4278
|
+
* it is in.
|
|
4279
|
+
*
|
|
4280
|
+
* Naming the place is right when there is a choice - it makes local-first
|
|
4281
|
+
* visible without opening anything. It says nothing at all when an app
|
|
4282
|
+
* offers exactly one destination: "a file" where a file is the only thing it
|
|
4283
|
+
* could ever be. Such an app states a condition instead - saved, unsaved,
|
|
4284
|
+
* locked - which is the part that changes.
|
|
4285
|
+
*/
|
|
4286
|
+
get trigger() {
|
|
4287
|
+
return this.#trigger;
|
|
4288
|
+
}
|
|
4289
|
+
set trigger(v) {
|
|
4290
|
+
this.#trigger = v === "status" ? "status" : "destination";
|
|
4291
|
+
this.rerender();
|
|
4292
|
+
}
|
|
4236
4293
|
/** Whether the menu is on screen. Settable, so a host can close it from its
|
|
4237
4294
|
* own router after the settings item navigated away. */
|
|
4238
4295
|
get open() {
|
|
@@ -4244,8 +4301,16 @@ var SelfstoreAccountElement = class extends FlowWidget {
|
|
|
4244
4301
|
this.watch();
|
|
4245
4302
|
this.rerender();
|
|
4246
4303
|
}
|
|
4304
|
+
attributeChangedCallback(name) {
|
|
4305
|
+
if (name === "trigger") {
|
|
4306
|
+
const value = this.attr(name);
|
|
4307
|
+
if (value !== null) this.trigger = value;
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4247
4310
|
connectedCallback() {
|
|
4248
4311
|
super.connectedCallback();
|
|
4312
|
+
const trigger = this.attr("trigger");
|
|
4313
|
+
if (trigger !== null) this.trigger = trigger;
|
|
4249
4314
|
this.follow(this.hostOf());
|
|
4250
4315
|
}
|
|
4251
4316
|
disconnectedCallback() {
|
|
@@ -4287,24 +4352,33 @@ var SelfstoreAccountElement = class extends FlowWidget {
|
|
|
4287
4352
|
return kind === `destination.kind.${targetKind}` ? label ?? targetKind : kind;
|
|
4288
4353
|
}
|
|
4289
4354
|
/**
|
|
4290
|
-
* The one line
|
|
4291
|
-
*
|
|
4292
|
-
*
|
|
4293
|
-
* (reconnect, unlock, changes to download) belongs to <selfstore-status>,
|
|
4294
|
-
* which owns both the wording and the button that resolves it.
|
|
4355
|
+
* The one line this element words itself: a plain "saved", the only state
|
|
4356
|
+
* with nothing to do about it and the only one where WHEN is the whole
|
|
4357
|
+
* information. Null in every other state.
|
|
4295
4358
|
*/
|
|
4296
|
-
|
|
4359
|
+
saved(host) {
|
|
4297
4360
|
const { status, lastSavedAt } = host.engine.state;
|
|
4298
|
-
if (status.state
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4361
|
+
if (status.state !== "saved" || !lastSavedAt || "status.saved" in this.labels) return null;
|
|
4362
|
+
return h(
|
|
4363
|
+
"span",
|
|
4364
|
+
{ part: "account-line" },
|
|
4365
|
+
this.t("account.saved", { when: this.since(lastSavedAt, this.t("account.justNow")) })
|
|
4366
|
+
);
|
|
4367
|
+
}
|
|
4368
|
+
/**
|
|
4369
|
+
* Anything that is NOT a plain "saved" - reconnect, unlock, changes to
|
|
4370
|
+
* export - belongs to <selfstore-status>, which owns both the wording and
|
|
4371
|
+
* the gesture. It goes under the card and across the whole menu, never
|
|
4372
|
+
* inside the card's text column: that column is sized for an address, and a
|
|
4373
|
+
* sentence wrapping in 167 px turned a three-word notice into 247 px of box.
|
|
4374
|
+
*/
|
|
4375
|
+
attention(host) {
|
|
4376
|
+
if (this.saved(host)) return null;
|
|
4304
4377
|
const el = document.createElement(
|
|
4305
4378
|
siblingTag(this.localName, "account", "status")
|
|
4306
4379
|
);
|
|
4307
|
-
el.setAttribute("variant", "
|
|
4380
|
+
el.setAttribute("variant", "line");
|
|
4381
|
+
el.setAttribute("part", "account-status");
|
|
4308
4382
|
el.labels = this.labels;
|
|
4309
4383
|
el.icons = this.icons;
|
|
4310
4384
|
el.store = this.store;
|
|
@@ -4338,6 +4412,23 @@ var SelfstoreAccountElement = class extends FlowWidget {
|
|
|
4338
4412
|
this.rerender();
|
|
4339
4413
|
}
|
|
4340
4414
|
}
|
|
4415
|
+
/**
|
|
4416
|
+
* What the trigger reads. The destination by default; the state when an app
|
|
4417
|
+
* has only one destination to offer, where naming it says nothing that ever
|
|
4418
|
+
* changes. The state comes from <selfstore-status>'s own words, so the two
|
|
4419
|
+
* surfaces cannot drift.
|
|
4420
|
+
*/
|
|
4421
|
+
said(host) {
|
|
4422
|
+
if (this.#trigger !== "status") return this.named(host);
|
|
4423
|
+
const el = document.createElement(
|
|
4424
|
+
siblingTag(this.localName, "account", "status")
|
|
4425
|
+
);
|
|
4426
|
+
el.setAttribute("variant", "line");
|
|
4427
|
+
el.setAttribute("part", "account-trigger-status");
|
|
4428
|
+
el.labels = this.labels;
|
|
4429
|
+
el.store = this.store;
|
|
4430
|
+
return el;
|
|
4431
|
+
}
|
|
4341
4432
|
card(host) {
|
|
4342
4433
|
const { targetKind } = host.engine.state;
|
|
4343
4434
|
const icon = this.icons[targetKind];
|
|
@@ -4357,7 +4448,7 @@ var SelfstoreAccountElement = class extends FlowWidget {
|
|
|
4357
4448
|
{ part: "account-text" },
|
|
4358
4449
|
h("span", { part: "account-title" }, this.named(host)),
|
|
4359
4450
|
mail ? h("span", { part: "account-mail" }, mail) : null,
|
|
4360
|
-
this.
|
|
4451
|
+
this.saved(host)
|
|
4361
4452
|
)
|
|
4362
4453
|
);
|
|
4363
4454
|
}
|
|
@@ -4378,12 +4469,13 @@ var SelfstoreAccountElement = class extends FlowWidget {
|
|
|
4378
4469
|
// The severity colors the DOT, never the label: a whole line turning
|
|
4379
4470
|
// amber reads as a warning about the destination's name.
|
|
4380
4471
|
h("span", { part: `account-dot sev-${status.severity}` }),
|
|
4381
|
-
h("span", {}, this.
|
|
4472
|
+
h("span", { part: "account-trigger-text" }, this.said(host))
|
|
4382
4473
|
);
|
|
4383
4474
|
const menu = this.#open ? h(
|
|
4384
4475
|
"div",
|
|
4385
4476
|
{ part: "card account-menu", role: "menu" },
|
|
4386
4477
|
this.card(host),
|
|
4478
|
+
this.attention(host),
|
|
4387
4479
|
h("div", { part: "account-sep" }),
|
|
4388
4480
|
h(
|
|
4389
4481
|
"button",
|