Extension: Allow using a manual location
This commit is contained in:
@@ -63,6 +63,19 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<default>0</default>
|
||||
</key>
|
||||
</schema>
|
||||
<schema id="org.gnome.shell.extensions.nightthemeswitcher.location" path="/org/gnome/shell/extensions/nightthemeswitcher/location/">
|
||||
<key name="manual-location" type="b">
|
||||
<default>false</default>
|
||||
</key>
|
||||
<key name="latitude" type="d">
|
||||
<range min="-90" max="90"/>
|
||||
<default>0</default>
|
||||
</key>
|
||||
<key name="longitude" type="d">
|
||||
<range min="-180" max="180"/>
|
||||
<default>0</default>
|
||||
</key>
|
||||
</schema>
|
||||
<schema id="org.gnome.shell.extensions.nightthemeswitcher.color-scheme" path="/org/gnome/shell/extensions/nightthemeswitcher/color-scheme/">
|
||||
<key name="day" enum="org.gnome.shell.extensions.nightthemeswitcher.color-scheme-enum">
|
||||
<default>"default"</default>
|
||||
|
||||
@@ -8,6 +8,53 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<property name="name">tweaks</property>
|
||||
<property name="title" translatable="yes">Tweaks</property>
|
||||
<property name="icon-name">nightthemeswitcher-tweaks-symbolic</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="AdwExpanderRow">
|
||||
<property name="title" translatable="yes">Manual location</property>
|
||||
<property name="subtitle" translatable="yes">Use a manual location instead of system the location service.</property>
|
||||
<child type="suffix">
|
||||
<object class="GtkSwitch" id="manual_location_switch">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSpinRow" id="latitude_spin">
|
||||
<property name="title" translatable="yes">Latitude</property>
|
||||
<binding name="sensitive">
|
||||
<lookup name="active">manual_location_switch</lookup>
|
||||
</binding>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="lower">-90</property>
|
||||
<property name="upper">90</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwSpinRow" id="longitude_spin">
|
||||
<property name="title" translatable="yes">Longitude</property>
|
||||
<binding name="sensitive">
|
||||
<lookup name="active">manual_location_switch</lookup>
|
||||
</binding>
|
||||
<property name="digits">2</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="lower">-180</property>
|
||||
<property name="upper">180</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
@@ -22,7 +69,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Sunrise</property>
|
||||
<property name="sensitive" bind-source="manual_schedule_switch" bind-property="active" bind-flags="sync-create"/>
|
||||
<binding name="sensitive">
|
||||
<lookup name="active">manual_schedule_switch</lookup>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="TimeChooser" id="schedule_sunrise_time_chooser">
|
||||
<property name="margin-top">12</property>
|
||||
@@ -35,7 +84,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">Sunset</property>
|
||||
<property name="sensitive" bind-source="manual_schedule_switch" bind-property="active" bind-flags="sync-create"/>
|
||||
<binding name="sensitive">
|
||||
<lookup name="active">manual_schedule_switch</lookup>
|
||||
</binding>
|
||||
<child>
|
||||
<object class="TimeChooser" id="schedule_sunset_time_chooser">
|
||||
<property name="margin-top">12</property>
|
||||
|
||||
+78
-63
@@ -27,10 +27,11 @@ import { Time } from "../enums/Time.js";
|
||||
* forced the manual schedule in the preferences.
|
||||
*/
|
||||
export class Timer extends GObject.Object {
|
||||
#settings;
|
||||
#colorSchemeSettings;
|
||||
#interfaceSettings;
|
||||
#locationSettings;
|
||||
#timeSettings;
|
||||
#colorSchemeSettings;
|
||||
#systemInterfaceSettings;
|
||||
#systemLocationSettings;
|
||||
/** @type {Time | undefined} */
|
||||
#time;
|
||||
|
||||
@@ -57,10 +58,11 @@ export class Timer extends GObject.Object {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#settings = NTS.getSettings(`${NTS.metadata["settings-schema"]}.time`);
|
||||
this.#locationSettings = NTS.getSettings(`${NTS.metadata["settings-schema"]}.location`);
|
||||
this.#timeSettings = NTS.getSettings(`${NTS.metadata["settings-schema"]}.time`);
|
||||
this.#colorSchemeSettings = NTS.getSettings(`${NTS.metadata["settings-schema"]}.color-scheme`);
|
||||
this.#interfaceSettings = new Gio.Settings({ schema: "org.gnome.desktop.interface" });
|
||||
this.#locationSettings = new Gio.Settings({ schema: "org.gnome.system.location" });
|
||||
this.#systemInterfaceSettings = new Gio.Settings({ schema: "org.gnome.desktop.interface" });
|
||||
this.#systemLocationSettings = new Gio.Settings({ schema: "org.gnome.system.location" });
|
||||
}
|
||||
|
||||
enable() {
|
||||
@@ -68,10 +70,13 @@ export class Timer extends GObject.Object {
|
||||
this.#cancellable = new Gio.Cancellable();
|
||||
this.#connectSettings();
|
||||
this.#trackTime();
|
||||
if (this.#settings.get_boolean("manual-schedule")) {
|
||||
if (this.#timeSettings.get_boolean("manual-schedule")) {
|
||||
debug.message("Using the manual schedule.");
|
||||
} else if (this.#locationSettings.get_boolean("manual-location")) {
|
||||
debug.message("Using the manual location.");
|
||||
this.#trackSuntimes();
|
||||
} else {
|
||||
debug.message("Using location.");
|
||||
debug.message("Using system location.");
|
||||
this.#trackLocation();
|
||||
this.#trackSuntimes();
|
||||
}
|
||||
@@ -116,7 +121,7 @@ export class Timer extends GObject.Object {
|
||||
debug.message(manual ? `Time manually set to ${time}.` : `Time changed to ${time}.`);
|
||||
|
||||
const isMonitorFullscreen = layoutManager.monitors.some((monitor) => monitor.inFullscreen);
|
||||
if (this.#settings.get_boolean("fullscreen-transition") || !isMonitorFullscreen) {
|
||||
if (this.#timeSettings.get_boolean("fullscreen-transition") || !isMonitorFullscreen) {
|
||||
try {
|
||||
layoutManager.screenTransition.run();
|
||||
} catch {}
|
||||
@@ -127,30 +132,38 @@ export class Timer extends GObject.Object {
|
||||
|
||||
#connectSettings() {
|
||||
debug.message("Connecting Timer to settings...");
|
||||
this.#settingsConnections.push({
|
||||
settings: this.#systemLocationSettings,
|
||||
id: this.#systemLocationSettings.connect("changed::enabled", this.#onSystemLocationStateChanged.bind(this)),
|
||||
});
|
||||
this.#settingsConnections.push({
|
||||
settings: this.#locationSettings,
|
||||
id: this.#locationSettings.connect("changed::enabled", this.#onLocationStateChanged.bind(this)),
|
||||
id: this.#locationSettings.connect("changed::manual-location", this.#onManualLocationStateChanged.bind(this)),
|
||||
});
|
||||
this.#settingsConnections.push({
|
||||
settings: this.#settings,
|
||||
id: this.#settings.connect("changed::location", this.#onLocationSettingsChanged.bind(this)),
|
||||
settings: this.#locationSettings,
|
||||
id: this.#locationSettings.connect("changed::latitude", this.#onLocationChanged.bind(this)),
|
||||
});
|
||||
this.#settingsConnections.push({
|
||||
settings: this.#settings,
|
||||
id: this.#settings.connect("changed::manual-schedule", this.#onManualScheduleStateChanged.bind(this)),
|
||||
settings: this.#locationSettings,
|
||||
id: this.#locationSettings.connect("changed::longitude", this.#onLocationChanged.bind(this)),
|
||||
});
|
||||
this.#settingsConnections.push({
|
||||
settings: this.#settings,
|
||||
id: this.#settings.connect(
|
||||
settings: this.#timeSettings,
|
||||
id: this.#timeSettings.connect("changed::manual-schedule", this.#onManualScheduleStateChanged.bind(this)),
|
||||
});
|
||||
this.#settingsConnections.push({
|
||||
settings: this.#timeSettings,
|
||||
id: this.#timeSettings.connect(
|
||||
"changed::nightthemeswitcher-ondemand-keybinding",
|
||||
this.#onOndemandKeybindingChanged.bind(this),
|
||||
),
|
||||
});
|
||||
// Only listen to the offset setting when not using a manual schedule
|
||||
if (!this.#settings.get_boolean("manual-schedule")) {
|
||||
if (!this.#timeSettings.get_boolean("manual-schedule")) {
|
||||
this.#settingsConnections.push({
|
||||
settings: this.#settings,
|
||||
id: this.#settings.connect("changed::offset", this.#onOffsetChanged.bind(this)),
|
||||
settings: this.#timeSettings,
|
||||
id: this.#timeSettings.connect("changed::offset", this.#onOffsetChanged.bind(this)),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -214,12 +227,12 @@ export class Timer extends GObject.Object {
|
||||
}
|
||||
|
||||
#addKeybinding() {
|
||||
this.#previousKeybinding = this.#settings.get_strv("nightthemeswitcher-ondemand-keybinding")[0];
|
||||
if (!this.#settings.get_strv("nightthemeswitcher-ondemand-keybinding")[0]) return;
|
||||
this.#previousKeybinding = this.#timeSettings.get_strv("nightthemeswitcher-ondemand-keybinding")[0];
|
||||
if (!this.#timeSettings.get_strv("nightthemeswitcher-ondemand-keybinding")[0]) return;
|
||||
debug.message("Adding keybinding...");
|
||||
wm.addKeybinding(
|
||||
"nightthemeswitcher-ondemand-keybinding",
|
||||
this.#settings,
|
||||
this.#timeSettings,
|
||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
||||
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
|
||||
() => {
|
||||
@@ -242,12 +255,17 @@ export class Timer extends GObject.Object {
|
||||
return colorScheme === this.#colorSchemeSettings.get_string("night") ? Time.NIGHT : Time.DAY;
|
||||
}
|
||||
|
||||
#onLocationStateChanged() {
|
||||
#onSystemLocationStateChanged() {
|
||||
this.disable();
|
||||
this.enable();
|
||||
}
|
||||
|
||||
#onLocationSettingsChanged() {
|
||||
#onManualLocationStateChanged() {
|
||||
this.disable();
|
||||
this.enable();
|
||||
}
|
||||
|
||||
#onLocationChanged() {
|
||||
this.#updateSuntimes();
|
||||
}
|
||||
|
||||
@@ -268,56 +286,52 @@ export class Timer extends GObject.Object {
|
||||
#onGeoclueReady(_geoclue, result) {
|
||||
try {
|
||||
this.#geoclue = Geoclue.Simple.new_finish(result);
|
||||
this.#geoclueLocationConnectionId = this.#geoclue.connect("notify::location", this.#onLocationChanged.bind(this));
|
||||
this.#geoclueLocationConnectionId = this.#geoclue.connect(
|
||||
"notify::location",
|
||||
this.#onGeoclueLocationChanged.bind(this),
|
||||
);
|
||||
debug.message("Connected to GeoClue.");
|
||||
this.#onLocationChanged();
|
||||
this.#onGeoclueLocationChanged();
|
||||
} catch (e) {
|
||||
const [latitude, longitude] = this.#settings.get_value("location").deepUnpack();
|
||||
if (latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180) {
|
||||
console.error(
|
||||
`[${NTS.metadata.name}] Unable to retrieve the location, using the last known location instead.\n${e}`,
|
||||
);
|
||||
this.#updateSuntimes();
|
||||
} else {
|
||||
console.error(
|
||||
`[${NTS.metadata.name}] Unable to retrieve the location, using the manual schedule times instead.\n${e}`,
|
||||
);
|
||||
console.error(
|
||||
`[${NTS.metadata.name}] Unable to retrieve the location, using the manual schedule times instead.\n${e}`,
|
||||
);
|
||||
|
||||
const source = new MessageTray.Source({
|
||||
title: NTS.metadata.name,
|
||||
icon: Gio.icon_new_for_string(
|
||||
GLib.build_filenamev([NTS.metadata.path, "icons", "nightthemeswitcher-symbolic.svg"]),
|
||||
),
|
||||
});
|
||||
messageTray.add(source);
|
||||
const source = new MessageTray.Source({
|
||||
title: NTS.metadata.name,
|
||||
icon: Gio.icon_new_for_string(
|
||||
GLib.build_filenamev([NTS.metadata.path, "icons", "nightthemeswitcher-symbolic.svg"]),
|
||||
),
|
||||
});
|
||||
messageTray.add(source);
|
||||
|
||||
const notification = new MessageTray.Notification({
|
||||
source,
|
||||
title: _("Unknown Location"),
|
||||
body: _("A manual schedule will be used to switch the dark mode."),
|
||||
"icon-name": "location-services-disabled-symbolic",
|
||||
});
|
||||
notification.addAction(_("Edit Manual Schedule"), () => NTS.openPreferences());
|
||||
const notification = new MessageTray.Notification({
|
||||
source,
|
||||
title: _("Error while getting your location"),
|
||||
body: _("A manual schedule will be used. You can edit it or manually set your location in the preferences."),
|
||||
"icon-name": "location-services-disabled-symbolic",
|
||||
});
|
||||
notification.addAction(_("Open Preferences"), () => NTS.openPreferences());
|
||||
|
||||
notification.connect("activated", () => NTS.openPreferences());
|
||||
notification.connect("activated", () => NTS.openPreferences());
|
||||
|
||||
source.addNotification(notification);
|
||||
source.addNotification(notification);
|
||||
|
||||
this.#settings.set_boolean("manual-schedule", true);
|
||||
}
|
||||
this.#timeSettings.set_boolean("manual-schedule", true);
|
||||
}
|
||||
}
|
||||
|
||||
#onLocationChanged(_geoclue, _location) {
|
||||
#onGeoclueLocationChanged(_geoclue, _location) {
|
||||
debug.message("Location has changed.");
|
||||
const { latitude, longitude } = this.#geoclue.get_location();
|
||||
debug.message(`Current location: (${latitude};${longitude})`);
|
||||
this.#settings.set_value("location", new GLib.Variant("(dd)", [latitude, longitude]));
|
||||
this.#locationSettings.set_double("latitude", latitude);
|
||||
this.#locationSettings.set_double("longitude", longitude);
|
||||
}
|
||||
|
||||
#computeTime() {
|
||||
const sunrise = this.#settings.get_double("sunrise");
|
||||
const sunset = this.#settings.get_double("sunset");
|
||||
const sunrise = this.#timeSettings.get_double("sunrise");
|
||||
const sunset = this.#timeSettings.get_double("sunset");
|
||||
const datetime = GLib.DateTime.new_now_local();
|
||||
const hour = datetime.get_hour() + datetime.get_minute() / 60 + datetime.get_second() / 3600;
|
||||
|
||||
@@ -326,11 +340,12 @@ export class Timer extends GObject.Object {
|
||||
// Sunset happens on the day after
|
||||
else if (sunrise > sunset) return hour >= sunrise || hour < sunset ? Time.DAY : Time.NIGHT;
|
||||
// Sunset and Sunrise times are identical; preserve current theme
|
||||
else return this.#time || this.#colorSchemeToTime(this.#interfaceSettings.get_string("color-scheme"));
|
||||
else return this.#time || this.#colorSchemeToTime(this.#systemInterfaceSettings.get_string("color-scheme"));
|
||||
}
|
||||
|
||||
#updateSuntimes() {
|
||||
const [latitude, longitude] = this.#settings.get_value("location").deepUnpack();
|
||||
const latitude = this.#locationSettings.get_double("latitude");
|
||||
const longitude = this.#locationSettings.get_double("longitude");
|
||||
|
||||
if (latitude < -90 && latitude > 90 && longitude < -180 && longitude > 180) return;
|
||||
|
||||
@@ -386,12 +401,12 @@ export class Timer extends GObject.Object {
|
||||
|
||||
const modulo = (n, m) => ((n % m) + m) % m;
|
||||
|
||||
const offset = this.#settings.get_double("offset");
|
||||
const offset = this.#timeSettings.get_double("offset");
|
||||
const sunrise = modulo(timeSunrise * 24 + offset, 24);
|
||||
const sunset = modulo(timeSunset * 24 - offset, 24);
|
||||
|
||||
this.#settings.set_double("sunrise", sunrise);
|
||||
this.#settings.set_double("sunset", sunset);
|
||||
this.#timeSettings.set_double("sunrise", sunrise);
|
||||
this.#timeSettings.set_double("sunset", sunset);
|
||||
|
||||
debug.message(`New sun times: (sunrise: ${sunrise}; sunset: ${sunset})`);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ export class TweaksPage extends Adw.PreferencesPage {
|
||||
GTypeName: "TweaksPage",
|
||||
Template: "resource:///org/gnome/Shell/Extensions/nightthemeswitcher/preferences/ui/TweaksPage.ui",
|
||||
InternalChildren: [
|
||||
"manual_location_switch",
|
||||
"latitude_spin",
|
||||
"longitude_spin",
|
||||
"manual_schedule_switch",
|
||||
"keyboard_shortcut_button",
|
||||
"schedule_sunrise_time_chooser",
|
||||
@@ -24,24 +27,34 @@ export class TweaksPage extends Adw.PreferencesPage {
|
||||
);
|
||||
}
|
||||
|
||||
constructor({ settings, ...params } = {}) {
|
||||
constructor({ locationSettings, timeSettings, ...params } = {}) {
|
||||
super(params);
|
||||
|
||||
settings.bind("manual-schedule", this._manual_schedule_switch, "active", Gio.SettingsBindFlags.DEFAULT);
|
||||
locationSettings.bind("manual-location", this._manual_location_switch, "active", Gio.SettingsBindFlags.DEFAULT);
|
||||
locationSettings.bind("latitude", this._latitude_spin, "value", Gio.SettingsBindFlags.DEFAULT);
|
||||
locationSettings.bind("longitude", this._longitude_spin, "value", Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
settings.bind("sunrise", this._schedule_sunrise_time_chooser, "time", Gio.SettingsBindFlags.DEFAULT);
|
||||
settings.bind("sunset", this._schedule_sunset_time_chooser, "time", Gio.SettingsBindFlags.DEFAULT);
|
||||
// We have to manually force this for AdwSpinRow after binding the value property
|
||||
this._latitude_spin.sensitive = this._manual_location_switch.active;
|
||||
this._longitude_spin.sensitive = this._manual_location_switch.active;
|
||||
|
||||
settings.bind("offset", this._schedule_offset_spin_button, "value", Gio.SettingsBindFlags.DEFAULT);
|
||||
timeSettings.bind("manual-schedule", this._manual_schedule_switch, "active", Gio.SettingsBindFlags.DEFAULT);
|
||||
timeSettings.bind("sunrise", this._schedule_sunrise_time_chooser, "time", Gio.SettingsBindFlags.DEFAULT);
|
||||
timeSettings.bind("sunset", this._schedule_sunset_time_chooser, "time", Gio.SettingsBindFlags.DEFAULT);
|
||||
timeSettings.bind("offset", this._schedule_offset_spin_button, "value", Gio.SettingsBindFlags.DEFAULT);
|
||||
timeSettings.bind(
|
||||
"fullscreen-transition",
|
||||
this._fullscreen_transition_switch,
|
||||
"active",
|
||||
Gio.SettingsBindFlags.DEFAULT,
|
||||
);
|
||||
|
||||
settings.bind("fullscreen-transition", this._fullscreen_transition_switch, "active", Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
settings.connect("changed::nightthemeswitcher-ondemand-keybinding", () => {
|
||||
this._keyboard_shortcut_button.keybinding = settings.get_strv("nightthemeswitcher-ondemand-keybinding")[0];
|
||||
timeSettings.connect("changed::nightthemeswitcher-ondemand-keybinding", () => {
|
||||
this._keyboard_shortcut_button.keybinding = timeSettings.get_strv("nightthemeswitcher-ondemand-keybinding")[0];
|
||||
});
|
||||
this._keyboard_shortcut_button.connect("notify::keybinding", () => {
|
||||
settings.set_strv("nightthemeswitcher-ondemand-keybinding", [this._keyboard_shortcut_button.keybinding]);
|
||||
timeSettings.set_strv("nightthemeswitcher-ondemand-keybinding", [this._keyboard_shortcut_button.keybinding]);
|
||||
});
|
||||
this._keyboard_shortcut_button.keybinding = settings.get_strv("nightthemeswitcher-ondemand-keybinding")[0];
|
||||
this._keyboard_shortcut_button.keybinding = timeSettings.get_strv("nightthemeswitcher-ondemand-keybinding")[0];
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -70,7 +70,10 @@ export default class NightThemeSwitcherPreferences extends ExtensionPreferences
|
||||
colorSchemeSettings: this.getSettings(`${this.metadata["settings-schema"]}.color-scheme`),
|
||||
}),
|
||||
new CommandsPage({ settings: this.getSettings(`${this.metadata["settings-schema"]}.commands`) }),
|
||||
new TweaksPage({ settings: this.getSettings(`${this.metadata["settings-schema"]}.time`) }),
|
||||
new TweaksPage({
|
||||
locationSettings: this.getSettings(`${this.metadata["settings-schema"]}.location`),
|
||||
timeSettings: this.getSettings(`${this.metadata["settings-schema"]}.time`),
|
||||
}),
|
||||
new ContributePage(),
|
||||
].forEach((page) => window.add(page));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user