Files
crossdesk/apps/harmony/entry/src/main/ets/mobile/RemotePrivacyScreen.ets
T

103 lines
5.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { tr } from './Localization';
export interface PrivacyStatus {
state: number; supported: boolean; input_block_supported: boolean;
overlay_active: boolean; input_blocked: boolean; remote_paused: boolean;
revision: number; reason: string; local_unlock_revision?: number;
}
export class RemotePrivacyScreen {
desktopAvailable: boolean = true;
snapshot?: PrivacyStatus;
pending: boolean = false;
unlockNotice: boolean = false;
requestId: number = 0;
private requestRevision: number = 0;
private receivedAt: number = 0;
private requestedAt: number = 0;
private failure: string = '';
setInteractiveStage(stage: string): void {
this.desktopAvailable = stage !== 'lock-screen' && stage !== 'credential-ui' && stage !== 'secure-desktop';
}
receive(s: PrivacyStatus, now: number): void {
if (!Number.isInteger(s.state) || s.state < 0 || s.state > 5 ||
!Number.isInteger(s.revision) || s.revision < 0 || s.revision > 0xffffffff ||
typeof s.supported !== 'boolean' || typeof s.input_block_supported !== 'boolean' ||
typeof s.overlay_active !== 'boolean' || typeof s.input_blocked !== 'boolean' ||
typeof s.remote_paused !== 'boolean' || typeof s.reason !== 'string' || s.reason.includes('\0')) return;
if (s.state === 3 && (!s.supported || !s.overlay_active || s.remote_paused)) return;
if (this.snapshot && ((s.revision - this.snapshot.revision) | 0) < 0) return;
const unlock = s.local_unlock_revision ?? 0;
if (!Number.isInteger(unlock) || unlock < 0 || unlock > 0xffffffff) return;
if (this.snapshot && ((unlock - (this.snapshot.local_unlock_revision ?? 0)) | 0) > 0) this.unlockNotice = true;
if (s.state === 3) this.unlockNotice = false;
this.snapshot = s; this.receivedAt = now; this.failure = '';
if (this.pending && ((s.revision - this.requestRevision) | 0) > 0 && s.state !== 2 && s.state !== 4) this.pending = false;
}
active(): boolean {
const s = this.snapshot;
return s !== undefined && (s.overlay_active || s.remote_paused || s.state === 2 || s.state === 3 || s.state === 4);
}
fresh(now: number): boolean { return this.snapshot !== undefined && now - this.receivedAt <= 5000; }
enabled(now: number): boolean {
const s = this.snapshot;
return s !== undefined && this.fresh(now) && s.state === 3 && s.overlay_active && !s.remote_paused;
}
buttonTitle(now: number): string {
if (this.enabled(now)) return tr("隐私屏已开启");
const s = this.snapshot;
if (this.fresh(now) && s?.supported && s.state === 1 && !this.active()) return tr("隐私屏已关闭");
return tr("隐私屏");
}
feedback(now: number): string {
if (!this.desktopAvailable) return '';
const s = this.snapshot;
if (!this.failure && (this.pending || this.fresh(now) && (s?.state === 2 || s?.state === 4))) return '';
if (!this.failure && !this.pending && this.fresh(now) && s?.supported &&
(this.enabled(now) || s.state === 1 && !this.active())) return '';
const detail = this.detail(now);
return this.status(now) + (detail ? ':' + detail : '');
}
canToggle(now: number): boolean {
const s = this.snapshot;
return this.desktopAvailable && s !== undefined && !this.pending && this.fresh(now) && s.state !== 4 && (this.active() || s.supported && s.state === 1);
}
canLock(now: number): boolean {
return this.desktopAvailable && !this.pending && this.fresh(now) && this.snapshot?.supported === true;
}
begin(now: number, lock: boolean = false): number {
this.tick(now);
if (!(lock ? this.canLock(now) : this.canToggle(now)) || !this.snapshot) return -1;
this.pending = true; this.requestedAt = now; this.requestRevision = this.snapshot.revision; this.failure = '';
this.requestId = (this.requestId + 1) >>> 0;
return this.requestId;
}
failed(id: number): void {
if (this.pending && this.requestId === id) { this.pending = false; this.failure = tr("指令发送失败,请重试"); }
}
tick(now: number): void {
if (this.pending && now - this.requestedAt >= 15000) {
this.pending = false; this.failure = tr("请求超时,尚未确认电脑的隐私屏状态");
}
}
status(now: number): string {
if (this.failure) return this.failure;
const s = this.snapshot;
if (!s) return tr("等待电脑返回隐私屏状态;旧版电脑端可能不支持");
if (!this.fresh(now)) return tr("隐私屏状态已过期,等待电脑确认");
if (s.state === 2) return tr("正在开启隐私屏…");
if (s.state === 4) return tr("正在关闭隐私屏…");
if (this.pending) return tr("指令已发送,等待电脑确认…");
if (s.state === 5) return tr("隐私屏异常");
if (!s.supported || s.state === 0) return tr("隐私屏暂不可用");
if (s.state === 3 && s.overlay_active && !s.remote_paused)
return tr("隐私屏已开启");
return s.state === 1 && !this.active() ? tr("隐私屏已关闭") : tr("隐私屏状态待确认");
}
detail(now: number): string {
const s = this.snapshot;
return s && this.fresh(now) && (s.state === 0 || s.state === 5 || !s.supported) ? s.reason : '';
}
}