mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-05-10 23:50:42 +00:00
Merge branch 'br-img' of https://github.com/dav1312/stremio-web into pr/1231
This commit is contained in:
commit
4107366094
7 changed files with 64 additions and 18 deletions
|
|
@ -41,7 +41,7 @@
|
|||
"react-i18next": "^15.1.3",
|
||||
"react-is": "18.3.1",
|
||||
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
|
||||
"stremio-translations": "github:Stremio/stremio-translations#c23317eec194b5a3318e98c2ea6acae5cfa32e2a",
|
||||
"stremio-translations": "github:Stremio/stremio-translations#fcad3f8077db865bd08b0f93d785f4090f19db40",
|
||||
"url": "0.11.4",
|
||||
"use-long-press": "^3.2.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ importers:
|
|||
specifier: github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6
|
||||
version: https://codeload.github.com/Stremio/spatial-navigation/tar.gz/64871b1422466f5f45d24ebc8bbd315b2ebab6a6
|
||||
stremio-translations:
|
||||
specifier: github:Stremio/stremio-translations#c23317eec194b5a3318e98c2ea6acae5cfa32e2a
|
||||
version: https://codeload.github.com/Stremio/stremio-translations/tar.gz/c23317eec194b5a3318e98c2ea6acae5cfa32e2a
|
||||
specifier: github:Stremio/stremio-translations#fcad3f8077db865bd08b0f93d785f4090f19db40
|
||||
version: https://codeload.github.com/Stremio/stremio-translations/tar.gz/fcad3f8077db865bd08b0f93d785f4090f19db40
|
||||
url:
|
||||
specifier: 0.11.4
|
||||
version: 0.11.4
|
||||
|
|
@ -4133,8 +4133,8 @@ packages:
|
|||
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/c23317eec194b5a3318e98c2ea6acae5cfa32e2a:
|
||||
resolution: {tarball: https://codeload.github.com/Stremio/stremio-translations/tar.gz/c23317eec194b5a3318e98c2ea6acae5cfa32e2a}
|
||||
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/fcad3f8077db865bd08b0f93d785f4090f19db40:
|
||||
resolution: {tarball: https://codeload.github.com/Stremio/stremio-translations/tar.gz/fcad3f8077db865bd08b0f93d785f4090f19db40}
|
||||
version: 1.51.0
|
||||
|
||||
string-length@4.0.2:
|
||||
|
|
@ -9378,7 +9378,7 @@ snapshots:
|
|||
es-errors: 1.3.0
|
||||
internal-slot: 1.1.0
|
||||
|
||||
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/c23317eec194b5a3318e98c2ea6acae5cfa32e2a: {}
|
||||
stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/fcad3f8077db865bd08b0f93d785f4090f19db40: {}
|
||||
|
||||
string-length@4.0.2:
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -19,10 +19,20 @@ type Props = {
|
|||
onShortcut: (name: ShortcutName) => void,
|
||||
};
|
||||
|
||||
const REPEAT_THROTTLE_MS = 130;
|
||||
|
||||
const ShortcutsProvider = ({ children, onShortcut }: Props) => {
|
||||
const listeners = useRef<Map<ShortcutName, Set<ShortcutListener>>>(new Map());
|
||||
const lastRepeatTime = useRef<Map<string, number>>(new Map());
|
||||
|
||||
const onKeyDown = useCallback(({ ctrlKey, shiftKey, code, key, repeat }: KeyboardEvent) => {
|
||||
if (repeat) {
|
||||
const now = Date.now();
|
||||
const last = lastRepeatTime.current.get(code) ?? 0;
|
||||
if (now - last < REPEAT_THROTTLE_MS) return;
|
||||
lastRepeatTime.current.set(code, now);
|
||||
}
|
||||
|
||||
const onKeyDown = useCallback(({ ctrlKey, shiftKey, code, key }: KeyboardEvent) => {
|
||||
SHORTCUTS.forEach(({ name, combos }) => combos.forEach((keys) => {
|
||||
const modifers = (keys.includes('Ctrl') ? ctrlKey : true)
|
||||
&& (keys.includes('Shift') ? shiftKey : true);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (C) 2017-2025 Smart code 203358507
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useRating from './useRating';
|
||||
import { ActionsGroup } from 'stremio/components';
|
||||
|
||||
|
|
@ -11,17 +12,20 @@ type Props = {
|
|||
};
|
||||
|
||||
const Ratings = ({ ratingInfo, className }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { onLiked, onLoved, liked, loved } = useRating(ratingInfo);
|
||||
const disabled = useMemo(() => ratingInfo?.type !== 'Ready', [ratingInfo]);
|
||||
|
||||
const items = useMemo(() => [
|
||||
{
|
||||
icon: liked ? 'thumbs-up' : 'thumbs-up-outline',
|
||||
label: liked ? t('RATING_UNLIKE') : t('RATING_LIKE'),
|
||||
disabled,
|
||||
onClick: onLiked,
|
||||
},
|
||||
{
|
||||
icon: loved ? 'heart' : 'heart-outline',
|
||||
label: loved ? t('RATING_UNLOVE') : t('RATING_LOVE'),
|
||||
disabled,
|
||||
onClick: onLoved,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
object-position: right;
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
|
@ -137,6 +137,12 @@
|
|||
|
||||
@media only screen and (max-width: @minimum) {
|
||||
.metadetails-container {
|
||||
.background-image-layer {
|
||||
.background-image {
|
||||
object-position: center;
|
||||
}
|
||||
}
|
||||
|
||||
.metadetails-content {
|
||||
display: block;
|
||||
overflow-y: auto;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
|
||||
const nextVideoPopupDismissed = React.useRef(false);
|
||||
const defaultSubtitlesSelected = React.useRef(false);
|
||||
const subtitlesEnabled = React.useRef(true);
|
||||
const lastSubtitleTrack = React.useRef(null);
|
||||
const defaultAudioTrackSelected = React.useRef(false);
|
||||
const playingOnExternalDevice = React.useRef(false);
|
||||
const [error, setError] = React.useState(null);
|
||||
|
|
@ -247,14 +247,22 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}, [video.state.videoScale]);
|
||||
|
||||
const onSubtitlesTrackSelected = React.useCallback((track) => {
|
||||
defaultSubtitlesSelected.current = true;
|
||||
video.setSubtitlesTrack(track?.id ?? null);
|
||||
if (track) {
|
||||
lastSubtitleTrack.current = { id: track.id, embedded: true };
|
||||
}
|
||||
streamStateChanged({
|
||||
subtitleTrack: track ? { id: track.id, embedded: true, lang: track.lang } : null,
|
||||
});
|
||||
}, [streamStateChanged]);
|
||||
|
||||
const onExtraSubtitlesTrackSelected = React.useCallback((track) => {
|
||||
defaultSubtitlesSelected.current = true;
|
||||
video.setExtraSubtitlesTrack(track?.id ?? null);
|
||||
if (track) {
|
||||
lastSubtitleTrack.current = { id: track.id, embedded: false };
|
||||
}
|
||||
streamStateChanged({
|
||||
subtitleTrack: track ? { id: track.id, embedded: false, lang: track.lang } : null,
|
||||
});
|
||||
|
|
@ -538,6 +546,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
React.useEffect(() => {
|
||||
defaultSubtitlesSelected.current = false;
|
||||
defaultAudioTrackSelected.current = false;
|
||||
lastSubtitleTrack.current = null;
|
||||
nextVideoPopupDismissed.current = false;
|
||||
playingOnExternalDevice.current = false;
|
||||
// we need a timeout here to make sure that previous page unloads and the new one loads
|
||||
|
|
@ -660,7 +669,7 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
|
||||
onShortcut('volumeDown', () => {
|
||||
if (video.state.volume !== null) {
|
||||
onVolumeChangeRequested(Math.min(video.state.volume - 5, 200));
|
||||
onVolumeChangeRequested(Math.max(video.state.volume - 5, 0));
|
||||
}
|
||||
}, [video.state.volume], !menusOpen);
|
||||
|
||||
|
|
@ -669,21 +678,27 @@ const Player = ({ urlParams, queryParams }) => {
|
|||
}, [onIncreaseSubtitlesDelay, onDecreaseSubtitlesDelay], !menusOpen);
|
||||
|
||||
onShortcut('subtitlesSize', (combo) => {
|
||||
combo === 1 ? onUpdateSubtitlesSize(-1) : onUpdateSubtitlesSize(1);
|
||||
combo === 1 ? onUpdateSubtitlesSize(1) : onUpdateSubtitlesSize(-1);
|
||||
}, [onUpdateSubtitlesSize, onUpdateSubtitlesSize], !menusOpen);
|
||||
|
||||
onShortcut('toggleSubtitles', () => {
|
||||
const savedTrack = player.streamState?.subtitleTrack;
|
||||
const isEnabled = video.state.selectedSubtitlesTrackId !== null || video.state.selectedExtraSubtitlesTrackId !== null;
|
||||
|
||||
if (subtitlesEnabled.current) {
|
||||
if (isEnabled) {
|
||||
if (video.state.selectedSubtitlesTrackId) {
|
||||
lastSubtitleTrack.current = { id: video.state.selectedSubtitlesTrackId, embedded: true };
|
||||
} else if (video.state.selectedExtraSubtitlesTrackId) {
|
||||
lastSubtitleTrack.current = { id: video.state.selectedExtraSubtitlesTrackId, embedded: false };
|
||||
}
|
||||
video.setSubtitlesTrack(null);
|
||||
video.setExtraSubtitlesTrack(null);
|
||||
} else if (savedTrack?.id) {
|
||||
savedTrack.embedded ? video.setSubtitlesTrack(savedTrack.id) : video.setExtraSubtitlesTrack(savedTrack.id);
|
||||
} else {
|
||||
const savedTrack = player.streamState?.subtitleTrack ?? lastSubtitleTrack.current;
|
||||
if (savedTrack?.id) {
|
||||
savedTrack.embedded ? video.setSubtitlesTrack(savedTrack.id) : video.setExtraSubtitlesTrack(savedTrack.id);
|
||||
}
|
||||
}
|
||||
|
||||
subtitlesEnabled.current = !subtitlesEnabled.current;
|
||||
}, [player.streamState], !menusOpen);
|
||||
}, [player.streamState, video.state.selectedSubtitlesTrackId, video.state.selectedExtraSubtitlesTrackId], !menusOpen);
|
||||
|
||||
onShortcut('subtitlesMenu', () => {
|
||||
closeMenus();
|
||||
|
|
|
|||
|
|
@ -24,6 +24,17 @@
|
|||
transition: transform 0.3s ease-in-out;
|
||||
z-index: 1;
|
||||
|
||||
// Safari has a compositing bug where transform animations on a parent with
|
||||
// scrollable children causes the video player element to shift left during the animation.
|
||||
// Disable the slide animation on Safari until WebKit resolves this.
|
||||
@supports (hanging-punctuation: first) and (-webkit-appearance: none) {
|
||||
&:global(.slide-left-enter),
|
||||
&:global(.slide-left-active),
|
||||
&:global(.slide-left-exit) {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
.close-button {
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
|
|
|||
Loading…
Reference in a new issue