diff --git a/actions/icons.js b/actions/icons.js index 11df9f0..24ead40 100644 --- a/actions/icons.js +++ b/actions/icons.js @@ -1,33 +1,47 @@ const { createActions: createActionCreators } = require('redux-actions'); -// const { getIconPath } = require('../modules/get-gtk-icon'); -const getIconPath = () => { - throw new Error('stub'); -}; +const freedesktopIcons = require('freedesktop-icons'); + +const { iconThemeNames } = require('../utils/theme'); const fallbacks = new Map(Object.entries({ 'audio-card-pci': 'audio-card', 'audio-card-usb': 'audio-card', })); -const getIconPathFallback = async (icon, size) => { - try { - return await getIconPath(icon, size); - } catch (error) { - if (error.message === 'No icon found') { - if (fallbacks.has(icon)) { - return getIconPathFallback(fallbacks.get(icon), size); - } - } - throw error; +const cache = new Map(); + +const getIconWithFallback = async name => { + if (cache.has(name)) { + return cache.get(name); } + + let res = await freedesktopIcons({ + name, + type: 'scalable', + }, iconThemeNames); + + if (!res) { + res = await freedesktopIcons({ + name, + size: 128, + }, iconThemeNames); + } + + if (!res && fallbacks.has(name)) { + return getIconWithFallback(fallbacks.get(name)); + } + + cache.set(name, res); + + return res; }; module.exports = createActionCreators({ ICONS: { GET_ICON_PATH: [ - (icon, size) => getIconPathFallback(icon, size), + icon => getIconWithFallback(icon), icon => icon, ], }, diff --git a/package.json b/package.json index 5e6b814..befceca 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "@jakejarrett/gtk-theme": "^1.1.2", "camelcase": "^5.0.0", "electron-store": "^2.0.0", + "freedesktop-icons": "^0.1.0", + "ini": "^1.3.5", "mathjs": "^5.2.3", "paclient": "^0.0.2", "r-dom": "^2.4.0", diff --git a/utils/theme/index.js b/utils/theme/index.js index 3a3cd1a..ccaa0ae 100644 --- a/utils/theme/index.js +++ b/utils/theme/index.js @@ -1,4 +1,9 @@ +const fs = require('fs'); +const path = require('path'); + +const ini = require('ini'); + const { theme } = require('@jakejarrett/gtk-theme'); const camelCase = require('camelcase'); @@ -8,4 +13,34 @@ theme.css.replace(/@define-color\s+([\w_]+?)\s+(.+?);/g, (_, name, value) => { colors[camelCase(name)] = value; }); -module.exports = { colors }; +const gtkIniPath = path.join( + process.env.HOME, + process.env.XDG_CONFIG_HOME || '.config', + 'gtk-3.0', + 'settings.ini', +); + +const iconThemeNames = (() => { + let gtk; + try { + gtk = ini.parse(fs.readFileSync(gtkIniPath, 'utf-8')); + } catch (error) { + console.error(error); + } + + if (gtk) { + return [ + gtk.Settings['gtk-icon-theme-name'], + gtk.Settings['gtk-fallback-icon-theme'], + 'hicolor', + ]; + } + + return [ 'Adwaita', 'hicolor' ]; +})(); + +module.exports = { + name: theme.theme_name, + iconThemeNames, + colors, +}; diff --git a/yarn.lock b/yarn.lock index 465a766..c79368f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2646,6 +2646,13 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +freedesktop-icons@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/freedesktop-icons/-/freedesktop-icons-0.1.0.tgz#33ed79c3695aa1c73e099497dc6dc4c557035f37" + integrity sha512-bXJgCzaaXg4WxnsF3GU35q5T46fRb/4gz2X7femz05T5jkCQ+Jlquobj1MZ+mpfCQ+kP62isx1jHU+AWF52Smw== + dependencies: + xdg-basedir "^3.0.0" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -3122,7 +3129,7 @@ inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@~1.3.0: +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==