@lingbi/studio 0.8.2 → 0.9.0

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/Application.d.ts CHANGED
@@ -5,6 +5,7 @@ import type { ObjImportResult } from './ObjImportResult';
5
5
  export declare class Application {
6
6
  private archiveImportController;
7
7
  private archiveImporting;
8
+ private archiveImportProgress;
8
9
  private booleanEditConfirmationVisible;
9
10
  private disposed;
10
11
  private downloadController;
@@ -17,6 +18,7 @@ export declare class Application {
17
18
  private editedArchiveResourceContext;
18
19
  private importGeneration;
19
20
  private importPerformanceMode;
21
+ private readonly importProgressCompositor;
20
22
  private inventoryConfirmationController;
21
23
  private inventoryConfirming;
22
24
  private inventoryError;
@@ -88,6 +90,7 @@ export declare class Application {
88
90
  private handleEditRequested;
89
91
  private handleBooleanEditConfirmed;
90
92
  private handleBooleanEditCancelled;
93
+ private handleArchiveImportProgress;
91
94
  private handleRendererWorkspaceStateChanged;
92
95
  private hasValidSceneSource;
93
96
  private mapModelResourceListSource;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Composes the archive extraction segment and the renderer load segment into
3
+ * one integer 0-100 import percentage. URL imports carry renderer progress
4
+ * only; archive imports map extraction onto 0-20 and the renderer pipeline
5
+ * onto 20-100.
6
+ */
7
+ export declare class ImportProgressCompositor {
8
+ compose(input: {
9
+ readonly archiveProgress: number | undefined;
10
+ readonly rendererProgress: number | undefined;
11
+ }): number | undefined;
12
+ private clampPercent;
13
+ }
@@ -16,6 +16,8 @@ export interface StudioToolbarState {
16
16
  readonly editEnabled: boolean;
17
17
  readonly editVisible: boolean;
18
18
  readonly editStatusMessage?: string;
19
+ readonly importInProgress?: boolean;
20
+ readonly importProgress?: number;
19
21
  readonly inventoryEnabled?: boolean;
20
22
  readonly inventoryError?: string;
21
23
  readonly inventoryInProgress?: boolean;
@@ -16,7 +16,12 @@ export declare class StudioWorkspace {
16
16
  private readonly booleanButtonElement;
17
17
  private readonly simulationButtonElement;
18
18
  private readonly booleanOperationOverlayElement;
19
+ private readonly booleanOperationSpinnerElement;
19
20
  private readonly booleanOperationStatusElement;
21
+ private readonly importPercentElement;
22
+ private readonly importProgressElement;
23
+ private readonly importProgressFillElement;
24
+ private readonly importProgressRowElement;
20
25
  private readonly booleanEditConfirmationElement;
21
26
  private readonly bottomToolbarElement;
22
27
  private readonly downloadButtonElement;
@@ -9,14 +9,16 @@ export declare class ArchiveImportWorkerClient implements ArchiveImportWorkerEnd
9
9
  private readonly jobValidator;
10
10
  private lastStartedTaskId;
11
11
  private readonly messageParser;
12
+ private readonly onProgress;
12
13
  private readonly workerFactory;
13
- constructor(workerFactory?: ArchiveImportWorkerFactory);
14
+ constructor(workerFactory?: ArchiveImportWorkerFactory, onProgress?: (percent: number) => void);
14
15
  cancel(taskId?: number): void;
15
16
  dispose(): void;
16
17
  handleWorkerEndpointError(message: string): void;
17
18
  handleWorkerEndpointMessage(message: unknown): void;
18
19
  start(job: ArchiveImportJobRequest): Promise<ArchiveImportResult>;
19
20
  private acceptChunk;
21
+ private handleProgress;
20
22
  private rejectTask;
21
23
  private resolveTask;
22
24
  private toError;
@@ -45,4 +45,10 @@ export interface ArchiveImportErrorMessage {
45
45
  readonly taskId: number;
46
46
  readonly type: 'error';
47
47
  }
48
- export type ArchiveImportOutboundMessage = ArchiveImportCancelledMessage | ArchiveImportCompleteMessage | ArchiveImportEntryChunkMessage | ArchiveImportEntryStartMessage | ArchiveImportErrorMessage;
48
+ export interface ArchiveImportProgressMessage {
49
+ readonly bytesLoaded: number;
50
+ readonly bytesTotal: number;
51
+ readonly taskId: number;
52
+ readonly type: 'progress';
53
+ }
54
+ export type ArchiveImportOutboundMessage = ArchiveImportCancelledMessage | ArchiveImportCompleteMessage | ArchiveImportEntryChunkMessage | ArchiveImportEntryStartMessage | ArchiveImportErrorMessage | ArchiveImportProgressMessage;
@@ -7,6 +7,8 @@ export declare class ArchiveImportWorkerMessageParser {
7
7
  private isFileLike;
8
8
  private isFormat;
9
9
  private isPositiveSafeInteger;
10
+ private isNonNegativeSafeInteger;
11
+ private parseProgress;
10
12
  private isRecord;
11
13
  private parseAcknowledgement;
12
14
  private parseCancellation;
@@ -1,10 +1,12 @@
1
1
  import type { ArchiveImportWorkerPort } from './ArchiveImportWorkerPort';
2
2
  /** Streams a ZIP file through fflate and returns validated role files by chunk. */
3
3
  export declare class ArchiveImportWorkerRuntime {
4
+ private static readonly MIN_PROGRESS_STEP_BYTES;
4
5
  private readonly inputChunkSize;
5
6
  private activeTask;
6
7
  private readonly jobValidator;
7
8
  private latestStartedTaskId;
9
+ private postedProgressBytes;
8
10
  private readonly centralDirectoryValidator;
9
11
  private readonly messageParser;
10
12
  private readonly pathValidator;
@@ -30,6 +32,7 @@ export declare class ArchiveImportWorkerRuntime {
30
32
  private postCancelled;
31
33
  private postComplete;
32
34
  private postError;
35
+ private postProgress;
33
36
  private processInputChunk;
34
37
  private pushToUnzip;
35
38
  private queueEntryChunk;
@@ -1013,6 +1013,8 @@
1013
1013
  return this.parseEntryStart(record, taskId);
1014
1014
  case "error":
1015
1015
  return typeof record["message"] === "string" ? { message: record["message"], taskId, type: "error" } : void 0;
1016
+ case "progress":
1017
+ return this.parseProgress(record, taskId);
1016
1018
  default:
1017
1019
  return void 0;
1018
1020
  }
@@ -1030,6 +1032,17 @@
1030
1032
  isPositiveSafeInteger(value) {
1031
1033
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
1032
1034
  }
1035
+ isNonNegativeSafeInteger(value) {
1036
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
1037
+ }
1038
+ parseProgress(record, taskId) {
1039
+ const bytesLoaded = record["bytesLoaded"];
1040
+ const bytesTotal = record["bytesTotal"];
1041
+ if (!this.isNonNegativeSafeInteger(bytesLoaded) || !this.isNonNegativeSafeInteger(bytesTotal)) {
1042
+ return void 0;
1043
+ }
1044
+ return { bytesLoaded, bytesTotal, taskId, type: "progress" };
1045
+ }
1033
1046
  isRecord(value) {
1034
1047
  return typeof value === "object" && value !== null && !Array.isArray(value);
1035
1048
  }
@@ -1112,10 +1125,12 @@
1112
1125
  }
1113
1126
  }
1114
1127
  class ArchiveImportWorkerRuntime {
1128
+ static MIN_PROGRESS_STEP_BYTES = 256 * 1024;
1115
1129
  inputChunkSize = 64 * 1024;
1116
1130
  activeTask;
1117
1131
  jobValidator = new ArchiveImportJobValidator();
1118
1132
  latestStartedTaskId = 0;
1133
+ postedProgressBytes = 0;
1119
1134
  centralDirectoryValidator = new ArchiveImportCentralDirectoryValidator();
1120
1135
  messageParser = new ArchiveImportWorkerMessageParser();
1121
1136
  pathValidator = new ArchiveImportPathValidator();
@@ -1171,6 +1186,9 @@
1171
1186
  }
1172
1187
  const unzip = this.createUnzip(task);
1173
1188
  const signature = new ArchiveImportSignatureValidator();
1189
+ const bytesTotal = task.request.file.size;
1190
+ let bytesLoaded = 0;
1191
+ this.postedProgressBytes = 0;
1174
1192
  try {
1175
1193
  for (; ; ) {
1176
1194
  this.throwIfCancelled(task);
@@ -1179,6 +1197,8 @@
1179
1197
  break;
1180
1198
  }
1181
1199
  await this.processInputChunk(task, unzip, signature, result.value);
1200
+ bytesLoaded += result.value.byteLength;
1201
+ this.postProgress(task, bytesLoaded, bytesTotal);
1182
1202
  }
1183
1203
  signature.finish();
1184
1204
  this.pushToUnzip(task, unzip, new Uint8Array(0), true);
@@ -1326,6 +1346,22 @@
1326
1346
  type: "error"
1327
1347
  });
1328
1348
  }
1349
+ postProgress(task, bytesLoaded, bytesTotal) {
1350
+ const minStepBytes = Math.max(
1351
+ Math.ceil(bytesTotal / 100),
1352
+ ArchiveImportWorkerRuntime.MIN_PROGRESS_STEP_BYTES
1353
+ );
1354
+ if (bytesLoaded !== bytesTotal && bytesLoaded - this.postedProgressBytes < minStepBytes) {
1355
+ return;
1356
+ }
1357
+ this.postedProgressBytes = bytesLoaded;
1358
+ this.port.postMessage({
1359
+ bytesLoaded,
1360
+ bytesTotal,
1361
+ taskId: task.request.taskId,
1362
+ type: "progress"
1363
+ });
1364
+ }
1329
1365
  async processInputChunk(task, unzip, signature, chunk) {
1330
1366
  for (let offset = 0; offset < chunk.byteLength; offset += this.inputChunkSize) {
1331
1367
  const part = chunk.subarray(offset, offset + this.inputChunkSize);