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(); // 消息删除监听 supportFavorites = [MessageContentType.text, MessageContentType.image] // 注册收藏的消息 notSupportForward: number[] = [] // 不支持转发的消息 openChannel?: Channel // 当前打开的会话频道 content?: JSX.Element baseContext!: WKBaseContext // 唐僧叨叨基础上下文 private _notificationIsClose: boolean = false // 通知是否关闭 private wsaddrs = new Array() // 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) => Section | undefined, sort?: number) { WKApp.sectionManager.register(EndpointCategory.channelSetting, sectionID, sectionFnc, sort) } // 获取频道设置 channelSettings(context: RouteContext): Section[] { return WKApp.sectionManager.sections(EndpointCategory.channelSetting, context) } // 注册管理设置 channelManageRegister(sectionID: string, sectionFnc: (context: RouteContext) => Section | undefined) { WKApp.sectionManager.register(EndpointCategory.channelManage, sectionID, sectionFnc) } // 获取频道管理 channelManages(context: RouteContext): 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(EndpointCategory.chatMenusPopover, param) } sectionAddRow(sectionID: string, row: Row, context: RouteContext) { const section = WKApp.sectionManager.section(sectionID, context) if (section) { if (!section.rows) { section.rows = [] } section.rows.push(row) } } // 注册用户信息 userInfoRegister(sectionID: string, sectionFnc: (context: RouteContext) => Section | undefined, sort?: number) { WKApp.sectionManager.register(EndpointCategory.userInfo, sectionID, sectionFnc) } // 获取用户信息 userInfos(context: RouteContext): Section[] { return WKApp.sectionManager.sections(EndpointCategory.userInfo, context) } private getFriendApplysKey() { return `${WKApp.loginInfo.uid}friendApplys` } public getFriendApplys(): Array { var friendApplys = new Array() 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() } 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() } 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() } 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 }