Adding killswitch to clear storage

This commit is contained in:
James Barnsley
2020-09-11 13:53:54 +12:00
parent a4fd0cd8e5
commit 5953fc84cf
12 changed files with 205 additions and 141 deletions

View File

@ -62,11 +62,11 @@ export default class GridItem extends React.Component {
}) => {
switch (uriType(uri)) {
case 'playlist':
return tracks_total ? (
return (
<span className="grid__item__secondary__content">
<I18n path="specs.tracks" count={tracks_total} />
<I18n path="specs.tracks" count={tracks_total || 0} />
</span>
) : null;
);
case 'artist':
return (

View File

@ -40,7 +40,6 @@ class Hotkeys extends React.Component {
ctrlKey,
metaKey,
shiftKey,
preventDefault,
} = e;
key = key.toLowerCase();
@ -71,13 +70,13 @@ class Hotkeys extends React.Component {
uiActions.createNotification({ content: 'play_arrow', type: 'shortcut' });
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Play' });
}
preventDefault();
e.preventDefault();
break;
case 's': // Stop
mopidyActions.stop();
uiActions.createNotification({ content: 'stop', type: 'shortcut' });
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Stop' });
break;
@ -88,14 +87,14 @@ class Hotkeys extends React.Component {
}
mopidyActions.setTimePosition(new_position);
uiActions.createNotification({ content: 'fast_rewind', type: 'shortcut' });
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Rewind' });
break;
case 'f': // Seek forwards 30 sec
mopidyActions.setTimePosition(play_time_position + 30000);
uiActions.createNotification({ content: 'fast_forward', type: 'shortcut' });
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Fastforward' });
break;
@ -103,7 +102,7 @@ class Hotkeys extends React.Component {
case '<': // Previous track
mopidyActions.previous();
uiActions.createNotification({ content: 'skip_previous', type: 'shortcut' });
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Previous' });
break;
@ -111,7 +110,7 @@ class Hotkeys extends React.Component {
case '>': // Next track
mopidyActions.next();
uiActions.createNotification({ content: 'skip_next', type: 'shortcut' });
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Next' });
break;
@ -128,7 +127,7 @@ class Hotkeys extends React.Component {
}
uiActions.createNotification({ content: 'volume_up', type: 'shortcut' });
}
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Volume up' });
break;
@ -144,7 +143,7 @@ class Hotkeys extends React.Component {
}
}
uiActions.createNotification({ content: 'volume_down', type: 'shortcut' });
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Volume down' });
break;
@ -158,36 +157,36 @@ class Hotkeys extends React.Component {
uiActions.createNotification({ content: 'volume_off', type: 'shortcut' });
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Mute' });
}
preventDefault();
e.preventDefault();
break;
case 'escape': // Cancel current action/context
if (dragging) {
uiActions.dragEnd();
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Dragging' });
} else if ($('body').hasClass('modal-open')) {
window.history.back();
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Modal' });
}
break;
case '1': // Navigation: Queue
history.push('/queue');
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Queue' });
break;
case '2': // Navigation: Search
history.push('/search');
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Search' });
break;
case '3': // Navigation: Kiosk mode
history.push('/kiosk-mode');
preventDefault();
e.preventDefault();
if (allow_reporting) ReactGA.event({ category: 'Hotkey', action: key, label: 'Kiosk mode' });
break;

View File

@ -38,7 +38,6 @@ class TrackList extends React.Component {
ctrlKey,
metaKey,
shiftKey,
preventDefault,
} = e;
// When we're focussed on certian elements, don't fire any shortcuts
@ -61,7 +60,7 @@ class TrackList extends React.Component {
if (tracks_keys && tracks_keys.length > 0) {
this.playTracks();
}
preventDefault();
e.preventDefault();
break;
case 'backspace':
@ -69,7 +68,7 @@ class TrackList extends React.Component {
if (tracks_keys && tracks_keys.length > 0) {
this.removeTracks();
}
preventDefault();
e.preventDefault();
break;
case 'a':
@ -78,7 +77,7 @@ class TrackList extends React.Component {
all_tracks.push(this.buildTrackKey(this.props.tracks[i], i));
}
this.props.uiActions.setSelectedTracks(all_tracks);
preventDefault();
e.preventDefault();
break;
}
}

View File

@ -365,6 +365,7 @@ settings:
share_configuration: Share configuration
restart: Restart server
reset_cache: Reset cache
reset_storage: Reset storage
reset: Reset all settings
about:
title: About

View File

@ -18,6 +18,7 @@ import {
getTrackIcon,
formatArtists,
formatArtist,
formatPlaylist,
} from '../../util/format';
import {
arrayOf,
@ -1564,25 +1565,27 @@ const MopidyMiddleware = (function () {
if (!response) return;
const playlist = {
...response,
...formatPlaylist(response),
uri: response.uri,
type: 'playlist',
provider: 'mopidy',
can_edit: true,
};
request(store, 'library.lookup', { uris: arrayOf('uri', response.tracks) })
.then((tracksResponse) => {
const tracks = response.tracks.map((simpleTrack) => {
const fullTracks = tracksResponse[simpleTrack.uri];
return {
...simpleTrack,
...(fullTracks.length ? fullTracks[0] : {}),
};
if (response.tracks) {
request(store, 'library.lookup', { uris: arrayOf('uri', response.tracks) })
.then((tracksResponse) => {
const tracks = response.tracks.map((simpleTrack) => {
const fullTracks = tracksResponse[simpleTrack.uri];
return {
...simpleTrack,
...(fullTracks.length ? fullTracks[0] : {}),
};
});
playlist.tracks = formatTracks(tracks);
store.dispatch(coreActions.itemLoaded(playlist));
});
playlist.tracks = tracks;
store.dispatch(coreActions.itemLoaded(playlist));
});
}
});
break;
@ -2194,15 +2197,17 @@ const MopidyMiddleware = (function () {
playlist_uris.forEach((uri, index) => {
request(store, 'playlists.lookup', { uri })
.then((response) => {
libraryPlaylists.push({
type: 'playlist',
name: response.name,
uri: response.uri,
source: uriSource(response.uri),
provider: 'mopidy',
last_modified: response.last_modified,
tracks: response.tracks,
});
libraryPlaylists.push(
formatPlaylist({
name: response.name,
uri: response.uri,
can_edit: uriSource(response.uri) === 'm3u',
last_modified: response.last_modified,
// By not including actual tracks they will be fetched when needed. We don't
// want these simple tracks because they don't contain duration, artist, etc.
tracks_total: response.tracks ? response.tracks.length : null,
}),
);
if (index === playlist_uris.length - 1) {
store.dispatch(coreActions.itemsLoaded(libraryPlaylists));
@ -2223,7 +2228,6 @@ const MopidyMiddleware = (function () {
request(store, 'library.lookup', { uris })
.then((response) => {
const libraryAlbums = indexToArray(response).map((tracks) => ({
source: 'local',
artists: tracks[0].artists || null,
tracks,
last_modified: tracks[0].last_modified,

View File

@ -426,6 +426,7 @@ const formatPlaylist = function (data) {
'can_edit',
'user',
'tracks',
'tracks_total',
];
// Loop fields and import from data
@ -448,6 +449,10 @@ const formatPlaylist = function (data) {
}
}
if (playlist.tracks_total === undefined) {
playlist.tracks_total = playlist.tracks ? playlist.tracks.length : 0;
}
if (data.last_modified_date && playlist.last_modified === undefined) {
playlist.last_modified = data.last_modified_date;
}

View File

@ -79,6 +79,24 @@ class Settings extends React.Component {
return false;
}
resetStorage = () => {
localForage.keys().then((keys) => {
const keysToKeep = ['persist:root', 'persist:ui', 'persist:spotify'];
const keysToRemove = keys.filter((key) => keysToKeep.indexOf(key) < 0);
keysToRemove.forEach((key, index) => {
localForage.removeItem(key).then(() => {
console.debug(`Removed ${key}`);
if (index === keysToRemove.length) {
console.debug('Reloading...');
window.location = '#';
window.location.reload(true);
}
});
});
});
}
resetServiceWorkerAndCache = () => {
const { coreActions: { handleException } } = this.props;
@ -533,10 +551,6 @@ class Settings extends React.Component {
>
<I18n path="settings.advanced.restart" />
</Button>
<ConfirmationButton
content={i18n('settings.advanced.reset')}
onConfirm={this.resetAllSettings}
/>
<Button
type="destructive"
onClick={this.resetServiceWorkerAndCache}
@ -544,6 +558,17 @@ class Settings extends React.Component {
>
<I18n path="settings.advanced.reset_cache" />
</Button>
<Button
type="destructive"
onClick={this.resetStorage}
tracking={{ category: 'System', action: 'ResetStorage' }}
>
<I18n path="settings.advanced.reset_storage" />
</Button>
<ConfirmationButton
content={i18n('settings.advanced.reset')}
onConfirm={this.resetAllSettings}
/>
</div>
<h4 className="underline">

View File

@ -18,8 +18,8 @@ import { collate } from '../../util/format';
class AddToPlaylist extends React.Component {
componentDidMount = () => {
const {
spotify_library_playlists,
mopidy_library_playlists,
spotify_library,
mopidy_library,
spotify_available,
coreActions: {
loadLibrary,
@ -29,11 +29,11 @@ class AddToPlaylist extends React.Component {
},
} = this.props;
if (!spotify_library_playlists && spotify_available) {
if (!spotify_library && spotify_available) {
loadLibrary('spotify:library:playlists');
}
if (!mopidy_library_playlists) {
if (!mopidy_library) {
loadLibrary('mopidy:library:playlists');
}
@ -56,8 +56,8 @@ class AddToPlaylist extends React.Component {
const {
uris,
items,
spotify_library,
mopidy_library,
spotify_library = { items_uris: [] },
mopidy_library = { items_uris: [] },
} = this.props;
let playlists = [
@ -89,12 +89,8 @@ class AddToPlaylist extends React.Component {
<h4 className="list__item__name">{ playlist.name }</h4>
<ul className="list__item__details details">
<li><Icon type="fontawesome" className="source" name={sourceIcon(playlist.uri)} /></li>
<li>
{playlist.tracks_total && (
<span className="mid_grey-text">
{`${playlist.tracks_total} tracks`}
</span>
)}
<li className="mid_grey-text">
{`${playlist.tracks_total || 0} tracks`}
</li>
</ul>
</div>
@ -114,8 +110,8 @@ const mapStateToProps = (state, ownProps) => ({
uris: (ownProps.match.params.uris ? decodeURIComponent(ownProps.match.params.uris).split(',') : []),
mopidy_uri_schemes: state.mopidy.uri_schemes,
items: state.core.items,
mopidy_library: state.core.libraries['mopidy:library:playlists'] || { items_uris: [] },
spotify_library: state.core.libraries['spotify:library:playlists'] || { items_uris: [] },
mopidy_library: state.core.libraries['mopidy:library:playlists'],
spotify_library: state.core.libraries['spotify:library:playlists'],
spotify_available: state.spotify.access_token,
load_queue: state.ui.load_queue,
me_id: (state.spotify.me ? state.spotify.me.id : false),