feat(im): 添加即时通讯数据库和缩放图片组件
- 实现了基于 WatermelonDB 的 IM 数据库功能 - 添加了 ScaledImage 组件用于图片尺寸自适应 - 集成了消息存储、会话管理、搜索等功能 - 配置了项目基础结构和依赖管理 - 定义了数据库表结构和类型声明
这个提交包含在:
父节点
9de1059e25
当前提交
2d1bebeeb5
@ -2,6 +2,7 @@
|
|||||||
"name": "@xuqm/rn-sdk",
|
"name": "@xuqm/rn-sdk",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"description": "XuqmGroup React Native SDK — meta-package (IM, Push, Update, Common)",
|
"description": "XuqmGroup React Native SDK — meta-package (IM, Push, Update, Common)",
|
||||||
|
"license": "UNLICENSED",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"react-native": "src/index.ts",
|
"react-native": "src/index.ts",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
|
|||||||
@ -54,7 +54,7 @@ function computeDimensions(
|
|||||||
return { width: Math.round(width), height: Math.round(height) }
|
return { width: Math.round(width), height: Math.round(height) }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ScaledImage(props: Props): JSX.Element {
|
export function ScaledImage(props: Props): React.ReactElement {
|
||||||
const {
|
const {
|
||||||
uri,
|
uri,
|
||||||
originalWidth,
|
originalWidth,
|
||||||
|
|||||||
@ -36,7 +36,7 @@ export const ImDatabase = {
|
|||||||
schema: imDbSchema,
|
schema: imDbSchema,
|
||||||
dbName,
|
dbName,
|
||||||
jsi: true,
|
jsi: true,
|
||||||
onSetUpError: (err) => console.error('[ImDatabase] setup error', err),
|
onSetUpError: (err: unknown) => console.error('[ImDatabase] setup error', err),
|
||||||
})
|
})
|
||||||
_db = new Database({
|
_db = new Database({
|
||||||
adapter,
|
adapter,
|
||||||
@ -57,7 +57,7 @@ export const ImDatabase = {
|
|||||||
.fetch()
|
.fetch()
|
||||||
|
|
||||||
if (existing.length === 0) {
|
if (existing.length === 0) {
|
||||||
await db.get<MessageModel>('im_messages').create(m => {
|
await db.get<MessageModel>('im_messages').create((m: MessageModel) => {
|
||||||
m.serverId = msg.id
|
m.serverId = msg.id
|
||||||
m.appId = msg.appId
|
m.appId = msg.appId
|
||||||
m.conversationId = convId
|
m.conversationId = convId
|
||||||
@ -72,7 +72,7 @@ export const ImDatabase = {
|
|||||||
m.syncedAt = now
|
m.syncedAt = now
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
await existing[0].update(m => {
|
await existing[0].update((m: MessageModel) => {
|
||||||
m.status = msg.status
|
m.status = msg.status
|
||||||
m.content = msg.content
|
m.content = msg.content
|
||||||
m.syncedAt = now
|
m.syncedAt = now
|
||||||
@ -87,7 +87,7 @@ export const ImDatabase = {
|
|||||||
|
|
||||||
const msgTime = new Date(msg.createdAt).getTime()
|
const msgTime = new Date(msg.createdAt).getTime()
|
||||||
if (convs.length === 0) {
|
if (convs.length === 0) {
|
||||||
await db.get<ConversationModel>('im_conversations').create(c => {
|
await db.get<ConversationModel>('im_conversations').create((c: ConversationModel) => {
|
||||||
c.appId = msg.appId
|
c.appId = msg.appId
|
||||||
c.targetId = msg.toId
|
c.targetId = msg.toId
|
||||||
c.chatType = msg.chatType
|
c.chatType = msg.chatType
|
||||||
@ -101,7 +101,7 @@ export const ImDatabase = {
|
|||||||
c.updatedAt = new Date()
|
c.updatedAt = new Date()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
await convs[0].update(c => {
|
await convs[0].update((c: ConversationModel) => {
|
||||||
if (msgTime >= c.lastMsgTime) {
|
if (msgTime >= c.lastMsgTime) {
|
||||||
c.lastMsgId = msg.id
|
c.lastMsgId = msg.id
|
||||||
c.lastMsgContent = msg.content
|
c.lastMsgContent = msg.content
|
||||||
@ -150,7 +150,7 @@ export const ImDatabase = {
|
|||||||
.fetch()
|
.fetch()
|
||||||
if (convs.length > 0) {
|
if (convs.length > 0) {
|
||||||
await db.write(async () => {
|
await db.write(async () => {
|
||||||
await convs[0].update(c => { c.unreadCount = 0 })
|
await convs[0].update((c: ConversationModel) => { c.unreadCount = 0 })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -225,7 +225,7 @@ export const ImDatabase = {
|
|||||||
.fetch()
|
.fetch()
|
||||||
if (convs.length > 0) {
|
if (convs.length > 0) {
|
||||||
await db.write(async () => {
|
await db.write(async () => {
|
||||||
await convs[0].update(c => { c.isMuted = muted })
|
await convs[0].update((c: ConversationModel) => { c.isMuted = muted })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -238,7 +238,7 @@ export const ImDatabase = {
|
|||||||
.fetch()
|
.fetch()
|
||||||
if (convs.length > 0) {
|
if (convs.length > 0) {
|
||||||
await db.write(async () => {
|
await db.write(async () => {
|
||||||
await convs[0].update(c => { c.isPinned = pinned })
|
await convs[0].update((c: ConversationModel) => { c.isPinned = pinned })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
61
src/types/watermelondb.d.ts
vendored
普通文件
61
src/types/watermelondb.d.ts
vendored
普通文件
@ -0,0 +1,61 @@
|
|||||||
|
declare module '@nozbe/watermelondb' {
|
||||||
|
export class Model {
|
||||||
|
static table: string
|
||||||
|
update(mutator: (record: this) => void | Promise<void>): Promise<this>
|
||||||
|
destroyPermanently(): Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Database {
|
||||||
|
constructor(options: unknown)
|
||||||
|
write<T>(work: () => Promise<T> | T): Promise<T>
|
||||||
|
get<T extends Model>(table: string): Collection<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Collection<T extends Model> {
|
||||||
|
query(...conditions: unknown[]): Query<T>
|
||||||
|
create(builder: (record: T) => void | Promise<void>): Promise<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Query<T extends Model> {
|
||||||
|
fetch(): Promise<T[]>
|
||||||
|
extend(...conditions: unknown[]): Query<T>
|
||||||
|
observe(): Observable<T[]>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Observable<T> {
|
||||||
|
subscribe(callback: (value: T) => void): Subscription
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Subscription {
|
||||||
|
unsubscribe(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Q: {
|
||||||
|
and(...conditions: unknown[]): unknown
|
||||||
|
or(...conditions: unknown[]): unknown
|
||||||
|
where(column: string, value: unknown): unknown
|
||||||
|
sortBy(column: string, order?: unknown): unknown
|
||||||
|
take(count: number): unknown
|
||||||
|
skip(count: number): unknown
|
||||||
|
oneOf(values: unknown[]): unknown
|
||||||
|
like(pattern: string): unknown
|
||||||
|
gte(value: unknown): unknown
|
||||||
|
lte(value: unknown): unknown
|
||||||
|
sanitizeLikeString(value: string): string
|
||||||
|
desc: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export function appSchema(schema: unknown): unknown
|
||||||
|
export function tableSchema(schema: unknown): unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@nozbe/watermelondb/adapters/sqlite' {
|
||||||
|
export default class SQLiteAdapter {
|
||||||
|
constructor(options: unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@nozbe/watermelondb/decorators' {
|
||||||
|
export function field(columnName: string): any
|
||||||
|
export function date(columnName: string): any
|
||||||
|
}
|
||||||
@ -3,6 +3,13 @@
|
|||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@xuqm/rn-common": ["packages/common/src"],
|
||||||
|
"@xuqm/rn-im": ["packages/im/src"],
|
||||||
|
"@xuqm/rn-push": ["packages/push/src"],
|
||||||
|
"@xuqm/rn-update": ["packages/update/src"]
|
||||||
|
},
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"jsx": "react-native",
|
"jsx": "react-native",
|
||||||
"lib": ["ES2020"],
|
"lib": ["ES2020"],
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户