Skip to content

Commit

Permalink
✨ fileStorage API改进 #138 (#199)
Browse files Browse the repository at this point in the history
* ✨ 优化文件存储API

* 🐛 修复CAT storageFile API与增加baseDir示例

* ✨ CAT fileStorage打开配置页面

* 📝 CAT fileStorage API示例完善
  • Loading branch information
CodFrm committed Jun 13, 2023
1 parent f3493ae commit 707d391
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 16 deletions.
13 changes: 13 additions & 0 deletions example/cat_file_storage.js
Expand Up @@ -6,23 +6,28 @@
// @author You
// @match https://bbs.tampermonkey.net.cn/
// @grant CAT_fileStorage
// @run-at document-start
// ==/UserScript==

CAT_fileStorage("upload", {
path: "test.txt",
baseDir: "test-dir",
data: new Blob(["Hello World"]),
onload() {
CAT_fileStorage("list", {
baseDir: "test-dir",
onload(list) {
console.log(list);
list.forEach(value => {
if (value.name === "test.txt") {
CAT_fileStorage("download", {
file: value,
baseDir: "test-dir",
async onload(data) {
console.log(await data.text());
CAT_fileStorage("delete", {
path: value.name,
baseDir: "test-dir",
onload() {
console.log('ok');
}
Expand All @@ -33,5 +38,13 @@ CAT_fileStorage("upload", {
});
}
})
}, onerror(err) {
console.log(err);
switch (err.code) {
case 1:
case 2:
CAT_fileStorage("config");
break;
}
}
})
130 changes: 130 additions & 0 deletions src/pages/components/GMApiSetting/index.tsx
@@ -0,0 +1,130 @@
import React, { useState } from "react";
import {
Button,
Card,
Collapse,
Link,
Message,
Space,
Typography,
} from "@arco-design/web-react";
import IoC from "@App/app/ioc";
import { SystemConfig } from "@App/pkg/config/config";
import FileSystemFactory, { FileSystemType } from "@Pkg/filesystem/factory";
import FileSystemParams from "../FileSystemParams";

const CollapseItem = Collapse.Item;

const GMApiSetting: React.FC = () => {
const systemConfig = IoC.instance(SystemConfig) as SystemConfig;
const [status, setStatus] = useState(systemConfig.catFileStorage.status);
const [fileSystemType, setFilesystemType] = useState<FileSystemType>(
systemConfig.catFileStorage.filesystem
);
const [fileSystemParams, setFilesystemParam] = useState<{
[key: string]: any;
}>(systemConfig.catFileStorage.params[fileSystemType] || {});

return (
<Card title="GM Api" bordered={false}>
<Collapse bordered={false} defaultActiveKey={["storage"]}>
<CollapseItem header="Storage API" name="storage">
<Space direction="vertical">
<FileSystemParams
preNode={
<Typography.Text>
设置
<Link
target="_black"
href="https://github.com/scriptscat/scriptcat/blob/main/example/cat_file_storage.js"
>
CAT_fileStorage
</Link>
使用的文件系统
</Typography.Text>
}
actionButton={[
<Button
key="save"
type="primary"
onClick={async () => {
try {
await FileSystemFactory.create(
fileSystemType,
fileSystemParams
);
} catch (e) {
Message.error(`账号信息验证失败: ${e}`);
return;
}
const params = { ...systemConfig.catFileStorage.params };
params[fileSystemType] = fileSystemParams;
systemConfig.catFileStorage = {
status: "success",
filesystem: fileSystemType,
params,
};
setStatus("success");
Message.success("保存成功");
}}
>
保存
</Button>,
<Button
key="reset"
onClick={() => {
const config = systemConfig.catFileStorage;
config.status = "unset";
systemConfig.catFileStorage = config;
setStatus("unset");
}}
type="primary"
status="danger"
>
重置
</Button>,
<Button
key="open"
type="secondary"
onClick={async () => {
try {
let fs = await FileSystemFactory.create(
fileSystemType,
fileSystemParams
);
fs = await fs.openDir("ScriptCat/app");
window.open(await fs.getDirUrl(), "_black");
} catch (e) {
Message.error(`账号信息验证失败: ${e}`);
}
}}
>
打开目录
</Button>,
]}
fileSystemType={fileSystemType}
fileSystemParams={fileSystemParams}
onChangeFileSystemType={(type) => {
setFilesystemType(type);
}}
onChangeFileSystemParams={(params) => {
setFilesystemParam(params);
}}
/>
{status === "unset" && (
<Typography.Text type="secondary">未设置</Typography.Text>
)}
{status === "success" && (
<Typography.Text type="success">使用中</Typography.Text>
)}
{status === "error" && (
<Typography.Text type="error">储存错误</Typography.Text>
)}
</Space>
</CollapseItem>
</Collapse>
</Card>
);
};

export default GMApiSetting;
2 changes: 1 addition & 1 deletion src/pages/options/routes/Logger.tsx
Expand Up @@ -28,7 +28,7 @@ function Subscribe() {
const [queryLogs, setQueryLogs] = React.useState<Logger[]>([]);
const [search, setSearch] = React.useState<string>("");
const [startTime, setStartTime] = React.useState(
dayjs().subtract(1, "hour").unix()
dayjs().subtract(24, "hour").unix()
);
const [endTime, setEndTime] = React.useState(dayjs().unix());
const loggerDAO = new LoggerDAO();
Expand Down
2 changes: 2 additions & 0 deletions src/pages/options/routes/Setting.tsx
Expand Up @@ -18,6 +18,7 @@ import { IconQuestionCircleFill } from "@arco-design/web-react/icon";
import { format } from "prettier";
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-import-module-exports
import babel from "prettier/parser-babel";
import GMApiSetting from "@App/pages/components/GMApiSetting";

function Setting() {
const systemConfig = IoC.instance(SystemConfig) as SystemConfig;
Expand Down Expand Up @@ -147,6 +148,7 @@ function Setting() {
</Checkbox>
</Space>
</Card>
<GMApiSetting />
<Card title="ESLint" bordered={false}>
<Space direction="vertical" className="w-full">
<Checkbox
Expand Down
20 changes: 20 additions & 0 deletions src/pkg/config/config.ts
Expand Up @@ -18,6 +18,12 @@ export type CloudSyncConfig = {
params: { [key: string]: any };
};

export type CATFileStorage = {
filesystem: FileSystemType;
params: { [key: string]: any };
status: "unset" | "success" | "error";
};

@IoC.Singleton(MessageHander)
export class SystemConfig {
static hook = new Hook<"update">();
Expand Down Expand Up @@ -177,6 +183,20 @@ export class SystemConfig {
this.set("cloud_sync", data);
}

get catFileStorage(): CATFileStorage {
return (
this.cache.get("cat_file_storage") || {
status: "unset",
filesystem: "webdav",
params: {},
}
);
}

set catFileStorage(data: CATFileStorage | undefined) {
this.set("cat_file_storage", data);
}

get scriptCatFlag() {
return <string>this.cache.get("script_cat_flag");
}
Expand Down
42 changes: 32 additions & 10 deletions src/runtime/background/gm_api.ts
Expand Up @@ -830,37 +830,59 @@ export default class GMApi {

@PermissionVerify.API({
confirm: (request: Request) => {
const [action, details] = request.params;
if (action === "config") {
return Promise.resolve(true);
}
const dir = details.baseDir ? details.baseDir : request.script.uuid;
return Promise.resolve({
permission: "file_storage",
permissionValue: "*",
permissionValue: dir,
title: "脚本正在试图操作脚本同步储存空间",
metadata: {
脚本名称: request.script.name,
},
describe: `请您确认是否允许脚本进行此操作,允许后将允许脚本操作你的脚本同步储存空间,会在储存空间下创建一个app/${request.script.uuid}的目录供给脚本使用`,
wildcard: true,
describe:
`请您确认是否允许脚本进行此操作,允许后将允许脚本操作你设定的储存空间,` +
`脚本会在储存空间下创建一个app/${dir}的目录进行使用`,
wildcard: false,
permissionContent: "脚本",
} as ConfirmParam);
},
alias: ["GM.xmlHttpRequest"],
})
// eslint-disable-next-line consistent-return
async CAT_fileStorage(request: Request, channel: Channel) {
const config = this.systemConfig.cloudSync;
if (!config.enable) {
return channel.throw({ code: 1, error: "is disable" });
}
const [action, details] = request.params;
console.log(action, details);

Check warning on line 857 in src/runtime/background/gm_api.ts

View workflow job for this annotation

GitHub Actions / Build

Unexpected console statement
if (action === "config") {
chrome.tabs.create({
url: `/src/options.html#/setting`,
active: true,
});
return Promise.resolve(true);
}
const fsConfig = this.systemConfig.catFileStorage;
if (fsConfig.status === "unset") {
return channel.throw({ code: 1, error: "file storage is disable" });
}
if (fsConfig.status === "error") {
return channel.throw({ code: 2, error: "file storge is error" });
}
let fs: FileSystem;
const baseDir = `ScriptCat/app/${request.script.uuid}`;
const baseDir = `ScriptCat/app/${
details.baseDir ? details.baseDir : request.script.uuid
}`;
try {
fs = await FileSystemFactory.create(
config.filesystem,
config.params[config.filesystem]
fsConfig.filesystem,
fsConfig.params[fsConfig.filesystem]
);
await FileSystemFactory.mkdirAll(fs, baseDir);
fs = await fs.openDir(baseDir);
} catch (e: any) {
fsConfig.status = "error";
this.systemConfig.catFileStorage = fsConfig;
return channel.throw({ code: 2, error: e.message });
}
switch (action) {
Expand Down
7 changes: 6 additions & 1 deletion src/runtime/content/gm_api.ts
Expand Up @@ -824,10 +824,15 @@ export default class GMApi {
depend: ["CAT_fetchBlob", "CAT_createBlobUrl"],
})
async CAT_fileStorage(
action: "list" | "download" | "upload" | "delete",
action: "list" | "download" | "upload" | "delete" | "config",
details: any
) {
if (action === "config") {
this.sendMessage("CAT_fileStorage", ["config"]);
return;
}
const sendDetails: { [key: string]: string } = {
baseDir: details.baseDir || "",
path: details.path || "",
filename: details.filename,
file: details.file,
Expand Down
13 changes: 9 additions & 4 deletions src/types/scriptcat.d.ts
Expand Up @@ -192,16 +192,18 @@ declare function CAT_userConfig(): void;
/**
* 操控脚本同步配置的文件储存源,将会在同步目录下创建一个app/uuid目录供此 API 使用
* 上传时默认覆盖同名文件, 请注意这是一个试验性质的 API, 后续可能会改变
* @param action 操作类型 list 列出指定目录所有文件, upload 上传文件, download 下载文件, delete 删除文件, 暂时不提供move/mkdir等操作
* @param action 操作类型 list 列出指定目录所有文件, upload 上传文件, download 下载文件, delete 删除文件, config 打开配置页, 暂时不提供move/mkdir等操作
* @param details
*/
declare function CAT_fileStorage(
action: "list",
details: {
// path?: string; // 暂时只允许操作根目录,所以屏蔽list的path
// 文件路径
path?: string;
// 基础目录,如果未设置,则将脚本uuid作为目录
baseDir?: string;
onload?: (files: CATType.FileStorageFileInfo[]) => void;
onerror?: (error: CATType.FileStorageError) => void;
// public?: boolean;
}
): void;
declare function CAT_fileStorage(
Expand All @@ -227,13 +229,16 @@ declare function CAT_fileStorage(
action: "upload",
details: {
path: string;
// 基础目录,如果未设置,则将脚本uuid作为目录
baseDir?: string;
data: Blob;
onload?: () => void;
// onprogress?: (progress: number) => void;
onerror?: (error: CATType.FileStorageError) => void;
// public?: boolean;
}
): void;
declare function CAT_fileStorage(action: "config"): void;

declare namespace CATType {
interface ProxyRule {
Expand Down Expand Up @@ -327,7 +332,7 @@ declare namespace GMTypes {
active?: boolean;
insert?: boolean;
setParent?: boolean;
useOpen?: boolean; // 这是一个实验性/不兼容其他管理器/不兼容Firefox的功能
useOpen?: boolean; // 这是一个实验性/不兼容其他管理器/不兼容Firefox的功能
}

interface XHRResponse {
Expand Down

0 comments on commit 707d391

Please sign in to comment.