diff --git a/app/command.ts b/app/command.ts
index ba3bb653..9330d4ff 100644
--- a/app/command.ts
+++ b/app/command.ts
@@ -1,3 +1,4 @@
+import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";
import Locale from "./locales";
@@ -11,21 +12,22 @@ interface Commands {
export function useCommand(commands: Commands = {}) {
const [searchParams, setSearchParams] = useSearchParams();
- if (commands === undefined) return;
+ useEffect(() => {
+ let shouldUpdate = false;
+ searchParams.forEach((param, name) => {
+ const commandName = name as keyof Commands;
+ if (typeof commands[commandName] === "function") {
+ commands[commandName]!(param);
+ searchParams.delete(name);
+ shouldUpdate = true;
+ }
+ });
- let shouldUpdate = false;
- searchParams.forEach((param, name) => {
- const commandName = name as keyof Commands;
- if (typeof commands[commandName] === "function") {
- commands[commandName]!(param);
- searchParams.delete(name);
- shouldUpdate = true;
+ if (shouldUpdate) {
+ setSearchParams(searchParams);
}
- });
-
- if (shouldUpdate) {
- setSearchParams(searchParams);
- }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [searchParams, commands]);
}
interface ChatCommands {
diff --git a/app/components/mask.tsx b/app/components/mask.tsx
index ea7cf3a5..be68c00e 100644
--- a/app/components/mask.tsx
+++ b/app/components/mask.tsx
@@ -30,7 +30,7 @@ import { useNavigate } from "react-router-dom";
import chatStyle from "./chat.module.scss";
import { useEffect, useState } from "react";
-import { downloadAs, readFromFile } from "../utils";
+import { copyToClipboard, downloadAs, readFromFile } from "../utils";
import { Updater } from "../typing";
import { ModelConfigList } from "./model-config";
import { FileName, Path } from "../constant";
@@ -65,6 +65,11 @@ export function MaskConfig(props: {
});
};
+ const copyMaskLink = () => {
+ const maskLink = `${location.protocol}//${location.host}/#${Path.NewChat}?mask=${props.mask.id}`;
+ copyToClipboard(maskLink);
+ };
+
const globalConfig = useAppConfig();
return (
@@ -125,6 +130,20 @@ export function MaskConfig(props: {
}}
>
+
+ {!props.shouldSyncFromGlobal ? (
+
+ }
+ text={Locale.Mask.Config.Share.Action}
+ onClick={copyMaskLink}
+ />
+
+ ) : null}
+
{props.shouldSyncFromGlobal ? (
{
- chatStore.newSession(mask);
- setTimeout(() => navigate(Path.Chat), 1);
+ setTimeout(() => {
+ chatStore.newSession(mask);
+ navigate(Path.Chat);
+ }, 10);
};
useCommand({
mask: (id) => {
try {
- const mask = maskStore.get(parseInt(id));
+ const intId = parseInt(id);
+ const mask = maskStore.get(intId) ?? BUILTIN_MASK_STORE.get(intId);
startChat(mask ?? undefined);
} catch {
console.error("[New Chat] failed to create chat from mask id=", id);
diff --git a/app/locales/cn.ts b/app/locales/cn.ts
index 6c8b6c0a..cb0cbbb1 100644
--- a/app/locales/cn.ts
+++ b/app/locales/cn.ts
@@ -297,6 +297,11 @@ const cn = {
Title: "隐藏预设对话",
SubTitle: "隐藏后预设对话不会出现在聊天界面",
},
+ Share: {
+ Title: "分享此面具",
+ SubTitle: "生成此面具的直达链接",
+ Action: "复制链接",
+ },
},
},
NewChat: {
diff --git a/app/locales/en.ts b/app/locales/en.ts
index ab489c25..11b8b157 100644
--- a/app/locales/en.ts
+++ b/app/locales/en.ts
@@ -301,6 +301,11 @@ const en: LocaleType = {
Title: "Hide Context Prompts",
SubTitle: "Do not show in-context prompts in chat",
},
+ Share: {
+ Title: "Share This Mask",
+ SubTitle: "Generate a link to this mask",
+ Action: "Copy Link",
+ },
},
},
NewChat: {