diff --git a/src/common/CONSTANTS.js b/src/common/CONSTANTS.js
index 2bbf49f94..f5702fd4e 100644
--- a/src/common/CONSTANTS.js
+++ b/src/common/CONSTANTS.js
@@ -7,6 +7,7 @@ const CATALOG_PREVIEW_SIZE = 10;
const CATALOG_PAGE_SIZE = 100;
const NONE_EXTRA_VALUE = 'None';
const SKIP_EXTRA_NAME = 'skip';
+const META_LINK_CATEGORY = 'meta';
const IMDB_LINK_CATEGORY = 'imdb';
const SHARE_LINK_CATEGORY = 'share';
const TYPE_PRIORITIES = {
@@ -31,6 +32,7 @@ module.exports = {
CATALOG_PAGE_SIZE,
NONE_EXTRA_VALUE,
SKIP_EXTRA_NAME,
+ META_LINK_CATEGORY,
IMDB_LINK_CATEGORY,
SHARE_LINK_CATEGORY,
TYPE_PRIORITIES
diff --git a/src/common/MetaPreview/MetaPreview.js b/src/common/MetaPreview/MetaPreview.js
index a1cae3a77..b5f96c0a5 100644
--- a/src/common/MetaPreview/MetaPreview.js
+++ b/src/common/MetaPreview/MetaPreview.js
@@ -27,43 +27,44 @@ const ALLOWED_LINK_REDIRECTS = [
const MetaPreview = ({ className, compact, name, logo, background, runtime, releaseInfo, released, description, links, trailer, inLibrary, toggleInLibrary }) => {
const [shareModalOpen, openShareModal, closeShareModal] = useBinaryState(false);
const linksGroups = React.useMemo(() => {
- return Array.isArray(links) ?
- links
- .filter((link) => link && typeof link.category === 'string' && typeof link.url === 'string')
- .reduce((linksGroups, { category, name, url }) => {
- if (category === CONSTANTS.IMDB_LINK_CATEGORY) {
- linksGroups[category] = {
- label: name,
- href: `https://www.stremio.com/warning#${encodeURIComponent(`https://www.imdb.com/title/${encodeURIComponent(url)}`)}`
- };
- } else if (category === CONSTANTS.SHARE_LINK_CATEGORY) {
- linksGroups[category] = {
- label: name,
- href: url
- };
- } else {
- const { protocol, host, path, pathname } = UrlUtils.parse(url);
- if (protocol === 'stremio:') {
- if (ALLOWED_LINK_REDIRECTS.some((regexp) => pathname.match(regexp))) {
- linksGroups[category] = linksGroups[category] || [];
- linksGroups[category].push({
- label: name,
- href: `#${path}`
- });
+ return links
+ .filter((link) => link && typeof link.category === 'string' && typeof link.url === 'string')
+ .reduce((linksGroups, { category, name, url }) => {
+ if (category === CONSTANTS.IMDB_LINK_CATEGORY) {
+ linksGroups.set(category, {
+ label: name,
+ href: `https://www.stremio.com/warning#${encodeURIComponent(`https://www.imdb.com/title/${encodeURIComponent(url)}`)}`
+ });
+ } else if (category === CONSTANTS.SHARE_LINK_CATEGORY) {
+ linksGroups.set(category, {
+ label: name,
+ href: url
+ });
+ } else {
+ const { protocol, host, path, pathname } = UrlUtils.parse(url);
+ if (protocol === 'stremio:') {
+ if (pathname !== null && ALLOWED_LINK_REDIRECTS.some((regexp) => pathname.match(regexp))) {
+ if (!linksGroups.has(category)) {
+ linksGroups.set(category, []);
}
- } else if (typeof host === 'string' && host.length > 0) {
- linksGroups[category] = linksGroups[category] || [];
- linksGroups[category].push({
+ linksGroups.get(category).push({
label: name,
- href: `https://www.stremio.com/warning#${encodeURIComponent(url)}`
+ href: `#${path}`
});
}
+ } else if (typeof host === 'string' && host.length > 0) {
+ if (!linksGroups.has(category)) {
+ linksGroups.set(category, []);
+ }
+ linksGroups.get(category).push({
+ label: name,
+ href: `https://www.stremio.com/warning#${encodeURIComponent(url)}`
+ });
}
+ }
- return linksGroups;
- }, {})
- :
- [];
+ return linksGroups;
+ }, new Map());
}, [links]);
const trailerHref = React.useMemo(() => {
if (typeof trailer !== 'object' || trailer === null) {
@@ -99,7 +100,7 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
null
}
{
- (typeof releaseInfo === 'string' && releaseInfo.length > 0) || (released instanceof Date && !isNaN(released.getTime())) || (typeof runtime === 'string' && runtime.length > 0) || typeof linksGroups[CONSTANTS.IMDB_LINK_CATEGORY] === 'object' ?
+ (typeof releaseInfo === 'string' && releaseInfo.length > 0) || (released instanceof Date && !isNaN(released.getTime())) || (typeof runtime === 'string' && runtime.length > 0) || linksGroups.has(CONSTANTS.IMDB_LINK_CATEGORY) ?
{
typeof runtime === 'string' && runtime.length > 0 ?
@@ -117,16 +118,16 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
null
}
{
- typeof linksGroups[CONSTANTS.IMDB_LINK_CATEGORY] === 'object' ?
+ linksGroups.has(CONSTANTS.IMDB_LINK_CATEGORY) ?
:
null
@@ -150,7 +151,7 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
null
}
{
- Object.keys(linksGroups)
+ Array.from(linksGroups.keys())
.filter((category) => {
return category !== CONSTANTS.IMDB_LINK_CATEGORY &&
category !== CONSTANTS.SHARE_LINK_CATEGORY;
@@ -160,7 +161,7 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
key={index}
className={styles['meta-links']}
label={category}
- links={linksGroups[category]}
+ links={linksGroups.get(category)}
/>
))
}
@@ -191,7 +192,7 @@ const MetaPreview = ({ className, compact, name, logo, background, runtime, rele
null
}
{
- typeof linksGroups[CONSTANTS.SHARE_LINK_CATEGORY] === 'object' ?
+ linksGroups.has(CONSTANTS.SHARE_LINK_CATEGORY) ?
:
diff --git a/src/common/deepLinking.js b/src/common/deepLinking.js
index f90bc1436..beff1431a 100644
--- a/src/common/deepLinking.js
+++ b/src/common/deepLinking.js
@@ -23,17 +23,6 @@ const withMetaItem = ({ metaItem }) => {
};
};
-const withMetaResource = ({ metaResource, type, id, videoId }) => {
- const queryParams = new URLSearchParams([['metaTransportUrl', metaResource.request.base]]);
- return {
- meta_details_videos: `#/metadetails/${encodeURIComponent(type)}/${encodeURIComponent(id)}?${queryParams.toString()}`,
- meta_details_streams: typeof videoId === 'string' ?
- `#/metadetails/${encodeURIComponent(type)}/${encodeURIComponent(id)}/${encodeURIComponent(videoId)}?${queryParams.toString()}`
- :
- null
- };
-};
-
const withLibItem = ({ libItem, streams = {} }) => {
const [stream, streamTransportUrl, metaTransportUrl] = typeof libItem.state.video_id === 'string' && typeof streams[`${encodeURIComponent(libItem._id)}/${encodeURIComponent(libItem.state.video_id)}`] === 'object' ?
streams[`${encodeURIComponent(libItem._id)}/${encodeURIComponent(libItem.state.video_id)}`]
@@ -60,13 +49,12 @@ const withLibItem = ({ libItem, streams = {} }) => {
};
const withVideo = ({ video, metaTransportUrl, metaItem, streams = {} }) => {
- const queryParams = new URLSearchParams([['metaTransportUrl', metaTransportUrl]]);
const [stream, streamTransportUrl] = typeof streams[`${encodeURIComponent(metaItem.id)}/${encodeURIComponent(video.id)}`] === 'object' ?
streams[`${encodeURIComponent(metaItem.id)}/${encodeURIComponent(video.id)}`]
:
[];
return {
- meta_details_streams: `#/metadetails/${encodeURIComponent(metaItem.type)}/${encodeURIComponent(metaItem.id)}/${encodeURIComponent(video.id)}?${queryParams.toString()}`,
+ meta_details_streams: `#/metadetails/${encodeURIComponent(metaItem.type)}/${encodeURIComponent(metaItem.id)}/${encodeURIComponent(video.id)}`,
// TODO check if stream is external
player: typeof stream === 'object' && typeof streamTransportUrl === 'string' ?
`#/player/${encodeURIComponent(serializeStream(stream))}/${encodeURIComponent(streamTransportUrl)}/${encodeURIComponent(metaTransportUrl)}/${encodeURIComponent(metaItem.type)}/${encodeURIComponent(metaItem.id)}/${encodeURIComponent(video.id)}`
@@ -96,7 +84,6 @@ const withCatalog = ({ request }) => {
module.exports = {
withCatalog,
withMetaItem,
- withMetaResource,
withLibItem,
withVideo,
withStream,
diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js
index 11404fa02..23d058142 100644
--- a/src/routes/Intro/Intro.js
+++ b/src/routes/Intro/Intro.js
@@ -277,23 +277,20 @@ const Intro = ({ queryParams }) => {
};
}, [routeFocused]);
React.useEffect(() => {
- var initScriptElement = document.createElement('script');
- var sdkScriptElement = document.createElement('script');
- initScriptElement.innerHTML = `window.fbAsyncInit = function() {
- FB.init({
- appId: '1537119779906825',
- autoLogAppEvents: false,
- xfbml: false,
- version: 'v2.5'
- });
- };`;
+ window.fbAsyncInit = function() {
+ FB.init({
+ appId: '1537119779906825',
+ autoLogAppEvents: false,
+ xfbml: false,
+ version: 'v2.5'
+ });
+ };
+ const sdkScriptElement = document.createElement('script');
sdkScriptElement.src = 'https://connect.facebook.net/en_US/sdk.js';
sdkScriptElement.async = true;
sdkScriptElement.defer = true;
- document.body.appendChild(initScriptElement);
document.body.appendChild(sdkScriptElement);
return () => {
- document.body.removeChild(initScriptElement);
document.body.removeChild(sdkScriptElement);
};
}, []);
diff --git a/src/routes/MetaDetails/MetaDetails.js b/src/routes/MetaDetails/MetaDetails.js
index 5c8c25789..ecda0105a 100644
--- a/src/routes/MetaDetails/MetaDetails.js
+++ b/src/routes/MetaDetails/MetaDetails.js
@@ -2,35 +2,41 @@
const React = require('react');
const PropTypes = require('prop-types');
-const { VerticalNavBar, HorizontalNavBar, MetaPreview, Image, useInLibrary } = require('stremio/common');
+const { VerticalNavBar, HorizontalNavBar, MetaPreview, ModalDialog, Image, useInLibrary } = require('stremio/common');
const StreamsList = require('./StreamsList');
const VideosList = require('./VideosList');
const useMetaDetails = require('./useMetaDetails');
+const useMetaExtensions = require('./useMetaExtensions');
const styles = require('./styles');
const MetaDetails = ({ urlParams, queryParams }) => {
const metaDetails = useMetaDetails(urlParams);
+ const { tabs, selectedMetaExtension, clearSelectedMetaExtension } = useMetaExtensions(metaDetails.meta_resources);
const metaResourceRef = React.useMemo(() => {
return metaDetails.selected !== null ? metaDetails.selected.meta_resources_ref : null;
}, [metaDetails.selected]);
- const selectedAddon = queryParams.get('metaTransportUrl');
const selectedMetaResource = React.useMemo(() => {
return metaDetails.meta_resources.reduceRight((result, metaResource) => {
- if (typeof selectedAddon === 'string') {
- if (metaResource.request.base === selectedAddon) {
- return metaResource;
- }
- } else if (metaResource.content.type === 'Ready') {
+ if (metaResource.content.type === 'Ready') {
return metaResource;
}
return result;
}, null);
- }, [metaDetails, selectedAddon]);
+ }, [metaDetails]);
const streamsResourceRef = metaDetails.selected !== null ? metaDetails.selected.streams_resource_ref : null;
const streamsResources = metaDetails.streams_resources;
+ const seasonQueryParam = React.useMemo(() => {
+ return queryParams.has('season') && !isNaN(queryParams.get('season')) ?
+ parseInt(queryParams.get('season'))
+ :
+ null;
+ }, [queryParams]);
+ const seasonOnSelect = React.useCallback((event) => {
+ window.location.replace(`#/metadetails/${selectedMetaResource.request.path.type_name}/${selectedMetaResource.request.path.id}?season=${event.value}`);
+ }, [selectedMetaResource]);
const selectedVideo = React.useMemo(() => {
- return streamsResourceRef !== null && selectedMetaResource !== null && selectedMetaResource.content.type === 'Ready' ?
+ return streamsResourceRef !== null && selectedMetaResource !== null ?
selectedMetaResource.content.content.videos.reduce((result, video) => {
if (video.id === streamsResourceRef.id) {
return video;
@@ -41,30 +47,21 @@ const MetaDetails = ({ urlParams, queryParams }) => {
:
null;
}, [selectedMetaResource, streamsResourceRef]);
- const tabs = React.useMemo(() => {
- return metaDetails.meta_resources.map((metaResource) => ({
- id: metaResource.addon.transportUrl,
- label: metaResource.addon.manifest.name,
- logo: metaResource.addon.manifest.logo,
- icon: 'ic_addons',
- href: metaResource.deepLinks.meta_details_streams !== null ? metaResource.deepLinks.meta_details_streams : metaResource.deepLinks.meta_details_videos
- }));
- }, [metaDetails]);
- const [inLibrary, toggleInLibrary] = useInLibrary(selectedMetaResource !== null && selectedMetaResource.content.type === 'Ready' ? selectedMetaResource.content.content : null);
+ const [inLibrary, toggleInLibrary] = useInLibrary(selectedMetaResource !== null ? selectedMetaResource.content.content : null);
return (
{
- metaDetails.meta_resources.length > 0 ?
+ tabs.length > 0 ?
:
null
@@ -88,7 +85,7 @@ const MetaDetails = ({ urlParams, queryParams }) => {
No metadata was found!
:
- selectedMetaResource !== null && selectedMetaResource.content.type === 'Ready' ?
+ selectedMetaResource !== null ?
{
typeof selectedMetaResource.content.content.background === 'string' &&
@@ -137,11 +134,28 @@ const MetaDetails = ({ urlParams, queryParams }) => {
:
null
}
+ {
+ selectedMetaExtension !== null ?
+
+
+
+ :
+ null
+ }
);
};
diff --git a/src/routes/MetaDetails/StreamsList/Stream/styles.less b/src/routes/MetaDetails/StreamsList/Stream/styles.less
index fe0e6aec6..3b2126558 100644
--- a/src/routes/MetaDetails/StreamsList/Stream/styles.less
+++ b/src/routes/MetaDetails/StreamsList/Stream/styles.less
@@ -63,6 +63,7 @@
flex: 1;
max-height: 3.6em;
margin: 0.5rem 1rem;
+ white-space: pre;
color: @color-surface-light5-90;
}
diff --git a/src/routes/MetaDetails/VideosList/VideosList.js b/src/routes/MetaDetails/VideosList/VideosList.js
index 5ea7e8b5c..a6a53ed35 100644
--- a/src/routes/MetaDetails/VideosList/VideosList.js
+++ b/src/routes/MetaDetails/VideosList/VideosList.js
@@ -7,20 +7,44 @@ const Image = require('stremio/common/Image');
const SearchBar = require('stremio/common/SearchBar');
const SeasonsBar = require('./SeasonsBar');
const Video = require('./Video');
-const useSelectableSeasons = require('./useSelectableSeasons');
const styles = require('./styles');
-const VideosList = ({ className, metaResource }) => {
+const VideosList = ({ className, metaResource, season, seasonOnSelect }) => {
const videos = React.useMemo(() => {
return metaResource && metaResource.content.type === 'Ready' ?
metaResource.content.content.videos
:
[];
}, [metaResource]);
- const [seasons, selectedSeason, videosForSeason, selectSeason] = useSelectableSeasons(videos);
- const seasonOnSelect = React.useCallback((event) => {
- selectSeason(event.value);
- }, []);
+ const seasons = React.useMemo(() => {
+ return videos
+ .map(({ season }) => season)
+ .filter((season, index, seasons) => {
+ return season !== null &&
+ !isNaN(season) &&
+ typeof season === 'number' &&
+ seasons.indexOf(season) === index;
+ })
+ .sort((a, b) => a - b);
+ }, [videos]);
+ const selectedSeason = React.useMemo(() => {
+ return seasons.includes(season) ?
+ season
+ :
+ seasons.length > 0 ?
+ seasons[seasons.length - 1]
+ :
+ null;
+ }, [seasons, season]);
+ const videosForSeason = React.useMemo(() => {
+ return videos
+ .filter((video) => {
+ return selectedSeason === null || video.season === selectedSeason;
+ })
+ .sort((a, b) => {
+ return a.episode - b.episode;
+ });
+ }, [videos, selectedSeason]);
const [search, setSearch] = React.useState('');
const searchInputOnChange = React.useCallback((event) => {
setSearch(event.currentTarget.value);
@@ -88,7 +112,9 @@ const VideosList = ({ className, metaResource }) => {
VideosList.propTypes = {
className: PropTypes.string,
- metaResource: PropTypes.object
+ metaResource: PropTypes.object,
+ season: PropTypes.number,
+ seasonOnSelect: PropTypes.func
};
module.exports = VideosList;
diff --git a/src/routes/MetaDetails/VideosList/useSelectableSeasons.js b/src/routes/MetaDetails/VideosList/useSelectableSeasons.js
deleted file mode 100644
index 295611022..000000000
--- a/src/routes/MetaDetails/VideosList/useSelectableSeasons.js
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2017-2020 Smart code 203358507
-
-const React = require('react');
-
-const reducer = (state, action) => {
- switch (action.type) {
- case 'videos-changed': {
- const seasons = action.videos
- .map(({ season }) => season)
- .filter((season, index, seasons) => {
- return season !== null &&
- !isNaN(season) &&
- typeof season === 'number' &&
- seasons.indexOf(season) === index;
- })
- .sort((a, b) => a - b);
- const selectedSeason = seasons.includes(state.selectedSeason) ?
- state.selectedSeason
- :
- seasons.length > 0 ?
- seasons[0]
- :
- null;
- return {
- ...state,
- videos: action.videos,
- seasons,
- selectedSeason
- };
- }
- case 'season-changed': {
- const selectedSeason = state.seasons.includes(action.season) ?
- action.season
- :
- state.season;
- return {
- ...state,
- selectedSeason
- };
- }
- default: {
- return state;
- }
- }
-};
-
-const initializer = (videos) => {
- const initialState = {
- videos: [],
- seasons: [],
- selectedSeason: null
- };
- const initAction = {
- type: 'videos-changed',
- videos
- };
-
- return reducer(initialState, initAction);
-};
-
-const useSelectableSeasons = (videos) => {
- const [state, dispatch] = React.useReducer(
- reducer,
- videos,
- initializer
- );
- const selectSeason = React.useCallback((season) => {
- dispatch({
- type: 'season-changed',
- season
- });
- }, []);
- const videosForSeason = React.useMemo(() => {
- return state.videos
- .filter((video) => {
- return state.selectedSeason === null || video.season === state.selectedSeason;
- })
- .sort((a, b) => {
- return a.episode - b.episode;
- });
- }, [state.videos, state.selectedSeason]);
- React.useEffect(() => {
- dispatch({
- type: 'videos-changed',
- videos
- });
- }, [videos]);
- return [state.seasons, state.selectedSeason, videosForSeason, selectSeason];
-};
-
-module.exports = useSelectableSeasons;
diff --git a/src/routes/MetaDetails/styles.less b/src/routes/MetaDetails/styles.less
index 295166dde..4949c3eb5 100644
--- a/src/routes/MetaDetails/styles.less
+++ b/src/routes/MetaDetails/styles.less
@@ -7,6 +7,11 @@
meta-info-container: meta-info-container;
}
+:import('~stremio/common/ModalDialog/styles.less') {
+ modal-dialog-container: modal-dialog-container;
+ title-modal-container: title-container;
+}
+
.metadetails-container {
display: flex;
flex-direction: column;
@@ -104,4 +109,20 @@
background-color: @color-background-dark5-70;
}
}
+}
+
+.meta-extension-modal-container {
+ .modal-dialog-container {
+ width: 80%;
+ height: 80%;
+
+ .title-modal-container {
+ max-height: 1.2em;
+ }
+
+ .meta-extension-modal-iframe {
+ width: 100%;
+ height: 100%;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/routes/MetaDetails/useMetaDetails.js b/src/routes/MetaDetails/useMetaDetails.js
index 6f2a6722c..a64f3d6ac 100644
--- a/src/routes/MetaDetails/useMetaDetails.js
+++ b/src/routes/MetaDetails/useMetaDetails.js
@@ -1,7 +1,7 @@
// Copyright (C) 2017-2020 Smart code 203358507
const React = require('react');
-const { deepLinking, useModelState } = require('stremio/common');
+const { CONSTANTS, deepLinking, useModelState } = require('stremio/common');
const initMetaDetailsState = () => ({
selected: null,
@@ -12,10 +12,10 @@ const initMetaDetailsState = () => ({
const mapMetaDetailsStateWithCtx = (meta_details, ctx) => {
const selected = meta_details.selected;
const meta_resources = meta_details.meta_resources.map((meta_resource) => {
- return {
- request: meta_resource.request,
- content: meta_resource.content.type === 'Ready' ?
- {
+ return meta_resource.content.type === 'Ready' ?
+ {
+ request: meta_resource.request,
+ content: {
type: 'Ready',
content: {
...meta_resource.content.content,
@@ -33,34 +33,27 @@ const mapMetaDetailsStateWithCtx = (meta_details, ctx) => {
:
NaN
),
+ upcoming: Date.parse(video.released) > Date.now(),
// TODO add watched and progress
deepLinks: deepLinking.withVideo({
video,
metaTransportUrl: meta_resource.request.base,
metaItem: meta_resource.content.content
})
- }))
+ })),
+ metaExtensions: meta_resource.content.content.links.filter((link) => link.category === CONSTANTS.META_LINK_CATEGORY)
+ }
+ },
+ addon: ctx.profile.addons.reduce((result, addon) => {
+ if (addon.transportUrl === meta_resource.request.base) {
+ return addon;
}
- }
- :
- meta_resource.content,
- deepLinks: meta_details.selected !== null ?
- deepLinking.withMetaResource({
- metaResource: meta_resource,
- type: meta_details.selected.meta_resource_ref.type_name,
- id: meta_details.selected.meta_resource_ref.id,
- videoId: meta_details.selected.streams_resource_ref !== null ? meta_details.selected.streams_resource_ref.id : null
- })
- :
- null,
- addon: ctx.profile.addons.reduce((result, addon) => {
- if (addon.transportUrl === meta_resource.request.base) {
- return addon;
- }
- return result;
- }, null)
- };
+ return result;
+ }, null)
+ }
+ :
+ meta_resource;
});
const streams_resources = meta_details.streams_resources.map((stream_resource) => {
return stream_resource.content.type === 'Ready' ?
diff --git a/src/routes/MetaDetails/useMetaExtensions.js b/src/routes/MetaDetails/useMetaExtensions.js
new file mode 100644
index 000000000..c2ccca389
--- /dev/null
+++ b/src/routes/MetaDetails/useMetaExtensions.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2017-2020 Smart code 203358507
+
+const React = require('react');
+
+const useMetaExtensions = (metaResources) => {
+ const tabs = React.useMemo(() => {
+ return metaResources.filter((metaResource) => metaResource.content.type === 'Ready' && metaResource.content.content.metaExtensions.length > 0 && metaResource.addon !== null)
+ .map((metaResource) => {
+ return metaResource.content.content.metaExtensions.map((metaExtension) => (
+ {
+ id: metaExtension.url,
+ label: metaResource.addon.manifest.name,
+ logo: metaResource.addon.manifest.logo,
+ icon: 'ic_addons',
+ onClick: () => { setSelectedMetaExtension(metaExtension); }
+ }
+ ));
+ })
+ .flat(2)
+ .filter((tab, index, tabs) => tabs.findIndex((_tab) => _tab.id === tab.id) === index);
+ }, [metaResources]);
+ const [selectedMetaExtension, setSelectedMetaExtension] = React.useState(null);
+ const clearSelectedMetaExtension = React.useCallback(() => {
+ setSelectedMetaExtension(null);
+ }, []);
+ return { tabs, selectedMetaExtension, clearSelectedMetaExtension };
+};
+
+module.exports = useMetaExtensions;
diff --git a/tests/hooks.spec.js b/tests/hooks.spec.js
deleted file mode 100644
index 916402c56..000000000
--- a/tests/hooks.spec.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2017-2020 Smart code 203358507
-
-const { renderHook, act } = require('@testing-library/react-hooks');
-const useSelectableSeasons = require('../src/routes/MetaDetails/VideosList/useSelectableSeasons');
-
-const videos = [{ 'season': 4 }, { 'season': 5 }, { 'season': 4 }, { 'season': 7 }];
-
-describe('hooks tests', () => {
- describe('useSelectableSeasons hook', () => {
- it('match 4', async () => {
- const { result } = renderHook(() => useSelectableSeasons(videos));
- const [, selectedSeason] = result.current;
- expect(selectedSeason).toBe(4);
- });
-
- it('match 5', async () => {
- const { result } = renderHook(() => useSelectableSeasons(videos));
-
- act(() => {
- const [, , , selectSeason] = result.current;
- selectSeason(5);
- });
-
- const [, selectedSeason] = result.current;
- expect(selectedSeason).toBe(5);
- });
-
- it('not match 6', async () => {
- const { result } = renderHook(() => useSelectableSeasons(videos));
-
- act(() => {
- const [, , , selectSeason] = result.current;
- selectSeason(6);
- });
-
- const [, selectedSeason] = result.current;
- expect(selectedSeason).toBe(undefined);
- });
-
- it('not match $', async () => {
- const { result } = renderHook(() => useSelectableSeasons(videos));
-
- act(() => {
- const [, , , selectSeason] = result.current;
- selectSeason('$');
- });
-
- const [, selectedSeason] = result.current;
- expect(selectedSeason).toBe(undefined);
- });
- });
-});