Files
xFrameworkComponentsHolder/projects/x-framework-components/src/lib/x-card/x-card.component.ts
T

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
}