Imrpove chat with gifs, videos, music player, redesigns and improved filesharing errors

This commit is contained in:
2026-03-06 04:47:07 +01:00
parent 2d84fbd91a
commit fe2347b54e
65 changed files with 3593 additions and 1030 deletions

View File

@@ -4,6 +4,7 @@ import { DeleteRoomCommand } from '../../types';
export async function handleDeleteRoom(command: DeleteRoomCommand, dataSource: DataSource): Promise<void> {
const { roomId } = command.payload;
await dataSource.getRepository(RoomEntity).delete({ id: roomId });
await dataSource.getRepository(MessageEntity).delete({ roomId });
}

View File

@@ -5,7 +5,6 @@ import { SaveMessageCommand } from '../../types';
export async function handleSaveMessage(command: SaveMessageCommand, dataSource: DataSource): Promise<void> {
const repo = dataSource.getRepository(MessageEntity);
const { message } = command.payload;
const entity = repo.create({
id: message.id,
roomId: message.roomId,
@@ -17,7 +16,7 @@ export async function handleSaveMessage(command: SaveMessageCommand, dataSource:
editedAt: message.editedAt ?? null,
reactions: JSON.stringify(message.reactions ?? []),
isDeleted: message.isDeleted ? 1 : 0,
replyToId: message.replyToId ?? null,
replyToId: message.replyToId ?? null
});
await repo.save(entity);

View File

@@ -34,7 +34,15 @@ if (fs.existsSync(projectRootDatabaseFilePath)) {
export const AppDataSource = new DataSource({
type: 'sqljs',
database: databaseFileBuffer,
entities: [MessageEntity, UserEntity, RoomEntity, ReactionEntity, BanEntity, AttachmentEntity, MetaEntity],
entities: [
MessageEntity,
UserEntity,
RoomEntity,
ReactionEntity,
BanEntity,
AttachmentEntity,
MetaEntity
],
migrations: [path.join(__dirname, 'migrations', '*.{ts,js}')],
synchronize: false,
logging: false,

View File

@@ -36,11 +36,16 @@ export async function initializeDatabase(): Promise<void> {
applicationDataSource = new DataSource({
type: 'sqljs',
database,
entities: [MessageEntity, UserEntity, RoomEntity, ReactionEntity, BanEntity, AttachmentEntity, MetaEntity],
migrations: [
path.join(__dirname, '..', 'migrations', '*.js'),
path.join(__dirname, '..', 'migrations', '*.ts')
entities: [
MessageEntity,
UserEntity,
RoomEntity,
ReactionEntity,
BanEntity,
AttachmentEntity,
MetaEntity
],
migrations: [path.join(__dirname, '..', 'migrations', '*.js'), path.join(__dirname, '..', 'migrations', '*.ts')],
synchronize: false,
logging: false,
autoSave: true,

View File

@@ -1,4 +1,8 @@
import { Entity, PrimaryColumn, Column } from 'typeorm';
import {
Entity,
PrimaryColumn,
Column
} from 'typeorm';
@Entity('meta')
export class MetaEntity {

View File

@@ -1,4 +1,8 @@
import { Entity, PrimaryColumn, Column } from 'typeorm';
import {
Entity,
PrimaryColumn,
Column
} from 'typeorm';
@Entity('reactions')
export class ReactionEntity {

View File

@@ -1,6 +1,7 @@
import {
app,
desktopCapturer,
dialog,
ipcMain,
shell
} from 'electron';
@@ -54,6 +55,24 @@ export function setupSystemHandlers(): void {
return true;
});
ipcMain.handle('save-file-as', async (_event, defaultFileName: string, base64Data: string) => {
const result = await dialog.showSaveDialog({
defaultPath: defaultFileName
});
if (result.canceled || !result.filePath) {
return { saved: false,
cancelled: true };
}
const buffer = Buffer.from(base64Data, 'base64');
await fsp.writeFile(result.filePath, buffer);
return { saved: true,
cancelled: false };
});
ipcMain.handle('ensure-dir', async (_event, dirPath: string) => {
await fsp.mkdir(dirPath, { recursive: true });
return true;

View File

@@ -13,6 +13,7 @@ export interface ElectronAPI {
getAppDataPath: () => Promise<string>;
readFile: (filePath: string) => Promise<string>;
writeFile: (filePath: string, data: string) => Promise<boolean>;
saveFileAs: (defaultFileName: string, data: string) => Promise<{ saved: boolean; cancelled: boolean }>;
fileExists: (filePath: string) => Promise<boolean>;
ensureDir: (dirPath: string) => Promise<boolean>;
@@ -31,6 +32,7 @@ const electronAPI: ElectronAPI = {
getAppDataPath: () => ipcRenderer.invoke('get-app-data-path'),
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath),
writeFile: (filePath, data) => ipcRenderer.invoke('write-file', filePath, data),
saveFileAs: (defaultFileName, data) => ipcRenderer.invoke('save-file-as', defaultFileName, data),
fileExists: (filePath) => ipcRenderer.invoke('file-exists', filePath),
ensureDir: (dirPath) => ipcRenderer.invoke('ensure-dir', dirPath),