Merge pull request #3438 from ethcore/jg-external-dapps
Dapp section & visibility changes
This commit is contained in:
commit
80288f8680
@ -19,5 +19,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.layout>div {
|
.layout>div {
|
||||||
padding-bottom: 0.25em;
|
padding-bottom: 0.75em;
|
||||||
}
|
}
|
||||||
|
@ -18,3 +18,22 @@
|
|||||||
.description {
|
.description {
|
||||||
margin-top: .5em !important;
|
margin-top: .5em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
.background {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
margin: 0 -1.5em;
|
||||||
|
padding: 0.5em 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.byline {
|
||||||
|
font-size: 0.75em;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -51,16 +51,37 @@ export default class AddDapps extends Component {
|
|||||||
] }
|
] }
|
||||||
visible
|
visible
|
||||||
scroll>
|
scroll>
|
||||||
<List>
|
<div className={ styles.warning }>
|
||||||
{ store.apps.map(this.renderApp) }
|
</div>
|
||||||
</List>
|
{ this.renderList(store.sortedLocal, 'Applications locally available', 'All applications installed locally on the machine by the user for access by the Parity client.') }
|
||||||
|
{ this.renderList(store.sortedBuiltin, 'Applications bundled with Parity', 'Experimental applications developed by the Parity team to show off dapp capabilities, integration, experimental features and to control certain network-wide client behaviour.') }
|
||||||
|
{ this.renderList(store.sortedNetwork, 'Applications on the global network', 'These applications are not affiliated with Parity nor are they published by Parity. Each remain under the control of their respective authors. Please ensure that you understand the goals for each application before interacting.') }
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderList (items, header, byline) {
|
||||||
|
if (!items || !items.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ styles.list }>
|
||||||
|
<div className={ styles.background }>
|
||||||
|
<div className={ styles.header }>{ header }</div>
|
||||||
|
<div className={ styles.byline }>{ byline }</div>
|
||||||
|
</div>
|
||||||
|
<List>
|
||||||
|
{ items.map(this.renderApp) }
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderApp = (app) => {
|
renderApp = (app) => {
|
||||||
const { store } = this.props;
|
const { store } = this.props;
|
||||||
const isHidden = store.hidden.includes(app.id);
|
const isHidden = !store.displayApps[app.id].visible;
|
||||||
|
|
||||||
const onCheck = () => {
|
const onCheck = () => {
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
store.showApp(app.id);
|
store.showApp(app.id);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
|
|
||||||
import { Container, ContainerTitle } from '../../../ui';
|
import { Container, ContainerTitle, Tags } from '../../../ui';
|
||||||
|
|
||||||
import styles from './summary.css';
|
import styles from './summary.css';
|
||||||
|
|
||||||
@ -49,6 +49,7 @@ export default class Summary extends Component {
|
|||||||
return (
|
return (
|
||||||
<Container className={ styles.container }>
|
<Container className={ styles.container }>
|
||||||
{ image }
|
{ image }
|
||||||
|
<Tags tags={ [app.type] } />
|
||||||
<div className={ styles.description }>
|
<div className={ styles.description }>
|
||||||
<ContainerTitle
|
<ContainerTitle
|
||||||
className={ styles.title }
|
className={ styles.title }
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
"name": "Token Deployment",
|
"name": "Token Deployment",
|
||||||
"description": "Deploy new basic tokens that you are able to send around",
|
"description": "Deploy new basic tokens that you are able to send around",
|
||||||
"author": "Parity Team <admin@ethcore.io>",
|
"author": "Parity Team <admin@ethcore.io>",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0",
|
||||||
|
"visible": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0xd1adaede68d344519025e2ff574650cd99d3830fe6d274c7a7843cdc00e17938",
|
"id": "0xd1adaede68d344519025e2ff574650cd99d3830fe6d274c7a7843cdc00e17938",
|
||||||
@ -13,7 +14,8 @@
|
|||||||
"name": "Registry",
|
"name": "Registry",
|
||||||
"description": "A global registry of addresses on the network",
|
"description": "A global registry of addresses on the network",
|
||||||
"author": "Parity Team <admin@ethcore.io>",
|
"author": "Parity Team <admin@ethcore.io>",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0",
|
||||||
|
"visible": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0x0a8048117e51e964628d0f2d26342b3cd915248b59bcce2721e1d05f5cfa2208",
|
"id": "0x0a8048117e51e964628d0f2d26342b3cd915248b59bcce2721e1d05f5cfa2208",
|
||||||
@ -21,7 +23,8 @@
|
|||||||
"name": "Token Registry",
|
"name": "Token Registry",
|
||||||
"description": "A registry of transactable tokens on the network",
|
"description": "A registry of transactable tokens on the network",
|
||||||
"author": "Parity Team <admin@ethcore.io>",
|
"author": "Parity Team <admin@ethcore.io>",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0",
|
||||||
|
"visible": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46",
|
"id": "0xf49089046f53f5d2e5f3513c1c32f5ff57d986e46309a42d2b249070e4e72c46",
|
||||||
@ -29,7 +32,8 @@
|
|||||||
"name": "Method Registry",
|
"name": "Method Registry",
|
||||||
"description": "A registry of method signatures for lookups on transactions",
|
"description": "A registry of method signatures for lookups on transactions",
|
||||||
"author": "Parity Team <admin@ethcore.io>",
|
"author": "Parity Team <admin@ethcore.io>",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0",
|
||||||
|
"visible": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0x058740ee9a5a3fb9f1cfa10752baec87e09cc45cd7027fd54708271aca300c75",
|
"id": "0x058740ee9a5a3fb9f1cfa10752baec87e09cc45cd7027fd54708271aca300c75",
|
||||||
@ -38,6 +42,7 @@
|
|||||||
"description": "A mapping of GitHub URLs to hashes for use in contracts as references",
|
"description": "A mapping of GitHub URLs to hashes for use in contracts as references",
|
||||||
"author": "Parity Team <admin@ethcore.io>",
|
"author": "Parity Team <admin@ethcore.io>",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"visible": false,
|
||||||
"secure": true
|
"secure": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin: -0.125em;
|
margin: -0.125em;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list+.list {
|
.list+.list {
|
||||||
@ -29,3 +30,25 @@
|
|||||||
flex: 0 1 50%;
|
flex: 0 1 50%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
background: rgba(0, 0, 0, 0.85);
|
||||||
|
bottom: 0.5em;
|
||||||
|
left: -0.125em;
|
||||||
|
position: absolute;
|
||||||
|
right: -0.125em;
|
||||||
|
top: -0.25em;
|
||||||
|
z-index: 100;
|
||||||
|
padding: 1em;
|
||||||
|
|
||||||
|
.body {
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: left;
|
||||||
|
max-width: 980px;
|
||||||
|
|
||||||
|
&>div:first-child {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
|
import { Checkbox } from 'material-ui';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
|
||||||
import { Actionbar, Page } from '../../ui';
|
import { Actionbar, Page } from '../../ui';
|
||||||
@ -37,6 +38,24 @@ export default class Dapps extends Component {
|
|||||||
store = new DappsStore(this.context.api);
|
store = new DappsStore(this.context.api);
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
let externalOverlay = null;
|
||||||
|
if (this.store.externalOverlayVisible) {
|
||||||
|
externalOverlay = (
|
||||||
|
<div className={ styles.overlay }>
|
||||||
|
<div className={ styles.body }>
|
||||||
|
<div>Applications made available on the network by 3rd-party authors are not affiliated with Parity nor are they published by Parity. Each remain under the control of their respective authors. Please ensure that you understand the goals for each before interacting.</div>
|
||||||
|
<div>
|
||||||
|
<Checkbox
|
||||||
|
className={ styles.accept }
|
||||||
|
label='I understand that these applications are not affiliated with Parity'
|
||||||
|
checked={ false }
|
||||||
|
onCheck={ this.onClickAcceptExternal } />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AddDapps store={ this.store } />
|
<AddDapps store={ this.store } />
|
||||||
@ -53,14 +72,27 @@ export default class Dapps extends Component {
|
|||||||
] }
|
] }
|
||||||
/>
|
/>
|
||||||
<Page>
|
<Page>
|
||||||
<div className={ styles.list }>
|
{ this.renderList(this.store.visibleLocal) }
|
||||||
{ this.store.visible.map(this.renderApp) }
|
{ this.renderList(this.store.visibleBuiltin) }
|
||||||
</div>
|
{ this.renderList(this.store.visibleNetwork, externalOverlay) }
|
||||||
</Page>
|
</Page>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderList (items, overlay) {
|
||||||
|
if (!items || !items.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={ styles.list }>
|
||||||
|
{ overlay }
|
||||||
|
{ items.map(this.renderApp) }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderApp = (app) => {
|
renderApp = (app) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -70,4 +102,8 @@ export default class Dapps extends Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClickAcceptExternal = () => {
|
||||||
|
this.store.closeExternalOverlay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,39 +14,65 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
import { action, computed, observable, transaction } from 'mobx';
|
import { action, computed, observable, transaction } from 'mobx';
|
||||||
|
import store from 'store';
|
||||||
|
|
||||||
import Contracts from '../../contracts';
|
import Contracts from '../../contracts';
|
||||||
import { hashToImageUrl } from '../../redux/util';
|
import { hashToImageUrl } from '../../redux/util';
|
||||||
|
|
||||||
import builtinApps from './builtin.json';
|
import builtinApps from './builtin.json';
|
||||||
|
|
||||||
const LS_KEY_HIDDEN = 'hiddenApps';
|
const LS_KEY_DISPLAY = 'displayApps';
|
||||||
const LS_KEY_EXTERNAL = 'externalApps';
|
const LS_KEY_EXTERNAL_ACCEPT = 'acceptExternal';
|
||||||
|
|
||||||
export default class DappsStore {
|
export default class DappsStore {
|
||||||
@observable apps = [];
|
@observable apps = [];
|
||||||
@observable externalApps = [];
|
@observable displayApps = {};
|
||||||
@observable hiddenApps = [];
|
|
||||||
@observable modalOpen = false;
|
@observable modalOpen = false;
|
||||||
|
@observable externalOverlayVisible = true;
|
||||||
|
|
||||||
constructor (api) {
|
constructor (api) {
|
||||||
this._api = api;
|
this._api = api;
|
||||||
|
|
||||||
this._readHiddenApps();
|
this.loadExternalOverlay();
|
||||||
this._readExternalApps();
|
this.readDisplayApps();
|
||||||
|
|
||||||
this._fetchBuiltinApps();
|
Promise
|
||||||
this._fetchLocalApps();
|
.all([
|
||||||
this._fetchRegistryApps();
|
this._fetchBuiltinApps(),
|
||||||
|
this._fetchLocalApps(),
|
||||||
|
this._fetchRegistryApps()
|
||||||
|
])
|
||||||
|
.then(this.writeDisplayApps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get visible () {
|
@computed get sortedBuiltin () {
|
||||||
return this.apps
|
return this.apps.filter((app) => app.type === 'builtin');
|
||||||
.filter((app) => {
|
}
|
||||||
return this.externalApps.includes(app.id) || !this.hiddenApps.includes(app.id);
|
|
||||||
})
|
@computed get sortedLocal () {
|
||||||
.sort((a, b) => a.name.localeCompare(b.name));
|
return this.apps.filter((app) => app.type === 'local');
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get sortedNetwork () {
|
||||||
|
return this.apps.filter((app) => app.type === 'network');
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get visibleApps () {
|
||||||
|
return this.apps.filter((app) => this.displayApps[app.id] && this.displayApps[app.id].visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get visibleBuiltin () {
|
||||||
|
return this.visibleApps.filter((app) => app.type === 'builtin');
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get visibleLocal () {
|
||||||
|
return this.visibleApps.filter((app) => app.type === 'local');
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get visibleNetwork () {
|
||||||
|
return this.visibleApps.filter((app) => app.type === 'network');
|
||||||
}
|
}
|
||||||
|
|
||||||
@action openModal = () => {
|
@action openModal = () => {
|
||||||
@ -57,14 +83,48 @@ export default class DappsStore {
|
|||||||
this.modalOpen = false;
|
this.modalOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action closeExternalOverlay = () => {
|
||||||
|
this.externalOverlayVisible = false;
|
||||||
|
store.set(LS_KEY_EXTERNAL_ACCEPT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action loadExternalOverlay () {
|
||||||
|
this.externalOverlayVisible = !(store.get(LS_KEY_EXTERNAL_ACCEPT) || false);
|
||||||
|
}
|
||||||
|
|
||||||
@action hideApp = (id) => {
|
@action hideApp = (id) => {
|
||||||
this.hiddenApps = this.hiddenApps.concat(id);
|
this.displayApps = Object.assign({}, this.displayApps, { [id]: { visible: false } });
|
||||||
this._writeHiddenApps();
|
this.writeDisplayApps();
|
||||||
}
|
}
|
||||||
|
|
||||||
@action showApp = (id) => {
|
@action showApp = (id) => {
|
||||||
this.hiddenApps = this.hiddenApps.filter((_id) => _id !== id);
|
this.displayApps = Object.assign({}, this.displayApps, { [id]: { visible: true } });
|
||||||
this._writeHiddenApps();
|
this.writeDisplayApps();
|
||||||
|
}
|
||||||
|
|
||||||
|
@action readDisplayApps = () => {
|
||||||
|
this.displayApps = store.get(LS_KEY_DISPLAY) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
@action writeDisplayApps = () => {
|
||||||
|
store.set(LS_KEY_DISPLAY, this.displayApps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action addApps = (apps) => {
|
||||||
|
transaction(() => {
|
||||||
|
this.apps = this.apps
|
||||||
|
.concat(apps || [])
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
const visibility = {};
|
||||||
|
apps.forEach((app) => {
|
||||||
|
if (!this.displayApps[app.id]) {
|
||||||
|
visibility[app.id] = { visible: app.visible };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.displayApps = Object.assign({}, this.displayApps, visibility);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_getHost (api) {
|
_getHost (api) {
|
||||||
@ -79,13 +139,16 @@ export default class DappsStore {
|
|||||||
return Promise
|
return Promise
|
||||||
.all(builtinApps.map((app) => dappReg.getImage(app.id)))
|
.all(builtinApps.map((app) => dappReg.getImage(app.id)))
|
||||||
.then((imageIds) => {
|
.then((imageIds) => {
|
||||||
transaction(() => {
|
this.addApps(
|
||||||
builtinApps.forEach((app, index) => {
|
builtinApps.map((app, index) => {
|
||||||
app.type = 'builtin';
|
app.type = 'builtin';
|
||||||
app.image = hashToImageUrl(imageIds[index]);
|
app.image = hashToImageUrl(imageIds[index]);
|
||||||
this.apps.push(app);
|
return app;
|
||||||
});
|
})
|
||||||
});
|
);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('DappsStore:fetchBuiltinApps', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,15 +163,12 @@ export default class DappsStore {
|
|||||||
return apps
|
return apps
|
||||||
.map((app) => {
|
.map((app) => {
|
||||||
app.type = 'local';
|
app.type = 'local';
|
||||||
|
app.visible = true;
|
||||||
return app;
|
return app;
|
||||||
})
|
})
|
||||||
.filter((app) => app.id && !['ui'].includes(app.id));
|
.filter((app) => app.id && !['ui'].includes(app.id));
|
||||||
})
|
})
|
||||||
.then((apps) => {
|
.then(this.addApps)
|
||||||
transaction(() => {
|
|
||||||
(apps || []).forEach((app) => this.apps.push(app));
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.warn('DappsStore:fetchLocal', error);
|
console.warn('DappsStore:fetchLocal', error);
|
||||||
});
|
});
|
||||||
@ -132,7 +192,9 @@ export default class DappsStore {
|
|||||||
.then((appsInfo) => {
|
.then((appsInfo) => {
|
||||||
const appIds = appsInfo
|
const appIds = appsInfo
|
||||||
.map(([appId, owner]) => this._api.util.bytesToHex(appId))
|
.map(([appId, owner]) => this._api.util.bytesToHex(appId))
|
||||||
.filter((appId) => !builtinApps.find((app) => app.id === appId));
|
.filter((appId) => {
|
||||||
|
return (new BigNumber(appId)).gt(0) && !builtinApps.find((app) => app.id === appId);
|
||||||
|
});
|
||||||
|
|
||||||
return Promise
|
return Promise
|
||||||
.all([
|
.all([
|
||||||
@ -147,7 +209,8 @@ export default class DappsStore {
|
|||||||
image: hashToImageUrl(imageIds[index]),
|
image: hashToImageUrl(imageIds[index]),
|
||||||
contentHash: this._api.util.bytesToHex(contentIds[index]).substr(2),
|
contentHash: this._api.util.bytesToHex(contentIds[index]).substr(2),
|
||||||
manifestHash: this._api.util.bytesToHex(manifestIds[index]).substr(2),
|
manifestHash: this._api.util.bytesToHex(manifestIds[index]).substr(2),
|
||||||
type: 'network'
|
type: 'network',
|
||||||
|
visible: true
|
||||||
};
|
};
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
@ -179,11 +242,7 @@ export default class DappsStore {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((apps) => {
|
.then(this.addApps)
|
||||||
transaction(() => {
|
|
||||||
(apps || []).forEach((app) => this.apps.push(app));
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.warn('DappsStore:fetchRegistry', error);
|
console.warn('DappsStore:fetchRegistry', error);
|
||||||
});
|
});
|
||||||
@ -201,44 +260,4 @@ export default class DappsStore {
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_readHiddenApps () {
|
|
||||||
const stored = localStorage.getItem(LS_KEY_HIDDEN);
|
|
||||||
|
|
||||||
if (stored) {
|
|
||||||
try {
|
|
||||||
this.hiddenApps = JSON.parse(stored);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('DappsStore:readHiddenApps', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_readExternalApps () {
|
|
||||||
const stored = localStorage.getItem(LS_KEY_EXTERNAL);
|
|
||||||
|
|
||||||
if (stored) {
|
|
||||||
try {
|
|
||||||
this.externalApps = JSON.parse(stored);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('DappsStore:readExternalApps', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_writeExternalApps () {
|
|
||||||
try {
|
|
||||||
localStorage.setItem(LS_KEY_EXTERNAL, JSON.stringify(this.externalApps));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('DappsStore:writeExternalApps', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_writeHiddenApps () {
|
|
||||||
try {
|
|
||||||
localStorage.setItem(LS_KEY_HIDDEN, JSON.stringify(this.hiddenApps));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('DappsStore:writeHiddenApps', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user