import variables from 'modules/variables'; import { PureComponent } from 'react'; import { toast } from 'react-toastify'; import { MdWifiOff, MdLocalMall, MdOutlineKeyboardArrowRight, MdSearch, MdOutlineArrowForward, MdLibraryAdd, } from 'react-icons/md'; import Item from '../Item'; import Items from '../Items'; import Dropdown from '../../settings/Dropdown'; import { install, urlParser, uninstall } from 'modules/helpers/marketplace'; export default class Marketplace extends PureComponent { constructor() { super(); this.state = { items: [], button: '', featured: {}, done: false, item: {}, collection: false, filter: '', }; this.buttons = { uninstall: ( ), install: ( ), }; this.controller = new AbortController(); } async toggle(type, data) { if (type === 'item') { let info; // get item info try { let type = this.props.type; if (type === 'all' || type === 'collections') { type = data.type; } info = await ( await fetch(`${variables.constants.MARKETPLACE_URL}/item/${type}/${data.name}`, { signal: this.controller.signal, }) ).json(); } catch (e) { if (this.controller.signal.aborted === false) { return toast(variables.getMessage('toasts.error')); } } if (this.controller.signal.aborted === true) { return; } // check if already installed let button = this.buttons.install; let addonInstalled = false; let addonInstalledVersion; const installed = JSON.parse(localStorage.getItem('installed')); if (installed.some((item) => item.name === info.data.name)) { button = this.buttons.uninstall; addonInstalled = true; for (let i = 0; i < installed.length; i++) { if (installed[i].name === info.data.name) { addonInstalledVersion = installed[i].version; break; } } } this.setState({ item: { type: info.data.type, display_name: info.data.name, author: info.data.author, description: urlParser(info.data.description.replace(/\n/g, '
')), //updated: info.updated, version: info.data.version, icon: info.data.screenshot_url, data: info.data, addonInstalled, addonInstalledVersion, api_name: data.name, }, button: button, }); variables.stats.postEvent('marketplace-item', `${this.state.item.display_name} viewed`); } else if (type === 'collection') { this.setState({ done: false, }); const collection = await ( await fetch(`${variables.constants.MARKETPLACE_URL}/collection/${data}`, { signal: this.controller.signal, }) ).json(); this.setState({ items: collection.data.items, collectionTitle: collection.data.name, collectionDescription: collection.data.description, collectionImg: collection.data.img, collection: true, done: true, }); } else { this.setState({ item: {}, }); } } async getItems() { const dataURL = this.props.type === 'collections' ? variables.constants.MARKETPLACE_URL + '/collections' : variables.constants.MARKETPLACE_URL + '/items/' + this.props.type; const { data } = await ( await fetch(dataURL, { signal: this.controller.signal, }) ).json(); const featured = await ( await fetch(variables.constants.MARKETPLACE_URL + '/featured', { signal: this.controller.signal, }) ).json(); const collections = await ( await fetch(variables.constants.MARKETPLACE_URL + '/collections', { signal: this.controller.signal, }) ).json(); if (this.controller.signal.aborted === true) { return; } this.setState({ items: data, oldItems: data, featured: featured.data, collections: collections.data, done: true, }); this.sortMarketplace(localStorage.getItem('sortMarketplace'), false); } manage(type) { if (type === 'install') { install(this.state.item.type, this.state.item.data); } else { uninstall(this.state.item.type, this.state.item.display_name); } toast(variables.getMessage('toasts.' + type + 'ed')); this.setState({ button: type === 'install' ? this.buttons.uninstall : this.buttons.install, }); variables.stats.postEvent( 'marketplace-item', `${this.state.item.display_name} ${type === 'install' ? 'installed' : 'uninstalled'}`, ); variables.stats.postEvent('marketplace', type === 'install' ? 'Install' : 'Uninstall'); } async installCollection() { this.setState({ busy: true }); try { const installed = JSON.parse(localStorage.getItem('installed')); for (const item of this.state.items) { if (installed.some((i) => i.name === item.display_name)) continue; // don't install if already installed let { data } = await ( await fetch(`${variables.constants.MARKETPLACE_URL}/item/${item.type}/${item.name}`, { signal: this.controller.signal, }) ).json(); install(data.type, data); variables.stats.postEvent('marketplace-item', `${item.display_name} installed}`); variables.stats.postEvent('marketplace', 'Install'); } toast(variables.getMessage('toasts.installed')); } catch (error) { console.error(error); toast(variables.getMessage('toasts.error')); } finally { this.setState({ busy: false }); } } sortMarketplace(value, sendEvent) { let items = this.state.oldItems; switch (value) { case 'a-z': items.sort(); // fix sort not working sometimes if (this.state.sortType === 'z-a') { items.reverse(); } break; case 'z-a': items.sort(); items.reverse(); break; default: break; } this.setState({ items: items, sortType: value, }); if (sendEvent) { variables.stats.postEvent('marketplace', 'Sort'); } } returnToMain() { this.setState({ items: this.state.oldItems, collection: false, }); } reloadItems() { this.setState({ done: false, }); this.getItems(); } componentDidMount() { if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') { return; } this.getItems(); } componentWillUnmount() { // stop making requests this.controller.abort(); } render() { const errorMessage = (msg) => { return ( <>
{variables.getMessage('modals.main.navbar.marketplace')}
{msg}
); }; if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') { return errorMessage( <>

{variables.getMessage('modals.main.marketplace.offline.title')}

{variables.getMessage('modals.main.marketplace.offline.description')}

, ); } if (this.state.done === false) { return errorMessage( <>
{variables.getMessage('modals.main.loading')}
, ); } const featured = () => { const openFeatured = () => { variables.stats.postEvent('marketplace', 'Featured clicked'); window.open(this.state.featured.buttonLink); }; return (

{this.state.featured.title}

{this.state.featured.name}

); }; if (this.state.items?.length === 0) { return ( <> {featured()} {errorMessage( <>

{variables.getMessage('modals.main.addons.empty.title')}

{variables.getMessage('modals.main.marketplace.no_items')}

, )} ); } if (this.state.item.display_name) { return ( this.toggle()} addonInstalled={this.state.item.addonInstalled} addonInstalledVersion={this.state.item.addonInstalledVersion} icon={this.state.item.screenshot_url} /> ); } return ( <> {this.state.collection === true ? ( <>
this.returnToMain()}> {variables.getMessage('modals.main.navbar.marketplace')} {' '} {variables.getMessage('modals.main.marketplace.collection')}
{variables.getMessage('modals.main.marketplace.collection')}
{this.state.collectionTitle} {this.state.collectionDescription}
) : ( <>
{variables.getMessage('modals.main.navbar.marketplace')}
{this.props.type !== 'collections' ? (
this.setState({ filter: event.target.value })} /> {/* this.reloadItems()}> {variables.getMessage('widgets.navbar.tooltips.refresh')} */}
) : null} this.sortMarketplace(value)} >
)} {this.props.type === 'collections' && !this.state.collection ? ( this.state.items.map((item) => ( <> {!item.news ? (
{item.display_name} {item.description}
) : null} )) ) : ( this.toggle('item', input)} collectionFunction={(input) => this.toggle('collection', input)} filter={this.state.filter} /> )} ); } }