import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { AccountInfo } from '../states/accounts.state'; import { Attachment } from './models/mastodon.interfaces'; import { MastodonWrapperService } from './mastodon-wrapper.service'; import { NotificationService } from './notification.service'; @Injectable({ providedIn: 'root' }) export class MediaService { mediaSubject: BehaviorSubject = new BehaviorSubject([]); fileCache: { [url: string]: File } = {}; constructor( private readonly notificationService: NotificationService, private readonly mastodonService: MastodonWrapperService) { } uploadMedia(account: AccountInfo, files: File[]) { for (let file of files) { this.postMedia(account, file); } } private postMedia(account: AccountInfo, file: File) { const uniqueId = `${file.name}${file.size}${Math.random()}`; const wrapper = new MediaWrapper(uniqueId, file, null); let medias = this.mediaSubject.value; medias.push(wrapper); if (medias.length > 4) { medias.splice(0, 1); } this.mediaSubject.next(medias); this.mastodonService.uploadMediaAttachment(account, file, null) .then((attachment: Attachment) => { this.fileCache[attachment.url] = file; let currentMedias = this.mediaSubject.value; let currentMedia = currentMedias.filter(x => x.id === uniqueId)[0]; if (currentMedia) { currentMedia.attachment = attachment; this.mediaSubject.next(currentMedias); } }) .catch((err) => { this.remove(wrapper); this.notificationService.notifyHttpError(err, account); }); } update(account: AccountInfo, media: MediaWrapper) { if (media.attachment.description === media.description) return; this.mastodonService.updateMediaAttachment(account, media.attachment.id, media.description) .then((att: Attachment) => { let medias = this.mediaSubject.value; let updatedMedia = medias.filter(x => x.id === media.id)[0]; updatedMedia.attachment.description = att.description; this.mediaSubject.next(medias); }) .catch((err) => { this.notificationService.notifyHttpError(err, account); }); } addExistingMedia(media: MediaWrapper){ if(!this.fileCache[media.attachment.url]) return; media.file = this.fileCache[media.attachment.url]; let medias = this.mediaSubject.value; medias.push(media); this.mediaSubject.next(medias); } remove(media: MediaWrapper) { let medias = this.mediaSubject.value; let filteredMedias = medias.filter(x => x.id !== media.id); this.mediaSubject.next(filteredMedias); } clearMedia() { this.mediaSubject.next([]); } migrateMedias(account: AccountInfo) { let medias = this.mediaSubject.value; medias.forEach(media => { media.isMigrating = true; }); this.mediaSubject.next(medias); for (let media of medias) { this.mastodonService.uploadMediaAttachment(account, media.file, media.description) .then((attachment: Attachment) => { this.fileCache[attachment.url] = media.file; let currentMedias = this.mediaSubject.value; let currentMedia = currentMedias.filter(x => x.id === media.id)[0]; if (currentMedia) { currentMedia.attachment = attachment; currentMedia.isMigrating = false; this.mediaSubject.next(currentMedias); } }) .catch((err) => { this.remove(media); this.notificationService.notifyHttpError(err, account); }); } } } export class MediaWrapper { constructor( public id: string, public file: File, attachment: Attachment) { this.attachment = attachment; } private _attachment: Attachment; public get attachment(): Attachment { return this._attachment; } public set attachment(value: Attachment){ if (value && value.meta && value.meta.audio_encode) { this.audioType = `audio/${value.meta.audio_encode}`; } else if (value && value.pleroma && value.pleroma.mime_type) { this.audioType = value.pleroma.mime_type; } this._attachment = value; } public description: string; public isMigrating: boolean; public audioType: string; }