colour -> color, behaviour -> behavior, centre -> center, favourite -> favorite, and about twenty other pairs, applied consistently across comments, docs, error/UI copy, and a handful of QML identifiers that used the British spelling as their actual name: SystemSettings' serialiseValue/serialiseTable/normaliseGradient, Displays' normaliseModes, Wallpaper's normalisePolicy, SettingsBackup's serialiseHomeState, DateTime's ntpSynchronised property, Clipboard's _normalise helper, and ShortcutCapture's cancelled signal (with its onCancelled handler in ShortcutsPage.qml). Every call site and the two tests that assert on the literal source text (settings-ownership and settings-backup-live contracts) were updated in lockstep. Left untouched: config/dot/espanso/match/packages/misspell-en/ is a vendored third-party autocorrect dictionary -- its entries are typo corrections, not our prose, and rewriting them would fight the package's own purpose (and any future re-sync from upstream). The already-American `favorites` property (Home page pinned accessories) was never actually misspelled -- only nearby comments and error strings said "favourites" -- so no data migration was needed there. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
177 lines
5.1 KiB
QML
177 lines
5.1 KiB
QML
pragma Singleton
|
|
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import QtQuick
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
property alias initialized: values.initialized
|
|
property alias favorites: values.favorites
|
|
property string saveError: ""
|
|
|
|
FileView {
|
|
id: preferencesFile
|
|
|
|
path: Quickshell.stateDir + "/panama-home.json"
|
|
blockLoading: true
|
|
printErrors: false
|
|
atomicWrites: true
|
|
onSaved: root.saveError = ""
|
|
onSaveFailed: error => root.saveError = "Could not save Home favorites."
|
|
|
|
JsonAdapter {
|
|
id: values
|
|
|
|
property bool initialized: false
|
|
property var favorites: []
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: values
|
|
function onInitializedChanged(): void { persistTimer.restart(); }
|
|
function onFavoritesChanged(): void { persistTimer.restart(); }
|
|
}
|
|
|
|
Component.onCompleted: preferencesFile.reload()
|
|
|
|
Timer {
|
|
id: persistTimer
|
|
interval: 180
|
|
repeat: false
|
|
onTriggered: preferencesFile.writeAdapter()
|
|
}
|
|
|
|
function cloneFavorites(): var {
|
|
var clone = [];
|
|
for (var index = 0; index < values.favorites.length; index++) {
|
|
var favorite = values.favorites[index];
|
|
clone.push({
|
|
id: favorite.id,
|
|
alias: favorite.alias
|
|
});
|
|
}
|
|
return clone;
|
|
}
|
|
|
|
function isValidEntityId(entityId: var): bool {
|
|
return typeof entityId === "string" && /^light\.[a-z0-9_]+$/.test(entityId);
|
|
}
|
|
|
|
function initialize(legacyIds: var): void {
|
|
if (values.initialized) {
|
|
return;
|
|
}
|
|
|
|
var seededFavorites = [];
|
|
var seen = {};
|
|
if (legacyIds && typeof legacyIds.length === "number") {
|
|
for (var index = 0; index < legacyIds.length; index++) {
|
|
var entityId = legacyIds[index];
|
|
if (!isValidEntityId(entityId) || seen[entityId]) {
|
|
continue;
|
|
}
|
|
seen[entityId] = true;
|
|
seededFavorites.push({ id: entityId, alias: "" });
|
|
}
|
|
}
|
|
|
|
values.favorites = seededFavorites;
|
|
values.initialized = true;
|
|
}
|
|
|
|
function resetHomeDefaults(): void {
|
|
persistTimer.stop();
|
|
values.favorites = [];
|
|
values.initialized = false;
|
|
root.saveError = "";
|
|
preferencesFile.writeAdapter();
|
|
}
|
|
|
|
function isSelected(entityId: string): bool {
|
|
for (var index = 0; index < values.favorites.length; index++) {
|
|
if (values.favorites[index].id === entityId) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function aliasFor(entityId: string, sourceName: string): string {
|
|
for (var index = 0; index < values.favorites.length; index++) {
|
|
var favorite = values.favorites[index];
|
|
if (favorite.id === entityId && favorite.alias !== "") {
|
|
return favorite.alias;
|
|
}
|
|
}
|
|
return sourceName;
|
|
}
|
|
|
|
function add(entityId: string): void {
|
|
if (!isValidEntityId(entityId) || isSelected(entityId)) {
|
|
return;
|
|
}
|
|
|
|
var nextFavorites = cloneFavorites();
|
|
nextFavorites.push({ id: entityId, alias: "" });
|
|
values.favorites = nextFavorites;
|
|
}
|
|
|
|
function remove(entityId: string): void {
|
|
var nextFavorites = [];
|
|
var removed = false;
|
|
for (var index = 0; index < values.favorites.length; index++) {
|
|
var favorite = values.favorites[index];
|
|
if (favorite.id === entityId) {
|
|
removed = true;
|
|
continue;
|
|
}
|
|
nextFavorites.push({ id: favorite.id, alias: favorite.alias });
|
|
}
|
|
if (removed) {
|
|
values.favorites = nextFavorites;
|
|
}
|
|
}
|
|
|
|
function setAlias(entityId: string, alias: string): void {
|
|
var nextFavorites = cloneFavorites();
|
|
var updated = false;
|
|
var trimmedAlias = String(alias).trim();
|
|
for (var index = 0; index < nextFavorites.length; index++) {
|
|
if (nextFavorites[index].id === entityId) {
|
|
nextFavorites[index] = { id: entityId, alias: trimmedAlias };
|
|
updated = true;
|
|
break;
|
|
}
|
|
}
|
|
if (updated) {
|
|
values.favorites = nextFavorites;
|
|
}
|
|
}
|
|
|
|
function move(entityId: string, targetIndex: int): void {
|
|
var nextFavorites = cloneFavorites();
|
|
var currentIndex = -1;
|
|
for (var index = 0; index < nextFavorites.length; index++) {
|
|
if (nextFavorites[index].id === entityId) {
|
|
currentIndex = index;
|
|
break;
|
|
}
|
|
}
|
|
if (currentIndex === -1) {
|
|
return;
|
|
}
|
|
|
|
var favorite = nextFavorites.splice(currentIndex, 1)[0];
|
|
var clampedIndex = Math.max(0, Math.min(targetIndex, nextFavorites.length));
|
|
nextFavorites.splice(clampedIndex, 0, favorite);
|
|
values.favorites = nextFavorites;
|
|
}
|
|
|
|
function retrySave(): void {
|
|
preferencesFile.writeAdapter();
|
|
}
|
|
}
|