diff --git a/src/js/locale/en.yaml b/src/js/locale/en.yaml
index f2894499..8b338653 100755
--- a/src/js/locale/en.yaml
+++ b/src/js/locale/en.yaml
@@ -569,6 +569,12 @@ modal:
title: Now playing
title_window: '%{name} by %{artist} (now playing)'
lyrics: Lyrics
+ import_configuration:
+ title: Import configuration
+ subtitle: Import third-party authorizations and other settings
+ subtitle_push: Another user has shared their configuration with you
+ configurations: Configurations to import
+ import_now: Import now
share_configuration:
title: Share configuration
subtitle: Push your authorizations and interface settings to another, connected user
@@ -580,6 +586,9 @@ modal:
snapcast_description: Server connection details
interface: Interface settings
interface_description: Theme, sorting, filters, etc
+ server:
+ title: Server
+ description: Make available for any user to import
import:
title: Configuration shared
subtitle: 'Another user has shared their configuration with you. This includes:'
diff --git a/src/js/services/pusher/middleware.js b/src/js/services/pusher/middleware.js
index 9f2d2104..44f70b3c 100755
--- a/src/js/services/pusher/middleware.js
+++ b/src/js/services/pusher/middleware.js
@@ -92,11 +92,7 @@ const PusherMiddleware = (function () {
store.dispatch(spotifyActions.tokenChanged(params.spotify_token));
break;
case 'share_configuration_received':
- store.dispatch(uiActions.createNotification({
- type: 'share-configuration-received',
- configuration: params,
- sticky: true,
- }));
+ store.dispatch(uiActions.openModal('import-configuration', params));
break;
case 'notification':
store.dispatch(uiActions.createNotification(params.notification));
diff --git a/src/js/services/ui/actions.js b/src/js/services/ui/actions.js
index d464ddfb..85874595 100755
--- a/src/js/services/ui/actions.js
+++ b/src/js/services/ui/actions.js
@@ -265,6 +265,14 @@ export function removeNotification(key, manual = false) {
};
}
+export function openModal(name, data) {
+ return {
+ type: 'OPEN_MODAL',
+ name,
+ data,
+ };
+}
+
/**
* Loaders
* */
diff --git a/src/js/services/ui/middleware.js b/src/js/services/ui/middleware.js
index 6e9bed42..2bd13bf6 100755
--- a/src/js/services/ui/middleware.js
+++ b/src/js/services/ui/middleware.js
@@ -1,5 +1,3 @@
-import ReactGA from 'react-ga';
-
const uiActions = require('./actions.js');
const UIMiddleware = (function () {
@@ -39,21 +37,10 @@ const UIMiddleware = (function () {
break;
case 'OPEN_MODAL':
- if (store.getState().ui.allow_reporting) {
- ReactGA.event({ category: 'Modal', action: 'Opened', label: action.modal.name });
- }
- $('body').addClass('modal-open');
- store.dispatch(uiActions.hideContextMenu());
- store.dispatch(uiActions.hideTouchContextMenu());
- next(action);
- break;
-
- case 'CLOSE_MODAL':
- if (store.getState().ui.allow_reporting) {
- ReactGA.event({ category: 'Modal', action: 'Closed', label: null });
- }
- $('body').removeClass('modal-open');
- next(action);
+ const { name } = action;
+ window.location = `/iris/modal/${name}`;
+ console.debug(action);
+ next(action); // Save data to state
break;
case 'HIDE_CONTEXT_MENU':
diff --git a/src/js/services/ui/reducer.js b/src/js/services/ui/reducer.js
index 6bedfa37..f5c792b6 100755
--- a/src/js/services/ui/reducer.js
+++ b/src/js/services/ui/reducer.js
@@ -76,10 +76,7 @@ export default function reducer(ui = {}, action) {
* Modals
* */
case 'OPEN_MODAL':
- return { ...ui, modal: action.modal };
-
- case 'CLOSE_MODAL':
- return { ...ui, modal: false };
+ return { ...ui, modal: action.data };
/**
* Notifications
diff --git a/src/js/views/Modals/ImportConfiguration.js b/src/js/views/Modals/ImportConfiguration.js
new file mode 100644
index 00000000..a70a25c7
--- /dev/null
+++ b/src/js/views/Modals/ImportConfiguration.js
@@ -0,0 +1,121 @@
+import React, { useState, useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { pick } from 'lodash';
+import Modal from './Modal';
+import { setWindowTitle, set as setUi, createNotification } from '../../services/ui/actions';
+import * as spotifyActions from '../../services/spotify/actions';
+import * as snapcastActions from '../../services/snapcast/actions';
+import * as lastfmActions from '../../services/lastfm/actions';
+import * as geniusActions from '../../services/genius/actions';
+import { i18n, I18n } from '../../locale';
+import Button from '../../components/Button';
+import { titleCase } from '../../util/helpers';
+
+const ImportConfiguration = () => {
+ const dispatch = useDispatch();
+ const [selected, setSelected] = useState([]);
+ const configuration = useSelector((state) => state.ui?.modal || {});
+
+ useEffect(() => {
+ setWindowTitle(i18n('modal.import_configuration.title'));
+ }, []);
+
+ const onSelectedChanged = (name) => {
+ setSelected((prev) => {
+ if (prev.indexOf(name) > -1) return prev.filter((prevName) => prevName !== name);
+
+ return [...prev, name];
+ });
+ }
+
+ const onSubmit = (e) => {
+ e.preventDefault();
+ const toImport = pick(configuration, selected);
+
+ if (toImport.ui) {
+ dispatch(setUi(toImport.ui));
+ }
+ if (toImport.spotify) {
+ dispatch(spotifyActions.importAuthorization(
+ toImport.spotify.authorization,
+ toImport.spotify.me,
+ ));
+ }
+ if (toImport.snapcast) {
+ dispatch(snapcastActions.set(toImport.snapcast));
+ setTimeout(() => dispatch(snapcastActions.connect()), 100);
+ }
+ if (toImport.lastfm) {
+ dispatch(lastfmActions.importAuthorization(
+ toImport.lastfm.authorization,
+ toImport.lastfm.me,
+ ));
+ }
+ if (toImport.genius) {
+ dispatch(geniusActions.importAuthorization(
+ toImport.genius.authorization,
+ toImport.genius.me,
+ ));
+ }
+ dispatch(createNotification({
+ content: i18n('modal.share_configuration.import.successful'),
+ }));
+
+ window.history.back();
+ }
+
+ return (
+
+
+
+
+
+
+