support clean orogress
This commit is contained in:
@@ -2,12 +2,14 @@ import { computed, ref } from "vue";
|
||||
import {
|
||||
startBrowserClean as runBrowserCleanCommand,
|
||||
startBrowserScan as runBrowserScanCommand,
|
||||
subscribeBrowserCleanProgress,
|
||||
} from "../services/tauri/cleaner";
|
||||
import type {
|
||||
AlertOptions,
|
||||
BrowserScanResult,
|
||||
CleanResult,
|
||||
ConfirmOptions,
|
||||
ProjectCleanProgressPayload,
|
||||
} from "../types/cleaner";
|
||||
import { formatItemSize } from "../utils/format";
|
||||
|
||||
@@ -19,6 +21,13 @@ interface BrowserState {
|
||||
cleanResult: CleanResult | null;
|
||||
}
|
||||
|
||||
interface BrowserCleanProgressState {
|
||||
completedItems: number;
|
||||
totalItems: number;
|
||||
currentItem: string;
|
||||
approxCompletedBytes: number;
|
||||
}
|
||||
|
||||
export function useBrowserClean(
|
||||
browser: "chrome" | "edge",
|
||||
showAlert: (options: AlertOptions) => void,
|
||||
@@ -31,20 +40,50 @@ export function useBrowserClean(
|
||||
scanResult: null,
|
||||
cleanResult: null,
|
||||
});
|
||||
const cleanProgress = ref<BrowserCleanProgressState>({
|
||||
completedItems: 0,
|
||||
totalItems: 0,
|
||||
currentItem: "",
|
||||
approxCompletedBytes: 0,
|
||||
});
|
||||
|
||||
const selectedStats = computed(() => {
|
||||
const scanResult = state.value.scanResult;
|
||||
if (!scanResult) return { sizeStr: "0 B", count: 0, hasSelection: false };
|
||||
if (!scanResult) return { totalBytes: 0, sizeStr: "0 B", count: 0, hasSelection: false };
|
||||
|
||||
const enabledProfiles = scanResult.profiles.filter((profile) => profile.enabled);
|
||||
const totalBytes = enabledProfiles.reduce((acc, profile) => acc + profile.cache_size, 0);
|
||||
|
||||
return {
|
||||
totalBytes,
|
||||
sizeStr: formatItemSize(totalBytes),
|
||||
count: enabledProfiles.length,
|
||||
hasSelection: enabledProfiles.length > 0,
|
||||
};
|
||||
});
|
||||
const cleanProgressSizeStr = computed(() => formatSizeValue(cleanProgress.value.approxCompletedBytes));
|
||||
|
||||
function formatSizeValue(bytes: number) {
|
||||
return formatItemSize(bytes);
|
||||
}
|
||||
|
||||
function resetCleanProgress() {
|
||||
cleanProgress.value = {
|
||||
completedItems: 0,
|
||||
totalItems: 0,
|
||||
currentItem: "",
|
||||
approxCompletedBytes: 0,
|
||||
};
|
||||
}
|
||||
|
||||
function handleCleanProgress(payload: ProjectCleanProgressPayload) {
|
||||
cleanProgress.value = {
|
||||
completedItems: payload.completed_items,
|
||||
totalItems: payload.total_items,
|
||||
currentItem: payload.current_item,
|
||||
approxCompletedBytes: payload.approx_completed_bytes,
|
||||
};
|
||||
}
|
||||
|
||||
async function startScan() {
|
||||
const current = state.value;
|
||||
@@ -102,7 +141,9 @@ export function useBrowserClean(
|
||||
return;
|
||||
}
|
||||
|
||||
resetCleanProgress();
|
||||
current.isCleaning = true;
|
||||
const unlisten = await subscribeBrowserCleanProgress(handleCleanProgress);
|
||||
try {
|
||||
current.cleanResult = await runBrowserCleanCommand(browser, selectedProfiles);
|
||||
current.isDone = true;
|
||||
@@ -114,6 +155,7 @@ export function useBrowserClean(
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
unlisten();
|
||||
current.isCleaning = false;
|
||||
}
|
||||
}
|
||||
@@ -138,11 +180,14 @@ export function useBrowserClean(
|
||||
scanResult: null,
|
||||
cleanResult: null,
|
||||
};
|
||||
resetCleanProgress();
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
selectedStats,
|
||||
cleanProgress,
|
||||
cleanProgressSizeStr,
|
||||
startScan,
|
||||
startClean,
|
||||
toggleAllProfiles,
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { startFastClean as runFastCleanCommand, startFastScan as runFastScanCommand } from "../services/tauri/cleaner";
|
||||
import {
|
||||
startFastClean as runFastCleanCommand,
|
||||
startFastScan as runFastScanCommand,
|
||||
subscribeFastCleanProgress,
|
||||
} from "../services/tauri/cleaner";
|
||||
import type {
|
||||
AlertOptions,
|
||||
CleanResult,
|
||||
ConfirmOptions,
|
||||
FastScanResult,
|
||||
ProjectCleanProgressPayload,
|
||||
} from "../types/cleaner";
|
||||
import { formatItemSize } from "../utils/format";
|
||||
|
||||
@@ -17,6 +22,13 @@ interface FastState {
|
||||
cleanResult: CleanResult | null;
|
||||
}
|
||||
|
||||
interface FastCleanProgressState {
|
||||
completedItems: number;
|
||||
totalItems: number;
|
||||
currentItem: string;
|
||||
approxCompletedBytes: number;
|
||||
}
|
||||
|
||||
export function useFastClean(
|
||||
showAlert: (options: AlertOptions) => void,
|
||||
requestConfirm: (options: ConfirmOptions) => Promise<boolean>,
|
||||
@@ -29,21 +41,47 @@ export function useFastClean(
|
||||
scanResult: null,
|
||||
cleanResult: null,
|
||||
});
|
||||
const cleanProgress = ref<FastCleanProgressState>({
|
||||
completedItems: 0,
|
||||
totalItems: 0,
|
||||
currentItem: "",
|
||||
approxCompletedBytes: 0,
|
||||
});
|
||||
|
||||
const selectedStats = computed(() => {
|
||||
const scanResult = state.value.scanResult;
|
||||
if (!scanResult) return { sizeStr: "0 B", count: 0, hasSelection: false };
|
||||
if (!scanResult) return { totalBytes: 0, sizeStr: "0 B", count: 0, hasSelection: false };
|
||||
|
||||
const enabledItems = scanResult.items.filter((item) => item.enabled);
|
||||
const totalBytes = enabledItems.reduce((acc, item) => acc + item.size, 0);
|
||||
const totalCount = enabledItems.reduce((acc, item) => acc + item.count, 0);
|
||||
|
||||
return {
|
||||
totalBytes,
|
||||
sizeStr: formatItemSize(totalBytes),
|
||||
count: totalCount,
|
||||
hasSelection: enabledItems.length > 0,
|
||||
};
|
||||
});
|
||||
const cleanProgressSizeStr = computed(() => formatItemSize(cleanProgress.value.approxCompletedBytes));
|
||||
|
||||
function resetCleanProgress() {
|
||||
cleanProgress.value = {
|
||||
completedItems: 0,
|
||||
totalItems: 0,
|
||||
currentItem: "",
|
||||
approxCompletedBytes: 0,
|
||||
};
|
||||
}
|
||||
|
||||
function handleCleanProgress(payload: ProjectCleanProgressPayload) {
|
||||
cleanProgress.value = {
|
||||
completedItems: payload.completed_items,
|
||||
totalItems: payload.total_items,
|
||||
currentItem: payload.current_item,
|
||||
approxCompletedBytes: payload.approx_completed_bytes,
|
||||
};
|
||||
}
|
||||
|
||||
async function startScan() {
|
||||
const current = state.value;
|
||||
@@ -104,7 +142,9 @@ export function useFastClean(
|
||||
}
|
||||
}
|
||||
|
||||
resetCleanProgress();
|
||||
current.isCleaning = true;
|
||||
const unlisten = await subscribeFastCleanProgress(handleCleanProgress);
|
||||
try {
|
||||
current.cleanResult = await runFastCleanCommand(selectedPaths);
|
||||
current.isDone = true;
|
||||
@@ -116,6 +156,7 @@ export function useFastClean(
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
unlisten();
|
||||
current.isCleaning = false;
|
||||
}
|
||||
}
|
||||
@@ -129,11 +170,14 @@ export function useFastClean(
|
||||
scanResult: null,
|
||||
cleanResult: null,
|
||||
};
|
||||
resetCleanProgress();
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
selectedStats,
|
||||
cleanProgress,
|
||||
cleanProgressSizeStr,
|
||||
startScan,
|
||||
startClean,
|
||||
reset,
|
||||
|
||||
@@ -9,7 +9,7 @@ const props = defineProps<{
|
||||
requestConfirm: (options: ConfirmOptions) => Promise<boolean>;
|
||||
}>();
|
||||
|
||||
const { state, selectedStats, startScan, startClean, toggleAllProfiles, invertProfiles, reset } =
|
||||
const { state, selectedStats, cleanProgress, cleanProgressSizeStr, startScan, startClean, toggleAllProfiles, invertProfiles, reset } =
|
||||
useBrowserClean(props.browser, props.showAlert, props.requestConfirm);
|
||||
|
||||
const browserName = props.browser === "chrome" ? "谷歌浏览器" : "微软浏览器";
|
||||
@@ -36,23 +36,26 @@ const browserName = props.browser === "chrome" ? "谷歌浏览器" : "微软浏
|
||||
|
||||
<div v-else-if="state.scanResult && !state.isDone" class="result-card">
|
||||
<div class="result-header">
|
||||
<span class="result-icon">🌍</span>
|
||||
<h2>扫描完成</h2>
|
||||
<span class="result-icon">{{ state.isCleaning ? "🧹" : "🌍" }}</span>
|
||||
<h2>{{ state.isCleaning ? "正在清理" : "扫描完成" }}</h2>
|
||||
</div>
|
||||
<div class="result-stats">
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">
|
||||
{{ splitSize(selectedStats.sizeStr).value }}
|
||||
<span class="unit">{{ splitSize(selectedStats.sizeStr).unit }}</span>
|
||||
{{ splitSize(state.isCleaning ? cleanProgressSizeStr : selectedStats.sizeStr).value }}
|
||||
<span class="unit">{{ splitSize(state.isCleaning ? cleanProgressSizeStr : selectedStats.sizeStr).unit }}</span>
|
||||
</span>
|
||||
<span class="stat-label">预计释放</span>
|
||||
<span class="stat-label">{{ state.isCleaning ? "已处理约" : "预计释放" }}</span>
|
||||
</div>
|
||||
<div class="stat-divider"></div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">{{ selectedStats.count }}</span>
|
||||
<span class="stat-label">用户资料数量</span>
|
||||
<span class="stat-value">{{ state.isCleaning ? `${cleanProgress.completedItems}/${cleanProgress.totalItems}` : selectedStats.count }}</span>
|
||||
<span class="stat-label">{{ state.isCleaning ? "已完成资料" : "用户资料数量" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="state.isCleaning" class="cleaning-note">
|
||||
正在清理:{{ cleanProgress.currentItem || "准备开始..." }},建议保持浏览器关闭以减少文件占用。
|
||||
</p>
|
||||
<button class="btn-primary main-btn" :disabled="state.isCleaning || !selectedStats.hasSelection" @click="startClean">
|
||||
{{ state.isCleaning ? "正在清理..." : "立即清理" }}
|
||||
</button>
|
||||
@@ -86,7 +89,7 @@ const browserName = props.browser === "chrome" ? "谷歌浏览器" : "微软浏
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="(state.isScanning || state.scanResult) && !state.isDone" class="detail-list">
|
||||
<div v-if="(state.isScanning || state.scanResult) && !state.isDone && !state.isCleaning" class="detail-list">
|
||||
<div class="list-header">
|
||||
<h3>用户资料列表</h3>
|
||||
<div class="list-actions">
|
||||
|
||||
@@ -8,7 +8,7 @@ const props = defineProps<{
|
||||
requestConfirm: (options: ConfirmOptions) => Promise<boolean>;
|
||||
}>();
|
||||
|
||||
const { state, selectedStats, startScan, startClean, reset } = useFastClean(
|
||||
const { state, selectedStats, cleanProgress, cleanProgressSizeStr, startScan, startClean, reset } = useFastClean(
|
||||
props.showAlert,
|
||||
props.requestConfirm,
|
||||
);
|
||||
@@ -35,24 +35,28 @@ const { state, selectedStats, startScan, startClean, reset } = useFastClean(
|
||||
|
||||
<div v-else-if="state.scanResult && !state.isDone" class="result-card">
|
||||
<div class="result-header">
|
||||
<span class="result-icon">📋</span>
|
||||
<h2>扫描完成</h2>
|
||||
<span class="result-icon">{{ state.isCleaning ? "🧹" : "📋" }}</span>
|
||||
<h2>{{ state.isCleaning ? "正在清理" : "扫描完成" }}</h2>
|
||||
</div>
|
||||
<div class="result-stats">
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">
|
||||
{{ splitSize(selectedStats.sizeStr).value }}
|
||||
<span class="unit">{{ splitSize(selectedStats.sizeStr).unit }}</span>
|
||||
{{ splitSize(state.isCleaning ? cleanProgressSizeStr : selectedStats.sizeStr).value }}
|
||||
<span class="unit">{{ splitSize(state.isCleaning ? cleanProgressSizeStr : selectedStats.sizeStr).unit }}</span>
|
||||
</span>
|
||||
<span class="stat-label">预计释放</span>
|
||||
<span class="stat-label">{{ state.isCleaning ? "已处理约" : "预计释放" }}</span>
|
||||
</div>
|
||||
<div class="stat-divider"></div>
|
||||
<div class="stat-item">
|
||||
<span class="stat-value">{{ selectedStats.count }}</span>
|
||||
<span class="stat-label">文件数量</span>
|
||||
<span class="stat-value">{{ state.isCleaning ? `${cleanProgress.completedItems}/${cleanProgress.totalItems}` : selectedStats.count }}</span>
|
||||
<span class="stat-label">{{ state.isCleaning ? "已完成项目" : "文件数量" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p v-if="state.isCleaning" class="cleaning-note">
|
||||
正在清理:{{ cleanProgress.currentItem || "准备开始..." }},请稍候,不要关闭程序。
|
||||
</p>
|
||||
|
||||
<button class="btn-primary main-btn" :disabled="state.isCleaning || !selectedStats.hasSelection" @click="startClean">
|
||||
{{ state.isCleaning ? "正在清理..." : "立即清理" }}
|
||||
</button>
|
||||
@@ -87,7 +91,7 @@ const { state, selectedStats, startScan, startClean, reset } = useFastClean(
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="(state.isScanning || state.scanResult) && !state.isDone" class="detail-list">
|
||||
<div v-if="(state.isScanning || state.scanResult) && !state.isDone && !state.isCleaning" class="detail-list">
|
||||
<h3>清理项详情</h3>
|
||||
<div
|
||||
v-for="item in state.scanResult?.items || []"
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
FastScanResult,
|
||||
FileNode,
|
||||
MemoryStats,
|
||||
ProjectCleanProgressPayload,
|
||||
ScanProgressPayload,
|
||||
} from "../../types/cleaner";
|
||||
|
||||
@@ -54,6 +55,22 @@ export function subscribeScanProgress(
|
||||
});
|
||||
}
|
||||
|
||||
export function subscribeFastCleanProgress(
|
||||
handler: (payload: ProjectCleanProgressPayload) => void,
|
||||
) {
|
||||
return listen<ProjectCleanProgressPayload>("fast-clean-progress", (event) => {
|
||||
handler(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export function subscribeBrowserCleanProgress(
|
||||
handler: (payload: ProjectCleanProgressPayload) => void,
|
||||
) {
|
||||
return listen<ProjectCleanProgressPayload>("browser-clean-progress", (event) => {
|
||||
handler(event.payload);
|
||||
});
|
||||
}
|
||||
|
||||
export function openInExplorer(path: string) {
|
||||
return invoke("open_in_explorer", { path });
|
||||
}
|
||||
|
||||
@@ -136,6 +136,13 @@
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.cleaning-note {
|
||||
margin: -8px 0 24px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: var(--text-sec);
|
||||
}
|
||||
|
||||
.scan-circle-container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
|
||||
@@ -64,6 +64,13 @@ export interface ScanProgressPayload {
|
||||
current_path: string;
|
||||
}
|
||||
|
||||
export interface ProjectCleanProgressPayload {
|
||||
completed_items: number;
|
||||
total_items: number;
|
||||
current_item: string;
|
||||
approx_completed_bytes: number;
|
||||
}
|
||||
|
||||
export type ModalType = "info" | "success" | "error";
|
||||
export type ModalMode = "alert" | "confirm";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user