mirror of
https://github.com/TangSengDaoDao/TangSengDaoDaoWeb
synced 2025-06-05 00:28:47 +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/"
|
||||
|
||||
electron_mirror "https://registry.npmmirror.com/-/binary/electron/"
|
||||
electron_mirror "https://npmmirror.com/mirrors/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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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;">
|
||||
<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)
|
||||
|
||||
|
@ -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())
|
||||
}
|
@ -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",
|
||||
"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"
|
||||
],
|
||||
|
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,
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
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 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<any, ImageCellState> {
|
||||
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 (
|
||||
<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) {
|
||||
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 <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>
|
||||
}
|
||||
}
|
||||
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": {
|
||||
"@tsdaodao/base": "*",
|
||||
"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 { 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<string, Contacts[]> = new Map()
|
||||
keyword?: string
|
||||
selectedItem?: Contacts // 被选中的联系人
|
||||
indexList: string[] = [];
|
||||
indexItemMap: Map<string, Contacts[]> = new Map();
|
||||
keyword?: string;
|
||||
selectedItem?: Contacts; // 被选中的联系人
|
||||
}
|
||||
|
||||
export default class ContactsList extends Component<any, ContactsState> {
|
||||
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<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)
|
||||
|
||||
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<string, Contacts[]>()
|
||||
let indexList = []
|
||||
for (const item of contacts) {
|
||||
let name = item.name
|
||||
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
|
||||
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 <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>
|
||||
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>
|
||||
<ContextMenus onContext={(context: ContextMenusContext) => {
|
||||
this.contextMenusContext = context
|
||||
}} menus={[{
|
||||
title: "查看资料", onClick: () => {
|
||||
const { selectedItem } = this.state
|
||||
this.baseContext.showUserInfo(selectedItem?.uid || "")
|
||||
<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();
|
||||
}
|
||||
}, {
|
||||
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("分享成功!")
|
||||
}
|
||||
}, "分享名片")
|
||||
}
|
||||
}]} />
|
||||
);
|
||||
}}
|
||||
></Search>
|
||||
</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 {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<FriendAddProps,FriendAddState> {
|
||||
baseContext!:WKBaseContext
|
||||
constructor(props:any) {
|
||||
super(props)
|
||||
export class FriendAdd extends Component<FriendAddProps, FriendAddState> {
|
||||
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 <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 {
|
||||
height: calc(100% - var( --wk-height-viewqueueheader));
|
||||
width: 100%;
|
||||
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.wk-newfriend-content li {
|
||||
|
@ -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 <Provider create={() => {
|
||||
return new NewFriendVM()
|
||||
}} render={(vm: NewFriendVM) => {
|
||||
export class NewFriend extends Component<any, NewFriendState> {
|
||||
contextMenusContext!: ContextMenusContext;
|
||||
|
||||
return <div className="wk-newfriend">
|
||||
<WKViewQueueHeader title="新朋友" onBack={() => {
|
||||
WKApp.routeLeft.pop()
|
||||
}} action={<div className="wk-viewqueueheader-content-action">
|
||||
<Button size="small" onClick={()=>{
|
||||
WKApp.routeLeft.push(<FriendAdd onBack={()=>{
|
||||
WKApp.routeLeft.pop()
|
||||
}}></FriendAdd>)
|
||||
}} >添加好友</Button>
|
||||
</div>}></WKViewQueueHeader>
|
||||
<div className="wk-newfriend-content">
|
||||
<ul>
|
||||
{
|
||||
vm.friendApplys.map((f) => {
|
||||
return <li key={f.to_uid} >
|
||||
<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>
|
||||
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 (
|
||||
<Provider
|
||||
create={() => {
|
||||
return new NewFriendVM();
|
||||
}}
|
||||
render={(vm: NewFriendVM) => {
|
||||
return (
|
||||
<div className="wk-newfriend">
|
||||
<WKViewQueueHeader
|
||||
title="新朋友"
|
||||
onBack={() => {
|
||||
WKApp.routeLeft.pop();
|
||||
}}
|
||||
action={
|
||||
<div className="wk-viewqueueheader-content-action">
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {
|
||||
WKApp.routeLeft.push(
|
||||
<FriendAdd
|
||||
onBack={() => {
|
||||
WKApp.routeLeft.pop();
|
||||
}}
|
||||
></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>
|
||||
}}>
|
||||
|
||||
</Provider>
|
||||
}
|
||||
}
|
||||
);
|
||||
}}
|
||||
></Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,13 @@ export class MediaMessageUploadTask extends MessageTask {
|
||||
async start(): Promise<void> {
|
||||
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()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://turborepo.org/schema.json",
|
||||
"pipeline": {
|
||||
"tasks": {
|
||||
"dev": {
|
||||
"cache": false
|
||||
},
|
||||
@ -37,5 +37,6 @@
|
||||
"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.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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user