mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-05-24 12:32:30 +00:00
Merge 40e46178bb into 01e728bd84
This commit is contained in:
commit
44979a5810
10 changed files with 174 additions and 1 deletions
|
|
@ -149,6 +149,9 @@ const App = () => {
|
|||
i18n.changeLanguage(args.settings.interfaceLanguage);
|
||||
}
|
||||
|
||||
if (args && args.settings && typeof args.settings.interfaceScale === 'number') {
|
||||
shell.scaleInterface(args.settings.interfaceScale);
|
||||
}
|
||||
if (args?.settings?.gamepadSupport !== undefined) {
|
||||
setGamepadSupportEnabled(args.settings.gamepadSupport);
|
||||
}
|
||||
|
|
@ -166,6 +169,9 @@ const App = () => {
|
|||
i18n.changeLanguage(state.profile.settings.interfaceLanguage);
|
||||
}
|
||||
|
||||
if (state && state.profile && state.profile.settings && typeof state.profile.settings.interfaceScale === 'number') {
|
||||
shell.scaleInterface(state.profile.settings.interfaceScale);
|
||||
}
|
||||
if (typeof state.profile.settings.gamepadSupport === 'boolean') {
|
||||
setGamepadSupportEnabled(state.profile.settings.gamepadSupport);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const SUBTITLES_SIZES = [75, 100, 125, 150, 175, 200, 250];
|
|||
const SUBTITLES_FONTS = ['PlusJakartaSans', 'Arial', 'Halvetica', 'Times New Roman', 'Verdana', 'Courier', 'Lucida Console', 'sans-serif', 'serif', 'monospace'];
|
||||
const SEEK_TIME_DURATIONS = [3000, 5000, 10000, 15000, 20000, 30000];
|
||||
const NEXT_VIDEO_POPUP_DURATIONS = [0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 65000, 70000, 75000, 80000, 85000, 90000];
|
||||
const INTERFACE_SCALES = { 75: 12, 100: 16, 125: 20, 150: 24, 175: 28 };
|
||||
const CATALOG_PREVIEW_SIZE = 10;
|
||||
const CATALOG_PAGE_SIZE = 100;
|
||||
const NONE_EXTRA_VALUE = 'None';
|
||||
|
|
@ -129,6 +130,7 @@ module.exports = {
|
|||
SUBTITLES_FONTS,
|
||||
SEEK_TIME_DURATIONS,
|
||||
NEXT_VIDEO_POPUP_DURATIONS,
|
||||
INTERFACE_SCALES,
|
||||
CATALOG_PREVIEW_SIZE,
|
||||
CATALOG_PAGE_SIZE,
|
||||
NONE_EXTRA_VALUE,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import { INTERFACE_SCALES } from './CONSTANTS';
|
||||
|
||||
const UI_SCALES = INTERFACE_SCALES as Record<number, number>;
|
||||
const SHELL_EVENT_OBJECT = 'transport';
|
||||
const transport = globalThis?.chrome?.webview;
|
||||
const events = new EventEmitter();
|
||||
|
|
@ -55,6 +57,12 @@ const useShell = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const scaleInterface = (value: number) => {
|
||||
const root = document.documentElement;
|
||||
const size = UI_SCALES[value];
|
||||
root.style.setProperty('font-size', `${size}px`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const onWindowVisibilityChanged = (data: WindowVisibility) => {
|
||||
setWindowClosed(data.visible === false && data.visibility === 0);
|
||||
|
|
@ -97,6 +105,7 @@ const useShell = () => {
|
|||
send,
|
||||
on,
|
||||
off,
|
||||
scaleInterface,
|
||||
windowClosed,
|
||||
windowHidden,
|
||||
};
|
||||
|
|
|
|||
65
src/components/Scale/Scale.less
Normal file
65
src/components/Scale/Scale.less
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
.scale {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.25rem;
|
||||
width: 100%;
|
||||
|
||||
.ticks {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
|
||||
.label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 0.8rem;
|
||||
color: var(--primary-foreground-color);
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
font-weight: 700;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
appearance: none;
|
||||
height: 1.5rem;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
padding: 0 1.5rem;
|
||||
cursor: pointer;
|
||||
|
||||
&::-webkit-slider-runnable-track {
|
||||
appearance: none;
|
||||
height: 0.25rem;
|
||||
border-radius: 1rem;
|
||||
background: var(--overlay-color);
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
appearance: none;
|
||||
width: 0.5rem;
|
||||
height: 1rem;
|
||||
margin-top: -0.375rem;
|
||||
border-radius: 1rem;
|
||||
background: var(--primary-accent-color);
|
||||
}
|
||||
|
||||
&::-moz-range-track {
|
||||
border-radius: 1rem;
|
||||
background: var(--overlay-color);
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
width: 0.5rem;
|
||||
height: 1rem;
|
||||
border-radius: 1rem;
|
||||
border: none;
|
||||
background: var(--primary-accent-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/components/Scale/Scale.tsx
Normal file
57
src/components/Scale/Scale.tsx
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import React, { MouseEvent, TouchEvent } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styles from './Scale.less';
|
||||
|
||||
type Props = {
|
||||
min: number,
|
||||
max: number,
|
||||
step: number,
|
||||
value: number,
|
||||
options: number[],
|
||||
tabIndex?: number,
|
||||
onChange: (value: number) => void,
|
||||
};
|
||||
|
||||
const Scale = ({ min, max, step, options, value, tabIndex, onChange }: Props) => {
|
||||
const onInputChange = ({ target }: MouseEvent<HTMLInputElement> | TouchEvent<HTMLInputElement>) => {
|
||||
const { value } = target as HTMLInputElement;
|
||||
onChange(parseInt(value));
|
||||
};
|
||||
|
||||
const onClick = ({ target }: MouseEvent<HTMLDivElement>) => {
|
||||
const { dataset } = target as HTMLInputElement;
|
||||
onChange(parseInt(dataset.value!));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles['scale']}>
|
||||
<div className={styles['ticks']} style={{ gridTemplateColumns: `repeat(${options.length}, 1fr)` }}>
|
||||
{
|
||||
options.map((tick) => (
|
||||
<div
|
||||
className={classNames(styles['label'], { [styles['active']]: value === tick })}
|
||||
key={tick}
|
||||
data-value={tick}
|
||||
onClick={onClick}
|
||||
>
|
||||
{tick}%
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<input
|
||||
type={'range'}
|
||||
key={value}
|
||||
tabIndex={tabIndex}
|
||||
defaultValue={value}
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
onMouseUp={onInputChange}
|
||||
onTouchEnd={onInputChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Scale;
|
||||
2
src/components/Scale/index.ts
Normal file
2
src/components/Scale/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import Scale from './Scale';
|
||||
export default Scale;
|
||||
|
|
@ -6,6 +6,7 @@ import Chips from './Chips';
|
|||
import ColorInput from './ColorInput';
|
||||
import ContextMenu from './ContextMenu';
|
||||
import ContinueWatchingItem from './ContinueWatchingItem';
|
||||
import Scale from './Scale';
|
||||
import DelayedRenderer from './DelayedRenderer';
|
||||
import EventModal from './EventModal';
|
||||
import HorizontalScroll from './HorizontalScroll';
|
||||
|
|
@ -41,6 +42,7 @@ export {
|
|||
ColorInput,
|
||||
ContextMenu,
|
||||
ContinueWatchingItem,
|
||||
Scale,
|
||||
DelayedRenderer,
|
||||
EventModal,
|
||||
HorizontalScroll,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { forwardRef } from 'react';
|
||||
import { useServices } from 'stremio/services';
|
||||
import { MultiselectMenu, Toggle } from 'stremio/components';
|
||||
import { Scale, MultiselectMenu, Toggle } from 'stremio/components';
|
||||
import { Section, Option } from '../components';
|
||||
import useInterfaceOptions from './useInterfaceOptions';
|
||||
|
||||
|
|
@ -13,6 +13,7 @@ const Interface = forwardRef<HTMLDivElement, Props>(({ profile }: Props, ref) =>
|
|||
|
||||
const {
|
||||
interfaceLanguageSelect,
|
||||
interfaceSize,
|
||||
quitOnCloseToggle,
|
||||
escExitFullscreenToggle,
|
||||
hideSpoilersToggle,
|
||||
|
|
@ -27,6 +28,12 @@ const Interface = forwardRef<HTMLDivElement, Props>(({ profile }: Props, ref) =>
|
|||
{...interfaceLanguageSelect}
|
||||
/>
|
||||
</Option>
|
||||
{
|
||||
shell.active &&
|
||||
<Option label={'SETTINGS_UI_SIZE'}>
|
||||
<Scale tabIndex={-1} {...interfaceSize} />
|
||||
</Option>
|
||||
}
|
||||
{
|
||||
shell.active &&
|
||||
<Option label={'SETTINGS_QUIT_ON_CLOSE'}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useMemo } from 'react';
|
||||
import { interfaceLanguages, useLanguageSorting } from 'stremio/common';
|
||||
import { INTERFACE_SCALES } from 'stremio/common/CONSTANTS';
|
||||
import { useServices } from 'stremio/services';
|
||||
|
||||
const useInterfaceOptions = (profile: Profile) => {
|
||||
|
|
@ -33,6 +34,26 @@ const useInterfaceOptions = (profile: Profile) => {
|
|||
}
|
||||
}), [profile.settings, sortedOptions]);
|
||||
|
||||
const interfaceSize = useMemo(() => ({
|
||||
min: 75,
|
||||
max: 175,
|
||||
step: 25,
|
||||
value: profile.settings.interfaceScale,
|
||||
options: Object.keys(INTERFACE_SCALES).map((value) => parseInt(value)),
|
||||
onChange: (value: number) => {
|
||||
core.transport.dispatch({
|
||||
action: 'Ctx',
|
||||
args: {
|
||||
action: 'UpdateSettings',
|
||||
args: {
|
||||
...profile.settings,
|
||||
interfaceScale: value
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}), [profile.settings]);
|
||||
|
||||
const escExitFullscreenToggle = useMemo(() => ({
|
||||
checked: profile.settings.escExitFullscreen,
|
||||
onClick: () => {
|
||||
|
|
@ -99,6 +120,7 @@ const useInterfaceOptions = (profile: Profile) => {
|
|||
|
||||
return {
|
||||
interfaceLanguageSelect,
|
||||
interfaceSize,
|
||||
escExitFullscreenToggle,
|
||||
quitOnCloseToggle,
|
||||
hideSpoilersToggle,
|
||||
|
|
|
|||
1
src/types/models/Ctx.d.ts
vendored
1
src/types/models/Ctx.d.ts
vendored
|
|
@ -22,6 +22,7 @@ type Settings = {
|
|||
videoMode: string | null,
|
||||
escExitFullscreen: boolean,
|
||||
interfaceLanguage: string,
|
||||
interfaceScale: number,
|
||||
quitOnClose: boolean,
|
||||
hideSpoilers: boolean,
|
||||
gamepadSupport: boolean,
|
||||
|
|
|
|||
Loading…
Reference in a new issue