diff --git a/extension.js b/extension.js index b38dcc4..430a182 100644 --- a/extension.js +++ b/extension.js @@ -6,101 +6,145 @@ import { Extension } from "resource:///org/gnome/shell/extensions/extension.js"; import * as Main from "resource:///org/gnome/shell/ui/main.js"; import GLib from "gi://GLib"; import Gio from "gi://Gio"; +import St from 'gi://St'; +import Clutter from 'gi://Clutter'; export default class IsoClock extends Extension { enable() { - const dateMenu = Main.panel.statusArea.dateMenu; - - const clockDisplayBox = dateMenu - .get_children() - .find((x) => x.style_class === "clock-display-box"); - - this.label = clockDisplayBox?.get_children().find( - (x) => x.style_class === "clock" - ); - - if (!this.label) { + this.mainClock = this.getClockFromPanel(Main.panel) + if (!this.mainClock) { console.error("No clock label? Aborting."); return; } - const gnomeSettings = Gio.Settings.new("org.gnome.desktop.interface"); this.gnomeCalendar = Gio.Settings.new("org.gnome.desktop.calendar"); + this.isoClocks = [] + this.createClocks(); - const override = () => { - // Don't do anything if the clock label hasn't actually changed - if (this.newClock == this.label.get_text()) { - return; - } + const updateClocks = () => { + // Set our clock labels to our new custom format + const now = GLib.DateTime.new_now_local(); + this.isoClocks.forEach(clock => { + clock.set_text(now.format(this.getIsoFormat())); + }); + }; - // Setup the custom clock format based on the clock settings in Gnome Settings - let day, date, week, time; + // Whenever the main clock label changes, update all our clocks + this.mainClockHandleId = this.mainClock.connect("notify::text", updateClocks); - if (gnomeSettings.get_boolean("clock-show-weekday")) { - day = "%A" - } + // Also update clocks when the "Week Numbers" setting changes. Week numbers + // don't appear in the default clock, so we'll watch the Gnome Settings + // handle for that. + this.calendarHandleId = this.gnomeCalendar.connect("changed::show-weekdate", () => { + updateClocks(); + }) + updateClocks(); + } - if (gnomeSettings.get_boolean("clock-show-date")) { - date = "%Y-%m-%d"; - } + disable() { + if (this.calendarHandleId) { + this.gnomeCalendar.disconnect(this.calendarHandleId); + this.calendarHandleId = null; + } - if (this.gnomeCalendar.get_boolean("show-weekdate")) { - week = "W%V-%u" - } + if (this.mainClockHandleId) { + this.mainClock.disconnect(this.mainClockHandleId); + this.mainClockHandleId = null; + } - if (gnomeSettings.get_string("clock-format") === '24h') { - time = "%H:%M"; - } else { - time = "%I:%M %p"; - } + this.destroyClocks(); - if (gnomeSettings.get_boolean("clock-show-seconds")) { - time = time.replace("%M","%M:%S"); - } + this.gnomeCalendar = null + this.mainClock = null; + } - const format = [day, date, week, time].filter(v => v).join(" "); + getClockFromPanel(panel) { + const dateMenu = panel?.statusArea?.dateMenu; + if (!dateMenu) return null; - // Keep a copy of the default clock text so that we can revert it when the - // extension is disabled - this.defaultClock = this.label.get_text(); + const clockDisplayBox = dateMenu + .get_children() + .find((x) => x.style_class === "clock-display-box"); - // Set the clock label to our new custom format - const now = GLib.DateTime.new_now_local(); - this.newClock = now.format(format); - this.label.set_text(this.newClock); - }; + return clockDisplayBox?.get_children().find( + (x) => x.style_class === "clock" + ) || null; + } - // Whenever the clock label updates override with our custom clock format - this.labelHandleId = this.label.connect("notify::text", override); + cloneClock(original) { + const clock = new St.Label({ + style_class: 'clock', + text: 'Initializing...', + y_expand: 0, + y_align: 0 + }); + clock.get_clutter_text().set_y_align(Clutter.ActorAlign.CENTER); + original.get_parent().insert_child_above(clock, original); + // original.hide(); + return clock + } - // We also need to know when the "Week Numbers" setting changes, as week numbers - // don't appear in the default clock. Trigger a refresh by setting clock back to - // its default value. This prevents an edge case where disabling the extension - // after a week number setting change causes unexpected behaviour - this.calendarHandleId = this.gnomeCalendar.connect("changed::show-weekdate", () => { - this.label.set_text(this.defaultClock); - }) - override(); + createClocks() { + // Hide the original clock and create our own + this.isoClocks.push(this.cloneClock(this.mainClock)); + this.mainClock.hide(); + + // If Dash to Panel is running, clone those too + if (global.dashToPanel) { + global.dashToPanel.panels.forEach(panel => { + const clock = this.getClockFromPanel(panel); + // If Dash to Panel is re-using the main clock, don't clone it again + if (clock !== this.mainClock) { + this.isoClocks.push(this.cloneClock(clock)); + clock.hide(); + } + }); + } } - disable() { - if (this.calendarHandleId) { - this.gnomeCalendar.disconnect(this.calendarHandleId); - this.calendarHandleId = null; + destroyClocks() { + this.isoClocks.forEach(clock => { + if (clock) { + clock.destroy(); + } + }); + this.isoClocks = []; + + global.dashToPanel?.panels?.forEach(panel => { + this.getClockFromPanel(panel)?.show(); + }); + + this.mainClock.show(); + } + + getIsoFormat() { + // Setup the custom clock format based on the clock settings in Gnome Settings + const gnomeSettings = Gio.Settings.new("org.gnome.desktop.interface"); + + let day, date, week, time; + + if (gnomeSettings.get_boolean("clock-show-weekday")) { + day = "%A" } - if (this.labelHandleId) { - this.label.disconnect(this.labelHandleId); - this.labelHandleId = null; + if (gnomeSettings.get_boolean("clock-show-date")) { + date = "%Y-%m-%d"; } - if (this.defaultClock) { - this.label.set_text(this.defaultClock); + if (this.gnomeCalendar.get_boolean("show-weekdate")) { + week = "W%V-%u" } - this.gnomeCalendar = null - this.label = null; - this.newClock = null; - this.defaultClock = null; + if (gnomeSettings.get_string("clock-format") === '24h') { + time = "%H:%M"; + } else { + time = "%I:%M %p"; + } + + if (gnomeSettings.get_boolean("clock-show-seconds")) { + time = time.replace("%M","%M:%S"); + } + + return [day, date, week, time].filter(v => v).join(" "); } }