diff --git a/client/desktop/src/main/inject/index.ts b/client/desktop/src/main/inject/index.ts index c5719313..7a8f8328 100644 --- a/client/desktop/src/main/inject/index.ts +++ b/client/desktop/src/main/inject/index.ts @@ -31,6 +31,18 @@ export function generateInjectedScript(): string { return [generateDeviceInfo()].join(';'); } +function getPlatform() { + if (process.platform === 'darwin') { + return 'mac'; + } else if (process.platform === 'win32') { + return 'windows'; + } else if (process.platform === 'linux') { + return 'linux'; + } else { + return process.platform; + } +} + function generateDeviceInfo() { - return `window.__electronDeviceInfo = { version: "${app.getVersion()}", name: "${app.getName()}" }`; + return `window.__electronDeviceInfo = { version: "${app.getVersion()}", name: "${app.getName()}", platform: "${getPlatform}" }`; } diff --git a/client/shared/index.tsx b/client/shared/index.tsx index 1a3a1b5a..3eedbc5f 100644 --- a/client/shared/index.tsx +++ b/client/shared/index.tsx @@ -39,6 +39,7 @@ export { // event export { sharedEvent, useSharedEventHandler } from './event/index'; +export type { SharedEventType } from './event/index'; // helper export { getDMConverseName } from './helper/converse-helper'; diff --git a/client/web/plugins/.eslintrc.js b/client/web/plugins/.eslintrc.js index 4976eb83..d8425b51 100644 --- a/client/web/plugins/.eslintrc.js +++ b/client/web/plugins/.eslintrc.js @@ -11,6 +11,10 @@ module.exports = { name: 'tailchat-shared', message: 'Only allow use `@capital/*`', }, + { + name: 'antd', + message: 'Only allow use `@capital/component`', + }, { name: 'translate', message: 'Maybe you should use `./translate`', diff --git a/client/web/plugins/com.msgbyte.env.electron/package.json b/client/web/plugins/com.msgbyte.env.electron/package.json index 7a3f6171..e66fa3a8 100644 --- a/client/web/plugins/com.msgbyte.env.electron/package.json +++ b/client/web/plugins/com.msgbyte.env.electron/package.json @@ -7,8 +7,11 @@ "scripts": { "sync:declaration": "tailchat declaration github" }, - "dependencies": {}, + "dependencies": { + "semver": "^7.5.4" + }, "devDependencies": { + "@types/semver": "^7.5.0", "@types/styled-components": "^5.1.26", "react": "18.2.0", "styled-components": "^5.3.6" diff --git a/client/web/plugins/com.msgbyte.env.electron/src/DeviceInfoPanel.tsx b/client/web/plugins/com.msgbyte.env.electron/src/DeviceInfoPanel.tsx index 0adcc0eb..3d29f0ee 100644 --- a/client/web/plugins/com.msgbyte.env.electron/src/DeviceInfoPanel.tsx +++ b/client/web/plugins/com.msgbyte.env.electron/src/DeviceInfoPanel.tsx @@ -1,14 +1,13 @@ +import { showSuccessToasts } from '@capital/common'; +import { Button } from '@capital/component'; import React from 'react'; +import { checkUpdate } from './checkUpdate'; import { Translate } from './translate'; - -interface WindowElectronDeviceInfo { - name: string; - version: string; -} +import { getDeviceInfo } from './utils'; export const DeviceInfoPanel: React.FC = React.memo(() => { - const deviceInfo: WindowElectronDeviceInfo = - (window as any).__electronDeviceInfo ?? {}; + const deviceInfo = getDeviceInfo(); + return (
@@ -17,6 +16,19 @@ export const DeviceInfoPanel: React.FC = React.memo(() => {
{Translate.clientVersion}: {deviceInfo.version}
+
+ {Translate.platform}: {deviceInfo.platform} +
+
); }); diff --git a/client/web/plugins/com.msgbyte.env.electron/src/checkUpdate.tsx b/client/web/plugins/com.msgbyte.env.electron/src/checkUpdate.tsx new file mode 100644 index 00000000..18456535 --- /dev/null +++ b/client/web/plugins/com.msgbyte.env.electron/src/checkUpdate.tsx @@ -0,0 +1,60 @@ +import { Button, notification } from '@capital/component'; +import React from 'react'; +import { Translate } from './translate'; +import { getDeviceInfo } from './utils'; + +const url = 'https://tailchat.msgbyte.com/downloads/client.json'; + +export async function checkUpdate(): Promise { + const deviceInfo = getDeviceInfo(); + const [semver, config] = await Promise.all([ + import('semver'), + fetch(url).then((res) => res.json()), + ]); + + const version = deviceInfo.version; + const platform = deviceInfo.platform; + const latestConfig = config?.[platform]; + const latestVersion = latestConfig?.version; + const latestUrl = latestConfig?.url; + + if (!latestVersion) { + console.warn('Not found latest version'); + return true; + } + if (!latestUrl) { + console.warn('Not found latest url'); + return true; + } + + if (semver.gt(latestVersion, version)) { + // 有新版本 + notification.info({ + message: Translate.newVersionTip, + description: ( +
+
{Translate.newVersionDesc}
+
+ {version} -> {latestVersion} +
+
+ ), + btn: ( + + ), + placement: 'topRight', + duration: 0, + }); + + return true; + } + + return false; +} diff --git a/client/web/plugins/com.msgbyte.env.electron/src/index.tsx b/client/web/plugins/com.msgbyte.env.electron/src/index.tsx index ce3005aa..202e5e4a 100644 --- a/client/web/plugins/com.msgbyte.env.electron/src/index.tsx +++ b/client/web/plugins/com.msgbyte.env.electron/src/index.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { DeviceInfoPanel } from './DeviceInfoPanel'; import { Translate } from './translate'; import { forwardSharedEvent } from './utils'; +import { checkUpdate } from './checkUpdate'; const PLUGIN_NAME = 'Electron Support'; @@ -37,3 +38,7 @@ regChatInputButton({ }); forwardSharedEvent('receiveUnmutedMessage'); + +setTimeout(() => { + checkUpdate(); +}, 1000); diff --git a/client/web/plugins/com.msgbyte.env.electron/src/translate.ts b/client/web/plugins/com.msgbyte.env.electron/src/translate.ts index 1f19e5e0..9325004e 100644 --- a/client/web/plugins/com.msgbyte.env.electron/src/translate.ts +++ b/client/web/plugins/com.msgbyte.env.electron/src/translate.ts @@ -13,4 +13,28 @@ export const Translate = { 'zh-CN': '客户端版本号', 'en-US': 'Client Version', }), + platform: localTrans({ + 'zh-CN': '平台', + 'en-US': 'Platform', + }), + newVersionTip: localTrans({ + 'zh-CN': '新版本提示', + 'en-US': 'New Version Upgrade Tip', + }), + newVersionDesc: localTrans({ + 'zh-CN': '发现有新的版本可以安装', + 'en-US': 'A new version was found to be installed', + }), + upgradeNow: localTrans({ + 'zh-CN': '立即更新', + 'en-US': 'Upgrade Now', + }), + checkVersion: localTrans({ + 'zh-CN': '检查更新', + 'en-US': 'Check for updates', + }), + isLatest: localTrans({ + 'zh-CN': '已经是最新版', + 'en-US': 'Already the latest version', + }), }; diff --git a/client/web/plugins/com.msgbyte.env.electron/src/utils.ts b/client/web/plugins/com.msgbyte.env.electron/src/utils.ts index 579eb0dd..ad5dd4d1 100644 --- a/client/web/plugins/com.msgbyte.env.electron/src/utils.ts +++ b/client/web/plugins/com.msgbyte.env.electron/src/utils.ts @@ -7,7 +7,7 @@ export function forwardSharedEvent( eventName: string, processPayload?: (payload: any) => Promise<{ type: string; payload: any }> ) { - sharedEvent.on(eventName, async (payload: any) => { + sharedEvent.on(eventName as any, async (payload: any) => { let type = eventName; if (processPayload) { const res = await processPayload(payload); @@ -23,3 +23,19 @@ export function forwardSharedEvent( postMessageEvent(type, payload); }); } + +interface ElectronDeviceInfo { + name: string; + version: string; + platform: string; +} +export function getDeviceInfo() { + const deviceInfo: ElectronDeviceInfo = { + name: '', + version: '0.0.0', + platform: 'windows', + ...((window as any).__electronDeviceInfo ?? {}), + }; + + return deviceInfo; +} diff --git a/client/web/plugins/com.msgbyte.env.electron/tsconfig.json b/client/web/plugins/com.msgbyte.env.electron/tsconfig.json index d9b47ed0..efb75ed0 100644 --- a/client/web/plugins/com.msgbyte.env.electron/tsconfig.json +++ b/client/web/plugins/com.msgbyte.env.electron/tsconfig.json @@ -2,6 +2,9 @@ "compilerOptions": { "esModuleInterop": true, "jsx": "react", - "importsNotUsedAsValues": "error" + "importsNotUsedAsValues": "error", + "paths": { + "@capital/*": ["../../src/plugin/*"], + } } } diff --git a/client/web/plugins/com.msgbyte.env.electron/types/tailchat.d.ts b/client/web/plugins/com.msgbyte.env.electron/types/tailchat.d.ts deleted file mode 100644 index 49f524ae..00000000 --- a/client/web/plugins/com.msgbyte.env.electron/types/tailchat.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare module '@capital/common'; -declare module '@capital/component'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71b36206..c6612b18 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1056,7 +1056,14 @@ importers: version: 18.2.0 client/web/plugins/com.msgbyte.env.electron: + dependencies: + semver: + specifier: ^7.5.4 + version: 7.5.4 devDependencies: + '@types/semver': + specifier: ^7.5.0 + version: 7.5.0 '@types/styled-components': specifier: ^5.1.26 version: 5.1.26 @@ -5439,7 +5446,7 @@ packages: react-router-config: 5.1.1(react-router@5.3.4)(react@17.0.2) react-router-dom: 5.3.4(react@17.0.2) rtl-detect: 1.0.4 - semver: 7.3.8 + semver: 7.5.4 serve-handler: 6.1.5 shelljs: 0.8.5 terser-webpack-plugin: 5.3.6(esbuild@0.15.18)(webpack@5.75.0) @@ -7380,7 +7387,7 @@ packages: resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} dependencies: '@gar/promisify': 1.1.3 - semver: 7.3.8 + semver: 7.5.4 dev: true /@npmcli/move-file@1.1.2: @@ -11528,7 +11535,7 @@ packages: loglevel: 1.8.0 mongoose: 6.1.1 reflect-metadata: 0.1.13 - semver: 7.3.8 + semver: 7.5.4 tslib: 2.5.0 dev: false @@ -12402,8 +12409,8 @@ packages: /@types/scheduler@0.16.2: resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} - /@types/semver@7.3.13: - resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} + /@types/semver@7.5.0: + resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} dev: true /@types/send@0.17.1: @@ -12666,7 +12673,7 @@ packages: ignore: 5.2.4 natural-compare-lite: 1.4.0 regexpp: 3.2.0 - semver: 7.3.8 + semver: 7.5.4 tsutils: 3.21.0(typescript@4.9.4) typescript: 4.9.4 transitivePeerDependencies: @@ -12740,7 +12747,7 @@ packages: debug: 4.3.4(supports-color@9.2.2) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.3.8 + semver: 7.5.4 tsutils: 3.21.0(typescript@4.9.4) typescript: 4.9.4 transitivePeerDependencies: @@ -12754,14 +12761,14 @@ packages: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@types/json-schema': 7.0.11 - '@types/semver': 7.3.13 + '@types/semver': 7.5.0 '@typescript-eslint/scope-manager': 5.53.0 '@typescript-eslint/types': 5.53.0 '@typescript-eslint/typescript-estree': 5.53.0(typescript@4.9.4) eslint: 8.34.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0(eslint@8.34.0) - semver: 7.3.8 + semver: 7.5.4 transitivePeerDependencies: - supports-color - typescript @@ -16307,7 +16314,7 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.21) postcss-value-parser: 4.2.0 schema-utils: 3.1.1 - semver: 7.3.8 + semver: 7.5.4 webpack: 5.75.0(esbuild@0.12.29)(webpack-cli@4.10.0) dev: true @@ -16324,7 +16331,7 @@ packages: postcss-modules-scope: 3.0.0(postcss@8.4.21) postcss-modules-values: 4.0.0(postcss@8.4.21) postcss-value-parser: 4.2.0 - semver: 7.3.8 + semver: 7.5.4 webpack: 5.75.0(esbuild@0.12.29)(webpack-cli@4.10.0) dev: false @@ -19193,7 +19200,7 @@ packages: memfs: 3.4.13 minimatch: 3.1.2 schema-utils: 2.7.0 - semver: 7.3.8 + semver: 7.5.4 tapable: 1.1.3 typescript: 4.9.4 webpack: 5.75.0(esbuild@0.12.29)(webpack-cli@4.10.0) @@ -22215,7 +22222,7 @@ packages: jest-util: 27.5.1 natural-compare: 1.4.0 pretty-format: 27.5.1 - semver: 7.3.8 + semver: 7.5.4 transitivePeerDependencies: - supports-color dev: true @@ -24946,7 +24953,7 @@ packages: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.11.0 - semver: 7.3.8 + semver: 7.5.4 validate-npm-package-license: 3.0.4 dev: true @@ -25625,7 +25632,7 @@ packages: got: 11.8.3 registry-auth-token: 5.0.1 registry-url: 6.0.1 - semver: 7.3.8 + semver: 7.5.4 dev: true /param-case@2.1.1: @@ -26284,7 +26291,7 @@ packages: loader-utils: 2.0.4 postcss: 7.0.39 schema-utils: 3.1.1 - semver: 7.3.8 + semver: 7.5.4 webpack: 5.75.0(esbuild@0.12.29)(webpack-cli@4.10.0) dev: true @@ -26298,7 +26305,7 @@ packages: cosmiconfig: 7.1.0 klona: 2.0.6 postcss: 8.4.21 - semver: 7.3.8 + semver: 7.5.4 webpack: 5.75.0(esbuild@0.12.29)(webpack-cli@4.10.0) dev: true @@ -26312,7 +26319,7 @@ packages: cosmiconfig: 7.1.0 klona: 2.0.6 postcss: 8.4.21 - semver: 7.3.8 + semver: 7.5.4 webpack: 5.75.0(esbuild@0.12.29)(webpack-cli@4.10.0) dev: false @@ -27026,7 +27033,7 @@ packages: pino-http: 5.8.0 pkg-conf: 3.1.0 resolve: 1.22.1 - semver: 7.3.8 + semver: 7.5.4 update-dotenv: 1.1.1(dotenv@8.6.0) uuid: 8.3.2 transitivePeerDependencies: @@ -30087,7 +30094,7 @@ packages: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} dependencies: - semver: 7.3.8 + semver: 7.5.4 dev: true /semver@5.7.1: @@ -30103,16 +30110,16 @@ packages: hasBin: true dev: true - /semver@7.3.7: - resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + /semver@7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} engines: {node: '>=10'} hasBin: true dependencies: lru-cache: 6.0.0 dev: true - /semver@7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} hasBin: true dependencies: @@ -31364,7 +31371,7 @@ packages: mime: 2.6.0 qs: 6.11.1 readable-stream: 3.6.1 - semver: 7.3.8 + semver: 7.5.4 transitivePeerDependencies: - supports-color dev: true @@ -32219,7 +32226,7 @@ packages: json5: 2.2.1 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.3.7 + semver: 7.5.4 typescript: 4.9.4 yargs-parser: 20.2.9 dev: true @@ -32255,7 +32262,7 @@ packages: json5: 2.2.1 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.3.7 + semver: 7.5.4 typescript: 4.9.4 yargs-parser: 20.2.9 dev: true @@ -32291,7 +32298,7 @@ packages: json5: 2.2.1 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.3.7 + semver: 7.5.4 typescript: 4.9.4 yargs-parser: 20.2.9 dev: true @@ -32327,7 +32334,7 @@ packages: json5: 2.2.1 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.3.7 + semver: 7.5.4 typescript: 4.9.4 yargs-parser: 20.2.9 dev: true @@ -32958,7 +32965,7 @@ packages: is-yarn-global: 0.3.0 latest-version: 5.1.0 pupa: 2.1.1 - semver: 7.3.8 + semver: 7.5.4 semver-diff: 3.1.1 xdg-basedir: 4.0.0 dev: false @@ -32978,7 +32985,7 @@ packages: is-yarn-global: 0.4.1 latest-version: 7.0.0 pupa: 3.1.0 - semver: 7.3.8 + semver: 7.5.4 semver-diff: 4.0.0 xdg-basedir: 5.1.0 dev: true