Skip to content

Commit

Permalink
Pause-on-hover setting
Browse files Browse the repository at this point in the history
  • Loading branch information
killergerbah committed Aug 4, 2024
1 parent 699df9e commit a743ab7
Show file tree
Hide file tree
Showing 19 changed files with 209 additions and 12 deletions.
40 changes: 38 additions & 2 deletions common/app/components/VideoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
SubtitleAlignment,
changeForTextSubtitleSetting,
textSubtitleSettingsForTrack,
PauseOnHoverMode,
} from '@project/common/settings';
import { surroundingSubtitles, mockSurroundingSubtitles, seekWithNudge } from '@project/common/util';
import { SubtitleCollection } from '@project/common/subtitle-collection';
Expand Down Expand Up @@ -173,6 +174,7 @@ interface ShowingSubtitleProps {
subtitleStyles: any;
imageBasedSubtitleScaleFactor: number;
className?: string;
onMouseOver: React.MouseEventHandler<HTMLDivElement>;
}

const ShowingSubtitle = ({
Expand All @@ -181,6 +183,7 @@ const ShowingSubtitle = ({
subtitleStyles,
imageBasedSubtitleScaleFactor,
className,
onMouseOver,
}: ShowingSubtitleProps) => {
let content;

Expand All @@ -196,23 +199,30 @@ const ShowingSubtitle = ({
content = <span style={subtitleStyles}>{subtitle.text}</span>;
}

return <div className={className ? className : ''}>{content}</div>;
return (
<div className={className ? className : ''} onMouseOver={onMouseOver}>
{content}
</div>
);
};

interface CachedShowingSubtitleProps {
index: number;
domCache: OffscreenDomCache;
className?: string;
onMouseOver: React.MouseEventHandler<HTMLDivElement>;
}

const CachedShowingSubtitle = React.memo(function CachedShowingSubtitle({
index,
domCache,
className,
onMouseOver,
}: CachedShowingSubtitleProps) {
return (
<div
className={className ? className : ''}
onMouseOver={onMouseOver}
ref={(ref) => {
if (!ref) {
return;
Expand Down Expand Up @@ -1264,6 +1274,23 @@ export default function VideoPlayer({
ms: 500,
});

const isPausedDueToHoverRef = useRef<boolean>();

const handleSubtitleMouseOver = useCallback(() => {
if (miscSettings.pauseOnHoverMode !== PauseOnHoverMode.disabled && videoRef.current?.paused === false) {
playerChannel.pause();
isPausedDueToHoverRef.current = true;
}
}, [miscSettings.pauseOnHoverMode, playerChannel]);

const handleVideoMouseOver = useCallback(() => {
if (miscSettings.pauseOnHoverMode === PauseOnHoverMode.inAndOut && isPausedDueToHoverRef.current) {
playerChannel.play();
}

isPausedDueToHoverRef.current = false;
}, [miscSettings.pauseOnHoverMode, playerChannel]);

// If the video player is taking up the entire screen, then the subtitle player isn't showing
// This code assumes some behavior in Player, namely that the subtitle player is automatically hidden
// (and therefore the VideoPlayer takes up all the space) when there isn't enough room for the subtitle player
Expand All @@ -1290,6 +1317,7 @@ export default function VideoPlayer({
className={showCursor ? classes.video : `${classes.cursorHidden} ${classes.video}`}
ref={videoRefCallback}
src={videoFile}
onMouseOver={handleVideoMouseOver}
/>
{displaySubtitles && (
<div
Expand All @@ -1306,7 +1334,14 @@ export default function VideoPlayer({
{showSubtitles.map((subtitle, index) => {
if (miscSettings.preCacheSubtitleDom) {
const domCache = getSubtitleDomCache();
return <CachedShowingSubtitle key={index} index={subtitle.index} domCache={domCache} />;
return (
<CachedShowingSubtitle
key={index}
index={subtitle.index}
domCache={domCache}
onMouseOver={handleSubtitleMouseOver}
/>
);
}

return (
Expand All @@ -1317,6 +1352,7 @@ export default function VideoPlayer({
className={trackStyles[subtitle.track].classes}
videoRef={videoRef}
imageBasedSubtitleScaleFactor={subtitleSettings.imageBasedSubtitleScaleFactor}
onMouseOver={handleSubtitleMouseOver}
/>
);
})}
Expand Down
2 changes: 2 additions & 0 deletions common/app/services/video-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ export default class VideoChannel {
language,
lastSubtitleOffset,
tabName,
pauseOnHoverMode,
} = settings;
const message: MiscSettingsToVideoMessage = {
command: 'miscSettings',
Expand All @@ -572,6 +573,7 @@ export default class VideoChannel {
language,
lastSubtitleOffset,
tabName,
pauseOnHoverMode,
},
};
this.protocol.postMessage(message);
Expand Down
48 changes: 48 additions & 0 deletions common/components/SettingsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
AsbplayerSettings,
CustomAnkiFieldSettings,
KeyBindName,
PauseOnHoverMode,
SubtitleListPreference,
TextSubtitleSettings,
changeForTextSubtitleSetting,
Expand Down Expand Up @@ -832,6 +833,7 @@ export default function SettingsForm({
streamingEnableOverlay,
webSocketClientEnabled,
webSocketServerUrl,
pauseOnHoverMode,
} = settings;

const [selectedSubtitleAppearanceTrack, setSelectedSubtitleAppearanceTrack] = useState<number>();
Expand Down Expand Up @@ -2415,6 +2417,52 @@ export default function SettingsForm({
/>
</RadioGroup>
</Grid>
<Grid item>
<FormLabel className={classes.top} component="legend">
{t('settings.pauseOnHoverMode')}
</FormLabel>
<RadioGroup row={false}>
<LabelWithHoverEffect
control={
<Radio
checked={pauseOnHoverMode === PauseOnHoverMode.disabled}
value={PauseOnHoverMode.disabled}
onChange={(event) =>
event.target.checked &&
handleSettingChanged('pauseOnHoverMode', PauseOnHoverMode.disabled)
}
/>
}
label={t('pauseOnHoverMode.disabled')}
/>
<LabelWithHoverEffect
control={
<Radio
checked={pauseOnHoverMode === PauseOnHoverMode.inAndOut}
value={PauseOnHoverMode.inAndOut}
onChange={(event) =>
event.target.checked &&
handleSettingChanged('pauseOnHoverMode', PauseOnHoverMode.inAndOut)
}
/>
}
label={t('pauseOnHoverMode.inAndOut')}
/>
<LabelWithHoverEffect
control={
<Radio
checked={pauseOnHoverMode === PauseOnHoverMode.inNotOut}
value={PauseOnHoverMode.inNotOut}
onChange={(event) =>
event.target.checked &&
handleSettingChanged('pauseOnHoverMode', PauseOnHoverMode.inNotOut)
}
/>
}
label={t('pauseOnHoverMode.inNotOut')}
/>
</RadioGroup>
</Grid>
<Grid item>
<TextField
type="number"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "Always play",
"pause": "Always pause"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "Auswahl anwenden",
"audio": "Audio",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "Enable WebSocket client",
"webSocketServerUrl": "WebSocket Server URL",
"firefoxExtensionShortcutHelp": "Edit this shortcut from the Plugin manager at about:addons.",
"postMinePlayback": "Post-mining playback state"
"postMinePlayback": "Post-mining playback state",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Click, hold, and drag to mine multiple subtitles"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "Always play",
"pause": "Always pause"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "Apply Selection",
"audio": "Audio",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "Enable WebSocket client",
"webSocketServerUrl": "WebSocket Server URL",
"firefoxExtensionShortcutHelp": "Edit this shortcut from the Plugin manager at about:addons.",
"postMinePlayback": "Post-mining playback state"
"postMinePlayback": "Post-mining playback state",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Click, hold, and drag to mine multiple subtitles"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "Siempre reproducir",
"pause": "Siempre pausar"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "Aplicar Selección",
"audio": "Audio",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "Habilitar cliente WebSocket",
"webSocketServerUrl": "URL del servidor WebSocket",
"firefoxExtensionShortcutHelp": "Edita este acceso directo desde el gestor de plugins en about:addons.",
"postMinePlayback": "Estado de reproducción post-minado"
"postMinePlayback": "Estado de reproducción post-minado",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Haz click, mantén y arrastra para minar múltiples subtítulos"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "常に再生する",
"pause": "常に停止する"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "選択範囲を適用する",
"audio": "音声",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "WebSocketクライアントを有効",
"webSocketServerUrl": "WebSocketサーバーのURL",
"firefoxExtensionShortcutHelp": "ショートカットの編集はプラグイン管理 (about:addons)で行えます。",
"postMinePlayback": "マイニング後のプレイバック状態"
"postMinePlayback": "マイニング後のプレイバック状態",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "複数の字幕をマイニングするには、クリックし、押し続け、ドラッグしてください"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "Zawsze odtwarzaj",
"pause": "Zawsze pauzuj"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "Zastosuj wybór",
"audio": "Audio",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "Włącz klienta WebSocket",
"webSocketServerUrl": "Adres URL serwera WebSocket",
"firefoxExtensionShortcutHelp": "Edytuj ten skrót z poziomu menedżera wtyczek na about:addons.",
"postMinePlayback": "Stan odtwarzania po kopaniu"
"postMinePlayback": "Stan odtwarzania po kopaniu",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Kliknij, przytrzymaj i przeciągnij, aby wykopać więcej linii napisów"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/pt_BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "Sempre reproduzir",
"pause": "Sempre pausado"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "Aplicar seleção",
"audio": "Áudio",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "Enable WebSocket client",
"webSocketServerUrl": "WebSocket Server URL",
"firefoxExtensionShortcutHelp": "Edit this shortcut from the Plugin manager at about:addons.",
"postMinePlayback": "Post-mining playback state"
"postMinePlayback": "Post-mining playback state",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Clique, segure e arraste para minerar múltiplas legendas"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "Always play",
"pause": "Always pause"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "Применить выбор",
"audio": "Аудио",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "Enable WebSocket client",
"webSocketServerUrl": "WebSocket Server URL",
"firefoxExtensionShortcutHelp": "Edit this shortcut from the Plugin manager at about:addons.",
"postMinePlayback": "Post-mining playback state"
"postMinePlayback": "Post-mining playback state",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Нажмите, удерживайте и перетащите, чтобы смайнить несколько субтитров"
Expand Down
8 changes: 7 additions & 1 deletion common/locales/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
"play": "Always play",
"pause": "Always pause"
},
"pauseOnHoverMode": {
"disabled": "Disabled",
"inNotOut": "Enabled",
"inAndOut": "Enabled with auto-resume"
},
"ankiDialog": {
"applySelection": "应用选中时间范围",
"audio": "音频",
Expand Down Expand Up @@ -339,7 +344,8 @@
"webSocketClientEnabled": "Enable WebSocket client",
"webSocketServerUrl": "WebSocket Server URL",
"firefoxExtensionShortcutHelp": "Edit this shortcut from the Plugin manager at about:addons.",
"postMinePlayback": "Post-mining playback state"
"postMinePlayback": "Post-mining playback state",
"pauseOnHoverMode": "Auto-pause when mousing over subtitles"
},
"subtitlePlayer": {
"multiSubtitleSelectHelp": "Click, hold, and drag to mine multiple subtitles"
Expand Down
2 changes: 2 additions & 0 deletions common/settings/settings-import-export.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PauseOnHoverMode } from './settings';
import { validateSettings } from './settings-import-export';
import { defaultSettings } from './settings-provider';

Expand Down Expand Up @@ -132,5 +133,6 @@ it('validates exported settings', () => {
streamingCondensedPlaybackMinimumSkipIntervalMs: 1000,
streamingScreenshotDelay: 1000,
streamingSubtitleListPreference: 'app',
pauseOnHoverMode: PauseOnHoverMode.disabled,
});
});
3 changes: 3 additions & 0 deletions common/settings/settings-import-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ const settingsSchema = {
webSocketServerUrl: {
type: 'string',
},
pauseOnHoverMode: {
type: 'number',
},
_schema: {
type: 'number',
},
Expand Down
Loading

0 comments on commit a743ab7

Please sign in to comment.