mirror of
https://github.com/TangSengDaoDao/TangSengDaoDaoWeb
synced 2025-06-06 09:08:59 +00:00
Merge branch 'main' of https://github.com/TangSengDaoDao/TangSengDaoDaoWeb
This commit is contained in:
commit
cbf9f5907a
3
.yarnrc
3
.yarnrc
@ -1,3 +1,2 @@
|
|||||||
registry "https://registry.npmmirror.com/"
|
registry "https://registry.npmmirror.com/"
|
||||||
|
electron_mirror "https://npmmirror.com/mirrors/electron/"
|
||||||
electron_mirror "https://registry.npmmirror.com/-/binary/electron/"
|
|
20
README.md
20
README.md
@ -2,34 +2,34 @@
|
|||||||
|
|
||||||
<a href="https://zh-hans.react.dev/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://zh-hans.react.dev/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/React-17.0.2-%236CB52D.svg?logo=React" alt="React" />
|
<img src="https://img.shields.io/badge/React-17.0.2-%236CB52D.svg?logo=React" alt="React" />
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://ts.nodejs.cn/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://ts.nodejs.cn/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/TypeScript-5.0.4-%236CB52D.svg?logo=TypeScript&logoColor=FFF" alt="TypeScript" />
|
<img src="https://img.shields.io/badge/TypeScript-5.0.4-%236CB52D.svg?logo=TypeScript&logoColor=FFF" alt="TypeScript" />
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://yarn.bootcss.com/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://yarn.bootcss.com/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/Yarn-1.22.17-%236CB52D.svg?logo=Yarn&logoColor=FFF" alt="Yarn" />
|
<img src="https://img.shields.io/badge/Yarn-1.22.17-%236CB52D.svg?logo=Yarn&logoColor=FFF" alt="Yarn" />
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://nodejs.org/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://nodejs.org/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/Node-18.17.1-%236CB52D.svg?logo=Node&logoColor=FFF" alt="Node">
|
<img src="https://img.shields.io/badge/Node-18.17.1-%236CB52D.svg?logo=Node&logoColor=FFF" alt="Node">
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://webpack.docschina.org/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://webpack.docschina.org/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/Webpack-5.88.2-%236CB52D.svg?logo=Webpack" alt="Webpack" />
|
<img src="https://img.shields.io/badge/Webpack-5.88.2-%236CB52D.svg?logo=Webpack" alt="Webpack" />
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://www.electronjs.org/zh/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://www.electronjs.org/zh/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/Electron-26.0.0-%236CB52D.svg?logo=Electron&logoColor=FFF" alt="Electron" />
|
<img src="https://img.shields.io/badge/Electron-26.0.0-%236CB52D.svg?logo=Electron&logoColor=FFF" alt="Electron" />
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://www.electron.build/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://www.electron.build/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/ElectronBuilder-24.9.1-%236CB52D.svg?logo=ElectronBuilder&logoColor=FFF" alt="ElectronBuilder" />
|
<img src="https://img.shields.io/badge/ElectronBuilder-24.9.1-%236CB52D.svg?logo=ElectronBuilder&logoColor=FFF" alt="ElectronBuilder" />
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://semi.design/zh-CN/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://semi.design/zh-CN/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/Semi UI-2.24.2-%236CB52D.svg?logo=SemiUI" alt="SemiUI">
|
<img src="https://img.shields.io/badge/Semi UI-2.24.2-%236CB52D.svg?logo=SemiUI" alt="SemiUI">
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://turbo.build/repo" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://turbo.build/repo" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/turbo-1.4.7-%236CB52D.svg?logo=Turbo&logoColor=FFF" alt="Turbo" />
|
<img src="https://img.shields.io/badge/turbo-1.4.7-%236CB52D.svg?logo=Turbo&logoColor=FFF" alt="Turbo" />
|
||||||
</a>  
|
</a>
|
||||||
<a href="https://githubim.com/" target="_blank" rel="noopener" style="display:inline-block;">
|
<a href="https://githubim.com/" target="_blank" rel="noopener" style="display:inline-block;">
|
||||||
<img src="https://img.shields.io/badge/WukongIm-1.2.10-%236CB52D.svg?logo=WukonIm" alt="Wukongim" />
|
<img src="https://img.shields.io/badge/WukongIm-1.2.10-%236CB52D.svg?logo=WukonIm" alt="Wukongim" />
|
||||||
</a>  
|
</a>
|
||||||
|
|
||||||
📚 [在线文档](https://tsdaodao.com/) | 🚀 [演示地址](https://web.botgate.cn/)(账号/密码:15900000002/a1234567)
|
📚 [在线文档](https://tsdaodao.com/) | 🚀 [演示地址](https://web.botgate.cn/)(账号/密码:15900000002/a1234567)
|
||||||
|
|
||||||
|
@ -1,70 +1,40 @@
|
|||||||
var path = require('path')
|
var path = require('path')
|
||||||
|
const { override, babelInclude, addWebpackPlugin, overrideDevServer } = require('customize-cra')
|
||||||
const { override, babelInclude, addWebpackPlugin } = require('customize-cra')
|
|
||||||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
|
|
||||||
// module.exports = override(
|
const addDevServerConfig = () => config => {
|
||||||
// // 注意是production环境启动该plugin
|
return {
|
||||||
// process.env.NODE_ENV === 'production' && addWebpackPlugin(
|
...config,
|
||||||
// new UglifyJsPlugin({
|
client: {
|
||||||
// // 开启打包缓存
|
overlay: false
|
||||||
// cache: true,
|
}
|
||||||
// // 开启多线程打包
|
};
|
||||||
// parallel: true,
|
}
|
||||||
// uglifyOptions: {
|
|
||||||
// // 删除警告
|
|
||||||
// warnings: false,
|
|
||||||
// // 压缩
|
|
||||||
// compress: {
|
|
||||||
// // 移除console
|
|
||||||
// drop_console: true,
|
|
||||||
// // 移除debugger
|
|
||||||
// drop_debugger: true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
|
|
||||||
module.exports = function (config, env) {
|
module.exports = {
|
||||||
if (process.env.NODE_ENV === 'production') {
|
webpack: function (config, env) {
|
||||||
config.devtool = false;
|
if (process.env.NODE_ENV === 'production') {
|
||||||
}
|
config.devtool = false;
|
||||||
if (env === 'production') {
|
}
|
||||||
config.optimization = {
|
if (env === 'production') {
|
||||||
minimize: true,
|
config.optimization = {
|
||||||
minimizer: [new TerserPlugin()],
|
minimize: true,
|
||||||
};
|
minimizer: [new TerserPlugin()],
|
||||||
}
|
};
|
||||||
return Object.assign(
|
}
|
||||||
config,
|
return Object.assign(
|
||||||
override(
|
config,
|
||||||
// 判断环境变量ANALYZER参数的值
|
override(
|
||||||
process.env.ANALYZER && addWebpackPlugin(new BundleAnalyzerPlugin()),
|
// 判断环境变量ANALYZER参数的值
|
||||||
// process.env.NODE_ENV === 'production' && addWebpackPlugin(
|
process.env.ANALYZER && addWebpackPlugin(new BundleAnalyzerPlugin()),
|
||||||
// new UglifyJsPlugin({
|
babelInclude([
|
||||||
// cache: true,
|
/* transpile (converting to es5) code in src/ and shared component library */
|
||||||
// // 开启多线程打包
|
path.resolve('src'),
|
||||||
// parallel: true,
|
path.resolve('../../packages'),
|
||||||
// uglifyOptions: {
|
])
|
||||||
// // 删除警告
|
)(config, env)
|
||||||
// warnings: false,
|
)
|
||||||
// // 压缩
|
},
|
||||||
// compress: {
|
devServer: overrideDevServer(addDevServerConfig())
|
||||||
// // 移除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)
|
|
||||||
)
|
|
||||||
}
|
}
|
@ -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",
|
|
||||||
},
|
|
||||||
};
|
|
58
apps/web/electron-builder.yml
Normal file
58
apps/web/electron-builder.yml
Normal file
@ -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
|
||||||
|
|
@ -55,7 +55,6 @@
|
|||||||
"customize-cra": "^1.0.0",
|
"customize-cra": "^1.0.0",
|
||||||
"electron": "26.0.0",
|
"electron": "26.0.0",
|
||||||
"electron-builder": "^24.9.1",
|
"electron-builder": "^24.9.1",
|
||||||
"electron-log": "^5.0.1",
|
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"kill-port": "^2.0.1",
|
"kill-port": "^2.0.1",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
@ -64,7 +63,7 @@
|
|||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"terser-webpack-plugin": "^5.3.9",
|
"terser-webpack-plugin": "^5.3.9",
|
||||||
"tsc-watch": "^6.0.4",
|
"tsc-watch": "^6.0.4",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^4.5.5",
|
||||||
"wait-on": "^7.2.0",
|
"wait-on": "^7.2.0",
|
||||||
"webpack-bundle-analyzer": "^4.5.0"
|
"webpack-bundle-analyzer": "^4.5.0"
|
||||||
},
|
},
|
||||||
@ -73,7 +72,7 @@
|
|||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
">0.2%",
|
"> 1%",
|
||||||
"not dead",
|
"not dead",
|
||||||
"not op_mini all"
|
"not op_mini all"
|
||||||
],
|
],
|
||||||
|
BIN
apps/web/resources/icons/icon.icns
Normal file
BIN
apps/web/resources/icons/icon.icns
Normal file
Binary file not shown.
15
package.json
15
package.json
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
|
"name": "tsdd",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*",
|
"apps/*",
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"//": "See https://github.com/facebook/create-react-app/issues/11773",
|
|
||||||
"react-error-overlay": "6.0.11"
|
"react-error-overlay": "6.0.11"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"bootstrap": "yarn install",
|
|
||||||
"dev": "turbo run dev --parallel",
|
"dev": "turbo run dev --parallel",
|
||||||
"dev-ele": "turbo run dev-ele --parallel",
|
"dev-ele": "turbo run dev-ele --parallel",
|
||||||
"build": "turbo run build",
|
"build": "turbo run build",
|
||||||
@ -18,7 +18,8 @@
|
|||||||
"build-ele:win": "turbo run build-ele:win",
|
"build-ele:win": "turbo run build-ele:win",
|
||||||
"build-ele:linux": "turbo run build-ele:linux",
|
"build-ele:linux": "turbo run build-ele:linux",
|
||||||
"build-ele:linux-arm64": "turbo run build-ele:linux-arm64",
|
"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",
|
"lint": "turbo run lint",
|
||||||
"format": "prettier --write \"**/*.{ts,tsx,md}\""
|
"format": "prettier --write \"**/*.{ts,tsx,md}\""
|
||||||
},
|
},
|
||||||
@ -27,7 +28,11 @@
|
|||||||
"eslint-config-custom": "*",
|
"eslint-config-custom": "*",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"rimraf": "^5.0.5",
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf node_modules out-election"
|
"clean": "rimraf node_modules .turbo"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/parser": "^6.16.0",
|
"@typescript-eslint/parser": "^6.16.0",
|
||||||
|
25
packages/tsdaodaobase/src/Messages/Image/index.css
Normal file
25
packages/tsdaodaobase/src/Messages/Image/index.css
Normal file
@ -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;
|
||||||
|
}
|
@ -1,124 +1,172 @@
|
|||||||
import { MediaMessageContent } from "wukongimjssdk"
|
import WKSDK, { MediaMessageContent, Task } from "wukongimjssdk";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
import WKApp from "../../App"
|
import WKApp from "../../App";
|
||||||
import { MessageContentTypeConst } from "../../Service/Const"
|
import { MessageContentTypeConst } from "../../Service/Const";
|
||||||
import MessageBase from "../Base"
|
import MessageBase from "../Base";
|
||||||
import { MessageCell } from "../MessageCell"
|
import { MessageCell } from "../MessageCell";
|
||||||
import Viewer from 'react-viewer';
|
import Viewer from "react-viewer";
|
||||||
|
import "./index.css";
|
||||||
|
|
||||||
export class ImageContent extends MediaMessageContent {
|
export class ImageContent extends MediaMessageContent {
|
||||||
width!: number
|
width!: number;
|
||||||
height!: number
|
height!: number;
|
||||||
url!: string
|
url!: string;
|
||||||
imgData?: string
|
imgData?: string;
|
||||||
constructor(file?: File, imgData?: string, width?: number, height?: number) {
|
constructor(file?: File, imgData?: string, width?: number, height?: number) {
|
||||||
super()
|
super();
|
||||||
this.file = file
|
this.file = file;
|
||||||
this.imgData = imgData
|
this.imgData = imgData;
|
||||||
this.width = width || 0
|
this.width = width || 0;
|
||||||
this.height = height || 0
|
this.height = height || 0;
|
||||||
}
|
}
|
||||||
decodeJSON(content: any) {
|
decodeJSON(content: any) {
|
||||||
this.width = content["width"] || 0
|
this.width = content["width"] || 0;
|
||||||
this.height = content["height"] || 0
|
this.height = content["height"] || 0;
|
||||||
this.url = content["url"] || ''
|
this.url = content["url"] || "";
|
||||||
this.remoteUrl = this.url
|
this.remoteUrl = this.url;
|
||||||
}
|
}
|
||||||
encodeJSON() {
|
encodeJSON() {
|
||||||
return { "width": this.width || 0, "height": this.height || 0, "url": this.remoteUrl || "" }
|
return { width: this.width || 0, height: this.height || 0, url: this.remoteUrl || "" };
|
||||||
}
|
}
|
||||||
get contentType() {
|
get contentType() {
|
||||||
return MessageContentTypeConst.image
|
return MessageContentTypeConst.image;
|
||||||
}
|
}
|
||||||
get conversationDigest() {
|
get conversationDigest() {
|
||||||
return "[图片]"
|
return "[图片]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface ImageCellState {
|
interface ImageCellState {
|
||||||
showPreview: boolean
|
showPreview: boolean;
|
||||||
|
loading: boolean;
|
||||||
|
progress: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ImageCell extends MessageCell<any, ImageCellState> {
|
export class ImageCell extends MessageCell<any, ImageCellState> {
|
||||||
|
taskListener!: any;
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
showPreview: false,
|
||||||
|
loading: false,
|
||||||
|
progress: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props: any) {
|
imageScale(orgWidth: number, orgHeight: number, maxWidth = 250, maxHeight = 250) {
|
||||||
super(props)
|
let actSize = { width: orgWidth, height: orgHeight };
|
||||||
this.state = {
|
if (orgWidth > orgHeight) {
|
||||||
showPreview: false,
|
//横图
|
||||||
|
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 (
|
||||||
|
<div style={{ position: "relative" }}>
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
src={this.getImageSrc(content)}
|
||||||
|
style={{ borderRadius: "5px", width: scaleSize.width, height: scaleSize.height }}
|
||||||
|
/>
|
||||||
|
{this.state.loading && scaleSize.width > 32 && (
|
||||||
|
<i className="loading-box">
|
||||||
|
<img className="loading-icon" src={require("../../assets/loading.png")} alt="" />
|
||||||
|
{scaleSize.height > 46 && <p className="loading-text">{this.state.progress}%</p>}
|
||||||
|
</i>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
imageScale(orgWidth: number, orgHeight: number, maxWidth = 250, maxHeight = 250) {
|
render() {
|
||||||
let actSize = { width: orgWidth, height: orgHeight };
|
const { message, context } = this.props;
|
||||||
if (orgWidth > orgHeight) {//横图
|
const { showPreview } = this.state;
|
||||||
if (orgWidth > maxWidth) { // 横图超过最大宽度
|
const content = message.content as ImageContent;
|
||||||
let rate = maxWidth / orgWidth; // 缩放比例
|
let scaleSize = this.imageScale(content.width, content.height);
|
||||||
actSize.width = maxWidth;
|
const imageURL = this.getImageSrc(content) || "";
|
||||||
actSize.height = orgHeight * rate;
|
return (
|
||||||
}
|
<MessageBase context={context} message={message}>
|
||||||
} else if (orgWidth < orgHeight) { //竖图
|
<div
|
||||||
if (orgHeight > maxHeight) {
|
style={{ width: scaleSize.width, height: scaleSize.height, cursor: "pointer" }}
|
||||||
let rate = maxHeight / orgHeight; // 缩放比例
|
onClick={() => {
|
||||||
actSize.width = orgWidth * rate;
|
this.setState({
|
||||||
actSize.height = maxHeight;
|
showPreview: !this.state.showPreview,
|
||||||
}
|
});
|
||||||
} else if (orgWidth === orgHeight) {
|
}}
|
||||||
if (orgWidth > maxWidth) {
|
>
|
||||||
let rate = maxWidth / orgWidth; // 缩放比例
|
{this.getImageElement()}
|
||||||
actSize.width = maxWidth;
|
</div>
|
||||||
actSize.height = orgHeight * rate;
|
<Viewer
|
||||||
}
|
visible={showPreview}
|
||||||
}
|
noImgDetails={true}
|
||||||
return actSize;
|
downloadable={true}
|
||||||
}
|
rotatable={false}
|
||||||
|
changeable={false}
|
||||||
getImageSrc(content: ImageContent) {
|
showTotal={false}
|
||||||
if (content.url && content.url !== "") { // 等待发送的消息
|
onMaskClick={() => {
|
||||||
let downloadURL = WKApp.dataSource.commonDataSource.getImageURL(content.url, { width: content.width, height: content.height })
|
this.setState({ showPreview: false });
|
||||||
if (downloadURL.indexOf("?") != -1) {
|
}}
|
||||||
downloadURL += "&filename=image.png"
|
onClose={() => {
|
||||||
} else {
|
this.setState({ showPreview: false });
|
||||||
downloadURL += "?filename=image.png"
|
}}
|
||||||
}
|
images={[{ src: imageURL, alt: "", downloadUrl: imageURL }]}
|
||||||
return downloadURL
|
/>
|
||||||
}
|
</MessageBase>
|
||||||
return content.imgData
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
getImageElement() {
|
|
||||||
const { message } = this.props
|
|
||||||
const content = message.content as ImageContent
|
|
||||||
let scaleSize = this.imageScale(content.width, content.height);
|
|
||||||
return <img alt="" src={this.getImageSrc(content)} style={{ borderRadius: '5px', width: scaleSize.width, height: scaleSize.height }} />
|
|
||||||
}
|
|
||||||
|
|
||||||
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 <MessageBase context={context} message={message}>
|
|
||||||
<div style={{ width: scaleSize.width, height: scaleSize.height, cursor: "pointer" }} onClick={() => {
|
|
||||||
this.setState({
|
|
||||||
showPreview: !this.state.showPreview,
|
|
||||||
})
|
|
||||||
}}>
|
|
||||||
{this.getImageElement()}
|
|
||||||
</div>
|
|
||||||
<Viewer
|
|
||||||
visible={showPreview}
|
|
||||||
noImgDetails={true}
|
|
||||||
downloadable={true}
|
|
||||||
rotatable={false}
|
|
||||||
changeable={false}
|
|
||||||
showTotal={false}
|
|
||||||
onMaskClick={() => { this.setState({ showPreview: false }); }}
|
|
||||||
onClose={() => { this.setState({ showPreview: false }); }}
|
|
||||||
images={[{ src: imageURL, alt: '', downloadUrl: imageURL }]}
|
|
||||||
/>
|
|
||||||
</MessageBase>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
BIN
packages/tsdaodaobase/src/assets/loading.png
Normal file
BIN
packages/tsdaodaobase/src/assets/loading.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
@ -5,6 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tsdaodao/base": "*",
|
"@tsdaodao/base": "*",
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
"classnames": "^2.3.1"
|
"classnames": "^2.3.1",
|
||||||
|
"react-infinite-scroller": "^1.2.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,246 +1,287 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Component } from "react";
|
import { Component } from "react";
|
||||||
import { Contacts, ContactsChangeListener, ContextMenus, ContextMenusContext, WKApp, WKBase, WKBaseContext, WKNavMainHeader, Search, UserRelation } from "@tsdaodao/base"
|
import {
|
||||||
import "./index.css"
|
Contacts,
|
||||||
|
ContactsChangeListener,
|
||||||
|
ContextMenus,
|
||||||
|
ContextMenusContext,
|
||||||
|
WKApp,
|
||||||
|
WKBase,
|
||||||
|
WKBaseContext,
|
||||||
|
WKNavMainHeader,
|
||||||
|
Search,
|
||||||
|
UserRelation,
|
||||||
|
} from "@tsdaodao/base";
|
||||||
|
import "./index.css";
|
||||||
import { toSimplized } from "@tsdaodao/base";
|
import { toSimplized } from "@tsdaodao/base";
|
||||||
import { getPinyin } from "@tsdaodao/base";
|
import { getPinyin } from "@tsdaodao/base";
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
import { Toast } from "@douyinfe/semi-ui";
|
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 { ContactsListManager } from "../Service/ContactsListManager";
|
||||||
import { Card } from "@tsdaodao/base/src/Messages/Card";
|
import { Card } from "@tsdaodao/base/src/Messages/Card";
|
||||||
import WKAvatar from "@tsdaodao/base/src/Components/WKAvatar";
|
import WKAvatar from "@tsdaodao/base/src/Components/WKAvatar";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class ContactsState {
|
export class ContactsState {
|
||||||
indexList: string[] = []
|
indexList: string[] = [];
|
||||||
indexItemMap: Map<string, Contacts[]> = new Map()
|
indexItemMap: Map<string, Contacts[]> = new Map();
|
||||||
keyword?: string
|
keyword?: string;
|
||||||
selectedItem?: Contacts // 被选中的联系人
|
selectedItem?: Contacts; // 被选中的联系人
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ContactsList extends Component<any, ContactsState> {
|
export default class ContactsList extends Component<any, ContactsState> {
|
||||||
contactsChangeListener!: ContactsChangeListener
|
contactsChangeListener!: ContactsChangeListener;
|
||||||
channelInfoListener!: ChannelInfoListener
|
channelInfoListener!: ChannelInfoListener;
|
||||||
contextMenusContext!: ContextMenusContext
|
contextMenusContext!: ContextMenusContext;
|
||||||
baseContext!: WKBaseContext
|
baseContext!: WKBaseContext;
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props)
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
indexList: [],
|
indexList: [],
|
||||||
indexItemMap: new Map()
|
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 = () => {
|
WKApp.dataSource.addContactsChangeListener(this.contactsChangeListener);
|
||||||
this.rebuildIndex()
|
|
||||||
|
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)=>{
|
return v.name.indexOf(keyword) !== -1;
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WKApp.dataSource.addContactsChangeListener(this.contactsChangeListener)
|
buildIndex(contacts: Contacts[]) {
|
||||||
|
const indexItemMap = new Map<string, Contacts[]>();
|
||||||
|
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)
|
let existItems = indexItemMap.get(indexName);
|
||||||
|
if (!existItems) {
|
||||||
ContactsListManager.shared.setRefreshList = () => {
|
existItems = [];
|
||||||
this.setState({})
|
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() {
|
_handleContextMenu(item: Contacts, event: React.MouseEvent) {
|
||||||
ContactsListManager.shared.setRefreshList = undefined
|
this.contextMenusContext.show(event);
|
||||||
WKApp.dataSource.removeContactsChangeListener(this.contactsChangeListener)
|
this.setState({
|
||||||
WKSDK.shared().channelManager.removeListener(this.channelInfoListener)
|
selectedItem: item,
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionUI(indexName: string) {
|
||||||
|
const { indexItemMap } = this.state;
|
||||||
|
const { canSelect } = this.props;
|
||||||
|
const items = indexItemMap.get(indexName);
|
||||||
|
|
||||||
rebuildIndex() {
|
return (
|
||||||
console.log("rebuildIndex---->")
|
<div key={indexName} className="wk-contacts-section">
|
||||||
this.buildIndex(this.contactsList())
|
<div className="wk-contacts-section-list">
|
||||||
}
|
{items?.map((item, i) => {
|
||||||
|
let name = item.name;
|
||||||
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<string, Contacts[]>()
|
|
||||||
let indexList = []
|
|
||||||
for (const item of contacts) {
|
|
||||||
let name = item.name
|
|
||||||
if (item.remark && item.remark !== "") {
|
if (item.remark && item.remark !== "") {
|
||||||
name = item.remark
|
name = item.remark;
|
||||||
}
|
}
|
||||||
|
return (
|
||||||
let pinyinNick = getPinyin(toSimplized(name)).toUpperCase();
|
<div
|
||||||
let indexName = !pinyinNick || /[^a-z]/i.test(pinyinNick[0]) ? "#" : pinyinNick[0];
|
key={item.uid}
|
||||||
|
className={classnames(
|
||||||
let existItems = indexItemMap.get(indexName)
|
"wk-contacts-section-item",
|
||||||
if (!existItems) {
|
WKApp.shared.openChannel?.channelType === ChannelTypePerson &&
|
||||||
existItems = []
|
WKApp.shared.openChannel?.channelID === item.uid
|
||||||
indexList.push(indexName)
|
? "wk-contacts-section-item-selected"
|
||||||
}
|
: undefined
|
||||||
existItems.push(item)
|
)}
|
||||||
indexItemMap.set(indexName, existItems)
|
onClick={() => {
|
||||||
}
|
const channel = new Channel(item.uid, ChannelTypePerson);
|
||||||
indexList = indexList.sort((a, b) => {
|
WKApp.endpoints.showConversation(channel);
|
||||||
if (a === "#") {
|
this.setState({});
|
||||||
return -1
|
}}
|
||||||
}
|
onContextMenu={(e) => {
|
||||||
if (b === "#") {
|
this._handleContextMenu(item, e);
|
||||||
return 1
|
}}
|
||||||
}
|
>
|
||||||
return a.localeCompare(b)
|
<div className="wk-contacts-section-item-index">
|
||||||
})
|
{i === 0 ? indexName : ""}
|
||||||
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 <div key={indexName} className="wk-contacts-section">
|
|
||||||
<div className="wk-contacts-section-list">
|
|
||||||
{
|
|
||||||
items?.map((item, i) => {
|
|
||||||
let name = item.name
|
|
||||||
if (item.remark && item.remark !== "") {
|
|
||||||
name = item.remark
|
|
||||||
}
|
|
||||||
return <div key={item.uid} className={classnames("wk-contacts-section-item", WKApp.shared.openChannel?.channelType === ChannelTypePerson && WKApp.shared.openChannel?.channelID === item.uid ? "wk-contacts-section-item-selected" : undefined)} onClick={() => {
|
|
||||||
const channel = new Channel(item.uid, ChannelTypePerson)
|
|
||||||
WKApp.endpoints.showConversation(channel)
|
|
||||||
this.setState({})
|
|
||||||
}} onContextMenu={(e) => {
|
|
||||||
this._handleContextMenu(item, e)
|
|
||||||
}}>
|
|
||||||
<div className="wk-contacts-section-item-index">
|
|
||||||
{i === 0 ? indexName : ""}
|
|
||||||
</div>
|
|
||||||
<div className="wk-contacts-section-item-avatar">
|
|
||||||
<WKAvatar channel={new Channel(item.uid, ChannelTypePerson)}></WKAvatar>
|
|
||||||
</div>
|
|
||||||
<div className="wk-contacts-section-item-name">
|
|
||||||
{name}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { indexList } = this.state
|
|
||||||
return <WKBase onContext={(baseCtx) => {
|
|
||||||
this.baseContext = baseCtx
|
|
||||||
}}>
|
|
||||||
<div className="wk-contacts">
|
|
||||||
<WKNavMainHeader title="联系人"></WKNavMainHeader>
|
|
||||||
<div className="wk-contacts-content">
|
|
||||||
<div className="wk-contacts-content-header">
|
|
||||||
<Search placeholder="搜索" onChange={(v) => {
|
|
||||||
this.setState({
|
|
||||||
keyword: v
|
|
||||||
}, () => {
|
|
||||||
this.rebuildIndex()
|
|
||||||
})
|
|
||||||
}}></Search>
|
|
||||||
</div>
|
|
||||||
<div className="wk-contacts-content-fnc">
|
|
||||||
{
|
|
||||||
WKApp.endpoints.contactsHeaders().map((view, i) => {
|
|
||||||
return <div key={i}>{view}</div>
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="wk-contacts-content-contacts">
|
|
||||||
{
|
|
||||||
indexList.map((indexName) => {
|
|
||||||
return this.sectionUI(indexName)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<ContextMenus onContext={(context: ContextMenusContext) => {
|
<div className="wk-contacts-section-item-avatar">
|
||||||
this.contextMenusContext = context
|
<WKAvatar
|
||||||
}} menus={[{
|
channel={new Channel(item.uid, ChannelTypePerson)}
|
||||||
title: "查看资料", onClick: () => {
|
></WKAvatar>
|
||||||
const { selectedItem } = this.state
|
</div>
|
||||||
this.baseContext.showUserInfo(selectedItem?.uid || "")
|
<div className="wk-contacts-section-item-name">{name}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { indexList } = this.state;
|
||||||
|
return (
|
||||||
|
<WKBase
|
||||||
|
onContext={(baseCtx) => {
|
||||||
|
this.baseContext = baseCtx;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="wk-contacts">
|
||||||
|
<WKNavMainHeader title="联系人"></WKNavMainHeader>
|
||||||
|
<div className="wk-contacts-content">
|
||||||
|
<div className="wk-contacts-content-header">
|
||||||
|
<Search
|
||||||
|
placeholder="搜索"
|
||||||
|
onChange={(v) => {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
keyword: v,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.rebuildIndex();
|
||||||
}
|
}
|
||||||
}, {
|
);
|
||||||
title: "分享给朋友...", onClick: () => {
|
}}
|
||||||
WKApp.shared.baseContext.showConversationSelect((channels: Channel[]) => {
|
></Search>
|
||||||
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("分享成功!")
|
|
||||||
}
|
|
||||||
}, "分享名片")
|
|
||||||
}
|
|
||||||
}]} />
|
|
||||||
</div>
|
</div>
|
||||||
</WKBase>
|
<div className="wk-contacts-content-fnc">
|
||||||
}
|
{WKApp.endpoints.contactsHeaders().map((view, i) => {
|
||||||
}
|
return <div key={i}>{view}</div>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="wk-contacts-content-contacts">
|
||||||
|
{indexList.map((indexName) => {
|
||||||
|
return this.sectionUI(indexName);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ContextMenus
|
||||||
|
onContext={(context: ContextMenusContext) => {
|
||||||
|
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("分享成功!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"分享名片"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</WKBase>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,81 +1,98 @@
|
|||||||
import { WKApp, WKViewQueueHeader, QRCodeMy, Search } from "@tsdaodao/base";
|
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 React from "react";
|
||||||
import { Component, ReactNode } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { Spin,Toast } from '@douyinfe/semi-ui';
|
import { Spin, Toast } from "@douyinfe/semi-ui";
|
||||||
import "./index.css"
|
import "./index.css";
|
||||||
|
|
||||||
export interface FriendAddProps {
|
export interface FriendAddProps {
|
||||||
onBack?: () => void
|
onBack?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FriendAddState {
|
export class FriendAddState {
|
||||||
spinning!:boolean
|
spinning!: boolean;
|
||||||
keyword?:string
|
keyword?: string;
|
||||||
result?:any
|
result?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FriendAdd extends Component<FriendAddProps,FriendAddState> {
|
export class FriendAdd extends Component<FriendAddProps, FriendAddState> {
|
||||||
baseContext!:WKBaseContext
|
baseContext!: WKBaseContext;
|
||||||
constructor(props:any) {
|
constructor(props: any) {
|
||||||
super(props)
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
spinning: false,
|
spinning: false,
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async searchUser() {
|
||||||
|
const { keyword } = this.state;
|
||||||
|
if (!keyword) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchUser() {
|
this.setState({
|
||||||
const { keyword } = this.state
|
spinning: true,
|
||||||
if(!keyword) {
|
});
|
||||||
return
|
const result = await WKApp.dataSource.commonDataSource
|
||||||
}
|
.searchUser(keyword)
|
||||||
|
.catch((err) => {
|
||||||
this.setState({
|
Toast.error(err.msg);
|
||||||
spinning: true,
|
});
|
||||||
})
|
if (result) {
|
||||||
const result = await WKApp.dataSource.commonDataSource.searchUser(keyword).catch((err)=>{
|
this.setState({
|
||||||
Toast.error(err.msg)
|
result: result,
|
||||||
})
|
spinning: false,
|
||||||
if(result) {
|
});
|
||||||
this.setState({
|
if (result.exist !== 1) {
|
||||||
result: result,
|
Toast.error("用户不存在!");
|
||||||
spinning: false,
|
} else {
|
||||||
})
|
WKApp.shared.baseContext.showUserInfo(
|
||||||
if(result.exist !== 1) {
|
result.data.uid,
|
||||||
Toast.error("用户不存在!")
|
undefined,
|
||||||
}else {
|
result.data.vercode
|
||||||
WKApp.shared.baseContext.showUserInfo(result.data.uid,undefined,result.data.vercode)
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
render(): ReactNode {
|
|
||||||
const { onBack } = this.props
|
|
||||||
const { spinning } = this.state
|
|
||||||
return <WKBase onContext={(ctx)=>{
|
|
||||||
this.baseContext = ctx
|
|
||||||
}}>
|
|
||||||
<div className="wk-friendadd">
|
|
||||||
<WKViewQueueHeader title="添加好友" onBack={onBack} />
|
|
||||||
<div className="wk-friendadd-content">
|
|
||||||
<Spin spinning={spinning}>
|
|
||||||
<Search placeholder={`${WKApp.config.appName}号/手机号`} onChange={(v)=>{
|
|
||||||
this.setState({
|
|
||||||
keyword: v
|
|
||||||
})
|
|
||||||
}} onEnterPress={()=>{
|
|
||||||
this.searchUser()
|
|
||||||
}}></Search>
|
|
||||||
</Spin>
|
|
||||||
<div className="wk-friendadd-content-qrcode">
|
|
||||||
我的{WKApp.config.appName}号:{WKApp.loginInfo.shortNo} <img onClick={()=>{
|
|
||||||
WKApp.routeLeft.push(<QRCodeMy></QRCodeMy>)
|
|
||||||
}} src={require("./assets/icon_qrcode.png")}></img>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</WKBase>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render(): ReactNode {
|
||||||
|
const { onBack } = this.props;
|
||||||
|
const { spinning } = this.state;
|
||||||
|
return (
|
||||||
|
<WKBase
|
||||||
|
onContext={(ctx) => {
|
||||||
|
this.baseContext = ctx;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="wk-friendadd">
|
||||||
|
<WKViewQueueHeader title="添加好友" onBack={onBack} />
|
||||||
|
<div className="wk-friendadd-content">
|
||||||
|
<Spin spinning={spinning}>
|
||||||
|
<Search
|
||||||
|
placeholder={`${WKApp.config.appName}号/手机号`}
|
||||||
|
onChange={(v) => {
|
||||||
|
this.setState({
|
||||||
|
keyword: v,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onEnterPress={() => {
|
||||||
|
this.searchUser();
|
||||||
|
}}
|
||||||
|
></Search>
|
||||||
|
</Spin>
|
||||||
|
<div className="wk-friendadd-content-qrcode">
|
||||||
|
我的{WKApp.config.appName}号:{WKApp.loginInfo.shortNo}{" "}
|
||||||
|
<img
|
||||||
|
onClick={() => {
|
||||||
|
WKApp.routeLeft.push(<QRCodeMy></QRCodeMy>);
|
||||||
|
}}
|
||||||
|
src={require("./assets/icon_qrcode.png")}
|
||||||
|
></img>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WKBase>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
.wk-newfriend-content {
|
.wk-newfriend-content {
|
||||||
height: calc(100% - var( --wk-height-viewqueueheader));
|
height: calc(100% - var( --wk-height-viewqueueheader));
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wk-newfriend-content li {
|
.wk-newfriend-content li {
|
||||||
|
@ -1,58 +1,130 @@
|
|||||||
import { FriendApplyState, WKApp, WKViewQueueHeader, Provider } from "@tsdaodao/base";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import {
|
||||||
|
FriendApply,
|
||||||
|
FriendApplyState,
|
||||||
|
WKApp,
|
||||||
|
ContextMenus,
|
||||||
|
ContextMenusContext,
|
||||||
|
WKViewQueueHeader,
|
||||||
|
Provider,
|
||||||
|
} from "@tsdaodao/base";
|
||||||
import { Component, ReactNode } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { Button } from '@douyinfe/semi-ui';
|
import { Button } from "@douyinfe/semi-ui";
|
||||||
import "./index.css"
|
|
||||||
import { NewFriendVM } from "./vm";
|
import { NewFriendVM } from "./vm";
|
||||||
import "./index.css"
|
|
||||||
import { FriendAdd } from "../FriendAdd";
|
import { FriendAdd } from "../FriendAdd";
|
||||||
|
import "./index.css";
|
||||||
|
|
||||||
export class NewFriend extends Component {
|
export class NewFriendState {
|
||||||
|
selectedItem?: FriendApply; // 被选中的好友
|
||||||
|
}
|
||||||
|
|
||||||
render(): ReactNode {
|
export class NewFriend extends Component<any, NewFriendState> {
|
||||||
return <Provider create={() => {
|
contextMenusContext!: ContextMenusContext;
|
||||||
return new NewFriendVM()
|
|
||||||
}} render={(vm: NewFriendVM) => {
|
|
||||||
|
|
||||||
return <div className="wk-newfriend">
|
constructor(props: any) {
|
||||||
<WKViewQueueHeader title="新朋友" onBack={() => {
|
super(props);
|
||||||
WKApp.routeLeft.pop()
|
}
|
||||||
}} action={<div className="wk-viewqueueheader-content-action">
|
|
||||||
<Button size="small" onClick={()=>{
|
_handleContextMenu(item: FriendApply, event: React.MouseEvent) {
|
||||||
WKApp.routeLeft.push(<FriendAdd onBack={()=>{
|
console.log(item);
|
||||||
WKApp.routeLeft.pop()
|
this.contextMenusContext.show(event);
|
||||||
}}></FriendAdd>)
|
this.setState({
|
||||||
}} >添加好友</Button>
|
selectedItem: item,
|
||||||
</div>}></WKViewQueueHeader>
|
});
|
||||||
<div className="wk-newfriend-content">
|
}
|
||||||
<ul>
|
render(): ReactNode {
|
||||||
{
|
return (
|
||||||
vm.friendApplys.map((f) => {
|
<Provider
|
||||||
return <li key={f.to_uid} >
|
create={() => {
|
||||||
<div className="wk-newfriend-content-avatar">
|
return new NewFriendVM();
|
||||||
<img src={WKApp.shared.avatarUser(f.to_uid)}></img>
|
}}
|
||||||
</div>
|
render={(vm: NewFriendVM) => {
|
||||||
<div className="wk-newfriend-content-title">
|
return (
|
||||||
<div className="wk-newfriend-content-title-name">
|
<div className="wk-newfriend">
|
||||||
{f.to_name}
|
<WKViewQueueHeader
|
||||||
</div>
|
title="新朋友"
|
||||||
<div className="wk-newfriend-content-title-remark">
|
onBack={() => {
|
||||||
{f.remark}
|
WKApp.routeLeft.pop();
|
||||||
</div>
|
}}
|
||||||
</div>
|
action={
|
||||||
<div className="wk-newfriend-content-action">
|
<div className="wk-viewqueueheader-content-action">
|
||||||
<Button loading={vm.currentFriendApply?.to_uid === f.to_uid && vm.sureLoading } disabled={f.status == FriendApplyState.accepted} onClick={()=>{
|
<Button
|
||||||
vm.friendSure(f)
|
size="small"
|
||||||
}}>{f.status == FriendApplyState.accepted ? "已添加" : "确认"}</Button>
|
onClick={() => {
|
||||||
</div>
|
WKApp.routeLeft.push(
|
||||||
</li>
|
<FriendAdd
|
||||||
})
|
onBack={() => {
|
||||||
}
|
WKApp.routeLeft.pop();
|
||||||
</ul>
|
}}
|
||||||
</div>
|
></FriendAdd>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加好友
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
></WKViewQueueHeader>
|
||||||
|
<div className="wk-newfriend-content">
|
||||||
|
<ul>
|
||||||
|
{vm.friendApplys.map((f) => {
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={f.to_uid}
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
this._handleContextMenu(f, e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="wk-newfriend-content-avatar">
|
||||||
|
<img src={WKApp.shared.avatarUser(f.to_uid)}></img>
|
||||||
|
</div>
|
||||||
|
<div className="wk-newfriend-content-title">
|
||||||
|
<div className="wk-newfriend-content-title-name">
|
||||||
|
{f.to_name}
|
||||||
|
</div>
|
||||||
|
<div className="wk-newfriend-content-title-remark">
|
||||||
|
{f.remark}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="wk-newfriend-content-action">
|
||||||
|
<Button
|
||||||
|
loading={
|
||||||
|
vm.currentFriendApply?.to_uid === f.to_uid &&
|
||||||
|
vm.sureLoading
|
||||||
|
}
|
||||||
|
disabled={f.status == FriendApplyState.accepted}
|
||||||
|
onClick={() => {
|
||||||
|
vm.friendSure(f);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{f.status == FriendApplyState.accepted
|
||||||
|
? "已添加"
|
||||||
|
: "确认"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<ContextMenus
|
||||||
|
onContext={(context: ContextMenusContext) => {
|
||||||
|
this.contextMenusContext = context;
|
||||||
|
}}
|
||||||
|
menus={[
|
||||||
|
{
|
||||||
|
title: "删除",
|
||||||
|
onClick: () => {
|
||||||
|
const { selectedItem } = this.state;
|
||||||
|
selectedItem && vm.delFriendApply(selectedItem);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
}}>
|
);
|
||||||
|
}}
|
||||||
</Provider>
|
></Provider>
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -18,10 +18,13 @@ export class MediaMessageUploadTask extends MessageTask {
|
|||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
const mediaContent = this.message.content as MediaMessageContent
|
const mediaContent = this.message.content as MediaMessageContent
|
||||||
if(mediaContent.file) {
|
if(mediaContent.file) {
|
||||||
|
const fileNameSuffix = mediaContent.file.name.substring(
|
||||||
|
mediaContent.file.name.lastIndexOf(".")
|
||||||
|
);
|
||||||
const param = new FormData();
|
const param = new FormData();
|
||||||
param.append("file", mediaContent.file);
|
param.append("file", mediaContent.file);
|
||||||
const fileName = this.getUUID();
|
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)
|
const uploadURL = await this.getUploadURL(path)
|
||||||
if(uploadURL) {
|
if(uploadURL) {
|
||||||
this.uploadFile(mediaContent.file,uploadURL)
|
this.uploadFile(mediaContent.file,uploadURL)
|
||||||
@ -52,7 +55,7 @@ export class MediaMessageUploadTask extends MessageTask {
|
|||||||
this.canceler = c
|
this.canceler = c
|
||||||
}),
|
}),
|
||||||
onUploadProgress: e => {
|
onUploadProgress: e => {
|
||||||
var completeProgress = ((e.loaded / e.total) | 0);
|
var completeProgress = ((e.loaded / e.total) || 0);
|
||||||
this._progress = completeProgress
|
this._progress = completeProgress
|
||||||
this.update()
|
this.update()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://turborepo.org/schema.json",
|
"$schema": "https://turborepo.org/schema.json",
|
||||||
"pipeline": {
|
"tasks": {
|
||||||
"dev": {
|
"dev": {
|
||||||
"cache": false
|
"cache": false
|
||||||
},
|
},
|
||||||
@ -37,5 +37,6 @@
|
|||||||
"clean": {
|
"clean": {
|
||||||
"dependsOn": ["^clean"]
|
"dependsOn": ["^clean"]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"ui": "stream"
|
||||||
}
|
}
|
||||||
|
148
yarn.lock
148
yarn.lock
@ -5046,20 +5046,10 @@ caniuse-api@^3.0.0:
|
|||||||
lodash.memoize "^4.1.2"
|
lodash.memoize "^4.1.2"
|
||||||
lodash.uniq "^4.5.0"
|
lodash.uniq "^4.5.0"
|
||||||
|
|
||||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400:
|
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001517, caniuse-lite@^1.0.30001520:
|
||||||
version "1.0.30001495"
|
version "1.0.30001643"
|
||||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz"
|
resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz"
|
||||||
integrity sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==
|
integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==
|
||||||
|
|
||||||
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==
|
|
||||||
|
|
||||||
case-sensitive-paths-webpack-plugin@^2.4.0:
|
case-sensitive-paths-webpack-plugin@^2.4.0:
|
||||||
version "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:
|
react-error-overlay@6.0.11, react-error-overlay@^6.0.11:
|
||||||
version "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==
|
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:
|
react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.4:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
@ -12753,95 +12750,47 @@ tsutils@^3.21.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^1.8.1"
|
tslib "^1.8.1"
|
||||||
|
|
||||||
turbo-android-arm64@1.4.7:
|
turbo-darwin-64@2.0.9:
|
||||||
version "1.4.7"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/turbo-android-arm64/-/turbo-android-arm64-1.4.7.tgz#553f68a1f475495549fb8a260461239c90f40410"
|
resolved "https://registry.npmmirror.com/turbo-darwin-64/-/turbo-darwin-64-2.0.9.tgz#dc7bb92060a41b92155195dba5850c9669fa765a"
|
||||||
integrity sha512-BtWtH8e8w1GhtYpGQmkcDS/AUzVZhQ4ZZN+qtUFei1wZD7VAdtJ9Wcsfi3WD+mXA6vtpIpRJVfQMcShr8l8ErA==
|
integrity sha512-owlGsOaExuVGBUfrnJwjkL1BWlvefjSKczEAcpLx4BI7Oh6ttakOi+JyomkPkFlYElRpjbvlR2gP8WIn6M/+xQ==
|
||||||
|
|
||||||
turbo-darwin-64@1.4.7:
|
turbo-darwin-arm64@2.0.9:
|
||||||
version "1.4.7"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.4.7.tgz#c23e2452a01115136e631dc06aa6a9bb379d2d32"
|
resolved "https://registry.npmmirror.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.0.9.tgz#6e5ce2c0f03999c6ec0116d5525841107da3078b"
|
||||||
integrity sha512-bMvZaAz5diec9feZ0XpQosYI8U0kiOQM2tj2sv0Y2WZbe227wodVMCQMyUowmcotO8nr6NF76Xo5E+H+dnY6LQ==
|
integrity sha512-XAXkKkePth5ZPPE/9G9tTnPQx0C8UTkGWmNGYkpmGgRr8NedW+HrPsi9N0HcjzzIH9A4TpNYvtiV+WcwdaEjKA==
|
||||||
|
|
||||||
turbo-darwin-arm64@1.4.7:
|
turbo-linux-64@2.0.9:
|
||||||
version "1.4.7"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.4.7.tgz#4212917f4892159033cfa88bafa662f6e865fe49"
|
resolved "https://registry.npmmirror.com/turbo-linux-64/-/turbo-linux-64-2.0.9.tgz#e00e5e1b1cffab23c58888e7c397e108dc24fe2f"
|
||||||
integrity sha512-AyfxYfKgh1EigQKjypbnDoMLuy4e/n/go+KYiWKKIpOaWXWLBokrBWzYN/aI3NMDRUJWK5ExdlWI9Nleelq8uQ==
|
integrity sha512-l9wSgEjrCFM1aG16zItBsZ206ZlhSSx1owB8Cgskfv0XyIXRGHRkluihiaxkp+UeU5WoEfz4EN5toc+ICA0q0w==
|
||||||
|
|
||||||
turbo-freebsd-64@1.4.7:
|
turbo-linux-arm64@2.0.9:
|
||||||
version "1.4.7"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.4.7.tgz#7d60d44a623bd000f53673a0db0205a16d8815e6"
|
resolved "https://registry.npmmirror.com/turbo-linux-arm64/-/turbo-linux-arm64-2.0.9.tgz#d240e4f0a784d03f1a79fd9e6c4e83abd9aa57c7"
|
||||||
integrity sha512-T5/osfbCh0rL53MFS5byFFfsR3vPMHIKIJ4fMMCNkoHsmFj2R0Pv53nqhEItogt0FJwCDHPyt7oBqO83H/AWQQ==
|
integrity sha512-gRnjxXRne18B27SwxXMqL3fJu7jw/8kBrOBTBNRSmZZiG1Uu3nbnP7b4lgrA/bCku6C0Wligwqurvtpq6+nFHA==
|
||||||
|
|
||||||
turbo-freebsd-arm64@1.4.7:
|
turbo-windows-64@2.0.9:
|
||||||
version "1.4.7"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.4.7.tgz#35e5b23313d42aab074e69c1d1c44cab17f438ac"
|
resolved "https://registry.npmmirror.com/turbo-windows-64/-/turbo-windows-64-2.0.9.tgz#d52835302e722cc7de670b90aca55ce2b3516879"
|
||||||
integrity sha512-PL+SaO78AUCas+YKj01UiS2rpmGcxz8XPmLdFWmq6PYjPX6GL5UBAc3pkBphIm0aTLZtsikoEul+JrwAuAy6UA==
|
integrity sha512-ZVo0apxUvaRq4Vm1qhsfqKKhtRgReYlBVf9MQvVU1O9AoyydEQvLDO1ryqpXDZWpcHoFxHAQc9msjAMtE5K2lA==
|
||||||
|
|
||||||
turbo-linux-32@1.4.7:
|
turbo-windows-arm64@2.0.9:
|
||||||
version "1.4.7"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.4.7.tgz#2861539d767cdfca058224f284991d918d7b1965"
|
resolved "https://registry.npmmirror.com/turbo-windows-arm64/-/turbo-windows-arm64-2.0.9.tgz#45f0aa685514ec1cc753a559924e003b22b24bb7"
|
||||||
integrity sha512-dK94UwDzySMALoQtjBVVPbWJZP6xw3yHGuytM3q5p4kfMZPSA+rgNBn5T5Af2Rc7jxlLAsu5ODJ0SgIbWSF5Hg==
|
integrity sha512-sGRz7c5Pey6y7y9OKi8ypbWNuIRPF9y8xcMqL56OZifSUSo+X2EOsOleR9MKxQXVaqHPGOUKWsE6y8hxBi9pag==
|
||||||
|
|
||||||
turbo-linux-64@1.4.7:
|
turbo@2.0.9:
|
||||||
version "1.4.7"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.4.7.tgz#5ff0e648a1d0b0053ad2f3c6a4fc735744cadc16"
|
resolved "https://registry.npmmirror.com/turbo/-/turbo-2.0.9.tgz#fa0ab576c4cb9a8fc9db648e9ac9adfe10a22ae5"
|
||||||
integrity sha512-F6IM23zgTYo9gYJaNp17gVvQBt0hMIvz52OF91DpPYSLpV2h9OSlzPJ3j5TGaWueS/bc/YCV23+VojXX/MauGQ==
|
integrity sha512-QaLaUL1CqblSKKPgLrFW3lZWkWG4pGBQNW+q1ScJB5v1D/nFWtsrD/yZljW/bdawg90ihi4/ftQJ3h6fz1FamA==
|
||||||
|
|
||||||
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==
|
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
turbo-android-arm64 "1.4.7"
|
turbo-darwin-64 "2.0.9"
|
||||||
turbo-darwin-64 "1.4.7"
|
turbo-darwin-arm64 "2.0.9"
|
||||||
turbo-darwin-arm64 "1.4.7"
|
turbo-linux-64 "2.0.9"
|
||||||
turbo-freebsd-64 "1.4.7"
|
turbo-linux-arm64 "2.0.9"
|
||||||
turbo-freebsd-arm64 "1.4.7"
|
turbo-windows-64 "2.0.9"
|
||||||
turbo-linux-32 "1.4.7"
|
turbo-windows-arm64 "2.0.9"
|
||||||
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"
|
|
||||||
|
|
||||||
type-check@^0.4.0, type-check@~0.4.0:
|
type-check@^0.4.0, type-check@~0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
@ -12936,6 +12885,11 @@ typedarray-to-buffer@^3.1.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-typedarray "^1.0.0"
|
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:
|
typescript@^5.3.3:
|
||||||
version "5.3.3"
|
version "5.3.3"
|
||||||
resolved "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
|
resolved "https://registry.npmmirror.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user