mue/src/components/modals/main/marketplace/sections/Marketplace.jsx

473 lines
14 KiB
React
Raw Normal View History

import variables from 'modules/variables';
2021-08-14 19:10:48 +00:00
import { PureComponent } from 'react';
2021-08-15 21:28:37 +00:00
import { toast } from 'react-toastify';
import {
MdWifiOff,
MdLocalMall,
MdOutlineKeyboardArrowRight,
2022-10-21 21:33:30 +00:00
MdSearch,
MdOutlineArrowForward,
2023-01-21 12:10:40 +00:00
MdLibraryAdd,
} from 'react-icons/md';
2021-03-07 19:06:49 +00:00
import Item from '../Item';
import Items from '../Items';
2021-05-02 13:44:23 +00:00
import Dropdown from '../../settings/Dropdown';
2021-03-07 19:06:49 +00:00
2021-08-28 14:34:12 +00:00
import { install, urlParser, uninstall } from 'modules/helpers/marketplace';
2021-03-07 19:06:49 +00:00
2021-08-14 19:10:48 +00:00
export default class Marketplace extends PureComponent {
2021-03-23 13:10:34 +00:00
constructor() {
super();
2021-03-07 19:06:49 +00:00
this.state = {
items: [],
button: '',
featured: {},
done: false,
item: {},
collection: false,
2022-10-21 21:33:30 +00:00
filter: '',
2021-04-08 19:02:31 +00:00
};
this.buttons = {
uninstall: (
<button onClick={() => this.manage('uninstall')}>
{variables.getMessage('modals.main.marketplace.product.buttons.remove')}
</button>
),
install: (
<button onClick={() => this.manage('install')}>
{variables.getMessage('modals.main.marketplace.product.buttons.addtomue')}
2023-01-21 12:10:40 +00:00
<MdLibraryAdd />
</button>
),
2021-04-16 11:26:56 +00:00
};
this.controller = new AbortController();
}
2021-03-07 19:06:49 +00:00
async toggle(type, data) {
2021-04-14 12:45:11 +00:00
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();
2021-04-14 12:45:11 +00:00
} catch (e) {
if (this.controller.signal.aborted === false) {
return toast(variables.getMessage('toasts.error'));
}
}
if (this.controller.signal.aborted === true) {
return;
2021-04-14 12:45:11 +00:00
}
2021-03-07 19:06:49 +00:00
2021-04-14 12:45:11 +00:00
// check if already installed
let button = this.buttons.install;
let addonInstalled = false;
let addonInstalledVersion;
2021-04-14 12:45:11 +00:00
const installed = JSON.parse(localStorage.getItem('installed'));
2021-04-16 11:39:51 +00:00
if (installed.some((item) => item.name === info.data.name)) {
2021-04-14 12:45:11 +00:00
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;
}
}
2021-04-14 12:45:11 +00:00
}
2021-04-14 12:45:11 +00:00
this.setState({
item: {
2021-05-03 14:39:34 +00:00
type: info.data.type,
2021-04-14 12:45:11 +00:00
display_name: info.data.name,
author: info.data.author,
2021-08-14 19:10:48 +00:00
description: urlParser(info.data.description.replace(/\n/g, '<br>')),
2021-04-14 12:45:11 +00:00
//updated: info.updated,
version: info.data.version,
icon: info.data.screenshot_url,
data: info.data,
addonInstalled,
addonInstalledVersion,
api_name: data.name,
2021-04-14 12:45:11 +00:00
},
button: button,
2021-04-14 12:45:11 +00:00
});
2021-06-21 16:42:14 +00:00
2021-09-28 22:04:04 +00:00
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,
2022-08-03 09:42:04 +00:00
collectionTitle: collection.data.name,
collectionDescription: collection.data.description,
collectionImg: collection.data.img,
collection: true,
done: true,
});
2021-04-14 12:45:11 +00:00
} else {
this.setState({
item: {},
2021-04-14 12:45:11 +00:00
});
}
}
2021-03-07 19:06:49 +00:00
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;
}
2021-03-07 19:06:49 +00:00
this.setState({
items: data,
oldItems: data,
featured: featured.data,
collections: collections.data,
done: true,
2021-03-07 19:06:49 +00:00
});
2021-05-02 13:44:23 +00:00
2021-06-21 16:42:14 +00:00
this.sortMarketplace(localStorage.getItem('sortMarketplace'), false);
2021-03-07 19:06:49 +00:00
}
manage(type) {
2021-04-14 12:45:11 +00:00
if (type === 'install') {
2021-08-14 19:10:48 +00:00
install(this.state.item.type, this.state.item.data);
2021-04-14 12:45:11 +00:00
} else {
2021-08-14 19:10:48 +00:00
uninstall(this.state.item.type, this.state.item.display_name);
2021-03-07 19:06:49 +00:00
}
toast(variables.getMessage('toasts.' + type + 'ed'));
2021-03-07 19:06:49 +00:00
this.setState({
button: type === 'install' ? this.buttons.uninstall : this.buttons.install,
2021-03-07 19:06:49 +00:00
});
2021-06-21 16:42:14 +00:00
variables.stats.postEvent(
'marketplace-item',
`${this.state.item.display_name} ${type === 'install' ? 'installed' : 'uninstalled'}`,
);
variables.stats.postEvent('marketplace', type === 'install' ? 'Install' : 'Uninstall');
2021-03-07 19:06:49 +00:00
}
2023-01-21 12:10:40 +00:00
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 });
}
}
2021-06-21 16:42:14 +00:00
sortMarketplace(value, sendEvent) {
2021-05-02 13:44:23 +00:00
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();
}
2021-05-02 13:44:23 +00:00
break;
case 'z-a':
items.sort();
items.reverse();
2021-05-03 10:27:52 +00:00
break;
default:
break;
2021-05-02 13:44:23 +00:00
}
this.setState({
items: items,
sortType: value,
2021-05-02 13:44:23 +00:00
});
2021-06-21 16:42:14 +00:00
if (sendEvent) {
2021-09-28 22:04:04 +00:00
variables.stats.postEvent('marketplace', 'Sort');
2021-06-21 16:42:14 +00:00
}
2021-05-02 13:44:23 +00:00
}
returnToMain() {
this.setState({
items: this.state.oldItems,
collection: false,
});
}
reloadItems() {
this.setState({
done: false,
});
this.getItems();
}
2021-03-07 19:06:49 +00:00
componentDidMount() {
if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
return;
}
this.getItems();
}
componentWillUnmount() {
// stop making requests
this.controller.abort();
}
2021-03-07 19:06:49 +00:00
render() {
const errorMessage = (msg) => {
return (
<>
<div className="flexTopMarketplace">
<span className="mainTitle">
{variables.getMessage('modals.main.navbar.marketplace')}
</span>
</div>
<div className="emptyItems">
<div className="emptyMessage">{msg}</div>
</div>
</>
);
2021-04-16 11:39:51 +00:00
};
2021-03-07 19:06:49 +00:00
if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
return errorMessage(
<>
<MdWifiOff />
<h1>{variables.getMessage('modals.main.marketplace.offline.title')}</h1>
<p className="description">
{variables.getMessage('modals.main.marketplace.offline.description')}
</p>
</>,
);
}
if (this.state.done === false) {
return errorMessage(
<>
<div className="loaderHolder">
<div id="loader"></div>
<span className="subtitle">{variables.getMessage('modals.main.loading')}</span>
</div>
</>,
);
}
2021-05-26 21:28:26 +00:00
const featured = () => {
2021-06-21 16:42:14 +00:00
const openFeatured = () => {
2021-09-28 22:04:04 +00:00
variables.stats.postEvent('marketplace', 'Featured clicked');
2021-06-21 16:42:14 +00:00
window.open(this.state.featured.buttonLink);
2021-08-27 17:27:11 +00:00
};
2021-05-26 21:28:26 +00:00
return (
<div className="featured" style={{ backgroundColor: this.state.featured.colour }}>
2021-05-26 21:28:26 +00:00
<p>{this.state.featured.title}</p>
<h1>{this.state.featured.name}</h1>
<button className="addToMue" onClick={() => openFeatured()}>
{this.state.featured.buttonText}
</button>
2021-05-26 21:28:26 +00:00
</div>
);
};
2021-05-26 21:28:26 +00:00
2022-10-31 08:04:03 +00:00
if (this.state.items?.length === 0) {
2021-05-26 21:28:26 +00:00
return (
<>
{featured()}
{errorMessage(
<>
<MdLocalMall />
<h1>{variables.getMessage('modals.main.addons.empty.title')}</h1>
<p className="description">
{variables.getMessage('modals.main.marketplace.no_items')}
</p>
</>,
)}
2021-05-26 21:28:26 +00:00
</>
);
}
2021-05-03 10:27:52 +00:00
if (this.state.item.display_name) {
return (
<Item
data={this.state.item}
button={this.state.button}
toggleFunction={() => this.toggle()}
addonInstalled={this.state.item.addonInstalled}
addonInstalledVersion={this.state.item.addonInstalledVersion}
icon={this.state.item.screenshot_url}
/>
);
2021-05-03 10:27:52 +00:00
}
2021-03-07 19:06:49 +00:00
return (
2021-04-03 12:32:00 +00:00
<>
{this.state.collection === true ? (
<>
<div className="flexTopMarketplace">
2022-07-16 11:06:58 +00:00
<span className="mainTitle" onClick={() => this.returnToMain()}>
<span className="backTitle">
{variables.getMessage('modals.main.navbar.marketplace')}
2022-07-16 11:06:58 +00:00
</span>
2022-10-21 21:33:30 +00:00
<MdOutlineKeyboardArrowRight />{' '}
{variables.getMessage('modals.main.marketplace.collection')}
2022-07-16 11:06:58 +00:00
</span>
</div>
2022-08-03 09:42:04 +00:00
<div
className="collectionPage"
style={{
backgroundImage: `linear-gradient(to bottom, transparent, black), url('${this.state.collectionImg}')`,
2022-08-03 09:42:04 +00:00
}}
>
2023-01-21 12:10:40 +00:00
<div className="nice-tag">
{variables.getMessage('modals.main.marketplace.collection')}
</div>
<div className="content">
2022-08-03 09:42:04 +00:00
<span className="mainTitle">{this.state.collectionTitle}</span>
<span className="subtitle">{this.state.collectionDescription}</span>
</div>
2023-01-21 12:10:40 +00:00
<button
className="addAllButton"
onClick={() => this.installCollection()}
disabled={this.state.busy}
>
{variables.getMessage('modals.main.marketplace.add_all')}
<MdLibraryAdd />
</button>
</div>
</>
) : (
<>
<div className="flexTopMarketplace">
<span className="mainTitle">
{variables.getMessage('modals.main.navbar.marketplace')}
</span>
</div>
<div className="headerExtras marketplaceCondition">
2022-10-21 21:33:30 +00:00
{this.props.type !== 'collections' ? (
<div>
<form className="marketplaceSearch">
<input
label={variables.getMessage('widgets.search')}
placeholder={variables.getMessage('widgets.search')}
2022-10-21 21:33:30 +00:00
name="filter"
id="filter"
value={this.state.filter}
onChange={(event) => this.setState({ filter: event.target.value })}
/>
<MdSearch />
</form>
{/*<span className="link marketplaceRefresh" onClick={() => this.reloadItems()}>
<MdRefresh /> {variables.getMessage('widgets.navbar.tooltips.refresh')}
</span>*/}
</div>
) : null}
<Dropdown
label={variables.getMessage('modals.main.addons.sort.title')}
name="sortMarketplace"
onChange={(value) => this.sortMarketplace(value)}
>
<option value="a-z">{variables.getMessage('modals.main.addons.sort.a_z')}</option>
<option value="z-a">{variables.getMessage('modals.main.addons.sort.z_a')}</option>
</Dropdown>
2022-10-21 21:33:30 +00:00
</div>
</>
)}
2022-11-06 11:59:59 +00:00
{this.props.type === 'collections' && !this.state.collection ? (
this.state.items.map((item) => (
<>
{!item.news ? (
<div
className="collection"
style={
item.news
? { backgroundColor: item.background_colour }
: {
backgroundImage: `linear-gradient(to left, #000, transparent, #000), url('${item.img}')`,
}
}
>
<div className="content">
<span className="title">{item.display_name}</span>
<span className="subtitle">{item.description}</span>
</div>
<button
2022-08-31 21:21:37 +00:00
className="collectionButton"
onClick={() => this.toggle('collection', item.name)}
>
<MdOutlineArrowForward />{' '}
{variables.getMessage('modals.main.marketplace.explore_collection')}
</button>
</div>
) : null}
</>
))
) : (
<Items
type={this.props.type}
items={this.state.items}
2022-10-21 21:33:30 +00:00
collection={
this.state.collections[Math.floor(Math.random() * this.state.collections.length)] ||
[]
}
onCollection={this.state.collection}
toggleFunction={(input) => this.toggle('item', input)}
collectionFunction={(input) => this.toggle('collection', input)}
2022-10-21 21:33:30 +00:00
filter={this.state.filter}
/>
)}
2021-04-03 12:32:00 +00:00
</>
);
}
}