diff --git a/frontend/src/app/components/fab/speed-dial/speed-dial-option.directive.ts b/frontend/src/app/components/fab/speed-dial/speed-dial-option.directive.ts index 1ed1b9f..071ad41 100644 --- a/frontend/src/app/components/fab/speed-dial/speed-dial-option.directive.ts +++ b/frontend/src/app/components/fab/speed-dial/speed-dial-option.directive.ts @@ -7,10 +7,10 @@ import { MatTooltip } from '@angular/material/tooltip'; }) export class SpeedDialOptionDirective { constructor( - @Host() @Optional() test?: MatTooltip, - @Host() @Optional() test2?: MatButton + @Host() @Optional() tooltip?: MatTooltip, + @Host() @Optional() button?: MatButton ) { - if (test) test.position = 'left'; - if (test2) test2.color = 'primary'; + if (tooltip) tooltip.position = 'left'; + if (button) button.color = 'primary'; } } diff --git a/frontend/src/app/components/fab/speed-dial/speed-dial.component.ts b/frontend/src/app/components/fab/speed-dial/speed-dial.component.ts index b5707cd..0d55308 100644 --- a/frontend/src/app/components/fab/speed-dial/speed-dial.component.ts +++ b/frontend/src/app/components/fab/speed-dial/speed-dial.component.ts @@ -21,37 +21,48 @@ export class SpeedDialComponent { public openManager = new OpenManager(); - private lastMouseEvent: number = 0; + private touchUntil: number = 0; + + @HostListener('document:touchstart', ['$event']) + @HostListener('document:touchend', ['$event']) + touchEvent(e: TouchEvent) { + if (e.type === 'touchstart') { + this.touchUntil = Infinity; + } else { + this.touchUntil = e.timeStamp + 2000; + } + } @HostListener('document:click', ['$event']) - anyClick(e: MouseEvent) { - if (!this.openManager.isOpen) return; - if (this.lastMouseEvent === e.timeStamp) return; + @HostListener('document:keydown.escape', ['$event']) + anyClick(e: Event) { + console.log(e); + if (!this.openManager.isOpen || this.openManager.isAnimating) return; this.openManager.close(); } click(e: MouseEvent) { - if (this.lastMouseEvent === e.timeStamp) return; - - this.lastMouseEvent = e.timeStamp; - const value = this.openManager.toggle(); - - if (value === false) { + console.log(e); + if (!this.openManager.isOpen) { + this.openManager.open(); + } else { this.clickEmitter.next(); } } enter(e: MouseEvent) { + if (e.timeStamp <= this.touchUntil) return; + if (this.openOnHover) { - this.lastMouseEvent = e.timeStamp; this.openManager.open(); } } leave(e: MouseEvent) { + if (e.timeStamp <= this.touchUntil) return; + if (this.openOnHover) { - this.lastMouseEvent = e.timeStamp; this.openManager.close(); } } diff --git a/frontend/src/app/routes/view/view.component.html b/frontend/src/app/routes/view/view.component.html index 01c5cf9..e6c12bd 100644 --- a/frontend/src/app/routes/view/view.component.html +++ b/frontend/src/app/routes/view/view.component.html @@ -47,13 +47,7 @@ [open-on-hover]="true" (main-click)="download()" > - - - diff --git a/frontend/src/app/routes/view/view.component.ts b/frontend/src/app/routes/view/view.component.ts index 8202da6..df6053d 100644 --- a/frontend/src/app/routes/view/view.component.ts +++ b/frontend/src/app/routes/view/view.component.ts @@ -39,6 +39,10 @@ export class ViewComponent implements OnInit { this.utilService.downloadFile(this.imageLinks.source); } + share() { + this.utilService.shareLink(this.imageLinks.source); + } + goBackHome() { this.router.navigate(['/']); } diff --git a/frontend/src/app/services/api/api.service.ts b/frontend/src/app/services/api/api.service.ts index 2a49533..8be6f14 100644 --- a/frontend/src/app/services/api/api.service.ts +++ b/frontend/src/app/services/api/api.service.ts @@ -38,6 +38,10 @@ export class ApiService { return this.fetchHead(url, { method: 'HEAD' }); } + public async getBuffer(url: string): AsyncFailable { + return this.fetchBuffer(url, { method: 'GET' }); + } + public async post( sendType: ZodDtoStatic, receiveType: ZodDtoStatic, diff --git a/frontend/src/app/util/util-module/util.service.ts b/frontend/src/app/util/util-module/util.service.ts index 93856cb..df3cfff 100644 --- a/frontend/src/app/util/util-module/util.service.ts +++ b/frontend/src/app/util/util-module/util.service.ts @@ -3,7 +3,10 @@ import { Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; +import { HasFailed } from 'picsur-shared/dist/types'; import { map, Observable } from 'rxjs'; +import { ApiService } from 'src/app/services/api/api.service'; +import { Logger } from 'src/app/services/logger/logger.service'; import { SnackBarType } from '../../models/dto/snack-bar-type.dto'; import { ConfirmDialogComponent, @@ -14,13 +17,16 @@ import { providedIn: 'root', }) export class UtilService { + private readonly logger = new Logger('UtilService'); + private isDesktopObservable: Observable; constructor( private snackBar: MatSnackBar, private dialog: MatDialog, private router: Router, - private breakPointObserver: BreakpointObserver + private breakPointObserver: BreakpointObserver, + private api: ApiService ) { this.isDesktopObservable = this.breakPointObserver .observe(['(min-width: 576px)']) // Bootstrap breakpoints @@ -73,6 +79,50 @@ export class UtilService { link.remove(); } + public canShare(): boolean { + return navigator.canShare !== undefined && navigator.share !== undefined; + } + + public async shareLink(url: string) { + if (!this.canShare()) { + this.showSnackBar( + 'Sharing is not supported on your device', + SnackBarType.Warning + ); + return; + } + + let image = await this.api.getBuffer(url); + if (HasFailed(image)){ + this.showSnackBar( + 'Sharing is not supported on your device', + SnackBarType.Warning + ); + return; + } + + let file = new File([image], 'image.gif', { type: 'image/gif' }); + + let a = navigator.canShare({ + title: 'test', + files: [file], + }); + console.log(a); + + try { + await navigator.share({ + title: 'test', + files: [file], + }); + } catch (e) { + this.logger.error(e); + this.showSnackBar( + 'Sharing is not supported on your device', + SnackBarType.Warning + ); + } + } + public async sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); }