mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-03-11 13:05:48 +00:00
Merge branch 'development' of https://github.com/Stremio/stremio-web into development
Some checks are pending
Build / build (push) Waiting to run
Some checks are pending
Build / build (push) Waiting to run
This commit is contained in:
commit
54b017c39f
6 changed files with 60 additions and 4 deletions
|
|
@ -8,6 +8,7 @@ const { default: Icon } = require('@stremio/stremio-icons/react');
|
|||
const { usePlatform, useBinaryState, withCoreSuspender } = require('stremio/common');
|
||||
const { AddonDetailsModal, Button, Image, MainNavBars, ModalDialog, SearchBar, SharePrompt, TextInput, MultiselectMenu } = require('stremio/components');
|
||||
const { useServices } = require('stremio/services');
|
||||
const useToast = require('stremio/common/Toast/useToast');
|
||||
const Addon = require('./Addon');
|
||||
const useInstalledAddons = require('./useInstalledAddons');
|
||||
const useRemoteAddons = require('./useRemoteAddons');
|
||||
|
|
@ -20,6 +21,7 @@ const Addons = ({ urlParams, queryParams }) => {
|
|||
const { t } = useTranslation();
|
||||
const platform = usePlatform();
|
||||
const { core } = useServices();
|
||||
const toast = useToast();
|
||||
const installedAddons = useInstalledAddons(urlParams);
|
||||
const remoteAddons = useRemoteAddons(urlParams);
|
||||
const [addonDetailsTransportUrl, setAddonDetailsTransportUrl] = useAddonDetailsTransportUrl(urlParams, queryParams);
|
||||
|
|
@ -29,7 +31,17 @@ const Addons = ({ urlParams, queryParams }) => {
|
|||
const addAddonUrlInputRef = React.useRef(null);
|
||||
const addAddonOnSubmit = React.useCallback(() => {
|
||||
if (addAddonUrlInputRef.current !== null) {
|
||||
setAddonDetailsTransportUrl(addAddonUrlInputRef.current.value);
|
||||
try {
|
||||
let url = new URL(addAddonUrlInputRef.current.value).toString();
|
||||
setAddonDetailsTransportUrl(url);
|
||||
} catch (e) {
|
||||
toast.show({
|
||||
type: 'error',
|
||||
title: `Failed to parse addon url: ${addAddonUrlInputRef.current.value}`,
|
||||
timeout: 10000
|
||||
});
|
||||
console.error('Failed to parse addon url:', e);
|
||||
}
|
||||
}
|
||||
}, [setAddonDetailsTransportUrl]);
|
||||
const addAddonModalButtons = React.useMemo(() => {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ const EpisodePicker = ({ className, onSubmit }: Props) => {
|
|||
|
||||
const { initialSeason, initialEpisode } = useMemo(() => {
|
||||
const splitPath = window.location.hash.split('/');
|
||||
if (splitPath[splitPath.length - 1] === '') {
|
||||
splitPath.pop();
|
||||
}
|
||||
const videoId = decodeURIComponent(splitPath[splitPath.length - 1]);
|
||||
const [, pathSeason, pathEpisode] = videoId ? videoId.split(':') : [];
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,11 @@ const MetaDetails = ({ urlParams, queryParams }) => {
|
|||
const handleEpisodeSearch = React.useCallback((season, episode) => {
|
||||
const searchVideoHash = encodeURIComponent(`${urlParams.id}:${season}:${episode}`);
|
||||
const url = window.location.hash;
|
||||
const searchVideoPath = url.replace(encodeURIComponent(urlParams.videoId), searchVideoHash);
|
||||
|
||||
const searchVideoPath = (urlParams.videoId === undefined || urlParams.videoId === null || urlParams.videoId === '') ?
|
||||
url + (!url.endsWith('/') ? '/' : '') + searchVideoHash
|
||||
: url.replace(encodeURIComponent(urlParams.videoId), searchVideoHash);
|
||||
|
||||
window.location = searchVideoPath;
|
||||
}, [urlParams, window.location]);
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ const Stream = ({ className, videoId, videoReleased, addonName, name, descriptio
|
|||
}, [href, deepLinks]);
|
||||
|
||||
const streamLink = React.useMemo(() => {
|
||||
return deepLinks?.externalPlayer?.streaming;
|
||||
}, [deepLinks]);
|
||||
|
||||
const downloadLink = React.useMemo(() => {
|
||||
return deepLinks?.externalPlayer?.download;
|
||||
}, [deepLinks]);
|
||||
|
||||
|
|
@ -116,6 +120,28 @@ const Stream = ({ className, videoId, videoReleased, addonName, name, descriptio
|
|||
}
|
||||
}, [props.onClick, profile.settings, markVideoAsWatched]);
|
||||
|
||||
const copyDownloadLink = React.useCallback((event) => {
|
||||
event.preventDefault();
|
||||
closeMenu();
|
||||
if (downloadLink) {
|
||||
navigator.clipboard.writeText(downloadLink)
|
||||
.then(() => {
|
||||
toast.show({
|
||||
type: 'success',
|
||||
title: t('PLAYER_COPY_DOWNLOAD_LINK_SUCCESS'),
|
||||
timeout: 4000
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
toast.show({
|
||||
type: 'error',
|
||||
title: t('PLAYER_COPY_DOWNLOAD_LINK_ERROR'),
|
||||
timeout: 4000,
|
||||
});
|
||||
});
|
||||
}
|
||||
}, [downloadLink]);
|
||||
|
||||
const copyStreamLink = React.useCallback((event) => {
|
||||
event.preventDefault();
|
||||
closeMenu();
|
||||
|
|
@ -195,6 +221,13 @@ const Stream = ({ className, videoId, videoReleased, addonName, name, descriptio
|
|||
<div className={styles['context-menu-option-label']}>{t('CTX_COPY_STREAM_LINK')}</div>
|
||||
</Button>
|
||||
}
|
||||
{
|
||||
downloadLink &&
|
||||
<Button className={styles['context-menu-option-container']} title={t('CTX_DOWNLOAD_VIDEO')} onClick={copyDownloadLink}>
|
||||
<Icon className={styles['menu-icon']} name={'download'} />
|
||||
<div className={styles['context-menu-option-label']}>{t('CTX_COPY_VIDEO_DOWNLOAD_LINK')}</div>
|
||||
</Button>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}, [copyStreamLink, onClick]);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ const useMetaDetails = (urlParams) => {
|
|||
id: urlParams.id,
|
||||
extra: []
|
||||
},
|
||||
streamPath: typeof urlParams.videoId === 'string' ?
|
||||
streamPath: typeof urlParams.videoId === 'string' && urlParams.videoId !== '' ?
|
||||
{
|
||||
resource: 'stream',
|
||||
type: urlParams.type,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ const useSeason = (urlParams, queryParams) => {
|
|||
const setSeason = React.useCallback((season) => {
|
||||
const nextQueryParams = new URLSearchParams(queryParams);
|
||||
nextQueryParams.set('season', season);
|
||||
window.location.replace(`#${urlParams.path}?${nextQueryParams}`);
|
||||
const path = urlParams.path.endsWith('/') ?
|
||||
urlParams.path.slice(0, -1):
|
||||
urlParams.path;
|
||||
|
||||
window.location.replace(`#${path}?${nextQueryParams}`);
|
||||
}, [urlParams, queryParams]);
|
||||
return [season, setSeason];
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue