feat(android): switch to screen-on rotation service and updated scheduler
The rotation service now responds to screen on/off events via a dedicated ScreenOnRotationService, reducing background work and avoiding perpetual wakeful states. Manifest and receiver logic were adjusted to align with the new behavior and energy constraints. Scheduling and enablement now consistently use timed-based rules and screen-on preferences, with the boot and alarm paths updated to honor these settings. This avoids unnecessary foreground services and keeps the app compliant with Doze and battery optimizations. Immich image handling improvements include throttled progress updates, larger cache allowances, and a connectivity-aware automatic download check to avoid unwanted network usage. - Use ScreenOnRotationService for screen-on based rotation scheduling - Centralize enablement via timed-enabled paths and AlarmManager windowing - Improve Immich cache and progress reporting with connectivity checks
This commit is contained in:
+7
-8
@@ -14,9 +14,10 @@ function SettingRow({ icon, label, value, onChange }: { icon: React.ReactNode; l
|
||||
return <div className="setting-row"><div className="setting-icon">{icon}</div><span>{label}</span><Switch checked={value} onChange={onChange} label={label} /></div>;
|
||||
}
|
||||
|
||||
function IntervalRow({ value, onChange, label, paused, everyMinutes }: { value: number; onChange: (value: number) => void; label: string; paused: string; everyMinutes: (minutes: number) => string }) {
|
||||
function IntervalRow({ value, onChange, label, paused, screenOn, everyMinutes }: { value: number; onChange: (value: number) => void; label: string; paused: string; screenOn: string; everyMinutes: (minutes: number) => string }) {
|
||||
return <label className="setting-row interval-row"><div className="setting-icon"><Smartphone /></div><span>{label}</span><select value={value} onChange={event => onChange(Number(event.target.value))} aria-label={label}>
|
||||
<option value={0}>{paused}</option>
|
||||
<option value={-1}>{screenOn}</option>
|
||||
{[5, 15, 30, 60, 180, 360, 720].map(minutes => <option value={minutes} key={minutes}>{everyMinutes(minutes)}</option>)}
|
||||
</select></label>;
|
||||
}
|
||||
@@ -54,11 +55,9 @@ export default function App() {
|
||||
const refresh = () => { void getState().then(setState).catch(() => undefined); };
|
||||
refresh();
|
||||
const onVisibilityChange = () => { if (!document.hidden) refresh(); };
|
||||
const refreshInterval = window.setInterval(() => { if (!document.hidden) refresh(); }, 15000);
|
||||
document.addEventListener("visibilitychange", onVisibilityChange);
|
||||
window.addEventListener("focus", refresh);
|
||||
return () => {
|
||||
window.clearInterval(refreshInterval);
|
||||
document.removeEventListener("visibilitychange", onVisibilityChange);
|
||||
window.removeEventListener("focus", refresh);
|
||||
};
|
||||
@@ -118,11 +117,11 @@ export default function App() {
|
||||
}
|
||||
|
||||
async function updateInterval(minutes: number) {
|
||||
setState(prev => ({ ...prev, intervalMinutes: minutes, enabled: minutes > 0 }));
|
||||
setState(prev => ({ ...prev, intervalMinutes: minutes, enabled: minutes !== 0 }));
|
||||
try {
|
||||
const saved = await setIntervalMinutes(minutes);
|
||||
setState(saved);
|
||||
setNotice(minutes > 0 ? t.intervalSaved : t.automaticDisabled);
|
||||
setNotice(minutes !== 0 ? t.intervalSaved : t.automaticDisabled);
|
||||
}
|
||||
catch { setNotice(t.androidOnly); }
|
||||
}
|
||||
@@ -249,7 +248,7 @@ export default function App() {
|
||||
setNotice(it.importing);
|
||||
const poll = window.setInterval(() => {
|
||||
void getImmichImportProgress().then(setImmichImportProgress).catch(() => undefined);
|
||||
}, 250);
|
||||
}, 750);
|
||||
try {
|
||||
setState(await importImmichAssets([...immichSelected]));
|
||||
setImmichSelected(new Set());
|
||||
@@ -408,7 +407,7 @@ export default function App() {
|
||||
<div className="hero-meta"><span><Sparkles size={16} /> {t.currentImage}</span><button onClick={next} disabled={busy}>{t.nextImage} <ChevronRight size={18} /></button></div>
|
||||
</section>
|
||||
|
||||
<IntervalRow value={state.intervalMinutes} onChange={updateInterval} label={t.changeInterval} paused={t.paused} everyMinutes={t.everyMinutes} />
|
||||
<IntervalRow value={state.intervalMinutes} onChange={updateInterval} label={t.changeInterval} paused={t.paused} screenOn={t.screenOn} everyMinutes={t.everyMinutes} />
|
||||
|
||||
<button className="primary" onClick={choose} disabled={busy}><Images />{busy ? t.pleaseWait : t.selectImages}</button>
|
||||
|
||||
@@ -421,7 +420,7 @@ export default function App() {
|
||||
</> : tab === "settings" ? <section className="settings-page">
|
||||
<h2>{t.settings}</h2><p>{t.settingsIntro}</p>
|
||||
<label className="language-setting"><div className="setting-icon"><Languages /></div><div><strong>{t.language}</strong><span>{languageNames[language]}</span></div><select className="locale-select" value={language} onChange={event => setLanguage(event.target.value as Language)} aria-label={t.language}>{languages.map(locale => <option value={locale} key={locale}>{languageNames[locale]}</option>)}</select></label>
|
||||
<div className="settings-list"><IntervalRow value={state.intervalMinutes} onChange={updateInterval} label={t.changeInterval} paused={t.paused} everyMinutes={t.everyMinutes} /><SettingRow icon={<Shuffle />} label={t.shuffle} value={state.shuffle} onChange={v => update("shuffle", v)} /><SettingRow icon={<LockKeyhole />} label={t.lockScreenOnly} value={state.lockScreenOnly} onChange={v => update("lockScreenOnly", v)} /></div>
|
||||
<div className="settings-list"><IntervalRow value={state.intervalMinutes} onChange={updateInterval} label={t.changeInterval} paused={t.paused} screenOn={t.screenOn} everyMinutes={t.everyMinutes} /><SettingRow icon={<Shuffle />} label={t.shuffle} value={state.shuffle} onChange={v => update("shuffle", v)} /><SettingRow icon={<LockKeyhole />} label={t.lockScreenOnly} value={state.lockScreenOnly} onChange={v => update("lockScreenOnly", v)} /></div>
|
||||
<section className="immich-settings">
|
||||
<div className="immich-title"><span><Cloud /></span><div><h3>{it.immich}</h3><p>{it.immichIntro}</p></div></div>
|
||||
{immichConnection.configured ? <>
|
||||
|
||||
Reference in New Issue
Block a user