Skip to content

Commit

Permalink
Fixed: Show only the last notification and show others on mouse hover
Browse files Browse the repository at this point in the history
  • Loading branch information
mbnuqw committed Apr 7, 2023
1 parent 22ee069 commit 2947fe3
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 62 deletions.
13 changes: 12 additions & 1 deletion src/services/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export const Notifications = {
err,
notify,
resetTimer,
resetTimers,
restartTimer,
restartTimers,
progress,
finishProgress,
updateProgress,
Expand All @@ -32,15 +34,20 @@ function notify(config: Notification, timeout = 5555): Notification {
config.id = id
if (!config.lvl) config.lvl = 'info'
config.timeout = timeout
restartTimer(config)
if (timersEnabled) restartTimer(config)
const len = Notifications.reactive.list.push(config)
return Notifications.reactive.list[len - 1]
}

let timersEnabled = true
function resetTimer(nn: Notification): void {
if (nn.timer) clearTimeout(nn.timer)
nn.timer = undefined
}
function resetTimers(): void {
timersEnabled = false
Notifications.reactive.list.forEach(resetTimer)
}

function restartTimer(nn: Notification): void {
if (nn.timer) clearTimeout(nn.timer)
Expand All @@ -51,6 +58,10 @@ function restartTimer(nn: Notification): void {
}, nn.timeout)
}
}
function restartTimers(): void {
timersEnabled = true
Notifications.reactive.list.forEach(restartTimer)
}

function progress(config: Notification): Notification {
const id = Utils.uid()
Expand Down
79 changes: 79 additions & 0 deletions src/sidebar/components/popup.notification.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<template lang="pug">
.notification(
v-if="notification"
:key="notification.id"
:data-lvl="notification.lvl"
:data-timeout="!!notification.timer"
:style="getTimeoutCSSVar(notification)"
@mousedown.left="onMouseDown()")
.header(@mousedown.middle="onHideMouseDown()")
.icon(v-if="notification.icon")
svg(v-if="notification.icon[0] === '#'")
use(:xlink:href="notification.icon")
img(v-else :src="notification.icon")
.title {{notification.title}}
.details(v-if="notification.details" @mousedown.middle="onHideMouseDown()") {{notification.details}}
.progress(v-if="notification.progress"
:data-progress-unknown="notification.progress.percent === -1"
:style="getProgressPercent(notification)")
.progress-bar
.progress-bar-value

.ctrls(v-if="notification.ctrl || notification.controls")
.ctrl(v-if="notification.ctrl" @click="onCtrlMouseDown($event, index, notification?.callback)")
.label {{notification.ctrl}}
.separator(v-if="notification.ctrl")
template(v-for="ctrl in notification.controls" :key="ctrl.label")
.ctrl(
:data-icon="!!ctrl.icon"
:title="ctrl.label"
@click="onCtrlMouseDown($event, index, ctrl.callback)")
svg(v-if="ctrl.icon")
use(:xlink:href="ctrl.icon")
.label(v-else-if="ctrl.label") {{ctrl.label}}
.separator
.ctrl(
data-icon="true"
:title="translate('notif.hide_tooltip')"
@click="onHideMouseDown()")
svg.-close
use(xlink:href="#icon_close")
</template>

<script lang="ts" setup>
import { translate } from 'src/dict'
import { Notification } from 'src/types'
import { Notifications } from 'src/services/notifications'
const props = defineProps<{
notification: Notification
index: number
}>()
function getProgressPercent(info: Notification): Record<string, string> {
return { '--percent': `${info.progress?.percent ?? 0}%` }
}
function onMouseDown(): void {
if (!props.notification.ctrl && !props.notification.controls) onHideMouseDown()
}
function onHideMouseDown(): void {
Notifications.reactive.list.splice(props.index, 1)
Notifications.setHiddenRecently()
}
function onCtrlMouseDown(e: MouseEvent, index: number, cb?: () => void): void {
if (e.button !== 0) return
if (cb) {
cb()
Notifications.reactive.list.splice(index, 1)
Notifications.setHiddenRecently()
}
}
function getTimeoutCSSVar(info: Notification): Record<string, string> | undefined {
if (!info.timeout) return
return { '--timeout': `${info.timeout + 200}ms` }
}
</script>
109 changes: 49 additions & 60 deletions src/sidebar/components/popup.notifications.vue
Original file line number Diff line number Diff line change
@@ -1,78 +1,67 @@
<template lang="pug">
.Notifications
.Notifications(
@mouseenter="Notifications.resetTimers(), onMouseEnter()"
@mouseleave="Notifications.restartTimers(), onMouseLeave()")
TransitionGroup(name="notification" tag="div")
.notification(
v-for="(info, i) in Notifications.reactive.list"
:key="info.id"
:data-lvl="info.lvl"
:data-timeout="!!info.timer"
:style="getTimeoutCSSVar(info)"
@mousedown="onMouseDown($event, info, i)"
@mouseenter="Notifications.resetTimer(info)"
@mouseleave="Notifications.restartTimer(info)")
.header
.icon(v-if="info.icon")
svg(v-if="info.icon[0] === '#'")
use(:xlink:href="info.icon")
img(v-else :src="info.icon")
.title {{info.title}}
.details(v-if="info.details") {{info.details}}
.progress(v-if="info.progress"
:data-progress-unknown="info.progress.percent === -1"
:style="getProgressPercent(info)")
.progress-bar
.progress-bar-value
.indicators(v-if="restNotifications.length && !restNotificationsVisible" :key="'ind'")
.indicator(v-for="i of restNotifications.length" :key="i"): .ring

NotificationContainer(
v-if="restNotificationsVisible"
v-for="(n, i) of restNotifications"
:key="n.id"
:notification="n"
:index="i")

NotificationContainer(
v-if="activeNotif"
:key="activeNotif.id"
:notification="activeNotif"
:index="activeNotificationIndex")

.ctrls(v-if="info.ctrl || info.controls")
.ctrl(v-if="info.ctrl" @click="onCtrlMouseDown($event, i, info.callback)")
.label {{info.ctrl}}
.separator(v-if="info.ctrl")
template(v-for="ctrl in info.controls" :key="ctrl.label")
.ctrl(
:data-icon="!!ctrl.icon"
:title="ctrl.label"
@click="onCtrlMouseDown($event, i, ctrl.callback)")
svg(v-if="ctrl.icon")
use(:xlink:href="ctrl.icon")
.label(v-else-if="ctrl.label") {{ctrl.label}}
.separator
.ctrl(
data-icon="true"
:title="translate('notif.hide_tooltip')"
@click="onHideMouseDown($event, i)")
svg
use(xlink:href="#icon_expand")
</template>

<script lang="ts" setup>
import { translate } from 'src/dict'
import { computed, ref, watch } from 'vue'
import { Notification } from 'src/types'
import { Notifications } from 'src/services/notifications'
import NotificationContainer from './popup.notification.vue'
function getProgressPercent(info: Notification): Record<string, string> {
return { '--percent': `${info.progress?.percent ?? 0}%` }
}
const activeNotificationIndex = ref(0)
const restNotificationsVisible = ref(false)
const activeNotif = computed<Notification | null>(() => {
return Notifications.reactive.list[activeNotificationIndex.value] ?? null
})
const restNotifications = computed<Notification[]>(() => {
const pre = Notifications.reactive.list.slice(0, activeNotificationIndex.value)
const post = Notifications.reactive.list.slice(activeNotificationIndex.value + 1)
return pre.concat(post)
})
watch(Notifications.reactive.list, () => {
activeNotificationIndex.value = Notifications.reactive.list.length - 1
})
function onMouseDown(e: MouseEvent, info: Notification, index: number): void {
if (!info.ctrl && !info.controls) onHideMouseDown(e, index)
function onMouseEnter() {
showRestNotifications()
}
function onHideMouseDown(e: MouseEvent, index: number): void {
Notifications.reactive.list.splice(index, 1)
Notifications.setHiddenRecently()
function onMouseLeave() {
hideRestNotifications()
}
function onCtrlMouseDown(e: MouseEvent, index: number, cb?: () => void): void {
if (e.button !== 0) return
if (cb) {
cb()
Notifications.reactive.list.splice(index, 1)
Notifications.setHiddenRecently()
}
function showRestNotifications() {
clearTimeout(hideRestNotificationsTimeout)
restNotificationsVisible.value = true
}
function getTimeoutCSSVar(info: Notification): Record<string, string> | undefined {
if (!info.timeout) return
return { '--timeout': `${info.timeout + 200}ms` }
let hideRestNotificationsTimeout: number | undefined
function hideRestNotifications() {
clearTimeout(hideRestNotificationsTimeout)
hideRestNotificationsTimeout = setTimeout(() => {
restNotificationsVisible.value = false
}, 250)
}
</script>
34 changes: 33 additions & 1 deletion src/styles/themes/proton/sidebar/popup.notifications.styl
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@
fill: var(--notification-fg)
flex-shrink: 0
opacity: .7
> svg.-close
width: 11px
height: 11px
&:hover:before
opacity: .08
&:hover .label
Expand All @@ -276,10 +279,39 @@
flex-grow: 0
width: 30px

.Notifications .indicators
position: relative
height: 7px
width: 100%
padding: 0 calc(var(--notification-border-radius) + var(--notification-margin))
display: flex
justify-content: flex-end
align-items: flex-start
flex-shrink: 0
grid-gap: var(--notification-margin)
z-index: 100

.Notifications .indicators .indicator
position: relative
height: 5px
width: 5px
border-radius: var(--notification-border-radius)
background-color: var(--notification-bg)
overflow: clip
&:before
content: ''
position: absolute
top: 0
left: 0
width: 100%
height: 100%
opacity: .3
background-color: var(--notification-fg)

#root .notification-enter-active
#root .notification-leave-active
transition: transform var(--d-fast), opacity var(--d-fast), z-index var(--d-fast)
#root .notification-leave-active
#root .notification.notification-leave-active
position: absolute
width: calc(100% - var(--notification-margin) * 2)
#root .notification-move
Expand Down

0 comments on commit 2947fe3

Please sign in to comment.