Refactor: Improve display of notifications to indicate severity. This allow user to disable toasts and just rely on color coding

This commit is contained in:
arabcoders 2025-11-20 16:49:50 +03:00
parent c74c6ed60e
commit 4d22e345e5
3 changed files with 54 additions and 4 deletions

View file

@ -45,11 +45,12 @@
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
<span class="icon"><i class="fas fa-bell" /></span>
<span class="tag ml-2">
<span class="is-underlined">{{ store.unreadCount }}</span>
<span class="tag ml-2" :class="store.severityColor">
<span :class="{ 'is-bold': store.unreadCount }">{{ store.unreadCount }}</span>
<span>&nbsp;/&nbsp;</span>
<span class="is-underlined">{{ store.notifications.length }}</span>
</span>
<span class="icon ml-2" v-if="store.severityIcon"><i :class="store.severityIcon" /></span>
</a>
<div class="navbar-dropdown is-right" style="width: 400px;">
<template v-if="store.notifications.length > 0">

View file

@ -204,7 +204,7 @@ const pauseDownload = () => {
dialog_confirm.value.visible = true
dialog_confirm.value.html_message = `
<span class="icon-text">
<span class="icon"><i class="fa-solid fa-exclamation-triangle"/></span>
<span class="icon"><i class="fa-solid fa-exclamation-triangle"></i></span>
<span class="is-bold">Pause All non-active downloads?</span>
</span>
<br>

View file

@ -2,10 +2,46 @@ import { defineStore } from 'pinia'
import { useStorage } from '@vueuse/core'
import type { notification, notificationType } from '~/composables/useNotification'
const _map: Record<notificationType, { level: number; color: string; icon: string }> = {
'error': { level: 3, color: 'is-danger', icon: 'fas fa-circle-exclamation' },
'warning': { level: 2, color: 'is-warning', icon: 'fas fa-triangle-exclamation' },
'success': { level: 1, color: 'is-primary', icon: 'fas fa-circle-check' },
'info': { level: 0, color: 'is-info', icon: 'fas fa-circle-info' }
}
export const useNotificationStore = defineStore('notifications', () => {
const notifications = useStorage<notification[]>('notifications', [])
const unreadCount = computed<number>(() => notifications.value.filter(n => !n.seen).length)
const severityLevel = computed<notificationType | null>(() => {
const unread = notifications.value.filter(n => !n.seen)
if (0 === unread.length) {
return null
}
return unread.reduce((h, n) => _map[n.level].level > _map[h.level].level ? n : h).level
})
const severityColor = computed<string>(() => {
const level = severityLevel.value
return level ? _map[level].color : ''
})
const severityIcon = computed<string>(() => {
const level = severityLevel.value
return level ? _map[level].icon : ''
})
const sortedNotifications = computed<notification[]>(() => {
return [...notifications.value].sort((a, b) => {
const severityDiff = _map[b.level].level - _map[a.level].level
if (0 !== severityDiff) {
return severityDiff
}
return (new Date(b.created).getTime()) - (new Date(a.created).getTime())
})
})
const add = (level: notificationType, message: string, seen: boolean = false): string => {
const id = Array.from(
window.crypto.getRandomValues(new Uint8Array(14 / 2)),
@ -43,5 +79,18 @@ export const useNotificationStore = defineStore('notifications', () => {
const remove = (id: string) => notifications.value = notifications.value.filter(n => n.id !== id)
return { notifications, unreadCount, add, get, markAllRead, clear, markRead, remove }
return {
notifications,
unreadCount,
severityLevel,
severityColor,
severityIcon,
sortedNotifications,
add,
get,
markAllRead,
clear,
markRead,
remove
}
})