round64: Neues Android-Startbildschirm-artiges Design fuer die mobile Ansicht, umschaltbar in den Einstellungen

This commit is contained in:
2026-07-26 16:55:00 +02:00
parent c05562c4cd
commit 538fba5fc3
7 changed files with 747 additions and 18 deletions

View File

@@ -1,17 +1,31 @@
import type { FastifyInstance } from "fastify";
import * as settingsRepo from "../db/repositories/settings.js";
function serializeSettings() {
const all = settingsRepo.listSettings();
return {
recentVisitsLimit: Number(all.recentVisitsLimit ?? 5),
readLaterLimit: Number(all.readLaterLimit ?? 5),
staleDeviceThresholdDays: Number(all.staleDeviceThresholdDays ?? 7),
liveStatusEnabled: all.liveStatusEnabled === "true",
liveStatusIntervalMinutes: Number(all.liveStatusIntervalMinutes ?? 5),
liveStatusLastRunAt: all.liveStatusLastRunAt ?? null,
// NEU (round64): Wahl zwischen dem bisherigen (Listen-)Design und einem
// neuen, Android-Startbildschirm-artigen Design für die MOBILE Ansicht
// (Desktop bleibt davon unberührt). Bewusst hier in den serverseitigen
// Einstellungen statt nur im sessionStorage/localStorage des jeweiligen
// Browsers, damit die Wahl wirklich app-weit gilt, nicht nur pro Gerät.
mobileHomeStyle: all.mobileHomeStyle === "android" ? "android" : "classic",
// Nur relevant, wenn mobileHomeStyle "android" ist: Kategorien als
// antippbare "Ordner" (wie ein Android-Ordner mit Mini-Vorschau) oder
// alles auf einer durchgehend scrollbaren Seite mit Abschnitts-Überschriften.
mobileHomeFolderMode: all.mobileHomeFolderMode === "scroll" ? "scroll" : "folders",
};
}
export async function settingsRoutes(app: FastifyInstance): Promise<void> {
app.get("/api/settings", async () => {
const all = settingsRepo.listSettings();
return {
recentVisitsLimit: Number(all.recentVisitsLimit ?? 5),
readLaterLimit: Number(all.readLaterLimit ?? 5),
staleDeviceThresholdDays: Number(all.staleDeviceThresholdDays ?? 7),
liveStatusEnabled: all.liveStatusEnabled === "true",
liveStatusIntervalMinutes: Number(all.liveStatusIntervalMinutes ?? 5),
liveStatusLastRunAt: all.liveStatusLastRunAt ?? null,
};
return serializeSettings();
});
app.patch("/api/settings", async (request, reply) => {
@@ -22,6 +36,8 @@ export async function settingsRoutes(app: FastifyInstance): Promise<void> {
staleDeviceThresholdDays?: number;
liveStatusEnabled?: boolean;
liveStatusIntervalMinutes?: number;
mobileHomeStyle?: string;
mobileHomeFolderMode?: string;
}
| undefined;
@@ -61,14 +77,20 @@ export async function settingsRoutes(app: FastifyInstance): Promise<void> {
settingsRepo.setSetting("liveStatusIntervalMinutes", String(Math.round(value)));
}
const all = settingsRepo.listSettings();
return {
recentVisitsLimit: Number(all.recentVisitsLimit ?? 5),
readLaterLimit: Number(all.readLaterLimit ?? 5),
staleDeviceThresholdDays: Number(all.staleDeviceThresholdDays ?? 7),
liveStatusEnabled: all.liveStatusEnabled === "true",
liveStatusIntervalMinutes: Number(all.liveStatusIntervalMinutes ?? 5),
liveStatusLastRunAt: all.liveStatusLastRunAt ?? null,
};
if (body?.mobileHomeStyle !== undefined) {
if (body.mobileHomeStyle !== "classic" && body.mobileHomeStyle !== "android") {
return reply.code(400).send({ error: "mobileHomeStyle muss 'classic' oder 'android' sein" });
}
settingsRepo.setSetting("mobileHomeStyle", body.mobileHomeStyle);
}
if (body?.mobileHomeFolderMode !== undefined) {
if (body.mobileHomeFolderMode !== "folders" && body.mobileHomeFolderMode !== "scroll") {
return reply.code(400).send({ error: "mobileHomeFolderMode muss 'folders' oder 'scroll' sein" });
}
settingsRepo.setSetting("mobileHomeFolderMode", body.mobileHomeFolderMode);
}
return serializeSettings();
});
}