644 lines
14 KiB
TypeScript
644 lines
14 KiB
TypeScript
import {
|
|
isImage,
|
|
isVideo,
|
|
isAudio,
|
|
XFileBlob,
|
|
isValidURL,
|
|
isDocument,
|
|
isFunction,
|
|
isXFileBlob,
|
|
nameofInstance,
|
|
isNullOrUndefined,
|
|
isNullOrEmptyString,
|
|
XResourceIdentifier,
|
|
XColorIdentifier,
|
|
} from 'x-framework-core';
|
|
import {
|
|
MediaType,
|
|
toMediaType,
|
|
MediaSourceType,
|
|
isMediaTypePassed,
|
|
VMediaPresentType,
|
|
getMediaSourceType,
|
|
isVMediaPresentType,
|
|
MediaSourceInputType,
|
|
isVMediaPresentTypePassed,
|
|
VMediaPresentTypeIdentifier,
|
|
} from './v-media.typings';
|
|
import {
|
|
XSlotName,
|
|
XIconNames,
|
|
XSlotLayout,
|
|
XButtonType,
|
|
XIconIdentifier,
|
|
} from 'x-framework-components';
|
|
import { XFileDto } from 'x-saherelm-api-sdk';
|
|
import { Component, Input } from '@angular/core';
|
|
import { SafeUrl } from '@angular/platform-browser';
|
|
import { FileLocalizationsResourceIDs } from '../v-file.configs';
|
|
import { VBaseInCardComponent } from '../../classes/v-base.component';
|
|
import { XSimpleListItemSlideOption } from '../../typings/simple.list-item.typings';
|
|
|
|
@Component({
|
|
selector: 'v-media',
|
|
templateUrl: './v-media.component.html',
|
|
styleUrls: ['./v-media.component.scss'],
|
|
})
|
|
export class VMediaComponent extends VBaseInCardComponent {
|
|
//
|
|
//#region Props ...
|
|
|
|
//
|
|
readonly SlotNames = Object.assign({}, XSlotName);
|
|
readonly ButtonTypes = Object.assign({}, XButtonType);
|
|
readonly SlotLayouts = Object.assign({}, XSlotLayout);
|
|
readonly MediaPresentTypes = Object.assign({}, VMediaPresentType);
|
|
|
|
/**
|
|
* Provided Source for Presenting ...
|
|
*/
|
|
@Input()
|
|
src: MediaSourceInputType = undefined;
|
|
|
|
/**
|
|
* CSS Classes names to Attach ...
|
|
*/
|
|
@Input()
|
|
cssClass: Array<string> = [];
|
|
|
|
/**
|
|
* Force to Use Thumbnails Paths if Provided XFileDto source ...
|
|
*/
|
|
@Input()
|
|
useThumbnailsIfProvided: boolean = true;
|
|
|
|
/**
|
|
* Specify How to Represent Component ...
|
|
*/
|
|
@Input()
|
|
presentType: VMediaPresentTypeIdentifier = VMediaPresentType.AsCard;
|
|
|
|
/**
|
|
* Thumbnail Provided Icon's Color ...
|
|
*/
|
|
@Input()
|
|
thumbnailIconColor: XColorIdentifier = this.ColorNames.TertiaryShade;
|
|
|
|
/**
|
|
* Provides Thumbnails Icon for Use if necessary ...
|
|
*
|
|
* @param type
|
|
* @returns
|
|
*/
|
|
@Input()
|
|
thumbnailIconProvider: (type: MediaType) => XIconIdentifier = (type) => {
|
|
//
|
|
let result: XIconIdentifier = undefined;
|
|
|
|
//
|
|
if (isMediaTypePassed(type)) {
|
|
//
|
|
switch (type) {
|
|
//
|
|
case MediaType.Image:
|
|
result = XIconNames.image;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Video:
|
|
result = XIconNames.video;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Audio:
|
|
result = XIconNames.audio;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Document:
|
|
result = XIconNames.document;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Provides Thumbnail Title for Use if necessary ...
|
|
* @param type
|
|
* @returns
|
|
*/
|
|
@Input()
|
|
thumbnailTitleProvider: (type: MediaType) => XResourceIdentifier = (type) => {
|
|
//
|
|
let result: XResourceIdentifier = undefined;
|
|
|
|
//
|
|
if (isMediaTypePassed(type)) {
|
|
//
|
|
switch (type) {
|
|
//
|
|
case MediaType.Image:
|
|
result = FileLocalizationsResourceIDs.image;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Video:
|
|
result = FileLocalizationsResourceIDs.video;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Audio:
|
|
result = FileLocalizationsResourceIDs.audio;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Document:
|
|
result = FileLocalizationsResourceIDs.document;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Provided Actions which Used only in Card Present Type ...
|
|
*/
|
|
@Input()
|
|
providedActions: Array<XSimpleListItemSlideOption> = [];
|
|
|
|
//
|
|
// Required Fields For Describe Media ...
|
|
|
|
//
|
|
url: string = undefined;
|
|
info: string = undefined;
|
|
type: MediaType = undefined;
|
|
safeUrl: SafeUrl = undefined;
|
|
inputType: MediaSourceType = undefined;
|
|
|
|
//
|
|
thumbnailUrl: string = undefined;
|
|
thumbnailSafeUrl: SafeUrl = undefined;
|
|
thumbnailIcon: XIconIdentifier = undefined;
|
|
thumbnailTitle: XResourceIdentifier = undefined;
|
|
//#endregion
|
|
|
|
//
|
|
//#region LifeCycles ...
|
|
afterViewInit(): void {
|
|
super.afterViewInit();
|
|
|
|
//
|
|
this.handlePrepareSource();
|
|
}
|
|
|
|
onChange(changeKeys: string[]): void {
|
|
super.onChange(changeKeys);
|
|
|
|
//
|
|
let isChanged = false;
|
|
let applyChnages = false;
|
|
|
|
//
|
|
// Providers Change ...
|
|
isChanged =
|
|
changeKeys.includes(nameofInstance(this, 'thumbnailIconProvider')) ||
|
|
changeKeys.includes(nameofInstance(this, 'thumbnailTitleProvider'));
|
|
if (isChanged) {
|
|
//
|
|
// Icon ...
|
|
if (
|
|
isNullOrUndefined(this.thumbnailIconProvider) ||
|
|
!isFunction(this.thumbnailIconProvider)
|
|
) {
|
|
//
|
|
this.thumbnailIconProvider = (type) => {
|
|
//
|
|
let result: XIconIdentifier = undefined;
|
|
|
|
//
|
|
if (isMediaTypePassed(type)) {
|
|
//
|
|
switch (type) {
|
|
//
|
|
case MediaType.Image:
|
|
result = XIconNames.image;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Video:
|
|
result = XIconNames.video;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Audio:
|
|
result = XIconNames.audio;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Document:
|
|
result = XIconNames.document;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
};
|
|
}
|
|
|
|
//
|
|
// Title ...
|
|
if (
|
|
isNullOrUndefined(this.thumbnailTitleProvider) ||
|
|
!isFunction(this.thumbnailTitleProvider)
|
|
) {
|
|
//
|
|
this.thumbnailTitleProvider = (type) => {
|
|
//
|
|
let result: XResourceIdentifier = undefined;
|
|
|
|
//
|
|
if (isMediaTypePassed(type)) {
|
|
//
|
|
switch (type) {
|
|
//
|
|
case MediaType.Image:
|
|
result = FileLocalizationsResourceIDs.image;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Video:
|
|
result = FileLocalizationsResourceIDs.video;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Audio:
|
|
result = FileLocalizationsResourceIDs.audio;
|
|
break;
|
|
|
|
//
|
|
case MediaType.Document:
|
|
result = FileLocalizationsResourceIDs.document;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
};
|
|
}
|
|
|
|
//
|
|
applyChnages = true;
|
|
this.thumbnailIcon = this.thumbnailIconProvider(this.type);
|
|
this.thumbnailTitle = this.thumbnailTitleProvider(this.type);
|
|
}
|
|
|
|
//
|
|
// Source Change ...
|
|
isChanged = changeKeys.includes(nameofInstance(this, 'src'));
|
|
if (isChanged) {
|
|
this.handlePrepareSource();
|
|
}
|
|
|
|
//
|
|
// PresentType Change ...
|
|
isChanged = changeKeys.includes(nameofInstance(this, 'presentType'));
|
|
if (isChanged) {
|
|
//
|
|
if (
|
|
isNullOrUndefined(this.presentType) ||
|
|
!isVMediaPresentType(this.presentType)
|
|
) {
|
|
//
|
|
applyChnages = true;
|
|
this.presentType = VMediaPresentType.AsCard;
|
|
}
|
|
|
|
//
|
|
this.setAttribute(nameofInstance(this, 'presentType'), this.presentType);
|
|
}
|
|
|
|
//
|
|
// Provided Actions ...
|
|
isChanged = changeKeys.includes(nameofInstance(this, 'providedActions'));
|
|
if (isChanged) {
|
|
//
|
|
if (isNullOrUndefined(this.providedActions)) {
|
|
//
|
|
applyChnages = true;
|
|
this.providedActions = [];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Thumbnail Icon Color ...
|
|
isChanged = changeKeys.includes(nameofInstance(this, 'thumbnailIconColor'));
|
|
if (isChanged) {
|
|
//
|
|
if (isNullOrEmptyString(this.thumbnailIconColor)) {
|
|
//
|
|
applyChnages = true;
|
|
this.thumbnailIconColor = this.ColorNames.TertiaryShade;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (applyChnages) {
|
|
this.detectChanges();
|
|
}
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Providers ...
|
|
/**
|
|
* Check Present Type is Allow Component Presenting ...
|
|
*
|
|
* @returns
|
|
*/
|
|
canPresent() {
|
|
return isVMediaPresentTypePassed(this.presentType);
|
|
}
|
|
|
|
/**
|
|
* Check Conditions For Thumbnail Present Type ...
|
|
*/
|
|
canShowAsThumbnail() {
|
|
return (
|
|
!isNullOrUndefined(this.thumbnailIcon) &&
|
|
!isNullOrUndefined(this.thumbnailTitle)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check Provided Actions ...
|
|
*/
|
|
hasActions() {
|
|
return (
|
|
!isNullOrUndefined(this.providedActions) &&
|
|
this.hasChild(this.providedActions)
|
|
);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Handlers ...
|
|
/**
|
|
* Prepare Source and Parse data ...
|
|
*
|
|
* @returns
|
|
*/
|
|
handlePrepareSource() {
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(this.src)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Detect Input Type ...
|
|
this.inputType = getMediaSourceType(this.src);
|
|
switch (this.inputType) {
|
|
//
|
|
case MediaSourceType.Url:
|
|
this.handlePrepareUrlSource();
|
|
break;
|
|
|
|
//
|
|
case MediaSourceType.File:
|
|
this.handlePrepareFileSource();
|
|
break;
|
|
|
|
//
|
|
case MediaSourceType.Blob:
|
|
case MediaSourceType.XFileBlob:
|
|
this.handlePrepareBlobSource();
|
|
break;
|
|
|
|
//
|
|
case MediaSourceType.XFileDto:
|
|
this.handlePrepareDtoSource();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Preparing Thumbnail Info ...
|
|
this.thumbnailIcon = this.thumbnailIconProvider(this.type);
|
|
this.thumbnailTitle = this.thumbnailTitleProvider(this.type);
|
|
|
|
//
|
|
// Detect Thumbnail URL ...
|
|
if (this.type === MediaType.Image) {
|
|
//
|
|
if (this.inputType === MediaSourceType.XFileDto) {
|
|
//
|
|
const value = this.src as XFileDto;
|
|
this.thumbnailUrl = !isNullOrEmptyString(value.thumbPath)
|
|
? value.thumbPath
|
|
: value.path;
|
|
} else {
|
|
this.thumbnailUrl = this.url;
|
|
}
|
|
|
|
//
|
|
if (isNullOrUndefined(this.thumbnailUrl)) {
|
|
this.thumbnailUrl = undefined;
|
|
}
|
|
|
|
//
|
|
if (!isNullOrUndefined(this.safeUrl) && isNullOrEmptyString(this.url)) {
|
|
//
|
|
this.thumbnailUrl = undefined;
|
|
this.thumbnailSafeUrl = this.safeUrl;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calling Action Handler ...
|
|
*
|
|
* @param action
|
|
* @returns
|
|
*/
|
|
async handleCallingActionHandler(action: XSimpleListItemSlideOption) {
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(action)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Validate Handler Exists ...
|
|
if (isNullOrUndefined(action.handler) && !isFunction(action.handler)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Calling Action Handler ...
|
|
await this.getValuesAsync(action.handler(this.src));
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Private ...
|
|
/**
|
|
* Set Thumbnail Size ...
|
|
*
|
|
* @param size
|
|
*/
|
|
private handleSetThumbnailSize(size: number) {
|
|
//
|
|
if (size < 32) {
|
|
size = 32;
|
|
}
|
|
|
|
//
|
|
const name = 'thumbnail-size';
|
|
const value = `${size}px;`;
|
|
|
|
//
|
|
this.setCssVar(name, value);
|
|
this.setCssVar(name, value, document.documentElement);
|
|
}
|
|
|
|
/**
|
|
* Extract required data when user provides string as source ...
|
|
*/
|
|
private handlePrepareUrlSource() {
|
|
//
|
|
let value = this.src as string;
|
|
|
|
//
|
|
// Detecting Type ...
|
|
this.detectType(value);
|
|
|
|
//
|
|
// Assign URL if has a Valid Url ...
|
|
this.url = value;
|
|
|
|
//
|
|
if (isValidURL(value)) {
|
|
//
|
|
this.info = value;
|
|
}
|
|
|
|
//
|
|
this.safeUrl = undefined;
|
|
this.thumbnailSafeUrl = undefined;
|
|
}
|
|
|
|
/**
|
|
* Extract required data when user provides XFileDto as source ...
|
|
*/
|
|
private handlePrepareDtoSource() {
|
|
//
|
|
let value = this.src as XFileDto;
|
|
|
|
//
|
|
// Validate ...
|
|
if (isNullOrUndefined(value) || isNullOrEmptyString(value.id)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Detecting Type ...
|
|
this.detectType(value);
|
|
|
|
//
|
|
// Check Can User Thumbnail ...
|
|
if (this.useThumbnailsIfProvided && !isNullOrEmptyString(value.thumbPath)) {
|
|
this.url = value.thumbPath;
|
|
} else if (!isNullOrEmptyString(value.path)) {
|
|
this.url = value.path;
|
|
}
|
|
|
|
//
|
|
this.safeUrl = undefined;
|
|
this.thumbnailSafeUrl = undefined;
|
|
this.info = value.name || value.path || value.thumb || value.thumbPath;
|
|
}
|
|
|
|
/**
|
|
* Extract required data when user provides Blob as source ...
|
|
*/
|
|
private handlePrepareBlobSource() {
|
|
//
|
|
// Blob ...
|
|
if (this.src instanceof Blob) {
|
|
//
|
|
let value = this.src as Blob;
|
|
this.url = undefined;
|
|
this.detectType(value);
|
|
this.safeUrl =
|
|
this.sharedService.managerService.securityService.toSafeURL(
|
|
URL.createObjectURL(value),
|
|
);
|
|
} else if (isXFileBlob(this.src)) {
|
|
//
|
|
let value = this.src as XFileBlob;
|
|
this.detectType(value);
|
|
this.url = value.name;
|
|
this.info = value.name;
|
|
this.safeUrl = undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract required data when user provides File as source ...
|
|
*/
|
|
private handlePrepareFileSource() {
|
|
//
|
|
let value = this.src as File;
|
|
|
|
//
|
|
this.detectType(value);
|
|
this.url = undefined;
|
|
this.safeUrl = this.sharedService.managerService.securityService.toSafeURL(
|
|
URL.createObjectURL(value),
|
|
);
|
|
this.info = value.name;
|
|
}
|
|
|
|
/**
|
|
* Detect Media Type based on Identifier ...
|
|
*
|
|
* @param identifier
|
|
* @returns
|
|
*/
|
|
private detectType(identifier: XFileDto | File | Blob | XFileBlob | string) {
|
|
//
|
|
let result: MediaType = MediaType.None;
|
|
|
|
//
|
|
// Validate ...
|
|
if (!isNullOrUndefined(identifier)) {
|
|
//
|
|
if (this.inputType === MediaSourceType.XFileDto) {
|
|
this.type = toMediaType((identifier as XFileDto).type);
|
|
} else {
|
|
//
|
|
if (isImage(identifier as any)) {
|
|
this.type = MediaType.Image;
|
|
} else if (isVideo(identifier as any)) {
|
|
this.type = MediaType.Video;
|
|
} else if (isAudio(identifier as any)) {
|
|
this.type = MediaType.Audio;
|
|
} else if (isDocument(identifier as any)) {
|
|
this.type = MediaType.Document;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//#endregion
|
|
}
|