diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..c1da1247e
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+screenshots/*
+screenshots*
diff --git a/Dockerfile b/Dockerfile
index 4eeb450cf..2febdd65f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,24 +1,31 @@
-# Stremio Node 14.x
-FROM stremio/node-base:fermium
-
-# Meta
-LABEL Description="Stremio Web" Vendor="Smart Code OOD" Version="1.0.0"
-
-# Update GitHub remote host key
-RUN echo "github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=" >> ~/.ssh/known_hosts
-
-# Create app directory
-RUN mkdir -p /var/www/stremio-web
-
-# Install app dependencies
-WORKDIR /var/www/stremio-web
-COPY . /var/www/stremio-web
-RUN npm install
-
-# Bundle app source
-WORKDIR /var/www/stremio-web
-
-RUN npm run build
-
-EXPOSE 8080
-CMD ["node", "http_server.js"]
+# Stremio Node 14.x
+# the node version for running Stremio Web
+ARG NODE_VERSION=15-alpine
+FROM node:$NODE_VERSION AS base
+
+# Meta
+LABEL Description="Stremio Web" Vendor="Smart Code OOD" Version="1.0.0"
+
+RUN mkdir -p /var/www/stremio-web
+WORKDIR /var/www/stremio-web
+
+# Install app dependencies
+FROM base AS prebuild
+
+RUN apk update && apk upgrade && \
+ apk add --no-cache git
+WORKDIR /var/www/stremio-web
+COPY . .
+RUN npm install
+RUN npm run build
+
+# Bundle app source
+FROM base AS final
+
+WORKDIR /var/www/stremio-web
+COPY . .
+COPY --from=prebuild /var/www/stremio-web/node_modules ./node_modules
+COPY --from=prebuild /var/www/stremio-web/build ./build
+
+EXPOSE 8080
+CMD ["node", "http_server.js"]
diff --git a/README.md b/README.md
index 20f3f6413..06a5428ae 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# Stremio - Freedom to Stream

-[](https://stremio.github.io/stremio-web/)
+[](https://stremio.github.io/stremio-web/development)
Stremio is a modern media center that's a one-stop solution for your video entertainment. You discover, watch and organize video content from easy to install addons.
@@ -46,4 +46,4 @@ npm run build
## License
-Stremio is copyright 2017-2022 Smart code and available under GPLv2 license. See the [LICENSE](/LICENSE.md) file in the project for more information.
+Stremio is copyright 2017-2023 Smart code and available under GPLv2 license. See the [LICENSE](/LICENSE.md) file in the project for more information.
diff --git a/images/icon_x192.png b/images/icon_x192.png
index ca1a5a722..17b06916a 100644
Binary files a/images/icon_x192.png and b/images/icon_x192.png differ
diff --git a/images/icon_x512.png b/images/icon_x512.png
index c33705169..4807007a0 100644
Binary files a/images/icon_x512.png and b/images/icon_x512.png differ
diff --git a/package-lock.json b/package-lock.json
index f1b15e61d..401948d6e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,9 +12,9 @@
"@babel/runtime": "7.16.0",
"@sentry/browser": "6.13.3",
"@stremio/stremio-colors": "5.0.1",
- "@stremio/stremio-core-web": "0.44.23",
+ "@stremio/stremio-core-web": "0.44.25",
"@stremio/stremio-icons": "5.0.0-beta.3",
- "@stremio/stremio-video": "0.0.24",
+ "@stremio/stremio-video": "0.0.25-rc.2",
"a-color-picker": "1.2.1",
"bowser": "2.11.0",
"buffer": "6.0.3",
@@ -2704,9 +2704,9 @@
"integrity": "sha512-Dt3PYmy1DZ473QNs99KYXVWQPHtpIl37VUY0+gCEvvuCqE1fRrZIJtZ9KbysUKonvO7WwdQDztgcW0iGoc1dEA=="
},
"node_modules/@stremio/stremio-core-web": {
- "version": "0.44.23",
- "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.23.tgz",
- "integrity": "sha512-I3t0jxZdyNTLIE0w2O1fJIQ562BJc2iN26xL056KiD5FIuGfTAJ/vdHTiPAbcmEXsO3TPxX9fOGsntNEhnO2cA==",
+ "version": "0.44.25",
+ "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.25.tgz",
+ "integrity": "sha512-kW/AAh+c1qnfV5xFbfM+VFFvuRXp4M1pQuUj94O6my2kC39zKkZnFMQRDNbzoodoUQY0fusDM1K7rIw3DmlqEg==",
"dependencies": {
"@babel/runtime": "7.16.0"
}
@@ -2717,9 +2717,9 @@
"integrity": "sha512-K+jDsizEgxpBC+b0HExCUg+bnsWPZnx96qUfkdQ9nBDVAN/kzcP24Jq/4KwkiEyqDEcvC5l+xBzOLzkhdLwTMw=="
},
"node_modules/@stremio/stremio-video": {
- "version": "0.0.24",
- "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.24.tgz",
- "integrity": "sha512-k9bSyQBbZQnLll62P/enc/gy2eILZrW0xuU/MRxxTm9gtjo+8JLp/77H0a4tQFFHjJ9WPuNj4K6Lo2UnGem3kg==",
+ "version": "0.0.25-rc.2",
+ "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.25-rc.2.tgz",
+ "integrity": "sha512-OXNimBgPpkin5gX39Bsx/w6M+5ifP71amZEYlvsZz3CDKxGHkQTPLzl4z6RrbVr8wz8nt6eiWIj8BKxa4/u6nQ==",
"dependencies": {
"buffer": "6.0.3",
"color": "4.2.3",
@@ -16834,9 +16834,9 @@
"integrity": "sha512-Dt3PYmy1DZ473QNs99KYXVWQPHtpIl37VUY0+gCEvvuCqE1fRrZIJtZ9KbysUKonvO7WwdQDztgcW0iGoc1dEA=="
},
"@stremio/stremio-core-web": {
- "version": "0.44.23",
- "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.23.tgz",
- "integrity": "sha512-I3t0jxZdyNTLIE0w2O1fJIQ562BJc2iN26xL056KiD5FIuGfTAJ/vdHTiPAbcmEXsO3TPxX9fOGsntNEhnO2cA==",
+ "version": "0.44.25",
+ "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.44.25.tgz",
+ "integrity": "sha512-kW/AAh+c1qnfV5xFbfM+VFFvuRXp4M1pQuUj94O6my2kC39zKkZnFMQRDNbzoodoUQY0fusDM1K7rIw3DmlqEg==",
"requires": {
"@babel/runtime": "7.16.0"
}
@@ -16847,9 +16847,9 @@
"integrity": "sha512-K+jDsizEgxpBC+b0HExCUg+bnsWPZnx96qUfkdQ9nBDVAN/kzcP24Jq/4KwkiEyqDEcvC5l+xBzOLzkhdLwTMw=="
},
"@stremio/stremio-video": {
- "version": "0.0.24",
- "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.24.tgz",
- "integrity": "sha512-k9bSyQBbZQnLll62P/enc/gy2eILZrW0xuU/MRxxTm9gtjo+8JLp/77H0a4tQFFHjJ9WPuNj4K6Lo2UnGem3kg==",
+ "version": "0.0.25-rc.2",
+ "resolved": "https://registry.npmjs.org/@stremio/stremio-video/-/stremio-video-0.0.25-rc.2.tgz",
+ "integrity": "sha512-OXNimBgPpkin5gX39Bsx/w6M+5ifP71amZEYlvsZz3CDKxGHkQTPLzl4z6RrbVr8wz8nt6eiWIj8BKxa4/u6nQ==",
"requires": {
"buffer": "6.0.3",
"color": "4.2.3",
diff --git a/package.json b/package.json
index c26a659d9..20c139e20 100755
--- a/package.json
+++ b/package.json
@@ -15,9 +15,9 @@
"@babel/runtime": "7.16.0",
"@sentry/browser": "6.13.3",
"@stremio/stremio-colors": "5.0.1",
- "@stremio/stremio-core-web": "0.44.23",
+ "@stremio/stremio-core-web": "0.44.25",
"@stremio/stremio-icons": "5.0.0-beta.3",
- "@stremio/stremio-video": "0.0.24",
+ "@stremio/stremio-video": "0.0.25-rc.2",
"a-color-picker": "1.2.1",
"bowser": "2.11.0",
"buffer": "6.0.3",
diff --git a/screenshots/board.png b/screenshots/board.png
index 10359e455..1fa83799a 100644
Binary files a/screenshots/board.png and b/screenshots/board.png differ
diff --git a/screenshots/discover.png b/screenshots/discover.png
index 554328045..eab8b5a2e 100644
Binary files a/screenshots/discover.png and b/screenshots/discover.png differ
diff --git a/screenshots/metadetails.png b/screenshots/metadetails.png
index 898c5c9cd..9aec4a302 100644
Binary files a/screenshots/metadetails.png and b/screenshots/metadetails.png differ
diff --git a/src/App/App.js b/src/App/App.js
index be59767b7..de443d9d4 100644
--- a/src/App/App.js
+++ b/src/App/App.js
@@ -6,7 +6,7 @@ const { useTranslation } = require('react-i18next');
const { Router } = require('stremio-router');
const { Core, Shell, Chromecast, DragAndDrop, KeyboardShortcuts, ServicesProvider } = require('stremio/services');
const { NotFound } = require('stremio/routes');
-const { ToastProvider, CONSTANTS, withCoreSuspender } = require('stremio/common');
+const { ToastProvider, TooltipProvider, CONSTANTS, withCoreSuspender } = require('stremio/common');
const ServicesToaster = require('./ServicesToaster');
const DeepLinkHandler = require('./DeepLinkHandler');
const ErrorDialog = require('./ErrorDialog');
@@ -159,13 +159,15 @@ const App = () => {
:
-
-
-
+
+
+
+
+
:
diff --git a/src/App/styles.less b/src/App/styles.less
index f2a96b1f3..038f6cf56 100644
--- a/src/App/styles.less
+++ b/src/App/styles.less
@@ -117,6 +117,19 @@ html {
}
}
+ .tooltip-container {
+ height: 2.5rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 1.5rem;
+ font-size: 1rem;
+ color: var(--primary-foreground-color);
+ border-radius: var(--border-radius);
+ background-color: var(--modal-background-color);
+ transition: opacity 0.25s ease-out;
+ }
+
.router {
width: 100%;
height: 100%;
diff --git a/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenuContent.js b/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenuContent.js
index ab130e62c..9492ed7fc 100644
--- a/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenuContent.js
+++ b/src/common/NavBar/HorizontalNavBar/NavMenu/NavMenuContent.js
@@ -90,9 +90,14 @@ const NavMenuContent = ({ onClick }) => {
-
+ {
+ profile.auth !== null ?
+
+ :
+ null
+ }
);
diff --git a/src/common/Tooltip/Tooltip.js b/src/common/Tooltip/Tooltip.js
new file mode 100644
index 000000000..91a11ef5c
--- /dev/null
+++ b/src/common/Tooltip/Tooltip.js
@@ -0,0 +1,63 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const React = require('react');
+const PropTypes = require('prop-types');
+const useTooltip = require('./useTooltip');
+const styles = require('./styles');
+
+const createId = () => (Math.random() + 1).toString(36).substring(7);
+
+const Tooltip = ({ label, position, margin }) => {
+ const tooltip = useTooltip();
+
+ const id = React.useRef(createId());
+ const element = React.useRef(null);
+
+ const onMouseEnter = () => {
+ tooltip.toggle(id.current, true);
+ };
+
+ const onMouseLeave = () => {
+ tooltip.toggle(id.current, false);
+ };
+
+ React.useEffect(() => {
+ if (element.current && element.current.parentElement) {
+ const parentElement = element.current.parentElement;
+ tooltip.add({
+ id: id.current,
+ label,
+ position,
+ margin,
+ parent: parentElement,
+ });
+
+ parentElement.addEventListener('mouseenter', onMouseEnter);
+ parentElement.addEventListener('mouseleave', onMouseLeave);
+ }
+
+ return () => {
+ if (element.current && element.current.parentElement) {
+ const parentElement = element.current.parentElement;
+ parentElement.removeEventListener('mouseenter', onMouseEnter);
+ parentElement.removeEventListener('mouseleave', onMouseLeave);
+
+ tooltip.remove(id.current);
+ }
+ };
+ }, []);
+
+ return (
+
+ );
+};
+
+Tooltip.displayName = 'Tooltip';
+
+Tooltip.propTypes = {
+ label: PropTypes.string.isRequired,
+ position: PropTypes.string.isRequired,
+ margin: PropTypes.number,
+};
+
+module.exports = Tooltip;
diff --git a/src/common/Tooltip/TooltipContext.js b/src/common/Tooltip/TooltipContext.js
new file mode 100644
index 000000000..f4da8a082
--- /dev/null
+++ b/src/common/Tooltip/TooltipContext.js
@@ -0,0 +1,8 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const { createContext } = require('react');
+
+const TooltipContext = createContext(null);
+
+module.exports = TooltipContext;
+
diff --git a/src/common/Tooltip/TooltipProvider.js b/src/common/Tooltip/TooltipProvider.js
new file mode 100644
index 000000000..c19780248
--- /dev/null
+++ b/src/common/Tooltip/TooltipProvider.js
@@ -0,0 +1,106 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const React = require('react');
+const { useState, createRef } = require('react');
+const PropTypes = require('prop-types');
+const classNames = require('classnames');
+const TooltipContext = require('./TooltipContext');
+const styles = require('./styles');
+
+const TooltipProvider = ({ children, className }) => {
+ const [tooltips, setTooltips] = useState([]);
+
+ const add = ({ id, label, position, margin = 15, parent }) => {
+ const ref = createRef(null);
+
+ const tooltip = {
+ ref,
+ id,
+ label,
+ position,
+ margin: margin,
+ active: false,
+ parent,
+ };
+
+ setTooltips((tooltips) => ([
+ ...tooltips,
+ tooltip,
+ ]));
+ };
+
+ const remove = (id) => {
+ setTooltips((tooltips) => (
+ tooltips.filter((tooltip) => tooltip.id !== id)
+ ));
+ };
+
+ const toggle = (id, state) => {
+ setTooltips((tooltips) => (
+ tooltips.map((tooltip) => {
+ if (tooltip.id === id) {
+ tooltip.active = state;
+ }
+ return tooltip;
+ })
+ ));
+ };
+
+ const style = (ref, position, margin, active, parent) => {
+ if (!active) return {};
+
+ const tooltipHeight = ref.current?.offsetHeight ?? 0;
+ const tooltipWidth = ref.current?.offsetWidth ?? 0;
+ const parentBounds = parent.getBoundingClientRect();
+
+ switch (position) {
+ case 'top':
+ return {
+ top: `${parentBounds.top - tooltipHeight - margin}px`,
+ left: `${(parentBounds.left + (parentBounds.width / 2)) - (tooltipWidth / 2)}px`,
+ };
+ case 'bottom':
+ return {
+ top: `${parentBounds.top + parentBounds.height + margin}px`,
+ left: `${(parentBounds.left + (parentBounds.width / 2)) - (tooltipWidth / 2)}px`,
+ };
+ case 'left':
+ return {
+ top: `${parentBounds.top + (parentBounds.height / 2) - (tooltipHeight / 2)}px`,
+ left: `${(parentBounds.left - tooltipWidth - margin)}px`,
+ };
+ case 'right':
+ return {
+ top: `${parentBounds.top + (parentBounds.height / 2) - (tooltipHeight / 2)}px`,
+ left: `${(parentBounds.left + parentBounds.width + margin)}px`,
+ };
+ }
+ };
+
+ return (
+
+ { children }
+
+ {
+ tooltips.map(({ ref, id, label, position, margin, active, parent }) => (
+
+ { label }
+
+ ))
+ }
+
+
+ );
+};
+
+TooltipProvider.propTypes = {
+ children: PropTypes.node,
+ className: PropTypes.string,
+};
+
+module.exports = TooltipProvider;
diff --git a/src/common/Tooltip/index.js b/src/common/Tooltip/index.js
new file mode 100644
index 000000000..82356a28f
--- /dev/null
+++ b/src/common/Tooltip/index.js
@@ -0,0 +1,9 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const TooltipProvider = require('./TooltipProvider');
+const Tooltip = require('./Tooltip');
+
+module.exports = {
+ TooltipProvider,
+ Tooltip,
+};
diff --git a/src/common/Tooltip/styles.less b/src/common/Tooltip/styles.less
new file mode 100644
index 000000000..d69825b71
--- /dev/null
+++ b/src/common/Tooltip/styles.less
@@ -0,0 +1,22 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+.tooltip {
+ z-index: -1;
+ visibility: hidden;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+.tooltip-container {
+ position: fixed;
+ visibility: hidden;
+ opacity: 0;
+
+ &:global(.active) {
+ visibility: visible;
+ opacity: 1;
+ }
+}
\ No newline at end of file
diff --git a/src/common/Tooltip/useTooltip.js b/src/common/Tooltip/useTooltip.js
new file mode 100644
index 000000000..d787dca39
--- /dev/null
+++ b/src/common/Tooltip/useTooltip.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+const React = require('react');
+const TooltipContext = require('./TooltipContext');
+
+const useTooltip = () => {
+ return React.useContext(TooltipContext);
+};
+
+module.exports = useTooltip;
diff --git a/src/common/index.js b/src/common/index.js
index f267be575..700fd432b 100644
--- a/src/common/index.js
+++ b/src/common/index.js
@@ -23,6 +23,7 @@ const SharePrompt = require('./SharePrompt');
const Slider = require('./Slider');
const TextInput = require('./TextInput');
const { ToastProvider, useToast } = require('./Toast');
+const { TooltipProvider, Tooltip } = require('./Tooltip');
const comparatorWithPriorities = require('./comparatorWithPriorities');
const CONSTANTS = require('./CONSTANTS');
const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender');
@@ -70,6 +71,8 @@ module.exports = {
TextInput,
ToastProvider,
useToast,
+ TooltipProvider,
+ Tooltip,
comparatorWithPriorities,
CONSTANTS,
withCoreSuspender,
diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js
index cfdbaf4ce..602ae1516 100644
--- a/src/routes/Player/Player.js
+++ b/src/routes/Player/Player.js
@@ -33,6 +33,28 @@ const Player = ({ urlParams, queryParams }) => {
queryParams.has('maxAudioChannels') ? parseInt(queryParams.get('maxAudioChannels'), 10) : null
];
}, [queryParams]);
+ const [player, videoParamsChanged, timeChanged, pausedChanged, ended] = usePlayer(urlParams);
+ const [settings, updateSettings] = useSettings();
+ const streamingServer = useStreamingServer();
+ const routeFocused = useRouteFocused();
+ const toast = useToast();
+ const [, , , toggleFullscreen] = useFullscreen();
+ const [casting, setCasting] = React.useState(() => {
+ return chromecast.active && chromecast.transport.getCastState() === cast.framework.CastState.CONNECTED;
+ });
+ const [immersed, setImmersed] = React.useState(true);
+ const setImmersedDebounced = React.useCallback(debounce(setImmersed, 3000), []);
+ const [optionsMenuOpen, , closeOptionsMenu, toggleOptionsMenu] = useBinaryState(false);
+ const [subtitlesMenuOpen, , closeSubtitlesMenu, toggleSubtitlesMenu] = useBinaryState(false);
+ const [infoMenuOpen, , closeInfoMenu, toggleInfoMenu] = useBinaryState(false);
+ const [speedMenuOpen, , closeSpeedMenu, toggleSpeedMenu] = useBinaryState(false);
+ const [videosMenuOpen, , closeVideosMenu, toggleVideosMenu] = useBinaryState(false);
+ const [nextVideoPopupOpen, openNextVideoPopup, closeNextVideoPopup] = useBinaryState(false);
+ const [statisticsMenuOpen, , closeStatisticsMenu, toggleStatisticsMenu] = useBinaryState(false);
+ const nextVideoPopupDismissed = React.useRef(false);
+ const defaultSubtitlesSelected = React.useRef(false);
+ const defaultAudioTrackSelected = React.useRef(false);
+ const [error, setError] = React.useState(null);
const [videoState, setVideoState] = React.useReducer(
(videoState, nextVideoState) => ({ ...videoState, ...nextVideoState }),
{
@@ -66,28 +88,6 @@ const Player = ({ urlParams, queryParams }) => {
extraSubtitlesOutlineColor: null
}
);
- const [player, timeChanged, pausedChanged, ended] = usePlayer(urlParams, videoState.videoParams);
- const [settings, updateSettings] = useSettings();
- const streamingServer = useStreamingServer();
- const routeFocused = useRouteFocused();
- const toast = useToast();
- const [, , , toggleFullscreen] = useFullscreen();
- const [casting, setCasting] = React.useState(() => {
- return chromecast.active && chromecast.transport.getCastState() === cast.framework.CastState.CONNECTED;
- });
- const [immersed, setImmersed] = React.useState(true);
- const setImmersedDebounced = React.useCallback(debounce(setImmersed, 3000), []);
- const [optionsMenuOpen, , closeOptionsMenu, toggleOptionsMenu] = useBinaryState(false);
- const [subtitlesMenuOpen, , closeSubtitlesMenu, toggleSubtitlesMenu] = useBinaryState(false);
- const [infoMenuOpen, , closeInfoMenu, toggleInfoMenu] = useBinaryState(false);
- const [speedMenuOpen, , closeSpeedMenu, toggleSpeedMenu] = useBinaryState(false);
- const [videosMenuOpen, , closeVideosMenu, toggleVideosMenu] = useBinaryState(false);
- const [nextVideoPopupOpen, openNextVideoPopup, closeNextVideoPopup] = useBinaryState(false);
- const [statisticsMenuOpen, , closeStatisticsMenu, toggleStatisticsMenu] = useBinaryState(false);
- const nextVideoPopupDismissed = React.useRef(false);
- const defaultSubtitlesSelected = React.useRef(false);
- const defaultAudioTrackSelected = React.useRef(false);
- const [error, setError] = React.useState(null);
const videoRef = React.useRef(null);
const dispatch = React.useCallback((action, options) => {
if (videoRef.current !== null) {
@@ -353,6 +353,9 @@ const Player = ({ urlParams, queryParams }) => {
pausedChanged(videoState.paused);
}
}, [videoState.paused]);
+ React.useEffect(() => {
+ videoParamsChanged(videoState.videoParams);
+ }, [videoState.videoParams]);
React.useEffect(() => {
if (!!settings.bingeWatching && player.nextVideo !== null && !nextVideoPopupDismissed.current) {
if (videoState.time !== null && videoState.duration !== null && videoState.time < videoState.duration && (videoState.duration - videoState.time) <= settings.nextVideoNotificationDuration) {
diff --git a/src/routes/Player/usePlayer.js b/src/routes/Player/usePlayer.js
index 53aa84fe4..d530d78db 100644
--- a/src/routes/Player/usePlayer.js
+++ b/src/routes/Player/usePlayer.js
@@ -32,7 +32,7 @@ const map = (player) => ({
player.metaItem,
});
-const usePlayer = (urlParams, videoParams) => {
+const usePlayer = (urlParams) => {
const { core } = useServices();
const { decodeStream } = useCoreSuspender();
const stream = decodeStream(urlParams.stream);
@@ -44,7 +44,6 @@ const usePlayer = (urlParams, videoParams) => {
model: 'Player',
args: {
stream,
- videoParams,
streamRequest: typeof urlParams.streamTransportUrl === 'string' && typeof urlParams.type === 'string' && typeof urlParams.videoId === 'string' ?
{
base: urlParams.streamTransportUrl,
@@ -86,7 +85,16 @@ const usePlayer = (urlParams, videoParams) => {
action: 'Unload'
};
}
- }, [urlParams, videoParams]);
+ }, [urlParams]);
+ const videoParamsChanged = React.useCallback((videoParams) => {
+ core.transport.dispatch({
+ action: 'Player',
+ args: {
+ action: 'VideoParamsChanged',
+ args: { videoParams }
+ }
+ }, 'player');
+ }, []);
const timeChanged = React.useCallback((time, duration, device) => {
core.transport.dispatch({
action: 'Player',
@@ -114,7 +122,7 @@ const usePlayer = (urlParams, videoParams) => {
}, 'player');
}, []);
const player = useModelState({ model: 'player', action, map });
- return [player, timeChanged, pausedChanged, ended];
+ return [player, videoParamsChanged, timeChanged, pausedChanged, ended];
};
module.exports = usePlayer;
diff --git a/src/routes/Settings/Settings.js b/src/routes/Settings/Settings.js
index 2a2fdf721..25c2dcb27 100644
--- a/src/routes/Settings/Settings.js
+++ b/src/routes/Settings/Settings.js
@@ -300,6 +300,26 @@ const Settings = () => {
{ t('PRIVACY_POLICY') }
+ {
+ profile.auth !== null && profile.auth.user !== null && typeof profile.auth.user.email === 'string' ?
+
+
+
+ :
+ null
+ }
+ {
+ profile.auth !== null && profile.auth.user !== null ?
+
+
+
+ :
+ null
+ }
{ t('SETTINGS_NAV_PLAYER') }
@@ -437,8 +457,8 @@ const Settings = () => {
streamingServer.settings.type === 'Ready' ?
t('SETTINGS_SERVER_STATUS_ONLINE')
:
- streamingServer.settings.type === 'Error' ?
- `${t('SETTINGS_SERVER_STATUS_ERROR')}: (${streamingServer.settings.content})`
+ streamingServer.settings.type === 'Err' ?
+ t('SETTINGS_SERVER_STATUS_ERROR')
:
streamingServer.settings.type
}