diff --git a/src/routes/Addons/Addon/Addon.js b/src/routes/Addons/Addon/Addon.js index 023c17732..d646ed2b9 100644 --- a/src/routes/Addons/Addon/Addon.js +++ b/src/routes/Addons/Addon/Addon.js @@ -2,24 +2,54 @@ const React = require('react'); const PropTypes = require('prop-types'); const classnames = require('classnames'); const Icon = require('stremio-icons/dom'); -const { Button } = require('stremio/common'); +const { Button, Image } = require('stremio/common'); const styles = require('./styles'); -const Addon = ({ className, id, name, logo, description, types, version, transportUrl, installed, toggle, onShareButtonClicked }) => { - const onKeyUp = React.useCallback((event) => { - if (event.key === 'Enter' && typeof toggle === 'function') { - toggle(event); +const Addon = ({ className, id, name, version, logo, description, types, installed, onToggle, onShare, dataset }) => { + const toggleButtonOnClick = React.useCallback((event) => { + if (typeof onToggle === 'function') { + onToggle({ + type: 'toggle', + nativeEvent: event.nativeEvent, + reactEvent: event, + dataset: dataset + }); } - }, [toggle]); + }, [onToggle, dataset]); + const shareButtonOnClick = React.useCallback((event) => { + if (typeof onShare === 'function') { + onShare({ + type: 'share', + nativeEvent: event.nativeEvent, + reactEvent: event, + dataset: dataset + }); + } + }, [onShare, dataset]); + const onKeyDown = React.useCallback((event) => { + if (event.key === 'Enter' && typeof onToggle === 'function') { + onToggle({ + type: 'toggle', + nativeEvent: event.nativeEvent, + reactEvent: event, + dataset: dataset + }); + } + }, [onToggle, dataset]); + const renderLogoFallback = React.useMemo(() => () => { + return ( + + ); + }, []); return ( - - @@ -68,14 +98,14 @@ Addon.propTypes = { className: PropTypes.string, id: PropTypes.string, name: PropTypes.string, + version: PropTypes.string, logo: PropTypes.string, description: PropTypes.string, types: PropTypes.arrayOf(PropTypes.string), - version: PropTypes.string, - transportUrl: PropTypes.string, installed: PropTypes.bool, - toggle: PropTypes.func, - onShareButtonClicked: PropTypes.func + onToggle: PropTypes.func, + onShare: PropTypes.func, + dataset: PropTypes.objectOf(PropTypes.string) }; module.exports = Addon; diff --git a/src/routes/Addons/Addon/styles.less b/src/routes/Addons/Addon/styles.less index 2ae172544..e57eea428 100644 --- a/src/routes/Addons/Addon/styles.less +++ b/src/routes/Addons/Addon/styles.less @@ -1,7 +1,6 @@ .addon-container { display: flex; flex-direction: row; - flex-wrap: wrap; align-items: flex-start; padding: 1rem; background-color: var(--color-backgroundlighter); @@ -17,6 +16,7 @@ display: block; width: 100%; height: 100%; + padding: 0.5rem; object-fit: contain; object-position: center; } @@ -31,14 +31,13 @@ } .info-container { - flex-grow: 1000; + flex-grow: 1; flex-shrink: 1; flex-basis: 0; display: flex; flex-direction: row; flex-wrap: wrap; align-items: baseline; - min-width: 40rem; padding: 0 0.5rem; .name-container { @@ -47,7 +46,7 @@ flex-basis: auto; padding: 0 0.5rem; max-height: 3.6em; - font-size: 1.5rem; + font-size: 1.6rem; color: var(--color-surfacelighter); } @@ -55,6 +54,7 @@ flex-grow: 1; flex-shrink: 1; flex-basis: auto; + margin-top: 0.5rem; padding: 0 0.5rem; max-height: 2.4em; color: var(--color-surfacelight); @@ -83,22 +83,14 @@ } .buttons-container { - flex-grow: 1; - flex-shrink: 0; - flex-basis: 0; - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-items: flex-end; - min-width: 17rem; + flex: none; + width: 17rem; .install-button-container, .uninstall-button-container, .share-button-container { - flex: none; display: flex; flex-direction: row; align-items: center; justify-content: center; - width: 17rem; height: 3.5rem; padding: 0 1rem; @@ -106,13 +98,8 @@ margin-top: 1rem; } - &:not(:last-child) { - margin-right: 1rem; - } - .icon { flex: none; - display: block; width: 1.5rem; height: 1.5rem; margin-right: 1rem; diff --git a/src/routes/Addons/Addons.js b/src/routes/Addons/Addons.js index c99f7bc30..083c16747 100644 --- a/src/routes/Addons/Addons.js +++ b/src/routes/Addons/Addons.js @@ -6,27 +6,32 @@ const useAddons = require('./useAddons'); const useSelectableInputs = require('./useSelectableInputs'); const styles = require('./styles'); +const navigateToAddonDetails = (addonsCatalogRequest, transportUrl) => { + const queryParams = new URLSearchParams([['addon', transportUrl]]); + if (addonsCatalogRequest !== null) { + const addonTransportUrl = encodeURIComponent(addonsCatalogRequest.base); + const catalogId = encodeURIComponent(addonsCatalogRequest.path.id); + const type = encodeURIComponent(addonsCatalogRequest.path.type_name); + window.location.replace(`#/addons/${addonTransportUrl}/${catalogId}/${type}?${queryParams}`); + } else { + window.location.replace(`#/addons?${queryParams}`); + } +}; + const Addons = ({ urlParams, queryParams }) => { - const navigateToAddonDetails = React.useCallback((transportUrl) => { - const queryParams = new URLSearchParams([['addon', transportUrl]]); - if (typeof urlParams.addonTransportUrl === 'string' && typeof urlParams.catalogId === 'string' && typeof urlParams.type === 'string') { - const addonTransportUrl = encodeURIComponent(urlParams.addonTransportUrl); - const catalogId = encodeURIComponent(urlParams.catalogId); - const type = encodeURIComponent(urlParams.type); - window.location.replace(`#/addons/${addonTransportUrl}/${catalogId}/${type}?${queryParams}`); - } else { - window.location.replace(`#/addons?${queryParams}`); - } - }, [urlParams]); const addons = useAddons(urlParams); const selectInputs = useSelectableInputs(addons); const [addAddonModalOpen, openAddAddonModal, closeAddAddonModal] = useBinaryState(false); const addAddonUrlInputRef = React.useRef(null); const addAddonOnSubmit = React.useCallback(() => { if (addAddonUrlInputRef.current !== null) { - navigateToAddonDetails(addAddonUrlInputRef.current.value); + const addonsCatalogRequest = addons.catalog_resource !== null ? + addons.catalog_resource.request + : + null; + navigateToAddonDetails(addonsCatalogRequest, addAddonUrlInputRef.current.value); } - }, [navigateToAddonDetails]); + }, [addons]); const addAddonModalButtons = React.useMemo(() => { return [ { @@ -49,19 +54,23 @@ const Addons = ({ urlParams, queryParams }) => { setSearch(event.currentTarget.value); }, []); const [sharedTransportUrl, setSharedTransportUrl] = React.useState(null); - const shareModalOnClose = React.useCallback(() => { + const clearSharedTransportUrl = React.useCallback(() => { setSharedTransportUrl(null); }, []); const onAddonShare = React.useCallback((event) => { setSharedTransportUrl(event.dataset.transportUrl); }, []); const onAddonToggle = React.useCallback((event) => { - navigateToAddonDetails(event.dataset.transportUrl); - }, []); + const addonsCatalogRequest = addons.catalog_resource !== null ? + addons.catalog_resource.request + : + null; + navigateToAddonDetails(addonsCatalogRequest, event.dataset.transportUrl); + }, [addons]); React.useLayoutEffect(() => { - closeAddAddonModal(null); + closeAddAddonModal(); setSearch(''); - setSharedTransportUrl(null); + clearSharedTransportUrl(); }, [urlParams, queryParams]); return (
@@ -127,12 +136,13 @@ const Addons = ({ urlParams, queryParams }) => { className={styles['addon']} id={addon.manifest.id} name={addon.manifest.name} + version={addon.manifest.version} logo={addon.manifest.logo} description={addon.manifest.description} types={addon.manifest.types} - version={addon.manifest.version} - onShare={onAddonShare} + installed={addon.installed} onToggle={onAddonToggle} + onShare={onAddonShare} dataset={{ transportUrl: addon.transportUrl }} /> )) @@ -163,8 +173,11 @@ const Addons = ({ urlParams, queryParams }) => { - + onCloseRequest={clearSharedTransportUrl}> + : null diff --git a/src/routes/Addons/useAddons.js b/src/routes/Addons/useAddons.js index aad7086bc..57be65b45 100644 --- a/src/routes/Addons/useAddons.js +++ b/src/routes/Addons/useAddons.js @@ -30,8 +30,7 @@ const mapAddonsStateWithCtx = (addons, ctx) => { version: descriptor.manifest.version, logo: descriptor.manifest.logo, description: descriptor.manifest.description, - types: descriptor.manifest.types, - catalogs: descriptor.manifest.catalogs, + types: descriptor.manifest.types } })) }