Skip to content

Commit

Permalink
Merge pull request #1057 from Arnei/update-to-react-18-rendering-pipe…
Browse files Browse the repository at this point in the history
…line

Update to react 18 rendering pipeline
  • Loading branch information
Arnei authored Sep 22, 2023
2 parents 54cb714 + 6c420bd commit 150cac5
Show file tree
Hide file tree
Showing 14 changed files with 381 additions and 479 deletions.
16 changes: 7 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"react-dom": "^18.2.0",
"react-draggable": "^4.4.5",
"react-final-form": "^6.5.9",
"react-hotkeys": "^2.0.0",
"react-hotkeys-hook": "^4.4.1",
"react-i18next": "^13.2.1",
"react-icons": "^4.9.0",
"react-indiana-drag-scroll": "^2.2.0",
Expand Down
20 changes: 0 additions & 20 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/
import parseToml from '@iarna/toml/parse-string';
import deepmerge from 'deepmerge';
import { configure } from 'react-hotkeys';
import { Flavor } from './types';

/**
Expand Down Expand Up @@ -173,25 +172,6 @@ export const init = async () => {
settings.callbackUrl = settings.allowedCallbackPrefixes.some(
p => settings.callbackUrl?.startsWith(p)
) ? settings.callbackUrl : undefined;

// Configure hotkeys
configure({
ignoreTags: [], // Do not ignore hotkeys when focused on a textarea, input, select
ignoreEventsCondition: (e: any) => {
// Ignore hotkeys when focused on a textarea, input, select IF that hotkey is expected to perform
// a certain function in that element that is more important than any hotkey function
// (e.g. you need "Space" in a textarea to create whitespaces, not play/pause videos)
if (e.target && e.target.tagName) {
const tagname = e.target.tagName.toLowerCase()
if ((tagname === "textarea" || tagname === "input" || tagname === "select")
&& (!e.altKey && !e.ctrlKey)
&& (e.code === "Space" || e.code === "ArrowLeft" || e.code === "ArrowRight" || e.code === "ArrowUp" || e.code === "ArrowDown")) {
return true
}
}
return false
},
})
};

/**
Expand Down
226 changes: 83 additions & 143 deletions src/globalKeys.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ApplicationKeyMap, ExtendedKeyMapOptions, KeyMapOptions, MouseTrapKeySequence } from 'react-hotkeys';
/**
* Contains mappings for special keyboard controls, beyond what is usually expected of a webpage
* Learn more about keymaps at https://github.com/greena13/react-hotkeys#defining-key-maps (12.03.2021)
Expand All @@ -8,7 +7,8 @@ import { ApplicationKeyMap, ExtendedKeyMapOptions, KeyMapOptions, MouseTrapKeySe
*
* If you add a new keyMap, be sure to add it to the getAllHotkeys function
*/
import { KeyMap } from "react-hotkeys";
import { match } from '@opencast/appkit';
import { ParseKeys } from 'i18next';
import { isMacOs } from 'react-device-detect';

// Groups for displaying hotkeys in the overview page
Expand All @@ -20,7 +20,7 @@ const groupSubtitleList = "keyboardControls.groupSubtitleList"
/**
* Helper function that rewrites keys based on the OS
*/
const rewriteKeys = (key: string) => {
export const rewriteKeys = (key: string) => {
let newKey = key
if (isMacOs) {
newKey = newKey.replace("Alt", "Option")
Expand All @@ -29,155 +29,95 @@ const rewriteKeys = (key: string) => {
return newKey
}

/**
* (Semi-) global map for video player controls
*/
export const videoPlayerKeyMap: KeyMap = {
preview: {
name: "video.previewButton",
sequence: rewriteKeys("Control+Alt+p"),
action: "keydown",
group: groupVideoPlayer,
},
play: {
name: "keyboardControls.videoPlayButton",
sequence: rewriteKeys("Space"),
sequences: [rewriteKeys("Control+Alt+Space"), "Space"],
action: "keydown",
group: groupVideoPlayer,
},
export const getGroupName = (groupName: string) : ParseKeys => {
return match(groupName, {
videoPlayer: () => groupVideoPlayer,
cutting: () => groupCuttingView,
timeline: () => groupCuttingViewScrubber,
subtitleList: () => groupSubtitleList,
})
}

/**
* (Semi-) global map for the buttons in the cutting view
*/
export const cuttingKeyMap: KeyMap = {
cut: {
name: "cuttingActions.cut-button",
sequence: rewriteKeys("Control+Alt+c"),
action: "keydown",
group: groupCuttingView,
},
delete: {
name: "cuttingActions.delete-button",
sequence: rewriteKeys("Control+Alt+d"),
action: "keydown",
group: groupCuttingView,
},
mergeLeft: {
name: "cuttingActions.mergeLeft-button",
sequence: rewriteKeys("Control+Alt+n"),
action: "keydown",
group: groupCuttingView,
},
mergeRight: {
name: "cuttingActions.mergeRight-button",
sequence: rewriteKeys("Control+Alt+m"),
action: "keydown",
group: groupCuttingView,
},
export interface IKeyMap {
[property: string]: IKeyGroup
}

/**
* (Semi-) global map for moving the scrubber
*/
export const scrubberKeyMap: KeyMap = {
left: {
name: "keyboardControls.scrubberLeft",
// Typescript requires 'sequence' even though there is 'sequences, but it doesn't do anything?
sequence: rewriteKeys("Control+Alt+j"),
sequences: [rewriteKeys("Control+Alt+j"), "Left"],
action: "keydown",
group: groupCuttingViewScrubber,
},
right: {
name: "keyboardControls.scrubberRight",
// Typescript requires 'sequence' even though there is 'sequences, but it doesn't do anything?
sequence: rewriteKeys("Control+Alt+l"),
sequences: [rewriteKeys("Control+Alt+l"), "Right"],
action: "keydown",
group: groupCuttingViewScrubber,
},
increase: {
name: "keyboardControls.scrubberIncrease",
// Typescript requires 'sequence' even though there is 'sequences, but it doesn't do anything?
sequence: rewriteKeys("Control+Alt+i"),
sequences: [rewriteKeys("Control+Alt+i"), "Up"],
action: "keydown",
group: groupCuttingViewScrubber,
},
decrease: {
name: "keyboardControls.scrubberDecrease",
// Typescript requires 'sequence' even though there is 'sequences, but it doesn't do anything?
sequence: rewriteKeys("Control+Alt+k"),
sequences: [rewriteKeys("Control+Alt+k"), "Down"],
action: "keydown",
group: groupCuttingViewScrubber,
},
export interface IKeyGroup {
[property: string]: IKey
}

export const subtitleListKeyMap: KeyMap = {
addAbove: {
name: "subtitleList.addSegmentAbove",
sequence: rewriteKeys("Control+Alt+q"),
action: "keydown",
group: groupSubtitleList,
},
addBelow: {
name: "subtitleList.addSegmentBelow",
sequence: rewriteKeys("Control+Alt+a"),
action: "keydown",
group: groupSubtitleList,
export interface IKey {
name: string
key: string
}

export const KEYMAP: IKeyMap = {
videoPlayer: {
play: {
name: "keyboardControls.videoPlayButton",
key: "Shift+Alt+Space, Space",
},
preview: {
name: "video.previewButton",
key: "Shift+Alt+p",
}
},
jumpAbove: {
name: "subtitleList.jumpToSegmentAbove",
sequence: rewriteKeys("Control+Alt+w"),
action: "keydown",
group: groupSubtitleList,
cutting: {
cut: {
name: "cuttingActions.cut-button",
key: "Shift+Alt+c",
},
delete: {
name: "cuttingActions.delete-button",
key: "Shift+Alt+d",
},
mergeLeft: {
name: "cuttingActions.mergeLeft-button",
key: "Shift+Alt+n",
},
mergeRight: {
name: "cuttingActions.mergeRight-button",
key: "Shift+Alt+m",
},
},
jumpBelow: {
name: "subtitleList.jumpToSegmentBelow",
sequence: rewriteKeys("Control+Alt+s"),
action: "keydown",
group: groupSubtitleList,
timeline: {
left: {
name: "keyboardControls.scrubberLeft",
key: "Shift+Alt+j , Left",
},
right: {
name: "keyboardControls.scrubberRight",
key: "Shift+Alt+l, Right",
},
increase: {
name: "keyboardControls.scrubberIncrease",
key: "Shift+Alt+i, Up",
},
decrease: {
name: "keyboardControls.scrubberDecrease",
key: "Shift+Alt+k, Down",
},
},
delete: {
name: "subtitleList.deleteSegment",
sequence: rewriteKeys("Control+Alt+d"),
action: "keydown",
group: groupSubtitleList,
}
}

/**
* Combines all keyMaps into a single list of keys for KeyboardControls to display
* Placing this under the keyMaps is important, else the translation hooks won't happen
*/
export const getAllHotkeys = () => {
const allKeyMaps = [videoPlayerKeyMap, cuttingKeyMap, scrubberKeyMap, subtitleListKeyMap]
const allKeys : ApplicationKeyMap = {}

for (const keyMap of allKeyMaps) {
for (const [key, value] of Object.entries(keyMap)) {

// Parse sequences
let sequences : KeyMapOptions[] = []
if ((value as ExtendedKeyMapOptions).sequences !== undefined) {
for (const sequence of (value as ExtendedKeyMapOptions).sequences) {
sequences.push({sequence: sequence as MouseTrapKeySequence, action: (value as ExtendedKeyMapOptions).action})
}
} else {
sequences = [{sequence: (value as ExtendedKeyMapOptions).sequence, action: (value as ExtendedKeyMapOptions).action }]
}

// Create new key
allKeys[key] = {
name: (value as ExtendedKeyMapOptions).name,
group: (value as ExtendedKeyMapOptions).group,
sequences: sequences,
}
subtitleList: {
addAbove: {
name: "subtitleList.addSegmentAbove",
key: "Shift+Alt+q",
},
addBelow: {
name: "subtitleList.addSegmentBelow",
key: "Shift+Alt+a",
},
jumpAbove: {
name: "subtitleList.jumpToSegmentAbove",
key: "Shift+Alt+w",
},
jumpBelow: {
name: "subtitleList.jumpToSegmentBelow",
key: "Shift+Alt+s",
},
delete: {
name: "subtitleList.deleteSegment",
key: "Shift+Alt+d",
}
}

return allKeys
}
29 changes: 13 additions & 16 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOMClient from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from 'react-redux'
Expand All @@ -8,15 +8,20 @@ import store from './redux/store'
import { init } from './config'
import { sleep } from './util/utilityFunctions'

import { GlobalHotKeys } from 'react-hotkeys';

import "@fontsource-variable/roboto-flex";

import './i18n/config';

import '@opencast/appkit/dist/colors.css'
import { ColorSchemeProvider } from '@opencast/appkit';

const container = document.getElementById('root')
if (!container) {
throw new Error('Failed to find the root element');
}
const root = ReactDOMClient.createRoot(container);


// Load config here
// Load the rest of the application and try to fetch the settings file from the
// server.
Expand All @@ -25,30 +30,22 @@ const initialize = Promise.race([
sleep(300),
]);

const render = (body: JSX.Element) => {
ReactDOM.render(body, document.getElementById('root'));
};

initialize.then(

() => {
ReactDOM.render(
root.render(
<React.StrictMode>
<Provider store={store}>
{/* Workaround for getApplicationKeyMap based on https://github.com/greena13/react-hotkeys/issues/228 */}
<GlobalHotKeys>
<ColorSchemeProvider>
<App />
</ColorSchemeProvider>
</GlobalHotKeys>
<ColorSchemeProvider>
<App />
</ColorSchemeProvider>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
},

// This error case is vey unlikely to occur.
e => render(<p>
e => root.render(<p>
{`Fatal error while loading app: ${e.message}`}
<br />
This might be caused by a incorrect configuration by the system administrator.
Expand Down
Loading

0 comments on commit 150cac5

Please sign in to comment.