diff --git a/.yarnrc b/.yarnrc index 3db8343..0136884 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,2 @@ registry "https://registry.npmmirror.com/" - -electron_mirror "https://registry.npmmirror.com/-/binary/electron/" \ No newline at end of file +electron_mirror "https://npmmirror.com/mirrors/electron/" \ No newline at end of file diff --git a/README.md b/README.md index 3aee0b9..0d33769 100644 --- a/README.md +++ b/README.md @@ -2,34 +2,34 @@ React -   +   TypeScript -   +   Yarn -   +   Node -   +   Webpack -   +   Electron -   +   ElectronBuilder -   +   SemiUI -   +   Turbo -   +   Wukongim -   +   📚 [在线文档](https://tsdaodao.com/) | 🚀 [演示地址](https://web.botgate.cn/)(账号/密码:15900000002/a1234567) diff --git a/apps/web/config-overrides.js b/apps/web/config-overrides.js index b0a616e..afa1d81 100644 --- a/apps/web/config-overrides.js +++ b/apps/web/config-overrides.js @@ -1,70 +1,40 @@ var path = require('path') - -const { override, babelInclude, addWebpackPlugin } = require('customize-cra') +const { override, babelInclude, addWebpackPlugin, overrideDevServer } = require('customize-cra') const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const TerserPlugin = require("terser-webpack-plugin"); -// module.exports = override( -// // 注意是production环境启动该plugin -// process.env.NODE_ENV === 'production' && addWebpackPlugin( -// new UglifyJsPlugin({ -// // 开启打包缓存 -// cache: true, -// // 开启多线程打包 -// parallel: true, -// uglifyOptions: { -// // 删除警告 -// warnings: false, -// // 压缩 -// compress: { -// // 移除console -// drop_console: true, -// // 移除debugger -// drop_debugger: true -// } -// } -// }) -// ) -// ) +const addDevServerConfig = () => config => { + return { + ...config, + client: { + overlay: false + } + }; +} -module.exports = function (config, env) { - if (process.env.NODE_ENV === 'production') { - config.devtool = false; - } - if (env === 'production') { - config.optimization = { - minimize: true, - minimizer: [new TerserPlugin()], - }; - } - return Object.assign( - config, - override( - // 判断环境变量ANALYZER参数的值 - process.env.ANALYZER && addWebpackPlugin(new BundleAnalyzerPlugin()), - // process.env.NODE_ENV === 'production' && addWebpackPlugin( - // new UglifyJsPlugin({ - // cache: true, - // // 开启多线程打包 - // parallel: true, - // uglifyOptions: { - // // 删除警告 - // warnings: false, - // // 压缩 - // compress: { - // // 移除console - // drop_console: true, - // // 移除debugger - // drop_debugger: true - // } - // }, - // }) - // ), - babelInclude([ - /* transpile (converting to es5) code in src/ and shared component library */ - path.resolve('src'), - path.resolve('../../packages'), - ]) - )(config, env) - ) +module.exports = { + webpack: function (config, env) { + if (process.env.NODE_ENV === 'production') { + config.devtool = false; + } + if (env === 'production') { + config.optimization = { + minimize: true, + minimizer: [new TerserPlugin()], + }; + } + return Object.assign( + config, + override( + // 判断环境变量ANALYZER参数的值 + process.env.ANALYZER && addWebpackPlugin(new BundleAnalyzerPlugin()), + babelInclude([ + /* transpile (converting to es5) code in src/ and shared component library */ + path.resolve('src'), + path.resolve('../../packages'), + ]) + )(config, env) + ) + }, + devServer: overrideDevServer(addDevServerConfig()) } \ No newline at end of file diff --git a/apps/web/electron-builder.js b/apps/web/electron-builder.js deleted file mode 100644 index 320224a..0000000 --- a/apps/web/electron-builder.js +++ /dev/null @@ -1,60 +0,0 @@ -module.exports = { - productName: "tangsengdaodao", //项目名 - appId: "com.tsdaodao.im", - copyright: "Copyright © tsdaodao", //版权 - directories: { - output: "dist-ele", // 输出文件夹 - }, - npmRebuild: false, - asar: false, - buildDependenciesFromSource: true, - electronDownload: { - mirror: "https://registry.npmmirror.com/-/binary/electron/", - }, - files: ["resources/**/*","out-election/**/*", "build/**/*"], // 需要打包的文件 - extraMetadata: { - main: "out-election/main/index.js", - }, - mac: { - category: "public.app-category.instant-messaging", - target: [ - { - target: 'dmg', - arch: ['x64', 'arm64'] - } - ], - artifactName: '${productName}-${os}-${version}-${arch}.${ext}', - icon: "resources/icons/icon.icns" - }, - dmg: { - // background: 'build/appdmg.png', // dmg安装窗口背景图 - icon: "resources/icons/icon.icns", // 客户端图标 - iconSize: 100, // 安装图标大小 - // 安装窗口中包含的项目和配置 - contents: [ - { x: 380, y: 280, type: "link", path: "/Applications" }, - { x: 110, y: 280, type: "file" }, - ], - window: { width: 500, height: 500 }, // 安装窗口大小 - }, - win: { - icon: "resources/icons/icon.ico", - verifyUpdateCodeSignature: false, - target: ["nsis", "zip"], - artifactName: "${productName}-Setup-${version}.${ext}" - }, - nsis: { - oneClick: false, // 是否一键安装 - allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。 - allowToChangeInstallationDirectory: true, // 允许修改安装目录 - // installerIcon: "./build/icon.ico",// 安装图标 - // uninstallerIcon: "./build/icons/bbb.ico",//卸载图标 - // installerHeaderIcon: "./build/icon.ico", // 安装时头部图标 - createDesktopShortcut: true, // 创建桌面图标 - createStartMenuShortcut: true, // 创建开始菜单图标 - }, - linux: { - target: ["AppImage", "deb"], - icon: "resources/icons/icon.icns", - }, -}; \ No newline at end of file diff --git a/apps/web/electron-builder.yml b/apps/web/electron-builder.yml new file mode 100644 index 0000000..1d5f280 --- /dev/null +++ b/apps/web/electron-builder.yml @@ -0,0 +1,58 @@ +productName: tangsengdaodao +appId: com.tsdaodao.im +copyright: Copyright © tsdaodao +directories: + output: dist-ele +npmRebuild: false +asar: false +buildDependenciesFromSource: true +electronDownload: + mirror: https://npmmirror.com/mirrors/electron/ +files: + - resources/**/* + - out-election/**/* + - build/**/* +extraMetadata: + main: out-election/main/index.js +mac: + category: public.app-category.instant-messaging + target: + - target: dmg + arch: + - x64 + - arm64 + artifactName: ${productName}-${os}-${version}-${arch}.${ext} + icon: resources/icons/icon.icns +dmg: + icon: resources/icons/icon.icns + iconSize: 100 + contents: + - x: 380 + y: 280 + type: link + path: /Applications + - x: 110 + y: 280 + type: link + window: + width: 500 + height: 500 +win: + icon: resources/icons/icon.ico + verifyUpdateCodeSignature: false + target: + - nsis + - zip + artifactName: ${productName}-Setup-${version}.${ext} +nsis: + oneClick: false + allowElevation: true + allowToChangeInstallationDirectory: true + createDesktopShortcut: true + createStartMenuShortcut: true +linux: + target: + - AppImage + - deb + icon: resources/icons/icon.icns + diff --git a/apps/web/package.json b/apps/web/package.json index 10fab80..4232297 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -55,7 +55,6 @@ "customize-cra": "^1.0.0", "electron": "26.0.0", "electron-builder": "^24.9.1", - "electron-log": "^5.0.1", "eslint-config-react-app": "^7.0.1", "kill-port": "^2.0.1", "npm-run-all": "^4.1.5", @@ -64,7 +63,7 @@ "react-scripts": "5.0.0", "terser-webpack-plugin": "^5.3.9", "tsc-watch": "^6.0.4", - "typescript": "^5.3.3", + "typescript": "^4.5.5", "wait-on": "^7.2.0", "webpack-bundle-analyzer": "^4.5.0" }, @@ -73,7 +72,7 @@ }, "browserslist": { "production": [ - ">0.2%", + "> 1%", "not dead", "not op_mini all" ], diff --git a/apps/web/resources/icons/icon.icns b/apps/web/resources/icons/icon.icns new file mode 100644 index 0000000..32360ed Binary files /dev/null and b/apps/web/resources/icons/icon.icns differ diff --git a/package.json b/package.json index 97f03b9..d555a6f 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { + "name": "tsdd", "private": true, + "version": "0.0.0", "workspaces": [ "apps/*", "packages/*" ], "resolutions": { - "//": "See https://github.com/facebook/create-react-app/issues/11773", "react-error-overlay": "6.0.11" }, "scripts": { - "bootstrap": "yarn install", "dev": "turbo run dev --parallel", "dev-ele": "turbo run dev-ele --parallel", "build": "turbo run build", @@ -18,7 +18,8 @@ "build-ele:win": "turbo run build-ele:win", "build-ele:linux": "turbo run build-ele:linux", "build-ele:linux-arm64": "turbo run build-ele:linux-arm64", - "clean": "turbo run clean && rimraf node_modules", + "bootstrap": "yarn install", + "clean": "turbo run clean && rimraf node_modules .turbo", "lint": "turbo run lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"" }, @@ -27,7 +28,11 @@ "eslint-config-custom": "*", "prettier": "^2.5.1", "rimraf": "^5.0.5", - "turbo": "latest" + "turbo": "2.0.9" }, - "version": "0.0.0" + "packageManager": "yarn@1.22.19", + "engines": { + "node": ">=18.0.0", + "yarn": ">=1.22.19" + } } diff --git a/packages/eslint-config-custom/package.json b/packages/eslint-config-custom/package.json index 3e2d85b..82db02e 100644 --- a/packages/eslint-config-custom/package.json +++ b/packages/eslint-config-custom/package.json @@ -4,7 +4,7 @@ "main": "index.js", "license": "MIT", "scripts": { - "clean": "rimraf node_modules out-election" + "clean": "rimraf node_modules .turbo" }, "dependencies": { "@typescript-eslint/parser": "^6.16.0", diff --git a/packages/tsdaodaobase/src/Messages/Image/index.css b/packages/tsdaodaobase/src/Messages/Image/index.css new file mode 100644 index 0000000..2898e23 --- /dev/null +++ b/packages/tsdaodaobase/src/Messages/Image/index.css @@ -0,0 +1,25 @@ +@keyframes loading { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} +.loading-box{ + width: 32px; + height: 32px; + position:absolute; + top:50%; + left:50%; + transform:translate(-16px,-16px); +} +.loading-icon{ + width: 32px; + height: 32px; + animation: loading 1s linear infinite; +} +.loading-text{ + font-size: 14px; + white-space: nowrap; +} diff --git a/packages/tsdaodaobase/src/Messages/Image/index.tsx b/packages/tsdaodaobase/src/Messages/Image/index.tsx index 4064973..d8c4a7f 100644 --- a/packages/tsdaodaobase/src/Messages/Image/index.tsx +++ b/packages/tsdaodaobase/src/Messages/Image/index.tsx @@ -1,124 +1,172 @@ -import { MediaMessageContent } from "wukongimjssdk" -import React from "react" -import WKApp from "../../App" -import { MessageContentTypeConst } from "../../Service/Const" -import MessageBase from "../Base" -import { MessageCell } from "../MessageCell" -import Viewer from 'react-viewer'; - - +import WKSDK, { MediaMessageContent, Task } from "wukongimjssdk"; +import React from "react"; +import WKApp from "../../App"; +import { MessageContentTypeConst } from "../../Service/Const"; +import MessageBase from "../Base"; +import { MessageCell } from "../MessageCell"; +import Viewer from "react-viewer"; +import "./index.css"; export class ImageContent extends MediaMessageContent { - width!: number - height!: number - url!: string - imgData?: string - constructor(file?: File, imgData?: string, width?: number, height?: number) { - super() - this.file = file - this.imgData = imgData - this.width = width || 0 - this.height = height || 0 - } - decodeJSON(content: any) { - this.width = content["width"] || 0 - this.height = content["height"] || 0 - this.url = content["url"] || '' - this.remoteUrl = this.url - } - encodeJSON() { - return { "width": this.width || 0, "height": this.height || 0, "url": this.remoteUrl || "" } - } - get contentType() { - return MessageContentTypeConst.image - } - get conversationDigest() { - return "[图片]" - } + width!: number; + height!: number; + url!: string; + imgData?: string; + constructor(file?: File, imgData?: string, width?: number, height?: number) { + super(); + this.file = file; + this.imgData = imgData; + this.width = width || 0; + this.height = height || 0; + } + decodeJSON(content: any) { + this.width = content["width"] || 0; + this.height = content["height"] || 0; + this.url = content["url"] || ""; + this.remoteUrl = this.url; + } + encodeJSON() { + return { width: this.width || 0, height: this.height || 0, url: this.remoteUrl || "" }; + } + get contentType() { + return MessageContentTypeConst.image; + } + get conversationDigest() { + return "[图片]"; + } } - interface ImageCellState { - showPreview: boolean + showPreview: boolean; + loading: boolean; + progress: number; } export class ImageCell extends MessageCell { + taskListener!: any; + constructor(props: any) { + super(props); + this.state = { + showPreview: false, + loading: false, + progress: 0, + }; + } - constructor(props: any) { - super(props) - this.state = { - showPreview: false, + imageScale(orgWidth: number, orgHeight: number, maxWidth = 250, maxHeight = 250) { + let actSize = { width: orgWidth, height: orgHeight }; + if (orgWidth > orgHeight) { + //横图 + if (orgWidth > maxWidth) { + // 横图超过最大宽度 + let rate = maxWidth / orgWidth; // 缩放比例 + actSize.width = maxWidth; + actSize.height = orgHeight * rate; + } + } else if (orgWidth < orgHeight) { + //竖图 + if (orgHeight > maxHeight) { + let rate = maxHeight / orgHeight; // 缩放比例 + actSize.width = orgWidth * rate; + actSize.height = maxHeight; + } + } else if (orgWidth === orgHeight) { + if (orgWidth > maxWidth) { + let rate = maxWidth / orgWidth; // 缩放比例 + actSize.width = maxWidth; + actSize.height = orgHeight * rate; + } + } + return actSize; + } + + getImageSrc(content: ImageContent) { + if (content.url && content.url !== "") { + // 等待发送的消息 + let downloadURL = WKApp.dataSource.commonDataSource.getImageURL(content.url, { + width: content.width, + height: content.height, + }); + if (downloadURL.indexOf("?") != -1) { + downloadURL += "&filename=image.png"; + } else { + downloadURL += "?filename=image.png"; + } + return downloadURL; + } + return content.imgData; + } + + getImageElement() { + const { message } = this.props; + const content = message.content as ImageContent; + let scaleSize = this.imageScale(content.width, content.height); + if (!this.taskListener && !content?.url) { + this.taskListener = (task: Task) => { + this.setState({ + loading: true, + progress: Math.trunc(task.progress() * 100), + }); + if (task.progress() === 1) { + this.setState({ + loading: false, + progress: 100, + }); + WKSDK.shared().taskManager.removeListener(this.taskListener); } + }; + WKSDK.shared().taskManager.addListener(this.taskListener); } + return ( +
+ + {this.state.loading && scaleSize.width > 32 && ( + + + {scaleSize.height > 46 &&

{this.state.progress}%

} +
+ )} +
+ ); + } - imageScale(orgWidth: number, orgHeight: number, maxWidth = 250, maxHeight = 250) { - let actSize = { width: orgWidth, height: orgHeight }; - if (orgWidth > orgHeight) {//横图 - if (orgWidth > maxWidth) { // 横图超过最大宽度 - let rate = maxWidth / orgWidth; // 缩放比例 - actSize.width = maxWidth; - actSize.height = orgHeight * rate; - } - } else if (orgWidth < orgHeight) { //竖图 - if (orgHeight > maxHeight) { - let rate = maxHeight / orgHeight; // 缩放比例 - actSize.width = orgWidth * rate; - actSize.height = maxHeight; - } - } else if (orgWidth === orgHeight) { - if (orgWidth > maxWidth) { - let rate = maxWidth / orgWidth; // 缩放比例 - actSize.width = maxWidth; - actSize.height = orgHeight * rate; - } - } - return actSize; - } - - getImageSrc(content: ImageContent) { - if (content.url && content.url !== "") { // 等待发送的消息 - let downloadURL = WKApp.dataSource.commonDataSource.getImageURL(content.url, { width: content.width, height: content.height }) - if (downloadURL.indexOf("?") != -1) { - downloadURL += "&filename=image.png" - } else { - downloadURL += "?filename=image.png" - } - return downloadURL - } - return content.imgData - } - - getImageElement() { - const { message } = this.props - const content = message.content as ImageContent - let scaleSize = this.imageScale(content.width, content.height); - return - } - - render() { - const { message, context } = this.props - const { showPreview } = this.state - const content = message.content as ImageContent - let scaleSize = this.imageScale(content.width, content.height); - const imageURL = this.getImageSrc(content) || "" - return -
{ - this.setState({ - showPreview: !this.state.showPreview, - }) - }}> - {this.getImageElement()} -
- { this.setState({ showPreview: false }); }} - onClose={() => { this.setState({ showPreview: false }); }} - images={[{ src: imageURL, alt: '', downloadUrl: imageURL }]} - /> -
- } -} \ No newline at end of file + render() { + const { message, context } = this.props; + const { showPreview } = this.state; + const content = message.content as ImageContent; + let scaleSize = this.imageScale(content.width, content.height); + const imageURL = this.getImageSrc(content) || ""; + return ( + +
{ + this.setState({ + showPreview: !this.state.showPreview, + }); + }} + > + {this.getImageElement()} +
+ { + this.setState({ showPreview: false }); + }} + onClose={() => { + this.setState({ showPreview: false }); + }} + images={[{ src: imageURL, alt: "", downloadUrl: imageURL }]} + /> +
+ ); + } +} diff --git a/packages/tsdaodaobase/src/assets/loading.png b/packages/tsdaodaobase/src/assets/loading.png new file mode 100644 index 0000000..1ae2361 Binary files /dev/null and b/packages/tsdaodaobase/src/assets/loading.png differ diff --git a/packages/tsdaodaocontacts/package.json b/packages/tsdaodaocontacts/package.json index ebbf539..010c0c1 100644 --- a/packages/tsdaodaocontacts/package.json +++ b/packages/tsdaodaocontacts/package.json @@ -5,6 +5,7 @@ "dependencies": { "@tsdaodao/base": "*", "axios": "^0.25.0", - "classnames": "^2.3.1" + "classnames": "^2.3.1", + "react-infinite-scroller": "^1.2.6" } } diff --git a/packages/tsdaodaocontacts/src/Contacts/index.tsx b/packages/tsdaodaocontacts/src/Contacts/index.tsx index 4bebefe..a5dbb5a 100644 --- a/packages/tsdaodaocontacts/src/Contacts/index.tsx +++ b/packages/tsdaodaocontacts/src/Contacts/index.tsx @@ -1,246 +1,287 @@ import React from "react"; import { Component } from "react"; -import { Contacts, ContactsChangeListener, ContextMenus, ContextMenusContext, WKApp, WKBase, WKBaseContext, WKNavMainHeader, Search, UserRelation } from "@tsdaodao/base" -import "./index.css" +import { + Contacts, + ContactsChangeListener, + ContextMenus, + ContextMenusContext, + WKApp, + WKBase, + WKBaseContext, + WKNavMainHeader, + Search, + UserRelation, +} from "@tsdaodao/base"; +import "./index.css"; import { toSimplized } from "@tsdaodao/base"; import { getPinyin } from "@tsdaodao/base"; import classnames from "classnames"; import { Toast } from "@douyinfe/semi-ui"; -import { Channel, ChannelTypePerson, WKSDK,ChannelInfoListener,ChannelInfo } from "wukongimjssdk"; +import { + Channel, + ChannelTypePerson, + WKSDK, + ChannelInfoListener, + ChannelInfo, +} from "wukongimjssdk"; import { ContactsListManager } from "../Service/ContactsListManager"; import { Card } from "@tsdaodao/base/src/Messages/Card"; import WKAvatar from "@tsdaodao/base/src/Components/WKAvatar"; - - - export class ContactsState { - indexList: string[] = [] - indexItemMap: Map = new Map() - keyword?: string - selectedItem?: Contacts // 被选中的联系人 + indexList: string[] = []; + indexItemMap: Map = new Map(); + keyword?: string; + selectedItem?: Contacts; // 被选中的联系人 } export default class ContactsList extends Component { - contactsChangeListener!: ContactsChangeListener - channelInfoListener!: ChannelInfoListener - contextMenusContext!: ContextMenusContext - baseContext!: WKBaseContext - constructor(props: any) { - super(props) + contactsChangeListener!: ContactsChangeListener; + channelInfoListener!: ChannelInfoListener; + contextMenusContext!: ContextMenusContext; + baseContext!: WKBaseContext; + constructor(props: any) { + super(props); - this.state = { - indexList: [], - indexItemMap: new Map() + this.state = { + indexList: [], + indexItemMap: new Map(), + }; + } + componentDidMount() { + this.contactsChangeListener = () => { + this.rebuildIndex(); + }; + + this.channelInfoListener = (channelInfo: ChannelInfo) => { + if (channelInfo.channel.channelType !== ChannelTypePerson) { + return; + } + //是否包含 + let exist = false; + WKApp.dataSource.contactsList.forEach((v) => { + if (v.uid === channelInfo.channel.channelID) { + exist = true; + v.name = channelInfo.title; + v.remark = channelInfo?.orgData.remark; + return; } - } - componentDidMount() { + }); + if (exist) { + this.rebuildIndex(); + } + }; - this.contactsChangeListener = () => { - this.rebuildIndex() + WKApp.dataSource.addContactsChangeListener(this.contactsChangeListener); + + this.rebuildIndex(); + + WKSDK.shared().channelManager.addListener(this.channelInfoListener); + + ContactsListManager.shared.setRefreshList = () => { + this.setState({}); + }; + } + + componentWillUnmount() { + ContactsListManager.shared.setRefreshList = undefined; + WKApp.dataSource.removeContactsChangeListener(this.contactsChangeListener); + WKSDK.shared().channelManager.removeListener(this.channelInfoListener); + } + + rebuildIndex() { + console.log("rebuildIndex---->"); + this.buildIndex(this.contactsList()); + } + + contactsList() { + const { keyword } = this.state; + return WKApp.dataSource.contactsList.filter((v) => { + if (v.status === UserRelation.blacklist) { + return false; + } + if (v.follow !== 1) { + return false; + } + if (!keyword || keyword === "") { + return true; + } + + if (v.remark && v.remark !== "") { + if (v.remark.indexOf(keyword) !== -1) { + return true; } + } - this.channelInfoListener = (channelInfo:ChannelInfo)=>{ - if(channelInfo.channel.channelType !== ChannelTypePerson) { - return - } - //是否包含 - let exist = false - WKApp.dataSource.contactsList.forEach((v)=>{ - if(v.uid === channelInfo.channel.channelID) { - exist = true - v.name = channelInfo.title - v.remark = channelInfo?.orgData.remark - return - } - }) - if(exist) { - this.rebuildIndex() - } - } + return v.name.indexOf(keyword) !== -1; + }); + } - WKApp.dataSource.addContactsChangeListener(this.contactsChangeListener) + buildIndex(contacts: Contacts[]) { + const indexItemMap = new Map(); + let indexList = []; + for (const item of contacts) { + let name = item.name; + if (item.remark && item.remark !== "") { + name = item.remark; + } - this.rebuildIndex() + let pinyinNick = getPinyin(toSimplized(name)).toUpperCase(); + let indexName = + !pinyinNick || /[^a-z]/i.test(pinyinNick[0]) ? "#" : pinyinNick[0]; - WKSDK.shared().channelManager.addListener(this.channelInfoListener) - - ContactsListManager.shared.setRefreshList = () => { - this.setState({}) - } + let existItems = indexItemMap.get(indexName); + if (!existItems) { + existItems = []; + indexList.push(indexName); + } + existItems.push(item); + indexItemMap.set(indexName, existItems); } + indexList = indexList.sort((a, b) => { + if (a === "#") { + return -1; + } + if (b === "#") { + return 1; + } + return a.localeCompare(b); + }); + this.setState({ + indexList: indexList, + indexItemMap: indexItemMap, + }); + } - componentWillUnmount() { - ContactsListManager.shared.setRefreshList = undefined - WKApp.dataSource.removeContactsChangeListener(this.contactsChangeListener) - WKSDK.shared().channelManager.removeListener(this.channelInfoListener) - } + _handleContextMenu(item: Contacts, event: React.MouseEvent) { + this.contextMenusContext.show(event); + this.setState({ + selectedItem: item, + }); + } + sectionUI(indexName: string) { + const { indexItemMap } = this.state; + const { canSelect } = this.props; + const items = indexItemMap.get(indexName); - rebuildIndex() { - console.log("rebuildIndex---->") - this.buildIndex(this.contactsList()) - } - - contactsList() { - const { keyword } = this.state - return WKApp.dataSource.contactsList.filter((v) => { - if (v.status === UserRelation.blacklist) { - return false - } - if (v.follow !== 1) { - return false - } - if (!keyword || keyword === "") { - return true - } - - if (v.remark && v.remark !== "") { - if (v.remark.indexOf(keyword) !== -1) { - return true - } - } - - return v.name.indexOf(keyword) !== -1 - }) - } - - - buildIndex(contacts: Contacts[]) { - const indexItemMap = new Map() - let indexList = [] - for (const item of contacts) { - let name = item.name + return ( +
+
+ {items?.map((item, i) => { + let name = item.name; if (item.remark && item.remark !== "") { - name = item.remark + name = item.remark; } - - let pinyinNick = getPinyin(toSimplized(name)).toUpperCase(); - let indexName = !pinyinNick || /[^a-z]/i.test(pinyinNick[0]) ? "#" : pinyinNick[0]; - - let existItems = indexItemMap.get(indexName) - if (!existItems) { - existItems = [] - indexList.push(indexName) - } - existItems.push(item) - indexItemMap.set(indexName, existItems) - } - indexList = indexList.sort((a, b) => { - if (a === "#") { - return -1 - } - if (b === "#") { - return 1 - } - return a.localeCompare(b) - }) - this.setState({ - indexList: indexList, - indexItemMap: indexItemMap, - }) - } - - _handleContextMenu(item: Contacts, event: React.MouseEvent) { - this.contextMenusContext.show(event) - this.setState({ - selectedItem: item, - }) - } - - sectionUI(indexName: string) { - const { indexItemMap } = this.state - const { canSelect } = this.props - const items = indexItemMap.get(indexName) - - return
-
- { - items?.map((item, i) => { - let name = item.name - if (item.remark && item.remark !== "") { - name = item.remark - } - return
{ - const channel = new Channel(item.uid, ChannelTypePerson) - WKApp.endpoints.showConversation(channel) - this.setState({}) - }} onContextMenu={(e) => { - this._handleContextMenu(item, e) - }}> -
- {i === 0 ? indexName : ""} -
-
- -
-
- {name} -
-
- }) - } -
-
- - } - render() { - const { indexList } = this.state - return { - this.baseContext = baseCtx - }}> -
- -
-
- { - this.setState({ - keyword: v - }, () => { - this.rebuildIndex() - }) - }}> -
-
- { - WKApp.endpoints.contactsHeaders().map((view, i) => { - return
{view}
- }) - } -
-
- { - indexList.map((indexName) => { - return this.sectionUI(indexName) - }) - } -
+ return ( +
{ + const channel = new Channel(item.uid, ChannelTypePerson); + WKApp.endpoints.showConversation(channel); + this.setState({}); + }} + onContextMenu={(e) => { + this._handleContextMenu(item, e); + }} + > +
+ {i === 0 ? indexName : ""}
- { - this.contextMenusContext = context - }} menus={[{ - title: "查看资料", onClick: () => { - const { selectedItem } = this.state - this.baseContext.showUserInfo(selectedItem?.uid || "") +
+ +
+
{name}
+
+ ); + })} +
+
+ ); + } + render() { + const { indexList } = this.state; + return ( + { + this.baseContext = baseCtx; + }} + > +
+ +
+
+ { + this.setState( + { + keyword: v, + }, + () => { + this.rebuildIndex(); } - }, { - title: "分享给朋友...", onClick: () => { - WKApp.shared.baseContext.showConversationSelect((channels: Channel[]) => { - const { selectedItem } = this.state - if (channels && channels.length > 0) { - for (const channel of channels) { - const card = new Card() - card.uid = selectedItem?.uid || "" - card.name = selectedItem?.name || "" - card.vercode = selectedItem?.vercode||"" - WKSDK.shared().chatManager.send(card, channel) - } - Toast.success("分享成功!") - } - }, "分享名片") - } - }]} /> + ); + }} + >
- - } -} \ No newline at end of file +
+ {WKApp.endpoints.contactsHeaders().map((view, i) => { + return
{view}
; + })} +
+
+ {indexList.map((indexName) => { + return this.sectionUI(indexName); + })} +
+
+ { + this.contextMenusContext = context; + }} + menus={[ + { + title: "查看资料", + onClick: () => { + const { selectedItem } = this.state; + this.baseContext.showUserInfo(selectedItem?.uid || ""); + }, + }, + { + title: "分享给朋友...", + onClick: () => { + WKApp.shared.baseContext.showConversationSelect( + (channels: Channel[]) => { + const { selectedItem } = this.state; + if (channels && channels.length > 0) { + for (const channel of channels) { + const card = new Card(); + card.uid = selectedItem?.uid || ""; + card.name = selectedItem?.name || ""; + card.vercode = selectedItem?.vercode || ""; + WKSDK.shared().chatManager.send(card, channel); + } + Toast.success("分享成功!"); + } + }, + "分享名片" + ); + }, + }, + ]} + /> +
+
+ ); + } +} diff --git a/packages/tsdaodaocontacts/src/FriendAdd/index.tsx b/packages/tsdaodaocontacts/src/FriendAdd/index.tsx index 3069c8b..546d1fe 100644 --- a/packages/tsdaodaocontacts/src/FriendAdd/index.tsx +++ b/packages/tsdaodaocontacts/src/FriendAdd/index.tsx @@ -1,81 +1,98 @@ import { WKApp, WKViewQueueHeader, QRCodeMy, Search } from "@tsdaodao/base"; -import {WKBase, WKBaseContext } from "@tsdaodao/base"; +import { WKBase, WKBaseContext } from "@tsdaodao/base"; import React from "react"; import { Component, ReactNode } from "react"; -import { Spin,Toast } from '@douyinfe/semi-ui'; -import "./index.css" +import { Spin, Toast } from "@douyinfe/semi-ui"; +import "./index.css"; export interface FriendAddProps { - onBack?: () => void + onBack?: () => void; } export class FriendAddState { - spinning!:boolean - keyword?:string - result?:any + spinning!: boolean; + keyword?: string; + result?: any; } -export class FriendAdd extends Component { - baseContext!:WKBaseContext - constructor(props:any) { - super(props) +export class FriendAdd extends Component { + baseContext!: WKBaseContext; + constructor(props: any) { + super(props); - this.state = { - spinning: false, - } + this.state = { + spinning: false, + }; + } + + async searchUser() { + const { keyword } = this.state; + if (!keyword) { + return; } - async searchUser() { - const { keyword } = this.state - if(!keyword) { - return - } - - this.setState({ - spinning: true, - }) - const result = await WKApp.dataSource.commonDataSource.searchUser(keyword).catch((err)=>{ - Toast.error(err.msg) - }) - if(result) { - this.setState({ - result: result, - spinning: false, - }) - if(result.exist !== 1) { - Toast.error("用户不存在!") - }else { - WKApp.shared.baseContext.showUserInfo(result.data.uid,undefined,result.data.vercode) - } + this.setState({ + spinning: true, + }); + const result = await WKApp.dataSource.commonDataSource + .searchUser(keyword) + .catch((err) => { + Toast.error(err.msg); + }); + if (result) { + this.setState({ + result: result, + spinning: false, + }); + if (result.exist !== 1) { + Toast.error("用户不存在!"); + } else { + WKApp.shared.baseContext.showUserInfo( + result.data.uid, + undefined, + result.data.vercode + ); } - } - - - render(): ReactNode { - const { onBack } = this.props - const { spinning } = this.state - return { - this.baseContext = ctx - }}> -
- -
- - { - this.setState({ - keyword: v - }) - }} onEnterPress={()=>{ - this.searchUser() - }}> - -
- 我的{WKApp.config.appName}号:{WKApp.loginInfo.shortNo} { - WKApp.routeLeft.push() - }} src={require("./assets/icon_qrcode.png")}> -
-
-
-
} -} \ No newline at end of file + } + + render(): ReactNode { + const { onBack } = this.props; + const { spinning } = this.state; + return ( + { + this.baseContext = ctx; + }} + > +
+ +
+ + { + this.setState({ + keyword: v, + }); + }} + onEnterPress={() => { + this.searchUser(); + }} + > + +
+ 我的{WKApp.config.appName}号:{WKApp.loginInfo.shortNo}{" "} + { + WKApp.routeLeft.push(); + }} + src={require("./assets/icon_qrcode.png")} + > +
+
+
+
+ ); + } +} diff --git a/packages/tsdaodaocontacts/src/NewFriend/index.css b/packages/tsdaodaocontacts/src/NewFriend/index.css index 91b6636..d6b5acf 100644 --- a/packages/tsdaodaocontacts/src/NewFriend/index.css +++ b/packages/tsdaodaocontacts/src/NewFriend/index.css @@ -9,7 +9,7 @@ .wk-newfriend-content { height: calc(100% - var( --wk-height-viewqueueheader)); width: 100%; - + overflow-y: auto; } .wk-newfriend-content li { diff --git a/packages/tsdaodaocontacts/src/NewFriend/index.tsx b/packages/tsdaodaocontacts/src/NewFriend/index.tsx index c285feb..b3d884a 100644 --- a/packages/tsdaodaocontacts/src/NewFriend/index.tsx +++ b/packages/tsdaodaocontacts/src/NewFriend/index.tsx @@ -1,58 +1,130 @@ -import { FriendApplyState, WKApp, WKViewQueueHeader, Provider } from "@tsdaodao/base"; import React from "react"; +import { + FriendApply, + FriendApplyState, + WKApp, + ContextMenus, + ContextMenusContext, + WKViewQueueHeader, + Provider, +} from "@tsdaodao/base"; import { Component, ReactNode } from "react"; -import { Button } from '@douyinfe/semi-ui'; -import "./index.css" +import { Button } from "@douyinfe/semi-ui"; import { NewFriendVM } from "./vm"; -import "./index.css" import { FriendAdd } from "../FriendAdd"; +import "./index.css"; -export class NewFriend extends Component { +export class NewFriendState { + selectedItem?: FriendApply; // 被选中的好友 +} - render(): ReactNode { - return { - return new NewFriendVM() - }} render={(vm: NewFriendVM) => { +export class NewFriend extends Component { + contextMenusContext!: ContextMenusContext; - return
- { - WKApp.routeLeft.pop() - }} action={
- -
}>
-
-
    - { - vm.friendApplys.map((f) => { - return
  • -
    - -
    -
    -
    - {f.to_name} -
    -
    - {f.remark} -
    -
    -
    - -
    -
  • - }) - } -
-
+ constructor(props: any) { + super(props); + } + + _handleContextMenu(item: FriendApply, event: React.MouseEvent) { + console.log(item); + this.contextMenusContext.show(event); + this.setState({ + selectedItem: item, + }); + } + render(): ReactNode { + return ( + { + return new NewFriendVM(); + }} + render={(vm: NewFriendVM) => { + return ( +
+ { + WKApp.routeLeft.pop(); + }} + action={ +
+ +
+ } + >
+
+
    + {vm.friendApplys.map((f) => { + return ( +
  • { + this._handleContextMenu(f, e); + }} + > +
    + +
    +
    +
    + {f.to_name} +
    +
    + {f.remark} +
    +
    +
    + +
    +
  • + ); + })} +
+
+ { + this.contextMenusContext = context; + }} + menus={[ + { + title: "删除", + onClick: () => { + const { selectedItem } = this.state; + selectedItem && vm.delFriendApply(selectedItem); + }, + }, + ]} + />
- }}> - -
- } -} \ No newline at end of file + ); + }} + > + ); + } +} diff --git a/packages/tsdaodaodatasource/src/task.ts b/packages/tsdaodaodatasource/src/task.ts index 3c45906..4322876 100644 --- a/packages/tsdaodaodatasource/src/task.ts +++ b/packages/tsdaodaodatasource/src/task.ts @@ -18,10 +18,13 @@ export class MediaMessageUploadTask extends MessageTask { async start(): Promise { const mediaContent = this.message.content as MediaMessageContent if(mediaContent.file) { + const fileNameSuffix = mediaContent.file.name.substring( + mediaContent.file.name.lastIndexOf(".") + ); const param = new FormData(); param.append("file", mediaContent.file); const fileName = this.getUUID(); - const path = `/${this.message.channel.channelType}/${this.message.channel.channelID}/${fileName}${mediaContent.extension??""}` + const path = `/${this.message.channel.channelType}/${this.message.channel.channelID}/${fileName}${fileNameSuffix ?? ""}`; const uploadURL = await this.getUploadURL(path) if(uploadURL) { this.uploadFile(mediaContent.file,uploadURL) @@ -52,7 +55,7 @@ export class MediaMessageUploadTask extends MessageTask { this.canceler = c }), onUploadProgress: e => { - var completeProgress = ((e.loaded / e.total) | 0); + var completeProgress = ((e.loaded / e.total) || 0); this._progress = completeProgress this.update() } diff --git a/turbo.json b/turbo.json index 6a32018..b70840d 100644 --- a/turbo.json +++ b/turbo.json @@ -1,6 +1,6 @@ { "$schema": "https://turborepo.org/schema.json", - "pipeline": { + "tasks": { "dev": { "cache": false }, @@ -37,5 +37,6 @@ "clean": { "dependsOn": ["^clean"] } - } + }, + "ui": "stream" } diff --git a/yarn.lock b/yarn.lock index a46fc41..60b7c17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5046,20 +5046,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400: - version "1.0.30001495" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz" - integrity sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg== - -caniuse-lite@^1.0.30001517: - version "1.0.30001533" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001533.tgz#1180daeb2518b93c82f19b904d1fefcf82197707" - integrity sha512-9aY/b05NKU4Yl2sbcJhn4A7MsGwR1EPfW/nrqsnqVA0Oq50wpmPaGI+R1Z0UKlUl96oxUkGEOILWtOHck0eCWw== - -caniuse-lite@^1.0.30001520: - version "1.0.30001534" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz#f24a9b2a6d39630bac5c132b5dff89b39a12e7dd" - integrity sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001520: + version "1.0.30001643" + resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz" + integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg== case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" @@ -11009,9 +10999,16 @@ react-draggable@^4.0.3: react-error-overlay@6.0.11, react-error-overlay@^6.0.11: version "6.0.11" - resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" + resolved "https://registry.npmmirror.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== +react-infinite-scroller@^1.2.6: + version "1.2.6" + resolved "https://registry.npmmirror.com/react-infinite-scroller/-/react-infinite-scroller-1.2.6.tgz#8b80233226dc753a597a0eb52621247f49b15f18" + integrity sha512-mGdMyOD00YArJ1S1F3TVU9y4fGSfVVl6p5gh/Vt4u99CJOptfVu/q5V/Wlle72TMgYlBwIhbxK5wF0C/R33PXQ== + dependencies: + prop-types "^15.5.8" + react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -12753,95 +12750,47 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -turbo-android-arm64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-android-arm64/-/turbo-android-arm64-1.4.7.tgz#553f68a1f475495549fb8a260461239c90f40410" - integrity sha512-BtWtH8e8w1GhtYpGQmkcDS/AUzVZhQ4ZZN+qtUFei1wZD7VAdtJ9Wcsfi3WD+mXA6vtpIpRJVfQMcShr8l8ErA== +turbo-darwin-64@2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/turbo-darwin-64/-/turbo-darwin-64-2.0.9.tgz#dc7bb92060a41b92155195dba5850c9669fa765a" + integrity sha512-owlGsOaExuVGBUfrnJwjkL1BWlvefjSKczEAcpLx4BI7Oh6ttakOi+JyomkPkFlYElRpjbvlR2gP8WIn6M/+xQ== -turbo-darwin-64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.4.7.tgz#c23e2452a01115136e631dc06aa6a9bb379d2d32" - integrity sha512-bMvZaAz5diec9feZ0XpQosYI8U0kiOQM2tj2sv0Y2WZbe227wodVMCQMyUowmcotO8nr6NF76Xo5E+H+dnY6LQ== +turbo-darwin-arm64@2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.9.tgz#6e5ce2c0f03999c6ec0116d5525841107da3078b" + integrity sha512-XAXkKkePth5ZPPE/9G9tTnPQx0C8UTkGWmNGYkpmGgRr8NedW+HrPsi9N0HcjzzIH9A4TpNYvtiV+WcwdaEjKA== -turbo-darwin-arm64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.4.7.tgz#4212917f4892159033cfa88bafa662f6e865fe49" - integrity sha512-AyfxYfKgh1EigQKjypbnDoMLuy4e/n/go+KYiWKKIpOaWXWLBokrBWzYN/aI3NMDRUJWK5ExdlWI9Nleelq8uQ== +turbo-linux-64@2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/turbo-linux-64/-/turbo-linux-64-2.0.9.tgz#e00e5e1b1cffab23c58888e7c397e108dc24fe2f" + integrity sha512-l9wSgEjrCFM1aG16zItBsZ206ZlhSSx1owB8Cgskfv0XyIXRGHRkluihiaxkp+UeU5WoEfz4EN5toc+ICA0q0w== -turbo-freebsd-64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.4.7.tgz#7d60d44a623bd000f53673a0db0205a16d8815e6" - integrity sha512-T5/osfbCh0rL53MFS5byFFfsR3vPMHIKIJ4fMMCNkoHsmFj2R0Pv53nqhEItogt0FJwCDHPyt7oBqO83H/AWQQ== +turbo-linux-arm64@2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/turbo-linux-arm64/-/turbo-linux-arm64-2.0.9.tgz#d240e4f0a784d03f1a79fd9e6c4e83abd9aa57c7" + integrity sha512-gRnjxXRne18B27SwxXMqL3fJu7jw/8kBrOBTBNRSmZZiG1Uu3nbnP7b4lgrA/bCku6C0Wligwqurvtpq6+nFHA== -turbo-freebsd-arm64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.4.7.tgz#35e5b23313d42aab074e69c1d1c44cab17f438ac" - integrity sha512-PL+SaO78AUCas+YKj01UiS2rpmGcxz8XPmLdFWmq6PYjPX6GL5UBAc3pkBphIm0aTLZtsikoEul+JrwAuAy6UA== +turbo-windows-64@2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/turbo-windows-64/-/turbo-windows-64-2.0.9.tgz#d52835302e722cc7de670b90aca55ce2b3516879" + integrity sha512-ZVo0apxUvaRq4Vm1qhsfqKKhtRgReYlBVf9MQvVU1O9AoyydEQvLDO1ryqpXDZWpcHoFxHAQc9msjAMtE5K2lA== -turbo-linux-32@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.4.7.tgz#2861539d767cdfca058224f284991d918d7b1965" - integrity sha512-dK94UwDzySMALoQtjBVVPbWJZP6xw3yHGuytM3q5p4kfMZPSA+rgNBn5T5Af2Rc7jxlLAsu5ODJ0SgIbWSF5Hg== +turbo-windows-arm64@2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/turbo-windows-arm64/-/turbo-windows-arm64-2.0.9.tgz#45f0aa685514ec1cc753a559924e003b22b24bb7" + integrity sha512-sGRz7c5Pey6y7y9OKi8ypbWNuIRPF9y8xcMqL56OZifSUSo+X2EOsOleR9MKxQXVaqHPGOUKWsE6y8hxBi9pag== -turbo-linux-64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.4.7.tgz#5ff0e648a1d0b0053ad2f3c6a4fc735744cadc16" - integrity sha512-F6IM23zgTYo9gYJaNp17gVvQBt0hMIvz52OF91DpPYSLpV2h9OSlzPJ3j5TGaWueS/bc/YCV23+VojXX/MauGQ== - -turbo-linux-arm64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.4.7.tgz#c5cb63db0ab59dd2ea37be4e44efef119a289ad1" - integrity sha512-kFe5jzj3FoY6jAEwyNEswndj1t/fPl0qyxfcQv6aNPz7Nb2Lh7mY/EEse+CG3ydIo5RZKba7ppQoBSDmHx7JsA== - -turbo-linux-arm@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-linux-arm/-/turbo-linux-arm-1.4.7.tgz#93ed9e43a95760e660a42dbf65cbfd430e558e89" - integrity sha512-FTh4itdMNZ7IxGKknFnQ6iPO9vGGKqyySkCYLR01lnw6BTnKL9KuM9XUCBRyn7dNmHhAnqu1ZtVsBkH7CE7DEw== - -turbo-linux-mips64le@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-linux-mips64le/-/turbo-linux-mips64le-1.4.7.tgz#77357165c3ae0102fd5924dd85229676938dd717" - integrity sha512-756nG8dnPQVcnl9s70S4NQ43aJjpsnc2h0toktPO+9u2ayv9XTbIPvZLFsS55bDeYhodDGvxoB96W6Xnx01hyQ== - -turbo-linux-ppc64le@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.4.7.tgz#2a7399d6ee31d894d48aea393ed1f9addc4a310c" - integrity sha512-VS2ofGN/XsafNGJdZ21UguURHb7KRG879yWLj59hO1d+0xXXQbx7ljsmEPOhiE4UjEdx4Ur6P44BhztTgDx9Og== - -turbo-windows-32@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-windows-32/-/turbo-windows-32-1.4.7.tgz#e93233d8681886dc0b609c897447991afa378340" - integrity sha512-M5GkZdA0CbJAOcR8SScM63CBV+NtX7qjhoNNOl0F99nGJ+rO3dH71CcM/rbhlz9SQzKQoX8rcuwZHe4r2HZAug== - -turbo-windows-64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.4.7.tgz#da9fe6b6bf2b6fd1f85ecdc186fc7a49b8411d22" - integrity sha512-ftZUtZ1BX1vi8MbxKr+a7riIkhwvGnNTtWGprVu+aDJ8PnV+lNqbkrLJGvKP7Cn22hGTfzcjNNPcJ5PBZpQEQw== - -turbo-windows-arm64@1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-1.4.7.tgz#c60a772aab36c45ce461e3305e35d1c22a00e516" - integrity sha512-mZ79XeJFfaeVKdBV3w0eoGaqAxFnwxrme0jZtSWemAbeDSCF/13wcbLGwtq0+Lu0LxEGweeQ5AqsCIc9t9i6sA== - -turbo@latest: - version "1.4.7" - resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.4.7.tgz#859989a5dce2a7b1fa51f17ac4fb1e34dbfd455d" - integrity sha512-oIk7PAISPidDOkTM5M+ydEe5GDQ/+TahDgIbaYKeAAy2Qpmur4s0HybSDWHIdxLqI96OPD/mOKymRLrjh3Mdhg== +turbo@2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/turbo/-/turbo-2.0.9.tgz#fa0ab576c4cb9a8fc9db648e9ac9adfe10a22ae5" + integrity sha512-QaLaUL1CqblSKKPgLrFW3lZWkWG4pGBQNW+q1ScJB5v1D/nFWtsrD/yZljW/bdawg90ihi4/ftQJ3h6fz1FamA== optionalDependencies: - turbo-android-arm64 "1.4.7" - turbo-darwin-64 "1.4.7" - turbo-darwin-arm64 "1.4.7" - turbo-freebsd-64 "1.4.7" - turbo-freebsd-arm64 "1.4.7" - turbo-linux-32 "1.4.7" - turbo-linux-64 "1.4.7" - turbo-linux-arm "1.4.7" - turbo-linux-arm64 "1.4.7" - turbo-linux-mips64le "1.4.7" - turbo-linux-ppc64le "1.4.7" - turbo-windows-32 "1.4.7" - turbo-windows-64 "1.4.7" - turbo-windows-arm64 "1.4.7" + turbo-darwin-64 "2.0.9" + turbo-darwin-arm64 "2.0.9" + turbo-linux-64 "2.0.9" + turbo-linux-arm64 "2.0.9" + turbo-windows-64 "2.0.9" + turbo-windows-arm64 "2.0.9" type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -12936,6 +12885,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typescript@^4.5.5: + version "4.9.5" + resolved "https://registry.npmmirror.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + typescript@^5.3.3: version "5.3.3" resolved "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"