/*
* Copyright (c) Huawei Device Co., Ltd. 2024-2025. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { LogDomain, LogHelper } from '@ohos/basicutils';
import { systemDateTime } from '@kit.BasicServicesKit';
import { AbstractObserverManager } from '../base/AbstractObserverManager';
import { ResUtils } from '@ohos/windowscene/src/main/ets/utils/ResourceUtils';
const TAG: string = 'CountDownTimer';
const log: LogHelper = LogHelper.getLogHelper(LogDomain.KG, TAG);
const INVALID_ID: number = -1;
/**
* 倒计时接口定义
*/
export interface CountDownTimerListener {
/**
* 在倒计时期间触发的回调
*
* @param millisUntilFinished 锁屏倒计时完成剩余时间
*/
onTick: (millisUntilFinished: number) => void;
/**
* 锁屏倒计时结束触发的回调
*/
onFinish: () => void;
}
/**
* 锁屏倒计时器
*/
export default class CountDownTimer extends AbstractObserverManager<CountDownTimerListener> {
private intervalId: number = INVALID_ID;
// 获取被锁定之后的解锁时间
private stopTimeInFuture: number = 0;
private _millisLeft: number = 0;
public get millisLeft(): number {
return this._millisLeft;
}
/**
* 开始倒计时
*
* @param millisInFuture 需要倒计时的时间
* @returns time 被锁定之后的解锁时间
*/
public start(millisInFuture: number): number {
try {
// 获取自系统启动以来经过的时间
let realActiveTime = systemDateTime.getUptime(systemDateTime.TimeType.STARTUP, false);
// 获取被锁定之后的解锁时间
this.stopTimeInFuture = realActiveTime + millisInFuture;
if (this.intervalId !== -1) {
this._millisLeft = millisInFuture;
log.showInfo('intervalId failed, msg is null');
this.stop();
}
// 立即显示错误消息
this.broadcastDataChange((observer) => observer?.onTick?.(millisInFuture));
log.showInfo('countdown start');
this.intervalId = setInterval(() => {
let millisLeft = this.stopTimeInFuture - systemDateTime.getUptime(systemDateTime.TimeType.STARTUP, false);
this._millisLeft = Math.max(0, millisLeft);
if (millisLeft <= 0) {
this.stop();
} else {
this.broadcastDataChange((observer) => observer?.onTick?.(millisLeft));
}
}, 1000);
} catch (error) {
log.showError('start error');
}
return this.stopTimeInFuture;
}
/**
* 取消倒计时.
*/
public stop(): void {
if (this.intervalId !== -1) {
clearInterval(this.intervalId);
this.intervalId = INVALID_ID;
log.showInfo('countdown stop');
this.broadcastDataChange((observer) => observer?.onFinish?.());
}
}
/**
* 格式化时间
*
* @param freezingMillisecond
* @returns
*/
public static formatTime(freezingMillisecond: number): string {
let minute = Math.floor(freezingMillisecond / (60 * 1000));
let second = Math.round((freezingMillisecond % (60 * 1000)) / 1000);
let time = '';
if (minute !== 0) {
let strTipMinute: string = ResUtils.getInnerPluralByResource($r('app.plural.psd_incorrect_will_locked2'), minute);
time += strTipMinute + ' ';
}
if (second !== 0) {
let strTipSecond: string = ResUtils.getInnerPluralByResource($r('app.plural.psd_incorrect_will_locked3'), second);
time += strTipSecond;
}
return time;
}
}