mirror of
https://github.com/NicolasConstant/sengi
synced 2025-02-09 08:28:40 +01:00
added media edition #56
This commit is contained in:
parent
17bdd7db42
commit
ab38f8fc05
@ -110,7 +110,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
let files = <File[]>event.dataTransfer.files;
|
let files = <File[]>event.dataTransfer.files;
|
||||||
const selectedAccount = this.toolsService.getSelectedAccounts()[0];
|
const selectedAccount = this.toolsService.getSelectedAccounts()[0];
|
||||||
this.mediaService.uploadMedia(files, selectedAccount);
|
this.mediaService.uploadMedia(selectedAccount, files);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
<div *ngIf="m.attachment === null" class="media__loading" title="{{m.file.name}}">
|
<div *ngIf="m.attachment === null" class="media__loading" title="{{m.file.name}}">
|
||||||
<app-waiting-animation class="waiting-icon status-form__sending--waiting"></app-waiting-animation>
|
<app-waiting-animation class="waiting-icon status-form__sending--waiting"></app-waiting-animation>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="m.attachment !== null" class="media__loaded" title="{{m.file.name}}">
|
<div *ngIf="m.attachment !== null" class="media__loaded" title="{{m.file.name}}"
|
||||||
|
(mouseleave) ="updateMedia(m)">
|
||||||
<div class="media__loaded--hover">
|
<div class="media__loaded--hover">
|
||||||
<button class="media__loaded--button" title="remove" (click)="removeMedia(m)">
|
<button class="media__loaded--button" title="remove" (click)="removeMedia(m)">
|
||||||
<fa-icon [icon]="faTimes"></fa-icon>
|
<fa-icon [icon]="faTimes"></fa-icon>
|
||||||
</button>
|
</button>
|
||||||
<input class="media__loaded--description" autocomplete="off" placeholder="Describe for the visually impaired"/>
|
<input class="media__loaded--description" [(ngModel)]="m.description"
|
||||||
|
autocomplete="off" placeholder="Describe for the visually impaired"/>
|
||||||
</div>
|
</div>
|
||||||
<img class="media__loaded--preview" src="{{m.attachment.preview_url}}" />
|
<img class="media__loaded--preview" src="{{m.attachment.preview_url}}" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
height: 10px;
|
height: 10px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top:5px;
|
top:5px;
|
||||||
right:7px;
|
right:8px;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { faTimes } from "@fortawesome/free-solid-svg-icons";
|
import { faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { MediaService, MediaWrapper } from '../../../services/media.service';
|
import { MediaService, MediaWrapper } from '../../../services/media.service';
|
||||||
import { Subscription } from 'rxjs';
|
import { ToolsService } from '../../../services/tools.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-media',
|
selector: 'app-media',
|
||||||
@ -14,7 +15,9 @@ export class MediaComponent implements OnInit, OnDestroy {
|
|||||||
media: MediaWrapper[] = [];
|
media: MediaWrapper[] = [];
|
||||||
private mediaSub: Subscription;
|
private mediaSub: Subscription;
|
||||||
|
|
||||||
constructor(private readonly mediaService: MediaService) { }
|
constructor(
|
||||||
|
private readonly toolsService: ToolsService,
|
||||||
|
private readonly mediaService: MediaService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.mediaSub = this.mediaService.mediaSubject.subscribe((media: MediaWrapper[]) => {
|
this.mediaSub = this.mediaService.mediaSubject.subscribe((media: MediaWrapper[]) => {
|
||||||
@ -27,9 +30,13 @@ export class MediaComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeMedia(media: MediaWrapper): boolean {
|
removeMedia(media: MediaWrapper): boolean {
|
||||||
console.warn('delete');
|
this.mediaService.remove(media);
|
||||||
console.warn(media);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMedia(media: MediaWrapper): boolean {
|
||||||
|
const account = this.toolsService.getSelectedAccounts()[0];
|
||||||
|
this.mediaService.update(account, media);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { HttpHeaders, HttpClient } from '@angular/common/http';
|
import { HttpHeaders, HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import { ApiRoutes } from './models/api.settings';
|
import { ApiRoutes } from './models/api.settings';
|
||||||
import { Account, Status, Results, Context, Relationship, Instance } from "./models/mastodon.interfaces";
|
import { Account, Status, Results, Context, Relationship, Instance, Attachment } from "./models/mastodon.interfaces";
|
||||||
import { AccountInfo } from '../states/accounts.state';
|
import { AccountInfo } from '../states/accounts.state';
|
||||||
import { StreamTypeEnum } from '../states/streams.state';
|
import { StreamTypeEnum } from '../states/streams.state';
|
||||||
|
|
||||||
@ -195,6 +195,22 @@ export class MastodonService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uploadMediaAttachment(account: AccountInfo, file: File): Promise<Attachment> {
|
||||||
|
let input = new FormData();
|
||||||
|
input.append('file', file);
|
||||||
|
const route = `https://${account.instance}${this.apiRoutes.uploadMediaAttachment}`;
|
||||||
|
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
|
||||||
|
return this.httpClient.post<Attachment>(route, input, { headers: headers }).toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: add focus support
|
||||||
|
updateMediaAttachment(account: AccountInfo, mediaId: string, description: string): Promise<Attachment> {
|
||||||
|
let input = new FormData();
|
||||||
|
input.append('description', description);
|
||||||
|
const route = `https://${account.instance}${this.apiRoutes.updateMediaAttachment.replace('{0}', mediaId)}`;
|
||||||
|
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
|
||||||
|
return this.httpClient.put<Attachment>(route, input, { headers: headers }).toPromise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum VisibilityEnum {
|
export enum VisibilityEnum {
|
||||||
|
@ -5,6 +5,8 @@ import { BehaviorSubject, Subject } from 'rxjs';
|
|||||||
import { AccountInfo } from '../states/accounts.state';
|
import { AccountInfo } from '../states/accounts.state';
|
||||||
import { ApiRoutes } from './models/api.settings';
|
import { ApiRoutes } from './models/api.settings';
|
||||||
import { Attachment } from './models/mastodon.interfaces';
|
import { Attachment } from './models/mastodon.interfaces';
|
||||||
|
import { MastodonService } from './mastodon.service';
|
||||||
|
import { NotificationService } from './notification.service';
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -15,27 +17,25 @@ export class MediaService {
|
|||||||
|
|
||||||
mediaSubject: BehaviorSubject<MediaWrapper[]> = new BehaviorSubject<MediaWrapper[]>([]);
|
mediaSubject: BehaviorSubject<MediaWrapper[]> = new BehaviorSubject<MediaWrapper[]>([]);
|
||||||
|
|
||||||
constructor(private readonly httpClient: HttpClient) { }
|
constructor(
|
||||||
|
private readonly notificationService: NotificationService,
|
||||||
|
private readonly mastodonService: MastodonService) { }
|
||||||
|
|
||||||
uploadMedia(files: File[], account: AccountInfo){
|
uploadMedia(account: AccountInfo, files: File[]){
|
||||||
for (let file of files) {
|
for (let file of files) {
|
||||||
this.postMedia(file, account);
|
this.postMedia(account, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private postMedia(file: File, account: AccountInfo){
|
private postMedia(account: AccountInfo, file: File){
|
||||||
const uniqueId = `${file.name}${file.size}${Math.random()}`;
|
const uniqueId = `${file.name}${file.size}${Math.random()}`;
|
||||||
const wrapper = new MediaWrapper(uniqueId, file, null);
|
const wrapper = new MediaWrapper(uniqueId, file, null, null);
|
||||||
|
|
||||||
let medias = this.mediaSubject.value;
|
let medias = this.mediaSubject.value;
|
||||||
medias.push(wrapper);
|
medias.push(wrapper);
|
||||||
this.mediaSubject.next(medias);
|
this.mediaSubject.next(medias);
|
||||||
|
|
||||||
let input = new FormData();
|
this.mastodonService.uploadMediaAttachment(account, file)
|
||||||
input.append('file', file);
|
|
||||||
const route = `https://${account.instance}${this.apiRoutes.uploadMediaAttachment}`;
|
|
||||||
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
|
|
||||||
this.httpClient.post(route, input, { headers: headers }).toPromise()
|
|
||||||
.then((attachment: Attachment) => {
|
.then((attachment: Attachment) => {
|
||||||
let currentMedias = this.mediaSubject.value;
|
let currentMedias = this.mediaSubject.value;
|
||||||
let currentMedia = currentMedias.filter(x => x.id === uniqueId)[0];
|
let currentMedia = currentMedias.filter(x => x.id === uniqueId)[0];
|
||||||
@ -45,18 +45,37 @@ export class MediaService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
let currentMedias = this.mediaSubject.value;
|
this.remove(wrapper);
|
||||||
let currentMedia = currentMedias.filter(x => x.id !== uniqueId);
|
this.notificationService.notifyHttpError(err);
|
||||||
this.mediaSubject.next(currentMedia);
|
|
||||||
|
|
||||||
//TODO: notify
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update( account: AccountInfo, media: MediaWrapper): any {
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(media: MediaWrapper): any {
|
||||||
|
let medias = this.mediaSubject.value;
|
||||||
|
let filteredMedias = medias.filter(x => x.id !== media.id);
|
||||||
|
this.mediaSubject.next(filteredMedias);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MediaWrapper {
|
export class MediaWrapper {
|
||||||
constructor(
|
constructor(
|
||||||
public id: string,
|
public id: string,
|
||||||
public file: File,
|
public file: File,
|
||||||
public attachment: Attachment) {}
|
public attachment: Attachment,
|
||||||
|
public description: string) {}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ export class ApiRoutes {
|
|||||||
followRemote = '/api/v1/follows';
|
followRemote = '/api/v1/follows';
|
||||||
getInstance = '/api/v1/instance';
|
getInstance = '/api/v1/instance';
|
||||||
uploadMediaAttachment = '/api/v1/media';
|
uploadMediaAttachment = '/api/v1/media';
|
||||||
|
updateMediaAttachment = '/api/v1/media/{0}';
|
||||||
getMutes = '/api/v1/mutes';
|
getMutes = '/api/v1/mutes';
|
||||||
getNotifications = '/api/v1/notifications';
|
getNotifications = '/api/v1/notifications';
|
||||||
getSingleNotifications = '/api/v1/notifications/{0}';
|
getSingleNotifications = '/api/v1/notifications/{0}';
|
||||||
|
@ -61,6 +61,8 @@ export interface Attachment {
|
|||||||
remote_url: string;
|
remote_url: string;
|
||||||
preview_url: string;
|
preview_url: string;
|
||||||
text_url: string;
|
text_url: string;
|
||||||
|
meta: any;
|
||||||
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Card {
|
export interface Card {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user