Added attachment support
This commit is contained in:
@@ -1,11 +1,21 @@
|
||||
import {signal} from '@angular/core';
|
||||
import {FileData} from '@chatenium/chatenium-sdk/domain/fileUploadService.schema';
|
||||
import {FileDataWithPreview} from './message-box';
|
||||
|
||||
export class MessageBoxViewModel {
|
||||
onMessageSend: (message: string) => void
|
||||
onMessageSend: (message: string, files: FileDataWithPreview[] | null) => void
|
||||
|
||||
constructor(onMessageSend: (message: string) => void) {
|
||||
constructor(onMessageSend: (message: string, files: FileDataWithPreview[] | null) => void) {
|
||||
this.onMessageSend = onMessageSend
|
||||
}
|
||||
|
||||
message = signal<string>("")
|
||||
files = signal<FileDataWithPreview[]>([])
|
||||
|
||||
get dialogOpen() {
|
||||
return this.files().length != 0
|
||||
}
|
||||
set dialogOpen(value: boolean) {
|
||||
this.files.set([])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,35 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template [(tuiDialog)]="viewModel().dialogOpen" [tuiDialogOptions]="{label: 'chat.elements.messageBox.fileUploadDialog.label'|translate}">
|
||||
<masonry [maxColSize]="2" style="overflow-y: scroll; height: 500px">
|
||||
@for (file of viewModel().files(); track file) {
|
||||
@if (file.type == "image") {
|
||||
<img [src]="file.preview" style="width: 100%; height: 100%; object-fit: fill;"/>
|
||||
}
|
||||
}
|
||||
</masonry>
|
||||
|
||||
<div style="margin-top: 10px; display: flex; gap: 10px; width: 100%">
|
||||
<tui-textfield style="width: 100%">
|
||||
<label tuiLabel>{{"chat.elements.messageBox.placeholder"|translate}}</label>
|
||||
<textarea
|
||||
#caption
|
||||
placeholder="{{ 'chat.elements.messageBox.message'|translate }}"
|
||||
[(ngModel)]="viewModel().message"
|
||||
tuiTextarea
|
||||
></textarea>
|
||||
</tui-textfield>
|
||||
|
||||
<button tuiButton iconStart="@tui.send" (click)="sendMessageWithCaption(caption)"></button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<div id="message-box" [style]="'border-radius:'+messageBoxRadius+'px;'">
|
||||
<div class="items-left">
|
||||
<button tuiButton appearance="flat">
|
||||
<button tuiButton appearance="flat" (click)="uplInput.click()">
|
||||
<tui-icon icon="@tui.file-up"/>
|
||||
<input #uplInput type="file" (change)="handleFileInput($event)" multiple hidden/>
|
||||
</button>
|
||||
|
||||
<button tuiButton appearance="flat">
|
||||
@@ -29,7 +54,7 @@
|
||||
[class.hidden]="message.value != ''">{{ "chat.elements.messageBox.placeholder"|translate }}</span>
|
||||
</div>
|
||||
<div class="items-right">
|
||||
<button tuiButton appearance="flat" (click)="viewModel().onMessageSend(message.value)">
|
||||
<button tuiButton appearance="flat" (click)="viewModel().onMessageSend(message.value, null)">
|
||||
<tui-icon icon="@tui.send"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
import {Component, HostListener, inject, input} from '@angular/core';
|
||||
import {TuiAppearance, TuiButton, TuiGroup, TuiIcon, TuiScrollbarDirective} from '@taiga-ui/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',
|
||||
@@ -14,7 +27,12 @@ import {FormsModule} from '@angular/forms';
|
||||
TuiGroup,
|
||||
TuiIcon,
|
||||
TuiButton,
|
||||
FormsModule
|
||||
FormsModule,
|
||||
TuiDialog,
|
||||
Oimg,
|
||||
Masonry,
|
||||
TuiTextfield,
|
||||
TuiTextarea
|
||||
],
|
||||
templateUrl: './message-box.html',
|
||||
styleUrl: './message-box.scss',
|
||||
@@ -56,4 +74,82 @@ export class MessageBox {
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user