|
@@ -1,8 +1,220 @@
|
|
|
import { SegmentButton, SegmentButtonItemTuple, SegmentButtonOptions } from '@kit.ArkUI';
|
|
import { SegmentButton, SegmentButtonItemTuple, SegmentButtonOptions } from '@kit.ArkUI';
|
|
|
-import { DownloadCenterManager, DownloadCenterTask } from '../common/util/DownloadCenterManager';
|
|
|
|
|
|
|
+import { DownloadCenterTask } from '../common/util/DownloadCenterManager';
|
|
|
import { CommonConstants } from '../common/constants/CommonConstants';
|
|
import { CommonConstants } from '../common/constants/CommonConstants';
|
|
|
import { StrUtil } from '@pura/harmony-utils';
|
|
import { StrUtil } from '@pura/harmony-utils';
|
|
|
-import { LazyDataSource } from '../common/util/LazyDataSource';
|
|
|
|
|
|
|
+
|
|
|
|
|
+@Component
|
|
|
|
|
+struct DownloadCenterTaskRow {
|
|
|
|
|
+ @Prop themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
|
|
|
|
|
+ @Prop task: DownloadCenterTask;
|
|
|
|
|
+ @Prop isDownloading: boolean = true;
|
|
|
|
|
+ @Prop refreshVersion: number = 0;
|
|
|
|
|
+ onPauseTask: (taskId: string) => void = (_taskId: string): void => {};
|
|
|
|
|
+ onResumeTask: (taskId: string) => void = (_taskId: string): void => {};
|
|
|
|
|
+
|
|
|
|
|
+ build() {
|
|
|
|
|
+ ListItem() {
|
|
|
|
|
+ Column({ space: 8 }) {
|
|
|
|
|
+ Row({ space: 10 }) {
|
|
|
|
|
+ Image(StrUtil.isNotEmpty(this.task.coverPath) ? this.task.coverPath : $r('app.media.alt'))
|
|
|
|
|
+ .width(54)
|
|
|
|
|
+ .height(54)
|
|
|
|
|
+ .borderRadius(9)
|
|
|
|
|
+ .sourceSize({ width: 38, height: 38 })
|
|
|
|
|
+ .alt($r('app.media.alt'))
|
|
|
|
|
+ .fillColor(this.themeColor)
|
|
|
|
|
+ .objectFit(ImageFit.Cover)
|
|
|
|
|
+
|
|
|
|
|
+ Column({ space: 4 }) {
|
|
|
|
|
+ Text(this.task.title)
|
|
|
|
|
+ .fontSize(14)
|
|
|
|
|
+ .fontWeight(FontWeight.Medium)
|
|
|
|
|
+ .fontColor($r('app.color.text_color'))
|
|
|
|
|
+ .maxLines(1)
|
|
|
|
|
+ .textOverflow({ overflow: TextOverflow.Ellipsis })
|
|
|
|
|
+
|
|
|
|
|
+ Row() {
|
|
|
|
|
+ Text(this.getTaskTotalSizeText())
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor($r('app.color.text_color'))
|
|
|
|
|
+ .opacity(0.6)
|
|
|
|
|
+ Text(' · ')
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor($r('app.color.text_color'))
|
|
|
|
|
+ .opacity(0.35)
|
|
|
|
|
+ Text(this.isDownloading ? this.getTaskStatusText() : '已完成')
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor(this.getTaskStatusColor())
|
|
|
|
|
+ .opacity(0.85)
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ }
|
|
|
|
|
+ .alignItems(HorizontalAlign.Start)
|
|
|
|
|
+ .layoutWeight(1)
|
|
|
|
|
+
|
|
|
|
|
+ if (this.isDownloading) {
|
|
|
|
|
+ this.taskActionButtonBuilder()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+
|
|
|
|
|
+ if (this.isDownloading) {
|
|
|
|
|
+ Progress({ value: this.task.progress, total: 100, type: ProgressType.Linear })
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .color(this.getTaskStatusColor())
|
|
|
|
|
+ .backgroundColor($r('app.color.track_color'))
|
|
|
|
|
+ .style({ strokeWidth: 5 })
|
|
|
|
|
+
|
|
|
|
|
+ Row() {
|
|
|
|
|
+ Text(this.getTaskProgressLabelText())
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor(this.getTaskStatusColor())
|
|
|
|
|
+ .maxLines(1)
|
|
|
|
|
+ .textOverflow({ overflow: TextOverflow.Ellipsis })
|
|
|
|
|
+ .layoutWeight(1)
|
|
|
|
|
+ Text(this.getTaskSpeedText())
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor($r('app.color.text_color'))
|
|
|
|
|
+ .opacity(0.75)
|
|
|
|
|
+ .margin({ right: 6 })
|
|
|
|
|
+ Text(this.getTaskProgressInfo())
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor($r('app.color.text_color'))
|
|
|
|
|
+ .opacity(0.6)
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Text(`${this.refreshVersion}`)
|
|
|
|
|
+ .fontSize(0.1)
|
|
|
|
|
+ .fontColor(Color.Transparent)
|
|
|
|
|
+ .opacity(0)
|
|
|
|
|
+ .width(0)
|
|
|
|
|
+ .height(0)
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .padding(12)
|
|
|
|
|
+ .backgroundColor($r('app.color.start_window_background'))
|
|
|
|
|
+ .borderRadius(10)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Builder
|
|
|
|
|
+ private taskActionButtonBuilder() {
|
|
|
|
|
+ Button(this.getTaskActionText())
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor(this.isTaskRunning() ? $r('app.color.text_color') : $r('app.color.start_window_background'))
|
|
|
|
|
+ .height(30)
|
|
|
|
|
+ .padding({ left: 14, right: 14, top: 0, bottom: 0 })
|
|
|
|
|
+ .backgroundColor(this.isTaskRunning() ? $r('app.color.bg_card') : this.themeColor)
|
|
|
|
|
+ .borderRadius(15)
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ if (this.isTaskRunning()) {
|
|
|
|
|
+ this.onPauseTask(this.task.taskId);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.onResumeTask(this.task.taskId);
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private isTaskRunning(): boolean {
|
|
|
|
|
+ return this.task.status === 'downloading';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskActionText(): string {
|
|
|
|
|
+ return this.isTaskRunning() ? '暂停' : '开始';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskTotalSizeText(): string {
|
|
|
|
|
+ if (this.task.totalBytes > 0) {
|
|
|
|
|
+ return this.formatBytes(this.task.totalBytes);
|
|
|
|
|
+ }
|
|
|
|
|
+ return StrUtil.isNotEmpty(this.task.sizeText) ? this.task.sizeText : '--';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskProgressInfo(): string {
|
|
|
|
|
+ const downloadedText: string = this.task.downloadedBytes > 0 ? this.formatBytes(this.task.downloadedBytes) : '0 B';
|
|
|
|
|
+ const totalText: string = this.getTaskTotalSizeText();
|
|
|
|
|
+ return `${downloadedText} / ${totalText}`;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskProgressLabel(): string {
|
|
|
|
|
+ const value = this.task.progress;
|
|
|
|
|
+ const rounded = Math.round(value * 10) / 10;
|
|
|
|
|
+ const isInt = Math.abs(rounded - Math.round(rounded)) < 0.001;
|
|
|
|
|
+ return isInt ? `${Math.round(rounded)}%` : `${rounded.toFixed(1)}%`;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskProgressLabelText(): string {
|
|
|
|
|
+ if (this.task.status === 'failed') {
|
|
|
|
|
+ return StrUtil.isNotEmpty(this.task.errorMessage) ? this.task.errorMessage : '下载失败';
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.task.status === 'paused') {
|
|
|
|
|
+ return `已暂停 ${this.getTaskProgressLabel()}`;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.task.status === 'pending') {
|
|
|
|
|
+ return `等待中 ${this.getTaskProgressLabel()}`;
|
|
|
|
|
+ }
|
|
|
|
|
+ return this.getTaskProgressLabel();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskSpeedText(): string {
|
|
|
|
|
+ if (this.task.status === 'failed') {
|
|
|
|
|
+ return '--';
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.task.status === 'paused') {
|
|
|
|
|
+ return '已暂停';
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.task.status === 'pending') {
|
|
|
|
|
+ return '等待中';
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.task.speedBytesPerSec > 0) {
|
|
|
|
|
+ return `${this.formatBytes(this.task.speedBytesPerSec)}/s`;
|
|
|
|
|
+ }
|
|
|
|
|
+ return '0 B/s';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskStatusText(): string {
|
|
|
|
|
+ switch (this.task.status) {
|
|
|
|
|
+ case 'downloading':
|
|
|
|
|
+ return '下载中';
|
|
|
|
|
+ case 'paused':
|
|
|
|
|
+ return '已暂停';
|
|
|
|
|
+ case 'failed':
|
|
|
|
|
+ return '下载失败';
|
|
|
|
|
+ case 'pending':
|
|
|
|
|
+ return '等待中';
|
|
|
|
|
+ case 'completed':
|
|
|
|
|
+ default:
|
|
|
|
|
+ return '已完成';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private getTaskStatusColor() {
|
|
|
|
|
+ if (this.task.status === 'failed') {
|
|
|
|
|
+ return $r('app.color.btn_red');
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.task.status === 'paused' || this.task.status === 'pending') {
|
|
|
|
|
+ return $r('app.color.text_color');
|
|
|
|
|
+ }
|
|
|
|
|
+ return this.themeColor;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private formatBytes(bytes: number): string {
|
|
|
|
|
+ if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
|
|
|
+ return '';
|
|
|
|
|
+ }
|
|
|
|
|
+ const units: string[] = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
|
|
|
+ let size: number = bytes;
|
|
|
|
|
+ let index: number = 0;
|
|
|
|
|
+ while (size >= 1024 && index < units.length - 1) {
|
|
|
|
|
+ size /= 1024;
|
|
|
|
|
+ index += 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ const precision: number = index === 0 ? 0 : 2;
|
|
|
|
|
+ return `${size.toFixed(precision)} ${units[index]}`;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
@Component
|
|
@Component
|
|
|
export struct DownloadCenter {
|
|
export struct DownloadCenter {
|
|
@@ -11,29 +223,30 @@ export struct DownloadCenter {
|
|
|
@Prop appName: string = '';
|
|
@Prop appName: string = '';
|
|
|
@Prop topSafeHeight: number = 0;
|
|
@Prop topSafeHeight: number = 0;
|
|
|
@Prop bottomSafeHeight: number = 0;
|
|
@Prop bottomSafeHeight: number = 0;
|
|
|
|
|
+ @Prop @Watch('onTasksVersionChanged') tasksVersion: number = 0;
|
|
|
|
|
+ @Prop activeTasksProp: DownloadCenterTask[] = [];
|
|
|
|
|
+ @Prop completedTasksProp: DownloadCenterTask[] = [];
|
|
|
@Link selectedIndexes: number[];
|
|
@Link selectedIndexes: number[];
|
|
|
- @State activeTaskCount: number = 0;
|
|
|
|
|
- @State completedTaskCount: number = 0;
|
|
|
|
|
|
|
+ @State activeTasks: DownloadCenterTask[] = [];
|
|
|
|
|
+ @State completedTasks: DownloadCenterTask[] = [];
|
|
|
|
|
+ @State renderVersion: number = 0;
|
|
|
onClose: () => void = () => {};
|
|
onClose: () => void = () => {};
|
|
|
onPauseTask: (taskId: string) => void = (_taskId: string): void => {};
|
|
onPauseTask: (taskId: string) => void = (_taskId: string): void => {};
|
|
|
onResumeTask: (taskId: string) => void = (_taskId: string): void => {};
|
|
onResumeTask: (taskId: string) => void = (_taskId: string): void => {};
|
|
|
- private readonly downloadCenterManager: DownloadCenterManager = DownloadCenterManager.getInstance();
|
|
|
|
|
- private readonly activeTaskDataSource: LazyDataSource<DownloadCenterTask> = new LazyDataSource<DownloadCenterTask>([]);
|
|
|
|
|
- private readonly completedTaskDataSource: LazyDataSource<DownloadCenterTask> = new LazyDataSource<DownloadCenterTask>([]);
|
|
|
|
|
- private refreshTimer: number = -1;
|
|
|
|
|
- private readonly downloadCenterListener: () => void = (): void => {
|
|
|
|
|
- this.syncTasksFromManager();
|
|
|
|
|
- };
|
|
|
|
|
|
|
|
|
|
aboutToAppear(): void {
|
|
aboutToAppear(): void {
|
|
|
- this.downloadCenterManager.subscribe(this.downloadCenterListener);
|
|
|
|
|
- this.syncTasksFromManager();
|
|
|
|
|
- this.startAutoRefresh();
|
|
|
|
|
|
|
+ this.syncTasksFromProps();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
aboutToDisappear(): void {
|
|
aboutToDisappear(): void {
|
|
|
- this.downloadCenterManager.unsubscribe(this.downloadCenterListener);
|
|
|
|
|
- this.stopAutoRefresh();
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ aboutToReuse(): void {
|
|
|
|
|
+ this.syncTasksFromProps();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private onTasksVersionChanged(): void {
|
|
|
|
|
+ this.syncTasksFromProps();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
build() {
|
|
build() {
|
|
@@ -95,58 +308,20 @@ export struct DownloadCenter {
|
|
|
.backgroundColor($r('app.color.index_background'))
|
|
.backgroundColor($r('app.color.index_background'))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private syncTasksFromManager(): void {
|
|
|
|
|
- this.updateActiveTasks(this.downloadCenterManager.getActiveTasks());
|
|
|
|
|
- this.updateCompletedTasks(this.downloadCenterManager.getCompletedTasks());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private updateActiveTasks(tasks: DownloadCenterTask[]): void {
|
|
|
|
|
- this.updateTaskDataSourceByDiff(this.activeTaskDataSource, tasks);
|
|
|
|
|
- this.activeTaskCount = this.activeTaskDataSource.totalCount();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private updateCompletedTasks(tasks: DownloadCenterTask[]): void {
|
|
|
|
|
- this.updateTaskDataSourceByDiff(this.completedTaskDataSource, tasks);
|
|
|
|
|
- this.completedTaskCount = this.completedTaskDataSource.totalCount();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private updateTaskDataSourceByDiff(dataSource: LazyDataSource<DownloadCenterTask>, tasks: DownloadCenterTask[]): void {
|
|
|
|
|
- const nextTasks: DownloadCenterTask[] = tasks ? tasks : [];
|
|
|
|
|
- const currentTasks: DownloadCenterTask[] = dataSource.dataArray;
|
|
|
|
|
-
|
|
|
|
|
- let structureChanged: boolean = currentTasks.length !== nextTasks.length;
|
|
|
|
|
- if (!structureChanged) {
|
|
|
|
|
- for (let index: number = 0; index < nextTasks.length; index += 1) {
|
|
|
|
|
- if (currentTasks[index].taskId !== nextTasks[index].taskId) {
|
|
|
|
|
- structureChanged = true;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (structureChanged) {
|
|
|
|
|
- const replacedTasks: DownloadCenterTask[] = nextTasks.map((task: DownloadCenterTask): DownloadCenterTask => {
|
|
|
|
|
- return this.cloneTask(task);
|
|
|
|
|
- });
|
|
|
|
|
- dataSource.pushArrayData(replacedTasks);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- for (let index: number = 0; index < nextTasks.length; index += 1) {
|
|
|
|
|
- const currentTask: DownloadCenterTask = currentTasks[index];
|
|
|
|
|
- const nextTask: DownloadCenterTask = nextTasks[index];
|
|
|
|
|
- if (this.isTaskEqual(currentTask, nextTask)) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- dataSource.dataArray[index] = this.cloneTask(nextTask);
|
|
|
|
|
- dataSource.notifyDataChange(index);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ private syncTasksFromProps(): void {
|
|
|
|
|
+ this.activeTasks = this.activeTasksProp.map((task: DownloadCenterTask): DownloadCenterTask => {
|
|
|
|
|
+ return this.cloneTask(task);
|
|
|
|
|
+ });
|
|
|
|
|
+ this.completedTasks = this.completedTasksProp.map((task: DownloadCenterTask): DownloadCenterTask => {
|
|
|
|
|
+ return this.cloneTask(task);
|
|
|
|
|
+ });
|
|
|
|
|
+ this.renderVersion = this.tasksVersion;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Builder
|
|
@Builder
|
|
|
private taskListBuilder() {
|
|
private taskListBuilder() {
|
|
|
if (this.getCurrentTabIndex() === 0) {
|
|
if (this.getCurrentTabIndex() === 0) {
|
|
|
- if (this.activeTaskCount <= 0) {
|
|
|
|
|
|
|
+ if (this.activeTasks.length <= 0) {
|
|
|
Column() {
|
|
Column() {
|
|
|
Text('暂无下载任务')
|
|
Text('暂无下载任务')
|
|
|
.fontSize(14)
|
|
.fontSize(14)
|
|
@@ -158,10 +333,17 @@ export struct DownloadCenter {
|
|
|
.justifyContent(FlexAlign.Center)
|
|
.justifyContent(FlexAlign.Center)
|
|
|
} else {
|
|
} else {
|
|
|
List({ space: 10 }) {
|
|
List({ space: 10 }) {
|
|
|
- LazyForEach(this.activeTaskDataSource, (task: DownloadCenterTask) => {
|
|
|
|
|
- this.taskListItemBuilder(task, true)
|
|
|
|
|
|
|
+ ForEach(this.activeTasks, (task: DownloadCenterTask) => {
|
|
|
|
|
+ DownloadCenterTaskRow({
|
|
|
|
|
+ themeColor: this.themeColor,
|
|
|
|
|
+ task: task,
|
|
|
|
|
+ isDownloading: true,
|
|
|
|
|
+ refreshVersion: this.renderVersion,
|
|
|
|
|
+ onPauseTask: this.onPauseTask,
|
|
|
|
|
+ onResumeTask: this.onResumeTask
|
|
|
|
|
+ })
|
|
|
}, (task: DownloadCenterTask): string => {
|
|
}, (task: DownloadCenterTask): string => {
|
|
|
- return task.taskId;
|
|
|
|
|
|
|
+ return this.getTaskRenderKey(task);
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
.scrollBar(BarState.Off)
|
|
.scrollBar(BarState.Off)
|
|
@@ -169,7 +351,7 @@ export struct DownloadCenter {
|
|
|
.width('100%')
|
|
.width('100%')
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- if (this.completedTaskCount <= 0) {
|
|
|
|
|
|
|
+ if (this.completedTasks.length <= 0) {
|
|
|
Column() {
|
|
Column() {
|
|
|
Text('暂无历史下载记录')
|
|
Text('暂无历史下载记录')
|
|
|
.fontSize(14)
|
|
.fontSize(14)
|
|
@@ -181,10 +363,15 @@ export struct DownloadCenter {
|
|
|
.justifyContent(FlexAlign.Center)
|
|
.justifyContent(FlexAlign.Center)
|
|
|
} else {
|
|
} else {
|
|
|
List({ space: 10 }) {
|
|
List({ space: 10 }) {
|
|
|
- LazyForEach(this.completedTaskDataSource, (task: DownloadCenterTask) => {
|
|
|
|
|
- this.taskListItemBuilder(task, false)
|
|
|
|
|
|
|
+ ForEach(this.completedTasks, (task: DownloadCenterTask) => {
|
|
|
|
|
+ DownloadCenterTaskRow({
|
|
|
|
|
+ themeColor: this.themeColor,
|
|
|
|
|
+ task: task,
|
|
|
|
|
+ isDownloading: false,
|
|
|
|
|
+ refreshVersion: this.renderVersion
|
|
|
|
|
+ })
|
|
|
}, (task: DownloadCenterTask): string => {
|
|
}, (task: DownloadCenterTask): string => {
|
|
|
- return task.taskId;
|
|
|
|
|
|
|
+ return this.getTaskRenderKey(task);
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
.scrollBar(BarState.Off)
|
|
.scrollBar(BarState.Off)
|
|
@@ -194,108 +381,6 @@ export struct DownloadCenter {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @Builder
|
|
|
|
|
- private taskListItemBuilder(task: DownloadCenterTask, isDownloading: boolean) {
|
|
|
|
|
- ListItem() {
|
|
|
|
|
- Column({ space: 8 }) {
|
|
|
|
|
- Row({ space: 10 }) {
|
|
|
|
|
- Image(StrUtil.isNotEmpty(task.coverPath) ? task.coverPath : $r('app.media.alt'))
|
|
|
|
|
- .width(54)
|
|
|
|
|
- .height(54)
|
|
|
|
|
- .borderRadius(9)
|
|
|
|
|
- .sourceSize({ width: 38, height: 38 })
|
|
|
|
|
- .alt($r('app.media.alt'))
|
|
|
|
|
- .fillColor(this.themeColor)
|
|
|
|
|
- .objectFit(ImageFit.Cover)
|
|
|
|
|
-
|
|
|
|
|
- Column({ space: 4 }) {
|
|
|
|
|
- Text(task.title)
|
|
|
|
|
- .fontSize(14)
|
|
|
|
|
- .fontWeight(FontWeight.Medium)
|
|
|
|
|
- .fontColor($r('app.color.text_color'))
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .textOverflow({ overflow: TextOverflow.Ellipsis })
|
|
|
|
|
-
|
|
|
|
|
- Row() {
|
|
|
|
|
- Text(this.getTaskTotalSizeText(task))
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor($r('app.color.text_color'))
|
|
|
|
|
- .opacity(0.6)
|
|
|
|
|
- Text(' · ')
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor($r('app.color.text_color'))
|
|
|
|
|
- .opacity(0.35)
|
|
|
|
|
- Text(isDownloading ? this.getTaskStatusText(task) : '已完成')
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor(this.getTaskStatusColor(task))
|
|
|
|
|
- .opacity(0.85)
|
|
|
|
|
- }
|
|
|
|
|
- .width('100%')
|
|
|
|
|
- }
|
|
|
|
|
- .alignItems(HorizontalAlign.Start)
|
|
|
|
|
- .layoutWeight(1)
|
|
|
|
|
-
|
|
|
|
|
- if (isDownloading) {
|
|
|
|
|
- this.taskActionButtonBuilder(task)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- .width('100%')
|
|
|
|
|
-
|
|
|
|
|
- if (isDownloading) {
|
|
|
|
|
- Progress({ value: task.progress, total: 100, type: ProgressType.Linear })
|
|
|
|
|
- .width('100%')
|
|
|
|
|
- .color(this.getTaskStatusColor(task))
|
|
|
|
|
- .backgroundColor($r('app.color.track_color'))
|
|
|
|
|
- .style({ strokeWidth: 5 })
|
|
|
|
|
-
|
|
|
|
|
- Row() {
|
|
|
|
|
- Text(this.getTaskProgressLabelText(task))
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor(this.getTaskStatusColor(task))
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .textOverflow({ overflow: TextOverflow.Ellipsis })
|
|
|
|
|
- .layoutWeight(1)
|
|
|
|
|
- Text(this.getTaskSpeedText(task))
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor($r('app.color.text_color'))
|
|
|
|
|
- .opacity(0.75)
|
|
|
|
|
- .margin({ right: 6 })
|
|
|
|
|
- Text(this.getTaskProgressInfo(task))
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor($r('app.color.text_color'))
|
|
|
|
|
- .opacity(0.6)
|
|
|
|
|
- }
|
|
|
|
|
- .width('100%')
|
|
|
|
|
- }
|
|
|
|
|
- // else {
|
|
|
|
|
- // Text(this.getTaskProgressInfo(task))
|
|
|
|
|
- // .fontSize(12)
|
|
|
|
|
- // .fontColor($r('app.color.text_color'))
|
|
|
|
|
- // .opacity(0.6)
|
|
|
|
|
- // .width('100%')
|
|
|
|
|
- // }
|
|
|
|
|
- }
|
|
|
|
|
- .width('100%')
|
|
|
|
|
- .padding(12)
|
|
|
|
|
- .backgroundColor($r('app.color.start_window_background'))
|
|
|
|
|
- .borderRadius(10)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private startAutoRefresh(): void {
|
|
|
|
|
- this.stopAutoRefresh();
|
|
|
|
|
- this.refreshTimer = setInterval(() => {
|
|
|
|
|
- this.syncTasksFromManager();
|
|
|
|
|
- }, 120);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private stopAutoRefresh(): void {
|
|
|
|
|
- if (this.refreshTimer >= 0) {
|
|
|
|
|
- clearInterval(this.refreshTimer);
|
|
|
|
|
- this.refreshTimer = -1;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private showDownloadDirectoryDialog(): void {
|
|
private showDownloadDirectoryDialog(): void {
|
|
|
this.getUIContext().showAlertDialog({
|
|
this.getUIContext().showAlertDialog({
|
|
|
title: '下载目录说明',
|
|
title: '下载目录说明',
|
|
@@ -318,16 +403,14 @@ export struct DownloadCenter {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private resolveCurrentDownloadDirectory(): string {
|
|
private resolveCurrentDownloadDirectory(): string {
|
|
|
- const activeTasks: DownloadCenterTask[] = this.activeTaskDataSource.dataArray;
|
|
|
|
|
- for (let i = 0; i < activeTasks.length; i += 1) {
|
|
|
|
|
- const task: DownloadCenterTask = activeTasks[i];
|
|
|
|
|
|
|
+ for (let i = 0; i < this.activeTasks.length; i += 1) {
|
|
|
|
|
+ const task: DownloadCenterTask = this.activeTasks[i];
|
|
|
if (StrUtil.isNotEmpty(task.downloadDir)) {
|
|
if (StrUtil.isNotEmpty(task.downloadDir)) {
|
|
|
return task.downloadDir;
|
|
return task.downloadDir;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- const completedTasks: DownloadCenterTask[] = this.completedTaskDataSource.dataArray;
|
|
|
|
|
- for (let i = 0; i < completedTasks.length; i += 1) {
|
|
|
|
|
- const task: DownloadCenterTask = completedTasks[i];
|
|
|
|
|
|
|
+ for (let i = 0; i < this.completedTasks.length; i += 1) {
|
|
|
|
|
+ const task: DownloadCenterTask = this.completedTasks[i];
|
|
|
if (StrUtil.isNotEmpty(task.downloadDir)) {
|
|
if (StrUtil.isNotEmpty(task.downloadDir)) {
|
|
|
return task.downloadDir;
|
|
return task.downloadDir;
|
|
|
}
|
|
}
|
|
@@ -335,124 +418,8 @@ export struct DownloadCenter {
|
|
|
return '';
|
|
return '';
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @Builder
|
|
|
|
|
- private taskActionButtonBuilder(task: DownloadCenterTask) {
|
|
|
|
|
- Button(this.getTaskActionText(task))
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor(this.isTaskRunning(task) ? $r('app.color.text_color') : $r('app.color.start_window_background'))
|
|
|
|
|
- .height(30)
|
|
|
|
|
- .padding({ left: 14, right: 14, top: 0, bottom: 0 })
|
|
|
|
|
- .backgroundColor(this.isTaskRunning(task) ? $r('app.color.bg_card') : this.themeColor)
|
|
|
|
|
- .borderRadius(15)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- if (this.isTaskRunning(task)) {
|
|
|
|
|
- this.onPauseTask(task.taskId);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- this.onResumeTask(task.taskId);
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private isTaskRunning(task: DownloadCenterTask): boolean {
|
|
|
|
|
- return task.status === 'downloading';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskActionText(task: DownloadCenterTask): string {
|
|
|
|
|
- return this.isTaskRunning(task) ? '暂停' : '开始';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskTotalSizeText(task: DownloadCenterTask): string {
|
|
|
|
|
- if (task.totalBytes > 0) {
|
|
|
|
|
- return this.formatBytes(task.totalBytes);
|
|
|
|
|
- }
|
|
|
|
|
- return StrUtil.isNotEmpty(task.sizeText) ? task.sizeText : '--';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskProgressInfo(task: DownloadCenterTask): string {
|
|
|
|
|
- const downloadedText: string = task.downloadedBytes > 0 ? this.formatBytes(task.downloadedBytes) : '0 B';
|
|
|
|
|
- const totalText: string = this.getTaskTotalSizeText(task);
|
|
|
|
|
- return `${downloadedText} / ${totalText}`;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskProgressLabel(task: DownloadCenterTask): string {
|
|
|
|
|
- const value = task.progress;
|
|
|
|
|
- const rounded = Math.round(value * 10) / 10;
|
|
|
|
|
- const isInt = Math.abs(rounded - Math.round(rounded)) < 0.001;
|
|
|
|
|
- return isInt ? `${Math.round(rounded)}%` : `${rounded.toFixed(1)}%`;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskProgressLabelText(task: DownloadCenterTask): string {
|
|
|
|
|
- if (task.status === 'failed') {
|
|
|
|
|
- return StrUtil.isNotEmpty(task.errorMessage) ? task.errorMessage : '下载失败';
|
|
|
|
|
- }
|
|
|
|
|
- if (task.status === 'paused') {
|
|
|
|
|
- return `已暂停 ${this.getTaskProgressLabel(task)}`;
|
|
|
|
|
- }
|
|
|
|
|
- if (task.status === 'pending') {
|
|
|
|
|
- return `等待中 ${this.getTaskProgressLabel(task)}`;
|
|
|
|
|
- }
|
|
|
|
|
- return this.getTaskProgressLabel(task);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskSpeedText(task: DownloadCenterTask): string {
|
|
|
|
|
- if (task.status === 'failed') {
|
|
|
|
|
- return '--';
|
|
|
|
|
- }
|
|
|
|
|
- if (task.status === 'paused') {
|
|
|
|
|
- return '已暂停';
|
|
|
|
|
- }
|
|
|
|
|
- if (task.status === 'pending') {
|
|
|
|
|
- return '等待中';
|
|
|
|
|
- }
|
|
|
|
|
- if (task.speedBytesPerSec > 0) {
|
|
|
|
|
- return `${this.formatBytes(task.speedBytesPerSec)}/s`;
|
|
|
|
|
- }
|
|
|
|
|
- return '0 B/s';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskStatusText(task: DownloadCenterTask): string {
|
|
|
|
|
- switch (task.status) {
|
|
|
|
|
- case 'downloading':
|
|
|
|
|
- return '下载中';
|
|
|
|
|
- case 'paused':
|
|
|
|
|
- return '已暂停';
|
|
|
|
|
- case 'failed':
|
|
|
|
|
- return '下载失败';
|
|
|
|
|
- case 'pending':
|
|
|
|
|
- return '等待中';
|
|
|
|
|
- case 'completed':
|
|
|
|
|
- default:
|
|
|
|
|
- return '已完成';
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private getTaskStatusColor(task: DownloadCenterTask) {
|
|
|
|
|
- if (task.status === 'failed') {
|
|
|
|
|
- return $r('app.color.btn_red');
|
|
|
|
|
- }
|
|
|
|
|
- if (task.status === 'paused' || task.status === 'pending') {
|
|
|
|
|
- return $r('app.color.text_color');
|
|
|
|
|
- }
|
|
|
|
|
- return this.themeColor;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private isTaskEqual(left: DownloadCenterTask, right: DownloadCenterTask): boolean {
|
|
|
|
|
- return left.taskId === right.taskId
|
|
|
|
|
- && left.title === right.title
|
|
|
|
|
- && left.fileName === right.fileName
|
|
|
|
|
- && left.coverPath === right.coverPath
|
|
|
|
|
- && left.sizeText === right.sizeText
|
|
|
|
|
- && left.sourceUrl === right.sourceUrl
|
|
|
|
|
- && left.targetPath === right.targetPath
|
|
|
|
|
- && left.downloadDir === right.downloadDir
|
|
|
|
|
- && left.totalBytes === right.totalBytes
|
|
|
|
|
- && left.downloadedBytes === right.downloadedBytes
|
|
|
|
|
- && left.progress === right.progress
|
|
|
|
|
- && left.speedBytesPerSec === right.speedBytesPerSec
|
|
|
|
|
- && left.status === right.status
|
|
|
|
|
- && left.errorMessage === right.errorMessage
|
|
|
|
|
- && left.createdAt === right.createdAt
|
|
|
|
|
- && left.finishedAt === right.finishedAt;
|
|
|
|
|
|
|
+ private getTaskRenderKey(task: DownloadCenterTask): string {
|
|
|
|
|
+ return task.taskId;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private cloneTask(task: DownloadCenterTask): DownloadCenterTask {
|
|
private cloneTask(task: DownloadCenterTask): DownloadCenterTask {
|
|
@@ -476,21 +443,6 @@ export struct DownloadCenter {
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private formatBytes(bytes: number): string {
|
|
|
|
|
- if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
|
|
|
- return '';
|
|
|
|
|
- }
|
|
|
|
|
- const units: string[] = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
|
|
|
- let size: number = bytes;
|
|
|
|
|
- let index: number = 0;
|
|
|
|
|
- while (size >= 1024 && index < units.length - 1) {
|
|
|
|
|
- size /= 1024;
|
|
|
|
|
- index += 1;
|
|
|
|
|
- }
|
|
|
|
|
- const precision: number = index === 0 ? 0 : 2;
|
|
|
|
|
- return `${size.toFixed(precision)} ${units[index]}`;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private getCurrentTabIndex(): number {
|
|
private getCurrentTabIndex(): number {
|
|
|
if (!this.selectedIndexes || this.selectedIndexes.length <= 0) {
|
|
if (!this.selectedIndexes || this.selectedIndexes.length <= 0) {
|
|
|
return 0;
|
|
return 0;
|