-
-
+ {
+ addAddonModalOpen ?
+
+
+
+ :
+ null
+ }
+ {
+ typeof sharedTransportUrl === 'string' ?
+
+
+
+ :
+ null
+ }
);
};
diff --git a/src/routes/Addons/styles.less b/src/routes/Addons/styles.less
index ff3b7f2c1..f7ef52dcd 100644
--- a/src/routes/Addons/styles.less
+++ b/src/routes/Addons/styles.less
@@ -1,3 +1,7 @@
+:import('~stremio/common/Multiselect/styles.less') {
+ multiselect-menu-container: menu-container;
+}
+
.addons-container {
display: flex;
flex-direction: column;
@@ -16,11 +20,12 @@
display: flex;
flex-direction: column;
- .top-bar-container {
+ .selectable-inputs-container {
flex: none;
+ align-self: stretch;
display: flex;
flex-direction: row;
- margin: 2rem;
+ padding: 1.5rem;
overflow: visible;
.add-button-container {
@@ -30,7 +35,7 @@
align-items: center;
height: 3rem;
max-width: 15rem;
- margin-right: 1rem;
+ margin-right: 1.5rem;
padding: 0 1rem;
background-color: var(--color-signal5);
@@ -40,8 +45,8 @@
.icon {
flex: none;
- width: 1.5rem;
- height: 1.5rem;
+ width: 1.2rem;
+ height: 1.2rem;
margin-right: 1rem;
fill: var(--color-surfacelighter);
}
@@ -56,12 +61,17 @@
}
}
- .dropdown {
+ .select-input-container {
flex-grow: 0;
flex-shrink: 1;
flex-basis: 15rem;
height: 3rem;
- margin-right: 1rem;
+ margin-right: 1.5rem;
+
+ .multiselect-menu-container {
+ max-height: calc(3.2rem * 7);
+ overflow: auto;
+ }
}
.search-bar-container {
@@ -72,7 +82,6 @@
flex-direction: row;
align-items: center;
height: 3rem;
- margin-right: 1rem;
padding: 0 1rem;
background-color: var(--color-backgroundlighter);
cursor: text;
@@ -82,7 +91,7 @@
}
.icon {
- display: block;
+ flex: none;
width: 1.2rem;
height: 1.2rem;
margin-right: 1rem;
@@ -91,7 +100,6 @@
.search-input {
flex: 1;
- align-self: stretch;
color: var(--color-surfacelighter);
&::placeholder {
@@ -103,32 +111,31 @@
}
}
+ .message-container {
+ flex: 1;
+ align-self: stretch;
+ padding: 0 1.5rem;
+ font-size: 2rem;
+ color: var(--color-surfacelighter);
+ }
+
.addons-list-container {
flex: 1;
align-self: stretch;
- padding: 0 2rem;
+ padding: 0 1.5rem;
overflow-y: auto;
.addon {
- width: 100%;
- margin-bottom: 2rem;
- }
-
- .message-container {
- padding: 0 2rem;
- font-size: 2rem;
- color: var(--color-surfacelighter);
+ margin-bottom: 1.5rem;
}
}
}
}
-.add-addon-prompt-container {
- .url-content {
- flex: 1;
- width: 100%;
- padding: 0.5rem;
- font-size: 0.9rem;
+.add-addon-modal-container {
+ .addon-url-input {
+ width: 25rem;
+ padding: 0.5rem 1rem;
color: var(--color-surfacedark);
border: thin solid var(--color-surface);
}
@@ -138,8 +145,8 @@
}
}
-.addon-prompt-container {
- .cancel-button {
- background-color: var(--color-surfacedark);
+.share-modal-container {
+ .share-prompt-container {
+ width: 25rem;
}
}
\ No newline at end of file
diff --git a/src/routes/Addons/useAddonDetails.js b/src/routes/Addons/useAddonDetails.js
new file mode 100644
index 000000000..afa45eceb
--- /dev/null
+++ b/src/routes/Addons/useAddonDetails.js
@@ -0,0 +1,48 @@
+const React = require('react');
+const { useModelState } = require('stremio/common');
+
+const initAddonDetailsState = () => ({
+ descriptor: null
+});
+
+const mapAddonDetailsStateWithCtx = (addonDetails, ctx) => {
+ const descriptor = addonDetails.descriptor !== null && addonDetails.descriptor.content.type === 'Ready' ?
+ {
+ ...addonDetails.descriptor,
+ content: {
+ ...addonDetails.descriptor.content,
+ installed: ctx.content.addons.some((addon) => addon.transportUrl === addonDetails.descriptor.transport_url),
+ }
+ }
+ :
+ addonDetails.descriptor;
+ return { descriptor };
+};
+
+const useAddonDetails = (queryParams) => {
+ const loadAddonDetailsAction = React.useMemo(() => {
+ if (queryParams.has('addon')) {
+ return {
+ action: 'Load',
+ args: {
+ load: 'AddonDetails',
+ args: {
+ transport_url: queryParams.get('addon')
+ }
+ }
+ };
+ } else {
+ return {
+ action: 'Unload'
+ };
+ }
+ }, [queryParams]);
+ return useModelState({
+ model: 'addon_details',
+ action: loadAddonDetailsAction,
+ mapWithCtx: mapAddonDetailsStateWithCtx,
+ init: initAddonDetailsState,
+ });
+};
+
+module.exports = useAddonDetails;
diff --git a/src/routes/Addons/useAddons.js b/src/routes/Addons/useAddons.js
index b29b23cd4..57be65b45 100644
--- a/src/routes/Addons/useAddons.js
+++ b/src/routes/Addons/useAddons.js
@@ -15,8 +15,28 @@ const initAddonsState = () => ({
const mapAddonsStateWithCtx = (addons, ctx) => {
const selectable = addons.selectable;
- const catalog_resource = addons.catalog_resource;
- // TODO add MY catalogId replace catalog content if resource catalog id is MY
+ // TODO replace catalog content if resource catalog id is MY
+ const catalog_resource = addons.catalog_resource !== null && addons.catalog_resource.content.type === 'Ready' ?
+ {
+ ...addons.catalog_resource,
+ content: {
+ ...addons.catalog_resource.content,
+ content: addons.catalog_resource.content.content.map((descriptor) => ({
+ transportUrl: descriptor.transportUrl,
+ installed: ctx.content.addons.some((addon) => addon.transportUrl === descriptor.transportUrl),
+ manifest: {
+ id: descriptor.manifest.id,
+ name: descriptor.manifest.name,
+ version: descriptor.manifest.version,
+ logo: descriptor.manifest.logo,
+ description: descriptor.manifest.description,
+ types: descriptor.manifest.types
+ }
+ }))
+ }
+ }
+ :
+ addons.catalog_resource;
return { selectable, catalog_resource };
};
diff --git a/src/routes/Addons/useSelectableInputs.js b/src/routes/Addons/useSelectableInputs.js
index 8376fa846..1b1c4dd15 100644
--- a/src/routes/Addons/useSelectableInputs.js
+++ b/src/routes/Addons/useSelectableInputs.js
@@ -15,18 +15,6 @@ const equalWithouExtra = (request1, request2) => {
};
const mapSelectableInputs = (addons) => {
- const selectedCatalogRequest = addons.catalog_resource !== null ?
- addons.catalog_resource.request
- :
- {
- base: null,
- path: {
- resource: 'addon_catalog',
- id: null,
- type_name: null,
- extra: []
- }
- };
const catalogSelect = {
title: 'Select catalog',
options: addons.selectable.catalogs
@@ -36,7 +24,8 @@ const mapSelectableInputs = (addons) => {
})),
selected: addons.selectable.catalogs
.filter(({ load_request: { path: { id } } }) => {
- return id === selectedCatalogRequest.path.id;
+ return addons.catalog_resource !== null &&
+ addons.catalog_resource.request.path.id === id;
})
.map(({ load_request }) => JSON.stringify(load_request)),
onSelect: (event) => {
@@ -52,7 +41,8 @@ const mapSelectableInputs = (addons) => {
})),
selected: addons.selectable.types
.filter(({ load_request }) => {
- return equalWithouExtra(load_request, selectedCatalogRequest);
+ return addons.catalog_resource !== null &&
+ equalWithouExtra(addons.catalog_resource.request, load_request);
})
.map(({ load_request }) => JSON.stringify(load_request)),
onSelect: (event) => {
diff --git a/src/routes/Addons/useSelectedAddon.js b/src/routes/Addons/useSelectedAddon.js
deleted file mode 100644
index 5bffaec37..000000000
--- a/src/routes/Addons/useSelectedAddon.js
+++ /dev/null
@@ -1,35 +0,0 @@
-const React = require('react');
-const UrlUtils = require('url');
-const { routesRegexp, useLocationHash, useRouteActive } = require('stremio/common');
-
-const useSelectedAddon = (transportUrl) => {
- const [addon, setAddon] = React.useState(null);
- const locationHash = useLocationHash();
- const active = useRouteActive(routesRegexp.addons.regexp);
- React.useEffect(() => {
- if (typeof transportUrl !== 'string') {
- setAddon(null);
- return;
- }
-
- fetch(transportUrl) // TODO
- .then((resp) => resp.json())
- .then((manifest) => setAddon({ manifest, transportUrl, flags: {} }));
- }, [transportUrl]);
- const clear = React.useCallback(() => {
- if (active) {
- const { pathname, search } = UrlUtils.parse(locationHash.slice(1));
- const queryParams = new URLSearchParams(search || '');
- queryParams.delete('addon');
- if ([...queryParams].length !== 0) {
- window.location.replace(`#${pathname}?${queryParams.toString()}`);
- } else {
- window.location.replace(`#${pathname}`);
- }
- setAddon(null);
- }
- }, [active, locationHash]);
- return [addon, clear, setAddon];
-};
-
-module.exports = useSelectedAddon;
diff --git a/src/routes/MetaDetails/MetaDetails.js b/src/routes/MetaDetails/MetaDetails.js
index 16417e77a..42221f5a8 100644
--- a/src/routes/MetaDetails/MetaDetails.js
+++ b/src/routes/MetaDetails/MetaDetails.js
@@ -12,7 +12,20 @@ const MetaDetails = ({ urlParams }) => {
const [metaResourceRef, metaResources, selectedMetaResource] = useSelectableResource(metaDetails.selected.meta_resource_ref, metaDetails.meta_resources);
const streamsResourceRef = metaDetails.selected.streams_resource_ref;
const streamsResources = metaDetails.streams_resources;
- const [inLibrary, , , toggleInLibrary] = useInLibrary(metaResourceRef !== null ? metaResourceRef.id : null);
+ const metaItem = React.useMemo(() => {
+ return selectedMetaResource !== null ?
+ selectedMetaResource.content.content
+ :
+ metaResourceRef !== null ?
+ {
+ id: metaResourceRef.id,
+ type: metaResourceRef.type_name,
+ name: ''
+ }
+ :
+ null;
+ }, [metaResourceRef, selectedMetaResource]);
+ const [inLibrary, toggleInLibrary] = useInLibrary(metaItem);
return (