diff --git a/css/styles.scss b/css/styles.scss index 21b2bc14..781d591f 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -9,18 +9,23 @@ padding: 10px; opacity: .6; - .svg { - width: 20px; - height: 20px; - } - &:hover, &:focus { opacity: 1 !important; } + .notification__dot { + fill: #ff4402; + &--white { + fill: var(--color-primary-text); + } + } + &.hasNotifications { opacity: 1 !important; + animation-name: pulse; + animation-duration: 1600ms; + animation-iteration-count: 4; &:hover, &:focus { @@ -28,12 +33,23 @@ } } - &, - img { + * { cursor: pointer; } } +@keyframes pulse { + 0% { + opacity: 1; + } + 60% { + opacity: .6; + } + 100% { + opacity: 1; + } +} + .notification-container { display: none; right: 13px; @@ -51,7 +67,7 @@ padding: 50px 0; margin: 0; - @include icon-black-white('notifications-dark', 'notifications', 1); + @include icon-black-white('notifications', 'notifications', 1); } .dismiss-all { @@ -140,16 +156,6 @@ } } - img.notification-icon { - width: 32px; - height: 32px; - display: flex; - - body.theme--dark & { - filter: invert(1); - } - } - strong { font-weight: bold; opacity: 1; diff --git a/img/notifications-dark.svg b/img/notifications-dark.svg index 1bc88f4c..cb059a06 100644 --- a/img/notifications-dark.svg +++ b/img/notifications-dark.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/img/notifications-new-dark.svg b/img/notifications-new-dark.svg deleted file mode 100644 index 8a318aed..00000000 --- a/img/notifications-new-dark.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/img/notifications-new.svg b/img/notifications-new.svg deleted file mode 100644 index 6e1630fc..00000000 --- a/img/notifications-new.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/img/notifications-red-new-dark.svg b/img/notifications-red-new-dark.svg deleted file mode 100644 index 94218dba..00000000 --- a/img/notifications-red-new-dark.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/img/notifications-red-new.svg b/img/notifications-red-new.svg deleted file mode 100644 index 31e013e9..00000000 --- a/img/notifications-red-new.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/img/notifications.png b/img/notifications.png index ee525c0d..f0e6d1fa 100644 Binary files a/img/notifications.png and b/img/notifications.png differ diff --git a/img/notifications.svg b/img/notifications.svg index a77cc418..54835a6d 100644 --- a/img/notifications.svg +++ b/img/notifications.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9ba10940..cf192f69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2061,6 +2061,55 @@ "npm": "^7.0.0" } }, + "node_modules/@nextcloud/vue/node_modules/loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/@nextcloud/vue/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@nextcloud/vue/node_modules/style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/@nextcloud/webpack-vue-config": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@nextcloud/webpack-vue-config/-/webpack-vue-config-5.0.0.tgz", @@ -2257,8 +2306,7 @@ "node_modules/@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "peer": true + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -2673,7 +2721,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2731,7 +2778,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peer": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -3396,8 +3442,6 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "peer": true, "engines": { "node": "*" } @@ -5258,8 +5302,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "peer": true, "engines": { "node": ">= 4" } @@ -6621,8 +6663,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "peer": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.2.7", @@ -6707,8 +6748,7 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "peer": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -8769,8 +8809,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "peer": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -10781,7 +10820,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "peer": true, "engines": { "node": ">=6" } @@ -12534,6 +12572,8 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "peer": true, "engines": { "node": ">= 12.13.0" }, @@ -13684,7 +13724,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "peer": true, "dependencies": { "punycode": "^2.1.0" } @@ -16139,6 +16178,36 @@ "vue-material-design-icons": "^5.0.0", "vue-multiselect": "^2.1.6", "vue2-datepicker": "^3.6.3" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "style-loader": { + "version": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + } } }, "@nextcloud/webpack-vue-config": { @@ -16307,8 +16376,7 @@ "@types/json-schema": { "version": "7.0.9", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "peer": true + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, "@types/json5": { "version": "0.0.29", @@ -16693,7 +16761,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -16737,7 +16804,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peer": true, "requires": {} }, "amdefine": { @@ -17273,9 +17339,7 @@ "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "peer": true + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, "binary-extensions": { "version": "1.13.1", @@ -18753,9 +18817,7 @@ "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "peer": true + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, "encodeurl": { "version": "1.0.2", @@ -19778,8 +19840,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "peer": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.7", @@ -19848,8 +19909,7 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "peer": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -21386,8 +21446,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "peer": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -22976,8 +23035,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "peer": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "q": { "version": "1.5.1", @@ -24352,6 +24410,8 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "peer": true, "requires": {} }, "style-search": { @@ -25204,7 +25264,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "peer": true, "requires": { "punycode": "^2.1.0" } diff --git a/src/App.vue b/src/App.vue index b738d638..5bf698c6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -10,12 +10,25 @@ aria-controls="notification-container" aria-expanded="false" @click="requestWebNotificationPermissions"> - + fill-color="var(--color-primary-text)" /> + + + + + + +
-
-
-

- {{ t('notifications', 'Requesting browser permissions to show notifications') }} -

-

- {{ t('notifications', 'No notifications') }} -

-
+ + + + {{ webNotificationsGranted === null + ? t('notifications', 'Requesting browser permissions to show notifications') + : t('notifications', 'No notifications') }} + +
@@ -63,11 +79,13 @@ import Button from '@nextcloud/vue/dist/Components/Button' import Close from 'vue-material-design-icons/Close' import axios from '@nextcloud/axios' import { subscribe, unsubscribe } from '@nextcloud/event-bus' -import { loadState } from '@nextcloud/initial-state' import { showError } from '@nextcloud/dialogs' -import { imagePath, generateOcsUrl } from '@nextcloud/router' +import { generateOcsUrl } from '@nextcloud/router' import { getNotificationsData } from './services/notificationsService' import { listen } from '@nextcloud/notify_push' +import Bell from 'vue-material-design-icons/Bell' +import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent' +import { getCapabilities } from '@nextcloud/capabilities' export default { name: 'App', @@ -75,17 +93,18 @@ export default { components: { Button, Close, + Bell, + EmptyContent, Notification, }, data() { return { webNotificationsGranted: false, - hadNotifications: false, backgroundFetching: false, hasNotifyPush: false, shutdown: false, - theming: {}, + theming: getCapabilities()?.theming || {}, notifications: [], lastETag: null, lastTabId: null, @@ -106,27 +125,6 @@ export default { _$icon: null, computed: { - iconPath() { - let iconPath = 'notifications' - - if (this.webNotificationsGranted === null || this.notifications.length) { - if (this.isRedThemed) { - iconPath += '-red' - } - iconPath += '-new' - } - - if (this.invertedTheme) { - iconPath += '-dark' - } - - return imagePath('notifications', iconPath) - }, - - invertedTheme() { - return !!this.theming?.inverted - }, - isRedThemed() { if (this.theming?.color) { const hsl = this.rgbToHsl(this.theming.color.substring(1, 3), @@ -146,11 +144,6 @@ export default { }, }, - beforeMount() { - console.debug('Loading theming data for notification bell styling') - this.theming = loadState('theming', 'data', {}) - }, - mounted() { this.tabId = OC.requestToken || ('' + Math.random()) this._$icon = $(this.$refs.icon) @@ -187,19 +180,6 @@ export default { unsubscribe('networkOnline', this.handleNetworkOnline) }, - updated() { - if (!this.hadNotifications && this.notifications.length) { - console.debug('New notification, animating the bell icon') - this._$icon - .animate({ opacity: 0.6 }, 600) - .animate({ opacity: 1 }, 600) - .animate({ opacity: 0.6 }, 600) - .animate({ opacity: 1 }, 600) - } - - this.hadNotifications = this.notifications.length > 0 - }, - methods: { handleNetworkOffline() { console.debug('Network is offline, slowing down pollingInterval to ' + this.pollIntervalBase * 10) @@ -432,21 +412,25 @@ export default { diff --git a/src/Components/Notification.vue b/src/Components/Notification.vue index 4e42f405..e49fffed 100644 --- a/src/Components/Notification.vue +++ b/src/Components/Notification.vue @@ -320,8 +320,17 @@ export default {