pinokiod 8.0.116 → 8.0.117
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/registry_core.js +4 -3
- package/package.json +1 -1
- package/server/public/vault.js +11 -24
- package/test/vault-engine.test.js +21 -2
- package/test/vault-ui.test.js +37 -0
|
@@ -5414,11 +5414,12 @@ class RegistryCore {
|
|
|
5414
5414
|
where.push(clause.sql)
|
|
5415
5415
|
values.push(...clause.values)
|
|
5416
5416
|
}
|
|
5417
|
+
const folded = "pinokio_path_name(name)"
|
|
5417
5418
|
const order = sizeSort === "asc"
|
|
5418
|
-
?
|
|
5419
|
+
? `bytes ASC, ${folded} ASC`
|
|
5419
5420
|
: sizeSort === "desc"
|
|
5420
|
-
?
|
|
5421
|
-
: nameSort === "desc" ?
|
|
5421
|
+
? `bytes DESC, ${folded} ASC`
|
|
5422
|
+
: nameSort === "desc" ? `${folded} DESC` : `${folded} ASC`
|
|
5422
5423
|
// Values bind in the order the placeholders appear: the CTE's substr, then
|
|
5423
5424
|
// its WHERE, then the two separators in the outer select and filter.
|
|
5424
5425
|
return this.database.prepare(`
|
package/package.json
CHANGED
package/server/public/vault.js
CHANGED
|
@@ -2098,13 +2098,14 @@ const sourceSort = (a, b) => {
|
|
|
2098
2098
|
const rank = (source) => source && source.kind === "external" ? 1 : source ? 0 : 2
|
|
2099
2099
|
return rank(first) - rank(second) || groupTitle(first).localeCompare(groupTitle(second))
|
|
2100
2100
|
}
|
|
2101
|
-
// The
|
|
2102
|
-
// order the
|
|
2103
|
-
|
|
2101
|
+
// The name a row shows in its Name column. Every list orders by this, so the
|
|
2102
|
+
// order matches the column the user clicked; the path below it is context, not
|
|
2103
|
+
// the sort key.
|
|
2104
|
+
const rowName = (item) => basename(item.relative_path || item.path)
|
|
2104
2105
|
const flatLocation = (item) => externalLocation(item) ||
|
|
2105
2106
|
[groupTitle(sourceById(item.source_id)), item.relative_path].filter(Boolean).join(" / ")
|
|
2106
2107
|
const renderFlatFiles = (items) => [...items]
|
|
2107
|
-
.sort((a, b) => compareRows(a, b,
|
|
2108
|
+
.sort((a, b) => compareRows(a, b, rowName))
|
|
2108
2109
|
.map((item) => {
|
|
2109
2110
|
const expandable = Number(item.location_count) > 1
|
|
2110
2111
|
return `<div class="vault-file-row">
|
|
@@ -2205,7 +2206,7 @@ const renderDuplicateGroups = (items) => {
|
|
|
2205
2206
|
const action = source && source.shareable && allShareable
|
|
2206
2207
|
? `<button class="vault-button" type="button" data-deduplicate-scope="${attr(sourceId)}">${esc(COPY.deduplicate)} ${countLabel(allShareable)}</button>`
|
|
2207
2208
|
: `<span class="vault-unavailable">${esc(COPY.sharing_unavailable)}</span>`
|
|
2208
|
-
return `<div class="vault-group-row"><div class="vault-group-main"><div class="vault-group-title"><i class="fa-regular fa-folder"></i><span>${esc(groupTitle(source))}</span></div><div class="vault-group-meta">${countLabel(group.length, COPY.duplicate.toLowerCase(), COPY.duplicates.toLowerCase())} · ${bytes ? fmt(bytes) : COPY.unavailable}</div></div><div class="vault-group-action">${action}</div></div>${[...group].sort((a, b) => compareRows(a, b,
|
|
2209
|
+
return `<div class="vault-group-row"><div class="vault-group-main"><div class="vault-group-title"><i class="fa-regular fa-folder"></i><span>${esc(groupTitle(source))}</span></div><div class="vault-group-meta">${countLabel(group.length, COPY.duplicate.toLowerCase(), COPY.duplicates.toLowerCase())} · ${bytes ? fmt(bytes) : COPY.unavailable}</div></div><div class="vault-group-action">${action}</div></div>${[...group].sort((a, b) => compareRows(a, b, rowName)).map((item) => renderFileRow(item, 0, true)).join("")}`
|
|
2209
2210
|
}).join("")
|
|
2210
2211
|
}
|
|
2211
2212
|
|
|
@@ -2226,8 +2227,10 @@ const emptyState = (view) => {
|
|
|
2226
2227
|
return `<div class="vault-empty"><div class="vault-empty-inner"><i class="${content[2]}"></i><h3>${esc(content[0])}</h3><p>${esc(content[1])}</p>${view === "duplicates" ? `<button class="vault-button" type="button" data-view="all">${esc(COPY.view_all)}</button>` : ""}</div></div>`
|
|
2227
2228
|
}
|
|
2228
2229
|
|
|
2229
|
-
const renderReclaimable = (
|
|
2230
|
-
if (!
|
|
2230
|
+
const renderReclaimable = (rows) => {
|
|
2231
|
+
if (!rows.length) return emptyState("reclaimable")
|
|
2232
|
+
const blobs = [...rows]
|
|
2233
|
+
.sort((left, right) => compareRows(left, right, (blob) => blob.hash))
|
|
2231
2234
|
return blobs.map((blob) => `<div class="vault-file-row"><div class="vault-name-cell"><span class="vault-disclosure"></span><i class="fa-regular fa-file vault-name-icon"></i><span class="vault-name-copy"><span class="vault-file-name">${esc(`${blob.hash.slice(0, 12)}…`)}</span></span></div><span class="vault-size">${fmt(blob.size)}</span><span class="vault-space">${fmt(blob.size)}</span><span class="vault-row-action"><button class="vault-text-button" type="button" data-reclaim="${attr(blob.hash)}" data-reclaim-store="${attr(blob.store_id)}">${esc(COPY.reclaim)}</button></span></div>`).join("")
|
|
2232
2235
|
}
|
|
2233
2236
|
|
|
@@ -2461,22 +2464,6 @@ const renderTable = (items) => {
|
|
|
2461
2464
|
syncDuplicateGroupPageSelectionCheckbox()
|
|
2462
2465
|
}
|
|
2463
2466
|
|
|
2464
|
-
const orderedItems = (items) => {
|
|
2465
|
-
if (state.view === "activity") return items
|
|
2466
|
-
if (items.some((item) => item.kind === "duplicate_group")) return items
|
|
2467
|
-
if (state.view === "reclaimable") {
|
|
2468
|
-
return [...items].sort((a, b) => compareRows(a, b,
|
|
2469
|
-
(blob) => blob.hash))
|
|
2470
|
-
}
|
|
2471
|
-
if (state.displayMode === "files" && supportsDisplayMode()) {
|
|
2472
|
-
return [...items].sort((a, b) => compareRows(a, b, flatName))
|
|
2473
|
-
}
|
|
2474
|
-
return [...items].sort((a, b) => {
|
|
2475
|
-
const sourceOrder = state.sourceId ? 0 : sourceSort([a.source_id], [b.source_id])
|
|
2476
|
-
return sourceOrder || compareRows(a, b, (item) => item.relative_path || item.path)
|
|
2477
|
-
})
|
|
2478
|
-
}
|
|
2479
|
-
|
|
2480
2467
|
const pagedItems = (items) => {
|
|
2481
2468
|
const inventory = state.data.inventory
|
|
2482
2469
|
state.page = Number(inventory.page) || 0
|
|
@@ -2493,7 +2480,7 @@ const pagedItems = (items) => {
|
|
|
2493
2480
|
}
|
|
2494
2481
|
}
|
|
2495
2482
|
return {
|
|
2496
|
-
items
|
|
2483
|
+
items,
|
|
2497
2484
|
start: Number(inventory.start) || 0,
|
|
2498
2485
|
end: Number(inventory.end) || 0,
|
|
2499
2486
|
total: Number(inventory.total) || 0,
|
|
@@ -394,7 +394,9 @@ describe("Save Space engine", () => {
|
|
|
394
394
|
[`${root}\\app\\models\\big.bin`, 4000],
|
|
395
395
|
[`${root}\\app\\models\\small.bin`, 10],
|
|
396
396
|
[`${root}\\cache\\only\\deep\\x.bin`, 50],
|
|
397
|
-
[`${root}\\loose.bin`, 700]
|
|
397
|
+
[`${root}\\loose.bin`, 700],
|
|
398
|
+
[`${root}\\Zebra\\z.bin`, 5],
|
|
399
|
+
[`${root}\\apple\\a.bin`, 5]
|
|
398
400
|
].forEach(([filePath, size], index) =>
|
|
399
401
|
insert.run(filePath, `h${index}`, size, index + 1))
|
|
400
402
|
|
|
@@ -409,7 +411,24 @@ describe("Save Space engine", () => {
|
|
|
409
411
|
limit: 50,
|
|
410
412
|
offset: 0
|
|
411
413
|
})
|
|
412
|
-
assert.deepEqual(directories.map((row) => row.name),
|
|
414
|
+
assert.deepEqual(directories.map((row) => row.name).slice(0, 2),
|
|
415
|
+
["app", "cache"])
|
|
416
|
+
// Folder names fold case the same way file names do, so a capitalised
|
|
417
|
+
// folder does not jump ahead of every lowercase one.
|
|
418
|
+
const cased = core.treeDirectoryRows({
|
|
419
|
+
sourceId: "app:demo",
|
|
420
|
+
prefix: `${root}\\`,
|
|
421
|
+
separator: "\\",
|
|
422
|
+
statuses: [],
|
|
423
|
+
query: "",
|
|
424
|
+
nameOnly: false,
|
|
425
|
+
sizeSort: null,
|
|
426
|
+
nameSort: "asc",
|
|
427
|
+
limit: 50,
|
|
428
|
+
offset: 0
|
|
429
|
+
})
|
|
430
|
+
assert.deepEqual(cased.map((row) => row.name),
|
|
431
|
+
["app", "apple", "cache", "Zebra"])
|
|
413
432
|
assert.equal(directories[0].bytes, 4010)
|
|
414
433
|
// The collapse reads these, so they have to carry the whole subpath.
|
|
415
434
|
assert.equal(directories[1].lo, "cache\\only\\deep\\x.bin")
|
package/test/vault-ui.test.js
CHANGED
|
@@ -1015,6 +1015,43 @@ describe("Save Space interface", () => {
|
|
|
1015
1015
|
dom.window.close()
|
|
1016
1016
|
})
|
|
1017
1017
|
|
|
1018
|
+
test("Duplicates in Folders orders by name, not by the path below it", async () => {
|
|
1019
|
+
// Names and paths disagree on purpose: ordering by path gives decord,
|
|
1020
|
+
// numpy.libs, torch, triton -- which is what the screen used to show.
|
|
1021
|
+
const files = [
|
|
1022
|
+
["zebra.dll", "app/decord/zebra.dll"],
|
|
1023
|
+
["mango.dll", "app/numpy.libs/mango.dll"],
|
|
1024
|
+
["apple.dll", "app/torch/lib/apple.dll"]
|
|
1025
|
+
].map(([name, relative]) => item({
|
|
1026
|
+
path: `/pinokio/api/app/${relative}`,
|
|
1027
|
+
relative_path: relative,
|
|
1028
|
+
status: "duplicate",
|
|
1029
|
+
shareable: true,
|
|
1030
|
+
location_count: 2
|
|
1031
|
+
}))
|
|
1032
|
+
const base = fixture(files)
|
|
1033
|
+
base.inventory.source_counts.duplicates["app:app"] = files.length
|
|
1034
|
+
base.inventory.shareable_by_source["app:app"] = files.length
|
|
1035
|
+
const { dom } = await makePage(base)
|
|
1036
|
+
const document = dom.window.document
|
|
1037
|
+
|
|
1038
|
+
document.querySelector('[data-view="duplicates"]').click()
|
|
1039
|
+
await waitFor(() => document.querySelector(
|
|
1040
|
+
'[data-view="duplicates"].selected'))
|
|
1041
|
+
const names = () => [...document.querySelectorAll(
|
|
1042
|
+
"#vault-table-wrap .vault-file-name")].map((node) => node.textContent)
|
|
1043
|
+
|
|
1044
|
+
document.querySelector("[data-sort-name]").click()
|
|
1045
|
+
await waitFor(() => names()[0] === "apple.dll")
|
|
1046
|
+
assert.deepEqual(names(), ["apple.dll", "mango.dll", "zebra.dll"])
|
|
1047
|
+
|
|
1048
|
+
document.querySelector("[data-sort-name]").click()
|
|
1049
|
+
await waitFor(() => names()[0] === "zebra.dll")
|
|
1050
|
+
assert.deepEqual(names(), ["zebra.dll", "mango.dll", "apple.dll"])
|
|
1051
|
+
await settle()
|
|
1052
|
+
dom.window.close()
|
|
1053
|
+
})
|
|
1054
|
+
|
|
1018
1055
|
test("name sorting is offered wherever the Name column holds a name", async () => {
|
|
1019
1056
|
const duplicate = item({
|
|
1020
1057
|
path: "/pinokio/api/app/models/duplicate.bin",
|