// Copyright (C) 2017-2023 Smart code 203358507 const React = require('react'); const { useParams } = require('react-router'); const { useSearchParams } = require('react-router-dom'); const classnames = require('classnames'); const { useTranslation } = require('react-i18next'); const { default: Icon } = require('@stremio/stremio-icons/react'); const { useCore } = require('stremio/core'); const { usePlatform, useBinaryState, withCoreSuspender } = require('stremio/common'); const { AddonDetailsModal, Button, Image, MainNavBars, ModalDialog, SearchBar, SharePrompt, TextInput, MultiselectMenu } = require('stremio/components'); const useToast = require('stremio/common/Toast/useToast'); const Addon = require('./Addon'); const useInstalledAddons = require('./useInstalledAddons'); const useRemoteAddons = require('./useRemoteAddons'); const useAddonDetailsTransportUrl = require('./useAddonDetailsTransportUrl'); const useSelectableInputs = require('./useSelectableInputs'); const styles = require('./styles'); const { AddonPlaceholder } = require('./AddonPlaceholder'); const Addons = () => { const { type, transportUrl, catalogId } = useParams(); const [queryParams] = useSearchParams(); const urlParams = React.useMemo(() => ({ type, transportUrl, catalogId }), [type, transportUrl, catalogId]); const { t } = useTranslation(); const platform = usePlatform(); const core = useCore(); const toast = useToast(); const installedAddons = useInstalledAddons(urlParams); const remoteAddons = useRemoteAddons(urlParams); const [addonDetailsTransportUrl, setAddonDetailsTransportUrl] = useAddonDetailsTransportUrl(urlParams); const selectInputs = useSelectableInputs(installedAddons, remoteAddons); const [filtersModalOpen, openFiltersModal, closeFiltersModal] = useBinaryState(false); const [addAddonModalOpen, openAddAddonModal, closeAddAddonModal] = useBinaryState(false); const addAddonUrlInputRef = React.useRef(null); const addAddonOnSubmit = React.useCallback(() => { if (addAddonUrlInputRef.current !== null) { 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(() => { return [ { className: styles['cancel-button'], label: t('BUTTON_CANCEL'), props: { onClick: closeAddAddonModal } }, { label: t('ADDON_ADD'), props: { onClick: addAddonOnSubmit } } ]; }, [addAddonOnSubmit]); const [search, setSearch] = React.useState(''); const searchInputOnChange = React.useCallback((event) => { setSearch(event.currentTarget.value); }, []); const [sharedAddon, setSharedAddon] = React.useState(null); const clearSharedAddon = React.useCallback(() => { setSharedAddon(null); }, []); const onAddonShare = React.useCallback((event) => { setSharedAddon(event.dataset.addon); }, []); const onAddonInstall = React.useCallback((event) => { core.transport.dispatch({ action: 'Ctx', args: { action: 'InstallAddon', args: event.dataset.addon, } }); }, []); const onAddonUninstall = React.useCallback((event) => { core.transport.dispatch({ action: 'Ctx', args: { action: 'UninstallAddon', args: event.dataset.addon, } }); }, []); const onAddonConfigure = React.useCallback((event) => { platform.openExternal(event.dataset.addon.transportUrl.replace('manifest.json', 'configure')); }, []); const onAddonOpen = React.useCallback((event) => { setAddonDetailsTransportUrl(event.dataset.addon.transportUrl); }, [setAddonDetailsTransportUrl]); const closeAddonDetails = React.useCallback(() => { setAddonDetailsTransportUrl(null); }, [setAddonDetailsTransportUrl]); const searchFilterPredicate = React.useCallback((addon) => { return search.length === 0 || ( (typeof addon.manifest.name === 'string' && addon.manifest.name.toLowerCase().includes(search.toLowerCase())) || (typeof addon.manifest.description === 'string' && addon.manifest.description.toLowerCase().includes(search.toLowerCase())) ); }, [search]); const renderLogoFallback = React.useCallback(() => ( ), []); React.useLayoutEffect(() => { closeAddAddonModal(); setSearch(''); clearSharedAddon(); }, [urlParams, queryParams]); return (
{selectInputs.map((selectInput, index) => ( ))}
{ installedAddons.selected !== null ? installedAddons.selectable.types.length === 0 ?
{t('NO_ADDONS')}
: installedAddons.catalog.length === 0 ?
{t('NO_ADDONS_FOR_TYPE')}
:
{ installedAddons.catalog .filter(searchFilterPredicate) .map((addon, index) => ( )) }
: remoteAddons.selected !== null ? remoteAddons.catalog.content.type === 'Err' ?
{remoteAddons.catalog.content.content}
: remoteAddons.catalog.content.type === 'Loading' ?
{Array.from({ length: 6 }).map((_, index) => ( ))}
:
{ remoteAddons.catalog.content.content .filter(searchFilterPredicate) .map((addon, index) => ( )) }
:
{Array.from({ length: 6 }).map((_, index) => ( ))}
}
{ filtersModalOpen ? {selectInputs.map((selectInput, index) => ( ))} : null } { addAddonModalOpen ?
{t('ADD_ADDON_DESCRIPTION')}
: null } { sharedAddon !== null ?
{'
{typeof sharedAddon.manifest.name === 'string' && sharedAddon.manifest.name.length > 0 ? sharedAddon.manifest.name : sharedAddon.manifest.id} { typeof sharedAddon.manifest.version === 'string' && sharedAddon.manifest.version.length > 0 ? {t('ADDON_VERSION_SHORT', { version: sharedAddon.manifest.version })} : null }
: null } { typeof addonDetailsTransportUrl === 'string' ? : null } ); }; const AddonsFallback = () => ( ); module.exports = withCoreSuspender(Addons, AddonsFallback);