Skip to content

Commit 707d391

Browse files
authored
✨ fileStorage API改进 #138 (#199)
* ✨ 优化文件存储API * 🐛 修复CAT storageFile API与增加baseDir示例 * ✨ CAT fileStorage打开配置页面 * 📝 CAT fileStorage API示例完善
1 parent f3493ae commit 707d391

8 files changed

Lines changed: 213 additions & 16 deletions

File tree

example/cat_file_storage.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,28 @@
66
// @author You
77
// @match https://bbs.tampermonkey.net.cn/
88
// @grant CAT_fileStorage
9+
// @run-at document-start
910
// ==/UserScript==
1011

1112
CAT_fileStorage("upload", {
1213
path: "test.txt",
14+
baseDir: "test-dir",
1315
data: new Blob(["Hello World"]),
1416
onload() {
1517
CAT_fileStorage("list", {
18+
baseDir: "test-dir",
1619
onload(list) {
1720
console.log(list);
1821
list.forEach(value => {
1922
if (value.name === "test.txt") {
2023
CAT_fileStorage("download", {
2124
file: value,
25+
baseDir: "test-dir",
2226
async onload(data) {
2327
console.log(await data.text());
2428
CAT_fileStorage("delete", {
2529
path: value.name,
30+
baseDir: "test-dir",
2631
onload() {
2732
console.log('ok');
2833
}
@@ -33,5 +38,13 @@ CAT_fileStorage("upload", {
3338
});
3439
}
3540
})
41+
}, onerror(err) {
42+
console.log(err);
43+
switch (err.code) {
44+
case 1:
45+
case 2:
46+
CAT_fileStorage("config");
47+
break;
48+
}
3649
}
3750
})
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import React, { useState } from "react";
2+
import {
3+
Button,
4+
Card,
5+
Collapse,
6+
Link,
7+
Message,
8+
Space,
9+
Typography,
10+
} from "@arco-design/web-react";
11+
import IoC from "@App/app/ioc";
12+
import { SystemConfig } from "@App/pkg/config/config";
13+
import FileSystemFactory, { FileSystemType } from "@Pkg/filesystem/factory";
14+
import FileSystemParams from "../FileSystemParams";
15+
16+
const CollapseItem = Collapse.Item;
17+
18+
const GMApiSetting: React.FC = () => {
19+
const systemConfig = IoC.instance(SystemConfig) as SystemConfig;
20+
const [status, setStatus] = useState(systemConfig.catFileStorage.status);
21+
const [fileSystemType, setFilesystemType] = useState<FileSystemType>(
22+
systemConfig.catFileStorage.filesystem
23+
);
24+
const [fileSystemParams, setFilesystemParam] = useState<{
25+
[key: string]: any;
26+
}>(systemConfig.catFileStorage.params[fileSystemType] || {});
27+
28+
return (
29+
<Card title="GM Api" bordered={false}>
30+
<Collapse bordered={false} defaultActiveKey={["storage"]}>
31+
<CollapseItem header="Storage API" name="storage">
32+
<Space direction="vertical">
33+
<FileSystemParams
34+
preNode={
35+
<Typography.Text>
36+
设置
37+
<Link
38+
target="_black"
39+
href="https://github.com/scriptscat/scriptcat/blob/main/example/cat_file_storage.js"
40+
>
41+
CAT_fileStorage
42+
</Link>
43+
使用的文件系统
44+
</Typography.Text>
45+
}
46+
actionButton={[
47+
<Button
48+
key="save"
49+
type="primary"
50+
onClick={async () => {
51+
try {
52+
await FileSystemFactory.create(
53+
fileSystemType,
54+
fileSystemParams
55+
);
56+
} catch (e) {
57+
Message.error(`账号信息验证失败: ${e}`);
58+
return;
59+
}
60+
const params = { ...systemConfig.catFileStorage.params };
61+
params[fileSystemType] = fileSystemParams;
62+
systemConfig.catFileStorage = {
63+
status: "success",
64+
filesystem: fileSystemType,
65+
params,
66+
};
67+
setStatus("success");
68+
Message.success("保存成功");
69+
}}
70+
>
71+
保存
72+
</Button>,
73+
<Button
74+
key="reset"
75+
onClick={() => {
76+
const config = systemConfig.catFileStorage;
77+
config.status = "unset";
78+
systemConfig.catFileStorage = config;
79+
setStatus("unset");
80+
}}
81+
type="primary"
82+
status="danger"
83+
>
84+
重置
85+
</Button>,
86+
<Button
87+
key="open"
88+
type="secondary"
89+
onClick={async () => {
90+
try {
91+
let fs = await FileSystemFactory.create(
92+
fileSystemType,
93+
fileSystemParams
94+
);
95+
fs = await fs.openDir("ScriptCat/app");
96+
window.open(await fs.getDirUrl(), "_black");
97+
} catch (e) {
98+
Message.error(`账号信息验证失败: ${e}`);
99+
}
100+
}}
101+
>
102+
打开目录
103+
</Button>,
104+
]}
105+
fileSystemType={fileSystemType}
106+
fileSystemParams={fileSystemParams}
107+
onChangeFileSystemType={(type) => {
108+
setFilesystemType(type);
109+
}}
110+
onChangeFileSystemParams={(params) => {
111+
setFilesystemParam(params);
112+
}}
113+
/>
114+
{status === "unset" && (
115+
<Typography.Text type="secondary">未设置</Typography.Text>
116+
)}
117+
{status === "success" && (
118+
<Typography.Text type="success">使用中</Typography.Text>
119+
)}
120+
{status === "error" && (
121+
<Typography.Text type="error">储存错误</Typography.Text>
122+
)}
123+
</Space>
124+
</CollapseItem>
125+
</Collapse>
126+
</Card>
127+
);
128+
};
129+
130+
export default GMApiSetting;

src/pages/options/routes/Logger.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function Subscribe() {
2828
const [queryLogs, setQueryLogs] = React.useState<Logger[]>([]);
2929
const [search, setSearch] = React.useState<string>("");
3030
const [startTime, setStartTime] = React.useState(
31-
dayjs().subtract(1, "hour").unix()
31+
dayjs().subtract(24, "hour").unix()
3232
);
3333
const [endTime, setEndTime] = React.useState(dayjs().unix());
3434
const loggerDAO = new LoggerDAO();

src/pages/options/routes/Setting.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { IconQuestionCircleFill } from "@arco-design/web-react/icon";
1818
import { format } from "prettier";
1919
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-import-module-exports
2020
import babel from "prettier/parser-babel";
21+
import GMApiSetting from "@App/pages/components/GMApiSetting";
2122

2223
function Setting() {
2324
const systemConfig = IoC.instance(SystemConfig) as SystemConfig;
@@ -147,6 +148,7 @@ function Setting() {
147148
</Checkbox>
148149
</Space>
149150
</Card>
151+
<GMApiSetting />
150152
<Card title="ESLint" bordered={false}>
151153
<Space direction="vertical" className="w-full">
152154
<Checkbox

src/pkg/config/config.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ export type CloudSyncConfig = {
1818
params: { [key: string]: any };
1919
};
2020

21+
export type CATFileStorage = {
22+
filesystem: FileSystemType;
23+
params: { [key: string]: any };
24+
status: "unset" | "success" | "error";
25+
};
26+
2127
@IoC.Singleton(MessageHander)
2228
export class SystemConfig {
2329
static hook = new Hook<"update">();
@@ -177,6 +183,20 @@ export class SystemConfig {
177183
this.set("cloud_sync", data);
178184
}
179185

186+
get catFileStorage(): CATFileStorage {
187+
return (
188+
this.cache.get("cat_file_storage") || {
189+
status: "unset",
190+
filesystem: "webdav",
191+
params: {},
192+
}
193+
);
194+
}
195+
196+
set catFileStorage(data: CATFileStorage | undefined) {
197+
this.set("cat_file_storage", data);
198+
}
199+
180200
get scriptCatFlag() {
181201
return <string>this.cache.get("script_cat_flag");
182202
}

src/runtime/background/gm_api.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -830,37 +830,59 @@ export default class GMApi {
830830

831831
@PermissionVerify.API({
832832
confirm: (request: Request) => {
833+
const [action, details] = request.params;
834+
if (action === "config") {
835+
return Promise.resolve(true);
836+
}
837+
const dir = details.baseDir ? details.baseDir : request.script.uuid;
833838
return Promise.resolve({
834839
permission: "file_storage",
835-
permissionValue: "*",
840+
permissionValue: dir,
836841
title: "脚本正在试图操作脚本同步储存空间",
837842
metadata: {
838843
脚本名称: request.script.name,
839844
},
840-
describe: `请您确认是否允许脚本进行此操作,允许后将允许脚本操作你的脚本同步储存空间,会在储存空间下创建一个app/${request.script.uuid}的目录供给脚本使用`,
841-
wildcard: true,
845+
describe:
846+
`请您确认是否允许脚本进行此操作,允许后将允许脚本操作你设定的储存空间,` +
847+
`脚本会在储存空间下创建一个app/${dir}的目录进行使用`,
848+
wildcard: false,
842849
permissionContent: "脚本",
843850
} as ConfirmParam);
844851
},
845852
alias: ["GM.xmlHttpRequest"],
846853
})
847854
// eslint-disable-next-line consistent-return
848855
async CAT_fileStorage(request: Request, channel: Channel) {
849-
const config = this.systemConfig.cloudSync;
850-
if (!config.enable) {
851-
return channel.throw({ code: 1, error: "is disable" });
852-
}
853856
const [action, details] = request.params;
857+
console.log(action, details);
858+
if (action === "config") {
859+
chrome.tabs.create({
860+
url: `/src/options.html#/setting`,
861+
active: true,
862+
});
863+
return Promise.resolve(true);
864+
}
865+
const fsConfig = this.systemConfig.catFileStorage;
866+
if (fsConfig.status === "unset") {
867+
return channel.throw({ code: 1, error: "file storage is disable" });
868+
}
869+
if (fsConfig.status === "error") {
870+
return channel.throw({ code: 2, error: "file storge is error" });
871+
}
854872
let fs: FileSystem;
855-
const baseDir = `ScriptCat/app/${request.script.uuid}`;
873+
const baseDir = `ScriptCat/app/${
874+
details.baseDir ? details.baseDir : request.script.uuid
875+
}`;
856876
try {
857877
fs = await FileSystemFactory.create(
858-
config.filesystem,
859-
config.params[config.filesystem]
878+
fsConfig.filesystem,
879+
fsConfig.params[fsConfig.filesystem]
860880
);
861881
await FileSystemFactory.mkdirAll(fs, baseDir);
862882
fs = await fs.openDir(baseDir);
863883
} catch (e: any) {
884+
fsConfig.status = "error";
885+
this.systemConfig.catFileStorage = fsConfig;
864886
return channel.throw({ code: 2, error: e.message });
865887
}
866888
switch (action) {

src/runtime/content/gm_api.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,10 +824,15 @@ export default class GMApi {
824824
depend: ["CAT_fetchBlob", "CAT_createBlobUrl"],
825825
})
826826
async CAT_fileStorage(
827-
action: "list" | "download" | "upload" | "delete",
827+
action: "list" | "download" | "upload" | "delete" | "config",
828828
details: any
829829
) {
830+
if (action === "config") {
831+
this.sendMessage("CAT_fileStorage", ["config"]);
832+
return;
833+
}
830834
const sendDetails: { [key: string]: string } = {
835+
baseDir: details.baseDir || "",
831836
path: details.path || "",
832837
filename: details.filename,
833838
file: details.file,

src/types/scriptcat.d.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,18 @@ declare function CAT_userConfig(): void;
192192
/**
193193
* 操控脚本同步配置的文件储存源,将会在同步目录下创建一个app/uuid目录供此 API 使用
194194
* 上传时默认覆盖同名文件, 请注意这是一个试验性质的 API, 后续可能会改变
195-
* @param action 操作类型 list 列出指定目录所有文件, upload 上传文件, download 下载文件, delete 删除文件, 暂时不提供move/mkdir等操作
195+
* @param action 操作类型 list 列出指定目录所有文件, upload 上传文件, download 下载文件, delete 删除文件, config 打开配置页, 暂时不提供move/mkdir等操作
196196
* @param details
197197
*/
198198
declare function CAT_fileStorage(
199199
action: "list",
200200
details: {
201-
// path?: string; // 暂时只允许操作根目录,所以屏蔽list的path
201+
// 文件路径
202+
path?: string;
203+
// 基础目录,如果未设置,则将脚本uuid作为目录
204+
baseDir?: string;
202205
onload?: (files: CATType.FileStorageFileInfo[]) => void;
203206
onerror?: (error: CATType.FileStorageError) => void;
204-
// public?: boolean;
205207
}
206208
): void;
207209
declare function CAT_fileStorage(
@@ -227,13 +229,16 @@ declare function CAT_fileStorage(
227229
action: "upload",
228230
details: {
229231
path: string;
232+
// 基础目录,如果未设置,则将脚本uuid作为目录
233+
baseDir?: string;
230234
data: Blob;
231235
onload?: () => void;
232236
// onprogress?: (progress: number) => void;
233237
onerror?: (error: CATType.FileStorageError) => void;
234238
// public?: boolean;
235239
}
236240
): void;
241+
declare function CAT_fileStorage(action: "config"): void;
237242

238243
declare namespace CATType {
239244
interface ProxyRule {
@@ -327,7 +332,7 @@ declare namespace GMTypes {
327332
active?: boolean;
328333
insert?: boolean;
329334
setParent?: boolean;
330-
useOpen?: boolean; // 这是一个实验性/不兼容其他管理器/不兼容Firefox的功能
335+
useOpen?: boolean; // 这是一个实验性/不兼容其他管理器/不兼容Firefox的功能
331336
}
332337

333338
interface XHRResponse {

0 commit comments

Comments
 (0)