mirror of https://github.com/mue/mue.git
feat: update addons, sideload error modal, show reminder for preset settings
This commit is contained in:
parent
5baf067ff1
commit
c63a13a4c2
|
@ -24,6 +24,8 @@ const renderLoader = () => (
|
|||
|
||||
export default function MainModal({ modalClose }) {
|
||||
const language = window.language.modals.main.navbar;
|
||||
const { reminder } = window.language.modals.main.settings;
|
||||
const display = (localStorage.getItem('showReminder') === 'true') ? 'block' : 'none';
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -45,6 +47,11 @@ export default function MainModal({ modalClose }) {
|
|||
</Suspense>
|
||||
</div>
|
||||
</Tabs>
|
||||
<div className='reminder-info' style={{ display }}>
|
||||
<h1>{reminder.title}</h1>
|
||||
<p>{reminder.message}</p>
|
||||
<button className='pinNote' onClick={() => window.location.reload()}>{window.language.modals.main.error_boundary.refresh}</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,30 @@
|
|||
import { PureComponent } from 'react';
|
||||
import { PureComponent, Fragment } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { ArrowBack } from '@material-ui/icons';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
import { install, uninstall } from 'modules/helpers/marketplace';
|
||||
|
||||
import Lightbox from './Lightbox';
|
||||
|
||||
export default class Item extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showLightbox: false
|
||||
showLightbox: false,
|
||||
showUpdateButton: (this.props.addonInstalled === true && this.props.addonInstalledVersion !== this.props.data.version)
|
||||
};
|
||||
}
|
||||
|
||||
updateAddon() {
|
||||
uninstall(this.props.data.type, this.props.data.display_name);
|
||||
install(this.props.data.type, this.props.data);
|
||||
toast('Successfully updated!');
|
||||
this.setState({
|
||||
showUpdateButton: false
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const language = window.language.modals.main.marketplace.product;
|
||||
|
||||
|
@ -36,6 +49,18 @@ export default class Item extends PureComponent {
|
|||
if (!this.props.data.icon) {
|
||||
iconsrc = null;
|
||||
}
|
||||
|
||||
let updateButton;
|
||||
if (this.state.showUpdateButton) {
|
||||
updateButton = (
|
||||
<Fragment key='update'>
|
||||
<br/><br/>
|
||||
<button className='removeFromMue' onClick={() => this.updateAddon()}>
|
||||
Update Add-on
|
||||
</button>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='item'>
|
||||
|
@ -44,13 +69,14 @@ export default class Item extends PureComponent {
|
|||
<br/>
|
||||
<h1>{this.props.data.display_name}</h1>
|
||||
{this.props.button}
|
||||
{updateButton}
|
||||
<br/><br/>
|
||||
{iconsrc ? <img alt='product' draggable='false' src={iconsrc} onClick={() => this.setState({ showLightbox: true })}/> : null}
|
||||
<div className='side'>
|
||||
<div className='productInformation'>
|
||||
<ul>
|
||||
<li className='header'>{language.version}</li>
|
||||
<li>{this.props.data.version}</li>
|
||||
{updateButton ? <li>{this.props.data.version} (Installed: {this.props.data.addonInstalledVersion})</li> : <li>{this.props.data.version}</li>}
|
||||
<br/>
|
||||
<li className='header'>{language.author}</li>
|
||||
<li>{this.props.data.author}</li>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
export default function SideloadFailedModal({ modalClose, reason }) {
|
||||
return (
|
||||
<>
|
||||
<h1 style={{ textAlign: 'center' }}>Error</h1>
|
||||
<span>Failed to sideload addon</span>
|
||||
<br/><br/>
|
||||
<span>{reason}</span>
|
||||
<div className='resetfooter'>
|
||||
<button className='import' onClick={modalClose}>Close</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -44,11 +44,20 @@ export default class Marketplace extends PureComponent {
|
|||
|
||||
// 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({
|
||||
|
@ -60,7 +69,9 @@ export default class Marketplace extends PureComponent {
|
|||
//updated: info.updated,
|
||||
version: info.data.version,
|
||||
icon: info.data.screenshot_url,
|
||||
data: info.data
|
||||
data: info.data,
|
||||
addonInstalled,
|
||||
addonInstalledVersion
|
||||
},
|
||||
button: button
|
||||
});
|
||||
|
@ -200,7 +211,7 @@ export default class Marketplace extends PureComponent {
|
|||
}
|
||||
|
||||
if (this.state.item.display_name) {
|
||||
return <Item data={this.state.item} button={this.state.button} toggleFunction={() => this.toggle()}/>;
|
||||
return <Item data={this.state.item} button={this.state.button} toggleFunction={() => this.toggle()} addonInstalled={this.state.item.addonInstalled} addonInstalledVersion={this.state.item.addonInstalledVersion}/>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,25 +1,64 @@
|
|||
import { PureComponent } from 'react';
|
||||
import { LocalMall } from '@material-ui/icons';
|
||||
import { toast } from 'react-toastify';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
import SideloadFailedModal from '../SideloadFailedModal';
|
||||
|
||||
import FileUpload from '../../settings/FileUpload';
|
||||
|
||||
import { install } from 'modules/helpers/marketplace';
|
||||
|
||||
export default function Sideload() {
|
||||
const installAddon = (input) => {
|
||||
export default class Sideload extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showFailed: false,
|
||||
failedReason: ''
|
||||
}
|
||||
}
|
||||
|
||||
installAddon(input) {
|
||||
let failedReason = '';
|
||||
if (!input.name) {
|
||||
failedReason = 'No name provided';
|
||||
} else if (!input.author) {
|
||||
failedReason = 'No author provided';
|
||||
} else if (!input.type) {
|
||||
failedReason = 'No type provided';
|
||||
} else if (!input.version) {
|
||||
failedReason = 'No version provided';
|
||||
} else if (input.type === 'photos' && (!input.photos || !input.photos.length || !input.photos[0].url.default || !input.photos[0].photographer || !input.photos[0].location)) {
|
||||
failedReason = 'Invalid photos object';
|
||||
} else if (input.type === 'quotes' && (!input.quotes || !input.quotes.length || !input.quotes[0].quote || !input.quotes[0].author)) {
|
||||
failedReason = 'Invalid quotes object';
|
||||
}
|
||||
|
||||
if (failedReason !== '') {
|
||||
return this.setState({
|
||||
failedReason,
|
||||
showFailed: true
|
||||
});
|
||||
}
|
||||
|
||||
install(input.type, input);
|
||||
toast(window.language.toasts.installed);
|
||||
window.stats.postEvent('marketplace', 'Sideload');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='emptyitems'>
|
||||
<div className='emptyMessage'>
|
||||
<FileUpload id='file-input' type='settings' accept='application/json' loadFunction={(e) => installAddon(JSON.parse(e.target.result))} />
|
||||
<LocalMall/>
|
||||
<h1>{window.language.modals.main.addons.sideload}</h1>
|
||||
<button className='addToMue sideload' onClick={() => document.getElementById('file-input').click()}>{window.language.modals.main.settings.sections.background.source.upload}</button>
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className='emptyitems'>
|
||||
<div className='emptyMessage'>
|
||||
<FileUpload id='file-input' type='settings' accept='application/json' loadFunction={(e) => this.installAddon(JSON.parse(e.target.result))} />
|
||||
<LocalMall/>
|
||||
<h1>{window.language.modals.main.addons.sideload}</h1>
|
||||
<button className='addToMue sideload' onClick={() => document.getElementById('file-input').click()}>{window.language.modals.main.settings.sections.background.source.upload}</button>
|
||||
</div>
|
||||
<Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ showFailed: false })} isOpen={this.state.showFailed} className='Modal resetmodal mainModal sideloadModal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
|
||||
<SideloadFailedModal modalClose={() => this.setState({ showFailed: false })} reason={this.state.failedReason}/>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,3 +116,14 @@ p.author {
|
|||
width: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* sideload failed modal */
|
||||
.sideloadModal {
|
||||
min-width: 250px;
|
||||
max-width: 250px;
|
||||
overflow-x: hidden;
|
||||
|
||||
button {
|
||||
margin-left: -50px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@ import Stats from '../settings/sections/Stats';
|
|||
import Keybinds from '../settings/sections/Keybinds';
|
||||
|
||||
export default function Settings() {
|
||||
const { reminder, sections } = window.language.modals.main.settings;
|
||||
const display = (localStorage.getItem('showReminder') === 'true') ? 'block' : 'none';
|
||||
const { sections } = window.language.modals.main.settings;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -41,11 +40,6 @@ export default function Settings() {
|
|||
<div label={sections.changelog} name='changelog'><Changelog/></div>
|
||||
<div label={sections.about.title} name='about'><About/></div>
|
||||
</Tabs>
|
||||
<div className='reminder-info' style={{ display }}>
|
||||
<h1>{reminder.title}</h1>
|
||||
<p>{reminder.message}</p>
|
||||
<button className='pinNote' onClick={() => window.location.reload()}>{window.language.modals.main.error_boundary.refresh}</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,47 +1,16 @@
|
|||
import EventBus from './eventbus';
|
||||
|
||||
function showReminder() {
|
||||
document.querySelector('.reminder-info').style.display = 'block';
|
||||
localStorage.setItem('showReminder', true);
|
||||
}
|
||||
|
||||
// based on https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links
|
||||
export function urlParser(input) {
|
||||
const urlPattern = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_+.~#?&//=]*)/;
|
||||
return input.replace(urlPattern, '<a href="$&" target="_blank">$&</a>');
|
||||
}
|
||||
|
||||
export function uninstall(type, name) {
|
||||
switch (type) {
|
||||
case 'settings':
|
||||
const oldSettings = JSON.parse(localStorage.getItem('backup_settings'));
|
||||
localStorage.clear();
|
||||
oldSettings.forEach((item) => {
|
||||
localStorage.setItem(item.name, item.value);
|
||||
});
|
||||
break;
|
||||
case 'quotes':
|
||||
localStorage.removeItem('quote_packs');
|
||||
localStorage.removeItem('quoteAPI');
|
||||
localStorage.setItem('quoteType', localStorage.getItem('oldQuoteType'));
|
||||
localStorage.removeItem('oldQuoteType');
|
||||
EventBus.dispatch('refresh', 'marketplacequoteuninstall');
|
||||
break;
|
||||
case 'photos':
|
||||
localStorage.removeItem('photo_packs');
|
||||
localStorage.setItem('backgroundType', localStorage.getItem('oldBackgroundType'));
|
||||
localStorage.removeItem('oldBackgroundType');
|
||||
EventBus.dispatch('refresh', 'marketplacebackgrounduninstall');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
let installed = JSON.parse(localStorage.getItem('installed'));
|
||||
for (let i = 0; i < installed.length; i++) {
|
||||
if (installed[i].name === name) {
|
||||
installed.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
localStorage.setItem('installed', JSON.stringify(installed));
|
||||
}
|
||||
|
||||
export function install(type, input, sideload) {
|
||||
switch (type) {
|
||||
case 'settings':
|
||||
|
@ -59,6 +28,7 @@ export function install(type, input, sideload) {
|
|||
Object.keys(input.settings).forEach((key) => {
|
||||
localStorage.setItem(key, input.settings[key]);
|
||||
});
|
||||
showReminder();
|
||||
break;
|
||||
|
||||
case 'photos':
|
||||
|
@ -95,5 +65,43 @@ export function install(type, input, sideload) {
|
|||
installed.push(input);
|
||||
}
|
||||
|
||||
localStorage.setItem('installed', JSON.stringify(installed));
|
||||
}
|
||||
|
||||
export function uninstall(type, name) {
|
||||
switch (type) {
|
||||
case 'settings':
|
||||
const oldSettings = JSON.parse(localStorage.getItem('backup_settings'));
|
||||
localStorage.clear();
|
||||
oldSettings.forEach((item) => {
|
||||
localStorage.setItem(item.name, item.value);
|
||||
});
|
||||
showReminder();
|
||||
break;
|
||||
case 'quotes':
|
||||
localStorage.removeItem('quote_packs');
|
||||
localStorage.removeItem('quoteAPI');
|
||||
localStorage.setItem('quoteType', localStorage.getItem('oldQuoteType'));
|
||||
localStorage.removeItem('oldQuoteType');
|
||||
EventBus.dispatch('refresh', 'marketplacequoteuninstall');
|
||||
break;
|
||||
case 'photos':
|
||||
localStorage.removeItem('photo_packs');
|
||||
localStorage.setItem('backgroundType', localStorage.getItem('oldBackgroundType'));
|
||||
localStorage.removeItem('oldBackgroundType');
|
||||
EventBus.dispatch('refresh', 'marketplacebackgrounduninstall');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
let installed = JSON.parse(localStorage.getItem('installed'));
|
||||
for (let i = 0; i < installed.length; i++) {
|
||||
if (installed[i].name === name) {
|
||||
installed.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem('installed', JSON.stringify(installed));
|
||||
};
|
||||
|
|
|
@ -35,13 +35,3 @@ $modal-link-dark: map-get($modal, 'modal-link-dark');
|
|||
--photo-info: #{$photo-info-dark};
|
||||
--modal-link: #{$modal-link-dark};
|
||||
}
|
||||
|
||||
.no-animations {
|
||||
.ReactModal__Content,
|
||||
button,
|
||||
svg,
|
||||
input[type=text],
|
||||
.MuiSwitch-switchBase {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,10 +34,6 @@ body {
|
|||
text-shadow: 0 0 25px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.textBorder {
|
||||
filter: drop-shadow(var(--shadow-shift) var(--shadow-shift) 0 #111c);
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
color: map-get($theme-colours, 'main');
|
||||
opacity: 1;
|
||||
|
@ -53,7 +49,22 @@ body {
|
|||
color: map-get($theme-colours, 'main-text-color');
|
||||
}
|
||||
|
||||
// fonts imported from fontsource
|
||||
/* accessibility */
|
||||
.textBorder {
|
||||
filter: drop-shadow(var(--shadow-shift) var(--shadow-shift) 0 #111c);
|
||||
}
|
||||
|
||||
.no-animations {
|
||||
.ReactModal__Content,
|
||||
button,
|
||||
svg,
|
||||
input[type=text],
|
||||
.MuiSwitch-switchBase {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* fonts (imported from fontsource) */
|
||||
@font-face {
|
||||
font-family: 'Lexend Deca';
|
||||
font-style: normal;
|
||||
|
|
|
@ -16,7 +16,7 @@ module.exports = {
|
|||
use: ['babel-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(sa|sc|c)ss$/,
|
||||
test: /\.(|sc|c)ss$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
|
|
Loading…
Reference in New Issue