add favicon badge for unread notifs
This commit is contained in:
parent
f0a66448ee
commit
350eb489c2
6 changed files with 64 additions and 1 deletions
|
@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Import/export a muted users
|
- Import/export a muted users
|
||||||
- Proper handling of deletes when using websocket streaming
|
- Proper handling of deletes when using websocket streaming
|
||||||
- Added optimistic chat message sending, so you can start writing next message before the previous one has been sent
|
- Added optimistic chat message sending, so you can start writing next message before the previous one has been sent
|
||||||
|
- Added a small red badge to the favicon when there's unread notifications
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed chats list not updating its order when new messages come in
|
- Fixed chats list not updating its order when new messages come in
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
|
||||||
<title>Pleroma</title>
|
<title>Pleroma</title>
|
||||||
<!--server-generated-meta-->
|
<!--server-generated-meta-->
|
||||||
<link rel="icon" type="image/png" href="/favicon.png">
|
<link rel="icon" type="image/png" href="/static/dev_favicon.png">
|
||||||
</head>
|
</head>
|
||||||
<body class="hidden">
|
<body class="hidden">
|
||||||
<noscript>To use Pleroma, please enable JavaScript.</noscript>
|
<noscript>To use Pleroma, please enable JavaScript.</noscript>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { getOrCreateApp, getClientToken } from '../services/new_api/oauth.js'
|
||||||
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
||||||
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
||||||
import { applyTheme } from '../services/style_setter/style_setter.js'
|
import { applyTheme } from '../services/style_setter/style_setter.js'
|
||||||
|
import FaviconService from '../services/favicon_service/favicon_service.js'
|
||||||
|
|
||||||
let staticInitialResults = null
|
let staticInitialResults = null
|
||||||
|
|
||||||
|
@ -326,6 +327,8 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
const width = windowWidth()
|
const width = windowWidth()
|
||||||
store.dispatch('setMobileLayout', width <= 800)
|
store.dispatch('setMobileLayout', width <= 800)
|
||||||
|
|
||||||
|
FaviconService.initFaviconService()
|
||||||
|
|
||||||
const overrides = window.___pleromafe_dev_overrides || {}
|
const overrides = window.___pleromafe_dev_overrides || {}
|
||||||
const server = (typeof overrides.target !== 'undefined') ? overrides.target : window.location.origin
|
const server = (typeof overrides.target !== 'undefined') ? overrides.target : window.location.origin
|
||||||
store.dispatch('setInstanceOption', { name: 'server', value: server })
|
store.dispatch('setInstanceOption', { name: 'server', value: server })
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
filteredNotificationsFromStore,
|
filteredNotificationsFromStore,
|
||||||
unseenNotificationsFromStore
|
unseenNotificationsFromStore
|
||||||
} from '../../services/notification_utils/notification_utils.js'
|
} from '../../services/notification_utils/notification_utils.js'
|
||||||
|
import FaviconService from '../../services/favicon_service/favicon_service.js'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
@ -75,8 +76,10 @@ const Notifications = {
|
||||||
watch: {
|
watch: {
|
||||||
unseenCountTitle (count) {
|
unseenCountTitle (count) {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
|
FaviconService.drawFaviconBadge()
|
||||||
this.$store.dispatch('setPageTitle', `(${count})`)
|
this.$store.dispatch('setPageTitle', `(${count})`)
|
||||||
} else {
|
} else {
|
||||||
|
FaviconService.clearFaviconBadge()
|
||||||
this.$store.dispatch('setPageTitle', '')
|
this.$store.dispatch('setPageTitle', '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
56
src/services/favicon_service/favicon_service.js
Normal file
56
src/services/favicon_service/favicon_service.js
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { find } from 'lodash'
|
||||||
|
|
||||||
|
const createFaviconService = () => {
|
||||||
|
let favimg, favcanvas, favcontext, favicon
|
||||||
|
const faviconWidth = 48
|
||||||
|
const faviconHeight = 48
|
||||||
|
const strokeColor = 'rgb(200, 0, 0)'
|
||||||
|
const fillColor = 'rgb(255, 90, 90)'
|
||||||
|
const badgeRadius = 12
|
||||||
|
|
||||||
|
const initFaviconService = () => {
|
||||||
|
const nodes = document.getElementsByTagName('link')
|
||||||
|
favicon = find(nodes, node => node.rel === 'icon')
|
||||||
|
if (favicon) {
|
||||||
|
favcanvas = document.createElement('canvas')
|
||||||
|
favcanvas.width = faviconWidth
|
||||||
|
favcanvas.height = faviconHeight
|
||||||
|
favimg = new Image()
|
||||||
|
favimg.src = favicon.href
|
||||||
|
favcontext = favcanvas.getContext('2d')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearFaviconBadge = () => {
|
||||||
|
if (!favimg || !favcontext || !favicon) return
|
||||||
|
|
||||||
|
favcontext.clearRect(0, 0, faviconWidth, faviconHeight)
|
||||||
|
favcontext.drawImage(favimg, 0, 0, favimg.width, favimg.height, 0, 0, faviconWidth, faviconHeight)
|
||||||
|
favicon.href = favcanvas.toDataURL('image/png')
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawFaviconBadge = () => {
|
||||||
|
if (!favimg || !favcontext || !favcontext) return
|
||||||
|
|
||||||
|
clearFaviconBadge()
|
||||||
|
|
||||||
|
favcontext.drawImage(favimg, 0, 0, favimg.width, favimg.height, 0, 0, faviconWidth, faviconHeight)
|
||||||
|
favcontext.fillStyle = fillColor
|
||||||
|
favcontext.strokeStyle = strokeColor
|
||||||
|
favcontext.beginPath()
|
||||||
|
favcontext.arc(faviconWidth - badgeRadius, faviconHeight - badgeRadius, badgeRadius, 0, 2 * Math.PI, false)
|
||||||
|
favcontext.fill()
|
||||||
|
favcontext.stroke()
|
||||||
|
favicon.href = favcanvas.toDataURL('image/png')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
initFaviconService,
|
||||||
|
clearFaviconBadge,
|
||||||
|
drawFaviconBadge
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const FaviconService = createFaviconService()
|
||||||
|
|
||||||
|
export default FaviconService
|
BIN
static/dev_favicon.png
Normal file
BIN
static/dev_favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Loading…
Reference in a new issue