Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 3x 2x 2x 2x 5x 1x 1x 1x 2x | import { defineStore } from 'pinia';
import { ref } from 'vue';
type ProgressLike = {
Completed?: number;
Total?: number;
IsDecryption?: boolean;
Percentage?: number;
Title?: string;
StatusText?: string;
FileName?: string;
filename?: string;
};
type Info = ProgressLike & {
Id: string;
Closer?: ReturnType<typeof setTimeout> | null;
LastUpdated?: number;
};
export const useDownloadStore = defineStore('download', () => {
const infos = ref<Info[]>([]);
let bc: BroadcastChannel | null = null;
let _initialized = false;
function initCrossTab() {
if (_initialized) return;
_initialized = true;
bc = new BroadcastChannel('downloads');
bc.onmessage = (ev: MessageEvent<any>) => {
const msg = ev.data;
if (!msg || !msg.type) return;
if (msg.type === 'dl:start') upsert(msg.info);
else if (msg.type === 'dl:update') upsert(msg.info);
else if (msg.type === 'dl:finish') finish(msg.id);
};
}
function upsert(info: any) {
const id = String(info.Id ?? info.id);
const i = infos.value.findIndex((x) => x.Id === id);
const completed = Number(info.Completed ?? 0);
const total = Number(info.Total ?? 0);
const pct =
total > 0 ? (completed / total) * 100 : Number(info.Percentage ?? 0);
const now = Date.now();
const next: Info = {
...(infos.value[i] ?? {}),
...info,
Id: id,
Completed: completed,
Total: total,
Percentage: pct,
LastUpdated: now,
};
if (i >= 0) infos.value[i] = next;
else infos.value.push(next);
}
function finish(id: string) {
const i = infos.value.findIndex((x) => x.Id === String(id));
if (i >= 0) {
infos.value[i].LastUpdated = Date.now();
if (infos.value[i].Closer) clearTimeout(infos.value[i].Closer!);
infos.value[i].Closer = setTimeout(() => {
const idx = infos.value.findIndex((x) => x.Id === String(id));
if (idx >= 0) infos.value.splice(idx, 1);
}, 3000);
}
}
function touch(id: string) {
const i = infos.value.findIndex((x) => x.Id === String(id));
if (i >= 0) infos.value[i].LastUpdated = Date.now();
}
function requestPause(id: string) {
bc?.postMessage({ type: 'dl:pause', id });
}
function requestResume(id: string) {
bc?.postMessage({ type: 'dl:resume', id });
}
function requestCancel(id: string) {
bc?.postMessage({ type: 'dl:cancel', id });
}
return {
infos,
initCrossTab,
requestPause,
requestResume,
requestCancel,
touch,
};
});
|