417 lines
9.0 KiB
TypeScript
417 lines
9.0 KiB
TypeScript
import {
|
|
XCardAction,
|
|
XCardActionModel,
|
|
XCardContainerComponent,
|
|
} from './x-card.typings';
|
|
import { Subject, Subscription } from 'rxjs';
|
|
import { concatMap, map } from 'rxjs/operators';
|
|
import { XSizeModel } from '../classes/x-size.model.';
|
|
import { nameof, isNullOrEmptyString, isNullOrUndefined } from 'x-framework-core';
|
|
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild } from '@angular/core';
|
|
|
|
@Component({
|
|
// tslint:disable-next-line:component-selector
|
|
selector: 'x-card',
|
|
templateUrl: './x-card.component.html',
|
|
styleUrls: ['./x-card.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class XCardComponent extends XCardContainerComponent {
|
|
//
|
|
//#region Props ...
|
|
//
|
|
private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
|
|
|
|
//
|
|
//#region Card Elements ....
|
|
private CARD_IMAGE: ElementRef<HTMLElement> = undefined;
|
|
private CARD_HEADER: ElementRef<HTMLElement> = undefined;
|
|
private CARD_FOOTER: ElementRef<HTMLElement> = undefined;
|
|
private CARD_CONTENT: ElementRef<HTMLElement> = undefined;
|
|
private CARD_ACTIONS: ElementRef<HTMLElement> = undefined;
|
|
|
|
@ViewChild('cardImage', { static: false })
|
|
set cardImage(v: ElementRef<HTMLElement>) {
|
|
this.CARD_IMAGE = v;
|
|
}
|
|
|
|
@ViewChild('cardHeader', { static: false })
|
|
set cardHeader(v: ElementRef<HTMLElement>) {
|
|
this.CARD_HEADER = v;
|
|
}
|
|
|
|
@ViewChild('cardFooter', { static: false })
|
|
set cardFooter(v: ElementRef<HTMLElement>) {
|
|
this.CARD_FOOTER = v;
|
|
}
|
|
|
|
@ViewChild('cardContent', { static: false })
|
|
set cardContent(v: ElementRef<HTMLElement>) {
|
|
this.CARD_CONTENT = v;
|
|
}
|
|
|
|
@ViewChild('cardActions', { static: false })
|
|
set cardActions(v: ElementRef<HTMLElement>) {
|
|
this.CARD_ACTIONS = v;
|
|
}
|
|
|
|
get cardImage() {
|
|
return this.CARD_IMAGE;
|
|
}
|
|
|
|
get cardHeader() {
|
|
return this.CARD_HEADER;
|
|
}
|
|
|
|
get cardFooter() {
|
|
return this.CARD_FOOTER;
|
|
}
|
|
|
|
get cardContent() {
|
|
return this.CARD_CONTENT;
|
|
}
|
|
|
|
get cardActions() {
|
|
return this.CARD_ACTIONS;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Full Screen ...
|
|
private IS_FULLSCREEN: boolean = false;
|
|
set isFullscreen(v: boolean) {
|
|
//
|
|
const isChanged = v != this.IS_FULLSCREEN;
|
|
|
|
//
|
|
this.IS_FULLSCREEN = v;
|
|
}
|
|
get isFullscreen() {
|
|
return this.IS_FULLSCREEN;
|
|
}
|
|
//#endregion
|
|
//#endregion
|
|
|
|
//
|
|
//#region LifeCycles ...
|
|
onInit() {
|
|
super.onInit();
|
|
|
|
//
|
|
// Listen for fullscreen change events (handles ESC key and browser UI)
|
|
document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);
|
|
document.addEventListener('webkitfullscreenchange', this.fullscreenChangeHandler);
|
|
document.addEventListener('mozfullscreenchange', this.fullscreenChangeHandler);
|
|
document.addEventListener('MSFullscreenChange', this.fullscreenChangeHandler);
|
|
}
|
|
|
|
onChange(changeKeys: string[]) {
|
|
super.onChange(changeKeys);
|
|
|
|
//
|
|
//#region Action Provider Changed ...
|
|
//
|
|
const isActionProviderChanged = changeKeys.includes(
|
|
nameof<XCardComponent>('actionProvider'),
|
|
);
|
|
if (isActionProviderChanged) {
|
|
this.registerActionProvider();
|
|
}
|
|
//#endregion
|
|
}
|
|
|
|
onDestroy() {
|
|
super.onDestroy();
|
|
|
|
//
|
|
this.unregisterActionProvider();
|
|
|
|
//
|
|
document.removeEventListener('fullscreenchange', this.fullscreenChangeHandler);
|
|
document.removeEventListener('webkitfullscreenchange', this.fullscreenChangeHandler);
|
|
document.removeEventListener('mozfullscreenchange', this.fullscreenChangeHandler);
|
|
document.removeEventListener('MSFullscreenChange', this.fullscreenChangeHandler);
|
|
}
|
|
|
|
registerViewHandlers() {
|
|
super.registerViewHandlers();
|
|
|
|
//
|
|
this.registerActionProvider();
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region UI Providers ...
|
|
isNoTextCard() {
|
|
return this.getResourceValue(this.title).pipe(
|
|
concatMap((title) =>
|
|
this.getResourceValue(this.subTitle).pipe(
|
|
map((subTitle) => {
|
|
return {
|
|
title,
|
|
subTitle,
|
|
};
|
|
}),
|
|
map((object) => {
|
|
return (
|
|
isNullOrEmptyString(object.title) &&
|
|
isNullOrEmptyString(object.subTitle)
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Actions ...
|
|
public async enterFullscreen(options?: FullscreenOptions) {
|
|
//
|
|
if (this.isFullscreen) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
const element: HTMLElement = this.element?.nativeElement;
|
|
if (!element) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
try {
|
|
//
|
|
if (!this.canUseFullscreen()) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
await element.requestFullscreen(options);
|
|
|
|
//
|
|
this.isFullscreen = true;
|
|
this.detectChanges();
|
|
} catch { }
|
|
}
|
|
|
|
public async exitFullscreen() {
|
|
//
|
|
if (!this.isFullscreen) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
try {
|
|
//
|
|
if (document.fullscreenElement) {
|
|
await document.exitFullscreen();
|
|
}
|
|
|
|
//
|
|
this.isFullscreen = false;
|
|
this.detectChanges();
|
|
} catch { }
|
|
}
|
|
|
|
public async toggleFullscreen() {
|
|
//
|
|
if (this.isFullscreen) {
|
|
await this.exitFullscreen();
|
|
} else {
|
|
await this.enterFullscreen();
|
|
}
|
|
}
|
|
|
|
//
|
|
//#region Size Calculating ...
|
|
public calculateImageSize() {
|
|
//
|
|
let result: XSizeModel = undefined;
|
|
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(this.CARD_IMAGE) || isNullOrUndefined(this.CARD_IMAGE.nativeElement)) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = {
|
|
width: this.CARD_IMAGE.nativeElement.offsetWidth,
|
|
height: this.CARD_IMAGE.nativeElement.offsetHeight
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public calculateHeaderSize() {
|
|
//
|
|
let result: XSizeModel = undefined;
|
|
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(this.CARD_HEADER) || isNullOrUndefined(this.CARD_HEADER.nativeElement)) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = {
|
|
width: this.CARD_HEADER.nativeElement.offsetWidth,
|
|
height: this.CARD_HEADER.nativeElement.offsetHeight
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public calculateFooterSize() {
|
|
//
|
|
let result: XSizeModel = undefined;
|
|
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(this.CARD_FOOTER) || isNullOrUndefined(this.CARD_FOOTER.nativeElement)) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = {
|
|
width: this.CARD_FOOTER.nativeElement.offsetWidth,
|
|
height: this.CARD_FOOTER.nativeElement.offsetHeight
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public calculateContentSize() {
|
|
//
|
|
let result: XSizeModel = undefined;
|
|
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(this.CARD_CONTENT) || isNullOrUndefined(this.CARD_CONTENT.nativeElement)) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = {
|
|
width: this.CARD_CONTENT.nativeElement.offsetWidth,
|
|
height: this.CARD_CONTENT.nativeElement.offsetHeight
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
public calculateActionsSize() {
|
|
//
|
|
let result: XSizeModel = undefined;
|
|
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(this.CARD_ACTIONS) || isNullOrUndefined(this.CARD_ACTIONS.nativeElement)) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = {
|
|
width: this.CARD_ACTIONS.nativeElement.offsetWidth,
|
|
height: this.CARD_ACTIONS.nativeElement.offsetHeight
|
|
};
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//#endregion
|
|
//#endregion
|
|
|
|
//
|
|
//#region Private ...
|
|
//
|
|
//#region ActionProvider ...
|
|
private registerActionProvider() {
|
|
//
|
|
this.unregisterActionProvider();
|
|
|
|
//
|
|
if (!this.actionProvider) {
|
|
this.actionProvider = new Subject<XCardActionModel>();
|
|
}
|
|
|
|
//
|
|
// Handle Action Provider ...
|
|
this.ACTION_PROVIDER_SUBSCRIPTION = this.applyTakeUntilWrapper(
|
|
this.actionProvider.asObservable(),
|
|
).subscribe(async (model) => {
|
|
//
|
|
if (!model) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
switch (model.action) {
|
|
//
|
|
case XCardAction.Refresh:
|
|
this.detectChanges();
|
|
break;
|
|
|
|
//
|
|
case XCardAction.EnterFullScreen:
|
|
await this.enterFullscreen();
|
|
break;
|
|
|
|
//
|
|
case XCardAction.ExitFullScreen:
|
|
await this.exitFullscreen();
|
|
break;
|
|
|
|
//
|
|
case XCardAction.ToggleFullScreen:
|
|
await this.toggleFullscreen();
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
private unregisterActionProvider() {
|
|
//
|
|
if (!this.ACTION_PROVIDER_SUBSCRIPTION) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
this.ACTION_PROVIDER_SUBSCRIPTION.unsubscribe();
|
|
this.ACTION_PROVIDER_SUBSCRIPTION = null;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Fullscreen ...
|
|
private fullscreenChangeHandler = () => {
|
|
//
|
|
const isFullscreen = !!(
|
|
document.fullscreenElement ||
|
|
(document as any).webkitFullscreenElement ||
|
|
(document as any).mozFullScreenElement ||
|
|
(document as any).msFullscreenElement
|
|
);
|
|
|
|
//
|
|
this.isFullscreen = isFullscreen;
|
|
this.detectChanges();
|
|
};
|
|
|
|
private canUseFullscreen(): boolean {
|
|
return !!(
|
|
document.fullscreenEnabled ||
|
|
(document as any).webkitFullscreenEnabled ||
|
|
(document as any).mozFullScreenEnabled ||
|
|
(document as any).msFullscreenEnabled
|
|
);
|
|
}
|
|
//#endregion
|
|
//#endregion
|
|
}
|