diff --git a/client/web/plugins/com.msgbyte.filepizza/manifest.json b/client/web/plugins/com.msgbyte.filepizza/manifest.json index 9b80e5ff..6bcfa81f 100644 --- a/client/web/plugins/com.msgbyte.filepizza/manifest.json +++ b/client/web/plugins/com.msgbyte.filepizza/manifest.json @@ -5,6 +5,6 @@ "icon": "/plugins/com.msgbyte.filepizza/assets/icon.png", "version": "0.0.0", "author": "moonrailgun", - "description": "快捷打开 filepizza 以支持p2p传输文件", + "description": "在聊天输入框快捷打开 filepizza 以支持p2p传输文件", "requireRestart": true } diff --git a/client/web/plugins/com.msgbyte.filepizza/package.json b/client/web/plugins/com.msgbyte.filepizza/package.json index 31de686e..45f08d59 100644 --- a/client/web/plugins/com.msgbyte.filepizza/package.json +++ b/client/web/plugins/com.msgbyte.filepizza/package.json @@ -2,7 +2,7 @@ "name": "@plugins/com.msgbyte.filepizza", "main": "src/index.tsx", "version": "0.0.0", - "description": "快捷打开filepizza以支持p2p传输文件", + "description": "在聊天输入框快捷打开filepizza以支持p2p传输文件", "private": true, "scripts": { "sync:declaration": "tailchat declaration github" diff --git a/client/web/plugins/com.msgbyte.filesend/manifest.json b/client/web/plugins/com.msgbyte.filesend/manifest.json new file mode 100644 index 00000000..e1f5723c --- /dev/null +++ b/client/web/plugins/com.msgbyte.filesend/manifest.json @@ -0,0 +1,9 @@ +{ + "label": "filesend", + "name": "com.msgbyte.filesend", + "url": "/plugins/com.msgbyte.filesend/index.js", + "version": "0.0.0", + "author": "moonrailgun", + "description": "在聊天输入框快捷打开 Filesend 以支持传输文件", + "requireRestart": true +} diff --git a/client/web/plugins/com.msgbyte.filesend/package.json b/client/web/plugins/com.msgbyte.filesend/package.json new file mode 100644 index 00000000..a7950569 --- /dev/null +++ b/client/web/plugins/com.msgbyte.filesend/package.json @@ -0,0 +1,14 @@ +{ + "name": "@plugins/com.msgbyte.filesend", + "main": "src/index.tsx", + "version": "0.0.0", + "description": "在聊天输入框快捷打开 filesend 以支持传输文件", + "private": true, + "scripts": { + "sync:declaration": "tailchat declaration github" + }, + "dependencies": {}, + "devDependencies": { + "react": "18.2.0" + } +} diff --git a/client/web/plugins/com.msgbyte.filesend/src/index.tsx b/client/web/plugins/com.msgbyte.filesend/src/index.tsx new file mode 100644 index 00000000..92de24d6 --- /dev/null +++ b/client/web/plugins/com.msgbyte.filesend/src/index.tsx @@ -0,0 +1,35 @@ +import { regChatInputAction } from '@capital/common'; + +regChatInputAction({ + label: 'FileSend', + onClick: () => { + const width = 414; + const height = 736; + const top = (window.screen.height - height) / 2; + const left = (window.screen.width - width) / 2; + + window.open( + 'https://filesend.standardnotes.com/', + 'FileSend', + buildWindowFeatures({ + top, + left, + width, + height, + menubar: false, + toolbar: false, + location: false, + status: false, + resizable: true, + }) + ); + }, +}); + +function buildWindowFeatures( + options: Record +): string { + return Object.entries(options) + .map(([key, val]) => `${key}=${val}`) + .join(','); +} diff --git a/client/web/plugins/com.msgbyte.filesend/tsconfig.json b/client/web/plugins/com.msgbyte.filesend/tsconfig.json new file mode 100644 index 00000000..d9b47ed0 --- /dev/null +++ b/client/web/plugins/com.msgbyte.filesend/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "jsx": "react", + "importsNotUsedAsValues": "error" + } +} diff --git a/client/web/plugins/com.msgbyte.filesend/types/tailchat.d.ts b/client/web/plugins/com.msgbyte.filesend/types/tailchat.d.ts new file mode 100644 index 00000000..8fbeaea4 --- /dev/null +++ b/client/web/plugins/com.msgbyte.filesend/types/tailchat.d.ts @@ -0,0 +1,326 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +/// + +/** + * 该文件由 Tailchat 自动生成 + * 用于插件的类型声明 + * 生成命令: pnpm run plugins:declaration:generate + */ + +/** + * Tailchat 通用 + */ +declare module '@capital/common' { + export const useGroupPanelParams: any; + + /** + * 打开模态框 + */ + export const openModal: ( + content: React.ReactNode, + + props?: { + /** + * 是否显示右上角的关闭按钮 + * @default false + */ + closable?: boolean; + + /** + * 遮罩层是否可关闭 + */ + maskClosable?: boolean; + + /** + * 关闭modal的回调 + */ + onCloseModal?: () => void; + } + ) => number; + + export const closeModal: any; + + export const ModalWrapper: any; + + export const useModalContext: any; + + export const openConfirmModal: any; + + export const openReconfirmModal: any; + + export const Loadable: any; + + export const getGlobalState: any; + + export const getJWTUserInfo: () => Promise<{ + _id?: string; + nickname?: string; + email?: string; + avatar?: string; + }>; + + export const dataUrlToFile: any; + + export const urlSearchStringify: any; + + export const urlSearchParse: any; + + export const appendUrlSearch: any; + + export const getServiceWorkerRegistration: any; + + export const getServiceUrl: () => string; + + export const getCachedUserInfo: ( + userId: string, + refetch?: boolean + ) => Promise<{ + _id: string; + email: string; + nickname: string; + discriminator: string; + avatar: string | null; + temporary: boolean; + }>; + + export const getCachedConverseInfo: any; + + /** + * 本地翻译 + * @example + * localTrans({'zh-CN': '你好', 'en-US': 'Hello'}); + * + * @param trans 翻译对象 + */ + export const localTrans: (trans: Record<'zh-CN' | 'en-US', string>) => string; + + export const getLanguage: any; + + export const sharedEvent: any; + + export const useAsync: any; + + export const useAsyncFn: any; + + export const useAsyncRefresh: any; + + export const useAsyncRequest: any; + + export const uploadFile: any; + + export const showToasts: any; + + export const showErrorToasts: any; + + export const fetchAvailableServices: any; + + export const isValidStr: any; + + export const useGroupPanelInfo: any; + + export const sendMessage: any; + + export const useLocation: any; + + export const useNavigate: any; + + export const createFastFormSchema: any; + + export const fieldSchema: any; + + export const useCurrentUserInfo: any; + + export const createPluginRequest: (pluginName: string) => { + get: (actionName: string, config?: any) => Promise; + post: (actionName: string, data?: any, config?: any) => Promise; + }; + + export const postRequest: any; + + export const pluginCustomPanel: any; + + export const regCustomPanel: any; + + export const pluginGroupPanel: any; + + export const regGroupPanel: any; + + export const messageInterpreter: any; + + export const regMessageInterpreter: any; + + export const getMessageRender: any; + + export const regMessageRender: any; + + export const getMessageTextDecorators: any; + + export const regMessageTextDecorators: any; + + export const ChatInputActionContextProps: any; + + export const pluginChatInputActions: any; + + export const regChatInputAction: any; + + export const regSocketEventListener: (item: { + eventName: string; + eventFn: (...args: any[]) => void; + }) => void; + + export const pluginColorScheme: any; + + export const regPluginColorScheme: any; + + export const pluginInspectServices: any; + + export const regInspectService: any; + + export const pluginMessageExtraParsers: any; + + export const regMessageExtraParser: any; + + export const pluginRootRoute: any; + + export const regPluginRootRoute: any; + + export const pluginPanelActions: any; + + export const regPluginPanelAction: any; + + export const pluginPermission: any; + + export const regPluginPermission: (permission: { + /** + * 权限唯一key, 用于写入数据库 + * 如果为插件则权限点应当符合命名规范, 如: plugin.com.msgbyte.github.manage + */ + key: string; + /** + * 权限点显示名称 + */ + title: string; + /** + * 权限描述 + */ + desc: string; + /** + * 是否默认开启 + */ + default: boolean; + /** + * 是否依赖其他权限点 + */ + required?: string[]; + }) => void; + + export const useGroupIdContext: () => string; + + export const useGroupPanelContext: () => { + groupId: string; + panelId: string; + } | null; + + export const useSocketContext: any; +} + +/** + * Tailchat 组件 + */ +declare module '@capital/component' { + export const Button: any; + + export const Checkbox: any; + + export const Input: any; + + export const Divider: any; + + export const Space: any; + + export const Menu: any; + + export const Table: any; + + export const Switch: any; + + export const Tooltip: any; + + /** + * @link https://ant.design/components/notification-cn/ + */ + export const notification: any; + + export const Empty: any; + + export const Avatar: any; + + export const SensitiveText: React.FC<{ className?: string; text: string }>; + + export const TextArea: any; + + export const Image: any; + + export const Icon: React.FC<{ icon: string } & React.SVGProps>; + + export const IconBtn: React.FC<{ + icon: string; + iconClassName?: string; + shape?: 'circle' | 'square'; + title?: string; + }>; + + export const PillTabs: any; + + export const PillTabPane: any; + + export const LoadingSpinner: any; + + export const WebFastForm: any; + + export const WebMetaForm: any; + + export const createMetaFormSchema: any; + + export const metaFormFieldSchema: any; + + export const FullModalField: any; + + export const DefaultFullModalInputEditorRender: any; + + export const DefaultFullModalTextAreaEditorRender: any; + + export const openModal: any; + + export const closeModal: any; + + export const ModalWrapper: any; + + export const useModalContext: any; + + export const openConfirmModal: any; + + export const openReconfirmModal: any; + + export const Loading: any; + + export const SidebarView: any; + + export const GroupPanelSelector: any; + + export const Emoji: any; + + export const PortalAdd: any; + + export const PortalRemove: any; + + export const ErrorBoundary: any; + + export const UserName: React.FC<{ + userId: string; + className?: string; + }>; + + export const Markdown: any; +} diff --git a/client/web/plugins/com.msgbyte.filesfm/manifest.json b/client/web/plugins/com.msgbyte.filesfm/manifest.json index 71b4a871..cfdebc7c 100644 --- a/client/web/plugins/com.msgbyte.filesfm/manifest.json +++ b/client/web/plugins/com.msgbyte.filesfm/manifest.json @@ -5,6 +5,6 @@ "icon": "/plugins/com.msgbyte.filesfm/assets/icon.png", "version": "0.0.0", "author": "moonrailgun", - "description": "快捷打开 files.fm 以支持传输文件", + "description": "在聊天输入框快捷打开 files.fm 以支持传输文件", "requireRestart": true } diff --git a/client/web/plugins/com.msgbyte.filesfm/package.json b/client/web/plugins/com.msgbyte.filesfm/package.json index d06ad8e2..e0dae915 100644 --- a/client/web/plugins/com.msgbyte.filesfm/package.json +++ b/client/web/plugins/com.msgbyte.filesfm/package.json @@ -2,7 +2,7 @@ "name": "@plugins/com.msgbyte.filesfm", "main": "src/index.tsx", "version": "0.0.0", - "description": "快捷打开 files.fm 以支持传输文件", + "description": "在聊天输入框快捷打开 files.fm 以支持传输文件", "private": true, "scripts": { "sync:declaration": "tailchat declaration github" diff --git a/client/web/plugins/com.msgbyte.wenshushu/assets/icon.png b/client/web/plugins/com.msgbyte.wenshushu/assets/icon.png new file mode 100644 index 00000000..a8e88be4 Binary files /dev/null and b/client/web/plugins/com.msgbyte.wenshushu/assets/icon.png differ diff --git a/client/web/plugins/com.msgbyte.wenshushu/manifest.json b/client/web/plugins/com.msgbyte.wenshushu/manifest.json new file mode 100644 index 00000000..a57ea4aa --- /dev/null +++ b/client/web/plugins/com.msgbyte.wenshushu/manifest.json @@ -0,0 +1,10 @@ +{ + "label": "wenshushu", + "name": "com.msgbyte.wenshushu", + "url": "/plugins/com.msgbyte.wenshushu/index.js", + "icon": "/plugins/com.msgbyte.wenshushu/assets/icon.png", + "version": "0.0.0", + "author": "moonrailgun", + "description": "在聊天输入框快捷打开 文叔叔 以支持传输文件", + "requireRestart": true +} diff --git a/client/web/plugins/com.msgbyte.wenshushu/package.json b/client/web/plugins/com.msgbyte.wenshushu/package.json new file mode 100644 index 00000000..6acd4b70 --- /dev/null +++ b/client/web/plugins/com.msgbyte.wenshushu/package.json @@ -0,0 +1,14 @@ +{ + "name": "@plugins/com.msgbyte.wenshushu", + "main": "src/index.tsx", + "version": "0.0.0", + "description": "在聊天输入框快捷打开 文叔叔 以支持传输文件", + "private": true, + "scripts": { + "sync:declaration": "tailchat declaration github" + }, + "dependencies": {}, + "devDependencies": { + "react": "18.2.0" + } +} diff --git a/client/web/plugins/com.msgbyte.wenshushu/src/index.tsx b/client/web/plugins/com.msgbyte.wenshushu/src/index.tsx new file mode 100644 index 00000000..44677cdb --- /dev/null +++ b/client/web/plugins/com.msgbyte.wenshushu/src/index.tsx @@ -0,0 +1,35 @@ +import { regChatInputAction } from '@capital/common'; + +regChatInputAction({ + label: '文叔叔', + onClick: () => { + const width = 1230; // 不支持手机UA + const height = 736; + const top = (window.screen.height - height) / 2; + const left = (window.screen.width - width) / 2; + + window.open( + 'https://www.wenshushu.cn/', + '文叔叔', + buildWindowFeatures({ + top, + left, + width, + height, + menubar: false, + toolbar: false, + location: false, + status: false, + resizable: true, + }) + ); + }, +}); + +function buildWindowFeatures( + options: Record +): string { + return Object.entries(options) + .map(([key, val]) => `${key}=${val}`) + .join(','); +} diff --git a/client/web/plugins/com.msgbyte.wenshushu/tsconfig.json b/client/web/plugins/com.msgbyte.wenshushu/tsconfig.json new file mode 100644 index 00000000..d9b47ed0 --- /dev/null +++ b/client/web/plugins/com.msgbyte.wenshushu/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "jsx": "react", + "importsNotUsedAsValues": "error" + } +} diff --git a/client/web/plugins/com.msgbyte.wenshushu/types/tailchat.d.ts b/client/web/plugins/com.msgbyte.wenshushu/types/tailchat.d.ts new file mode 100644 index 00000000..8fbeaea4 --- /dev/null +++ b/client/web/plugins/com.msgbyte.wenshushu/types/tailchat.d.ts @@ -0,0 +1,326 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +/// + +/** + * 该文件由 Tailchat 自动生成 + * 用于插件的类型声明 + * 生成命令: pnpm run plugins:declaration:generate + */ + +/** + * Tailchat 通用 + */ +declare module '@capital/common' { + export const useGroupPanelParams: any; + + /** + * 打开模态框 + */ + export const openModal: ( + content: React.ReactNode, + + props?: { + /** + * 是否显示右上角的关闭按钮 + * @default false + */ + closable?: boolean; + + /** + * 遮罩层是否可关闭 + */ + maskClosable?: boolean; + + /** + * 关闭modal的回调 + */ + onCloseModal?: () => void; + } + ) => number; + + export const closeModal: any; + + export const ModalWrapper: any; + + export const useModalContext: any; + + export const openConfirmModal: any; + + export const openReconfirmModal: any; + + export const Loadable: any; + + export const getGlobalState: any; + + export const getJWTUserInfo: () => Promise<{ + _id?: string; + nickname?: string; + email?: string; + avatar?: string; + }>; + + export const dataUrlToFile: any; + + export const urlSearchStringify: any; + + export const urlSearchParse: any; + + export const appendUrlSearch: any; + + export const getServiceWorkerRegistration: any; + + export const getServiceUrl: () => string; + + export const getCachedUserInfo: ( + userId: string, + refetch?: boolean + ) => Promise<{ + _id: string; + email: string; + nickname: string; + discriminator: string; + avatar: string | null; + temporary: boolean; + }>; + + export const getCachedConverseInfo: any; + + /** + * 本地翻译 + * @example + * localTrans({'zh-CN': '你好', 'en-US': 'Hello'}); + * + * @param trans 翻译对象 + */ + export const localTrans: (trans: Record<'zh-CN' | 'en-US', string>) => string; + + export const getLanguage: any; + + export const sharedEvent: any; + + export const useAsync: any; + + export const useAsyncFn: any; + + export const useAsyncRefresh: any; + + export const useAsyncRequest: any; + + export const uploadFile: any; + + export const showToasts: any; + + export const showErrorToasts: any; + + export const fetchAvailableServices: any; + + export const isValidStr: any; + + export const useGroupPanelInfo: any; + + export const sendMessage: any; + + export const useLocation: any; + + export const useNavigate: any; + + export const createFastFormSchema: any; + + export const fieldSchema: any; + + export const useCurrentUserInfo: any; + + export const createPluginRequest: (pluginName: string) => { + get: (actionName: string, config?: any) => Promise; + post: (actionName: string, data?: any, config?: any) => Promise; + }; + + export const postRequest: any; + + export const pluginCustomPanel: any; + + export const regCustomPanel: any; + + export const pluginGroupPanel: any; + + export const regGroupPanel: any; + + export const messageInterpreter: any; + + export const regMessageInterpreter: any; + + export const getMessageRender: any; + + export const regMessageRender: any; + + export const getMessageTextDecorators: any; + + export const regMessageTextDecorators: any; + + export const ChatInputActionContextProps: any; + + export const pluginChatInputActions: any; + + export const regChatInputAction: any; + + export const regSocketEventListener: (item: { + eventName: string; + eventFn: (...args: any[]) => void; + }) => void; + + export const pluginColorScheme: any; + + export const regPluginColorScheme: any; + + export const pluginInspectServices: any; + + export const regInspectService: any; + + export const pluginMessageExtraParsers: any; + + export const regMessageExtraParser: any; + + export const pluginRootRoute: any; + + export const regPluginRootRoute: any; + + export const pluginPanelActions: any; + + export const regPluginPanelAction: any; + + export const pluginPermission: any; + + export const regPluginPermission: (permission: { + /** + * 权限唯一key, 用于写入数据库 + * 如果为插件则权限点应当符合命名规范, 如: plugin.com.msgbyte.github.manage + */ + key: string; + /** + * 权限点显示名称 + */ + title: string; + /** + * 权限描述 + */ + desc: string; + /** + * 是否默认开启 + */ + default: boolean; + /** + * 是否依赖其他权限点 + */ + required?: string[]; + }) => void; + + export const useGroupIdContext: () => string; + + export const useGroupPanelContext: () => { + groupId: string; + panelId: string; + } | null; + + export const useSocketContext: any; +} + +/** + * Tailchat 组件 + */ +declare module '@capital/component' { + export const Button: any; + + export const Checkbox: any; + + export const Input: any; + + export const Divider: any; + + export const Space: any; + + export const Menu: any; + + export const Table: any; + + export const Switch: any; + + export const Tooltip: any; + + /** + * @link https://ant.design/components/notification-cn/ + */ + export const notification: any; + + export const Empty: any; + + export const Avatar: any; + + export const SensitiveText: React.FC<{ className?: string; text: string }>; + + export const TextArea: any; + + export const Image: any; + + export const Icon: React.FC<{ icon: string } & React.SVGProps>; + + export const IconBtn: React.FC<{ + icon: string; + iconClassName?: string; + shape?: 'circle' | 'square'; + title?: string; + }>; + + export const PillTabs: any; + + export const PillTabPane: any; + + export const LoadingSpinner: any; + + export const WebFastForm: any; + + export const WebMetaForm: any; + + export const createMetaFormSchema: any; + + export const metaFormFieldSchema: any; + + export const FullModalField: any; + + export const DefaultFullModalInputEditorRender: any; + + export const DefaultFullModalTextAreaEditorRender: any; + + export const openModal: any; + + export const closeModal: any; + + export const ModalWrapper: any; + + export const useModalContext: any; + + export const openConfirmModal: any; + + export const openReconfirmModal: any; + + export const Loading: any; + + export const SidebarView: any; + + export const GroupPanelSelector: any; + + export const Emoji: any; + + export const PortalAdd: any; + + export const PortalRemove: any; + + export const ErrorBoundary: any; + + export const UserName: React.FC<{ + userId: string; + className?: string; + }>; + + export const Markdown: any; +} diff --git a/client/web/registry.json b/client/web/registry.json index f743983a..6ee516d3 100644 --- a/client/web/registry.json +++ b/client/web/registry.json @@ -76,6 +76,25 @@ "description": "快捷打开 files.fm 以支持传输文件", "requireRestart": true }, + { + "label": "wenshushu", + "name": "com.msgbyte.wenshushu", + "url": "/plugins/com.msgbyte.wenshushu/index.js", + "icon": "/plugins/com.msgbyte.wenshushu/assets/icon.png", + "version": "0.0.0", + "author": "moonrailgun", + "description": "在聊天输入框快捷打开 文叔叔 以支持传输文件", + "requireRestart": true + }, + { + "label": "filesend", + "name": "com.msgbyte.filesend", + "url": "/plugins/com.msgbyte.filesend/index.js", + "version": "0.0.0", + "author": "moonrailgun", + "description": "在聊天输入框快捷打开 Filesend 以支持传输文件", + "requireRestart": true + }, { "label": "用户地理位置", "name": "com.msgbyte.user.location",