Skip to content

Commit 8b4fd88

Browse files
committed
Merge branch 'main' into release/v1.4
2 parents b24ed21 + 30c36b9 commit 8b4fd88

6 files changed

Lines changed: 79 additions & 12 deletions

File tree

.husky/pre-commit

100644100755
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
#!/bin/sh
22

3-
pnpm run lint-fix
3+
pnpm run lint-fix
4+
5+
# 将已暂存且被 lint-fix 修改过的文件重新加入暂存区
6+
STAGED=$(git diff --cached --name-only --diff-filter=d)
7+
CHANGED=$(git diff --name-only)
8+
9+
for file in $CHANGED; do
10+
case "$STAGED" in
11+
*"$file"*) git add "$file" ;;
12+
esac
13+
done

.husky/pre-push

100644100755
File mode changed.

example/tests/gm_xhr_test.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ==UserScript==
22
// @name GM_xmlhttpRequest Exhaustive Test Harness v3
33
// @namespace tm-gmxhr-test
4-
// @version 1.2.3
4+
// @version 1.2.4
55
// @description Comprehensive in-page tests for GM_xmlhttpRequest: normal, abnormal, and edge cases with clear pass/fail output.
66
// @author you
77
// @match *://*/*?GM_XHR_TEST_SC
@@ -878,6 +878,36 @@ const enableTool = true;
878878
assertEq(objectProps(res), "ok", "Object Props OK");
879879
},
880880
},
881+
{
882+
name: "responseType=document(parse ok)",
883+
async run(fetch) {
884+
const { res } = await gmRequest({
885+
method: "GET",
886+
url: `${HB}/base64/PHRlc3QtMTIzPmhlbGxvPC90ZXN0LTEyMz4=`,
887+
responseType: "document",
888+
fetch,
889+
});
890+
assertEq(res.status, 200);
891+
assert(res.response instanceof Document, "xml present");
892+
assert(res.responseXML !== null, "xml OK");
893+
assert(!!res.responseXML.querySelector("test-123"), "xml content ok");
894+
},
895+
},
896+
{
897+
name: "responseType=document(parser error)",
898+
async run(fetch) {
899+
const { res } = await gmRequest({
900+
method: "GET",
901+
url: `${HB}/base64/AAAAAAEAAQA=`,
902+
responseType: "document",
903+
fetch,
904+
});
905+
assertEq(res.status, 200);
906+
assert(res.response instanceof Document, "xml present");
907+
assert(res.responseXML !== null, "xml OK");
908+
assert(!!res.responseXML.querySelector("parsererror"), "xml content ok");
909+
},
910+
},
881911
{
882912
name: "overrideMimeType (force text)",
883913
async run(fetch) {

packages/filesystem/auth.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ export const netDiskTypeMap: Partial<Record<FileSystemType, NetDiskType>> = {
136136
dropbox: "dropbox",
137137
};
138138

139+
export async function HasNetDiskToken(netDiskType: NetDiskType): Promise<boolean> {
140+
const localStorageDAO = new LocalStorageDAO();
141+
const key = `netdisk:token:${netDiskType}`;
142+
try {
143+
const token = await localStorageDAO.getValue<Token>(key);
144+
return !!token?.accessToken;
145+
} catch {
146+
return false;
147+
}
148+
}
149+
139150
export async function ClearNetDiskToken(netDiskType: NetDiskType) {
140151
const localStorageDAO = new LocalStorageDAO();
141152
const key = `netdisk:token:${netDiskType}`;

src/pages/components/FileSystemParams/index.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import React from "react";
1+
import React, { useEffect, useState } from "react";
22
import { Button, Input, Message, Popconfirm, Select, Space } from "@arco-design/web-react";
33
import type { FileSystemType } from "@Packages/filesystem/factory";
44
import FileSystemFactory from "@Packages/filesystem/factory";
55
import { useTranslation } from "react-i18next";
6-
import { ClearNetDiskToken, netDiskTypeMap } from "@Packages/filesystem/auth";
6+
import { ClearNetDiskToken, HasNetDiskToken, netDiskTypeMap } from "@Packages/filesystem/auth";
77

88
const FileSystemParams: React.FC<{
99
headerContent: React.ReactNode | string;
@@ -22,6 +22,17 @@ const FileSystemParams: React.FC<{
2222
}) => {
2323
const fsParams = FileSystemFactory.params();
2424
const { t } = useTranslation();
25+
const [hasBoundToken, setHasBoundToken] = useState(false);
26+
27+
const netDiskType = netDiskTypeMap[fileSystemType];
28+
29+
useEffect(() => {
30+
if (!netDiskType) {
31+
setHasBoundToken(false);
32+
return;
33+
}
34+
HasNetDiskToken(netDiskType).then(setHasBoundToken);
35+
}, [netDiskType]);
2536

2637
const fileSystemList: {
2738
key: FileSystemType;
@@ -53,7 +64,6 @@ const FileSystemParams: React.FC<{
5364
},
5465
];
5566

56-
const netDiskType = netDiskTypeMap[fileSystemType];
5767
const netDiskName = netDiskType ? fileSystemList.find((item) => item.key === fileSystemType)?.name : null;
5868

5969
return (
@@ -74,13 +84,14 @@ const FileSystemParams: React.FC<{
7484
))}
7585
</Select>
7686
{children}
77-
{netDiskType && netDiskName && (
87+
{netDiskType && netDiskName && hasBoundToken && (
7888
<Popconfirm
7989
key="netdisk-unbind"
8090
title={t("netdisk_unbind_confirm", { provider: netDiskName })}
8191
onOk={async () => {
8292
try {
8393
await ClearNetDiskToken(netDiskType);
94+
setHasBoundToken(false);
8495
Message.success(t("netdisk_unbind_success", { provider: netDiskName })!);
8596
} catch (error) {
8697
Message.error(`${t("netdisk_unbind_error", { provider: netDiskName })}: ${String(error)}`);

src/pages/components/layout/MainLayout.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ const importByUrls = async (urls: string[]): Promise<TImportStat | undefined> =>
119119
return stat;
120120
};
121121

122+
const getSafePopupParent = (p: Element) => {
123+
p = (p.closest("button")?.parentNode as Element) || p; // 確保 ancestor 沒有 button 元素
124+
p = (p.closest("span")?.parentNode as Element) || p; // 確保 ancestor 沒有 span 元素
125+
p = (p.closest(".arco-collapse-item-content")?.parentNode as Element) || p; // 確保 ancestor 沒有 .arco-collapse-item-content 元素
126+
p = (p.closest(".arco-card")?.parentNode as Element) || p; // 確保 ancestor 沒有 .arco-card 元素
127+
p = (p.closest("aside")?.parentNode as Element) || p; // 確保 ancestor 沒有 aside 元素
128+
return p;
129+
};
130+
122131
// --- 子组件:提取拖拽遮罩以优化性能 ---
123132
const DropzoneOverlay: React.FC<{ active: boolean; text: string }> = React.memo(({ active, text }) => {
124133
if (!active) return null;
@@ -297,16 +306,12 @@ const MainLayout: React.FC<{
297306
componentConfig={{
298307
Select: {
299308
getPopupContainer: (node) => {
300-
return node;
309+
return getSafePopupParent(node as Element);
301310
},
302311
},
303312
}}
304313
getPopupContainer={(node) => {
305-
let p = node.parentNode as Element;
306-
p = (p.closest("button")?.parentNode as Element) || p; // 確保 ancestor 沒有 button 元素
307-
p = (p.closest("span")?.parentNode as Element) || p; // 確保 ancestor 沒有 span 元素
308-
p = (p.closest("aside")?.parentNode as Element) || p; // 確保 ancestor 沒有 aside 元素
309-
return p;
314+
return getSafePopupParent(node.parentNode as Element);
310315
}}
311316
>
312317
{contextHolder}

0 commit comments

Comments
 (0)