From 1d717e9f2ec390c23dc15d7c5be64fbf31d8a16a Mon Sep 17 00:00:00 2001 From: Louis Dalibard Date: Sat, 5 Apr 2025 08:10:51 +0200 Subject: [PATCH] feat: add world clock module (#795) Co-authored-by: Louis Dalibard Co-authored-by: Jas Singh --- nix/module.nix | 13 ++ src/components/bar/exports.ts | 2 + src/components/bar/index.tsx | 2 + .../bar/modules/worldclock/index.tsx | 120 ++++++++++++++++++ src/components/bar/settings/config.tsx | 23 ++++ src/components/bar/settings/theme.tsx | 17 +++ src/options.ts | 21 +++ src/scss/style/bar/clock.scss | 66 ++++++++++ src/scss/style/bar/style.scss | 27 ++++ 9 files changed, 291 insertions(+) create mode 100644 src/components/bar/modules/worldclock/index.tsx diff --git a/nix/module.nix b/nix/module.nix index 3b25044..6c15238 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -291,6 +291,16 @@ in bar.customModules.weather.scrollDown = mkStrOption ""; bar.customModules.weather.scrollUp = mkStrOption ""; bar.customModules.weather.unit = mkStrOption "imperial"; + bar.customModules.worldclock.format = mkStrOption "%I:%M:%S %p %Z"; + bar.customModules.worldclock.formatDiffDate = mkStrOption "%a %b %d %I:%M:%S %p %Z"; + bar.customModules.worldclock.icon = mkStrOption "󱉊"; + bar.customModules.worldclock.middleClick = mkStrOption ""; + bar.customModules.worldclock.rightClick = mkStrOption ""; + bar.customModules.worldclock.scrollDown = mkStrOption ""; + bar.customModules.worldclock.scrollUp = mkStrOption ""; + bar.customModules.worldclock.showIcon = mkBoolOption true; + bar.customModules.worldclock.showTime = mkBoolOption true; + bar.customModules.worldclock.tz = mkStrListOption ["America/New_York" "Europe/Paris" "Asia/Tokyo"]; bar.launcher.autoDetectIcon = mkBoolOption false; bar.launcher.icon = mkStrOption "󰣇"; bar.launcher.middleClick = mkStrOption ""; @@ -507,6 +517,8 @@ in theme.bar.buttons.modules.updates.spacing = mkStrOption "0.45em"; theme.bar.buttons.modules.weather.enableBorder = mkBoolOption false; theme.bar.buttons.modules.weather.spacing = mkStrOption "0.45em"; + theme.bar.buttons.modules.worldclock.enableBorder = mkBoolOption false; + theme.bar.buttons.modules.worldclock.spacing = mkStrOption "0.45em"; theme.bar.buttons.monochrome = mkBoolOption false; theme.bar.buttons.network.enableBorder = mkBoolOption false; theme.bar.buttons.network.spacing = mkStrOption "0.5em"; @@ -724,3 +736,4 @@ in ]; }; } + diff --git a/src/components/bar/exports.ts b/src/components/bar/exports.ts index dbc3648..b4bdc32 100644 --- a/src/components/bar/exports.ts +++ b/src/components/bar/exports.ts @@ -25,6 +25,7 @@ import { Power } from '../../components/bar/modules/power/index'; import { Hyprsunset } from '../../components/bar/modules/hyprsunset/index'; import { Hypridle } from '../../components/bar/modules/hypridle/index'; import { Cava } from '../../components/bar/modules/cava/index'; +import { WorldClock } from '../../components/bar/modules/worldclock/index'; export { Menu, @@ -54,4 +55,5 @@ export { Hyprsunset, Hypridle, Cava, + WorldClock, }; diff --git a/src/components/bar/index.tsx b/src/components/bar/index.tsx index 12f79b2..5025de9 100644 --- a/src/components/bar/index.tsx +++ b/src/components/bar/index.tsx @@ -26,6 +26,7 @@ import { Hyprsunset, Hypridle, Cava, + WorldClock, } from './exports'; import { WidgetContainer } from './shared/WidgetContainer'; @@ -67,6 +68,7 @@ const widget = { hyprsunset: (): JSX.Element => WidgetContainer(Hyprsunset()), hypridle: (): JSX.Element => WidgetContainer(Hypridle()), cava: (): JSX.Element => WidgetContainer(Cava()), + worldclock: (): JSX.Element => WidgetContainer(WorldClock()), }; const gdkMonitorMapper = new GdkMonitorMapper(); diff --git a/src/components/bar/modules/worldclock/index.tsx b/src/components/bar/modules/worldclock/index.tsx new file mode 100644 index 0000000..892ff9d --- /dev/null +++ b/src/components/bar/modules/worldclock/index.tsx @@ -0,0 +1,120 @@ +import { openMenu } from '../../utils/menu'; +import options from 'src/options'; +import { BarBoxChild } from 'src/lib/types/bar.js'; +import { runAsyncCommand, throttledScrollHandler } from 'src/components/bar/utils/helpers.js'; +import { bind, Variable } from 'astal'; +import { onMiddleClick, onPrimaryClick, onScroll, onSecondaryClick } from 'src/lib/shared/eventHandlers'; +import { Astal } from 'astal/gtk3'; +import { systemTime } from 'src/globals/time'; +import { GLib } from 'astal'; + +const { format, formatDiffDate, tz, icon, showIcon, showTime, rightClick, middleClick, scrollUp, scrollDown } = + options.bar.customModules.worldclock; +const { style } = options.theme.bar.buttons; + +const time = Variable.derive( + [systemTime, format, formatDiffDate, tz], + (c, f, fdd, tzn) => + tzn + .map((t) => + c + .to_timezone(GLib.TimeZone.new(t)) + .format(c.to_timezone(GLib.TimeZone.new(t)).get_day_of_year() == c.get_day_of_year() ? f : fdd), + ) + .join(' | ') || '', +); + +const WorldClock = (): BarBoxChild => { + const ClockTime = (): JSX.Element =>