import {Component, HostListener, inject, input} from '@angular/core'; import { TuiAppearance, TuiButton, TuiDialog, TuiGroup, TuiIcon, TuiScrollbarDirective, TuiTextfield } from '@taiga-ui/core'; import {TranslatePipe} from '@ngx-translate/core'; import {ServiceManager} from '../../../service-manager'; import {MessageBoxViewModel} from './message-box-viewmodel'; import {FormsModule} from '@angular/forms'; import {v4 as uuidv4} from 'uuid'; import {Masonry} from '../masonry/masonry'; import {Oimg} from '../oimg/oimg'; import {FileData} from '@chatenium/chatenium-sdk/domain/fileUploadService.schema'; import {TuiTextarea, TuiTextareaComponent} from '@taiga-ui/kit'; @Component({ selector: 'message-box', imports: [ TuiAppearance, TranslatePipe, TuiScrollbarDirective, TuiGroup, TuiIcon, TuiButton, FormsModule, TuiDialog, Oimg, Masonry, TuiTextfield, TuiTextarea ], templateUrl: './message-box.html', styleUrl: './message-box.scss', }) export class MessageBox { viewModel = input.required() textareaHeight = 25 messageBoxRadius = 200 private dragCounter = 0; isDraggingOverWindow = false; @HostListener('window:dragenter', ['$event']) onDragEnter(event: DragEvent) { event.preventDefault(); this.dragCounter++; if (this.dragCounter === 1) { this.isDraggingOverWindow = true; console.log("Drag entered the window area"); } } @HostListener('window:dragleave', ['$event']) onDragLeave(event: DragEvent) { event.preventDefault(); this.dragCounter--; if (this.dragCounter === 0) { this.isDraggingOverWindow = false; console.log("Drag left the window completely"); } } onTextAreaInput(e: HTMLTextAreaElement) { const calculatedHeight = e.value.split(/\r?\n/).length * 25 const calculatedRadius = (200 - this.textareaHeight) this.textareaHeight = calculatedHeight > 180 ? 180 : calculatedHeight this.messageBoxRadius = calculatedRadius < 30 ? 30 : calculatedRadius } handleFileInput(event: any) { this.processFiles(event.target.files) } sendMessageWithCaption(e: TuiTextareaComponent) { this.viewModel().onMessageSend((e.content() as string), this.viewModel().files()) } async processFiles(fileList: FileList) { for (let i = 0; i < fileList.length; i++) { const file = fileList[i]; const type = file.type.split("/").shift() ?? "" let preview = "" let height = 0 let width = 0 console.log(type) if (type == "image") { try { const imgData = await makePicturePreview(file) console.log(imgData) preview = imgData.preview height = imgData.height width = imgData.width } catch (error) { console.error(error) } } console.log("push") this.viewModel().files().push({ fileId: uuidv4(), data: file, name: file.name, type: type, extension: file.name.split(".").pop() ?? "", preview: preview, height: height, width: width, }) console.log(this.viewModel().files()) } function makePicturePreview(file: File): Promise<{ preview: string, height: number, width: number }> { return new Promise((resolve, reject) => { const img = new Image(); const objectUrl = URL.createObjectURL(file); img.onload = () => { console.log("Loaded image") resolve({ preview: objectUrl, width: img.naturalWidth, height: img.naturalHeight, }); }; img.onerror = (err) => { URL.revokeObjectURL(objectUrl); console.error("Error loading image:", err); reject(err); }; img.src = objectUrl; }); } } } /** * All the extra data for client-side rendering. (With finished messages these are generated on the server) */ export interface FileDataWithPreview extends FileData { preview: string; height: number; width: number; }