Skip to content

Commit

Permalink
Handle computing of progress in better way
Browse files Browse the repository at this point in the history
Signed-off-by: xychen <xychen@listenai.com>
  • Loading branch information
xychen committed May 20, 2024
1 parent d59b8cb commit 9688585
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 78 deletions.
65 changes: 11 additions & 54 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,15 @@
</n-descriptions>
</n-spin>

<partition-view v-model:image="image" :busy="busyForFlash" :progress="progressTable" :errors
:style="{ flex: '1 1 auto' }" />
<partition-view v-model:image="image" :busy="busyForFlash" :progress :errors :style="{ flex: '1 1 auto' }" />

<n-flex align="center">
<n-flex align="center" :style="{ width: 'auto', flex: '1 1 auto' }">
<template v-if="status == FlashStatus.CONNECTING">
<n-spin size="small" />
</template>
<template v-else-if="status == FlashStatus.FLASHING">
<n-progress type="line" :percentage="progressPct" :show-indicator="false" />
<n-progress type="line" :percentage="progress.progress * 100" :show-indicator="false" />
</template>
<template v-else-if="status == FlashStatus.SUCCESS">
<n-text :class="$style.result" type="success">
Expand Down Expand Up @@ -99,11 +98,12 @@ import { cskburn, type ICSKBurnResult } from '@/utils/cskburn';
import { cleanUpTmpFiles } from '@/utils/file';
import { busyOn } from '@/composables/busyOn';
import { FlashStatus, useFlashProgress } from './composables/progress';
import { useListen } from '@/composables/tauri/useListen';
import AutoUpdater from '@/components/sections/AutoUpdater.vue';
import PortSelector from '@/components/sections/PortSelector.vue';
import PartitionView, { type IProgress } from '@/components/sections/PartitionView.vue';
import PartitionView from '@/components/sections/PartitionView.vue';
import LogView from '@/components/sections/LogView.vue';
import SelectableText from '@/components/common/SelectableText.vue';
Expand All @@ -121,15 +121,9 @@ const flashInfo = computed(() => {
}
});
enum FlashStatus {
CONNECTING,
FLASHING,
STOPPED,
SUCCESS,
ERROR,
}
const status = ref<FlashStatus | null>(null);
const progress = useFlashProgress(image, status);
const status = ref<null | FlashStatus>(null);
const busyForInfo = ref(false);
const busyForFlash = computed(() => status.value == FlashStatus.CONNECTING || status.value == FlashStatus.FLASHING);
Expand Down Expand Up @@ -219,48 +213,11 @@ const hasError = computed(() => errors.value.some((error) => !!error));
const output = ref<string[]>([]);
const outputShown = ref(false);
const progress = ref<{ index: number, current: number } | null>(null);
watch(image, () => {
progress.value = null;
progress.current = null;
status.value = null;
});
const progressTable = computed<IProgress | null>(() => {
if (progress.value == null) {
return null;
}
const state = ((): IProgress['state'] => {
switch (status.value) {
case FlashStatus.STOPPED:
return 'stopped';
case FlashStatus.ERROR:
return 'error';
default:
return 'progress';
}
})();
return { ...progress.value, state };
});
const progressPct = computed(() => {
if (image.value == null || progress.value == null) {
return 0;
}
const total = imageSize(image.value);
const wrote = imageSize(image.value, progress.value.index);
if (image.value.format == 'bin') {
const current = image.value.partitions[progress.value.index].file.size * progress.value.current;
return (wrote + current) / total * 100;
} else if (image.value.format == 'hex') {
const current = image.value.sections[progress.value.index].size * progress.value.current;
return (wrote + current) / total * 100;
}
});
let aborter: AbortController | undefined;
async function startFlash(): Promise<void> {
Expand All @@ -277,7 +234,7 @@ async function startFlash(): Promise<void> {
aborter = new AbortController();
progress.value = null;
progress.current = null;
output.value.splice(0);
status.value = FlashStatus.CONNECTING;
Expand All @@ -302,11 +259,11 @@ async function startFlash(): Promise<void> {
flashSize.value = size;
},
onPartition(index, _total, _addr) {
progress.value = { index, current: 0 };
progress.current = { index, progress: 0 };
status.value = FlashStatus.FLASHING;
},
onProgress(index, current) {
progress.value = { index, current };
progress.current = { index, progress: current };
},
onError(_error) {
mayHaveError = true;
Expand Down Expand Up @@ -360,7 +317,7 @@ watch([progress, status], async () => {
case FlashStatus.FLASHING:
await getCurrent().setProgressBar({
status: ProgressBarStatus.Normal,
progress: Math.round(progressPct.value ?? 0),
progress: Math.round(progress.progress * 100),
});
break;
case FlashStatus.STOPPED:
Expand Down
61 changes: 37 additions & 24 deletions src/components/sections/PartitionView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,29 @@
<n-flex :class="$style.hexFile" vertical align="center" justify="center" :wrap="false"
:style="{ height: '100%' }">
<selectable-text :class="$style.name" selectable>{{ image.file.name }}</selectable-text>
<span>(<file-size :class="$style.size" :size="image.file.size" />)</span>
<n-text v-if="props.errors[0]" type="error">
{{ props.errors[0] }}
</n-text>
<n-space>
<file-size :class="$style.size" :size="image.file.size" />
<template v-if="props.errors[0]">
<span>-</span>
<n-text type="error">{{ props.errors[0] }}</n-text>
</template>
<template v-if="props.progress.status == FlashStatus.STOPPED">
<span>-</span>
<n-text type="error">已停止</n-text>
</template>
<template v-else-if="props.progress.status == FlashStatus.ERROR">
<span>-</span>
<n-text type="error">异常</n-text>
</template>
<template v-else-if="props.progress.status == FlashStatus.FLASHING">
<span>-</span>
<n-text>{{ (props.progress.progress * 100).toFixed(1) }}%</n-text>
</template>
<template v-else-if="props.progress.status == FlashStatus.SUCCESS">
<span>-</span>
<n-text type="success">已完成</n-text>
</template>
</n-space>
<n-button secondary :disabled="props.busy" :style="{ marginTop: '16px' }" @click="() => image = null">
重新选择
</n-button>
Expand Down Expand Up @@ -70,23 +89,21 @@
<span>{{ props.errors[index] }}</span>
</n-popover>
</template>
<template v-else-if="props.progress == null || props.progress.index < index">
<n-text>未开始</n-text>
<template v-else-if="props.progress.perPartition?.[index]?.status == FlashStatus.STOPPED">
<n-text type="error">已停止</n-text>
</template>
<template v-else-if="props.progress.index == index">
<template v-if="props.progress.state == 'stopped'">
<n-text type="error">已停止</n-text>
</template>
<template v-else-if="props.progress.state == 'error'">
<n-text type="error">异常</n-text>
</template>
<template v-else>
<field-progress :progress="props.progress.current" />
</template>
<template v-else-if="props.progress.perPartition?.[index]?.status == FlashStatus.ERROR">
<n-text type="error">异常</n-text>
</template>
<template v-else-if="props.progress.perPartition?.[index]?.status == FlashStatus.FLASHING">
<field-progress :progress="props.progress.perPartition[index]?.progress ?? 0" />
</template>
<template v-else-if="props.progress.index > index">
<template v-else-if="props.progress.perPartition?.[index]?.status == FlashStatus.SUCCESS">
<field-progress :progress="1" />
</template>
<template v-else>
<n-text>未开始</n-text>
</template>
</template>
<template #column-actions="{ index }">
<n-button quaternary circle size="small" :disabled="props.busy" @click="() => handlePartRemove(index)">
Expand All @@ -110,6 +127,7 @@ import {
NFlex,
NIcon,
NPopover,
NSpace,
NSpin,
NText,
useMessage,
Expand All @@ -126,6 +144,7 @@ import { UserError } from '@/userError';
import { cleanUpImage, readImage, type IFlashImage } from '@/utils/images';
import { fromHex, toHex } from '@/utils/hex';
import { busyOn } from '@/composables/busyOn';
import { FlashStatus, type IFlashProgress } from '@/composables/progress';
import FileDropper from '@/components/common/FileDropper.vue';
import FileSize from '@/components/common/FileSize.vue';
Expand All @@ -136,12 +155,6 @@ import FieldBase from '@/components/datatable/FieldBase.vue';
import FieldAddr from '@/components/datatable/FieldAddr.vue';
import FieldProgress from '@/components/datatable/FieldProgress.vue';
export interface IProgress {
index: number;
state: 'progress' | 'stopped' | 'error';
current: number;
}
export interface IPartitionState {
addr: string;
}
Expand All @@ -150,7 +163,7 @@ const image = defineModel<IFlashImage | null>('image');
const props = defineProps<{
busy: boolean;
progress: IProgress | null;
progress: IFlashProgress;
errors: (string | undefined)[];
}>();
Expand Down
61 changes: 61 additions & 0 deletions src/composables/progress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { computed, reactive, ref, type Ref } from 'vue';
import { imageSize, type IFlashImage } from '@/utils/images';

export enum FlashStatus {
CONNECTING,
FLASHING,
STOPPED,
SUCCESS,
ERROR,
}

export interface IFlashProgress {
current: { index: number, progress: number } | null;
perPartition: ({ progress: number, status: FlashStatus | null } | null)[] | null;
progress: number;
status: FlashStatus | null;
}

export function useFlashProgress(image: Ref<IFlashImage | null>, status: Ref<FlashStatus | null>): IFlashProgress {
const current = ref<IFlashProgress['current']>(null);

const perPartition = computed(() => {
if (current.value == null) {
return null;
}

if (image.value?.format != 'bin') {
return null;
}

return image.value.partitions.map((_, index) => {
if (current.value == null || current.value.index < index) {
return null;
} else if (current.value.index == index) {
return { progress: current.value.progress, status: status.value };
} else {
return { progress: 1, status: FlashStatus.SUCCESS };
}
});
});

const progress = computed(() => {
if (image.value == null || current.value == null) {
return 0;
}

const total = imageSize(image.value);
const wrote = imageSize(image.value, current.value.index);
if (image.value.format == 'bin') {
const writing = image.value.partitions[current.value.index].file.size * current.value.progress;
return (wrote + writing) / total;
} else if (image.value.format == 'hex') {
const writing = image.value.sections[current.value.index].size * current.value.progress;
return (wrote + writing) / total;
} else {
return 0;
}
});

return reactive({ current, perPartition, progress, status });
}

0 comments on commit 9688585

Please sign in to comment.