From 67ed6552b831df66713bac9e672738796128d33f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 23 Jun 2020 14:10:17 +0200 Subject: Reorganize client shared modules --- client/src/app/shared/misc/constants.ts | 1 - client/src/app/shared/misc/help.component.html | 40 ---- client/src/app/shared/misc/help.component.scss | 42 ----- client/src/app/shared/misc/help.component.ts | 94 --------- .../app/shared/misc/list-overflow.component.html | 35 ---- .../app/shared/misc/list-overflow.component.scss | 61 ------ .../src/app/shared/misc/list-overflow.component.ts | 120 ------------ client/src/app/shared/misc/loader.component.html | 8 - client/src/app/shared/misc/loader.component.scss | 45 ----- client/src/app/shared/misc/loader.component.ts | 10 - client/src/app/shared/misc/peertube-web-storage.ts | 81 -------- client/src/app/shared/misc/screen.service.ts | 66 ------- .../app/shared/misc/small-loader.component.html | 3 - .../src/app/shared/misc/small-loader.component.ts | 11 -- client/src/app/shared/misc/storage.service.ts | 40 ---- client/src/app/shared/misc/utils.ts | 210 --------------------- 16 files changed, 867 deletions(-) delete mode 100644 client/src/app/shared/misc/constants.ts delete mode 100644 client/src/app/shared/misc/help.component.html delete mode 100644 client/src/app/shared/misc/help.component.scss delete mode 100644 client/src/app/shared/misc/help.component.ts delete mode 100644 client/src/app/shared/misc/list-overflow.component.html delete mode 100644 client/src/app/shared/misc/list-overflow.component.scss delete mode 100644 client/src/app/shared/misc/list-overflow.component.ts delete mode 100644 client/src/app/shared/misc/loader.component.html delete mode 100644 client/src/app/shared/misc/loader.component.scss delete mode 100644 client/src/app/shared/misc/loader.component.ts delete mode 100644 client/src/app/shared/misc/peertube-web-storage.ts delete mode 100644 client/src/app/shared/misc/screen.service.ts delete mode 100644 client/src/app/shared/misc/small-loader.component.html delete mode 100644 client/src/app/shared/misc/small-loader.component.ts delete mode 100644 client/src/app/shared/misc/storage.service.ts delete mode 100644 client/src/app/shared/misc/utils.ts (limited to 'client/src/app/shared/misc') diff --git a/client/src/app/shared/misc/constants.ts b/client/src/app/shared/misc/constants.ts deleted file mode 100644 index bb4a0884e..000000000 --- a/client/src/app/shared/misc/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const POP_STATE_MODAL_DISMISS = 'pop state dismiss' diff --git a/client/src/app/shared/misc/help.component.html b/client/src/app/shared/misc/help.component.html deleted file mode 100644 index 9a6d3e48e..000000000 --- a/client/src/app/shared/misc/help.component.html +++ /dev/null @@ -1,40 +0,0 @@ - -

- -

- - -

-
- -

- -

- -

- - -

-
- -

- -

-
- - - - diff --git a/client/src/app/shared/misc/help.component.scss b/client/src/app/shared/misc/help.component.scss deleted file mode 100644 index 43f33a53a..000000000 --- a/client/src/app/shared/misc/help.component.scss +++ /dev/null @@ -1,42 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -.help-tooltip-button { - cursor: pointer; - border: none; - - my-global-icon { - width: 17px; - position: relative; - top: -2px; - margin: 5px; - - @include apply-svg-color(pvar(--mainForegroundColor)) - } -} - -::ng-deep { - .help-popover { - z-index: z(help-popover) !important; - max-width: 300px; - - .popover-body { - font-family: $main-fonts; - text-align: left; - padding: 10px; - font-size: 13px; - background-color: pvar(--mainBackgroundColor); - color: pvar(--mainForegroundColor); - border-radius: 3px; - - p { - margin-bottom: 0; - } - - ul { - padding-left: 20px; - margin-bottom: 0; - } - } - } -} diff --git a/client/src/app/shared/misc/help.component.ts b/client/src/app/shared/misc/help.component.ts deleted file mode 100644 index e8c199e7d..000000000 --- a/client/src/app/shared/misc/help.component.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { AfterContentInit, Component, ContentChildren, Input, OnChanges, OnInit, QueryList, TemplateRef } from '@angular/core' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { MarkdownService } from '@app/shared/renderer' -import { PeerTubeTemplateDirective } from '@app/shared/angular/peertube-template.directive' - -@Component({ - selector: 'my-help', - styleUrls: [ './help.component.scss' ], - templateUrl: './help.component.html' -}) - -export class HelpComponent implements OnInit, OnChanges, AfterContentInit { - @Input() helpType: 'custom' | 'markdownText' | 'markdownEnhanced' = 'custom' - @Input() tooltipPlacement = 'right auto' - - @ContentChildren(PeerTubeTemplateDirective) templates: QueryList> - - isPopoverOpened = false - mainHtml = '' - - preHtmlTemplate: TemplateRef - customHtmlTemplate: TemplateRef - postHtmlTemplate: TemplateRef - - constructor (private i18n: I18n) { } - - ngOnInit () { - this.init() - } - - ngAfterContentInit () { - { - const t = this.templates.find(t => t.name === 'preHtml') - if (t) this.preHtmlTemplate = t.template - } - - { - const t = this.templates.find(t => t.name === 'customHtml') - if (t) this.customHtmlTemplate = t.template - } - - { - const t = this.templates.find(t => t.name === 'postHtml') - if (t) this.postHtmlTemplate = t.template - } - } - - ngOnChanges () { - this.init() - } - - onPopoverHidden () { - this.isPopoverOpened = false - } - - onPopoverShown () { - this.isPopoverOpened = true - } - - private init () { - if (this.helpType === 'markdownText') { - this.mainHtml = this.formatMarkdownSupport(MarkdownService.TEXT_RULES) - return - } - - if (this.helpType === 'markdownEnhanced') { - this.mainHtml = this.formatMarkdownSupport(MarkdownService.ENHANCED_RULES) - return - } - } - - private formatMarkdownSupport (rules: string[]) { - // tslint:disable:max-line-length - return this.i18n('Markdown compatible that supports:') + - this.createMarkdownList(rules) - } - - private createMarkdownList (rules: string[]) { - const rulesToText = { - 'emphasis': this.i18n('Emphasis'), - 'link': this.i18n('Links'), - 'newline': this.i18n('New lines'), - 'list': this.i18n('Lists'), - 'image': this.i18n('Images') - } - - const bullets = rules.map(r => rulesToText[r]) - .filter(text => text) - .map(text => '
  • ' + text + '
  • ') - .join('') - - return '
      ' + bullets + '
    ' - } -} diff --git a/client/src/app/shared/misc/list-overflow.component.html b/client/src/app/shared/misc/list-overflow.component.html deleted file mode 100644 index 986572801..000000000 --- a/client/src/app/shared/misc/list-overflow.component.html +++ /dev/null @@ -1,35 +0,0 @@ -
    - - - - - - - -
    - - - -
    -
    -
    - - - - diff --git a/client/src/app/shared/misc/list-overflow.component.scss b/client/src/app/shared/misc/list-overflow.component.scss deleted file mode 100644 index 1ec044489..000000000 --- a/client/src/app/shared/misc/list-overflow.component.scss +++ /dev/null @@ -1,61 +0,0 @@ -@import '_mixins'; - -:host { - width: 100%; -} - -.list-overflow-parent { - overflow: hidden; -} - -.list-overflow-menu { - position: absolute; - right: 25px; -} - -button { - width: 30px; - border: none; - - &::after { - display: none; - } - - &.routeActive { - &::after { - display: inherit; - border: 2px solid pvar(--mainColor); - position: relative; - right: 95%; - top: 50%; - } - } -} - -::ng-deep .dropdown-menu { - margin-top: 0 !important; - position: static; - right: auto; - bottom: auto -} - -.modal-body { - a { - @include disable-default-a-behaviour; - - color: currentColor; - box-sizing: border-box; - display: block; - font-size: 1.2rem; - padding: 9px 12px; - text-align: initial; - text-transform: unset; - width: 100%; - - &.active { - color: pvar(--mainBackgroundColor) !important; - background-color: pvar(--mainHoverColor); - opacity: .9; - } - } -} diff --git a/client/src/app/shared/misc/list-overflow.component.ts b/client/src/app/shared/misc/list-overflow.component.ts deleted file mode 100644 index 30f43ba43..000000000 --- a/client/src/app/shared/misc/list-overflow.component.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { - AfterViewInit, - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - ElementRef, - HostListener, - Input, - QueryList, - TemplateRef, - ViewChild, - ViewChildren -} from '@angular/core' -import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' -import { lowerFirst, uniqueId } from 'lodash-es' -import { ScreenService } from './screen.service' -import { take } from 'rxjs/operators' - -export interface ListOverflowItem { - label: string - routerLink: string | any[] -} - -@Component({ - selector: 'list-overflow', - templateUrl: './list-overflow.component.html', - styleUrls: [ './list-overflow.component.scss' ], - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class ListOverflowComponent implements AfterViewInit { - @Input() items: T[] - @Input() itemTemplate: TemplateRef<{item: T}> - - @ViewChild('modal', { static: true }) modal: ElementRef - @ViewChild('itemsParent', { static: true }) parent: ElementRef - @ViewChildren('itemsRendered') itemsRendered: QueryList - - showItemsUntilIndexExcluded: number - active = false - isInTouchScreen = false - isInMobileView = false - - private openedOnHover = false - - constructor ( - private cdr: ChangeDetectorRef, - private modalService: NgbModal, - private screenService: ScreenService - ) {} - - ngAfterViewInit () { - setTimeout(() => this.onWindowResize(), 0) - } - - isMenuDisplayed () { - return !!this.showItemsUntilIndexExcluded - } - - @HostListener('window:resize') - onWindowResize () { - this.isInTouchScreen = !!this.screenService.isInTouchScreen() - this.isInMobileView = !!this.screenService.isInMobileView() - - const parentWidth = this.parent.nativeElement.getBoundingClientRect().width - let showItemsUntilIndexExcluded: number - let accWidth = 0 - - for (const [index, el] of this.itemsRendered.toArray().entries()) { - accWidth += el.nativeElement.getBoundingClientRect().width - if (showItemsUntilIndexExcluded === undefined) { - showItemsUntilIndexExcluded = (parentWidth < accWidth) ? index : undefined - } - - const e = document.getElementById(this.getId(index)) - const shouldBeVisible = showItemsUntilIndexExcluded ? index < showItemsUntilIndexExcluded : true - e.style.visibility = shouldBeVisible ? 'inherit' : 'hidden' - } - - this.showItemsUntilIndexExcluded = showItemsUntilIndexExcluded - this.cdr.markForCheck() - } - - openDropdownOnHover (dropdown: NgbDropdown) { - this.openedOnHover = true - dropdown.open() - - // Menu was closed - dropdown.openChange - .pipe(take(1)) - .subscribe(() => this.openedOnHover = false) - } - - dropdownAnchorClicked (dropdown: NgbDropdown) { - if (this.openedOnHover) { - this.openedOnHover = false - return - } - - return dropdown.toggle() - } - - closeDropdownIfHovered (dropdown: NgbDropdown) { - if (this.openedOnHover === false) return - - dropdown.close() - this.openedOnHover = false - } - - toggleModal () { - this.modalService.open(this.modal, { centered: true }) - } - - dismissOtherModals () { - this.modalService.dismissAll() - } - - getId (id: number | string = uniqueId()): string { - return lowerFirst(this.constructor.name) + '_' + id - } -} diff --git a/client/src/app/shared/misc/loader.component.html b/client/src/app/shared/misc/loader.component.html deleted file mode 100644 index ca8ed063e..000000000 --- a/client/src/app/shared/misc/loader.component.html +++ /dev/null @@ -1,8 +0,0 @@ -
    -
    -
    -
    -
    -
    -
    -
    diff --git a/client/src/app/shared/misc/loader.component.scss b/client/src/app/shared/misc/loader.component.scss deleted file mode 100644 index ffac9c707..000000000 --- a/client/src/app/shared/misc/loader.component.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -// Thanks to https://loading.io/css/ (CC0 License) - -.loader { - display: inline-block; - position: relative; - width: 50px; - height: 50px; -} - -.loader div { - box-sizing: border-box; - display: block; - position: absolute; - width: 44px; - height: 44px; - margin: 6px; - border: 4px solid; - border-radius: 50%; - animation: loader 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; - border-color: #999999 transparent transparent transparent; -} - -.loader div:nth-child(1) { - animation-delay: -0.45s; -} - -.loader div:nth-child(2) { - animation-delay: -0.3s; -} - -.loader div:nth-child(3) { - animation-delay: -0.15s; -} - -@keyframes loader { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} diff --git a/client/src/app/shared/misc/loader.component.ts b/client/src/app/shared/misc/loader.component.ts deleted file mode 100644 index e3b1eea3a..000000000 --- a/client/src/app/shared/misc/loader.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, Input } from '@angular/core' - -@Component({ - selector: 'my-loader', - styleUrls: [ './loader.component.scss' ], - templateUrl: './loader.component.html' -}) -export class LoaderComponent { - @Input() loading: boolean -} diff --git a/client/src/app/shared/misc/peertube-web-storage.ts b/client/src/app/shared/misc/peertube-web-storage.ts deleted file mode 100644 index 0db1301bd..000000000 --- a/client/src/app/shared/misc/peertube-web-storage.ts +++ /dev/null @@ -1,81 +0,0 @@ -// Thanks: https://github.com/capaj/localstorage-polyfill - -const valuesMap = new Map() - -function proxify (instance: MemoryStorage) { - return new Proxy(instance, { - set: function (obj, prop: string | number, value) { - if (MemoryStorage.prototype.hasOwnProperty(prop)) { - instance[prop] = value - } else { - instance.setItem(prop, value) - } - return true - }, - get: function (target, name: string | number) { - if (MemoryStorage.prototype.hasOwnProperty(name)) { - return instance[name] - } - if (valuesMap.has(name)) { - return instance.getItem(name) - } - } - }) -} - -class MemoryStorage { - [key: string]: any - [index: number]: string - - getItem (key: any) { - const stringKey = String(key) - if (valuesMap.has(key)) { - return String(valuesMap.get(stringKey)) - } - - return null - } - - setItem (key: any, val: any) { - valuesMap.set(String(key), String(val)) - } - - removeItem (key: any) { - valuesMap.delete(key) - } - - clear () { - valuesMap.clear() - } - - key (i: any) { - if (arguments.length === 0) { - throw new TypeError('Failed to execute "key" on "Storage": 1 argument required, but only 0 present.') - } - - const arr = Array.from(valuesMap.keys()) - return arr[i] - } - - get length () { - return valuesMap.size - } -} - -let peertubeLocalStorage: Storage -let peertubeSessionStorage: Storage -try { - peertubeLocalStorage = localStorage - peertubeSessionStorage = sessionStorage -} catch (err) { - const instanceLocalStorage = new MemoryStorage() - const instanceSessionStorage = new MemoryStorage() - - peertubeLocalStorage = proxify(instanceLocalStorage) - peertubeSessionStorage = proxify(instanceSessionStorage) -} - -export { - peertubeLocalStorage, - peertubeSessionStorage -} diff --git a/client/src/app/shared/misc/screen.service.ts b/client/src/app/shared/misc/screen.service.ts deleted file mode 100644 index a69fad31d..000000000 --- a/client/src/app/shared/misc/screen.service.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Injectable } from '@angular/core' - -@Injectable() -export class ScreenService { - private windowInnerWidth: number - private lastFunctionCallTime: number - private cacheForMs = 500 - - constructor () { - this.refreshWindowInnerWidth() - } - - isInSmallView (marginLeft = 0) { - if (marginLeft > 0) { - const contentWidth = this.getWindowInnerWidth() - marginLeft - return contentWidth < 800 - } - - return this.getWindowInnerWidth() < 800 - } - - isInMediumView () { - return this.getWindowInnerWidth() < 1100 - } - - isInMobileView () { - return this.getWindowInnerWidth() < 500 - } - - isInTouchScreen () { - return 'ontouchstart' in window || navigator.msMaxTouchPoints - } - - getNumberOfAvailableMiniatures () { - const screenWidth = this.getWindowInnerWidth() - - let numberOfVideos = 1 - - if (screenWidth > 1850) numberOfVideos = 7 - else if (screenWidth > 1600) numberOfVideos = 6 - else if (screenWidth > 1370) numberOfVideos = 5 - else if (screenWidth > 1100) numberOfVideos = 4 - else if (screenWidth > 850) numberOfVideos = 3 - - return numberOfVideos - } - - // Cache window inner width, because it's an expensive call - getWindowInnerWidth () { - if (this.cacheWindowInnerWidthExpired()) this.refreshWindowInnerWidth() - - return this.windowInnerWidth - } - - private refreshWindowInnerWidth () { - this.lastFunctionCallTime = new Date().getTime() - - this.windowInnerWidth = window.innerWidth - } - - private cacheWindowInnerWidthExpired () { - if (!this.lastFunctionCallTime) return true - - return new Date().getTime() > (this.lastFunctionCallTime + this.cacheForMs) - } -} diff --git a/client/src/app/shared/misc/small-loader.component.html b/client/src/app/shared/misc/small-loader.component.html deleted file mode 100644 index 7886f8918..000000000 --- a/client/src/app/shared/misc/small-loader.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
    -
    -
    diff --git a/client/src/app/shared/misc/small-loader.component.ts b/client/src/app/shared/misc/small-loader.component.ts deleted file mode 100644 index 191877f14..000000000 --- a/client/src/app/shared/misc/small-loader.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component, Input } from '@angular/core' - -@Component({ - selector: 'my-small-loader', - styleUrls: [ ], - templateUrl: './small-loader.component.html' -}) - -export class SmallLoaderComponent { - @Input() loading: boolean -} diff --git a/client/src/app/shared/misc/storage.service.ts b/client/src/app/shared/misc/storage.service.ts deleted file mode 100644 index 0d4a8ab53..000000000 --- a/client/src/app/shared/misc/storage.service.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Injectable } from '@angular/core' -import { Observable, Subject } from 'rxjs' -import { - peertubeLocalStorage, - peertubeSessionStorage -} from './peertube-web-storage' -import { filter } from 'rxjs/operators' - -abstract class StorageService { - protected instance: Storage - static storageSub = new Subject() - - watch (keys?: string[]): Observable { - return StorageService.storageSub.asObservable().pipe(filter(val => keys ? keys.includes(val) : true)) - } - - getItem (key: string) { - return this.instance.getItem(key) - } - - setItem (key: string, data: any, notifyOfUpdate = true) { - this.instance.setItem(key, data) - if (notifyOfUpdate) StorageService.storageSub.next(key) - } - - removeItem (key: string, notifyOfUpdate = true) { - this.instance.removeItem(key) - if (notifyOfUpdate) StorageService.storageSub.next(key) - } -} - -@Injectable() -export class LocalStorageService extends StorageService { - protected instance: Storage = peertubeLocalStorage -} - -@Injectable() -export class SessionStorageService extends StorageService { - protected instance: Storage = peertubeSessionStorage -} diff --git a/client/src/app/shared/misc/utils.ts b/client/src/app/shared/misc/utils.ts deleted file mode 100644 index bc3ab85b3..000000000 --- a/client/src/app/shared/misc/utils.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { DatePipe } from '@angular/common' -import { environment } from '../../../environments/environment' -import { AuthService } from '../../core/auth' - -// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript -function getParameterByName (name: string, url: string) { - if (!url) url = window.location.href - name = name.replace(/[\[\]]/g, '\\$&') - - const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)') - const results = regex.exec(url) - - if (!results) return null - if (!results[2]) return '' - - return decodeURIComponent(results[2].replace(/\+/g, ' ')) -} - -function populateAsyncUserVideoChannels (authService: AuthService, channel: { id: number, label: string, support?: string }[]) { - return new Promise(res => { - authService.userInformationLoaded - .subscribe( - () => { - const user = authService.getUser() - if (!user) return - - const videoChannels = user.videoChannels - if (Array.isArray(videoChannels) === false) return - - videoChannels.forEach(c => channel.push({ id: c.id, label: c.displayName, support: c.support })) - - return res() - } - ) - }) -} - -function getAbsoluteAPIUrl () { - let absoluteAPIUrl = environment.apiUrl - if (!absoluteAPIUrl) { - // The API is on the same domain - absoluteAPIUrl = window.location.origin - } - - return absoluteAPIUrl -} - -const datePipe = new DatePipe('en') -function dateToHuman (date: string) { - return datePipe.transform(date, 'medium') -} - -function durationToString (duration: number) { - const hours = Math.floor(duration / 3600) - const minutes = Math.floor((duration % 3600) / 60) - const seconds = duration % 60 - - const minutesPadding = minutes >= 10 ? '' : '0' - const secondsPadding = seconds >= 10 ? '' : '0' - const displayedHours = hours > 0 ? hours.toString() + ':' : '' - - return ( - displayedHours + minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString() - ).replace(/^0/, '') -} - -function immutableAssign (target: A, source: B) { - return Object.assign({}, target, source) -} - -function objectToUrlEncoded (obj: any) { - const str: string[] = [] - for (const key of Object.keys(obj)) { - str.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])) - } - - return str.join('&') -} - -// Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34 -function objectToFormData (obj: any, form?: FormData, namespace?: string) { - const fd = form || new FormData() - let formKey - - for (const key of Object.keys(obj)) { - if (namespace) formKey = `${namespace}[${key}]` - else formKey = key - - if (obj[key] === undefined) continue - - if (Array.isArray(obj[key]) && obj[key].length === 0) { - fd.append(key, null) - continue - } - - if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) { - objectToFormData(obj[ key ], fd, formKey) - } else { - fd.append(formKey, obj[ key ]) - } - } - - return fd -} - -function objectLineFeedToHtml (obj: any, keyToNormalize: string) { - return immutableAssign(obj, { - [keyToNormalize]: lineFeedToHtml(obj[keyToNormalize]) - }) -} - -function lineFeedToHtml (text: string) { - if (!text) return text - - return text.replace(/\r?\n|\r/g, '
    ') -} - -function removeElementFromArray (arr: T[], elem: T) { - const index = arr.indexOf(elem) - if (index !== -1) arr.splice(index, 1) -} - -function sortBy (obj: any[], key1: string, key2?: string) { - return obj.sort((a, b) => { - const elem1 = key2 ? a[key1][key2] : a[key1] - const elem2 = key2 ? b[key1][key2] : b[key1] - - if (elem1 < elem2) return -1 - if (elem1 === elem2) return 0 - return 1 - }) -} - -function scrollToTop () { - window.scroll(0, 0) -} - -// Thanks: https://github.com/uupaa/dynamic-import-polyfill -function importModule (path: string) { - return new Promise((resolve, reject) => { - const vector = '$importModule$' + Math.random().toString(32).slice(2) - const script = document.createElement('script') - - const destructor = () => { - delete window[ vector ] - script.onerror = null - script.onload = null - script.remove() - URL.revokeObjectURL(script.src) - script.src = '' - } - - script.defer = true - script.type = 'module' - - script.onerror = () => { - reject(new Error(`Failed to import: ${path}`)) - destructor() - } - script.onload = () => { - resolve(window[ vector ]) - destructor() - } - const absURL = (environment.apiUrl || window.location.origin) + path - const loader = `import * as m from "${absURL}"; window.${vector} = m;` // export Module - const blob = new Blob([ loader ], { type: 'text/javascript' }) - script.src = URL.createObjectURL(blob) - - document.head.appendChild(script) - }) -} - -function isInViewport (el: HTMLElement) { - const bounding = el.getBoundingClientRect() - return ( - bounding.top >= 0 && - bounding.left >= 0 && - bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) && - bounding.right <= (window.innerWidth || document.documentElement.clientWidth) - ) -} - -function isXPercentInViewport (el: HTMLElement, percentVisible: number) { - const rect = el.getBoundingClientRect() - const windowHeight = (window.innerHeight || document.documentElement.clientHeight) - - return !( - Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible || - Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible - ) -} - -export { - sortBy, - durationToString, - lineFeedToHtml, - objectToUrlEncoded, - getParameterByName, - populateAsyncUserVideoChannels, - getAbsoluteAPIUrl, - dateToHuman, - immutableAssign, - objectToFormData, - objectLineFeedToHtml, - removeElementFromArray, - importModule, - scrollToTop, - isInViewport, - isXPercentInViewport -} -- cgit v1.2.3