perf(desktop): Dashboard-Aufbau in der Linux-App ohne Einblend-Animation, Melder gegen Fokus-Schuebe gedrosselt
Gemessen in der echten Linux-App (WebKitGTK): Haenger beim Oeffnen des Dashboards von 550-1100 ms auf 250-350 ms. Im alpha-Log kamen beim Oeffnen bis zu 50 Abfragen je Sekunde von Erinnerungs- und Nextcloud-Melder; Fokus-/ Sichtbarkeitswechsel loesen jetzt hoechstens alle 10 s eine Abfrage aus. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { cleanup, render } from '@testing-library/react';
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { DESKTOP_CLIENT_COOKIE_NAME } from '@/lib/desktop-client';
|
||||
import { DesktopPlatformMarker } from './desktop-platform-marker';
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
document.cookie = `${DESKTOP_CLIENT_COOKIE_NAME}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
||||
});
|
||||
|
||||
describe('DesktopPlatformMarker', () => {
|
||||
it('setzt das Betriebssystem der Desktop-App am html-Element', () => {
|
||||
document.cookie = `${DESKTOP_CLIENT_COOKIE_NAME}=${encodeURIComponent('1.9.2|abc1234|linux')}; path=/`;
|
||||
render(<DesktopPlatformMarker />);
|
||||
expect(document.documentElement.dataset.desktopOs).toBe('linux');
|
||||
});
|
||||
|
||||
it('setzt im Browser nichts', () => {
|
||||
render(<DesktopPlatformMarker />);
|
||||
expect(document.documentElement.dataset.desktopOs).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { getDesktopClientInfo } from '@/lib/desktop-client';
|
||||
|
||||
/**
|
||||
* DesktopPlatformMarker (quick-261002) — setzt `data-desktop-os` am
|
||||
* `<html>` (z. B. `linux`), damit CSS die Desktop-App je Betriebssystem
|
||||
* anpassen kann. Anlass: Die Linux-Webview (WebKitGTK) zeichnet ohne
|
||||
* Grafikbeschleunigung; die gestaffelte Einblend-Animation der Kacheln liess
|
||||
* den Aufbau des Dashboards spuerbar stocken (gemessen: Haenger von
|
||||
* 550-1100 ms auf ~230 ms ohne Animation). Im Browser ohne Wirkung.
|
||||
*/
|
||||
export function DesktopPlatformMarker() {
|
||||
useEffect(() => {
|
||||
const os = getDesktopClientInfo()?.os;
|
||||
if (!os) return;
|
||||
document.documentElement.dataset.desktopOs = os;
|
||||
return () => {
|
||||
delete document.documentElement.dataset.desktopOs;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -9,6 +9,8 @@ const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
||||
const MODULE_SLUG = 'nextcloud-status';
|
||||
/** Abstand der Abfrage beim Server. */
|
||||
const POLL_MS = 60_000;
|
||||
/** Mindestabstand fuer Abfragen nach Fokus-/Sichtbarkeitswechsel. */
|
||||
export const RESUME_MIN_MS = 10_000;
|
||||
|
||||
/** Rote Grundkennung der API -> Schluessel unter `nextcloudStatus.notify.down`. */
|
||||
const DOWN_KEYS: Record<string, string> = {
|
||||
@@ -110,7 +112,14 @@ export function NextcloudAlertNotifier() {
|
||||
void start();
|
||||
const interval = setInterval(() => void poll(), POLL_MS);
|
||||
|
||||
// Fokus/Sichtbarkeit loesen hoechstens alle RESUME_MIN_MS eine Abfrage aus:
|
||||
// In der Linux-Desktop-App kamen diese Ereignisse beim Oeffnen des
|
||||
// Dashboards in Schueben (bis zu 50 Abfragen je Sekunde im API-Log).
|
||||
let lastResume = Date.now();
|
||||
const resume = () => {
|
||||
const now = Date.now();
|
||||
if (now - lastResume < RESUME_MIN_MS) return;
|
||||
lastResume = now;
|
||||
pausedRef.current = false;
|
||||
void start();
|
||||
};
|
||||
|
||||
@@ -143,4 +143,16 @@ describe('ReminderNotifier', () => {
|
||||
});
|
||||
expect(mockList.mock.calls.length).toBe(after401 + 1);
|
||||
});
|
||||
it('viele Fokus-Ereignisse kurz hintereinander loesen nur eine Abfrage aus', async () => {
|
||||
mockList.mockResolvedValue([]);
|
||||
render(<ReminderNotifier />);
|
||||
await advance(0);
|
||||
await advance(15_000);
|
||||
const before = mockList.mock.calls.length;
|
||||
await act(async () => {
|
||||
for (let i = 0; i < 50; i++) window.dispatchEvent(new Event('focus'));
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
});
|
||||
expect(mockList.mock.calls.length).toBe(before + 1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,14 +9,16 @@ import {
|
||||
withNotifyLock,
|
||||
} from '@/lib/reminder-notify';
|
||||
import {
|
||||
listReminders,
|
||||
REMINDERS_CHANGED_EVENT,
|
||||
type Reminder,
|
||||
ReminderRequestError,
|
||||
listReminders,
|
||||
} from '@/lib/reminders-api';
|
||||
|
||||
/** Abstand der Abfrage beim Server. */
|
||||
const POLL_MS = 60_000;
|
||||
/** Mindestabstand fuer Abfragen nach Fokus-/Sichtbarkeitswechsel. */
|
||||
export const RESUME_MIN_MS = 10_000;
|
||||
/** Abstand der lokalen Faelligkeitspruefung gegen die geladene Liste (ohne Netz). */
|
||||
const TICK_MS = 10_000;
|
||||
const BODY_MAX = 200;
|
||||
@@ -87,7 +89,14 @@ export function ReminderNotifier() {
|
||||
const poll = setInterval(() => void load(), POLL_MS);
|
||||
const tick = setInterval(() => void notifyDue(), TICK_MS);
|
||||
|
||||
// Fokus/Sichtbarkeit loesen hoechstens alle RESUME_MIN_MS eine Abfrage aus:
|
||||
// In der Linux-Desktop-App kamen diese Ereignisse beim Oeffnen des
|
||||
// Dashboards in Schueben (bis zu 50 Abfragen je Sekunde im API-Log).
|
||||
let lastResume = Date.now();
|
||||
const resume = () => {
|
||||
const now = Date.now();
|
||||
if (now - lastResume < RESUME_MIN_MS) return;
|
||||
lastResume = now;
|
||||
pausedRef.current = false;
|
||||
void load();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user