@tutti-os/workspace-file-manager 0.0.181 → 0.0.183
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/README.md +6 -5
- package/dist/{chunk-KVP3Z2Y5.js → chunk-3CYSESCR.js} +222 -318
- package/dist/chunk-3CYSESCR.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +10 -28
- package/dist/index.js.map +1 -1
- package/dist/services/index.d.ts +5 -5
- package/dist/services/index.js +3 -27
- package/dist/{workspaceFileManagerLocations-mW7kL37e.d.ts → workspaceFileManagerLocations-nzbPIFj_.d.ts} +4 -13
- package/package.json +4 -4
- package/dist/chunk-KVP3Z2Y5.js.map +0 -1
package/README.md
CHANGED
|
@@ -18,11 +18,12 @@ only a transport-agnostic data kernel. Shared session orchestration, preview
|
|
|
18
18
|
flow, upload flow, activation flow, and React-facing interaction state may live
|
|
19
19
|
here when they are part of the reusable file-manager experience across hosts.
|
|
20
20
|
|
|
21
|
-
The shared surface
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
The shared surface consumes host-neutral classification and loading lifecycle
|
|
22
|
+
from `@tutti-os/workspace-file-preview`. This package owns file-manager-specific
|
|
23
|
+
activation-target shaping, localized state projection, shared view-model
|
|
24
|
+
derivation, and the host contract needed to drive those flows so different
|
|
25
|
+
hosts can integrate primarily by implementing `WorkspaceFileManagerHost`
|
|
26
|
+
instead of rebuilding workflow around the shared UI.
|
|
26
27
|
|
|
27
28
|
The optional React surface persists the adjustable locations-sidebar and
|
|
28
29
|
details-panel widths on the current device. Restored widths are clamped to the
|
|
@@ -1,110 +1,8 @@
|
|
|
1
|
-
// src/services/internal/workspaceFileManagerStore.ts
|
|
2
|
-
import { proxy } from "valtio";
|
|
3
|
-
|
|
4
1
|
// src/services/workspaceFileManagerTypes.ts
|
|
5
2
|
var workspaceFileManagerLogicalRoot = "/";
|
|
6
3
|
var workspaceFileManagerPersistedStateSchemaVersion = 3;
|
|
7
4
|
var workspaceFileManagerPreviousPersistedStateSchemaVersion = 2;
|
|
8
5
|
|
|
9
|
-
// src/services/internal/model/fileKinds.ts
|
|
10
|
-
import {
|
|
11
|
-
classifyWorkspaceFilePreviewKind as classifySharedWorkspaceFilePreviewKind,
|
|
12
|
-
resolveWorkspaceFileActivationTarget as resolveSharedWorkspaceFileActivationTarget,
|
|
13
|
-
resolveWorkspaceFilePreviewReadiness as resolveSharedWorkspaceFilePreviewReadiness
|
|
14
|
-
} from "@tutti-os/workspace-file-preview";
|
|
15
|
-
import {
|
|
16
|
-
copyWorkspaceFilePreviewBytes,
|
|
17
|
-
createWorkspaceFilePreviewLoadedState,
|
|
18
|
-
decodeWorkspaceTextFile,
|
|
19
|
-
formatWorkspacePreviewByteLimit,
|
|
20
|
-
isWorkspaceFileBrowserOpenable,
|
|
21
|
-
isWorkspacePreviewFileTooLarge,
|
|
22
|
-
isWorkspaceTextFileTooLarge,
|
|
23
|
-
looksLikeBinaryText,
|
|
24
|
-
normalizeWorkspaceFilePreviewBytes,
|
|
25
|
-
resolveWorkspaceFileExtension,
|
|
26
|
-
resolveWorkspaceFileVisualKind,
|
|
27
|
-
resolveWorkspaceImageMimeType,
|
|
28
|
-
resolveWorkspaceVideoMimeType,
|
|
29
|
-
workspaceFilePreviewMaxBytes,
|
|
30
|
-
workspaceFileTextMaxBytes
|
|
31
|
-
} from "@tutti-os/workspace-file-preview";
|
|
32
|
-
function classifyWorkspaceFilePreviewKind(entry) {
|
|
33
|
-
return classifySharedWorkspaceFilePreviewKind(entry);
|
|
34
|
-
}
|
|
35
|
-
function resolveWorkspaceFileActivationTarget(entry) {
|
|
36
|
-
const target = resolveSharedWorkspaceFileActivationTarget(entry);
|
|
37
|
-
if (!target) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
return {
|
|
41
|
-
fileKind: target.fileKind,
|
|
42
|
-
mtimeMs: target.mtimeMs ?? null,
|
|
43
|
-
name: target.name,
|
|
44
|
-
path: target.path,
|
|
45
|
-
sizeBytes: target.sizeBytes ?? null
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
function resolveWorkspaceFilePreviewReadiness(entry) {
|
|
49
|
-
const readiness = resolveSharedWorkspaceFilePreviewReadiness(entry);
|
|
50
|
-
if (readiness.status !== "ready") {
|
|
51
|
-
return readiness;
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
entry,
|
|
55
|
-
status: "ready",
|
|
56
|
-
target: {
|
|
57
|
-
fileKind: readiness.target.fileKind,
|
|
58
|
-
mtimeMs: readiness.target.mtimeMs ?? null,
|
|
59
|
-
name: readiness.target.name,
|
|
60
|
-
path: readiness.target.path,
|
|
61
|
-
sizeBytes: readiness.target.sizeBytes ?? null
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// src/services/internal/model/formatters.ts
|
|
67
|
-
import { formatTuttiShortDateTime } from "@tutti-os/ui-system/date-format";
|
|
68
|
-
function formatWorkspaceFileBytes(sizeBytes) {
|
|
69
|
-
if (sizeBytes === null || !Number.isFinite(sizeBytes)) {
|
|
70
|
-
return "--";
|
|
71
|
-
}
|
|
72
|
-
if (sizeBytes < 1024) {
|
|
73
|
-
return `${sizeBytes} B`;
|
|
74
|
-
}
|
|
75
|
-
const units = ["KB", "MB", "GB", "TB"];
|
|
76
|
-
let value = sizeBytes / 1024;
|
|
77
|
-
let unitIndex = 0;
|
|
78
|
-
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
79
|
-
value /= 1024;
|
|
80
|
-
unitIndex += 1;
|
|
81
|
-
}
|
|
82
|
-
return `${value >= 10 ? value.toFixed(1) : value.toFixed(2)} ${units[unitIndex]}`;
|
|
83
|
-
}
|
|
84
|
-
function formatWorkspaceFileModifiedTime(mtimeMs, locale) {
|
|
85
|
-
if (mtimeMs === null || !Number.isFinite(mtimeMs) || mtimeMs <= 0) {
|
|
86
|
-
return "--";
|
|
87
|
-
}
|
|
88
|
-
return formatTuttiShortDateTime(mtimeMs, locale);
|
|
89
|
-
}
|
|
90
|
-
function splitWorkspaceFileName(name) {
|
|
91
|
-
const extensionIndex = name.lastIndexOf(".");
|
|
92
|
-
const hasExtension = extensionIndex > 0 && extensionIndex < name.length - 1;
|
|
93
|
-
if (hasExtension) {
|
|
94
|
-
return {
|
|
95
|
-
end: name.slice(extensionIndex),
|
|
96
|
-
start: name.slice(0, extensionIndex)
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
if (name.length <= 24) {
|
|
100
|
-
return { end: "", start: name };
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
end: name.slice(-10),
|
|
104
|
-
start: name.slice(0, -10)
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
6
|
// src/services/internal/model/paths.ts
|
|
109
7
|
function normalizeWorkspaceFilePath(value, rootPath) {
|
|
110
8
|
const root = normalizeWorkspaceFileAbsolutePath(rootPath);
|
|
@@ -205,30 +103,6 @@ function readWindowsDrive(path) {
|
|
|
205
103
|
return /^[A-Za-z]:/.exec(path)?.[0] ?? "";
|
|
206
104
|
}
|
|
207
105
|
|
|
208
|
-
// src/services/internal/model/searchEntries.ts
|
|
209
|
-
function workspaceFileSearchEntryToEntry(entry) {
|
|
210
|
-
return {
|
|
211
|
-
hasChildren: entry.kind === "directory",
|
|
212
|
-
kind: entry.kind,
|
|
213
|
-
mtimeMs: null,
|
|
214
|
-
name: entry.name,
|
|
215
|
-
path: entry.path,
|
|
216
|
-
sizeBytes: null
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// src/services/internal/model/validation.ts
|
|
221
|
-
function validateWorkspaceFileEntryName(name) {
|
|
222
|
-
const trimmed = name.trim();
|
|
223
|
-
if (!trimmed) {
|
|
224
|
-
return "required";
|
|
225
|
-
}
|
|
226
|
-
if (trimmed.includes("/") || trimmed.includes("\\") || trimmed === "." || trimmed === "..") {
|
|
227
|
-
return "invalid";
|
|
228
|
-
}
|
|
229
|
-
return null;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
106
|
// src/services/workspaceFileManagerLocations.ts
|
|
233
107
|
function flattenWorkspaceFileLocations(sections) {
|
|
234
108
|
return sections.flatMap((section) => section.locations);
|
|
@@ -266,6 +140,148 @@ function isWorkspaceFileExternalLocation(location) {
|
|
|
266
140
|
return location?.kind === "external";
|
|
267
141
|
}
|
|
268
142
|
|
|
143
|
+
// src/services/internal/model/openWithApplicationsCache.ts
|
|
144
|
+
import { resolveWorkspaceFileExtension } from "@tutti-os/workspace-file-preview";
|
|
145
|
+
var openWithWarmupLimit = 8;
|
|
146
|
+
function resolveWorkspaceFileOpenWithCacheKey(entry) {
|
|
147
|
+
const extension = resolveWorkspaceFileExtension(
|
|
148
|
+
entry.path || entry.name || ""
|
|
149
|
+
);
|
|
150
|
+
return `${entry.kind}:${extension || "(no-ext)"}`;
|
|
151
|
+
}
|
|
152
|
+
var WorkspaceFileOpenWithApplicationsCache = class {
|
|
153
|
+
applicationsByKey = /* @__PURE__ */ new Map();
|
|
154
|
+
inflightByKey = /* @__PURE__ */ new Map();
|
|
155
|
+
warmupScheduledKeys = /* @__PURE__ */ new Set();
|
|
156
|
+
get(key) {
|
|
157
|
+
return this.applicationsByKey.get(key) ?? null;
|
|
158
|
+
}
|
|
159
|
+
async resolve(key, load) {
|
|
160
|
+
const cached = this.applicationsByKey.get(key);
|
|
161
|
+
if (cached) {
|
|
162
|
+
return cached;
|
|
163
|
+
}
|
|
164
|
+
const inflight = this.inflightByKey.get(key);
|
|
165
|
+
if (inflight) {
|
|
166
|
+
return inflight;
|
|
167
|
+
}
|
|
168
|
+
const promise = load().then((applications) => {
|
|
169
|
+
this.applicationsByKey.set(key, applications);
|
|
170
|
+
this.inflightByKey.delete(key);
|
|
171
|
+
return applications;
|
|
172
|
+
}).catch((error) => {
|
|
173
|
+
this.inflightByKey.delete(key);
|
|
174
|
+
throw error;
|
|
175
|
+
});
|
|
176
|
+
this.inflightByKey.set(key, promise);
|
|
177
|
+
return promise;
|
|
178
|
+
}
|
|
179
|
+
scheduleWarmup(entries, load) {
|
|
180
|
+
let scheduled = 0;
|
|
181
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
182
|
+
for (const entry of entries) {
|
|
183
|
+
if (entry.kind !== "file" || scheduled >= openWithWarmupLimit) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const key = resolveWorkspaceFileOpenWithCacheKey(entry);
|
|
187
|
+
if (seenKeys.has(key) || this.applicationsByKey.has(key) || this.inflightByKey.has(key) || this.warmupScheduledKeys.has(key)) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
seenKeys.add(key);
|
|
191
|
+
this.warmupScheduledKeys.add(key);
|
|
192
|
+
scheduled += 1;
|
|
193
|
+
void load(entry).finally(() => {
|
|
194
|
+
this.warmupScheduledKeys.delete(key);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// src/services/internal/workspaceFileManagerStore.ts
|
|
201
|
+
import { proxy } from "valtio";
|
|
202
|
+
|
|
203
|
+
// src/services/internal/model/fileKinds.ts
|
|
204
|
+
import { resolveWorkspaceFileActivationTarget as resolveSharedWorkspaceFileActivationTarget } from "@tutti-os/workspace-file-preview";
|
|
205
|
+
function resolveWorkspaceFileActivationTarget(entry) {
|
|
206
|
+
const target = resolveSharedWorkspaceFileActivationTarget(entry);
|
|
207
|
+
if (!target) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
fileKind: target.fileKind,
|
|
212
|
+
mtimeMs: target.mtimeMs ?? null,
|
|
213
|
+
name: target.name,
|
|
214
|
+
path: target.path,
|
|
215
|
+
sizeBytes: target.sizeBytes ?? null
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// src/services/internal/model/formatters.ts
|
|
220
|
+
import { formatTuttiShortDateTime } from "@tutti-os/ui-system/date-format";
|
|
221
|
+
function formatWorkspaceFileBytes(sizeBytes) {
|
|
222
|
+
if (sizeBytes === null || !Number.isFinite(sizeBytes)) {
|
|
223
|
+
return "--";
|
|
224
|
+
}
|
|
225
|
+
if (sizeBytes < 1024) {
|
|
226
|
+
return `${sizeBytes} B`;
|
|
227
|
+
}
|
|
228
|
+
const units = ["KB", "MB", "GB", "TB"];
|
|
229
|
+
let value = sizeBytes / 1024;
|
|
230
|
+
let unitIndex = 0;
|
|
231
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
232
|
+
value /= 1024;
|
|
233
|
+
unitIndex += 1;
|
|
234
|
+
}
|
|
235
|
+
return `${value >= 10 ? value.toFixed(1) : value.toFixed(2)} ${units[unitIndex]}`;
|
|
236
|
+
}
|
|
237
|
+
function formatWorkspaceFileModifiedTime(mtimeMs, locale) {
|
|
238
|
+
if (mtimeMs === null || !Number.isFinite(mtimeMs) || mtimeMs <= 0) {
|
|
239
|
+
return "--";
|
|
240
|
+
}
|
|
241
|
+
return formatTuttiShortDateTime(mtimeMs, locale);
|
|
242
|
+
}
|
|
243
|
+
function splitWorkspaceFileName(name) {
|
|
244
|
+
const extensionIndex = name.lastIndexOf(".");
|
|
245
|
+
const hasExtension = extensionIndex > 0 && extensionIndex < name.length - 1;
|
|
246
|
+
if (hasExtension) {
|
|
247
|
+
return {
|
|
248
|
+
end: name.slice(extensionIndex),
|
|
249
|
+
start: name.slice(0, extensionIndex)
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
if (name.length <= 24) {
|
|
253
|
+
return { end: "", start: name };
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
end: name.slice(-10),
|
|
257
|
+
start: name.slice(0, -10)
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// src/services/internal/model/searchEntries.ts
|
|
262
|
+
function workspaceFileSearchEntryToEntry(entry) {
|
|
263
|
+
return {
|
|
264
|
+
hasChildren: entry.kind === "directory",
|
|
265
|
+
kind: entry.kind,
|
|
266
|
+
mtimeMs: null,
|
|
267
|
+
name: entry.name,
|
|
268
|
+
path: entry.path,
|
|
269
|
+
sizeBytes: null
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/services/internal/model/validation.ts
|
|
274
|
+
function validateWorkspaceFileEntryName(name) {
|
|
275
|
+
const trimmed = name.trim();
|
|
276
|
+
if (!trimmed) {
|
|
277
|
+
return "required";
|
|
278
|
+
}
|
|
279
|
+
if (trimmed.includes("/") || trimmed.includes("\\") || trimmed === "." || trimmed === "..") {
|
|
280
|
+
return "invalid";
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
|
|
269
285
|
// src/services/internal/workspaceFileManagerStore.ts
|
|
270
286
|
function createWorkspaceFileManagerStore(input) {
|
|
271
287
|
const persistedState = normalizeWorkspaceFileManagerPersistedState(
|
|
@@ -866,154 +882,102 @@ var WorkspaceFileManagerNavigationController = class {
|
|
|
866
882
|
};
|
|
867
883
|
|
|
868
884
|
// src/services/internal/workspaceFileManagerPreviewController.ts
|
|
885
|
+
import {
|
|
886
|
+
createWorkspaceFilePreviewController,
|
|
887
|
+
formatWorkspacePreviewByteLimit,
|
|
888
|
+
workspaceFilePreviewMaxBytes
|
|
889
|
+
} from "@tutti-os/workspace-file-preview";
|
|
869
890
|
var WorkspaceFileManagerPreviewController = class {
|
|
870
891
|
copy;
|
|
871
|
-
host;
|
|
872
|
-
isDisposed;
|
|
873
892
|
resolveErrorMessage;
|
|
874
893
|
store;
|
|
875
|
-
|
|
876
|
-
|
|
894
|
+
previewController;
|
|
895
|
+
unsubscribePreview;
|
|
877
896
|
constructor(input) {
|
|
878
897
|
this.copy = input.copy;
|
|
879
|
-
this.host = input.host;
|
|
880
|
-
this.isDisposed = input.isDisposed;
|
|
881
898
|
this.resolveErrorMessage = input.resolveErrorMessage;
|
|
882
899
|
this.store = input.store;
|
|
900
|
+
this.previewController = createWorkspaceFilePreviewController({
|
|
901
|
+
read: input.host.readPreviewFile ? ({ entry }) => input.host.readPreviewFile(input.store.workspaceID, entry.path) : void 0,
|
|
902
|
+
toPreviewEntry: (entry) => entry
|
|
903
|
+
});
|
|
904
|
+
this.unsubscribePreview = this.previewController.subscribe(() => {
|
|
905
|
+
this.applyPreviewState(this.previewController.getSnapshot());
|
|
906
|
+
});
|
|
883
907
|
}
|
|
884
908
|
dispose() {
|
|
885
|
-
this.
|
|
886
|
-
this.
|
|
909
|
+
this.unsubscribePreview();
|
|
910
|
+
this.previewController.dispose();
|
|
887
911
|
}
|
|
888
912
|
async syncPreviewState() {
|
|
889
|
-
const requestID = this.previewRequestSeq + 1;
|
|
890
|
-
this.previewRequestSeq = requestID;
|
|
891
|
-
this.revokePreviewObjectUrl();
|
|
892
913
|
const selectedEntry = findWorkspaceFileEntry(
|
|
893
914
|
this.store,
|
|
894
915
|
this.store.selectedPath
|
|
895
916
|
);
|
|
917
|
+
const settled = this.previewController.setEntry(selectedEntry);
|
|
918
|
+
await settled;
|
|
919
|
+
this.applyPreviewState(this.previewController.getSnapshot());
|
|
920
|
+
}
|
|
921
|
+
applyPreviewState(state) {
|
|
896
922
|
const copy = this.copy();
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
}
|
|
901
|
-
const readiness = resolveWorkspaceFilePreviewReadiness(selectedEntry);
|
|
902
|
-
if (readiness.status === "directory") {
|
|
903
|
-
this.store.previewState = {
|
|
904
|
-
entry: selectedEntry,
|
|
905
|
-
status: "directory"
|
|
906
|
-
};
|
|
907
|
-
return;
|
|
908
|
-
}
|
|
909
|
-
if (readiness.status === "unsupported") {
|
|
910
|
-
this.store.previewState = {
|
|
911
|
-
entry: selectedEntry,
|
|
912
|
-
message: copy.t("previewUnsupported"),
|
|
913
|
-
status: "unsupported"
|
|
914
|
-
};
|
|
915
|
-
return;
|
|
916
|
-
}
|
|
917
|
-
if (readiness.status === "readonly") {
|
|
918
|
-
this.store.previewState = {
|
|
919
|
-
entry: selectedEntry,
|
|
920
|
-
message: resolveWorkspaceFileManagerPreviewReadonlyMessage(
|
|
921
|
-
copy,
|
|
922
|
-
readiness.reason,
|
|
923
|
-
readiness.maxSizeBytes
|
|
924
|
-
),
|
|
925
|
-
status: "readonly"
|
|
926
|
-
};
|
|
927
|
-
return;
|
|
928
|
-
}
|
|
929
|
-
const activationTarget = readiness.target;
|
|
930
|
-
this.store.previewState = {
|
|
931
|
-
entry: activationTarget,
|
|
932
|
-
status: "loading"
|
|
933
|
-
};
|
|
934
|
-
if (!this.host.readPreviewFile) {
|
|
935
|
-
this.store.previewState = {
|
|
936
|
-
entry: selectedEntry,
|
|
937
|
-
message: copy.t("previewUnsupported"),
|
|
938
|
-
status: "unsupported"
|
|
939
|
-
};
|
|
940
|
-
return;
|
|
941
|
-
}
|
|
942
|
-
try {
|
|
943
|
-
const bytes = normalizeWorkspaceFilePreviewBytes(
|
|
944
|
-
await this.host.readPreviewFile(
|
|
945
|
-
this.store.workspaceID,
|
|
946
|
-
selectedEntry.path
|
|
947
|
-
)
|
|
948
|
-
);
|
|
949
|
-
if (this.isDisposed() || requestID !== this.previewRequestSeq) {
|
|
923
|
+
switch (state.status) {
|
|
924
|
+
case "empty":
|
|
925
|
+
this.store.previewState = state;
|
|
950
926
|
return;
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
927
|
+
case "directory":
|
|
928
|
+
this.store.previewState = state;
|
|
929
|
+
return;
|
|
930
|
+
case "loading":
|
|
931
|
+
case "text":
|
|
932
|
+
case "image":
|
|
933
|
+
case "video": {
|
|
934
|
+
const target = resolveWorkspaceFileActivationTarget(state.entry);
|
|
935
|
+
if (!target) {
|
|
936
|
+
this.store.previewState = {
|
|
937
|
+
entry: state.entry,
|
|
938
|
+
message: copy.t("previewUnsupported"),
|
|
939
|
+
status: "unsupported"
|
|
940
|
+
};
|
|
965
941
|
return;
|
|
966
942
|
}
|
|
967
|
-
this.
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
status: loadedState.status
|
|
943
|
+
this.store.previewState = state.status === "loading" ? { entry: target, status: "loading" } : state.status === "text" ? { content: state.content, entry: target, status: "text" } : {
|
|
944
|
+
entry: target,
|
|
945
|
+
objectUrl: state.objectUrl,
|
|
946
|
+
status: state.status
|
|
972
947
|
};
|
|
973
948
|
return;
|
|
974
949
|
}
|
|
975
|
-
|
|
976
|
-
this.store.previewState = loadedState;
|
|
977
|
-
return;
|
|
978
|
-
}
|
|
979
|
-
if (loadedState.status === "html") {
|
|
980
|
-
this.store.previewState = loadedState;
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
983
|
-
if (loadedState.status === "readonly") {
|
|
950
|
+
case "readonly":
|
|
984
951
|
this.store.previewState = {
|
|
985
|
-
entry:
|
|
952
|
+
entry: state.entry,
|
|
986
953
|
message: resolveWorkspaceFileManagerPreviewReadonlyMessage(
|
|
987
954
|
copy,
|
|
988
|
-
|
|
989
|
-
|
|
955
|
+
state.reason,
|
|
956
|
+
state.maxSizeBytes
|
|
990
957
|
),
|
|
991
958
|
status: "readonly"
|
|
992
959
|
};
|
|
993
|
-
}
|
|
994
|
-
} catch (error) {
|
|
995
|
-
if (this.isDisposed() || requestID !== this.previewRequestSeq) {
|
|
996
960
|
return;
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
961
|
+
case "unsupported":
|
|
962
|
+
this.store.previewState = {
|
|
963
|
+
entry: state.entry,
|
|
964
|
+
message: copy.t("previewUnsupported"),
|
|
965
|
+
status: "unsupported"
|
|
966
|
+
};
|
|
967
|
+
return;
|
|
968
|
+
case "error":
|
|
969
|
+
this.store.previewState = {
|
|
970
|
+
entry: state.entry,
|
|
971
|
+
message: this.resolveErrorMessage(state.error, {
|
|
972
|
+
preview_file_too_large: copy.t("previewFileTooLarge", {
|
|
973
|
+
maxSize: formatWorkspacePreviewByteLimit(
|
|
974
|
+
workspaceFilePreviewMaxBytes
|
|
975
|
+
)
|
|
976
|
+
})
|
|
977
|
+
}),
|
|
978
|
+
status: "error"
|
|
979
|
+
};
|
|
1014
980
|
}
|
|
1015
|
-
URL.revokeObjectURL(this.previewObjectUrl);
|
|
1016
|
-
this.previewObjectUrl = null;
|
|
1017
981
|
}
|
|
1018
982
|
};
|
|
1019
983
|
function resolveWorkspaceFileManagerPreviewReadonlyMessage(copy, reason, maxSizeBytes) {
|
|
@@ -1241,63 +1205,6 @@ var WorkspaceFileManagerTreeController = class {
|
|
|
1241
1205
|
}
|
|
1242
1206
|
};
|
|
1243
1207
|
|
|
1244
|
-
// src/services/internal/model/openWithApplicationsCache.ts
|
|
1245
|
-
import { resolveWorkspaceFileExtension as resolveWorkspaceFileExtension2 } from "@tutti-os/workspace-file-preview";
|
|
1246
|
-
var openWithWarmupLimit = 8;
|
|
1247
|
-
function resolveWorkspaceFileOpenWithCacheKey(entry) {
|
|
1248
|
-
const extension = resolveWorkspaceFileExtension2(
|
|
1249
|
-
entry.path || entry.name || ""
|
|
1250
|
-
);
|
|
1251
|
-
return `${entry.kind}:${extension || "(no-ext)"}`;
|
|
1252
|
-
}
|
|
1253
|
-
var WorkspaceFileOpenWithApplicationsCache = class {
|
|
1254
|
-
applicationsByKey = /* @__PURE__ */ new Map();
|
|
1255
|
-
inflightByKey = /* @__PURE__ */ new Map();
|
|
1256
|
-
warmupScheduledKeys = /* @__PURE__ */ new Set();
|
|
1257
|
-
get(key) {
|
|
1258
|
-
return this.applicationsByKey.get(key) ?? null;
|
|
1259
|
-
}
|
|
1260
|
-
async resolve(key, load) {
|
|
1261
|
-
const cached = this.applicationsByKey.get(key);
|
|
1262
|
-
if (cached) {
|
|
1263
|
-
return cached;
|
|
1264
|
-
}
|
|
1265
|
-
const inflight = this.inflightByKey.get(key);
|
|
1266
|
-
if (inflight) {
|
|
1267
|
-
return inflight;
|
|
1268
|
-
}
|
|
1269
|
-
const promise = load().then((applications) => {
|
|
1270
|
-
this.applicationsByKey.set(key, applications);
|
|
1271
|
-
this.inflightByKey.delete(key);
|
|
1272
|
-
return applications;
|
|
1273
|
-
}).catch((error) => {
|
|
1274
|
-
this.inflightByKey.delete(key);
|
|
1275
|
-
throw error;
|
|
1276
|
-
});
|
|
1277
|
-
this.inflightByKey.set(key, promise);
|
|
1278
|
-
return promise;
|
|
1279
|
-
}
|
|
1280
|
-
scheduleWarmup(entries, load) {
|
|
1281
|
-
let scheduled = 0;
|
|
1282
|
-
const seenKeys = /* @__PURE__ */ new Set();
|
|
1283
|
-
for (const entry of entries) {
|
|
1284
|
-
if (entry.kind !== "file" || scheduled >= openWithWarmupLimit) {
|
|
1285
|
-
continue;
|
|
1286
|
-
}
|
|
1287
|
-
const key = resolveWorkspaceFileOpenWithCacheKey(entry);
|
|
1288
|
-
if (seenKeys.has(key) || this.applicationsByKey.has(key) || this.inflightByKey.has(key) || this.warmupScheduledKeys.has(key)) {
|
|
1289
|
-
continue;
|
|
1290
|
-
}
|
|
1291
|
-
seenKeys.add(key);
|
|
1292
|
-
this.warmupScheduledKeys.add(key);
|
|
1293
|
-
scheduled += 1;
|
|
1294
|
-
void load(entry).finally(() => {
|
|
1295
|
-
this.warmupScheduledKeys.delete(key);
|
|
1296
|
-
});
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
};
|
|
1300
|
-
|
|
1301
1208
|
// src/services/internal/workspaceFileManagerSession.ts
|
|
1302
1209
|
var DefaultWorkspaceFileManagerSession = class {
|
|
1303
1210
|
store;
|
|
@@ -1358,7 +1265,6 @@ var DefaultWorkspaceFileManagerSession = class {
|
|
|
1358
1265
|
this.previewController = new WorkspaceFileManagerPreviewController({
|
|
1359
1266
|
copy: () => this.copy,
|
|
1360
1267
|
host: input.host,
|
|
1361
|
-
isDisposed: () => this.isDisposed,
|
|
1362
1268
|
resolveErrorMessage: (error, overrides) => this.resolveErrorMessage(error, overrides),
|
|
1363
1269
|
store: this.store
|
|
1364
1270
|
});
|
|
@@ -2284,6 +2190,11 @@ function createWorkspaceFileManagerService() {
|
|
|
2284
2190
|
}
|
|
2285
2191
|
|
|
2286
2192
|
// src/services/workspaceFileEntryIconPolicy.ts
|
|
2193
|
+
import {
|
|
2194
|
+
classifyWorkspaceFilePreviewKind,
|
|
2195
|
+
resolveWorkspaceFileExtension as resolveWorkspaceFileExtension2,
|
|
2196
|
+
resolveWorkspaceFileVisualKind
|
|
2197
|
+
} from "@tutti-os/workspace-file-preview";
|
|
2287
2198
|
var defaultApplicationIconExtensions = /* @__PURE__ */ new Set([
|
|
2288
2199
|
"ai",
|
|
2289
2200
|
"dmg",
|
|
@@ -2326,12 +2237,12 @@ function shouldUseWorkspaceFileExtensionDocumentIcon(entry) {
|
|
|
2326
2237
|
return false;
|
|
2327
2238
|
}
|
|
2328
2239
|
const visualKind = resolveWorkspaceFileVisualKind(entry);
|
|
2329
|
-
const extension =
|
|
2240
|
+
const extension = resolveWorkspaceFileExtension2(entry.name).toLowerCase();
|
|
2330
2241
|
return visualKind === "code" || visualKind === "markdown" || extensionDocumentIconExtensions.has(extension) || classifyWorkspaceFilePreviewKind(entry) === "text";
|
|
2331
2242
|
}
|
|
2332
2243
|
function shouldUseWorkspaceFileArchiveIcon(entry) {
|
|
2333
2244
|
return entry.kind === "file" && archiveIconExtensions.has(
|
|
2334
|
-
|
|
2245
|
+
resolveWorkspaceFileExtension2(entry.name).toLowerCase()
|
|
2335
2246
|
);
|
|
2336
2247
|
}
|
|
2337
2248
|
function isWorkspaceApplicationBundle(entry) {
|
|
@@ -2341,7 +2252,7 @@ function resolveWorkspaceFileDefaultApplicationIconExtension(entry) {
|
|
|
2341
2252
|
if (entry.kind !== "file") {
|
|
2342
2253
|
return null;
|
|
2343
2254
|
}
|
|
2344
|
-
const extension =
|
|
2255
|
+
const extension = resolveWorkspaceFileExtension2(entry.name).toLowerCase();
|
|
2345
2256
|
return defaultApplicationIconExtensions.has(extension) ? extension : null;
|
|
2346
2257
|
}
|
|
2347
2258
|
function resolveWorkspaceFileEntryIconCacheKey(entry) {
|
|
@@ -2362,6 +2273,10 @@ function shouldResolveWorkspaceFileImageThumbnail(entry) {
|
|
|
2362
2273
|
}
|
|
2363
2274
|
|
|
2364
2275
|
// src/ui/workspaceFileManagerArrangeMode.ts
|
|
2276
|
+
import {
|
|
2277
|
+
resolveWorkspaceFileExtension as resolveWorkspaceFileExtension3,
|
|
2278
|
+
resolveWorkspaceFileVisualKind as resolveWorkspaceFileVisualKind2
|
|
2279
|
+
} from "@tutti-os/workspace-file-preview";
|
|
2365
2280
|
var workspaceFileManagerArrangeModeStorageKey = "tutti.workspace-file-manager.arrange-mode";
|
|
2366
2281
|
var workspaceFileManagerArrangeModes = /* @__PURE__ */ new Set([
|
|
2367
2282
|
"none",
|
|
@@ -2464,7 +2379,7 @@ function resolveEntryKindGroup(entry) {
|
|
|
2464
2379
|
if (entry.kind === "directory") {
|
|
2465
2380
|
return "directory";
|
|
2466
2381
|
}
|
|
2467
|
-
return
|
|
2382
|
+
return resolveWorkspaceFileVisualKind2(entry);
|
|
2468
2383
|
}
|
|
2469
2384
|
function resolveEntryApplicationGroup(entry) {
|
|
2470
2385
|
if (entry.kind === "directory") {
|
|
@@ -2473,22 +2388,11 @@ function resolveEntryApplicationGroup(entry) {
|
|
|
2473
2388
|
if (entry.name.trim().toLowerCase().endsWith(".app")) {
|
|
2474
2389
|
return "application";
|
|
2475
2390
|
}
|
|
2476
|
-
return
|
|
2391
|
+
return resolveWorkspaceFileExtension3(entry.name) || resolveEntryKindGroup(entry);
|
|
2477
2392
|
}
|
|
2478
2393
|
|
|
2479
2394
|
export {
|
|
2480
|
-
classifyWorkspaceFilePreviewKind,
|
|
2481
2395
|
resolveWorkspaceFileActivationTarget,
|
|
2482
|
-
decodeWorkspaceTextFile,
|
|
2483
|
-
isWorkspaceFileBrowserOpenable,
|
|
2484
|
-
isWorkspaceTextFileTooLarge,
|
|
2485
|
-
looksLikeBinaryText,
|
|
2486
|
-
resolveWorkspaceFileExtension,
|
|
2487
|
-
resolveWorkspaceFileVisualKind,
|
|
2488
|
-
resolveWorkspaceImageMimeType,
|
|
2489
|
-
resolveWorkspaceVideoMimeType,
|
|
2490
|
-
workspaceFilePreviewMaxBytes,
|
|
2491
|
-
workspaceFileTextMaxBytes,
|
|
2492
2396
|
formatWorkspaceFileBytes,
|
|
2493
2397
|
formatWorkspaceFileModifiedTime,
|
|
2494
2398
|
splitWorkspaceFileName,
|
|
@@ -2516,4 +2420,4 @@ export {
|
|
|
2516
2420
|
sortWorkspaceFileEntriesForArrangeMode,
|
|
2517
2421
|
resolveWorkspaceFileEntryArrangeDateMs
|
|
2518
2422
|
};
|
|
2519
|
-
//# sourceMappingURL=chunk-
|
|
2423
|
+
//# sourceMappingURL=chunk-3CYSESCR.js.map
|