Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 112 additions & 68 deletions extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(" ");
}
}