change storage error one-off into a global notice system

This commit is contained in:
Shpuld Shpuldson 2020-07-02 10:40:41 +03:00
parent 0997e5ff66
commit 1293bec77e
8 changed files with 167 additions and 40 deletions

View file

@ -13,6 +13,7 @@ import MobilePostStatusButton from './components/mobile_post_status_button/mobil
import MobileNav from './components/mobile_nav/mobile_nav.vue' import MobileNav from './components/mobile_nav/mobile_nav.vue'
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue' import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
import PostStatusModal from './components/post_status_modal/post_status_modal.vue' import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue'
import { windowWidth } from './services/window_utils/window_utils' import { windowWidth } from './services/window_utils/window_utils'
export default { export default {
@ -32,7 +33,8 @@ export default {
MobileNav, MobileNav,
SettingsModal, SettingsModal,
UserReportingModal, UserReportingModal,
PostStatusModal PostStatusModal,
GlobalNoticeList
}, },
data: () => ({ data: () => ({
mobileActivePanel: 'timeline', mobileActivePanel: 'timeline',
@ -107,9 +109,6 @@ export default {
return { return {
'order': this.$store.state.instance.sidebarRight ? 99 : 0 'order': this.$store.state.instance.sidebarRight ? 99 : 0
} }
},
showStorageError () {
return this.$store.state.interface.storageError === 'show'
} }
}, },
methods: { methods: {
@ -132,9 +131,6 @@ export default {
if (changed) { if (changed) {
this.$store.dispatch('setMobileLayout', mobileLayout) this.$store.dispatch('setMobileLayout', mobileLayout)
} }
},
hideStorageError () {
this.$store.dispatch('setStorageError', 'hide')
} }
} }
} }

View file

@ -806,15 +806,6 @@ nav {
} }
} }
.storage-error-notice {
text-align: center;
i {
cursor: pointer;
color: $fallback--text;
color: var(--alertErrorText, $fallback--text);
}
}
.button-icon { .button-icon {
font-size: 1.2em; font-size: 1.2em;
} }

View file

@ -101,16 +101,6 @@
</div> </div>
</div> </div>
<div class="main"> <div class="main">
<div
v-if="showStorageError"
class="alert error storage-error-notice"
>
{{ $t("errors.storage_unavailable") }}
<i
class="icon-cancel"
@click="hideStorageError"
/>
</div>
<div <div
v-if="!currentUser" v-if="!currentUser"
class="login-hint panel panel-default" class="login-hint panel panel-default"
@ -138,6 +128,7 @@
<PostStatusModal /> <PostStatusModal />
<SettingsModal /> <SettingsModal />
<portal-target name="modal" /> <portal-target name="modal" />
<GlobalNoticeList />
</div> </div>
</template> </template>

View file

@ -0,0 +1,15 @@
const GlobalNoticeList = {
computed: {
notices () {
return this.$store.state.interface.globalNotices
}
},
methods: {
closeNotice (notice) {
this.$store.dispatch('removeGlobalNotice', notice)
}
}
}
export default GlobalNoticeList

View file

@ -0,0 +1,77 @@
<template>
<div class="global-notice-list">
<div
v-for="(notice, index) in notices"
:key="index"
class="alert global-notice"
:class="{ ['global-' + notice.level]: true }"
>
<div class="notice-message">
{{ $t(notice.messageKey, notice.messageArgs) }}
</div>
<i
class="button-icon icon-cancel"
@click="closeNotice(notice)"
/>
</div>
</div>
</template>
<script src="./global_notice_list.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.global-notice-list {
position: fixed;
top: 50px;
width: 100%;
pointer-events: none;
z-index: 1001;
display: flex;
flex-direction: column;
align-items: center;
.global-notice {
pointer-events: auto;
text-align: center;
width: 40em;
max-width: calc(100% - 3em);
display: flex;
padding-left: 1.5em;
line-height: 2em;
.notice-message {
flex: 1 1 100%;
}
i {
flex: 0 0;
width: 1.5em;
cursor: pointer;
}
}
.global-error {
background-color: var(--alertPopupError, $fallback--cRed);
color: var(--alertPopupErrorText, $fallback--text);
i {
color: var(--alertPopupErrorText, $fallback--text);
}
}
.global-warning {
background-color: var(--alertPopupWarning, $fallback--cOrange);
color: var(--alertPopupWarningText, $fallback--text);
i {
color: var(--alertPopupWarningText, $fallback--text);
}
}
.global-info {
background-color: var(--alertPopupNeutral, $fallback--fg);
color: var(--alertPopupNeutralText, $fallback--text);
i {
color: var(--alertPopupNeutralText, $fallback--text);
}
}
}
</style>

View file

@ -62,14 +62,14 @@ const persistedStateOptions = {
}; };
(async () => { (async () => {
let persistedState let storageError = false
let storageError = 'none' const plugins = [pushNotifications]
try { try {
persistedState = await createPersistedState(persistedStateOptions) const persistedState = await createPersistedState(persistedStateOptions)
plugins.push(persistedState)
} catch (e) { } catch (e) {
console.error(e) console.error(e)
storageError = 'show' storageError = true
persistedState = _ => _
} }
const store = new Vuex.Store({ const store = new Vuex.Store({
modules: { modules: {
@ -93,11 +93,13 @@ const persistedStateOptions = {
polls: pollsModule, polls: pollsModule,
postStatus: postStatusModule postStatus: postStatusModule
}, },
plugins: [persistedState, pushNotifications], plugins,
strict: false // Socket modifies itself, let's ignore this for now. strict: false // Socket modifies itself, let's ignore this for now.
// strict: process.env.NODE_ENV !== 'production' // strict: process.env.NODE_ENV !== 'production'
}) })
store.dispatch('setStorageError', storageError) if (storageError) {
store.dispatch('pushGlobalNotice', { messageKey: 'errors.storage_unavailable', level: 'error' })
}
afterStoreSetup({ store, i18n }) afterStoreSetup({ store, i18n })
})() })()

View file

@ -8,14 +8,14 @@ const defaultState = {
noticeClearTimeout: null, noticeClearTimeout: null,
notificationPermission: null notificationPermission: null
}, },
storageError: 'none',
browserSupport: { browserSupport: {
cssFilter: window.CSS && window.CSS.supports && ( cssFilter: window.CSS && window.CSS.supports && (
window.CSS.supports('filter', 'drop-shadow(0 0)') || window.CSS.supports('filter', 'drop-shadow(0 0)') ||
window.CSS.supports('-webkit-filter', 'drop-shadow(0 0)') window.CSS.supports('-webkit-filter', 'drop-shadow(0 0)')
) )
}, },
mobileLayout: false mobileLayout: false,
globalNotices: []
} }
const interfaceMod = { const interfaceMod = {
@ -60,8 +60,11 @@ const interfaceMod = {
state.settingsModalLoaded = true state.settingsModalLoaded = true
} }
}, },
setStorageError (state, value) { pushGlobalNotice (state, notice) {
state.storageError = value state.globalNotices.push(notice)
},
removeGlobalNotice (state, notice) {
state.globalNotices = state.globalNotices.filter(n => n !== notice)
} }
}, },
actions: { actions: {
@ -86,8 +89,26 @@ const interfaceMod = {
togglePeekSettingsModal ({ commit }) { togglePeekSettingsModal ({ commit }) {
commit('togglePeekSettingsModal') commit('togglePeekSettingsModal')
}, },
setStorageError ({ commit }, value) { pushGlobalNotice (
commit('setStorageError', value) { commit, dispatch },
{
messageKey,
messageArgs = {},
level = 'error',
timeout = 0
}) {
const notice = {
messageKey,
messageArgs,
level
}
if (timeout) {
setTimeout(() => dispatch('removeGlobalNotice', notice), timeout)
}
commit('pushGlobalNotice', notice)
},
removeGlobalNotice ({ commit }, notice) {
commit('removeGlobalNotice', notice)
} }
} }
} }

View file

@ -34,7 +34,8 @@ export const DEFAULT_OPACITY = {
alert: 0.5, alert: 0.5,
input: 0.5, input: 0.5,
faint: 0.5, faint: 0.5,
underlay: 0.15 underlay: 0.15,
alertPopup: 0.85
} }
/** SUBJECT TO CHANGE IN THE FUTURE, this is all beta /** SUBJECT TO CHANGE IN THE FUTURE, this is all beta
@ -627,6 +628,39 @@ export const SLOT_INHERITANCE = {
textColor: true textColor: true
}, },
alertPopupError: {
depends: ['alertError'],
opacity: 'alertPopup'
},
alertPopupErrorText: {
depends: ['alertErrorText'],
layer: 'popover',
variant: 'alertPopupError',
textColor: true
},
alertPopupWarning: {
depends: ['alertWarning'],
opacity: 'alertPopup'
},
alertPopupWarningText: {
depends: ['alertWarningText'],
layer: 'popover',
variant: 'alertPopupWarning',
textColor: true
},
alertPopupNeutral: {
depends: ['alertNeutral'],
opacity: 'alertPopup'
},
alertPopupNeutralText: {
depends: ['alertNeutralText'],
layer: 'popover',
variant: 'alertPopupNeutral',
textColor: true
},
badgeNotification: '--cRed', badgeNotification: '--cRed',
badgeNotificationText: { badgeNotificationText: {
depends: ['text', 'badgeNotification'], depends: ['text', 'badgeNotification'],