2023-07-26 19:47:44 +08:00

591 lines
19 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { EndpointCommon } from "./EndpointCommon";
import APIClient from "./Service/APIClient";
import MenusManager from "./Service/Menus";
import { EndpointManager, IModule, ModuleManager } from "./Service/Module";
import { ProviderListener } from "./Service/Provider";
import RouteManager, { ContextRouteManager } from "./Service/Route";
import { Channel, ChannelTypeGroup, ChannelTypePerson, WKSDK, Message, MessageContentType } from "wukongimjssdk";
import { IConversationProvider } from "./Service/DataSource/DataProvider";
import MessageManager from "./Service/MessageManager";
import { DefaultEmojiService, EmojiService } from "./Service/EmojiService";
import SectionManager, { Row, Section } from "./Service/Section";
import { EndpointCategory } from "./Service/Const";
import { DataSource } from "./Service/DataSource/DataSource";
import { ConnectAddrCallback } from "wukongimjssdk";
import 'animate.css';
import "./App.css"
import RouteContext from "./Service/Context";
import { ConnectStatus } from "wukongimjssdk";
import { WKBaseContext } from "./Components/WKBase";
import StorageService from "./Service/StorageService";
import axios from "axios";
export enum ThemeMode {
light,
dark
}
export class WKConfig {
appName: string = "唐僧叨叨"
appVersion: string = "0.0.0" // app版本
themeColor: string = "#E46342" // 主题颜色
secondColor: string = "rgba(232, 234, 237)"
pageSize: number = 15 // 数据页大小
pageSizeOfMessage: number = 30 // 每次请求消息数量
fileHelperUID: string = "fileHelper" // 文件助手UID
systemUID: string = "u_10000" // 系统uid
private _themeMode: ThemeMode = ThemeMode.light // 主题模式
set themeMode(v: ThemeMode) {
this._themeMode = v
const body = document.body;
if (v === ThemeMode.dark) {
if (body.hasAttribute('theme-mode')) {
body.removeAttribute('theme-mode');
body.setAttribute('theme-mode', 'dark');
} else {
body.setAttribute('theme-mode', 'dark');
}
} else {
body.removeAttribute('theme-mode');
}
StorageService.shared.setItem("theme-mode", `${v}`)
WKApp.shared.notifyListener()
}
get themeMode() {
return this._themeMode
}
}
export class WKRemoteConfig {
revokeSecond: number = 2 * 60 // 撤回时间
requestSuccess: boolean = false
async startRequestConfig() {
await this.requestConfig()
if (!this.requestSuccess) {
setTimeout(() => {
this.startRequestConfig()
}, 3000);
}
}
requestConfig() {
return WKApp.apiClient.get("common/appconfig").then((result) => {
this.requestSuccess = true
this.revokeSecond = result["revoke_second"]
})
}
}
export type MessageDeleteListener = (message: Message, preMessage?: Message) => void;
export class LoginInfo {
appID!: string
shortNo!: string // 短号
token?: string
uid?: string
name: string | undefined
role!: string
isWork!: boolean
sex!: number
/**
* save 保存登录信息
*/
public save() {
this.setStorageItemForSID("app_id", this.appID ?? "")
this.setStorageItemForSID("short_no", this.shortNo ?? "")
this.setStorageItemForSID("uid", this.uid ?? "");
this.setStorageItemForSID("token", this.token ?? "");
this.setStorageItemForSID("name", this.name ?? "");
this.setStorageItemForSID("role", this.role ?? "")
this.setStorageItemForSID("is_work", this.isWork ? "1" : "0")
this.setStorageItemForSID("sex", this.sex == 1 ? "1" : "0")
}
// 获取查询参数
public getQueryVariable(variable: string) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] === variable) { return pair[1]; }
}
return (false);
}
public setStorageItemForSID(key: string, value: string) {
let sid = this.getSID()
this.setStorageItem(key + sid, value)
}
public getStorageItemForSID(key: string): string | null {
let sid = this.getSID()
return this.getStorageItem(key + sid)
}
public removeStorageItemForSID(key: string) {
let sid = this.getSID()
this.removeStorageItem(key + sid)
}
public getSID(): string {
let sid = this.getQueryVariable("sid") || "";
return sid
}
public setStorageItem(key: string, value: string) {
StorageService.shared.setItem(key, value)
}
public getStorageItem(key: string): string | null {
return StorageService.shared.getItem(key)
}
public removeStorageItem(key: string) {
StorageService.shared.removeItem(key)
}
/**
* load 加载登录信息
*/
public load() {
this.uid = this.getStorageItemForSID('uid') || '';
this.shortNo = this.getStorageItemForSID('short_no') || '';
this.token = this.getStorageItemForSID('token') || '';
this.name = this.getStorageItemForSID("name") || "";
this.appID = this.getStorageItemForSID("app_id") || '';
this.role = this.getStorageItemForSID("role") || ''
const isWorkStr = this.getStorageItemForSID("is_work")
if (isWorkStr === "1") {
this.isWork = true
} else {
this.isWork = false
}
const sexStr = this.getStorageItemForSID("sex")
if (sexStr === "1") {
this.sex = 1
} else {
this.sex = 0
}
}
// 是否登录
isLogined() {
if (!this.token || this.token === '') {
return false
}
return true
}
logout() {
this.token = undefined;
this.appID = "";
this.role = ""
this.removeStorageItem('token');
this.removeStorageItem('app_id')
this.removeStorageItem('role')
this.removeStorageItem('is_work')
}
}
export default class WKApp extends ProviderListener {
private constructor() {
super()
}
public static shared = new WKApp()
static route = RouteManager.shared // 路由管理
static routeLeft = new ContextRouteManager() // 左边页面路由
static routeRight = new ContextRouteManager() // 右边main页面路由
static menus = MenusManager.shared // 菜单
static apiClient = APIClient.shared // api客户端
static config: WKConfig = new WKConfig() // app配置
static remoteConfig: WKRemoteConfig = new WKRemoteConfig() // 远程配置
static loginInfo: LoginInfo = new LoginInfo() // 登录信息
static endpoints: EndpointCommon = new EndpointCommon() // 常用端点
static conversationProvider: IConversationProvider // 最近会话相关数据源
static messageManager: MessageManager = new MessageManager() // 消息管理
static emojiService: EmojiService = DefaultEmojiService.shared // emoji
static sectionManager: SectionManager = new SectionManager() // section管理
static dataSource: DataSource = new DataSource() // 数据源
static endpointManager: EndpointManager = EndpointManager.shared // 端点管理
private messageDeleteListeners: MessageDeleteListener[] = new Array<MessageDeleteListener>(); // 消息删除监听
supportFavorites = [MessageContentType.text, MessageContentType.image] // 注册收藏的消息
notSupportForward: number[] = [] // 不支持转发的消息
openChannel?: Channel // 当前打开的会话频道
content?: JSX.Element
baseContext!: WKBaseContext // 唐僧叨叨基础上下文
private _notificationIsClose: boolean = false // 通知是否关闭
private wsaddrs = new Array<string>() // ws的连接地址
private addrUsed = false // 地址是否被使用
set notificationIsClose(v: boolean) {
this._notificationIsClose = v
StorageService.shared.setItem("NotificationIsClose", v ? "1" : "")
}
get notificationIsClose() {
return this._notificationIsClose
}
// app启动
startup() {
WKApp.loginInfo.load() // 加载登录信息
const themeMode = StorageService.shared.getItem("theme-mode")
if (themeMode === "1") {
WKApp.config.themeMode = ThemeMode.dark
}
WKSDK.shared().config.provider.connectAddrCallback = async (callback: ConnectAddrCallback) => {
if (!this.wsaddrs || this.wsaddrs.length == 0) {
this.wsaddrs = await WKApp.dataSource.commonDataSource.imConnectAddrs()
}
if (this.wsaddrs.length > 0) {
console.log("connectAddrs--->", this.wsaddrs)
this.addrUsed = true
callback(this.wsaddrs[0])
}
}
WKApp.endpoints.addOnLogin(() => {
this.startMain()
})
if (WKApp.loginInfo.isLogined()) {
this.startMain()
}
WKSDK.shared().connectManager.addConnectStatusListener((status: ConnectStatus, reasonCode?: number) => {
if (status === ConnectStatus.ConnectKick) {
console.log("被踢--->", reasonCode)
WKApp.shared.logout()
} else if (reasonCode == 2) { // 认证失败!
WKApp.shared.logout()
} else if (status === ConnectStatus.Disconnect) {
if (this.addrUsed && this.wsaddrs.length > 1) {
const oldwsAddr = this.wsaddrs[0]
this.wsaddrs.splice(0, 1)
this.wsaddrs.push(oldwsAddr)
this.addrUsed = false
console.log("连接失败!切换地址->", this.wsaddrs)
}
}
})
// 通知设置
const notificationIsClose = StorageService.shared.getItem("NotificationIsClose")
if (notificationIsClose === "1") {
this._notificationIsClose = true
} else {
this._notificationIsClose = false
}
WKApp.remoteConfig.startRequestConfig()
}
startMain() {
this.connectIM()
WKApp.dataSource.contactsSync()
}
connectIM() {
WKSDK.shared().config.uid = WKApp.loginInfo.uid
WKSDK.shared().config.token = WKApp.loginInfo.token
WKSDK.shared().connect()
}
registerModule(module: IModule) {
ModuleManager.shared.register(module);
}
restContent(content: JSX.Element) {
this.content = content
this.notifyListener()
}
// 是否登录
isLogined() {
return WKApp.loginInfo.isLogined()
}
// 登出
logout() {
WKApp.loginInfo.logout()
window.location.reload()
}
avatarChannel(channel: Channel) {
if (!channel) {
return ""
}
let avatarTag = this.getChannelAvatarTag()
if (!avatarTag) {
avatarTag = "0"
}
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(channel)
if (channelInfo && channelInfo.logo && channelInfo.logo !== "") {
let logo = channelInfo.logo;
if (logo.indexOf("?") != -1) {
logo += "&v=" + avatarTag
} else {
logo += "?v=" + avatarTag
}
return WKApp.dataSource.commonDataSource.getImageURL(logo)
}
const baseURl = WKApp.apiClient.config.apiURL
if (channel.channelType === ChannelTypePerson) {
return `${baseURl}users/${channel.channelID}/avatar?v=${avatarTag}`
} else if (channel.channelType == ChannelTypeGroup) {
return `${baseURl}groups/${channel.channelID}/avatar?v=${avatarTag}`
}
return ""
}
avatarUser(uid: string) {
const c = new Channel(uid, ChannelTypePerson)
return this.avatarChannel(c)
}
// 我的用户头像发送改变
myUserAvatarChange() {
this.changeChannelAvatarTag()
}
changeChannelAvatarTag() {
let myAvatarTag = "channelAvatarTag"
WKApp.loginInfo.setStorageItem(myAvatarTag, new Date().getTime() + "")
}
getChannelAvatarTag() {
let myAvatarTag = "channelAvatarTag"
const tag = WKApp.loginInfo.getStorageItem(myAvatarTag)
if (!tag) {
return ""
}
return tag
}
avatarGroup(groupNo: string) {
const channel = new Channel(groupNo, ChannelTypeGroup)
return this.avatarChannel(channel)
}
// 注册频道设置
channelSettingRegister(sectionID: string, sectionFnc: (context: RouteContext<any>) => Section | undefined, sort?: number) {
WKApp.sectionManager.register(EndpointCategory.channelSetting, sectionID, sectionFnc, sort)
}
// 获取频道设置
channelSettings(context: RouteContext<any>): Section[] {
return WKApp.sectionManager.sections(EndpointCategory.channelSetting, context)
}
// 注册管理设置
channelManageRegister(sectionID: string, sectionFnc: (context: RouteContext<any>) => Section | undefined) {
WKApp.sectionManager.register(EndpointCategory.channelManage, sectionID, sectionFnc)
}
// 获取频道管理
channelManages(context: RouteContext<any>): Section[] {
return WKApp.sectionManager.sections(EndpointCategory.channelManage, context)
}
chatMenusRegister(sid: string, f: (param: any) => ChatMenus, sort?: number) {
WKApp.endpointManager.setMethod(sid, (param) => {
return f(param)
}, {
category: EndpointCategory.chatMenusPopover,
sort: sort,
})
}
chatMenus(param?: any): ChatMenus[] {
return WKApp.endpointManager.invokes<ChatMenus>(EndpointCategory.chatMenusPopover, param)
}
sectionAddRow(sectionID: string, row: Row, context: RouteContext<any>) {
const section = WKApp.sectionManager.section(sectionID, context)
if (section) {
if (!section.rows) {
section.rows = []
}
section.rows.push(row)
}
}
// 注册用户信息
userInfoRegister(sectionID: string, sectionFnc: (context: RouteContext<any>) => Section | undefined, sort?: number) {
WKApp.sectionManager.register(EndpointCategory.userInfo, sectionID, sectionFnc)
}
// 获取用户信息
userInfos(context: RouteContext<any>): Section[] {
return WKApp.sectionManager.sections(EndpointCategory.userInfo, context)
}
private getFriendApplysKey() {
return `${WKApp.loginInfo.uid}friendApplys`
}
public getFriendApplys(): Array<FriendApply> {
var friendApplys = new Array<FriendApply>()
const value = WKApp.loginInfo.getStorageItem(this.getFriendApplysKey())
if (!value || value === "") {
return friendApplys
}
const friendApplyObjs = JSON.parse(value)
if (friendApplyObjs && friendApplyObjs.length > 0) {
for (const friendApplyObj of friendApplyObjs) {
const f = new FriendApply()
f.uid = friendApplyObj.uid
f.name = friendApplyObj.name
f.remark = friendApplyObj.remark
f.state = friendApplyObj.state
f.token = friendApplyObj.token
f.unread = friendApplyObj.unread
f.createdAt = friendApplyObj.createdAt
friendApplys.push(f)
}
}
friendApplys.sort((a, b) => {
return b.createdAt - a.createdAt
})
return friendApplys
}
public getFriendApplysUnreadCount() {
const friendApplys = this.getFriendApplys()
let unreadCount = 0
if (friendApplys && friendApplys.length > 0) {
for (const friendApply of friendApplys) {
if (friendApply.unread) {
unreadCount++
}
}
}
return unreadCount
}
public friendApplyMarkAllReaded() {
let friendApplys = this.getFriendApplys()
if (!friendApplys) {
friendApplys = new Array<FriendApply>()
}
var change = false
for (const friendApply of friendApplys) {
if (friendApply.unread) {
friendApply.unread = false
change = true
}
}
if (change) {
WKApp.loginInfo.setStorageItem(this.getFriendApplysKey(), JSON.stringify(friendApplys))
WKApp.endpointManager.invokes(EndpointCategory.friendApplyDataChange)
}
}
public addFriendApply(friendApply: FriendApply) {
let friendApplys = this.getFriendApplys()
if (!friendApplys) {
friendApplys = new Array<FriendApply>()
}
var exist = false
for (let index = 0; index < friendApplys.length; index++) {
const friendAy = friendApplys[index];
if (friendAy.uid === friendApply.uid) {
friendApplys[index] = friendApply
exist = true
break
}
}
if (!exist) {
friendApplys.push(friendApply)
}
WKApp.loginInfo.setStorageItem(this.getFriendApplysKey(), JSON.stringify(friendApplys))
WKApp.endpointManager.invokes(EndpointCategory.friendApplyDataChange)
}
public updateFriendApply(friendApply: FriendApply) {
let friendApplys = this.getFriendApplys()
if (!friendApplys) {
friendApplys = new Array<FriendApply>()
}
var exist = false
for (let index = 0; index < friendApplys.length; index++) {
const friendAy = friendApplys[index];
if (friendAy.uid === friendApply.uid) {
friendApplys[index] = friendApply
exist = true
break
}
}
if (exist) {
WKApp.loginInfo.setStorageItem(this.getFriendApplysKey(), JSON.stringify(friendApplys))
}
}
public addMessageDeleteListener(listener: MessageDeleteListener) {
this.messageDeleteListeners.push(listener)
}
public removeMessageDeleteListener(listener: MessageDeleteListener) {
const len = this.messageDeleteListeners.length;
for (let i = 0; i < len; i++) {
if (listener === this.messageDeleteListeners[i]) {
this.messageDeleteListeners.splice(i, 1)
return;
}
}
}
public notifyMessageDeleteListener(message: Message, preMessage?: Message) {
const len = this.messageDeleteListeners.length;
for (let i = 0; i < len; i++) {
this.messageDeleteListeners[i](message, preMessage)
}
}
}
export enum FriendApplyState {
apply,
accepted
}
// 好友申请
export class FriendApply {
uid!: string
name!: string
remark?: string
token?: string
state!: FriendApplyState
unread: boolean = false // 是否未读
createdAt!: number // 创建时间
}
export class ChatMenus {
icon!: string
title!: string
sort?: number = 0
onClick?: () => void
}