pinokiod 8.0.47 → 8.0.49
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/constants.js +2 -2
- package/kernel/vault/index.js +18 -0
- package/package.json +1 -1
- package/server/public/vault.css +33 -2
- package/server/public/vault.js +194 -68
- package/server/views/partials/vault_workspace.ejs +1 -0
- package/test/vault-engine.test.js +21 -0
- package/test/vault-ui.test.js +484 -14
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const CANDIDATE_SIZE_BASE = process.platform === "win32" ? 1024 : 1000
|
|
2
|
-
const CANDIDATE_SIZE_OPTIONS = [10, 50, 100, 500]
|
|
2
|
+
const CANDIDATE_SIZE_OPTIONS = [1, 10, 50, 100, 500]
|
|
3
3
|
.map((value) => value * CANDIDATE_SIZE_BASE ** 2)
|
|
4
4
|
.concat(CANDIDATE_SIZE_BASE ** 3)
|
|
5
5
|
|
|
6
6
|
module.exports = {
|
|
7
|
-
SIZE_THRESHOLD: CANDIDATE_SIZE_OPTIONS[
|
|
7
|
+
SIZE_THRESHOLD: CANDIDATE_SIZE_OPTIONS[3],
|
|
8
8
|
CANDIDATE_SIZE_OPTIONS,
|
|
9
9
|
TMP_SUFFIX: ".pinokio-dedup-tmp",
|
|
10
10
|
SHA256_RE: /^[0-9a-f]{64}$/,
|
package/kernel/vault/index.js
CHANGED
|
@@ -1712,6 +1712,7 @@ class Vault {
|
|
|
1712
1712
|
)
|
|
1713
1713
|
let bytesOnDisk = 0
|
|
1714
1714
|
let wouldBe = 0
|
|
1715
|
+
let trackedLogicalBytes = 0
|
|
1715
1716
|
for (let index = 0; index < blobEntries.length; index++) {
|
|
1716
1717
|
const [hash, blob] = blobEntries[index]
|
|
1717
1718
|
const names = namesByHash.get(hash) || []
|
|
@@ -1723,6 +1724,7 @@ class Vault {
|
|
|
1723
1724
|
const linkedCopy = storeStat || names.some((name) => name.mode === "link") ? 1 : 0
|
|
1724
1725
|
const physicalCopies = linkedCopy + names.filter((name) => name.mode === "copy").length
|
|
1725
1726
|
const pendingBytes = pendingBytesByHash.get(hash) || 0
|
|
1727
|
+
trackedLogicalBytes += (size * names.length) + pendingBytes
|
|
1726
1728
|
bytesOnDisk += (size * physicalCopies) + pendingBytes
|
|
1727
1729
|
wouldBe += (size * Math.max(physicalCopies, names.length)) + pendingBytes
|
|
1728
1730
|
const orphan = !!(storeStat && storeStat.nlink === 1)
|
|
@@ -1733,6 +1735,22 @@ class Vault {
|
|
|
1733
1735
|
blobs.push(publicBlob)
|
|
1734
1736
|
blobByHash.set(hash, publicBlob)
|
|
1735
1737
|
}
|
|
1738
|
+
if (!scopeId) {
|
|
1739
|
+
// The scan total covers every regular file, including files below the
|
|
1740
|
+
// candidate threshold and files the user kept separate. The registry
|
|
1741
|
+
// figures above cover only content tracked by Save space. Add the
|
|
1742
|
+
// remainder to both sides so the global comparison represents the
|
|
1743
|
+
// complete scanned locations instead of silently omitting small files.
|
|
1744
|
+
const lastScan = registry.scanFor()
|
|
1745
|
+
const scannedBytes = lastScan && Number.isFinite(lastScan.bytes_total)
|
|
1746
|
+
? lastScan.bytes_total
|
|
1747
|
+
: null
|
|
1748
|
+
const untrackedScannedBytes = scannedBytes === null
|
|
1749
|
+
? 0
|
|
1750
|
+
: Math.max(0, scannedBytes - trackedLogicalBytes)
|
|
1751
|
+
bytesOnDisk += untrackedScannedBytes
|
|
1752
|
+
wouldBe += untrackedScannedBytes
|
|
1753
|
+
}
|
|
1736
1754
|
const duplicates = []
|
|
1737
1755
|
for (const [p, entry] of registry.duplicates) {
|
|
1738
1756
|
if (scopeId && entry.source_id !== scopeId) continue
|
package/package.json
CHANGED
package/server/public/vault.css
CHANGED
|
@@ -300,7 +300,8 @@ body[data-vault-mode="app"] .vault-overview {
|
|
|
300
300
|
.vault-action-state,
|
|
301
301
|
.vault-result,
|
|
302
302
|
.vault-feedback,
|
|
303
|
-
.vault-cloud-warning
|
|
303
|
+
.vault-cloud-warning,
|
|
304
|
+
.vault-cleanup-notice {
|
|
304
305
|
display: none;
|
|
305
306
|
align-items: center;
|
|
306
307
|
min-height: 38px;
|
|
@@ -319,7 +320,8 @@ body[data-vault-mode="app"] .vault-overview {
|
|
|
319
320
|
.vault-action-state.show,
|
|
320
321
|
.vault-result.show,
|
|
321
322
|
.vault-feedback.show,
|
|
322
|
-
.vault-cloud-warning.show
|
|
323
|
+
.vault-cloud-warning.show,
|
|
324
|
+
.vault-cleanup-notice.show { display: flex; }
|
|
323
325
|
.vault-scan-state i,
|
|
324
326
|
.vault-action-state i,
|
|
325
327
|
.vault-result > i { color: var(--task-accent); }
|
|
@@ -469,6 +471,18 @@ body[data-vault-mode="app"] .vault-overview {
|
|
|
469
471
|
.vault-cloud-warning { min-height: 34px; background: var(--vault-warning-soft); }
|
|
470
472
|
.vault-cloud-warning > i { color: var(--vault-warning); }
|
|
471
473
|
.vault-cloud-warning .vault-text-button { margin-left: auto; }
|
|
474
|
+
.vault-cleanup-notice {
|
|
475
|
+
flex: 0 0 auto;
|
|
476
|
+
background: color-mix(in srgb, var(--task-accent) 5%, var(--task-panel));
|
|
477
|
+
}
|
|
478
|
+
.vault-cleanup-notice > i { color: var(--task-accent); }
|
|
479
|
+
.vault-cleanup-notice strong { flex: 0 0 auto; font-weight: 650; }
|
|
480
|
+
.vault-cleanup-notice-detail {
|
|
481
|
+
min-width: 0;
|
|
482
|
+
flex: 1 1 auto;
|
|
483
|
+
color: var(--task-muted);
|
|
484
|
+
}
|
|
485
|
+
.vault-cleanup-notice .vault-button { flex: 0 0 auto; margin-left: auto; }
|
|
472
486
|
.vault-explorer {
|
|
473
487
|
display: grid;
|
|
474
488
|
min-height: 0;
|
|
@@ -912,10 +926,17 @@ body.dark .vault-row-action .vault-text-button:hover:not(:disabled) {
|
|
|
912
926
|
.vault-empty p { margin: 0; color: var(--task-muted); font-size: 12px; line-height: 1.55; }
|
|
913
927
|
.vault-empty .vault-button { margin-top: 10px; }
|
|
914
928
|
.vault-pane-footer {
|
|
929
|
+
display: flex;
|
|
930
|
+
align-items: center;
|
|
931
|
+
justify-content: space-between;
|
|
932
|
+
gap: 12px;
|
|
915
933
|
padding: 9px var(--vault-inline) 11px;
|
|
916
934
|
color: var(--task-muted);
|
|
917
935
|
font-size: 10.5px;
|
|
918
936
|
}
|
|
937
|
+
.vault-pagination { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; }
|
|
938
|
+
.vault-pagination .vault-text-button:disabled { cursor: default; }
|
|
939
|
+
.vault-page-range { font-variant-numeric: tabular-nums; }
|
|
919
940
|
.vault-event-kind { font-weight: 570; }
|
|
920
941
|
.vault-event-time { color: var(--task-muted); font-size: 10.5px; }
|
|
921
942
|
.vault-unavailable { color: var(--task-muted); font-size: 11px; }
|
|
@@ -943,7 +964,17 @@ body.dark .vault-row-action .vault-text-button:hover:not(:disabled) {
|
|
|
943
964
|
.vault-result-message { grid-template-columns: 16px minmax(0, 1fr); padding: 9px 0; }
|
|
944
965
|
.vault-result-heading { align-items: flex-start; flex-direction: column; gap: 2px; }
|
|
945
966
|
.vault-result-actions { grid-column: 2; }
|
|
967
|
+
.vault-pane-footer { align-items: flex-start; flex-direction: column; }
|
|
946
968
|
.vault-result.incomplete .vault-button { margin: 0; }
|
|
969
|
+
.vault-cleanup-notice.show {
|
|
970
|
+
display: grid;
|
|
971
|
+
grid-template-columns: 16px minmax(0, 1fr) auto;
|
|
972
|
+
align-items: center;
|
|
973
|
+
}
|
|
974
|
+
.vault-cleanup-notice > i { grid-area: 1 / 1; }
|
|
975
|
+
.vault-cleanup-notice strong { grid-area: 1 / 2; }
|
|
976
|
+
.vault-cleanup-notice-detail { grid-area: 2 / 2 / 3 / 4; }
|
|
977
|
+
.vault-cleanup-notice .vault-button { grid-area: 1 / 3; margin-left: 0; }
|
|
947
978
|
}
|
|
948
979
|
@media (pointer: coarse) {
|
|
949
980
|
.vault-page {
|