mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-28 08:42:43 +08:00
103 lines
5.1 KiB
Plaintext
103 lines
5.1 KiB
Plaintext
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 : '';
|
||
}
|
||
}
|