pinokiod 8.0.64 → 8.0.66
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/kernel/vault/index.js +17 -6
- package/package.json +1 -1
- package/server/public/app-vault-mode.js +112 -12
- package/server/public/layout.js +180 -17
- package/server/public/vault.css +39 -0
- package/server/public/vault.js +83 -28
- package/server/views/layout.ejs +40 -5
- package/test/vault-automatic-scan-ui.test.js +239 -44
- package/test/vault-engine.test.js +96 -22
- package/test/vault-ui.test.js +210 -15
package/kernel/vault/index.js
CHANGED
|
@@ -1494,7 +1494,7 @@ class Vault {
|
|
|
1494
1494
|
}
|
|
1495
1495
|
}
|
|
1496
1496
|
|
|
1497
|
-
async startFolderDiscovery(selectedRoot) {
|
|
1497
|
+
async startFolderDiscovery(selectedRoot, selectedThreshold) {
|
|
1498
1498
|
if (!this.enabled || !this.folderFinder) {
|
|
1499
1499
|
return { started: false, disabled: true }
|
|
1500
1500
|
}
|
|
@@ -1509,6 +1509,9 @@ class Vault {
|
|
|
1509
1509
|
!path.isAbsolute(selectedRoot.trim())) {
|
|
1510
1510
|
return { error: "Choose a valid folder or drive." }
|
|
1511
1511
|
}
|
|
1512
|
+
if (!CANDIDATE_SIZE_OPTIONS.includes(selectedThreshold)) {
|
|
1513
|
+
return { error: "Choose a valid minimum file size." }
|
|
1514
|
+
}
|
|
1512
1515
|
if (this.scanPromise) {
|
|
1513
1516
|
return { error: "Wait for the current scan to finish." }
|
|
1514
1517
|
}
|
|
@@ -1520,10 +1523,15 @@ class Vault {
|
|
|
1520
1523
|
return { error: "Run a global scan before finding folders." }
|
|
1521
1524
|
}
|
|
1522
1525
|
const publishedThreshold = Number(globalScan.candidate_min_bytes)
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1526
|
+
if (!Number.isFinite(publishedThreshold) || publishedThreshold < 0) {
|
|
1527
|
+
return { error: "Run a new global scan before finding folders." }
|
|
1528
|
+
}
|
|
1529
|
+
if (selectedThreshold < publishedThreshold) {
|
|
1530
|
+
return {
|
|
1531
|
+
error: "Run a global scan with this minimum file size before searching folders."
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
const threshold = selectedThreshold
|
|
1527
1535
|
const partial = !!globalScan.partial || (
|
|
1528
1536
|
Array.isArray(globalScan.exclusions) &&
|
|
1529
1537
|
globalScan.exclusions.length > 0
|
|
@@ -1832,7 +1840,10 @@ class Vault {
|
|
|
1832
1840
|
case "cancel_scan":
|
|
1833
1841
|
return this.cancelScan()
|
|
1834
1842
|
case "find_folders":
|
|
1835
|
-
return this.startFolderDiscovery(
|
|
1843
|
+
return this.startFolderDiscovery(
|
|
1844
|
+
payload.path,
|
|
1845
|
+
payload.candidate_size
|
|
1846
|
+
)
|
|
1836
1847
|
case "cancel_find_folders":
|
|
1837
1848
|
return this.cancelFolderDiscovery()
|
|
1838
1849
|
case "clear_find_folders":
|
package/package.json
CHANGED
|
@@ -5,6 +5,25 @@
|
|
|
5
5
|
const app = status.dataset.app || ""
|
|
6
6
|
const tab = status.closest("#save-space-tab")
|
|
7
7
|
const label = status.querySelector("[data-app-vault-mode-label]")
|
|
8
|
+
const origin = window.location.origin
|
|
9
|
+
let parentStateVersion = 0
|
|
10
|
+
let fallbackTimer = null
|
|
11
|
+
|
|
12
|
+
const normalizeSnapshot = (snapshot) => ({
|
|
13
|
+
global_scan_ready: !!(snapshot && snapshot.global_scan_ready === true),
|
|
14
|
+
settings: snapshot && Array.isArray(snapshot.settings)
|
|
15
|
+
? snapshot.settings.filter((setting) =>
|
|
16
|
+
setting && typeof setting.app === "string" && setting.app).map((setting) => ({
|
|
17
|
+
app: setting.app,
|
|
18
|
+
mode: setting.mode === "manual" ? "manual" : "automatic"
|
|
19
|
+
}))
|
|
20
|
+
: []
|
|
21
|
+
})
|
|
22
|
+
let latestSnapshot = normalizeSnapshot({
|
|
23
|
+
global_scan_ready: status.dataset.ready === "true",
|
|
24
|
+
settings: [{ app, mode: status.dataset.mode }]
|
|
25
|
+
})
|
|
26
|
+
|
|
8
27
|
const setState = (value, ready) => {
|
|
9
28
|
const mode = value === "manual" ? "manual" : "automatic"
|
|
10
29
|
const globalScanReady = ready === true
|
|
@@ -24,23 +43,104 @@
|
|
|
24
43
|
}
|
|
25
44
|
}
|
|
26
45
|
const applySnapshot = (snapshot) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
latestSnapshot = normalizeSnapshot(snapshot)
|
|
47
|
+
const setting = latestSnapshot.settings.find((item) =>
|
|
48
|
+
item.app === app)
|
|
49
|
+
setState(setting && setting.mode, latestSnapshot.global_scan_ready)
|
|
50
|
+
}
|
|
51
|
+
const vaultFrame = () =>
|
|
52
|
+
document.querySelector('iframe[name="app-vault"]')
|
|
53
|
+
const sendSnapshot = (targetWindow) => {
|
|
54
|
+
if (!targetWindow) return
|
|
55
|
+
try {
|
|
56
|
+
targetWindow.postMessage({
|
|
57
|
+
e: "vault-automatic-scan-state",
|
|
58
|
+
snapshot: latestSnapshot
|
|
59
|
+
}, origin)
|
|
60
|
+
} catch (_) {}
|
|
61
|
+
}
|
|
62
|
+
const relaySnapshot = () => {
|
|
63
|
+
const frame = vaultFrame()
|
|
64
|
+
if (frame) sendSnapshot(frame.contentWindow)
|
|
65
|
+
}
|
|
66
|
+
const mergeMode = (mode) => {
|
|
67
|
+
const settings = latestSnapshot.settings.filter((setting) =>
|
|
68
|
+
setting.app !== app)
|
|
69
|
+
settings.push({
|
|
70
|
+
app,
|
|
71
|
+
mode: mode === "manual" ? "manual" : "automatic"
|
|
72
|
+
})
|
|
73
|
+
applySnapshot({
|
|
74
|
+
global_scan_ready: latestSnapshot.global_scan_ready,
|
|
75
|
+
settings
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
const loadState = async () => {
|
|
79
|
+
if (!app) return
|
|
80
|
+
const requestedAtParentVersion = parentStateVersion
|
|
81
|
+
try {
|
|
82
|
+
const response = await fetch("/info/vault/automatic-scans", {
|
|
83
|
+
credentials: "same-origin",
|
|
84
|
+
cache: "no-store"
|
|
85
|
+
})
|
|
86
|
+
if (!response.ok) return
|
|
87
|
+
const snapshot = await response.json()
|
|
88
|
+
if (window.parent !== window &&
|
|
89
|
+
parentStateVersion !== requestedAtParentVersion) return
|
|
90
|
+
applySnapshot(snapshot)
|
|
91
|
+
relaySnapshot()
|
|
92
|
+
} catch (_) {}
|
|
33
93
|
}
|
|
34
94
|
|
|
35
95
|
setState(status.dataset.mode, status.dataset.ready === "true")
|
|
36
|
-
if (!app
|
|
96
|
+
if (!app) return
|
|
97
|
+
|
|
98
|
+
window.addEventListener("message", (event) => {
|
|
99
|
+
if (!event || event.origin !== origin ||
|
|
100
|
+
!event.data || typeof event.data !== "object") return
|
|
101
|
+
if (event.data.e === "vault-automatic-scan-state" &&
|
|
102
|
+
window.parent !== window && event.source === window.parent) {
|
|
103
|
+
parentStateVersion += 1
|
|
104
|
+
if (fallbackTimer !== null) {
|
|
105
|
+
window.clearTimeout(fallbackTimer)
|
|
106
|
+
fallbackTimer = null
|
|
107
|
+
}
|
|
108
|
+
applySnapshot(event.data.snapshot)
|
|
109
|
+
relaySnapshot()
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
const frame = vaultFrame()
|
|
113
|
+
if (!frame || frame.contentWindow !== event.source) return
|
|
114
|
+
if (event.data.e === "vault-automatic-scan-state-request") {
|
|
115
|
+
sendSnapshot(event.source)
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
if (event.data.e === "vault-automatic-mode-changed" &&
|
|
119
|
+
event.data.app === app) {
|
|
120
|
+
mergeMode(event.data.mode)
|
|
121
|
+
if (window.parent !== window) {
|
|
122
|
+
try {
|
|
123
|
+
window.parent.postMessage({
|
|
124
|
+
e: "vault-automatic-mode-changed",
|
|
125
|
+
app,
|
|
126
|
+
mode: status.dataset.mode
|
|
127
|
+
}, origin)
|
|
128
|
+
} catch (_) {}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
})
|
|
37
132
|
|
|
38
|
-
|
|
39
|
-
"/info/vault/automatic-scans/events")
|
|
40
|
-
source.onmessage = (event) => {
|
|
133
|
+
if (window.parent !== window) {
|
|
41
134
|
try {
|
|
42
|
-
|
|
135
|
+
window.parent.postMessage({
|
|
136
|
+
e: "vault-automatic-scan-state-request"
|
|
137
|
+
}, origin)
|
|
43
138
|
} catch (_) {}
|
|
139
|
+
fallbackTimer = window.setTimeout(() => {
|
|
140
|
+
fallbackTimer = null
|
|
141
|
+
loadState()
|
|
142
|
+
}, 500)
|
|
143
|
+
} else {
|
|
144
|
+
loadState()
|
|
44
145
|
}
|
|
45
|
-
window.addEventListener("beforeunload", () => source.close(), { once: true })
|
|
46
146
|
})()
|
package/server/public/layout.js
CHANGED
|
@@ -485,6 +485,70 @@
|
|
|
485
485
|
});
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
+
let latestAutomaticScanState = null;
|
|
489
|
+
|
|
490
|
+
function automaticScanState(snapshot) {
|
|
491
|
+
const settings = snapshot && Array.isArray(snapshot.settings)
|
|
492
|
+
? snapshot.settings.filter((setting) =>
|
|
493
|
+
setting && typeof setting.app === 'string' && setting.app).map((setting) => ({
|
|
494
|
+
app: setting.app,
|
|
495
|
+
mode: setting.mode === 'manual' ? 'manual' : 'automatic',
|
|
496
|
+
}))
|
|
497
|
+
: [];
|
|
498
|
+
return {
|
|
499
|
+
global_scan_ready: !!(snapshot && snapshot.global_scan_ready === true),
|
|
500
|
+
settings,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function sendAutomaticScanState(targetWindow) {
|
|
505
|
+
if (!targetWindow || !latestAutomaticScanState) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
try {
|
|
509
|
+
targetWindow.postMessage({
|
|
510
|
+
e: 'vault-automatic-scan-state',
|
|
511
|
+
snapshot: latestAutomaticScanState,
|
|
512
|
+
}, window.location.origin);
|
|
513
|
+
} catch (_) {}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function broadcastAutomaticScanState(snapshot) {
|
|
517
|
+
latestAutomaticScanState = automaticScanState(snapshot);
|
|
518
|
+
leafElements.forEach((entry) => {
|
|
519
|
+
sendAutomaticScanState(entry.iframe?.contentWindow || null);
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function isLeafWindow(sourceWindow) {
|
|
524
|
+
if (!sourceWindow) return false;
|
|
525
|
+
for (const entry of leafElements.values()) {
|
|
526
|
+
if (entry.iframe && entry.iframe.contentWindow === sourceWindow) {
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function mergeAutomaticMode(app, mode) {
|
|
534
|
+
if (!latestAutomaticScanState || typeof app !== 'string' || !app) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
const settings = latestAutomaticScanState.settings.filter((setting) =>
|
|
538
|
+
setting.app !== app);
|
|
539
|
+
settings.push({
|
|
540
|
+
app,
|
|
541
|
+
mode: mode === 'manual' ? 'manual' : 'automatic',
|
|
542
|
+
});
|
|
543
|
+
latestAutomaticScanState = {
|
|
544
|
+
global_scan_ready: latestAutomaticScanState.global_scan_ready,
|
|
545
|
+
settings,
|
|
546
|
+
};
|
|
547
|
+
leafElements.forEach((entry) => {
|
|
548
|
+
sendAutomaticScanState(entry.iframe?.contentWindow || null);
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
488
552
|
let activeResize = null;
|
|
489
553
|
|
|
490
554
|
function beginResize(splitId, pointerEvent) {
|
|
@@ -692,6 +756,20 @@
|
|
|
692
756
|
if (!event || !event.data || typeof event.data !== 'object') {
|
|
693
757
|
return;
|
|
694
758
|
}
|
|
759
|
+
if (event.data.e === 'vault-automatic-scan-state-request') {
|
|
760
|
+
if (event.origin === window.location.origin &&
|
|
761
|
+
isLeafWindow(event.source)) {
|
|
762
|
+
sendAutomaticScanState(event.source);
|
|
763
|
+
}
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if (event.data.e === 'vault-automatic-mode-changed') {
|
|
767
|
+
if (event.origin === window.location.origin &&
|
|
768
|
+
isLeafWindow(event.source)) {
|
|
769
|
+
mergeAutomaticMode(event.data.app, event.data.mode);
|
|
770
|
+
}
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
695
773
|
if (event.data.e === 'layout-state-request') {
|
|
696
774
|
let frameEntry = null;
|
|
697
775
|
let frameId = null;
|
|
@@ -855,9 +933,12 @@
|
|
|
855
933
|
</svg>`;
|
|
856
934
|
const MIN_CHECKING_VISIBLE_MS = 500;
|
|
857
935
|
const COMPLETION_VISIBLE_MS = 4000;
|
|
936
|
+
const NOTICE_EXIT_MS = 150;
|
|
937
|
+
const NOTICE_REFLOW_MS = 180;
|
|
858
938
|
|
|
859
939
|
let eventSource = null;
|
|
860
940
|
const cards = new Map();
|
|
941
|
+
let desiredCardOrder = [];
|
|
861
942
|
|
|
862
943
|
function statusText(state) {
|
|
863
944
|
if (state === 'paused') return 'Automatic checks are paused';
|
|
@@ -907,20 +988,92 @@
|
|
|
907
988
|
card.completion = null;
|
|
908
989
|
}
|
|
909
990
|
|
|
991
|
+
function reducedMotionRequested() {
|
|
992
|
+
return typeof window.matchMedia === 'function' &&
|
|
993
|
+
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
function syncTrayVisibility() {
|
|
997
|
+
tray.hidden = !tray.querySelector('.vault-auto-scan-row');
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
function reorderCards() {
|
|
1001
|
+
const exiting = tray.querySelector('.vault-auto-scan-row.is-exiting');
|
|
1002
|
+
desiredCardOrder.forEach((app) => {
|
|
1003
|
+
const card = cards.get(app);
|
|
1004
|
+
if (!card || !card.item) return;
|
|
1005
|
+
if (!card.item.isConnected || !exiting) {
|
|
1006
|
+
tray.appendChild(card.item);
|
|
1007
|
+
}
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
function cardPositions() {
|
|
1012
|
+
const positions = new Map();
|
|
1013
|
+
tray.querySelectorAll(
|
|
1014
|
+
'.vault-auto-scan-row:not(.is-exiting)').forEach((item) => {
|
|
1015
|
+
positions.set(item, item.getBoundingClientRect());
|
|
1016
|
+
});
|
|
1017
|
+
return positions;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
function animateCardReflow(before) {
|
|
1021
|
+
if (reducedMotionRequested()) return;
|
|
1022
|
+
before.forEach((bounds, item) => {
|
|
1023
|
+
if (!item.isConnected || typeof item.animate !== 'function') return;
|
|
1024
|
+
const next = item.getBoundingClientRect();
|
|
1025
|
+
const x = bounds.left - next.left;
|
|
1026
|
+
const y = bounds.top - next.top;
|
|
1027
|
+
if (Math.abs(x) < 0.5 && Math.abs(y) < 0.5) return;
|
|
1028
|
+
item.animate([
|
|
1029
|
+
{ transform: `translate3d(${x}px, ${y}px, 0)` },
|
|
1030
|
+
{ transform: 'translate3d(0, 0, 0)' }
|
|
1031
|
+
], {
|
|
1032
|
+
duration: NOTICE_REFLOW_MS,
|
|
1033
|
+
easing: 'cubic-bezier(0.25, 1, 0.5, 1)'
|
|
1034
|
+
});
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
function finishCardRemoval(card) {
|
|
1039
|
+
const before = cardPositions();
|
|
1040
|
+
card.item.remove();
|
|
1041
|
+
reorderCards();
|
|
1042
|
+
syncTrayVisibility();
|
|
1043
|
+
animateCardReflow(before);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
910
1046
|
function removeCard(app) {
|
|
911
1047
|
const card = cards.get(app);
|
|
912
|
-
if (card)
|
|
913
|
-
|
|
914
|
-
card.item.remove();
|
|
915
|
-
}
|
|
1048
|
+
if (!card) return;
|
|
1049
|
+
stopCompletion(card);
|
|
916
1050
|
cards.delete(app);
|
|
917
|
-
|
|
1051
|
+
if (!card.item.isConnected || reducedMotionRequested()) {
|
|
1052
|
+
finishCardRemoval(card);
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
card.item.classList.add('is-exiting');
|
|
1056
|
+
let finished = false;
|
|
1057
|
+
let fallbackTimer = null;
|
|
1058
|
+
const onAnimationEnd = (event) => {
|
|
1059
|
+
if (event.target === card.item &&
|
|
1060
|
+
event.animationName === 'vault-notice-exit') finish();
|
|
1061
|
+
};
|
|
1062
|
+
const finish = () => {
|
|
1063
|
+
if (finished) return;
|
|
1064
|
+
finished = true;
|
|
1065
|
+
if (fallbackTimer !== null) window.clearTimeout(fallbackTimer);
|
|
1066
|
+
card.item.removeEventListener('animationend', onAnimationEnd);
|
|
1067
|
+
finishCardRemoval(card);
|
|
1068
|
+
};
|
|
1069
|
+
card.item.addEventListener('animationend', onAnimationEnd);
|
|
1070
|
+
fallbackTimer = window.setTimeout(finish, NOTICE_EXIT_MS + 50);
|
|
918
1071
|
}
|
|
919
1072
|
|
|
920
1073
|
function resetCards() {
|
|
1074
|
+
desiredCardOrder = [];
|
|
921
1075
|
[...cards.keys()].forEach(removeCard);
|
|
922
|
-
|
|
923
|
-
tray.hidden = true;
|
|
1076
|
+
syncTrayVisibility();
|
|
924
1077
|
}
|
|
925
1078
|
|
|
926
1079
|
function scheduleCompletion(completion) {
|
|
@@ -1033,6 +1186,7 @@
|
|
|
1033
1186
|
dismissPending: false,
|
|
1034
1187
|
pointerInside: false,
|
|
1035
1188
|
focusInside: false,
|
|
1189
|
+
isNew: true,
|
|
1036
1190
|
completion: null
|
|
1037
1191
|
};
|
|
1038
1192
|
close.addEventListener('click', async () => {
|
|
@@ -1229,6 +1383,7 @@
|
|
|
1229
1383
|
}
|
|
1230
1384
|
|
|
1231
1385
|
function render(snapshot, options = {}) {
|
|
1386
|
+
broadcastAutomaticScanState(snapshot);
|
|
1232
1387
|
if (!snapshot || snapshot.global_scan_ready !== true) {
|
|
1233
1388
|
resetCards();
|
|
1234
1389
|
return;
|
|
@@ -1244,8 +1399,15 @@
|
|
|
1244
1399
|
setting && setting.mode === 'manual').map((setting) => setting.app)
|
|
1245
1400
|
: []);
|
|
1246
1401
|
const retained = new Set();
|
|
1402
|
+
let enteringCardIndex = 0;
|
|
1247
1403
|
validRows.forEach((row) => {
|
|
1248
|
-
updateCard(row);
|
|
1404
|
+
const card = updateCard(row);
|
|
1405
|
+
if (card.isNew) {
|
|
1406
|
+
card.item.style.setProperty('--vault-notice-enter-delay',
|
|
1407
|
+
`${Math.min(enteringCardIndex, 2) * 30}ms`);
|
|
1408
|
+
card.isNew = false;
|
|
1409
|
+
enteringCardIndex += 1;
|
|
1410
|
+
}
|
|
1249
1411
|
retained.add(row.app);
|
|
1250
1412
|
});
|
|
1251
1413
|
const completion = snapshot.completion;
|
|
@@ -1260,19 +1422,21 @@
|
|
|
1260
1422
|
cards.forEach((card, app) => {
|
|
1261
1423
|
if (card.completion && !manualApps.has(app)) retained.add(app);
|
|
1262
1424
|
});
|
|
1263
|
-
[
|
|
1264
|
-
if (!retained.has(app)) removeCard(app);
|
|
1265
|
-
});
|
|
1425
|
+
const order = [];
|
|
1266
1426
|
validRows.forEach((row) => {
|
|
1267
|
-
|
|
1268
|
-
if (card) tray.appendChild(card.item);
|
|
1427
|
+
if (!order.includes(row.app)) order.push(row.app);
|
|
1269
1428
|
});
|
|
1270
1429
|
cards.forEach((card, app) => {
|
|
1271
|
-
if (card.completion && !liveApps.has(app)) {
|
|
1272
|
-
|
|
1430
|
+
if (card.completion && !liveApps.has(app) && !order.includes(app)) {
|
|
1431
|
+
order.push(app);
|
|
1273
1432
|
}
|
|
1274
1433
|
});
|
|
1275
|
-
|
|
1434
|
+
desiredCardOrder = order;
|
|
1435
|
+
[...cards.keys()].forEach((app) => {
|
|
1436
|
+
if (!retained.has(app)) removeCard(app);
|
|
1437
|
+
});
|
|
1438
|
+
reorderCards();
|
|
1439
|
+
syncTrayVisibility();
|
|
1276
1440
|
}
|
|
1277
1441
|
|
|
1278
1442
|
async function loadState() {
|
|
@@ -1308,7 +1472,6 @@
|
|
|
1308
1472
|
}
|
|
1309
1473
|
};
|
|
1310
1474
|
eventSource.onerror = () => {
|
|
1311
|
-
resetCards();
|
|
1312
1475
|
loadState();
|
|
1313
1476
|
};
|
|
1314
1477
|
}
|
package/server/public/vault.css
CHANGED
|
@@ -910,6 +910,39 @@ body[data-vault-mode="global"] .vault-explorer {
|
|
|
910
910
|
display: grid;
|
|
911
911
|
gap: 0;
|
|
912
912
|
}
|
|
913
|
+
.vault-find-size-setting {
|
|
914
|
+
display: grid;
|
|
915
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
916
|
+
align-items: center;
|
|
917
|
+
gap: 16px;
|
|
918
|
+
min-height: 68px;
|
|
919
|
+
padding: 12px 18px;
|
|
920
|
+
border-bottom: 1px solid var(--task-border);
|
|
921
|
+
background: var(--task-panel);
|
|
922
|
+
}
|
|
923
|
+
.vault-find-size-copy {
|
|
924
|
+
display: grid;
|
|
925
|
+
min-width: 0;
|
|
926
|
+
gap: 3px;
|
|
927
|
+
color: var(--task-text);
|
|
928
|
+
cursor: pointer;
|
|
929
|
+
}
|
|
930
|
+
.vault-find-size-copy strong {
|
|
931
|
+
font-size: 12.5px;
|
|
932
|
+
font-weight: 650;
|
|
933
|
+
line-height: 1.2;
|
|
934
|
+
}
|
|
935
|
+
.vault-find-size-copy span {
|
|
936
|
+
color: var(--task-muted);
|
|
937
|
+
font-size: 10.5px;
|
|
938
|
+
font-weight: 450;
|
|
939
|
+
line-height: 1.2;
|
|
940
|
+
}
|
|
941
|
+
.vault-select.vault-find-size-select {
|
|
942
|
+
min-width: 118px;
|
|
943
|
+
height: 34px;
|
|
944
|
+
cursor: pointer;
|
|
945
|
+
}
|
|
913
946
|
.vault-find-choice {
|
|
914
947
|
display: grid;
|
|
915
948
|
width: 100%;
|
|
@@ -2037,6 +2070,11 @@ body.dark .vault-row-action .vault-text-button:hover:not(:disabled) {
|
|
|
2037
2070
|
}
|
|
2038
2071
|
@media (max-width: 520px) {
|
|
2039
2072
|
.vault-storage-legend { column-gap: 14px; row-gap: 4px; }
|
|
2073
|
+
.vault-find-size-setting {
|
|
2074
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2075
|
+
gap: 10px;
|
|
2076
|
+
}
|
|
2077
|
+
.vault-select.vault-find-size-select { width: 100%; }
|
|
2040
2078
|
}
|
|
2041
2079
|
@media (pointer: coarse) {
|
|
2042
2080
|
.vault-page {
|
|
@@ -2048,6 +2086,7 @@ body.dark .vault-row-action .vault-text-button:hover:not(:disabled) {
|
|
|
2048
2086
|
.vault-result .vault-button,
|
|
2049
2087
|
.vault-group-action .vault-button { min-height: 44px; }
|
|
2050
2088
|
.vault-scan-size-option { min-height: 44px; }
|
|
2089
|
+
.vault-select.vault-find-size-select { height: 44px; }
|
|
2051
2090
|
.vault-icon-button { width: 44px; height: 44px; }
|
|
2052
2091
|
.vault-find-tree-row {
|
|
2053
2092
|
grid-template-columns: 44px 44px 17px minmax(0, 1fr);
|