feat: Sticker pack list in sticker picker widget

This allows the user to jump to a specific sticker pack in the sticker picker. The list hides and shows when scrolling so no view size is lost. It also contains a quick shortcut to the sticker settings.
This commit is contained in:
Tony Stipanic 2020-03-29 18:28:39 +02:00
parent dd2b45494b
commit f9402f5aaa
No known key found for this signature in database
GPG Key ID: 3026BCCB6C9CC6BD
3 changed files with 103 additions and 1 deletions

View File

@ -14,7 +14,7 @@
<button class="btn btn-link btn-sm" (click)="openIntegrationManager()">Add some stickers</button> <button class="btn btn-link btn-sm" (click)="openIntegrationManager()">Add some stickers</button>
</div> </div>
<div class="sticker-picker" *ngIf="!isLoading && !authError"> <div class="sticker-picker" *ngIf="!isLoading && !authError">
<div class="sticker-pack" *ngFor="let pack of packs trackById"> <div class="sticker-pack" *ngFor="let pack of packs trackById" [attr.id]="'pack-' + pack.id">
<div class="header"> <div class="header">
<span class="title">{{ pack.displayName }}</span> <span class="title">{{ pack.displayName }}</span>
<span class="license"><a [href]="pack.license.urlPath" <span class="license"><a [href]="pack.license.urlPath"
@ -32,5 +32,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="sticker-pack-list" [@hideList]="isListVisible ? 'visible' : 'hidden'" (wheel)="scrollHorizontal($event)" >
<div class="sticker-pack-list-item" *ngFor="let pack of packs trackById" (click)="scrollToPack('pack-' + pack.id)">
<img [src]="getThumbnailUrl(pack.stickers[0].thumbnail.mxc, 48, 48)" width="40" height="40" class="image"
[alt]="pack.displayName" [ngbTooltip]="pack.displayName" placement="top" container="body"/>
</div>
<div class="sticker-pack-list-config" (click)="openIntegrationManager()"
ngbTooltip="Settings" placement="top" container="body">
<i class="fas fa-2x fa-cog"></i>
</div>
</div>
</div> </div>
</div> </div>

View File

@ -43,6 +43,7 @@
.sticker-picker { .sticker-picker {
margin: 15px 15px 30px; margin: 15px 15px 30px;
padding-bottom: 40px;
.sticker-pack { .sticker-pack {
.header { .header {
@ -92,5 +93,33 @@
} }
} }
} }
.sticker-pack-list {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background-color: themed(stickerPickerControlBgColor);
border-top: 1px solid themed(stickerPickerShadowColor);
overflow-x: auto;
white-space: nowrap;
padding: 1px 15px;
.sticker-pack-list-item {
display: inline-block;
cursor: pointer;
padding: 0 3px;
}
.sticker-pack-list-config {
display: inline-block;
cursor: pointer;
height: 40px;
width: 40px;
padding: 3px;
text-align: center;
vertical-align: middle;
}
}
} }
} }

View File

@ -1,6 +1,22 @@
import {
animate,
state,
style,
transition,
trigger
} from '@angular/animations';
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from "@angular/core"; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router"; import { ActivatedRoute } from "@angular/router";
import { CapableWidget, WIDGET_API_VERSION_OPENID } from "../capable-widget"; import { CapableWidget, WIDGET_API_VERSION_OPENID } from "../capable-widget";
import { fromEvent } from 'rxjs';
import {
distinctUntilChanged,
filter,
map,
pairwise,
share,
throttleTime
} from 'rxjs/operators';
import { Subscription } from "rxjs/Subscription"; import { Subscription } from "rxjs/Subscription";
import { ScalarWidgetApi } from "../../shared/services/scalar/scalar-widget.api"; import { ScalarWidgetApi } from "../../shared/services/scalar/scalar-widget.api";
import { StickerApiService } from "../../shared/services/integrations/sticker-api.service"; import { StickerApiService } from "../../shared/services/integrations/sticker-api.service";
@ -14,10 +30,25 @@ import { WIDGET_STICKER_PICKER } from "../../shared/models/widget";
selector: "my-generic-widget-wrapper", selector: "my-generic-widget-wrapper",
templateUrl: "sticker-picker.component.html", templateUrl: "sticker-picker.component.html",
styleUrls: ["sticker-picker.component.scss"], styleUrls: ["sticker-picker.component.scss"],
animations: [
trigger('hideList', [
state(
'hidden',
style({ opacity: 0, transform: 'translateY(100%)' })
),
state(
'visible',
style({ opacity: 1, transform: 'translateY(0)' })
),
transition('* => *', animate('200ms ease-in'))
])
]
}) })
export class StickerPickerWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy { export class StickerPickerWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy {
public isLoading = true; public isLoading = true;
public isListVisible = true;
public authError = false; public authError = false;
public packs: FE_UserStickerPack[]; public packs: FE_UserStickerPack[];
@ -68,6 +99,28 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
if (this.stickerWidgetApiSubscription) this.stickerWidgetApiSubscription.unsubscribe(); if (this.stickerWidgetApiSubscription) this.stickerWidgetApiSubscription.unsubscribe();
} }
public ngAfterViewInit() {
const scroll$ = fromEvent(window, 'scroll').pipe(
throttleTime(10),
map(() => window.pageYOffset),
pairwise(),
map(([y1, y2]): string => (y2 < y1 ? 'up' : 'down')),
distinctUntilChanged(),
share()
);
const scrollUp$ = scroll$.pipe(
filter(direction => direction === 'up')
);
const scrollDown = scroll$.pipe(
filter(direction => direction === 'down')
);
scrollUp$.subscribe(() => (this.isListVisible = true));
scrollDown.subscribe(() => (this.isListVisible = false));
}
protected onSupportedVersionsFound(): void { protected onSupportedVersionsFound(): void {
super.onSupportedVersionsFound(); super.onSupportedVersionsFound();
@ -133,6 +186,16 @@ export class StickerPickerWidgetWrapperComponent extends CapableWidget implement
} }
} }
public scrollHorizontal(event: WheelEvent): void {
document.getElementsByClassName('sticker-pack-list')[0].scrollLeft += event.deltaY;
event.preventDefault();
}
public scrollToPack(id: string) {
const el = document.getElementById(id);
el.scrollIntoView({behavior: 'smooth'});
}
public sendSticker(sticker: FE_Sticker, pack: FE_UserStickerPack) { public sendSticker(sticker: FE_Sticker, pack: FE_UserStickerPack) {
ScalarWidgetApi.sendSticker(sticker, pack); ScalarWidgetApi.sendSticker(sticker, pack);
} }