import * as Uebersicht from "uebersicht"; import * as Themes from "./styles/themes"; import * as Utils from "./utils"; import UserWidgetsCreator from "./components/settings/user-widgets-creator.jsx"; import AerospaceDisplayManager from "./components/settings/aerospace-display-manager.jsx"; export { Component, styles, Wrapper } from "./components/settings/settings.jsx"; const SETTINGS_STORAGE_KEY = "simple-bar-settings"; // The available themes are retrieved from the Themes collection // They are then split into dark and light themes const availableThemes = Object.keys(Themes.collection).map((key) => { const theme = Themes.collection[key]; return { code: key, name: theme.name, kind: theme.kind }; }); const darkThemes = availableThemes.filter((theme) => theme.kind === "dark"); const lightThemes = availableThemes.filter((theme) => theme.kind === "light"); // These are all the information displayed in the settings module export const data = { global: { label: "Global", documentation: "/global-settings/", infos: [ '- "No bar background" is visually better with the "Floating bar" option activated', '- The higher the "Sliding animation pace" value, the faster the texts slides (must be > 0, default is set to 4)', "
", '"Use background color as foreground":', "This setting will remove all background colors and use the removed color for all the foreground texts", ], }, theme: { label: "theme", type: "radio", options: ["auto", "dark", "light"], title: "Appearance & tweaks", }, floatingBar: { label: "Floating bar", type: "checkbox" }, noBarBg: { label: "No bar background", type: "checkbox" }, noColorInData: { label: "No colors in data", type: "checkbox" }, bottomBar: { label: "Bottom bar", type: "checkbox" }, sideDecoration: { label: "Apple logo", type: "checkbox" }, inlineSpacesOptions: { label: "Inline spaces options", type: "checkbox" }, disableAnimations: { label: "Disable persistent animations", type: "checkbox", }, enableMissives: { label: "Use internal notification system (missives)", type: "checkbox", fullWidth: true, }, disableNotifications: { label: "Disable notifications", type: "checkbox" }, compactMode: { label: "Compact mode", type: "checkbox" }, widgetMaxWidth: { label: "Widget max width", type: "text" }, widgetsBackgroundColorAsForeground: { label: "Use background color as foreground for widgets", type: "checkbox", fullWidth: true, }, spacesBackgroundColorAsForeground: { label: "Use background color as foreground for spaces & process", type: "checkbox", fullWidth: true, }, font: { label: "Global font", type: "text", placeholder: "default: JetBrains Mono", fullWidth: false, }, fontSize: { label: "Font size", type: "text", placeholder: "default: 11px", fullWidth: false, }, yabaiPath: { label: "yabai path", type: "text", placeholder: "default: $(which yabai)", fullWidth: true, title: "Configuration", }, aerospacePath: { label: "Aerospace path", type: "text", placeholder: "default: $(which aerospace)", fullWidth: true, }, windowManager: { title: "Which window or space manager are you using?", label: "", type: "radio", options: ["yabai", "aerospace"], }, shell: { title: "With which shell do you want to execute simple-bar scripts?", label: "", type: "radio", options: ["sh", "bash", "dash"], }, terminal: { title: "Which terminal should user facing commands be run in?", label: "", type: "radio", options: ["Terminal", "iTerm2"], }, slidingAnimationPace: { label: "Sliding animation speed", type: "number", placeholder: "Default: 4", fullWidth: true, }, enableServer: { label: "Enable simple-bar-server connection", type: "checkbox", fullWidth: true, title: "simple-bar-server", }, serverHttpPort: { label: "simple-bar-server http port", type: "number", placeholder: "Default: 7776", fullWidth: true, }, serverSocketPort: { label: "simple-bar-server socket port", type: "number", placeholder: "Default: 7777", fullWidth: true, }, yabaiServerRefresh: { label: "Refresh yabai spaces & process with simple-bar-server", type: "checkbox", fullWidth: true, }, aerospaceServerRefresh: { label: "Refresh AeroSpace spaces with simple-bar-server", type: "checkbox", fullWidth: true, }, themes: { label: "Themes", documentation: "/themes-settings/", infos: [ "Colors defined here will override the selected theme. Leave it empty to use the theme colors.", "
", "You can use any valid CSS color:", "- named-color", "- hex-color", "- rgb()", "- hsl()", "- hwb()", "
", "Styles are applied in this order:", "- Theme", "- Color overrides", "- Custom styles", "
", "The last one overrides the previous ones.", ], }, darkTheme: { label: "Dark theme", type: "select", options: darkThemes }, lightTheme: { label: "Light theme", type: "select", options: lightThemes }, colorMain: { label: "Main", type: "color", title: "Color overrides" }, colorMainAlt: { label: "Main alternative", type: "color" }, colorMinor: { label: "Minor", type: "color" }, colorAccent: { label: "Accent", type: "color" }, colorRed: { label: "Red", type: "color" }, colorGreen: { label: "Green", type: "color" }, colorYellow: { label: "Yellow", type: "color" }, colorOrange: { label: "Orange", type: "color" }, colorBlue: { label: "Blue", type: "color" }, colorMagenta: { label: "Magenta", type: "color" }, colorCyan: { label: "Cyan", type: "color" }, colorBlack: { label: "Black", type: "color" }, colorWhite: { label: "White", type: "color" }, colorForeground: { label: "Foreground", type: "color" }, colorBackground: { label: "Background", type: "color" }, process: { label: "Process", documentation: "/process-settings/", }, displayForFocusedSpace: { label: "yabai Display for focused space instead of current display space (usefull when you have simple-bar on one display in multi-monitor setup)", type: "checkbox", fullWidth: true, }, displayOnlyCurrent: { label: "yabai AeroSpace Display only current process name", type: "checkbox", fullWidth: true, }, centered: { label: "yabai AeroSpace Center process widget", type: "checkbox", }, showCurrentSpaceMode: { label: "yabai Show current space mode (BSP, Stack, Float)", type: "checkbox", fullWidth: true, }, hideWindowTitle: { label: "yabai AeroSpace Hide window titles (show only app name for each process)", type: "checkbox", fullWidth: true, }, displayOnlyIcon: { label: "yabai AeroSpace Display only process icon", type: "checkbox", fullWidth: true, }, expandAllProcesses: { label: "yabai AeroSpace Expand all processes", type: "checkbox", fullWidth: true, }, displaySkhdMode: { label: "yabai Display current skhd mode (requires some configuration, see readme file)", type: "checkbox", fullWidth: true, }, displayStackIndex: { label: "yabai Display stack-index for all processes in space (if greater than 0)", type: "checkbox", fullWidth: true, }, displayOnlyCurrentStack: { label: "yabai Display stack-index only for focused process", type: "checkbox", fullWidth: true, }, spacesDisplay: { label: "Spaces", documentation: "/spaces-settings/", infos: [ "You can declare here which apps to exclude from the spaces display", 'Each exclusion must be separated by a comma and a space ", "', "These exclusions will also be applied on the process name display", ], }, exclusions: { label: "yabai AeroSpace Exclusions by app name", type: "text", placeholder: "example: Finder, iTerm2", fullWidth: true, }, titleExclusions: { label: "yabai AeroSpace Exclusions by window title name", type: "text", placeholder: "example: Preferences", fullWidth: true, }, spacesExclusions: { label: "yabai AeroSpace Exclude spaces by space name", type: "text", placeholder: "example: Preferences", fullWidth: true, }, exclusionsAsRegex: { label: "yabai AeroSpace Use regex syntax in all exclusions fields", type: "checkbox", fullWidth: true, }, displayAllSpacesOnAllScreens: { label: "yabai AeroSpace Display all spaces on all screens", type: "checkbox", fullWidth: true, }, hideEmptySpaces: { label: "yabai AeroSpace Hide empty spaces", type: "checkbox", }, showOptionsOnHover: { label: "yabai Show space options on hover", type: "checkbox", fullWidth: true, }, switchSpacesWithoutYabai: { label: "yabai Switch spaces with ^⭠/^⭢ instead of yabai", type: "checkbox", fullWidth: true, }, hideDuplicateAppsInSpaces: { label: "yabai AeroSpace Hide duplicate app icons in same space", type: "checkbox", fullWidth: true, }, displayStickyWindowsSeparately: { label: "yabai Display sticky windows separately", type: "checkbox", fullWidth: true, }, hideCreateSpaceButton: { label: "yabai Hide create space button", type: "checkbox", fullWidth: true, }, customAeroSpaceDisplayIndexes: { label: "AeroSpace Custom AeroSpace display indexes", type: "component", Component: AerospaceDisplayManager, }, widgets: { label: "Widgets", documentation: "/widgets/", }, processWidget: { label: "Process name", type: "checkbox" }, zoomWidget: { label: "Zoom", type: "checkbox" }, timeWidget: { label: "Time", type: "checkbox" }, dateWidget: { label: "Date", type: "checkbox" }, wifiWidget: { label: "Network", type: "checkbox" }, vpnWidget: { label: "Viscosity VPN", type: "checkbox" }, micWidget: { label: "Microphone", type: "checkbox" }, soundWidget: { label: "Sound", type: "checkbox" }, githubWidget: { label: "GitHub", type: "checkbox" }, weatherWidget: { label: "Weather", type: "checkbox" }, netstatsWidget: { label: "Network stats", type: "checkbox" }, cpuWidget: { label: "CPU", type: "checkbox" }, gpuWidget: { label: "GPU", type: "checkbox" }, memoryWidget: { label: "Memory", type: "checkbox" }, batteryWidget: { label: "Battery", type: "checkbox" }, keyboardWidget: { label: "Keyboard", type: "checkbox" }, spotifyWidget: { label: "Spotify", type: "checkbox" }, youtubeMusicWidget: { label: "YouTube Music", type: "checkbox" }, cryptoWidget: { label: "Crypto", type: "checkbox" }, stockWidget: { label: "Stock", type: "checkbox" }, musicWidget: { label: "Music/iTunes", type: "checkbox" }, mpdWidget: { label: "MPD state via mpc", type: "checkbox" }, browserTrackWidget: { label: "Browser track", type: "checkbox" }, notificationsWidget: { label: "Notification badges", type: "checkbox" }, nextMeetingWidget: { label: "Next meeting", type: "checkbox" }, showOnDisplay: { label: "Show on display n°", type: "text", placeholder: "example: 1,2 (leave blank to show on all displays)", fullWidth: true, }, githubWidgetOptions: { label: "GitHub", documentation: "/github/", }, hideWhenNoNotification: { label: "Hide widget when no notification", type: "checkbox", }, notificationUrl: { label: "The URL opened on click", type: "text", placeholder: "example: https://github.com/notifications", fullWidth: true, }, ghBinaryPath: { label: "Path to gh binary", type: "text", placeholder: "example: /opt/homebrew/bin/gh", fullWidth: true, }, weatherWidgetOptions: { label: "Weather", documentation: "/weather/", infos: [ 'Leave "Your location" blank in order to let simple-bar use your geolocation.', "Doing so, you need to allow Übersicht access to your location: a popup should appear on first use.", ], }, showIcon: { label: "Show icon", type: "checkbox" }, unit: { title: "Temperature unit", label: "", type: "radio", options: ["C", "F"], }, hideLocation: { label: "Hide location", type: "checkbox" }, hideGradient: { label: "Hide gradient", type: "checkbox" }, customLocation: { label: "Your location", type: "text", placeholder: "example: Paris", fullWidth: true, }, netstatsWidgetOptions: { label: "Network stats", documentation: "/network-stats/", infos: [ "Here you can set the refresh frequency of the widget.", "The default value is set to 2000 ms (2 seconds).", ], }, netstatsThreshold: { label: "Hide below (kb/s)", type: "number", placeholder: "0 to always show", }, cpuWidgetOptions: { label: "CPU usage", documentation: "/cpu/", infos: [ "Here you can set the refresh frequency of the widget.", "The default value is set to 2000 ms (2 seconds).", ], }, cpuUsageThreshold: { label: "Hide below (%)", type: "number", placeholder: "0 to always show", }, gpuWidgetOptions: { label: "GPU usage", documentation: "/gpu/", infos: [ "Here you can set the refresh frequency of the widget.", "The default value is set to 2000 ms (2 seconds).", ], }, gpuMacmonBinaryPath: { label: "Path to macmon binary", type: "text", placeholder: "example: /opt/homebrew/bin/macmon", fullWidth: true, }, memoryWidgetOptions: { label: "Memory pressure", documentation: "/memory-pressure/", infos: [ "Here you can set the refresh frequency of the widget.", "The default value is set to 4000 ms (4 seconds).", ], }, memoryUsageThreshold: { label: "Hide below (%)", type: "number", placeholder: "0 to always show", }, displayAsGraph: { label: "Display as graph", type: "checkbox", fullWidth: true, }, cpuMonitorApp: { title: "Cpu monitor app", label: "", type: "radio", options: ["Top", "Activity Monitor", "None"], }, memoryMonitorApp: { title: " app", label: "", type: "radio", options: ["Top", "Activity Monitor", "None"], }, batteryWidgetOptions: { label: "Battery", documentation: "/battery/", infos: [ "no option (default) — Prevent the system from sleeping, not the display", "-d — Prevent the display from sleeping.", "-i — Prevent the system from idle sleeping.", "-s — Prevent the system from sleeping. This is valid only when system is running on AC power.", "-u — Declare that a user is active. If the display is off, this option turns the display on and prevents the display from going into idle sleep.", "-t 60 — Specifies the timeout value in seconds for which the command is valid.", ], }, toggleCaffeinateOnClick: { label: "Toggle caffeinate on click", type: "checkbox", fullWidth: true, }, disableCaffeinateInvertedBackground: { label: "Disable caffeinate inverted background", type: "checkbox", fullWidth: true, }, caffeinateOption: { label: "Caffeinate options", type: "text", placeholder: "example: -d", }, networkWidgetOptions: { label: "Network", documentation: "/network/", infos: [ "Here you can override the default displayed network source.", "And also turn Wifi on / off when clicking the Wifi icon.", "Additionally, you can choose to hide the network name for privacy.", ], }, networkDevice: { label: "Network device source name", type: "text", placeholder: "example: en0", }, hideWifiIfDisabled: { label: "Hide if disabled", type: "checkbox" }, toggleWifiOnClick: { label: "Toggle Wifi onclick", type: "checkbox" }, hideNetworkName: { label: "Hide network name", type: "checkbox" }, vpnWidgetOptions: { label: "Viscosity VPN", documentation: "/viscosity-vpn/", infos: ["Here you can set your Viscosity vpn connection name."], }, vpnConnectionName: { label: "Viscosity connection name", type: "text", fullWidth: true, }, vpnShowConnectionName: { label: "Display the connection name in the widget", type: "checkbox", fullWidth: true, }, zoomWidgetOptions: { label: "Zoom status", documentation: "/zoom/", }, showVideo: { label: "Show video status", type: "checkbox" }, showMic: { label: "Show mic status", type: "checkbox" }, soundWidgetOptions: { label: "Sound", documentation: "/sound/", }, micWidgetOptions: { label: "Mic", documentation: "/microphone/", }, keyboardWidgetOptions: { label: "Keyboard", documentation: "/keyboard/", }, keyboardMaxLength: { label: "Characters to display", type: "number", placeholder: "0 to show full name", }, timeWidgetOptions: { label: "Time", documentation: "/time/", }, hour12: { label: "12h time format", type: "checkbox" }, dayProgress: { label: "Day progress", type: "checkbox" }, showSeconds: { label: "Show seconds", type: "checkbox" }, dateWidgetOptions: { label: "Date", documentation: "/date/", }, shortDateFormat: { label: "Short format", type: "checkbox" }, locale: { label: "Locale", type: "text", placeholder: "example: en-UK" }, calendarApp: { label: "Calendar App", type: "text", placeholder: "example: Fantastical", fullWidth: true, }, youtubeMusicWidgetOptions: { label: "YouTube Music", }, spotifyWidgetOptions: { label: "Spotify", documentation: "/spotify/", }, cryptoWidgetOptions: { label: "Crypto", documentation: "/crypto/", }, stockWidgetOptions: { label: "Stock", documentation: "/stocks/", infos: [ "Here you can configure your API key for the Yahoo Finance API.", "If you haven't gotten one yet, go to https://www.yahoofinanceapi.com/.", "You can register for free and use the Basic tier (100 requests/day).", ], }, musicWidgetOptions: { label: "Music/iTunes", documentation: "/music-itunes/", }, mpdWidgetOptions: { label: "MPD via mpc", documentation: "/mpd-state-via-mpc/", }, mpdBinaryPath: { label: "Path to mpc binary", type: "text", placeholder: "example: /opt/homebrew/bin/mpc", fullWidth: true, }, mpdHost: { label: "Host", type: "text", placeholder: "example: 127.0.0.1", }, mpdPort: { label: "Port", type: "text", placeholder: "example: 6600", }, mpdFormatString: { label: "Format String (see `man mpc`)", type: "text", placeholder: "example: %title%[ - %artist%]|[%file%]", fullWidth: true, }, browserTrackWidgetOptions: { label: "Browser", documentation: "/browser-track/", }, excludedApps: { label: "Excluded apps (comma-separated app names)", type: "text", placeholder: "example: BetterTouchTool, Xcode", fullWidth: true, }, notificationsWidgetOptions: { label: "Notification badges", documentation: "/notifications/", infos: [ "Shows notification badge counts from running macOS apps.", "Click any badge to open that application.", 'Each app exclusion must be separated by a comma and a space ", "', ], }, nextMeetingWidgetOptions: { label: "Next meeting", documentation: "/next-meeting/", infos: [ "Shows your next upcoming calendar event with time until start.", "Supports one-click join for Zoom, Teams, Google Meet, and Webex.", "Handles Microsoft SafeLinks (Outlook URL protection) automatically.", "
", "Requires icalBuddy: brew install ical-buddy", "Grant calendar access when prompted.", ], }, icalBuddyPath: { label: "Path to icalBuddy binary", type: "text", placeholder: "default: auto-detect (Homebrew)", fullWidth: true, }, lookAheadHours: { label: "Look ahead (hours)", type: "number", placeholder: "default: 12", }, showJoinButton: { label: "Show join button", type: "checkbox" }, showTimeOnly: { label: "Show time only (hide title)", type: "checkbox" }, showSpecter: { label: "Show animated specter", type: "checkbox" }, showSpotifyMetadata: { label: "Show Spotify metadata", type: "checkbox" }, youtubeMusicPort: { label: "Port", type: "text", placeholder: "26538" }, denomination: { label: "Denomination", type: "text", placeholder: "usd" }, identifiers: { label: "Identifiers", type: "text", placeholder: "celo,bitcoin,ethereum", }, precision: { label: "Decimals rounding", type: "text", placeholder: 5 }, symbols: { label: "Symbols for your stocks, ETFs, mutual funds, ...", type: "text", placeholder: "AAPL,TSLA", fullWidth: true, }, yahooFinanceApiKey: { label: "Your API key for Yahoo Finance", type: "text", placeholder: "YOUR_API_KEY", fullWidth: true, }, showSymbol: { label: "Show symbol", type: "checkbox" }, showCurrency: { label: "Show currency", type: "checkbox" }, showMarketPrice: { label: "Show market price", type: "checkbox" }, showMarketChange: { label: "Show market change", type: "checkbox" }, showMarketPercent: { label: "Show market change percent", type: "checkbox" }, showColor: { label: "Show colored output for market change", type: "checkbox", }, userWidgets: { label: "User widgets", documentation: "/custom-widgets/", }, userWidgetsList: { type: "component", Component: UserWidgetsCreator }, refreshFrequency: { label: "Refresh frequency (in ms)", type: "number" }, customStyles: { label: "Custom styles", documentation: "/custom-styles/", }, styles: { label: "Styles", type: "textarea", fullWidth: true, minHeight: 240, }, }; // Default settings are defined here export const defaultSettings = { global: { theme: "auto", compactMode: false, floatingBar: false, noBarBg: false, noColorInData: false, bottomBar: false, sideDecoration: false, inlineSpacesOptions: false, disableAnimations: false, spacesBackgroundColorAsForeground: false, widgetsBackgroundColorAsForeground: false, widgetMaxWidth: "160px", slidingAnimationPace: 4, font: "JetBrains Mono, Monaco, Menlo, monospace", fontSize: "11px", yabaiPath: "$(which yabai)", aerospacePath: "$(which aerospace)", windowManager: "yabai", shell: "sh", terminal: "Terminal", disableNotifications: false, enableMissives: false, enableServer: false, serverSocketPort: 7777, yabaiServerRefresh: false, aerospaceServerRefresh: false, }, themes: { lightTheme: "NightShiftLight", darkTheme: "NightShiftDark", colorMain: "", colorMainAlt: "", colorMinor: "", colorAccent: "", colorRed: "", colorGreen: "", colorYellow: "", colorOrange: "", colorBlue: "", colorMagenta: "", colorCyan: "", colorBlack: "", colorWhite: "", colorForeground: "", colorBackground: "", }, process: { showOnDisplay: "", displayForFocusedSpace: false, displayOnlyCurrent: false, centered: false, showCurrentSpaceMode: false, hideWindowTitle: false, displayOnlyIcon: false, expandAllProcesses: false, displaySkhdMode: false, displayStackIndex: true, displayOnlyCurrentStack: false, }, spacesDisplay: { showOnDisplay: "", exclusions: "", titleExclusions: "", spacesExclusions: "", exclusionsAsRegex: false, displayAllSpacesOnAllScreens: false, hideDuplicateAppsInSpaces: false, displayStickyWindowsSeparately: false, hideCreateSpaceButton: false, hideEmptySpaces: false, showOptionsOnHover: true, switchSpacesWithoutYabai: false, customAeroSpaceDisplayIndexes: {}, }, widgets: { processWidget: true, githubWidget: false, weatherWidget: false, netstatsWidget: false, cpuWidget: false, gpuWidget: false, memoryWidget: false, batteryWidget: true, wifiWidget: true, vpnWidget: false, zoomWidget: false, soundWidget: true, micWidget: false, dateWidget: true, timeWidget: true, keyboardWidget: false, spotifyWidget: true, cryptoWidget: false, stockWidget: false, youtubeMusicWidget: false, musicWidget: true, mpdWidget: false, browserTrackWidget: false, notificationsWidget: false, nextMeetingWidget: false, }, githubWidgetOptions: { refreshFrequency: 1000 * 60 * 10, showOnDisplay: "", showIcon: true, hideWhenNoNotification: false, notificationUrl: "https://github.com/notifications", ghBinaryPath: "/opt/homebrew/bin/gh", }, weatherWidgetOptions: { refreshFrequency: 1000 * 60 * 30, showOnDisplay: "", showIcon: true, unit: "C", hideLocation: false, hideGradient: false, customLocation: "", }, netstatsWidgetOptions: { refreshFrequency: 2000, showOnDisplay: "", showIcon: true, displayAsGraph: false, netstatsThreshold: 0, }, cpuWidgetOptions: { refreshFrequency: 2000, showOnDisplay: "", showIcon: true, displayAsGraph: false, cpuUsageThreshold: 0, cpuMonitorApp: "Activity Monitor", }, gpuWidgetOptions: { refreshFrequency: 3000, showOnDisplay: "", showIcon: true, displayAsGraph: false, gpuMacmonBinaryPath: "/opt/homebrew/bin/macmon", }, memoryWidgetOptions: { refreshFrequency: 4000, showOnDisplay: "", showIcon: true, memoryUsageThreshold: 0, memoryMonitorApp: "Activity Monitor", }, batteryWidgetOptions: { refreshFrequency: 10000, showOnDisplay: "", showIcon: true, toggleCaffeinateOnClick: true, disableCaffeinateInvertedBackground: false, caffeinateOption: "", }, networkWidgetOptions: { refreshFrequency: 20000, showOnDisplay: "", showIcon: true, networkDevice: "en0", hideWifiIfDisabled: false, toggleWifiOnClick: false, hideNetworkName: false, }, vpnWidgetOptions: { refreshFrequency: 8000, showOnDisplay: "", showIcon: true, vpnConnectionName: "", vpnShowConnectionName: false, }, zoomWidgetOptions: { refreshFrequency: 5000, showOnDisplay: "", showVideo: true, showMic: true, }, soundWidgetOptions: { refreshFrequency: 20000, showOnDisplay: "", showIcon: true, }, micWidgetOptions: { refreshFrequency: 20000, showOnDisplay: "", showIcon: true, }, dateWidgetOptions: { refreshFrequency: 30000, showOnDisplay: "", showIcon: true, shortDateFormat: true, locale: "en-UK", calendarApp: "", }, timeWidgetOptions: { refreshFrequency: 1000, showOnDisplay: "", showIcon: true, hour12: false, dayProgress: true, showSeconds: false, }, keyboardWidgetOptions: { refreshFrequency: 20000, showOnDisplay: "", showIcon: true, keyboardMaxLength: 0, }, cryptoWidgetOptions: { refreshFrequency: 5 * 60 * 1000, showOnDisplay: "", showIcon: true, denomination: "usd", identifiers: "bitcoin,ethereum,celo", precision: 5, }, stockWidgetOptions: { refreshFrequency: 15 * 60 * 1000, showOnDisplay: "", showIcon: true, yahooFinanceApiKey: "YOUR_API_KEY", symbols: "AAPL,TSLA", showSymbol: true, showCurrency: true, showMarketPrice: true, showMarketChange: false, showMarketPercent: true, showColor: true, }, spotifyWidgetOptions: { refreshFrequency: 10000, showOnDisplay: "", showIcon: true, showSpecter: true, showSpotifyMetadata: true, }, youtubeMusicWidgetOptions: { refreshFrequency: 10000, showOnDisplay: "", showIcon: true, showSpecter: true, youtubeMusicPort: 26538, }, musicWidgetOptions: { refreshFrequency: 10000, showOnDisplay: "", showIcon: true, showSpecter: true, }, mpdWidgetOptions: { refreshFrequency: 10000, showOnDisplay: "", showIcon: true, showSpecter: true, mpdBinaryPath: "/opt/homebrew/bin/mpc", mpdPort: "6600", mpdHost: "127.0.0.1", mpdFormatString: "%title%[ - %artist%]|[%file%]", }, browserTrackWidgetOptions: { refreshFrequency: 10000, showOnDisplay: "", showIcon: true, showSpecter: true, }, notificationsWidgetOptions: { refreshFrequency: 10000, showOnDisplay: "", excludedApps: "", }, nextMeetingWidgetOptions: { refreshFrequency: 60000, showOnDisplay: "", showJoinButton: true, showTimeOnly: false, icalBuddyPath: "", lookAheadHours: 12, }, userWidgets: { userWidgetsList: {}, }, customStyles: { styles: "/* your custom css styles here */", }, }; // User widget default settings export const userWidgetDefault = { title: "Your widget name", icon: "Widget", backgroundColor: "--main-alt", output: 'echo "Hello world!"', onClickAction: "", onRightClickAction: "", onMiddleClickAction: "", refreshFrequency: 10000, showOnDisplay: "", active: true, noIcon: false, hideWhenNoOutput: true, }; // Colors available for user widgets export const userWidgetColors = [ "--main", "--main-alt", "--minor", "--accent", "--red", "--green", "--yellow", "--orange", "--blue", "--magenta", "--cyan", ]; /** * Retrieves the application settings from local storage. * If no settings are found, the default settings are used. * The settings schema is removed before returning the settings. * * @returns {Object} The application settings. */ export function get() { const storedSettings = window.localStorage.getItem(SETTINGS_STORAGE_KEY); const settings = storedSettings ? Utils.mergeDeep(defaultSettings, JSON.parse(storedSettings)) : defaultSettings; delete settings.$schema; return settings; } /** * Updates the settings by merging them with the schema, saving them to a config file, * and storing them in the local storage. * * @param {Object} newSettings - The new settings to be applied. * @returns {Promise} A promise that resolves when the settings have been saved. */ export async function set(newSettings) { pruneObsoleteSettings(newSettings); const settingsWithSchema = { $schema: "https://raw.githubusercontent.com/Jean-Tinland/simple-bar/refs/heads/master/lib/schemas/config.json", ...newSettings, }; await saveToConfigFile(settingsWithSchema); window.localStorage.setItem( SETTINGS_STORAGE_KEY, JSON.stringify(settingsWithSchema), ); } /** * Saves the provided settings to the configuration file. * * @param {Object} newSettings - The new settings to be saved. * @returns {Promise} A promise that resolves when the settings have been saved. * @throws Will throw an error if the settings cannot be saved. */ async function saveToConfigFile(newSettings) { try { const settings = JSON.stringify(newSettings, undefined, 2); const cleanSettings = settings.replace(/'/g, "'\"'\"'"); await Uebersicht.run(`echo '${cleanSettings}' | tee ~/.simplebarrc`); } catch (e) { // eslint-disable-next-line no-console console.error(e); } } /** * Checks if the configuration file for simple-bar exists. * * This function runs a shell command to check for the presence of the * configuration file located at `~/.simplebarrc`. If the file exists, * the function returns `true`; otherwise, it returns `false`. * * @returns {Promise} A promise that resolves to `true` if the * configuration file exists, and `false` otherwise. */ export async function checkIfConfigFileExists() { let exists = false; try { exists = Boolean(await Uebersicht.run(`ls ~/.simplebarrc`)); } catch (e) { // eslint-disable-next-line no-console console.error(e); } return exists; } /** * Removes obsolete settings from the provided settings object. * * @param {Object} settings - The settings object to prune. * @param {Object} settings.global - The global settings object. * @param {string} settings.global.externalConfigFile - The external configuration file setting to be removed. * @param {Object} settings.widgets - The widgets settings object. * @param {Object} settings.widgets.dndWidget - The dndWidget setting to be removed. * @param {Object} settings.widgets.undefined - The undefined widget setting to be removed. */ function pruneObsoleteSettings(settings) { delete settings.global.externalConfigFile; delete settings.widgets.dndWidget; delete settings.widgets.undefined; } /** * Loads the external configuration file for simple-bar. */ export async function loadExternalConfig() { const configFileExists = await checkIfConfigFileExists(); if (!configFileExists) return; try { const config = JSON.parse(await Uebersicht.run(`cat ~/.simplebarrc`)); const settings = Utils.mergeDeep(defaultSettings, config); return settings; } catch (e) { // eslint-disable-next-line no-console console.error("Error loading external config:", e); } } /** */ export async function init() { const externalConfig = await loadExternalConfig(); if (externalConfig) { set(externalConfig); } }