Co-authored-by: Alireza <ar.sedghi@gmail.com> Co-authored-by: Dan Rukas <dan.rukas@gmail.com> Co-authored-by: Tang Cheng <45505657+tctco@users.noreply.github.com>
This commit is contained in:
44 files changed
+516
-258
No files matched your search
@@ -64,7 +64,7 @@ export const fourUp = {
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
syncGroups: [HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ export const mprAnd3DVolumeViewport = {
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
syncGroups: [HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@ export const only3D = {
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP],
|
||||
syncGroups: [HYDRATE_SEG_SYNC_GROUP],
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
|
||||
@@ -39,6 +39,7 @@ import { useLutPresentationStore } from './stores/useLutPresentationStore';
|
||||
import { usePositionPresentationStore } from './stores/usePositionPresentationStore';
|
||||
import { useSegmentationPresentationStore } from './stores/useSegmentationPresentationStore';
|
||||
import { imageRetrieveMetadataProvider } from '@cornerstonejs/core/utilities';
|
||||
import { initializeWebWorkerProgressHandler } from './utils/initWebWorkerProgressHandler';
|
||||
|
||||
const { registerColormap } = csUtilities.colormap;
|
||||
|
||||
@@ -307,76 +308,6 @@ export default async function init({
|
||||
initializeWebWorkerProgressHandler(servicesManager.services.uiNotificationService);
|
||||
}
|
||||
|
||||
function initializeWebWorkerProgressHandler(uiNotificationService) {
|
||||
// Use a single map to track all active worker tasks
|
||||
const activeWorkerTasks = new Map();
|
||||
|
||||
// Create a normalized task key that doesn't include the random ID
|
||||
// This helps us identify and deduplicate the same type of task
|
||||
const getNormalizedTaskKey = type => {
|
||||
return `worker-task-${type.toLowerCase().replace(/\s+/g, '-')}`;
|
||||
};
|
||||
|
||||
eventTarget.addEventListener(EVENTS.WEB_WORKER_PROGRESS, ({ detail }) => {
|
||||
const { progress, type, id } = detail;
|
||||
|
||||
// Skip notifications for compute statistics
|
||||
if (type === cornerstoneTools.Enums.WorkerTypes.COMPUTE_STATISTICS) {
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedKey = getNormalizedTaskKey(type);
|
||||
|
||||
if (progress === 0) {
|
||||
// Check if we're already tracking a task of this type
|
||||
if (!activeWorkerTasks.has(normalizedKey)) {
|
||||
const progressPromise = new Promise((resolve, reject) => {
|
||||
activeWorkerTasks.set(normalizedKey, {
|
||||
resolve,
|
||||
reject,
|
||||
originalId: id,
|
||||
type,
|
||||
});
|
||||
});
|
||||
|
||||
uiNotificationService.show({
|
||||
id: normalizedKey, // Use the normalized key as ID for better deduplication
|
||||
title: `${type}`,
|
||||
message: `Computing...`,
|
||||
autoClose: false,
|
||||
allowDuplicates: false,
|
||||
deduplicationInterval: 60000, // 60 seconds - prevent frequent notifications of same type
|
||||
promise: progressPromise,
|
||||
promiseMessages: {
|
||||
loading: `Computing...`,
|
||||
success: `Completed successfully`,
|
||||
error: 'Web Worker failed',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// Already tracking this type of task, just let it continue
|
||||
console.debug(`Already tracking a "${type}" task, skipping duplicate notification`);
|
||||
}
|
||||
}
|
||||
// Task completed
|
||||
else if (progress === 100) {
|
||||
// Check if we have this task type in our tracking map
|
||||
const taskData = activeWorkerTasks.get(normalizedKey);
|
||||
|
||||
if (taskData) {
|
||||
// Resolve the promise to update the notification
|
||||
const { resolve } = taskData;
|
||||
resolve({ progress, type });
|
||||
|
||||
// Remove from tracking
|
||||
activeWorkerTasks.delete(normalizedKey);
|
||||
|
||||
console.debug(`Worker task "${type}" completed successfully`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped image load strategy with metadata handling
|
||||
* @param strategyFn - The image loading strategy function to wrap
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import { eventTarget, EVENTS } from '@cornerstonejs/core';
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools';
|
||||
|
||||
/**
|
||||
* Initializes a handler for web worker progress events.
|
||||
* Tracks active worker tasks and shows notifications for their progress.
|
||||
*
|
||||
* @param uiNotificationService - The UI notification service for showing progress notifications
|
||||
*/
|
||||
export function initializeWebWorkerProgressHandler(uiNotificationService: any) {
|
||||
// Use a single map to track all active worker tasks
|
||||
const activeWorkerTasks = new Map();
|
||||
|
||||
// Create a normalized task key that doesn't include the random ID
|
||||
// This helps us identify and deduplicate the same type of task
|
||||
const getNormalizedTaskKey = (type: string) => {
|
||||
return `worker-task-${type.toLowerCase().replace(/\s+/g, '-')}`;
|
||||
};
|
||||
|
||||
eventTarget.addEventListener(EVENTS.WEB_WORKER_PROGRESS, ({ detail }) => {
|
||||
let normalizedKey: string | undefined;
|
||||
let shouldCleanup = false;
|
||||
|
||||
try {
|
||||
const { progress, type, id } = detail;
|
||||
|
||||
// Skip notifications for compute statistics
|
||||
if (type === cornerstoneTools.Enums.WorkerTypes.COMPUTE_STATISTICS) {
|
||||
return;
|
||||
}
|
||||
|
||||
normalizedKey = getNormalizedTaskKey(type);
|
||||
|
||||
if (progress === 0) {
|
||||
// Check if we're already tracking a task of this type
|
||||
if (!activeWorkerTasks.has(normalizedKey)) {
|
||||
const progressPromise = new Promise((resolve, reject) => {
|
||||
try {
|
||||
activeWorkerTasks.set(normalizedKey, {
|
||||
resolve,
|
||||
reject,
|
||||
originalId: id,
|
||||
type,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error setting active worker task for type "${type}":`, error);
|
||||
reject(error);
|
||||
throw error; // Re-throw to trigger outer catch and cleanup
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
uiNotificationService.show({
|
||||
id: normalizedKey, // Use the normalized key as ID for better deduplication
|
||||
title: `${type}`,
|
||||
message: `Computing...`,
|
||||
autoClose: false,
|
||||
allowDuplicates: false,
|
||||
deduplicationInterval: 60000, // 60 seconds - prevent frequent notifications of same type
|
||||
promise: progressPromise,
|
||||
promiseMessages: {
|
||||
loading: `Computing...`,
|
||||
success: `Completed successfully`,
|
||||
error: 'Web Worker failed',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error showing web worker notification for type "${type}":`, error);
|
||||
shouldCleanup = true;
|
||||
throw error;
|
||||
}
|
||||
} else {
|
||||
// Already tracking this type of task, just let it continue
|
||||
console.debug(`Already tracking a "${type}" task, skipping duplicate notification`);
|
||||
}
|
||||
}
|
||||
// Task completed
|
||||
else if (progress === 100) {
|
||||
// Check if we have this task type in our tracking map
|
||||
const taskData = activeWorkerTasks.get(normalizedKey);
|
||||
|
||||
if (taskData) {
|
||||
// Resolve the promise to update the notification
|
||||
const { resolve } = taskData;
|
||||
resolve({ progress, type });
|
||||
|
||||
// Mark for cleanup
|
||||
shouldCleanup = true;
|
||||
|
||||
console.debug(`Worker task "${type}" completed successfully`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error in web worker progress handler for type "${detail?.type}":`, error);
|
||||
shouldCleanup = true;
|
||||
} finally {
|
||||
// Clean up if needed
|
||||
if (shouldCleanup && normalizedKey) {
|
||||
try {
|
||||
activeWorkerTasks.delete(normalizedKey);
|
||||
} catch (cleanupError) {
|
||||
console.error(
|
||||
`Error cleaning up active worker task for type "${detail?.type}":`,
|
||||
cleanupError
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -80,6 +80,7 @@ export default class ContextMenuController {
|
||||
this.services.uiDialogService.hide('context-menu');
|
||||
this.services.uiDialogService.show({
|
||||
id: 'context-menu',
|
||||
showOverlay: false,
|
||||
defaultPosition: ContextMenuController._getDefaultPosition(
|
||||
defaultPointsPosition,
|
||||
event?.detail || event,
|
||||
|
||||
@@ -37,6 +37,8 @@ import * as utils from './utils';
|
||||
import { Toolbox } from './utils';
|
||||
import MoreDropdownMenu from './Components/MoreDropdownMenu';
|
||||
import requestDisplaySetCreationForStudy from './Panels/requestDisplaySetCreationForStudy';
|
||||
import { Toolbar } from './Toolbar/Toolbar';
|
||||
|
||||
const defaultExtension: Types.Extensions.Extension = {
|
||||
/**
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
@@ -103,4 +105,5 @@ export {
|
||||
requestDisplaySetCreationForStudy,
|
||||
callInputDialog,
|
||||
createReportDialogPrompt,
|
||||
Toolbar,
|
||||
};
|
||||
Reference in new issue
Block a user