Add Desktop Notifications
This commit is contained in:
parent
b8d47d1db4
commit
2397a7e464
|
@ -22,6 +22,7 @@ import {
|
|||
playQueueReducer,
|
||||
albumViewReducer,
|
||||
activityReducer,
|
||||
settingsReducer,
|
||||
} from './reducers'
|
||||
import createAdminStore from './store/createAdminStore'
|
||||
import { i18nProvider } from './i18n'
|
||||
|
@ -50,6 +51,7 @@ const App = () => (
|
|||
theme: themeReducer,
|
||||
addToPlaylistDialog: addToPlaylistDialogReducer,
|
||||
activity: activityReducer,
|
||||
settings: settingsReducer,
|
||||
},
|
||||
})}
|
||||
>
|
||||
|
|
|
@ -3,3 +3,4 @@ export * from './themes'
|
|||
export * from './albumView'
|
||||
export * from './dialogs'
|
||||
export * from './serverEvents'
|
||||
export * from './settings'
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
export const SET_NOTIFICATIONS_STATE = 'SET_NOTIFICATIONS_STATE'
|
||||
|
||||
export const setNotificationsState = (enabled) => ({
|
||||
type: SET_NOTIFICATIONS_STATE,
|
||||
data: enabled,
|
||||
})
|
|
@ -18,6 +18,7 @@ import themes from '../themes'
|
|||
import config from '../config'
|
||||
import PlayerToolbar from './PlayerToolbar'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import { sendNotification, baseUrl } from '../utils'
|
||||
|
||||
const useStyle = makeStyles((theme) => ({
|
||||
audioTitle: {
|
||||
|
@ -54,6 +55,7 @@ const Player = () => {
|
|||
const queue = useSelector((state) => state.queue)
|
||||
const current = queue.current || {}
|
||||
const { authenticated } = useAuthState()
|
||||
const showNotifications = useSelector((state) => state.settings.notifications || false)
|
||||
|
||||
const visible = authenticated && queue.queue.length > 0
|
||||
const classes = useStyle({ visible })
|
||||
|
@ -230,9 +232,12 @@ const Player = () => {
|
|||
label: `${info.name} - ${info.singer}`,
|
||||
})
|
||||
}
|
||||
if (showNotifications) {
|
||||
sendNotification(info.name, `${info.singer} - ${info.album}`, baseUrl(info.cover))
|
||||
}
|
||||
}
|
||||
},
|
||||
[dispatch]
|
||||
[dispatch, showNotifications]
|
||||
)
|
||||
|
||||
const onAudioPause = useCallback(
|
||||
|
|
|
@ -262,7 +262,8 @@
|
|||
"songsAddedToPlaylist": "Added 1 song to playlist |||| Added %{smart_count} songs to playlist",
|
||||
"noPlaylistsAvailable": "None available",
|
||||
"delete_user_title": "Delete user '%{name}'",
|
||||
"delete_user_content": "Are you sure you want to delete this user and all their data (including playlists and preferences)?"
|
||||
"delete_user_content": "Are you sure you want to delete this user and all their data (including playlists and preferences)?",
|
||||
"notifications_blocked": "You have blocked Notifications for this site in your browser's settings or your browser does not support notifications."
|
||||
},
|
||||
"menu": {
|
||||
"library": "Library",
|
||||
|
@ -274,7 +275,8 @@
|
|||
"options": {
|
||||
"theme": "Theme",
|
||||
"language": "Language",
|
||||
"defaultView": "Default View"
|
||||
"defaultView": "Default View",
|
||||
"desktop_notifications": "Desktop Notifications"
|
||||
}
|
||||
},
|
||||
"albumList": "Albums",
|
||||
|
|
|
@ -8,10 +8,15 @@ import {
|
|||
useLocale,
|
||||
useSetLocale,
|
||||
useTranslate,
|
||||
BooleanInput,
|
||||
useNotify,
|
||||
} from 'react-admin'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import HelpOutlineIcon from '@material-ui/icons/HelpOutline'
|
||||
import { changeTheme } from '../actions'
|
||||
import {
|
||||
changeTheme,
|
||||
setNotificationsState,
|
||||
} from '../actions'
|
||||
import themes from '../themes'
|
||||
import { docsUrl } from '../utils'
|
||||
import { useGetLanguageChoices } from '../i18n'
|
||||
|
@ -119,6 +124,45 @@ const SelectDefaultView = (props) => {
|
|||
)
|
||||
}
|
||||
|
||||
const NotificationsToggle = (props) => {
|
||||
const translate = useTranslate()
|
||||
const dispatch = useDispatch()
|
||||
const notify = useNotify()
|
||||
const currentSetting = useSelector((state) => state.settings.notifications)
|
||||
const current = (() => {
|
||||
if (!("Notification" in window) || Notification.permission !== 'granted') {
|
||||
return false
|
||||
}
|
||||
return currentSetting
|
||||
})()
|
||||
|
||||
return (
|
||||
<BooleanInput
|
||||
{...props}
|
||||
source='notifications'
|
||||
label={translate('menu.personal.options.desktop_notifications')}
|
||||
defaultValue={current}
|
||||
onChange={async (notificationsEnabled) => {
|
||||
if (notificationsEnabled) {
|
||||
if (!('Notification' in window) || Notification.permission === 'denied') {
|
||||
notify(translate('message.notifications_blocked'), 'warning')
|
||||
notificationsEnabled = false
|
||||
} else {
|
||||
const response = await Notification.requestPermission()
|
||||
if (response !== 'granted') {
|
||||
notificationsEnabled = false
|
||||
}
|
||||
}
|
||||
if (!notificationsEnabled) {
|
||||
// Need to turn switch off
|
||||
}
|
||||
}
|
||||
dispatch(setNotificationsState(notificationsEnabled))
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const Personal = () => {
|
||||
const translate = useTranslate()
|
||||
const classes = useStyles()
|
||||
|
@ -130,6 +174,7 @@ const Personal = () => {
|
|||
<SelectTheme />
|
||||
<SelectLanguage />
|
||||
<SelectDefaultView />
|
||||
<NotificationsToggle />
|
||||
</SimpleForm>
|
||||
</Card>
|
||||
)
|
||||
|
|
|
@ -3,3 +3,4 @@ export * from './dialogReducer'
|
|||
export * from './playQueue'
|
||||
export * from './albumView'
|
||||
export * from './activityReducer'
|
||||
export * from './settingsReducer'
|
||||
|
|
|
@ -23,6 +23,7 @@ const mapToAudioLists = (item) => {
|
|||
trackId: id,
|
||||
name: item.title,
|
||||
singer: item.artist,
|
||||
album: item.album,
|
||||
albumId: item.albumId,
|
||||
artistId: item.albumArtistId,
|
||||
duration: item.duration,
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { SET_NOTIFICATIONS_STATE } from '../actions'
|
||||
|
||||
const initialState = {
|
||||
notifications: false,
|
||||
}
|
||||
|
||||
export const settingsReducer = (previousState = initialState, payload) => {
|
||||
const { type, data } = payload
|
||||
switch (type) {
|
||||
case SET_NOTIFICATIONS_STATE:
|
||||
return {
|
||||
...previousState,
|
||||
notifications: data
|
||||
}
|
||||
default:
|
||||
return previousState
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@ export default ({
|
|||
theme: state.theme,
|
||||
queue: pick(state.queue, ['queue', 'volume']),
|
||||
albumView: state.albumView,
|
||||
settings: state.settings,
|
||||
})
|
||||
}),
|
||||
1000
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './baseUrl'
|
||||
export * from './docsUrl'
|
||||
export * from './formatters'
|
||||
export * from './notifications'
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
export const sendNotification = (title, body = '', image = '') => {
|
||||
checkForNotificationPermission()
|
||||
new Notification(title, {
|
||||
body: body,
|
||||
icon: image,
|
||||
silent: true
|
||||
})
|
||||
}
|
||||
|
||||
const checkForNotificationPermission = () => {
|
||||
return 'Notification' in window && Notification.permission === 'granted'
|
||||
}
|
Loading…
Reference in New Issue