mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-04 04:42:05 -04:00
Add GeoClue2 integration as alternative to IP location (#1856)
* feat: switch auto location in weather widget to use GeoClue2 instead of simple IP check * nix: enable GeoClue2 service by default * lint: fix line endings * fix: fall back to IP location if GeoClue is not available
This commit is contained in:
@@ -61,12 +61,13 @@ Singleton {
|
||||
signal appPickerRequested(var data)
|
||||
signal screensaverStateUpdate(var data)
|
||||
signal clipboardStateUpdate(var data)
|
||||
signal locationStateUpdate(var data)
|
||||
|
||||
property bool capsLockState: false
|
||||
property bool screensaverInhibited: false
|
||||
property var screensaverInhibitors: []
|
||||
|
||||
property var activeSubscriptions: ["network", "network.credentials", "loginctl", "freedesktop", "freedesktop.screensaver", "gamma", "theme.auto", "bluetooth", "bluetooth.pairing", "dwl", "brightness", "wlroutput", "evdev", "browser", "dbus", "clipboard"]
|
||||
property var activeSubscriptions: ["network", "network.credentials", "loginctl", "freedesktop", "freedesktop.screensaver", "gamma", "theme.auto", "bluetooth", "bluetooth.pairing", "dwl", "brightness", "wlroutput", "evdev", "browser", "dbus", "clipboard", "location"]
|
||||
|
||||
Component.onCompleted: {
|
||||
if (socketPath && socketPath.length > 0) {
|
||||
@@ -284,7 +285,7 @@ Singleton {
|
||||
|
||||
function removeSubscription(service) {
|
||||
if (activeSubscriptions.includes("all")) {
|
||||
const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "dwl", "brightness", "extworkspace", "browser"];
|
||||
const allServices = ["network", "loginctl", "freedesktop", "gamma", "bluetooth", "dwl", "brightness", "extworkspace", "browser", "location"];
|
||||
const filtered = allServices.filter(s => s !== service);
|
||||
subscribe(filtered);
|
||||
} else {
|
||||
@@ -306,7 +307,7 @@ Singleton {
|
||||
excludeServices = [excludeServices];
|
||||
}
|
||||
|
||||
const allServices = ["network", "loginctl", "freedesktop", "gamma", "theme.auto", "bluetooth", "cups", "dwl", "brightness", "extworkspace", "browser", "dbus"];
|
||||
const allServices = ["network", "loginctl", "freedesktop", "gamma", "theme.auto", "bluetooth", "cups", "dwl", "brightness", "extworkspace", "browser", "dbus", "location"];
|
||||
const filtered = allServices.filter(s => !excludeServices.includes(s));
|
||||
subscribe(filtered);
|
||||
}
|
||||
@@ -395,6 +396,8 @@ Singleton {
|
||||
dbusSignalReceived(data.subscriptionId || "", data);
|
||||
} else if (service === "clipboard") {
|
||||
clipboardStateUpdate(data);
|
||||
} else if (service === "location") {
|
||||
locationStateUpdate(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
51
quickshell/Services/LocationService.qml
Normal file
51
quickshell/Services/LocationService.qml
Normal file
@@ -0,0 +1,51 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
readonly property bool locationAvailable: DMSService.isConnected && (DMSService.capabilities.length === 0 || DMSService.capabilities.includes("location"))
|
||||
|
||||
property var latitude: 0.0
|
||||
property var longitude: 0.0
|
||||
|
||||
signal locationChanged(var data)
|
||||
|
||||
Component.onCompleted: {
|
||||
console.info("LocationService: Initializing...");
|
||||
getState();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: DMSService
|
||||
|
||||
function onLocationStateUpdate(data) {
|
||||
if (locationAvailable) {
|
||||
handleStateUpdate(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleStateUpdate(data) {
|
||||
root.latitude = data.latitude;
|
||||
root.longitude = data.longitude;
|
||||
|
||||
root.locationChanged(data)
|
||||
}
|
||||
|
||||
function getState() {
|
||||
if (!locationAvailable)
|
||||
return;
|
||||
|
||||
DMSService.sendRequest("location.getState", null, response => {
|
||||
if (response.result) {
|
||||
handleStateUpdate(response.result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -480,7 +480,7 @@ Singleton {
|
||||
const cityName = SessionData.isGreeterMode ? GreetdSettings.weatherLocation : SettingsData.weatherLocation;
|
||||
|
||||
if (useAuto) {
|
||||
getLocationFromIP();
|
||||
getLocationFromService();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -511,8 +511,8 @@ Singleton {
|
||||
cityGeocodeFetcher.running = true;
|
||||
}
|
||||
|
||||
function getLocationFromIP() {
|
||||
ipLocationFetcher.running = true;
|
||||
function getLocationFromService() {
|
||||
getLocationFromCoords(LocationService.latitude, LocationService.longitude);
|
||||
}
|
||||
|
||||
function fetchWeather() {
|
||||
@@ -583,53 +583,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: ipLocationFetcher
|
||||
command: lowPriorityCmd.concat(curlBaseCmd).concat(["http://ip-api.com/json/"])
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const raw = text.trim();
|
||||
if (!raw || raw[0] !== "{") {
|
||||
root.handleWeatherFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(raw);
|
||||
|
||||
if (data.status === "fail") {
|
||||
throw new Error("IP location lookup failed");
|
||||
}
|
||||
|
||||
const lat = parseFloat(data.lat);
|
||||
const lon = parseFloat(data.lon);
|
||||
const city = data.city;
|
||||
|
||||
if (!city || isNaN(lat) || isNaN(lon)) {
|
||||
throw new Error("Missing or invalid location data");
|
||||
}
|
||||
|
||||
root.location = {
|
||||
city: city,
|
||||
latitude: lat,
|
||||
longitude: lon
|
||||
};
|
||||
fetchWeather();
|
||||
} catch (e) {
|
||||
root.handleWeatherFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onExited: exitCode => {
|
||||
if (exitCode !== 0) {
|
||||
root.handleWeatherFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: reverseGeocodeFetcher
|
||||
running: false
|
||||
@@ -872,6 +825,16 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: LocationService
|
||||
|
||||
function onLocationChanged(data) {
|
||||
if (SettingsData.useAutoLocation) {
|
||||
root.getLocationFromCoords(data.latitude, data.longitude)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
SettingsData.weatherCoordinatesChanged.connect(() => {
|
||||
root.location = null;
|
||||
|
||||
Reference in New Issue
Block a user