feat(hotkeys): Migrate hotkeys to customization service and fix issues with overrides (#4777)
This commit is contained in:
1 parent
4559d39a91
commit
3e6913b097
39 files changed
+814
-1552
No files matched your search
@@ -13,62 +13,39 @@ Tours allow you to provide step-by-step guidance to users, explaining different
|
||||
|
||||
### Adding a Tour to your Configuration
|
||||
|
||||
Here’s an example of adding a tour to your configuration file:
|
||||
Here's how you can add a tour to your configuration file:
|
||||
|
||||
```javascript
|
||||
window.config = {
|
||||
tours: [
|
||||
{
|
||||
id: 'basicViewerTour',
|
||||
route: '/viewer',
|
||||
steps: [
|
||||
customizationService: {
|
||||
'ohif.tours': {
|
||||
$set: [
|
||||
{
|
||||
id: 'scroll',
|
||||
title: 'Scrolling Through Images',
|
||||
text: 'You can scroll through the images using the mouse wheel or scrollbar.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'top',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_WHEEL',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'zoom',
|
||||
title: 'Zooming In and Out',
|
||||
text: 'You can zoom the images using the right click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
},
|
||||
// Add more steps as needed
|
||||
],
|
||||
tourOptions: {
|
||||
useModalOverlay: true,
|
||||
defaultStepOptions: {
|
||||
buttons: [
|
||||
id: 'basicViewerTour',
|
||||
route: '/viewer',
|
||||
steps: [
|
||||
{
|
||||
text: 'Skip all',
|
||||
action() {
|
||||
this.complete();
|
||||
id: 'zoom',
|
||||
title: 'Zooming In and Out',
|
||||
text: 'You can zoom the images using the right click.',
|
||||
attachTo: {
|
||||
element: '.viewport-element',
|
||||
on: 'left',
|
||||
},
|
||||
advanceOn: {
|
||||
selector: '.cornerstone-viewport-element',
|
||||
event: 'CORNERSTONE_TOOLS_MOUSE_UP',
|
||||
},
|
||||
secondary: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
## Explanation of Parameters
|
||||
|
||||
### `tours` Array
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: Hotkeys
|
||||
---
|
||||
|
||||
|
||||
## Key Changes:
|
||||
|
||||
* Hotkeys are no longer defined in mode factory via `hotkeys: [...hotkeys.defaults.hotkeyBindings]`
|
||||
* Hotkeys are now managed through the `customizationService` under the key `ohif.hotkeyBindings`
|
||||
* Default hotkeys are set automatically and can be customized using the customization service
|
||||
* User-defined hotkey preferences are now stored in a new format in localStorage
|
||||
* The `HotkeysManager` has undergone significant updates including better handling of defaults, key persistence, and cleanup
|
||||
|
||||
## Migration Steps:
|
||||
|
||||
### 1. Remove hotkeys array from mode factory definition
|
||||
|
||||
**Before:**
|
||||
```diff
|
||||
- function modeFactory({ modeConfiguration }) {
|
||||
- return {
|
||||
- id: 'basic',
|
||||
- // ... other configuration
|
||||
- hotkeys: [...hotkeys.defaults.hotkeyBindings],
|
||||
- };
|
||||
- }
|
||||
```
|
||||
|
||||
**After:**
|
||||
```diff
|
||||
+ function modeFactory({ modeConfiguration }) {
|
||||
+ return {
|
||||
+ id: 'basic',
|
||||
+ // ... other configuration
|
||||
+ // No hotkeys array necessary
|
||||
+ };
|
||||
+ }
|
||||
```
|
||||
|
||||
|
||||
### 2. Set custom hotkeys using the customization service
|
||||
|
||||
There are several methods to modify hotkeys using the customization service:
|
||||
|
||||
#### a. Completely replace all hotkeys using `$set`:
|
||||
|
||||
```diff
|
||||
+ onModeEnter: function ({ servicesManager }) {
|
||||
+ const { customizationService } = servicesManager.services;
|
||||
+ customizationService.setCustomizations({
|
||||
+ 'ohif.hotkeyBindings': {
|
||||
+ $set: [
|
||||
+ {
|
||||
+ commandName: 'setToolActive',
|
||||
+ commandOptions: { toolName: 'Zoom' },
|
||||
+ label: 'Zoom',
|
||||
+ keys: ['z'],
|
||||
+ isEditable: true,
|
||||
+ },
|
||||
+ ],
|
||||
+ },
|
||||
+ });
|
||||
```
|
||||
|
||||
#### b. Add new hotkeys using `$push`:
|
||||
|
||||
```diff
|
||||
+ onModeEnter: function ({ servicesManager }) {
|
||||
+ const { customizationService } = servicesManager.services;
|
||||
+ customizationService.setCustomizations({
|
||||
+ 'ohif.hotkeyBindings': {
|
||||
+ $push: [
|
||||
+ {
|
||||
+ commandName: 'myCustomCommand',
|
||||
+ label: 'My Custom Function',
|
||||
+ keys: ['ctrl+m'],
|
||||
+ isEditable: true,
|
||||
+ },
|
||||
+ ],
|
||||
+ },
|
||||
+ });
|
||||
+}
|
||||
```
|
||||
|
||||
### 4. Update configuration file if you were setting window.config.hotkeys
|
||||
|
||||
If you were previously defining hotkeys in your window.config.js file, it was not really
|
||||
taken into account. So you can safely remove it now.
|
||||
|
||||
**Before:**
|
||||
```diff
|
||||
- window.config = {
|
||||
- // ...other config
|
||||
- hotkeys: [
|
||||
- {
|
||||
- commandName: 'incrementActiveViewport',
|
||||
- label: 'Next Viewport',
|
||||
- keys: ['right'],
|
||||
- },
|
||||
- // ...more hotkeys
|
||||
- ],
|
||||
- };
|
||||
```
|
||||
|
||||
**After:**
|
||||
```diff
|
||||
+ window.config = {
|
||||
+ // ...other config
|
||||
+ };
|
||||
```
|
||||
|
||||
### 5. Be aware that user preferences are now handled differently
|
||||
|
||||
The new system automatically handles user-preferred hotkey mappings:
|
||||
|
||||
- User hotkey preferences are stored in `localStorage` under the key `user-preferred-keys`
|
||||
- The format is a hash-based mapping rather than a full array of definitions
|
||||
- There's a migration utility that converts old preferences to the new format
|
||||
- You don't need to manually handle this, but be aware of it if you're accessing localStorage directly
|
||||
|
||||
|
||||
## Benefits of the Change
|
||||
|
||||
1. **Consistent API**: Hotkeys now follow the same customization pattern as other OHIF features
|
||||
2. **More flexible**: Easier to modify specific hotkeys without replacing the entire set
|
||||
3. **Better user preferences**: User customizations are better preserved and migrated
|
||||
4. **Runtime updates**: Hotkeys can be modified at runtime through the customization service
|
||||
5. **Improved cleanup**: Better lifecycle management of hotkey bindings
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: Tours and Onboarding
|
||||
---
|
||||
|
||||
## Migration Guide: Tours
|
||||
|
||||
* Tours are no longer defined directly in `window.config.tours` but through the customization service under the key `ohif.tours`
|
||||
* The `waitForElement` utility function has been moved from the config file to a dedicated customization file
|
||||
* The structure of tour definitions (steps, options, etc.) remains largely the same
|
||||
|
||||
## Migration Steps:
|
||||
|
||||
|
||||
|
||||
### 1. Update any direct references to window.config.tours
|
||||
|
||||
If you have any code that directly references window.config.tours, update it to use the customization service:
|
||||
|
||||
```diff
|
||||
- const tours = window.config.tours;
|
||||
+ const tours = customizationService.getCustomization('ohif.tours');
|
||||
```
|
||||
|
||||
### 2. Use config update patterns for configuring tours
|
||||
|
||||
**Before:**
|
||||
```diff
|
||||
- window.config = {
|
||||
- tours: [
|
||||
- {
|
||||
- id: 'basicViewerTour',
|
||||
- route: '/viewer',
|
||||
- steps: [
|
||||
- // tour steps...
|
||||
- ],
|
||||
- tourOptions: {
|
||||
- // tour options...
|
||||
- },
|
||||
- },
|
||||
- ],
|
||||
- };
|
||||
```
|
||||
|
||||
**After:**
|
||||
```javascript
|
||||
window.config = {
|
||||
customizationService: {
|
||||
'ohif.tours': {
|
||||
$set: [
|
||||
{
|
||||
id: 'basicViewerTour',
|
||||
route: '/viewer',
|
||||
steps: [
|
||||
// Your tour steps
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
## Benefits of the Change
|
||||
|
||||
4. **Mode-specific Tours**: now you can have different tours for different modes
|
||||
@@ -74,6 +74,7 @@ export default [
|
||||
```
|
||||
|
||||
|
||||
## Behind the Scene
|
||||
When you `setHotkeys`, the `commandName` gets registered with the `commandsManager` and
|
||||
get run after the key is pressed.
|
||||
### Global vs Mode specific hotkeys
|
||||
|
||||
You can can set the global hotkeys and override them using the `$set` method
|
||||
in the customization service.
|
||||
@@ -148,6 +148,46 @@ window.config = {
|
||||
];
|
||||
|
||||
export const customizations = [
|
||||
{
|
||||
id: 'ohif.hotkeyBindings',
|
||||
description: 'Defines the hotkeys for the application.',
|
||||
default: 'look at hotkeyBindingsCustomization.ts file',
|
||||
configuration: `
|
||||
window.config = {
|
||||
// rest of window config
|
||||
customizationService: [
|
||||
{
|
||||
// this will override the default hotkeys and only have one hotkey
|
||||
'ohif.hotkeyBindings': {
|
||||
$set: [
|
||||
{
|
||||
commandName: 'scaleDownViewport',
|
||||
label: 'Zoom Out',
|
||||
keys: ['-'],
|
||||
isEditable: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
// or lets say you want to change one key of the default hotkeys to default
|
||||
// something else
|
||||
customizationService: [
|
||||
{
|
||||
// this will override the default hotkeys and only have one hotkey
|
||||
'ohif.hotkeyBindings': {
|
||||
$filter: {
|
||||
match: { commandName: 'scaleDownViewport' },
|
||||
$set: {
|
||||
keys: ['ctrl+shift+-'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
`,
|
||||
},
|
||||
{
|
||||
id: 'measurementLabels',
|
||||
description: 'Labels for measurement tools in the viewer that are automatically asked for.',
|
||||
|
||||
@@ -9,9 +9,27 @@ Throughout the development of the OHIF Viewer, we have participated in various
|
||||
conferences and "hackathons". In this page, we will provide the presentations
|
||||
and other resources that we have provided to the community in the past:
|
||||
|
||||
## 2025
|
||||
|
||||
### Machine Learning in Medical Imaging Consortium (MaLMIC) | January 2025
|
||||
|
||||
We presented two talks at the Machine Learning in Medical Imaging Consortium (MaLMIC) 2025 conference.
|
||||
|
||||
- Advanced Medical Imaging Visualization [Slides](https://docs.google.com/presentation/d/1HZDL-72nNe4BPawDxR3XnSFLB3oLo72RjExc-KHDZfo/edit?usp=sharing)
|
||||
- Introducing Advanced Segmentation Tools in the OHIF Viewer and Cornerstone3D [Slides](https://docs.google.com/presentation/d/146oJ24PPsFZaDPHeFudRF1dmbL42K9yHzQdXXAXdWxk/edit?usp=sharing)
|
||||
|
||||
|
||||
## 2024
|
||||
|
||||
### ITCR Sustainment Session 2024
|
||||
|
||||
Dr. Gordon Harris presented at ITCR sustainment session about the future of OHIF.
|
||||
|
||||
- OHIF Sustainability [Slides](https://docs.google.com/presentation/d/15380mjCzBKBj9PuysCW1Q9ODnyoypJrCDpj3atTtK6I/edit?usp=sharing)
|
||||
|
||||
### ITCR Sustainment Panel 2024
|
||||
|
||||
- Advanced Medical Imaging Visualization [Slides](https://docs.google.com/presentation/d/1alUp9uJpoJs3aAUE0KqrufGo6e6HHvXYmOAdJp-Rlkc/edit?usp=sharing)
|
||||
|
||||
|
||||
### IMNO 2024 - March 19-20, 2024
|
||||
|
||||
Reference in new issue
Block a user