@tutti-os/workspace-file-manager 0.0.182 → 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 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 owns host-neutral file preview classification,
22
- activation-target shaping, shared view-model derivation, and the host contract
23
- needed to drive those flows so different hosts can integrate primarily by
24
- implementing `WorkspaceFileManagerHost` instead of rebuilding workflow around
25
- the shared UI.
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
- previewObjectUrl = null;
876
- previewRequestSeq = 0;
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.previewRequestSeq += 1;
886
- this.revokePreviewObjectUrl();
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
- if (!selectedEntry) {
898
- this.store.previewState = { status: "empty" };
899
- return;
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
- const loadedState = createWorkspaceFilePreviewLoadedState({
953
- bytes,
954
- entry: selectedEntry,
955
- target: activationTarget
956
- });
957
- if (loadedState.status === "image" || loadedState.status === "video") {
958
- const objectUrl = URL.createObjectURL(
959
- new Blob([loadedState.bytes], {
960
- type: loadedState.contentType
961
- })
962
- );
963
- if (this.isDisposed() || requestID !== this.previewRequestSeq) {
964
- URL.revokeObjectURL(objectUrl);
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.previewObjectUrl = objectUrl;
968
- this.store.previewState = {
969
- entry: activationTarget,
970
- objectUrl,
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
- if (loadedState.status === "text") {
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: selectedEntry,
952
+ entry: state.entry,
986
953
  message: resolveWorkspaceFileManagerPreviewReadonlyMessage(
987
954
  copy,
988
- loadedState.reason,
989
- loadedState.maxSizeBytes
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
- this.store.previewState = {
999
- entry: selectedEntry,
1000
- message: this.resolveErrorMessage(error, {
1001
- preview_file_too_large: copy.t("previewFileTooLarge", {
1002
- maxSize: formatWorkspacePreviewByteLimit(
1003
- workspaceFilePreviewMaxBytes
1004
- )
1005
- })
1006
- }),
1007
- status: "error"
1008
- };
1009
- }
1010
- }
1011
- revokePreviewObjectUrl() {
1012
- if (!this.previewObjectUrl) {
1013
- return;
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 = resolveWorkspaceFileExtension(entry.name).toLowerCase();
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
- resolveWorkspaceFileExtension(entry.name).toLowerCase()
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 = resolveWorkspaceFileExtension(entry.name).toLowerCase();
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 resolveWorkspaceFileVisualKind(entry);
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 resolveWorkspaceFileExtension(entry.name) || resolveEntryKindGroup(entry);
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-KVP3Z2Y5.js.map
2423
+ //# sourceMappingURL=chunk-3CYSESCR.js.map