Compare commits

...

7 Commits

Author SHA1 Message Date
CrescentLeaf
940845db84 !break: 获取消息方法更新: 支持 offset, 客户端协议破坏性变更参数为对象 2025-12-28 00:30:51 +08:00
CrescentLeaf
01c1ccfd00 修正接口名称 2025-12-28 00:24:14 +08:00
CrescentLeaf
d944401691 一些参数命名的修改 2025-12-28 00:22:27 +08:00
CrescentLeaf
d4d28c2760 删除重复代码 2025-12-28 00:20:20 +08:00
CrescentLeaf
aa8a205e5f 前后端一些接口的重命名 2025-12-28 00:18:25 +08:00
CrescentLeaf
ef84cc30c0 修改参数符号名称 2025-12-28 00:09:07 +08:00
CrescentLeaf
f36c747a72 修正(取消)收藏对话框的关闭逻辑 2025-12-28 00:04:55 +08:00
9 changed files with 53 additions and 103 deletions

View File

@@ -53,7 +53,7 @@ export default class Chat extends BaseClientObject {
}
}
static async getOrCreatePrivateChatOrThrow(client: LingChairClient, user_id: string) {
const re = await client.invoke("Chat.getIdForPrivate", {
const re = await client.invoke("Chat.getOrCreatePrivateChat", {
token: client.access_token,
target: user_id,
})
@@ -81,23 +81,24 @@ export default class Chat extends BaseClientObject {
* 对话消息
* ================================================
*/
async getMessages(page: number = 0) {
return (await this.getMessageBeans(page)).map((v) => new Message(this.client, v))
async getMessages(args: { page?: number, offset?: number }) {
return (await this.getMessageBeans(args)).map((v) => new Message(this.client, v))
}
async getMessagesOrThrow(page: number = 0) {
return (await this.getMessageBeansOrThrow(page)).map((v) => new Message(this.client, v))
async getMessagesOrThrow(args: { page?: number, offset?: number }) {
return (await this.getMessageBeansOrThrow(args)).map((v) => new Message(this.client, v))
}
async getMessageBeans(page: number = 0) {
async getMessageBeans(args: { page?: number, offset?: number }) {
try {
return await this.getMessageBeansOrThrow(page)
return await this.getMessageBeansOrThrow(args)
} catch (_) {
return []
}
}
async getMessageBeansOrThrow(page: number = 0) {
async getMessageBeansOrThrow({ page, offset }: { page?: number, offset?: number }) {
const re = await this.client.invoke("Chat.getMessageHistory", {
token: this.client.access_token,
page,
offset,
target: this.bean.id,
})
if (re.code == 200) return re.data!.messages as MessageBean[]

View File

@@ -123,9 +123,9 @@ export default class UserMySelf extends User {
}
}
async addFavouriteChatsOrThrow(chat_ids: string[]) {
const re = await this.client.invoke("User.addContacts", {
const re = await this.client.invoke("User.addFavouriteChats", {
token: this.client.access_token,
targets: chat_ids,
chat_ids,
})
if (re.code != 200) throw new CallbackError(re)
}
@@ -138,9 +138,9 @@ export default class UserMySelf extends User {
}
}
async removeFavouriteChatsOrThrow(chat_ids: string[]) {
const re = await this.client.invoke("User.removeContacts", {
const re = await this.client.invoke("User.removeFavouriteChats", {
token: this.client.access_token,
targets: chat_ids,
chat_ids,
})
if (re.code != 200) throw new CallbackError(re)
}
@@ -152,11 +152,11 @@ export default class UserMySelf extends User {
}
}
async getMyFavouriteChatBeansOrThrow() {
const re = await this.client.invoke("User.getMyContacts", {
const re = await this.client.invoke("User.getMyFavouriteChats", {
token: this.client.access_token
})
if (re.code == 200)
return (re.data!.favourite_chats || re.data!.contacts_list) as ChatBean[]
return (re.data!.favourite_chats) as ChatBean[]
throw new CallbackError(re)
}
async getMyFavouriteChats() {

View File

@@ -78,6 +78,8 @@ export default function UserOrChatInfoDialog({ chat, useRef }: { chat?: Chat, us
!isMySelf && <mdui-list-item icon={favourited ? "favorite_border" : "favorite"} rounded onClick={() => dialog({
headline: favourited ? "取消收藏对话" : "收藏对话",
description: favourited ? "确定从收藏对话列表中移除吗? (虽然这不会导致聊天记录丢失)" : "确定要添加到收藏对话列表吗?",
closeOnEsc: true,
closeOnOverlayClick: true,
actions: [
{
text: "取消",

View File

@@ -2,9 +2,9 @@ import { Chat, Message } from 'lingchair-client-protocol'
import * as React from 'react'
export default function ChatMessageContainer({
chatInfo,
chat,
}: {
chatInfo: Chat
chat: Chat
}) {
const [messages, setMessages] = React.useState<Message[]>()

View File

@@ -15,9 +15,9 @@ export type CallMethod =
"User.getInfo" |
// 收藏对话列表
"User.getMyContacts" |
"User.addContacts" |
"User.removeContacts" |
"User.getMyFavouriteChats" |
"User.addFavouriteChats" |
"User.removeFavouriteChats" |
// 最近对话列表
"User.getMyRecentChats" |
@@ -36,7 +36,7 @@ export type CallMethod =
// 对话创建
"Chat.createGroup" |
"Chat.getIdForPrivate" |
"Chat.getOrCreatePrivateChat" |
// 入群请求
"Chat.processJoinRequest" |
@@ -51,9 +51,6 @@ export type CallMethod =
"Chat.sendMessage" |
"Chat.getMessageHistory"
// (废弃) 文件上传
// "Chat.uploadFile"
export type ClientEvent =
// 对话收消息
"Client.onMessage"

View File

@@ -87,7 +87,11 @@ export default class ChatApi extends BaseApi {
* @param page 頁面
*/
this.registerEvent("Chat.getMessageHistory", (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token', 'target', 'page'])) return {
if (this.checkArgsMissing(args, ['token', 'target'])) return {
msg: "参数缺失",
code: 400,
}
if (!args.page && !args.offset) return {
msg: "参数缺失",
code: 400,
}
@@ -112,49 +116,10 @@ export default class ChatApi extends BaseApi {
code: 200,
msg: "成功",
data: {
messages: MessagesManager.getInstanceForChat(chat).getMessagesWithPage(15, args.page as number),
messages: MessagesManager.getInstanceForChat(chat)[args.page ? 'getMessagesWithPage' : 'getMessagesWithOffset'](null, (args.page ? args.page : args.offset) as number),
},
}
})
/**
* 上傳文件
* @param token 令牌
* @param target 目標對話
* @param file_name 文件名稱
* @param data 文件二進制數據
*/
/* this.registerEvent("Chat.uploadFile", async (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token', 'target', 'data', 'file_name'])) return {
msg: "参数缺失",
code: 400,
}
const token = TokenManager.decode(args.token as string)
if (!this.checkToken(token, deviceId)) return {
code: 401,
msg: "令牌无效",
}
const chat = Chat.findById(args.target as string)
if (chat == null) return {
code: 404,
msg: "对话不存在",
}
if (!UserChatLinker.checkUserIsLinkedToChat(token.author, chat!.bean.id)) return {
code: 403,
msg: "用户无权访问此对话",
}
const file = await FileManager.uploadFile(args.file_name as string, args.data as Buffer<ArrayBufferLike>, args.target as string)
return {
code: 200,
msg: "成功",
data: {
file_hash: file.getHash()
},
}
}) */
/**
* ======================================================
* 对话成员
@@ -388,7 +353,7 @@ export default class ChatApi extends BaseApi {
* @param token 令牌
* @param target 目標用户
*/
this.registerEvent("Chat.getIdForPrivate", (args, { deviceId }) => {
this.registerEvent("Chat.getOrCreatePrivateChat", (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token', 'target'])) return {
msg: "参数缺失",
code: 400,
@@ -413,10 +378,6 @@ export default class ChatApi extends BaseApi {
code: 200,
msg: '成功',
data: {
// TODO: 移除这个, 将本方法重命名为 getOrCreatePrivateChat
// 并重构原 Web 客户端所引用的内容
chat_id: chat.bean.id,
id: chat.bean.id,
name: chat.bean.name,
type: chat.bean.type,
@@ -459,7 +420,7 @@ export default class ChatApi extends BaseApi {
chat.addAdmin(user.bean.id, [
AdminPermissions.OWNER,
])
user.addContact(chat.bean.id)
user.addFavouriteChat(chat.bean.id)
MessagesManager.getInstanceForChat(chat).addSystemMessage("群组已创建")
return {
@@ -570,10 +531,6 @@ export default class ChatApi extends BaseApi {
msg: "参数缺失",
code: 400,
}
/* if (!(args.avatar instanceof Buffer)) return {
msg: "参数不合法",
code: 400,
} */
const token = TokenManager.decode(args.token as string)
const user = User.findById(token.author) as User
@@ -587,9 +544,6 @@ export default class ChatApi extends BaseApi {
if (chat.bean.type == 'group')
if (chat.checkUserIsAdmin(user.bean.id)) {
chat.setAvatarFileHash(args.file_hash as string)
/* const avatar: Buffer = args.avatar as Buffer
if (avatar)
chat.setAvatar(avatar) */
} else
return {
code: 403,

View File

@@ -144,10 +144,6 @@ export default class UserApi extends BaseApi {
msg: "参数缺失",
code: 400,
}
if (this.checkArgsEmpty(args, ['nickname', 'password'])) return {
msg: "参数不得为空",
code: 400,
}
const username: string | null = args.username as string
const nickname: string = args.nickname as string
@@ -321,7 +317,7 @@ export default class UserApi extends BaseApi {
const user = User.findById(token.author) as User
const recentChats = user.getRecentChats()
const recentChatsList = []
const recentChatsList: any[] = []
for (const [chatId, content] of recentChats) {
const chat = Chat.findById(chatId)
recentChatsList.push({
@@ -341,7 +337,7 @@ export default class UserApi extends BaseApi {
}
})
// 獲取聯絡人列表
this.registerEvent("User.getMyContacts", (args, { deviceId }) => {
this.registerEvent("User.getMyFavouriteChats", (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token'])) return {
msg: "参数缺失",
code: 400,
@@ -354,7 +350,7 @@ export default class UserApi extends BaseApi {
}
const user = User.findById(token.author) as User
const contacts = user.getContactsList()
const contacts = user.getFavouriteChats()
contacts.push(ChatPrivate.getChatIdByUsersId(token.author, token.author))
return {
@@ -374,8 +370,8 @@ export default class UserApi extends BaseApi {
}
})
// 添加聯絡人
this.registerEvent("User.addContacts", (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token', 'targets'])) return {
this.registerEvent("User.addFavouriteChats", (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token', 'chat_ids'])) return {
msg: "参数缺失",
code: 400,
}
@@ -388,14 +384,14 @@ export default class UserApi extends BaseApi {
let fail = 0
const user = User.findById(token.author) as User
for (const target of (args.targets as string[])) {
for (const target of (args.chat_ids as string[])) {
const chat = Chat.findById(target) || Chat.findByName(target)
const targetUser = User.findByAccount(target) as User
if (chat)
user!.addContact(chat.bean.id)
user!.addFavouriteChat(chat.bean.id)
else if (targetUser) {
const privChat = ChatPrivate.findOrCreateForPrivate(user, targetUser)
user!.addContact(privChat.bean.id)
user!.addFavouriteChat(privChat.bean.id)
} else {
fail++
}
@@ -407,8 +403,8 @@ export default class UserApi extends BaseApi {
}
})
// 添加聯絡人
this.registerEvent("User.removeContacts", (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token', 'targets'])) return {
this.registerEvent("User.removeFavouriteChats", (args, { deviceId }) => {
if (this.checkArgsMissing(args, ['token', 'chat_ids'])) return {
msg: "参数缺失",
code: 400,
}
@@ -420,7 +416,7 @@ export default class UserApi extends BaseApi {
}
const user = User.findById(token.author) as User
user.removeContacts(args.targets as string[])
user.removeFavouriteChats(args.chat_ids as string[])
return {
msg: "成功",

View File

@@ -59,14 +59,14 @@ export default class MessagesManager {
text
})
}
getMessages(limit: number = 15, offset: number = 0) {
const ls = MessagesManager.database.prepare(`SELECT * FROM ${this.getTableName()} ORDER BY id DESC LIMIT ? OFFSET ?;`).all(limit, offset) as unknown as MessageBean[]
getMessagesWithOffset(limit: number | undefined | null, offset: number = 0) {
const ls = MessagesManager.database.prepare(`SELECT * FROM ${this.getTableName()} ORDER BY id DESC LIMIT ? OFFSET ?;`).all(limit || 15, offset) as unknown as MessageBean[]
return ls.map((v) => ({
...v,
chat_id: this.chat.bean.id,
}))
}
getMessagesWithPage(limit: number = 15, page: number = 0) {
return this.getMessages(limit, limit * page)
getMessagesWithPage(limit: number | undefined | null, page: number = 0) {
return this.getMessagesWithOffset(limit, (limit || 15) * page)
}
}

View File

@@ -138,17 +138,17 @@ export default class User {
return new Map()
}
}
addContact(chatId: string) {
const ls = this.getContactsList()
addFavouriteChat(chatId: string) {
const ls = this.getFavouriteChats()
if (ls.indexOf(chatId) != -1 || ChatPrivate.getChatIdByUsersId(this.bean.id, this.bean.id) == chatId) return
ls.push(chatId)
this.setAttr("contacts_list", JSON.stringify(ls))
}
removeContacts(contacts: string[]) {
const ls = this.getContactsList().filter((v) => !contacts.includes(v))
removeFavouriteChats(contacts: string[]) {
const ls = this.getFavouriteChats().filter((v) => !contacts.includes(v))
this.setAttr("contacts_list", JSON.stringify(ls))
}
getContactsList() {
getFavouriteChats() {
try {
return JSON.parse(this.bean.contacts_list) as string[]
} catch (e) {
@@ -159,13 +159,13 @@ export default class User {
getAllChatsList() {
return UserChatLinker.getUserChats(this.bean.id)
}
getNickName(): string {
getNickName() {
return this.bean.nickname
}
setNickName(nickName: string) {
this.setAttr("nickname", nickName)
}
getPassword(): string {
getPassword() {
return this.bean.password
}
setPassword(password: string) {