display library disk usage (#976)

This commit is contained in:
an-lee
2024-08-15 17:18:12 +08:00
committed by GitHub
parent 7da9fb8095
commit 04a4f9b296
8 changed files with 176 additions and 15 deletions

View File

@@ -723,5 +723,18 @@
"cannotFindSourceFile": "Cannot find source file",
"cleanUp": "Clean up",
"cleanUpConfirmation": "Are you sure to remove resources without source file?",
"cleanedUpSuccessfully": "Cleaned up successfully"
"cleanedUpSuccessfully": "Cleaned up successfully",
"libraryDescriptions": {
"library": "Contains all files created by Enjoy while you are using the app.",
"database": "Records all your activities and settings.",
"audios": "Contains all audio files you added.",
"videos": "Contains all video files you added.",
"segments": "Contains all segments you make recording or note.",
"speeches": "Contains all speeches created by AI TTS.",
"recordings": "Contains all recordings you made.",
"whisper": "Contains all whisper models you downloaded.",
"waveforms": "Contains all waveforms decoded from audio/videos. They're for caching. It's save to delete them.",
"logs": "Contains some logs helpful for debugging.",
"cache": "Contains cached files. They will be cleaned up automatically."
}
}

View File

@@ -723,5 +723,18 @@
"cannotFindSourceFile": "无法找到源文件,可能已经被删除",
"cleanUp": "清理",
"cleanUpConfirmation": "您确定要移除所有找不到源文件的资源吗?",
"cleanedUpSuccessfully": "清理成功"
"cleanedUpSuccessfully": "清理成功",
"libraryDescriptions": {
"library": "资源库总目录,包含所有您使用 Enjoy 过程产生的文件",
"database": "数据库文件,记录您使用 Enjoy 的所有数据",
"audios": "您添加的所有音频文件",
"videos": "您添加的所有视频文件",
"segments": "音频/视频文件的段落,跟读过程中产生",
"speeches": "AI TTS 服务生成的语音文件",
"recordings": "您的所有录音文件",
"whisper": "Whisper 模型文件,用于语音转文本",
"waveforms": "波形文件,用于显示音频波形。用作缓存,可以删除",
"logs": "日志文件,帮助开发者调试问题",
"cache": "缓存文件,会自动清理。"
}
}

View File

@@ -384,6 +384,43 @@ ${log}
}
);
ipcMain.handle("app-disk-usage", () => {
const paths: { [key: string]: string } = {
library: settings.libraryPath(),
database: settings.dbPath(),
audios: path.join(settings.userDataPath(), "audios"),
videos: path.join(settings.userDataPath(), "videos"),
segments: path.join(settings.userDataPath(), "segments"),
speeches: path.join(settings.userDataPath(), "speeches"),
recordings: path.join(settings.userDataPath(), "recordings"),
whisper: path.join(settings.libraryPath(), "whisper"),
waveforms: path.join(settings.libraryPath(), "waveforms"),
logs: path.join(settings.libraryPath(), "logs"),
cache: settings.cachePath(),
};
const sizeSync = (p: string): number => {
const stat = fs.statSync(p);
if (stat.isFile()) return stat.size;
else if (stat.isDirectory())
return fs
.readdirSync(p)
.reduce((a, e) => a + sizeSync(path.join(p, e)), 0);
else return 0; // can't take size of a stream/symlink/socket/
};
return Object.keys(paths).map((key) => {
const p = paths[key];
const size = sizeSync(p);
return {
name: key,
path: p,
size,
};
});
});
// Shell
ipcMain.handle("shell-open-external", (_event, url) => {
shell.openExternal(url);

View File

@@ -47,6 +47,9 @@ contextBridge.exposeInMainWorld("__ENJOY_APP__", {
removeCmdOutputListeners: () => {
ipcRenderer.removeAllListeners("app-on-cmd-output");
},
diskUsage: () => {
return ipcRenderer.invoke("app-disk-usage");
},
version,
},
window: {

View File

@@ -1,12 +1,20 @@
import { t } from "i18next";
import {
Badge,
Button,
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
ScrollArea,
Separator,
} from "@renderer/components/ui";
import {
AppSettingsProviderContext,
} from "@renderer/context";
import { useContext } from "react";
import { AppSettingsProviderContext } from "@renderer/context";
import { useContext, useEffect, useState } from "react";
import { InfoIcon } from "lucide-react";
import { humanFileSize } from "@/utils";
export const LibrarySettings = () => {
const { libraryPath, EnjoyApp } = useContext(AppSettingsProviderContext);
@@ -25,12 +33,6 @@ export const LibrarySettings = () => {
}
};
const openLibraryPath = async () => {
if (libraryPath) {
await EnjoyApp.shell.openPath(libraryPath);
}
};
return (
<div className="flex items-start justify-between py-4">
<div className="">
@@ -40,9 +42,26 @@ export const LibrarySettings = () => {
<div className="">
<div className="flex items-center justify-end space-x-2 mb-2">
<Button variant="secondary" size="sm" onClick={openLibraryPath}>
{t("open")}
</Button>
<Dialog>
<DialogTrigger asChild>
<Button variant="secondary" size="sm">
{t("detail")}
</Button>
</DialogTrigger>
<DialogContent className="h-3/5">
<DialogHeader>
<DialogTitle>{t("usage")}</DialogTitle>
<DialogDescription className="sr-only">
Disk usage of Enjoy
</DialogDescription>
</DialogHeader>
<div className="h-full overflow-hidden">
<ScrollArea className="h-full px-4">
<DiskUsage />
</ScrollArea>
</div>
</DialogContent>
</Dialog>
<Button
variant="secondary"
size="sm"
@@ -59,3 +78,51 @@ export const LibrarySettings = () => {
</div>
);
};
const DiskUsage = () => {
const [usage, setUsage] = useState<DiskUsageType>([]);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const openPath = async (path: string) => {
if (path) {
await EnjoyApp.shell.openPath(path);
}
};
useEffect(() => {
EnjoyApp.app.diskUsage().then((usage) => {
console.log(usage);
setUsage(usage);
});
}, []);
return (
<div className="grid gap-4">
{usage.map((item) => (
<div key={item.name}>
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="flex items-center space-x-2 mb-2">
<Badge>/{item.path.split("/").pop()}</Badge>
<div className="text-sm text-muted-foreground">
{humanFileSize(item.size)}
</div>
</div>
<div className="text-sm">
{t(`libraryDescriptions.${item.name}`)}
</div>
</div>
<Button
onClick={() => openPath(item.path)}
variant="secondary"
size="sm"
>
{t("open")}
</Button>
</div>
<Separator className="my-2" />
</div>
))}
</div>
);
};

View File

@@ -13,6 +13,7 @@ type EnjoyAppType = {
createIssue: (title: string, body: string) => Promise<void>;
onCmdOutput: (callback: (event, output: string) => void) => void;
removeCmdOutputListeners: () => void;
diskUsage: () => Promise<DiskUsageType>;
version: string;
};
window: {

View File

@@ -183,3 +183,9 @@ type PlatformInfo = {
arch: string;
version: string;
};
type DiskUsageType = {
name: string;
path: string;
size: number;
}[];

View File

@@ -127,3 +127,24 @@ export const convertIpaToNormal = (
return converted;
}
};
// make size of bytes human readable
export const humanFileSize = (bytes: number, si: boolean = false) => {
const thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) {
return bytes + " B";
}
const units = si
? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
: ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
let u = -1;
const r = 10;
do {
bytes /= thresh;
++u;
} while (
Math.round(Math.abs(bytes) * r) / r >= thresh &&
u < units.length - 1
);
return bytes.toFixed(1) + " " + units[u];
};