feat: Add emoji and alot of other fixes
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
ReactionEntity,
|
||||
BanEntity,
|
||||
AttachmentEntity,
|
||||
CustomEmojiEntity,
|
||||
MetaEntity,
|
||||
PluginDataEntity
|
||||
} from '../../../entities';
|
||||
@@ -27,6 +28,7 @@ export async function handleClearAllData(dataSource: DataSource): Promise<void>
|
||||
await dataSource.getRepository(ReactionEntity).clear();
|
||||
await dataSource.getRepository(BanEntity).clear();
|
||||
await dataSource.getRepository(AttachmentEntity).clear();
|
||||
await dataSource.getRepository(CustomEmojiEntity).clear();
|
||||
await dataSource.getRepository(MetaEntity).clear();
|
||||
await dataSource.getRepository(PluginDataEntity).clear();
|
||||
}
|
||||
|
||||
7
electron/cqrs/commands/handlers/deleteCustomEmoji.ts
Normal file
7
electron/cqrs/commands/handlers/deleteCustomEmoji.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
import { CustomEmojiEntity } from '../../../entities';
|
||||
import { DeleteCustomEmojiCommand } from '../../types';
|
||||
|
||||
export async function handleDeleteCustomEmoji(command: DeleteCustomEmojiCommand, dataSource: DataSource): Promise<void> {
|
||||
await dataSource.getRepository(CustomEmojiEntity).delete({ id: command.payload.emojiId });
|
||||
}
|
||||
19
electron/cqrs/commands/handlers/saveCustomEmoji.ts
Normal file
19
electron/cqrs/commands/handlers/saveCustomEmoji.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
import { CustomEmojiEntity } from '../../../entities';
|
||||
import { SaveCustomEmojiCommand } from '../../types';
|
||||
|
||||
export async function handleSaveCustomEmoji(command: SaveCustomEmojiCommand, dataSource: DataSource): Promise<void> {
|
||||
const { emoji } = command.payload;
|
||||
|
||||
await dataSource.getRepository(CustomEmojiEntity).save({
|
||||
id: emoji.id,
|
||||
name: emoji.name,
|
||||
creatorUserId: emoji.creatorUserId,
|
||||
dataUrl: emoji.dataUrl,
|
||||
hash: emoji.hash,
|
||||
mime: emoji.mime,
|
||||
size: emoji.size,
|
||||
createdAt: emoji.createdAt,
|
||||
updatedAt: emoji.updatedAt
|
||||
});
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import {
|
||||
RemoveBanCommand,
|
||||
SaveAttachmentCommand,
|
||||
DeleteAttachmentsForMessageCommand,
|
||||
SaveCustomEmojiCommand,
|
||||
DeleteCustomEmojiCommand,
|
||||
SavePluginDataCommand,
|
||||
DeletePluginDataCommand,
|
||||
SaveMetaCommand
|
||||
@@ -39,6 +41,8 @@ import { handleSaveBan } from './handlers/saveBan';
|
||||
import { handleRemoveBan } from './handlers/removeBan';
|
||||
import { handleSaveAttachment } from './handlers/saveAttachment';
|
||||
import { handleDeleteAttachmentsForMessage } from './handlers/deleteAttachmentsForMessage';
|
||||
import { handleSaveCustomEmoji } from './handlers/saveCustomEmoji';
|
||||
import { handleDeleteCustomEmoji } from './handlers/deleteCustomEmoji';
|
||||
import { handleSavePluginData } from './handlers/savePluginData';
|
||||
import { handleDeletePluginData } from './handlers/deletePluginData';
|
||||
import { handleSaveMeta } from './handlers/saveMeta';
|
||||
@@ -61,6 +65,8 @@ export const buildCommandHandlers = (dataSource: DataSource): Record<CommandType
|
||||
[CommandType.RemoveBan]: (cmd) => handleRemoveBan(cmd as RemoveBanCommand, dataSource),
|
||||
[CommandType.SaveAttachment]: (cmd) => handleSaveAttachment(cmd as SaveAttachmentCommand, dataSource),
|
||||
[CommandType.DeleteAttachmentsForMessage]: (cmd) => handleDeleteAttachmentsForMessage(cmd as DeleteAttachmentsForMessageCommand, dataSource),
|
||||
[CommandType.SaveCustomEmoji]: (cmd) => handleSaveCustomEmoji(cmd as SaveCustomEmojiCommand, dataSource),
|
||||
[CommandType.DeleteCustomEmoji]: (cmd) => handleDeleteCustomEmoji(cmd as DeleteCustomEmojiCommand, dataSource),
|
||||
[CommandType.SavePluginData]: (cmd) => handleSavePluginData(cmd as SavePluginDataCommand, dataSource),
|
||||
[CommandType.DeletePluginData]: (cmd) => handleDeletePluginData(cmd as DeletePluginDataCommand, dataSource),
|
||||
[CommandType.SaveMeta]: (cmd) => handleSaveMeta(cmd as SaveMetaCommand, dataSource),
|
||||
|
||||
@@ -9,6 +9,7 @@ import { RoomEntity } from '../entities/RoomEntity';
|
||||
import { ReactionEntity } from '../entities/ReactionEntity';
|
||||
import { BanEntity } from '../entities/BanEntity';
|
||||
import { AttachmentEntity } from '../entities/AttachmentEntity';
|
||||
import { CustomEmojiEntity } from '../entities/CustomEmojiEntity';
|
||||
import { ReactionPayload } from './types';
|
||||
import {
|
||||
relationRecordToRoomPayload,
|
||||
@@ -140,6 +141,20 @@ export function rowToAttachment(row: AttachmentEntity) {
|
||||
};
|
||||
}
|
||||
|
||||
export function rowToCustomEmoji(row: CustomEmojiEntity) {
|
||||
return {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
creatorUserId: row.creatorUserId,
|
||||
dataUrl: row.dataUrl,
|
||||
hash: row.hash,
|
||||
mime: row.mime,
|
||||
size: row.size,
|
||||
createdAt: row.createdAt,
|
||||
updatedAt: row.updatedAt
|
||||
};
|
||||
}
|
||||
|
||||
export function rowToBan(row: BanEntity) {
|
||||
return {
|
||||
oderId: row.oderId,
|
||||
|
||||
9
electron/cqrs/queries/handlers/getCustomEmojis.ts
Normal file
9
electron/cqrs/queries/handlers/getCustomEmojis.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
import { CustomEmojiEntity } from '../../../entities';
|
||||
import { rowToCustomEmoji } from '../../mappers';
|
||||
|
||||
export async function handleGetCustomEmojis(dataSource: DataSource) {
|
||||
const rows = await dataSource.getRepository(CustomEmojiEntity).find({ order: { updatedAt: 'DESC' } });
|
||||
|
||||
return rows.map(rowToCustomEmoji);
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import { handleGetBansForRoom } from './handlers/getBansForRoom';
|
||||
import { handleIsUserBanned } from './handlers/isUserBanned';
|
||||
import { handleGetAttachmentsForMessage } from './handlers/getAttachmentsForMessage';
|
||||
import { handleGetAllAttachments } from './handlers/getAllAttachments';
|
||||
import { handleGetCustomEmojis } from './handlers/getCustomEmojis';
|
||||
import { handleGetPluginData } from './handlers/getPluginData';
|
||||
import { handleGetMeta } from './handlers/getMeta';
|
||||
|
||||
@@ -50,6 +51,7 @@ export const buildQueryHandlers = (dataSource: DataSource): Record<QueryTypeKey,
|
||||
[QueryType.IsUserBanned]: (query) => handleIsUserBanned(query as IsUserBannedQuery, dataSource),
|
||||
[QueryType.GetAttachmentsForMessage]: (query) => handleGetAttachmentsForMessage(query as GetAttachmentsForMessageQuery, dataSource),
|
||||
[QueryType.GetAllAttachments]: () => handleGetAllAttachments(dataSource),
|
||||
[QueryType.GetCustomEmojis]: () => handleGetCustomEmojis(dataSource),
|
||||
[QueryType.GetPluginData]: (query) => handleGetPluginData(query as GetPluginDataQuery, dataSource),
|
||||
[QueryType.GetMeta]: (query) => handleGetMeta(query as GetMetaQuery, dataSource)
|
||||
});
|
||||
|
||||
@@ -15,6 +15,8 @@ export const CommandType = {
|
||||
RemoveBan: 'remove-ban',
|
||||
SaveAttachment: 'save-attachment',
|
||||
DeleteAttachmentsForMessage: 'delete-attachments-for-message',
|
||||
SaveCustomEmoji: 'save-custom-emoji',
|
||||
DeleteCustomEmoji: 'delete-custom-emoji',
|
||||
SavePluginData: 'save-plugin-data',
|
||||
DeletePluginData: 'delete-plugin-data',
|
||||
SaveMeta: 'save-meta',
|
||||
@@ -39,6 +41,7 @@ export const QueryType = {
|
||||
IsUserBanned: 'is-user-banned',
|
||||
GetAttachmentsForMessage: 'get-attachments-for-message',
|
||||
GetAllAttachments: 'get-all-attachments',
|
||||
GetCustomEmojis: 'get-custom-emojis',
|
||||
GetPluginData: 'get-plugin-data',
|
||||
GetMeta: 'get-meta'
|
||||
} as const;
|
||||
@@ -178,6 +181,18 @@ export interface AttachmentPayload {
|
||||
savedPath?: string;
|
||||
}
|
||||
|
||||
export interface CustomEmojiPayload {
|
||||
id: string;
|
||||
name: string;
|
||||
creatorUserId: string;
|
||||
dataUrl: string;
|
||||
hash: string;
|
||||
mime: string;
|
||||
size: number;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
export type PluginDataScopePayload = 'local' | 'server';
|
||||
|
||||
export interface PluginDataPayload {
|
||||
@@ -204,6 +219,8 @@ export interface SaveBanCommand { type: typeof CommandType.SaveBan; payload: { b
|
||||
export interface RemoveBanCommand { type: typeof CommandType.RemoveBan; payload: { oderId: string } }
|
||||
export interface SaveAttachmentCommand { type: typeof CommandType.SaveAttachment; payload: { attachment: AttachmentPayload } }
|
||||
export interface DeleteAttachmentsForMessageCommand { type: typeof CommandType.DeleteAttachmentsForMessage; payload: { messageId: string } }
|
||||
export interface SaveCustomEmojiCommand { type: typeof CommandType.SaveCustomEmoji; payload: { emoji: CustomEmojiPayload } }
|
||||
export interface DeleteCustomEmojiCommand { type: typeof CommandType.DeleteCustomEmoji; payload: { emojiId: string } }
|
||||
export interface SavePluginDataCommand { type: typeof CommandType.SavePluginData; payload: PluginDataPayload }
|
||||
export interface DeletePluginDataCommand { type: typeof CommandType.DeletePluginData; payload: Omit<PluginDataPayload, 'value'> }
|
||||
export interface SaveMetaCommand { type: typeof CommandType.SaveMeta; payload: { key: string; value: string | null } }
|
||||
@@ -226,6 +243,8 @@ export type Command =
|
||||
| RemoveBanCommand
|
||||
| SaveAttachmentCommand
|
||||
| DeleteAttachmentsForMessageCommand
|
||||
| SaveCustomEmojiCommand
|
||||
| DeleteCustomEmojiCommand
|
||||
| SavePluginDataCommand
|
||||
| DeletePluginDataCommand
|
||||
| SaveMetaCommand
|
||||
@@ -255,6 +274,7 @@ export interface GetBansForRoomQuery { type: typeof QueryType.GetBansForRoom; pa
|
||||
export interface IsUserBannedQuery { type: typeof QueryType.IsUserBanned; payload: { userId: string; roomId: string } }
|
||||
export interface GetAttachmentsForMessageQuery { type: typeof QueryType.GetAttachmentsForMessage; payload: { messageId: string } }
|
||||
export interface GetAllAttachmentsQuery { type: typeof QueryType.GetAllAttachments; payload: Record<string, never> }
|
||||
export interface GetCustomEmojisQuery { type: typeof QueryType.GetCustomEmojis; payload: Record<string, never> }
|
||||
export interface GetPluginDataQuery { type: typeof QueryType.GetPluginData; payload: Omit<PluginDataPayload, 'value'> }
|
||||
export interface GetMetaQuery { type: typeof QueryType.GetMeta; payload: { key: string } }
|
||||
|
||||
@@ -274,5 +294,6 @@ export type Query =
|
||||
| IsUserBannedQuery
|
||||
| GetAttachmentsForMessageQuery
|
||||
| GetAllAttachmentsQuery
|
||||
| GetCustomEmojisQuery
|
||||
| GetPluginDataQuery
|
||||
| GetMetaQuery;
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
RoomUserRoleEntity,
|
||||
RoomChannelPermissionEntity,
|
||||
ReactionEntity,
|
||||
CustomEmojiEntity,
|
||||
BanEntity,
|
||||
AttachmentEntity,
|
||||
MetaEntity,
|
||||
@@ -50,6 +51,7 @@ export const AppDataSource = new DataSource({
|
||||
RoomUserRoleEntity,
|
||||
RoomChannelPermissionEntity,
|
||||
ReactionEntity,
|
||||
CustomEmojiEntity,
|
||||
BanEntity,
|
||||
AttachmentEntity,
|
||||
MetaEntity,
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
RoomUserRoleEntity,
|
||||
RoomChannelPermissionEntity,
|
||||
ReactionEntity,
|
||||
CustomEmojiEntity,
|
||||
BanEntity,
|
||||
AttachmentEntity,
|
||||
MetaEntity,
|
||||
@@ -224,6 +225,7 @@ export async function initializeDatabase(): Promise<void> {
|
||||
RoomUserRoleEntity,
|
||||
RoomChannelPermissionEntity,
|
||||
ReactionEntity,
|
||||
CustomEmojiEntity,
|
||||
BanEntity,
|
||||
AttachmentEntity,
|
||||
MetaEntity,
|
||||
|
||||
35
electron/entities/CustomEmojiEntity.ts
Normal file
35
electron/entities/CustomEmojiEntity.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
PrimaryColumn
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('custom_emojis')
|
||||
export class CustomEmojiEntity {
|
||||
@PrimaryColumn('text')
|
||||
id!: string;
|
||||
|
||||
@Column('text')
|
||||
name!: string;
|
||||
|
||||
@Column('text')
|
||||
creatorUserId!: string;
|
||||
|
||||
@Column('text')
|
||||
dataUrl!: string;
|
||||
|
||||
@Column('text')
|
||||
hash!: string;
|
||||
|
||||
@Column('text')
|
||||
mime!: string;
|
||||
|
||||
@Column('integer')
|
||||
size!: number;
|
||||
|
||||
@Column('integer')
|
||||
createdAt!: number;
|
||||
|
||||
@Column('integer')
|
||||
updatedAt!: number;
|
||||
}
|
||||
@@ -8,6 +8,7 @@ export { RoomRoleEntity } from './RoomRoleEntity';
|
||||
export { RoomUserRoleEntity } from './RoomUserRoleEntity';
|
||||
export { RoomChannelPermissionEntity } from './RoomChannelPermissionEntity';
|
||||
export { ReactionEntity } from './ReactionEntity';
|
||||
export { CustomEmojiEntity } from './CustomEmojiEntity';
|
||||
export { BanEntity } from './BanEntity';
|
||||
export { AttachmentEntity } from './AttachmentEntity';
|
||||
export { MetaEntity } from './MetaEntity';
|
||||
|
||||
@@ -553,6 +553,29 @@ export function setupSystemHandlers(): void {
|
||||
return true;
|
||||
});
|
||||
|
||||
ipcMain.handle('copy-file', async (_event, sourceFilePath: string, destinationFilePath: string) => {
|
||||
if (typeof sourceFilePath !== 'string' || !sourceFilePath.trim()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof destinationFilePath !== 'string' || !destinationFilePath.trim()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const stats = await fsp.stat(sourceFilePath);
|
||||
|
||||
if (!stats.isFile()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await fsp.copyFile(sourceFilePath, destinationFilePath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('file-exists', async (_event, filePath: string) => {
|
||||
try {
|
||||
await fsp.access(filePath, fs.constants.F_OK);
|
||||
|
||||
27
electron/migrations/1000000000011-AddCustomEmojis.ts
Normal file
27
electron/migrations/1000000000011-AddCustomEmojis.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddCustomEmojis1000000000011 implements MigrationInterface {
|
||||
name = 'AddCustomEmojis1000000000011';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE IF NOT EXISTS "custom_emojis" (
|
||||
"id" TEXT PRIMARY KEY NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"creatorUserId" TEXT NOT NULL,
|
||||
"dataUrl" TEXT NOT NULL,
|
||||
"hash" TEXT NOT NULL,
|
||||
"mime" TEXT NOT NULL,
|
||||
"size" INTEGER NOT NULL,
|
||||
"createdAt" INTEGER NOT NULL,
|
||||
"updatedAt" INTEGER NOT NULL
|
||||
)`);
|
||||
await queryRunner.query(`CREATE INDEX IF NOT EXISTS "idx_custom_emojis_updated_at" ON "custom_emojis" ("updatedAt")`);
|
||||
await queryRunner.query(`CREATE INDEX IF NOT EXISTS "idx_custom_emojis_creator" ON "custom_emojis" ("creatorUserId")`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS "idx_custom_emojis_creator"`);
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS "idx_custom_emojis_updated_at"`);
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "custom_emojis"`);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
import { contextBridge, ipcRenderer, webUtils } from 'electron';
|
||||
import { Command, Query } from './cqrs/types';
|
||||
|
||||
const LINUX_SCREEN_SHARE_MONITOR_AUDIO_CHUNK_CHANNEL = 'linux-screen-share-monitor-audio-chunk';
|
||||
@@ -310,6 +310,8 @@ export interface ElectronAPI {
|
||||
saveFileAs: (defaultFileName: string, data: string) => Promise<{ saved: boolean; cancelled: boolean }>;
|
||||
saveExistingFileAs: (sourceFilePath: string, defaultFileName: string) => Promise<{ saved: boolean; cancelled: boolean }>;
|
||||
openFilePath: (filePath: string) => Promise<{ opened: boolean; reason?: string }>;
|
||||
copyFile: (sourceFilePath: string, destinationFilePath: string) => Promise<boolean>;
|
||||
getPathForFile: (file: File) => string;
|
||||
fileExists: (filePath: string) => Promise<boolean>;
|
||||
getFileUrl: (filePath: string) => Promise<string | null>;
|
||||
deleteFile: (filePath: string) => Promise<boolean>;
|
||||
@@ -441,6 +443,8 @@ const electronAPI: ElectronAPI = {
|
||||
saveFileAs: (defaultFileName, data) => ipcRenderer.invoke('save-file-as', defaultFileName, data),
|
||||
saveExistingFileAs: (sourceFilePath, defaultFileName) => ipcRenderer.invoke('save-existing-file-as', sourceFilePath, defaultFileName),
|
||||
openFilePath: (filePath) => ipcRenderer.invoke('open-file-path', filePath),
|
||||
copyFile: (sourceFilePath, destinationFilePath) => ipcRenderer.invoke('copy-file', sourceFilePath, destinationFilePath),
|
||||
getPathForFile: (file) => webUtils.getPathForFile(file),
|
||||
fileExists: (filePath) => ipcRenderer.invoke('file-exists', filePath),
|
||||
getFileUrl: (filePath) => ipcRenderer.invoke('get-file-url', filePath),
|
||||
deleteFile: (filePath) => ipcRenderer.invoke('delete-file', filePath),
|
||||
|
||||
Reference in New Issue
Block a user