From b95ad0b94e4000450c3bc867841a8fe000d0674c Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Tue, 26 Nov 2024 12:07:30 -0300 Subject: [PATCH] fix: Icon color att app files Signed-off-by: Vitor Mattos --- package-lock.json | 53 +++++++++++++++++++++++++++++------ package.json | 1 + src/helpers/useIsDarkTheme.js | 40 ++++++++++++++++++++++++++ src/init.js | 4 ++- src/utils/isDarkTheme.js | 24 ++++++++++++++++ 5 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 src/helpers/useIsDarkTheme.js create mode 100644 src/utils/isDarkTheme.js diff --git a/package-lock.json b/package-lock.json index 41195ccea9..30c5a66e42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "@nextcloud/router": "^3.0.1", "@nextcloud/upload": "^1.7.0", "@nextcloud/vue": "^8.21.0", + "@vueuse/core": "^11.3.0", "blueimp-md5": "^2.19.0", "copy-webpack-plugin": "^12.0.2", "crypto-js": "^4.2.0", @@ -4593,6 +4594,30 @@ "vue-demi": ">=0.14.10" } }, + "node_modules/@vueuse/components/node_modules/@vueuse/core": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.2.0.tgz", + "integrity": "sha512-JIUwRcOqOWzcdu1dGlfW04kaJhW3EXnnjJJfLTtddJanymTL7lF1C0+dVVZ/siLfc73mWn+cGP1PE1PKPruRSA==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "11.2.0", + "@vueuse/shared": "11.2.0", + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/components/node_modules/@vueuse/metadata": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.2.0.tgz", + "integrity": "sha512-L0ZmtRmNx+ZW95DmrgD6vn484gSpVeRbgpWevFKXwqqQxW9hnSi2Ppuh2BzMjnbv4aJRiIw8tQatXT9uOB23dQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@vueuse/components/node_modules/vue-demi": { "version": "0.14.10", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", @@ -4620,14 +4645,26 @@ } }, "node_modules/@vueuse/core": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.2.0.tgz", - "integrity": "sha512-JIUwRcOqOWzcdu1dGlfW04kaJhW3EXnnjJJfLTtddJanymTL7lF1C0+dVVZ/siLfc73mWn+cGP1PE1PKPruRSA==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.3.0.tgz", + "integrity": "sha512-7OC4Rl1f9G8IT6rUfi9JrKiXy4bfmHhZ5x2Ceojy0jnd3mHNEvV4JaRygH362ror6/NZ+Nl+n13LPzGiPN8cKA==", "license": "MIT", "dependencies": { "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "11.2.0", - "@vueuse/shared": "11.2.0", + "@vueuse/metadata": "11.3.0", + "@vueuse/shared": "11.3.0", + "vue-demi": ">=0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/@vueuse/shared": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.3.0.tgz", + "integrity": "sha512-P8gSSWQeucH5821ek2mn/ciCk+MS/zoRKqdQIM3bHq6p7GXDAJLmnRRKmF5F65sAVJIfzQlwR3aDzwCn10s8hA==", + "license": "MIT", + "dependencies": { "vue-demi": ">=0.14.10" }, "funding": { @@ -4661,9 +4698,9 @@ } }, "node_modules/@vueuse/metadata": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.2.0.tgz", - "integrity": "sha512-L0ZmtRmNx+ZW95DmrgD6vn484gSpVeRbgpWevFKXwqqQxW9hnSi2Ppuh2BzMjnbv4aJRiIw8tQatXT9uOB23dQ==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.3.0.tgz", + "integrity": "sha512-pwDnDspTqtTo2HwfLw4Rp6yywuuBdYnPYDq+mO38ZYKGebCUQC/nVj/PXSiK9HX5otxLz8Fn7ECPbjiRz2CC3g==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" diff --git a/package.json b/package.json index c22d13ff11..adf05c5a65 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@nextcloud/router": "^3.0.1", "@nextcloud/upload": "^1.7.0", "@nextcloud/vue": "^8.21.0", + "@vueuse/core": "^11.3.0", "blueimp-md5": "^2.19.0", "copy-webpack-plugin": "^12.0.2", "crypto-js": "^4.2.0", diff --git a/src/helpers/useIsDarkTheme.js b/src/helpers/useIsDarkTheme.js new file mode 100644 index 0000000000..30100a6229 --- /dev/null +++ b/src/helpers/useIsDarkTheme.js @@ -0,0 +1,40 @@ +/** + * SPDX-FileCopyrightText: 2024 LibreCode coop and contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { createSharedComposable, useMutationObserver, usePreferredDark } from '@vueuse/core' +import { ref, watch } from 'vue' + +import { checkIfDarkTheme } from '../utils/isDarkTheme.js' + +/** + * Check whether the dark theme is enabled on a specific element. + * If you need to check an entire page, use `useIsDarkTheme` instead. + * Reacts on element attributes changes and system theme changes. + * @param {HTMLElement} el - The element to check for the dark theme enabled on + * @return {boolean} - computed boolean whether the dark theme is enabled + */ +export function useIsDarkThemeElement(el = document.body) { + const isDarkTheme = ref(checkIfDarkTheme(el)) + const isDarkSystemTheme = usePreferredDark() + + /** Update the isDarkTheme */ + function updateIsDarkTheme() { + isDarkTheme.value = checkIfDarkTheme(el) + } + + // Watch for element changes to handle data-theme* attributes change + useMutationObserver(el, updateIsDarkTheme, { attributes: true }) + // Watch for system theme changes for the default theme + watch(isDarkSystemTheme, updateIsDarkTheme, { immediate: true }) + + return isDarkTheme +} + +/** + * Shared composable to check whether the dark theme is enabled on the page. + * Reacts on body data-theme-* attributes changes and system theme changes. + * @return {boolean} - computed boolean whether the dark theme is enabled + */ +export const useIsDarkTheme = createSharedComposable(() => useIsDarkThemeElement()) diff --git a/src/init.js b/src/init.js index bc8ed84e1a..94851e5a94 100644 --- a/src/init.js +++ b/src/init.js @@ -13,6 +13,8 @@ import { getUploader } from '@nextcloud/upload' import logger from './logger.js' import LibreSignLogoSvg from '../img/app-colored.svg?raw' +import LibreSignLogoDarkSvg from '../img/app-dark.svg?raw' +import { useIsDarkTheme } from './helpers/useIsDarkTheme.js' Vue.prototype.t = translate Vue.prototype.n = translatePlural @@ -22,7 +24,7 @@ Vue.prototype.OCA = OCA addNewFileMenuEntry({ id: 'libresign-request', displayName: t('libresign', 'New signature request'), - iconSvgInline: LibreSignLogoSvg, + iconSvgInline: useIsDarkTheme() ? LibreSignLogoDarkSvg : LibreSignLogoSvg, uploadManager: getUploader(), order: 1, enabled() { diff --git a/src/utils/isDarkTheme.js b/src/utils/isDarkTheme.js new file mode 100644 index 0000000000..577c686ea0 --- /dev/null +++ b/src/utils/isDarkTheme.js @@ -0,0 +1,24 @@ +/** + * SPDX-FileCopyrightText: 2024 LibreCode coop and contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +/** + * Check if dark theme is used on a specific element + * @param {HTMLElement} el - Element to check for dark theme, default is document.body, which is used for data-theme-* settings + * @return {boolean} - Whether the dark theme is enabled via Nextcloud theme + */ +export function checkIfDarkTheme(el = document.body) { + // Nextcloud uses --background-invert-if-dark for dark theme filters in CSS + // Values: + // - 'invert(100%)' for dark theme + // - 'no' for light theme + // This is the most reliable way to check for dark theme, including custom themes + const backgroundInvertIfDark = window.getComputedStyle(el).getPropertyValue('--background-invert-if-dark') + if (backgroundInvertIfDark !== undefined) { + return backgroundInvertIfDark === 'invert(100%)' + } + + // There is no theme? Fallback to the light theme + return false +}