Adding killswitch to clear storage
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
20
mopidy_iris/static/app.min.js
vendored
20
mopidy_iris/static/app.min.js
vendored
File diff suppressed because one or more lines are too long
@ -106,7 +106,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1599594930";
|
||||
var build = "1599762714";
|
||||
var version = "3.52.4";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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),
|
||||
|
||||
Reference in New Issue
Block a user