{"version":3,"file":"7918.86e08d35390aaffe.js","mappings":"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","names":["PAGE","ClipsService","_ClipsService","constructor","store","sentryService","clipsApi","youtubeService","analyticsService","this","getPoster","clip","res","poster","DEFAULT_POSTER","youtube_id","getThumbnail","url","createClipFromFilestack","filestackResult","projectId","userId","_this","_asyncToGenerator","uploadTags","lastModifiedDate","duration","environment","production","console","log","warn","Error","newVideo","filename","type","mimetype","size","Date","toISOString","loading","originalFile","lastModified","convertVideoFileToClip","source","src","filestackConfig","storeTo","path","orig","key","name","file","id","Utils","removeFileExt","filmingDate","getDateTimeString","createClip","then","newClip","subClipsUpdated","dispatch","mystackActions","toFixed","seconds","durationInSeconds","clipUpload","error","DEBUG_LOGS","hlsMeta","HLS_META_TRANSCODE","Clip","clipActions","catch","err","Array","isArray","errors","length","errorType","info","message","params","sub","subscribeClipsUpdated","subscribe","next","updates","JSON","parse","hlsSrc","sources","Object","keys","isHlsComplete","unsubscribe","captureError","errorMessage","complete","getPosterTimeFromPoster","sNum","substring","lastIndexOf","parsed","parseInt","updatePosterToPosterTime","posterTime","newPoster","slice","startIndex","endIndex","handleSubClips","i0","i1","i2","i3","i4","i5","factory","ɵfac","providedIn","TabFabContainerComponent","_TabFabContainerComponent","_viewContainerRef","router","initialUrl","subscriptions","Subscription","ngAfterViewInit","attachPortal","subscription","events","pipe","filter","e","NavigationEnd","distinctUntilChanged","route","setTimeout","outlet","hasAttached","detach","add","ngOnDestroy","DomPortalOutlet","document","querySelector","portal","TemplatePortal","portalContent","attachTemplatePortal","selectors","viewQuery","rf","ctx","TabFabContainerComponent_ng_template_0_Template","PortalModule","encapsulation","list_r2","_r1","ngIf","ctx_r2","loadMoreStacks","headingWithDefault","_c1","layoutType","Carousel","_c0","stackList","items$","nextToken","label","CarouselGuidesComponent","_CarouselGuidesComponent","translate","LAYOUT_TYPE","listId","showListIfEmpty","ngOnInit","labelWithDefault","list$","select","selectList","selectStackListItems","shareReplay","stackActions","filters","GUIDES_PROJECT","FilterEntityTypes","Featured","q","instant","heading","list","inputs","standalone","features","decls","vars","consts","template","CarouselGuidesComponent_ng_container_0_Template","tmp_0_0","NgIf","AsyncPipe","StackListComponent","user_r2","$implicit","viewUserProfile","avatarFallback","tmp_4_0","undefined","tmp_5_0","tmp_6_0","UserListPopoverComponent","_UserListPopoverComponent","modalController","popoverCtrl","users","DEFAULT_USER_AVATAR_TERTIARY","modal","create","component","ProjectMemberModalComponent","componentProps","cssClass","dismiss","present","UserListPopoverComponent_ion_item_1_Template","IonLabel","IonAvatar","IonItem","IonList","NgFor","ImageFadeInDirective","ImageFallbackDirective","AvatarUrlPipe","styles","$event","_r4","viewUserList","hiddenUsersCount_r5","AvatarStackComponent","_AvatarStackComponent","_users","value","threshold","_threshold","changeDetectorRef","platform","modalOpened","EventEmitter","avatarStack","show","hide","avatarStackItemSize","avatarStackItemSizePx","onDestroy$","Subject","resize","refreshAvatarStack","forEach","u","i","selectMember","takeUntil","us","take","user","username","splitAvatarStackOnThreshold","_a","_b","_c","_d","currentThreshold","getDynamicThreshold","detectChanges","Math","floor","avatarStackEl","nativeElement","clientWidth","trackByFn","index","_this2","emit","event","_this3","popover","showBackdrop","data","selected","onDidDismiss","AvatarStackComponent_div_2_Template","AvatarStackComponent_div_3_Template","IonBadge","changeDetection","NoStackClipsDisclaimerComponent","_NoStackClipsDisclaimerComponent","configService","navCtrl","DISCOVER_LINK_ID","onDiscoverClick","preventDefault","stopPropagation","eltClass","target","attributes","getNamedItem","getStackDiscoverPath","navigateForward","hostBindings","TranslatePipe","_r2","onPlayerEnded","onVideoPlaying","onPlaylistDone","playerId","stack_r4","clips","currentPlaylistIndex$","isPageShowing","doHlsDestroy","project$","StackPlayPage_section_5_div_1_Template","hasStackClips","_r5","toggleExplore","i_r8","_r7","playIndex","clip_r9","isVideoPlaying","currentClipDetail_r10","description","StackPlayPage_ng_container_8_div_2_div_9_div_1_div_7_Template","isShowingClipDetails","tmp_16_0","title","StackPlayPage_ng_container_8_div_2_div_9_div_1_Template","_r11","pausePlayer","avatarStackThreshold","contributors","_c2","tmp_9_0","_c3","stack_r12","stackId","_c4","routeProjectDetail","project_r13","routerLinkJoin","_r14","approveStack","StackPlayPage_ng_container_8_div_2_div_25_ion_spinner_3_Template","approvingStack","_r15","_r16","confirmTranscode","StackPlayPage_ng_container_8_div_2_div_27_ion_item_1_ion_spinner_3_Template","StackPlayPage_ng_container_8_div_2_div_27_ion_item_1_span_6_Template","optimizingStack","isAllClipsHls","StackPlayPage_ng_container_8_div_2_div_27_ion_item_1_Template","dtePublished","hasYoutubeClips","StackPlayPage_ng_container_8_div_2_fs_thumbnail_poster_4_Template","_r6","togglePlaylist","StackPlayPage_ng_container_8_div_2_div_9_Template","StackPlayPage_ng_container_8_div_2_ng_container_17_Template","StackPlayPage_ng_container_8_div_2_ng_template_18_Template","StackPlayPage_ng_container_8_div_2_div_20_Template","StackPlayPage_ng_container_8_div_2_div_22_Template","StackPlayPage_ng_container_8_div_2_div_24_Template","StackPlayPage_ng_container_8_div_2_div_25_Template","StackPlayPage_ng_container_8_div_2_div_26_Template","StackPlayPage_ng_container_8_div_2_div_27_Template","openTabFab","fabClick","addAllClipsToStack","addClipToStack","isPlaylistOpen","enableClipDetails","currentClip$","dteSaved","views","shares","singleContributor_r17","currentUserId$","showJoinButton","isProjectAdmin","isProjectModerated","isApproved","isStackPublic","doHlsDebug","isSiteAdmin","canApprove","isProjectMember","StackPlayPage_ng_container_8_div_1_Template","StackPlayPage_ng_container_8_div_2_Template","enableExplore","isExploreOpen","noClips_r18","StackPlayPage_ng_template_12_div_0_Template","STACK_PLAY_PLAYER_ID","StackPlayPage","_StackPlayPage","activatedRoute","snapshot","paramMap","get","inviteType","toLowerCase","alertCtrl","toaster","projectService","projectMemberService","stackService","clipsService","userService","videoPlayerService","videoService","tokensService","renderer","pageTitle","ENABLE_EXPLORE","isStackLoading","userId$","PROJECT_DETAIL_ROUTE","selectedItemSuccess$","BehaviorSubject","topDrawerExpand$","topDrawerClose$","_wasPageShowing","isFabOpen","_playlistSelected","_incExpandEvent","_incCloseEvent","token$","onOrientationChange","orient","ready","is","stack$","selectAndGetPlay","x","y","playlist","stringify","tap","stack","clearTimeout","contributorTimeout","loadMembers","userIds","map","c","privacy","STACK_PRIVACY","PUBLIC","getProjectPreview","p","project","isModerated","getInviteTypeFromProject","loadingTimeout","providerId","HLS_META_UPGRADE_PROP","sendStackForHLSTranscode","selectCurrentPlayIndex","currentPlaylistIndex","getSelectedStackCurrentPlayClip","currentClip","ClipActions","t","isTokenExpired","token","projectRole","eventType","payload","returnUrl","isLandscape","userIsGlobalAdmin$","isAdmin","window","addEventListener","evt","ionViewWillEnter","ionViewWillLeave","closeTabFab","pause","play","scrollToItem","playlistScroller","smoothScrollTo","expandDraftDrawer","showCreateForm","closeDraftDrawer","tabFab","activated","close","isCreateNew","draftDrawerExpanded","draftDrawerSelected","draftDrawerNewItem","navigate","_ref2","_x","apply","arguments","header","subHeader","buttons","text","role","handler","_","i6","i7","i8","i9","i10","i11","i12","i13","IonContent","StackPlayPage_section_5_Template","StackPlayPage_ng_container_8_Template","StackPlayPage_ng_template_10_Template","StackPlayPage_ng_template_12_Template","loading_r19","RouterLink","FormsModule","i14","StackPopoverActionsComponent","TopNavbarComponent","ThumbnailPosterComponent","UploaderStatsComponent","VideoPlayerComponent","IonHeader","IonButton","IonIcon","IonThumbnail","IonSpinner","IonText","IonToggle","IonNote","IonFab","IonFabButton","IonFabList","IonChip","IonCard","IonCardContent","IonSkeletonText"],"ignoreList":[],"sourceRoot":"webpack:///","sources":["./src/app/clips/shared/services/clips.service.ts","./src/app/shared/components/tab-fab-container/tab-fab-container.component.html","./src/app/shared/components/tab-fab-container/tab-fab-container.component.ts","./src/app/stacks/carousels/carousel-guides/carousel-guides.component.html","./src/app/stacks/carousels/carousel-guides/carousel-guides.component.ts","./src/app/shared/components/user-list-popover/user-list-popover.component.html","./src/app/shared/components/user-list-popover/user-list-popover.component.ts","./src/app/shared/components/ui/avatar-stack/avatar-stack.component.html","./src/app/shared/components/ui/avatar-stack/avatar-stack.component.ts","./src/app/stacks/shared/components/no-stack-clips-disclaimer/no-stack-clips-disclaimer.component.ts","./src/app/stacks/stack-play/stack-play.page.html","./src/app/stacks/stack-play/stack-play.page.ts"],"sourcesContent":["/** @format */\n\nimport { Injectable } from '@angular/core';\nimport { Store } from '@ngrx/store';\nimport { State } from '@store/reducers';\nimport * as clipActions from '@store/actions/clips.actions';\nimport * as mystackActions from '@store/actions/mystack.actions';\nimport { ClipsApiService } from '@app/core/api/clips-api.service';\nimport { AnalyticsService } from '@app/core/services/analytics/analytics.service';\nimport { SentryService } from '@app/core/services/sentry.service';\nimport { YoutubeService } from '@app/core/services/youtube.service';\nimport { Utils } from '@app/shared/utils';\nimport { ClipVideoFile, Clip } from '@app/shared/models/clip.model';\nimport { convertVideoFileToClip, isHlsComplete } from '@app/shared/models/clip.model';\nimport { HLS_META_TRANSCODE, DEFAULT_POSTER } from '@app/shared/models/clip.model';\nimport { environment, filestackConfig } from 'src/environments/environment';\n\nconst DEBUG_LOGS = false;\nconst PAGE = '[ClipsService]';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class ClipsService {\n constructor(\n private store: Store<State>,\n private sentryService: SentryService,\n private clipsApi: ClipsApiService,\n private youtubeService: YoutubeService,\n private analyticsService: AnalyticsService\n ) {}\n\n getPoster(clip: Clip, res: string = 'default') {\n let poster = DEFAULT_POSTER;\n if (clip) {\n if (clip.poster) {\n poster = clip.poster;\n } else if (clip.youtube_id) {\n poster = this.youtubeService.getThumbnail(clip.youtube_id, res).url;\n }\n }\n return poster;\n }\n\n /**\n * Create a new Clip from the FileStack Upload\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async createClipFromFilestack(filestackResult: any, projectId: string, userId: string) {\n DEBUG_LOGS && console.log(`createClipFromFilestack filestackResult =`, filestackResult);\n const {\n uploadTags: {\n lastModifiedDate = null, // = (new Date()).toISOString(),\n // filesize = filestackResult.size, // don't use the stringified from uploadTags\n duration = 0,\n } = {},\n } = filestackResult;\n // MVP-1169 file selected metadata\n !environment.production &&\n console.log(`get size & updatedDate from filestackResult:`, { lastModifiedDate, duration, filestackResult });\n\n if (!filestackResult || !projectId) {\n console.warn(`${PAGE} createClipFromFilestack missing required params`, { filestackResult, projectId });\n throw new Error('Missing required parameters - unable to create clip.');\n }\n\n const newVideo: ClipVideoFile = {\n filename: filestackResult.filename,\n type: filestackResult.mimetype,\n size: filestackResult.size,\n lastModifiedDate: new Date().toISOString(),\n loading: true,\n };\n\n // get additional metadata if it exists.\n if (lastModifiedDate) {\n newVideo.lastModifiedDate = lastModifiedDate;\n } else if (filestackResult.originalFile) {\n if (\n filestackResult.originalFile.lastModifiedDate &&\n typeof filestackResult.originalFile.lastModifiedDate.toISOString === 'function'\n ) {\n newVideo.lastModifiedDate = filestackResult.originalFile.lastModifiedDate.toISOString();\n } else if (filestackResult.originalFile.lastModified) {\n newVideo.lastModifiedDate = new Date(filestackResult.originalFile.lastModified).toISOString();\n }\n }\n\n // create our clip...\n const clip = convertVideoFileToClip(newVideo);\n clip.source = clip.source || {};\n // it is important that this startsWith(filestackConfig.storeTo.path) in the clipApi logic\n clip.source.src = filestackConfig.storeTo.clip.path + newVideo.filename;\n clip.source.orig = filestackResult.key;\n clip.source.filename = newVideo.filename;\n clip.source.type = newVideo.type;\n clip.source.loading = newVideo.loading;\n clip.source.lastModifiedDate = newVideo.lastModifiedDate;\n\n if (filestackResult.originalFile && filestackResult.originalFile.name) {\n clip.source.file = filestackResult.originalFile;\n }\n // this must match for api to do its magic...\n clip.id = Utils.removeFileExt(newVideo.filename);\n clip.projectId = projectId;\n\n if (typeof clip.filmingDate !== 'string') {\n clip.filmingDate = Utils.getDateTimeString(clip.filmingDate);\n }\n\n DEBUG_LOGS && console.log(`${PAGE} createClipFromFilestack -> createClip:`, clip);\n\n // kick off the createClip flow, subscribe to updates, add to mystack\n // as soon as we return, the Capture Page will nav to the Stack Editor\n return this.createClip(clip).then((newClip) => {\n DEBUG_LOGS &&\n console.log(`${PAGE} createClipFromFilestack -> now watch updates & addToStack (createClip result:`, newClip);\n // watch changes and push to store\n this.subClipsUpdated(newClip.projectId, newClip.id, userId);\n // add the clip to the Editor\n this.store.dispatch(mystackActions.addClip({ clip: newClip }));\n\n try {\n // analytics\n const size =\n newVideo && newVideo.size && typeof newVideo.size.toFixed === 'function' ? newVideo.size.toFixed(0) : false;\n const seconds =\n clip.source && clip.source.durationInSeconds && typeof clip.source.durationInSeconds.toFixed === 'function'\n ? clip.source.durationInSeconds.toFixed(3)\n : false;\n this.analyticsService.clipUpload({\n projectId: newClip.projectId,\n id: newClip.id,\n userId: newClip.userId,\n ...(seconds && { seconds }),\n ...(size && { size }),\n });\n } catch (error) {\n console.warn(`Analytics error:`, error);\n }\n });\n }\n\n /**\n * upload clip and add to store\n * @param clip\n * 1. Create the clip in DB\n * 2.\n */\n createClip(clip: Clip): Promise<Clip> {\n DEBUG_LOGS && console.log(`${PAGE} createClip`, clip);\n\n // add the new HLS transcoding instruction\n clip.hlsMeta = {\n ...(clip.hlsMeta || {}),\n ...HLS_META_TRANSCODE,\n };\n\n return this.clipsApi\n .createClip(clip)\n .then((res) => {\n DEBUG_LOGS && console.log(`${PAGE} createClip res:`, res);\n // add the clip to the Store\n const newClip = new Clip(res);\n this.store.dispatch(clipActions.addClip({ clip: newClip }));\n return newClip;\n })\n .catch((err) => {\n if (\n err &&\n Array.isArray(err.errors) &&\n err.errors.length > 0 &&\n err.errors[0] &&\n err.errors[0].errorType &&\n err.errors[0].errorType === 'DynamoDB:ConditionalCheckFailedException'\n ) {\n console.info(`${PAGE} createClip already Exists:`, err);\n return new Clip(clip);\n }\n console.error(`${PAGE} createClip err:`, err);\n if (err && Array.isArray(err.errors) && err.errors.length > 0 && err.errors[0].message) {\n throw err.errors[0].message;\n }\n throw err;\n });\n }\n\n /**\n * clipUpdate GraphQL Subscription\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n subClipsUpdated(projectId: string, id = '', userId = '') {\n const params: { projectId: string; id?: string } = {\n projectId,\n };\n if (id) {\n params.id = id;\n }\n // not currently using userId on this GQL subscription in the API\n // if (userId) { params.userId = userId; }\n\n // keeping the sub variable local so there can be multiple open subs\n const sub = this.clipsApi.subscribeClipsUpdated(params).subscribe({\n next: (res) => {\n // todo: convert to handleSubClips(res) when this not needed by editor\n DEBUG_LOGS && console.log(`${PAGE} clipsUpdatedSubscription next:`, res);\n if (!res || !res.id || !res.projectId) {\n throw new Error('Missing clip id in subscription?');\n }\n const updates: Partial<Clip> = {};\n let hlsMeta;\n if (res.hlsMeta) {\n try {\n hlsMeta = typeof res.hlsMeta === 'string' ? JSON.parse(res.hlsMeta) : res.hlsMeta;\n updates.hlsMeta = hlsMeta;\n } catch (error) {\n console.log(`Caught error during JSON.parse(res.hlsMeta):`, {\n hlsMeta: res.hlsMeta,\n error: error.message || error,\n });\n }\n }\n if (res.hlsSrc) {\n updates.hlsSrc = res.hlsSrc;\n }\n if (Array.isArray(res.sources) && res.sources.length > 0) {\n updates.sources = res.sources;\n }\n if (res.poster) {\n updates.poster = res.poster;\n }\n if (res.duration) {\n updates.duration = res.duration;\n }\n\n if (Object.keys(updates).length > 0) {\n // take the updates and flow to store...\n this.store.dispatch(\n clipActions.updateClipTranscoding({\n projectId: res.projectId,\n id: res.id,\n updates,\n })\n );\n DEBUG_LOGS &&\n console.log(`${PAGE} clipsUpdatedSubscription updateClipTranscoding:`, {\n projectId: res.projectId,\n id: res.id,\n updates,\n });\n }\n\n if (isHlsComplete(new Clip(updates))) {\n // when complete, this.unsubClipsUpdated()\n sub.unsubscribe();\n }\n },\n error: (err) => {\n console.warn(`${PAGE} clipsUpdatedSubscription ERROR:`, err);\n this.sentryService.captureError(err);\n\n if (projectId && id) {\n this.store.dispatch(\n clipActions.updateClipTranscoding({\n projectId,\n id,\n updates: {\n hlsMeta: {\n errorMessage: err.message || err.errorMessage || err,\n },\n },\n })\n );\n }\n sub.unsubscribe();\n },\n complete: () => {\n DEBUG_LOGS && console.log(`${PAGE} clipsUpdatedSubscription => Complete`);\n },\n });\n }\n //end GraphQL Subscription\n\n /**\n * Take the poster string and return poster time from the transcoded name\n * example poster path:\n * https://videos.filmstacker.com/public/filmstacker-dev/jd_-_jd-note_202203021348/jd_-_jd-note_202203021348_thumb.0000000.jpg\n */\n getPosterTimeFromPoster(clip: Clip) {\n if (clip && clip.poster) {\n const sNum = clip.poster.substring(clip.poster.lastIndexOf('_thumb.'), clip.poster.lastIndexOf('.'));\n // there shouldn't be any dashes anymore\n // const sTime = sNum.replace(/-/g, '').replace(/0/gi, '');\n try {\n const parsed = parseInt(sNum, 10);\n return parsed > 0 ? parsed : 0;\n } catch (error) {\n return 0;\n }\n }\n return 0;\n }\n\n /**\n * Update the poster image to match the new posterTime\n *\n * @todo verify it exists in s3\n * potential ref: https://stackoverflow.com/questions/9815762/detect-when-an-image-fails-to-load-in-javascript\n *\n * example poster path:\n * https://videos.filmstacker.com/public/filmstacker-dev/jd_-_jd-note_202203021348/jd_-_jd-note_202203021348_thumb.0000000.jpg\n */\n updatePosterToPosterTime(clip: Clip, posterTime: number) {\n if (clip && clip.poster) {\n let newPoster = clip.poster;\n const sNum = ('0000000' + posterTime).slice(-7);\n const startIndex = newPoster.lastIndexOf('_thumb.') + '_thumb.'.length;\n const endIndex = newPoster.lastIndexOf('.');\n newPoster = newPoster.slice(0, startIndex) + sNum + newPoster.slice(endIndex);\n console.log(`${PAGE} change clip.poster (TODO: verify it exists in s3) posterTime: ${posterTime} to:`, {\n sNum,\n newPoster,\n });\n return newPoster;\n } else {\n console.warn(`${PAGE} missing clip.poster - unable to change`, clip);\n return null;\n }\n }\n\n /**\n * @deprecated unused - use subClipsUpdated\n * Do what we need with the clip we just received\n */\n private handleSubClips(res) {\n DEBUG_LOGS && console.log(`${PAGE} handleSubClips next:`, res);\n if (!res || !res.id || !res.projectId) {\n throw new Error('Missing clip id in subscription?');\n }\n // if any values exist not null, add them as changes?\n const updates: Partial<Clip> = {};\n let hlsMeta;\n if (res.hlsMeta) {\n try {\n hlsMeta = typeof res.hlsMeta === 'string' ? JSON.parse(res.hlsMeta) : res.hlsMeta;\n updates.hlsMeta = hlsMeta;\n } catch (error) {\n console.log(`Caught error during JSON.parse(res.hlsMeta):`, {\n hlsMeta: res.hlsMeta,\n error: error.message || error,\n });\n }\n }\n if (res.hlsSrc) {\n updates.hlsSrc = res.hlsSrc;\n }\n if (Array.isArray(res.sources) && res.sources.length > 0) {\n updates.sources = res.sources;\n }\n if (res.poster) {\n updates.poster = res.poster;\n }\n if (res.duration) {\n updates.duration = res.duration;\n }\n\n // take the updates and flow to store...\n // this.store.dispatch(clipActions.updateClipTranscoding({\n // projectId: res.projectId,\n // id: res.id,\n // updates,\n // }));\n }\n}\n","<!-- @format -->\n\n<ng-template #portalContent><ng-content></ng-content></ng-template>\n","/** @format */\n\nimport { PortalModule, DomPortalOutlet, TemplatePortal } from '@angular/cdk/portal';\nimport { AfterViewInit, Component, OnDestroy, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';\nimport { NavigationEnd, Router, RouterEvent, Event as RouterEvents } from '@angular/router';\nimport { Subscription } from 'rxjs';\nimport { distinctUntilChanged, filter } from 'rxjs/operators';\n\n@Component({\n selector: 'fs-tab-fab-container',\n templateUrl: './tab-fab-container.component.html',\n standalone: true,\n imports: [PortalModule],\n})\nexport class TabFabContainerComponent implements OnDestroy, AfterViewInit {\n @ViewChild('portalContent') portalContent: TemplateRef<unknown>;\n\n outlet: DomPortalOutlet;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n portal: TemplatePortal<any>;\n\n initialUrl = this.router.url;\n\n private subscriptions = new Subscription();\n\n constructor(private _viewContainerRef: ViewContainerRef, private router: Router) {}\n\n ngAfterViewInit() {\n this.attachPortal();\n // watch over route changes to detach or re-attach portals.\n // reason: if a route has a defined portal in its template and the user routes away from it,\n // that route only gets detached from the change detection. thus it will stay in the DOM, no update logic.\n // that is why we work on the update logic manually ourselves.\n const subscription = this.router.events\n .pipe(\n filter((e: Event | RouterEvent | RouterEvents): e is RouterEvent => e instanceof NavigationEnd),\n distinctUntilChanged()\n )\n .subscribe((route: RouterEvent) => {\n if (route.url === this.initialUrl) {\n // for change detection reasons we need to delay this operation\n setTimeout(() => {\n this.attachPortal();\n });\n }\n if (this.outlet.hasAttached()) {\n this.outlet.detach();\n }\n });\n this.subscriptions.add(subscription);\n }\n\n ngOnDestroy() {\n this.subscriptions.unsubscribe();\n }\n\n private attachPortal() {\n this.outlet = new DomPortalOutlet(document.querySelector('#tab-portal-container'));\n this.portal = new TemplatePortal(this.portalContent, this._viewContainerRef);\n this.outlet.attachTemplatePortal(this.portal);\n }\n}\n","<ng-container *ngIf=\"((stackList.items$ | async)?.length > 0 || showListIfEmpty) && (stackList.list$ | async) as list\">\n <h3>{{ headingWithDefault }}</h3>\n <app-stack-list \n [layout]=\"{\n type: layoutType.Carousel,\n options: {\n hasAddNewItemButton: false\n }\n }\"\n [items]=\"stackList.items$ | async\"\n [canLoadMore]=\"!!list.nextToken\"\n [isLoading]=\"list.loading\"\n [heading]=\"stackList.label\"\n (loadMore)=\"loadMoreStacks(list)\"\n ></app-stack-list>\n</ng-container>\n\n","/** @format */\n\nimport { Component, Input, OnInit } from '@angular/core';\nimport { NgIf, AsyncPipe } from '@angular/common';\nimport { shareReplay } from 'rxjs/operators';\nimport { TranslateService } from '@ngx-translate/core';\nimport { Store } from '@ngrx/store';\nimport { State } from '@store/reducers';\nimport * as stackActions from '@store/actions/stacks.actions';\nimport { List, selectList, selectStackListItems } from '@store/selectors/lists.selectors';\nimport { FilterEntityTypes } from '@store/selectors/viewstate.selectors';\nimport { GUIDES_PROJECT } from '@app/app.config';\nimport { LAYOUT_TYPE } from '@app/shared/models/layout.model';\nimport { StackList } from '@app/shared/models/list.model';\nimport { StackListComponent } from '@app/stacks/shared/components/stack-list/stack-list.component';\n\nconst CAROUSEL_GUIDES_LIST_ID = 'carousel_guides';\nconst CAROUSEL_GUIDES_HEADING = 'DISCOVER.GUIDES.HEADING';\nconst CAROUSEL_GUIDES_LABEL = 'DISCOVER.GUIDES.LABEL';\n\n@Component({\n selector: 'fs-carousel-guides',\n templateUrl: './carousel-guides.component.html',\n styleUrls: ['./carousel-guides.component.scss'],\n standalone: true,\n imports: [NgIf, AsyncPipe, StackListComponent],\n})\nexport class CarouselGuidesComponent implements OnInit {\n stackList: StackList;\n layoutType = LAYOUT_TYPE;\n\n @Input() heading: string;\n @Input() label: string;\n @Input() listId = CAROUSEL_GUIDES_LIST_ID;\n @Input() showListIfEmpty = true;\n\n constructor(private translate: TranslateService, private store: Store<State>) {}\n\n ngOnInit() {\n this.stackList = {\n id: this.listId,\n label: this.labelWithDefault,\n list$: this.store.select(selectList(this.listId)),\n items$: this.store.select(selectStackListItems(this.listId)).pipe(shareReplay(1)),\n };\n\n this.store.dispatch(\n stackActions.loadFilteredStacks({\n listId: this.listId,\n filters: {\n // : FilterEntity\n projectId: GUIDES_PROJECT,\n type: FilterEntityTypes.Featured,\n id: this.listId,\n q: null,\n },\n })\n );\n }\n\n get labelWithDefault() {\n return this.label ?? this.translate.instant(CAROUSEL_GUIDES_LABEL);\n }\n\n get headingWithDefault() {\n return this.heading ?? this.translate.instant(CAROUSEL_GUIDES_HEADING);\n }\n\n loadMoreStacks(list: List) {\n this.store.dispatch(\n stackActions.loadMoreFilteredStacks({\n listId: list.id,\n filters: list.filters,\n nextToken: list.nextToken,\n })\n );\n }\n}\n","<ion-list class=\"light users-popover\" lines=\"none\">\n <ion-item\n *ngFor=\"let user of users\"\n button\n small\n detail=\"false\"\n (click)=\"viewUserProfile(user.userId)\"\n >\n <ion-avatar class=\"users-popover__avatar\" slot=\"start\">\n <img\n class=\"users-popover__avatar__image\"\n [src]=\"user.userId | avatarUrl:'dark'\"\n [fallback]=\"avatarFallback\"\n imageFadeIn\n [alt]=\"user?.name ?? user.userId\"\n [title]=\"user?.name ?? user.userId\"\n />\n </ion-avatar>\n <!-- <ion-text style=\"padding-left: 0; white-space: nowrap\" slot=\"start\"> -->\n <ion-label>\n {{ user?.name ?? user.userId }}\n </ion-label>\n </ion-item>\n</ion-list>\n","/** @format */\n\nimport { Component, Input } from '@angular/core';\nimport { NgFor } from '@angular/common';\nimport { ModalController, PopoverController, IonList, IonItem, IonAvatar, IonLabel } from '@ionic/angular/standalone';\nimport { User, DEFAULT_USER_AVATAR_TERTIARY } from '@app/shared/models/user.model';\nimport { AvatarUrlPipe } from '@app/shared/pipes/avatar-url.pipe';\nimport { ImageFadeInDirective } from '@app/shared/directives/image-fade-in.directive';\nimport { ImageFallbackDirective } from '@app/shared/directives/image-fallback.directive';\nimport { ProjectMemberModalComponent } from '@app/project-members/project-member-modal/project-member-modal.component';\n\n@Component({\n selector: 'app-user-list-popover',\n templateUrl: './user-list-popover.component.html',\n styleUrls: ['./user-list-popover.component.scss'],\n standalone: true,\n imports: [IonLabel, IonAvatar, IonItem, IonList, NgFor, ImageFadeInDirective, ImageFallbackDirective, AvatarUrlPipe],\n})\nexport class UserListPopoverComponent {\n @Input() users: Partial<User>[] = [];\n\n avatarFallback = DEFAULT_USER_AVATAR_TERTIARY;\n\n constructor(private modalController: ModalController, private popoverCtrl: PopoverController) {}\n\n async viewUserProfile(userId: string) {\n const modal = await this.modalController.create({\n component: ProjectMemberModalComponent,\n componentProps: {\n userId,\n },\n cssClass: 'modal-lg',\n });\n this.popoverCtrl.dismiss({ userId });\n return await modal.present();\n }\n}\n","<div class=\"avatar-stack\" #avatarStackContainer>\n <div class=\"avatar-stack__item\" *ngFor=\"let user of avatarStack.show; trackBy: trackByFn\">\n <ion-avatar class=\"avatar-stack__item__avatar\">\n <img class=\"avatar-stack__item__avatar__image\"\n [src]=\"user.userId | avatarUrl\"\n [fallback]\n imageFadeIn\n [alt]=\"user.userId\"\n [title]=\"user.name || user.userId\"\n (click)=\"viewUserProfile(user.userId)\" />\n </ion-avatar>\n </div>\n <div class=\"avatar-stack__item\" *ngIf=\"avatarStack?.hide?.length; let hiddenUsersCount\">\n <ion-badge\n class=\"avatar-stack__item__badge\"\n color=\"primary\"\n (click)=\"viewUserList($event)\"\n >+{{hiddenUsersCount}}\n </ion-badge>\n </div>\n</div>","/** @format */\n\nimport {\n Component,\n Input,\n OnInit,\n ViewChild,\n ElementRef,\n HostBinding,\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n OnDestroy,\n EventEmitter,\n Output,\n} from '@angular/core';\nimport { NgFor, NgIf } from '@angular/common';\nimport { IonAvatar, IonBadge, ModalController, Platform, PopoverController } from '@ionic/angular/standalone';\nimport { Subject } from 'rxjs';\nimport { filter, take, takeUntil } from 'rxjs/operators';\nimport { Store } from '@ngrx/store';\nimport { selectMember } from '@store/selectors/members.selectors';\nimport { User } from '@app/shared/models/user.model';\nimport { UserListPopoverComponent } from '@app/shared/components/user-list-popover/user-list-popover.component';\nimport { ImageFallbackDirective } from '@app/shared/directives/image-fallback.directive';\nimport { AvatarUrlPipe } from '@app/shared/pipes/avatar-url.pipe';\nimport { ProjectMemberModalComponent } from '@app/project-members/project-member-modal/project-member-modal.component';\n\n/** it is more interesting to show all users than just the hidden ones */\nconst SHOW_ALL_IN_POPUP = true;\n\n@Component({\n selector: 'fs-avatar-stack',\n templateUrl: './avatar-stack.component.html',\n styleUrls: ['./avatar-stack.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [NgFor, NgIf, ImageFallbackDirective, AvatarUrlPipe, IonAvatar, IonBadge],\n})\nexport class AvatarStackComponent implements OnInit, AfterViewInit, OnDestroy {\n @Input()\n get users() {\n return this._users;\n }\n set users(value: Partial<User>[]) {\n this._users = value;\n }\n\n @Input()\n get threshold() {\n return this._threshold;\n }\n set threshold(value: number) {\n this._threshold = value;\n }\n\n @Output() modalOpened = new EventEmitter<string>();\n\n public avatarStack = {\n show: [],\n hide: [],\n };\n\n @ViewChild('avatarStackContainer', { static: false }) avatarStackEl: ElementRef;\n\n private _threshold: number;\n private avatarStackItemSize = 36;\n @HostBinding('style.--avatar-size')\n private avatarStackItemSizePx = `${this.avatarStackItemSize}px`;\n\n /** inner users for names */\n private _users: Partial<User>[] = [];\n\n private onDestroy$ = new Subject<void>();\n\n constructor(\n private store: Store,\n private changeDetectorRef: ChangeDetectorRef,\n private modalController: ModalController,\n private platform: Platform,\n private popoverCtrl: PopoverController\n ) {}\n\n ngOnInit(): void {\n this.platform.resize.subscribe(async () => {\n this.refreshAvatarStack();\n });\n\n (this.users || []).forEach((u, i) => {\n if (u?.userId) {\n this.store\n .select(selectMember(u.userId))\n .pipe(\n takeUntil(this.onDestroy$),\n filter((us) => us?.userId?.length > 0),\n take(1)\n )\n .subscribe((user) => {\n if (user?.userId) {\n this._users[i].name = user.name || user.username || user.userId;\n }\n });\n }\n });\n }\n\n ngAfterViewInit(): void {\n this.refreshAvatarStack();\n const REFRESH_EL_DELAY = 1000;\n setTimeout(() => {\n // First iteration could omit side elements, observed on stack-play where content-actions side-bar width is omitted by getDynamicThreshold.\n this.refreshAvatarStack();\n }, REFRESH_EL_DELAY);\n }\n\n ngOnDestroy(): void {\n this.onDestroy$.next();\n this.onDestroy$.complete();\n }\n\n splitAvatarStackOnThreshold(threshold: number) {\n /**\n * Avoid showing only one more Elt badge\n */\n if (this.users?.slice(threshold).length === 1) {\n threshold = this.users?.length;\n }\n this.avatarStack = {\n show: this.users?.slice(0, threshold),\n hide: this.users?.slice(threshold),\n };\n }\n\n refreshAvatarStack() {\n const currentThreshold = this.threshold ?? this.getDynamicThreshold();\n\n this.splitAvatarStackOnThreshold(currentThreshold);\n this.changeDetectorRef.detectChanges();\n }\n\n /**\n * Min threshold is 1, to avoid showing only more Elt w/o any avatar\n */\n getDynamicThreshold(): number {\n const avatarStackWidth = this.avatarStackEl.nativeElement.clientWidth;\n const threshold = Math.floor(avatarStackWidth / this.avatarStackItemSize) - 2;\n\n return threshold > 0 ? threshold : 1;\n }\n\n trackByFn(index, user) {\n return user?.userId ?? index;\n }\n\n async viewUserProfile(id: string) {\n const modal = await this.modalController.create({\n component: ProjectMemberModalComponent,\n componentProps: {\n userId: id,\n },\n cssClass: 'modal-lg',\n });\n this.modalOpened.emit(id);\n return await modal.present();\n }\n\n async viewUserList(event: MouseEvent) {\n const users = SHOW_ALL_IN_POPUP ? this.users : this.avatarStack?.hide ?? [];\n const popover = await this.popoverCtrl.create({\n component: UserListPopoverComponent,\n componentProps: {\n users,\n },\n cssClass: 'user-list-popover',\n showBackdrop: false, // allow to see video when opened\n event,\n });\n await popover.present();\n const { data: { userId: selected = '' } = {} } = await popover.onDidDismiss();\n if (selected) {\n this.modalOpened.emit(selected);\n }\n }\n}\n","/** @format */\n\nimport { Component, HostListener } from '@angular/core';\nimport { NavController } from '@ionic/angular/standalone';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { ConfigService } from '@app/core/config/config.service';\n\n@Component({\n selector: 'app-no-stack-clips-disclaimer',\n template: `\n <div class=\"ion-padding\">\n <h2>{{ 'PLAYER.INTRO_HEADER' | translate }}</h2>\n <p [innerHTML]=\"'PLAYER.INTRO_TEXT' | translate\"></p>\n </div>\n `,\n // styles: [':host >>> span { color: red; }'],\n styleUrls: ['./no-stack-clips-disclaimer.component.scss'],\n standalone: true,\n imports: [TranslatePipe],\n})\nexport class NoStackClipsDisclaimerComponent {\n DISCOVER_LINK_ID = 'discover_link';\n\n constructor(private configService: ConfigService, private navCtrl: NavController) {}\n\n @HostListener('click', ['$event'])\n onDiscoverClick(event: Event) {\n event.preventDefault();\n event.stopPropagation();\n const elt = event.target as HTMLElement;\n const eltClass = elt.attributes.getNamedItem('class');\n if (eltClass && eltClass.value === this.DISCOVER_LINK_ID) {\n this.configService.getStackDiscoverPath().then((path) => {\n this.navCtrl.navigateForward(path);\n });\n }\n }\n}\n","<ion-header style=\"z-index:300;\">\n <app-top-navbar \n [title]=\"pageTitle\" \n [drawerEnabled]=\"true\"\n \n [drawerExpandEvent]=\"topDrawerExpand$ | async\"\n [drawerCloseEvent]=\"topDrawerClose$ | async\"\n [drawerSelectedItemSuccess]=\"selectedItemSuccess$ | async\"\n (drawerSelected)=\"draftDrawerSelected($event)\"\n (drawerNewItem)=\"draftDrawerNewItem($event)\"\n (drawerExpand)=\"draftDrawerExpanded($event)\"\n (drawerClose)=\"draftDrawerExpanded($event)\"\n >\n </app-top-navbar>\n</ion-header>\n<section *ngIf=\"stack$ | async as stack\">\n <!-- MVP-989 note that ngIf= && isPageShowing will cause playlist to restart from the beginning -->\n <div class=\"player-wrap\" *ngIf=\"hasStackClips\">\n <app-video-player\n #topPlayer\n [playerId]=\"playerId\"\n [stack]=\"stack\"\n [playlist]=\"stack.clips\"\n [currentIndex]=\"currentPlaylistIndex$ | async\"\n [autoplay]=\"isPageShowing\"\n [fullscreen]=\"false\"\n [handlePlaylistDone]=\"true\"\n [doHlsDestroy]=\"doHlsDestroy\"\n [project]=\"project$ | async\"\n (videoDone)=\"onPlayerEnded($event)\"\n (videoPlaying)=\"onVideoPlaying($event)\"\n (playlistDone)=\"onPlaylistDone($event)\"\n ></app-video-player>\n </div>\n</section>\n<ion-content forceOverflow=\"false\">\n <ng-container *ngIf=\"!isStackLoading && (stack$ | async) as stack; else loading\">\n <div class=\"panel-action\" *ngIf=\"enableExplore && !isExploreOpen && stack.stackId\">\n <ion-button class=\"explore-action-btn ion-text-uppercase\" color=\"medium\" (click)=\"toggleExplore()\">\n {{ 'PLAYER.EXPLORE_TAB' | translate }}\n </ion-button>\n </div>\n <div class=\"container\" *ngIf=\"hasStackClips; else noClips\">\n <div\n class=\"content\"\n [class.content--collapsed-sidebar]=\"isPlaylistOpen\"\n >\n <div class=\"content__left ion-padding-top\" scrollY=\"true\" #playlistScroller>\n <fs-thumbnail-poster\n *ngFor=\"let clip of stack.clips; ; let i = index\"\n [item]=\"clip\"\n [isPlaying]=\"i === (currentPlaylistIndex$ | async) && isVideoPlaying\"\n [isCurrent]=\"i === (currentPlaylistIndex$ | async)\"\n [showAvatar]=\"true\"\n (click)=\"playIndex(i)\"\n ></fs-thumbnail-poster>\n <div class=\"tab-bottom-spacer\"></div>\n </div>\n <div class=\"content__right ion-padding-top\" scrollY=\"true\"\n [class.content__right--expanded]=\"isPlaylistOpen\"\n >\n <ion-button color=\"medium\" class=\"content__right__collapser ion-padding-top\" fill=\"clear\" (click)=\"togglePlaylist()\">\n <ion-icon [name]=\"isPlaylistOpen ? 'chevron-forward-outline' : 'chevron-back-outline'\"></ion-icon>\n </ion-button>\n\n <div *ngIf=\"enableClipDetails && (currentClip$ | async) as currentClipDetail\" class=\"clip-details\">\n <div *ngIf=\"currentClipDetail?.id\" [class.clip-details__showing]=\"isShowingClipDetails\" class=\"clip-details__wrap ion-padding-bottom\">\n <ion-item lines=\"none\">\n <ion-thumbnail slot=\"start\" class=\"clip-details__poster\">\n <fs-thumbnail-poster\n [item]=\"currentClipDetail\"\n [showAvatar]=\"false\"\n [showDuration]=\"false\"\n [showActionIcon]=\"false\"\n ></fs-thumbnail-poster>\n </ion-thumbnail>\n <ion-label>\n <div class=\"clip-details__title\">\n {{ currentClipDetail?.title ?? currentClipDetail.id }}\n </div>\n <div *ngIf=\"currentClipDetail?.description\" class=\"clip-details__description\">\n {{ currentClipDetail.description }}\n </div>\n </ion-label>\n </ion-item>\n </div>\n </div>\n\n <h1>{{ stack.title }}</h1>\n \n <fs-uploader-stats\n [userId]=\"stack.userId\"\n [date]=\"stack.dteSaved\"\n [showAvatar]=\"true\"\n [views]=\"stack.views\"\n [shares]=\"stack.shares\"\n [stacks]=\"stack?.clips?.length\"\n [stacksTitle]=\"'Clips'\"\n ></fs-uploader-stats>\n\n <p>{{ stack.description }}</p>\n\n <div class=\"content__right__contributors\">\n <ng-container *ngIf=\"contributors?.length > 1; else singleContributor\">\n <div class=\"content__right__contributors__stack\">\n <fs-avatar-stack [threshold]=\"avatarStackThreshold\" [users]=\"contributors\" (modalOpened)=\"pausePlayer()\"></fs-avatar-stack>\n </div>\n <div class=\"content__right__contributors__label\">\n <ion-icon name=\"people-outline\"></ion-icon>\n <span>\n {{'STACK.CONTRIBUTORS_LABEL.PLURAL' | translate: { count: contributors.length } }}\n </span>\n </div>\n <div style=\"clear: both\"></div>\n </ng-container>\n </div>\n\n <ng-template #singleContributor>\n {{'STACK.CONTRIBUTORS_LABEL.SINGULAR' | translate: { count: contributors?.length ?? 1 } }}\n </ng-template>\n\n \n\n <div *ngIf=\"(currentUserId$ | async) === stack.userId && !stack.dtePublished\" class=\"content__right__draft-actions\">\n <ion-button fill=\"outline\" [routerLink]=\"['/stack/edit', stack.projectId, stack.stackId]\">\n {{ 'COMMON.EDIT' | translate }}\n </ion-button>\n <!-- Needs upgraded to v3 MVP-1146 -->\n <ion-button [routerLink]=\"['/stack/edit', stack.projectId, stack.stackId]\">\n {{ 'COMMON.PUBLISH' | translate }}\n </ion-button>\n </div>\n\n <div *ngIf=\"project$ | async as project\" class=\"ion-padding-top\">\n {{ 'COMMON.PROJECT' | translate }}:\n <a [routerLink]=\"[routeProjectDetail, stack.projectId]\">{{ project.title }}</a>\n </div>\n\n <div class=\"container ion-text-center ion-padding\" *ngIf=\"showJoinButton\">\n <ion-button size=\"large\" [routerLink]=\"routerLinkJoin\" queryParamsHandling=\"preserve\">\n {{ 'COMMON.JOIN_AS_CREW' | translate }}\n </ion-button>\n </div>\n\n <div *ngIf=\"isProjectAdmin && isProjectModerated && !stack.isApproved && stack.dtePublished && isStackPublic\" class=\"ion-padding-top\">\n <!-- if you're a project admin & this stack needs approved -->\n <ion-item lines=\"none\">\n <ion-button slot=\"end\"\n fill=\"outline\" \n [disabled]=\"approvingStack\"\n (click)=\"approveStack(stack)\">\n <ion-spinner *ngIf=\"approvingStack\" slot=\"start\"></ion-spinner>\n <ion-label>\n {{ 'STACK.ACTIONS.APPROVE' | translate }}\n </ion-label>\n </ion-button>\n </ion-item>\n </div>\n\n <!-- HLS Dev tool -->\n <div *ngIf=\"doHlsDebug\" class=\"ion-padding-top ion-margin-top\">\n <!-- HLS Player optimization test - Attach/Re-Attach or Destroy/Build -->\n <ion-text color=\"medium\" style=\"font-size:80%\">HLS DEV:</ion-text>\n <ion-item style=\"--padding-start:0;--padding-end:0;\" lines=\"none\">\n <ion-toggle slot=\"end\" [enableOnOffLabels]=\"true\" [(ngModel)]=\"doHlsDestroy\" style=\"padding:0\">\n <div class=\"ion-text-capitalize ion-text-wrap\" style=\"font-size:70%;padding:0;margin:0;margin-right:3px;\">Re/Attach</div>\n </ion-toggle>\n <ion-note slot=\"end\" color=\"ion-color-medium\" style=\"white-space:normal;font-size:70%;\">Destroy<br>/build</ion-note>\n </ion-item>\n </div>\n\n <!-- HLS Dev tool -->\n <div *ngIf=\"isSiteAdmin && stack\">\n <!-- if you're a site admin & this stack need upgraded (and not a draft), offer it -->\n <ion-item *ngIf=\"!stack.hlsSrc && stack.dtePublished && !hasYoutubeClips\" class=\"ion-padding-top ion-margin-top\" style=\"--padding-start:0;--padding-end:0;\" lines=\"none\">\n <ion-label slot=\"end\" style=\"font-size:70%;padding:0;margin:0;margin-right:3px;\">\n <ion-button \n fill=\"outline\" \n [disabled]=\"optimizingStack\"\n (click)=\"confirmTranscode()\">\n <ion-spinner *ngIf=\"optimizingStack\" slot=\"start\"></ion-spinner>\n <ion-label>\n Upgrad{{ optimizingStack ? 'ing' : 'e' }} Stack <span *ngIf=\"!isAllClipsHls\"> Clips </span> to HLS\n </ion-label>\n </ion-button>\n </ion-label>\n </ion-item>\n </div>\n\n <div class=\"tab-bottom-spacer\"></div>\n </div>\n <div class=\"content__actions ion-padding-top\" scrollY=\"true\">\n <div class=\"reserve-space-add-fab\"></div>\n \n <!-- isProjectAdmin && isProjectModerated && !stack.isApproved -->\n <app-stack-popover-actions \n [stack]=\"stack\" \n [currentClip]=\"currentClip$ | async\"\n [isModerated]=\"isProjectModerated\"\n [canApprove]=\"canApprove\"\n [canAddToStack]=\"false\"\n [doHandleAddToStack]=\"false\"\n [isProjectMember]=\"isProjectMember || isProjectAdmin\"\n [isProjectAdmin]=\"isProjectAdmin\"\n (addToStack)=\"openTabFab($event)\"\n ></app-stack-popover-actions>\n </div>\n <!-- moved from tab-fab-container MVP-1336 -->\n <ion-fab class=\"popover-fab\" #tabFabPlayer>\n <ion-fab-button size=\"default\" (click)=\"fabClick($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-list side=\"bottom\">\n <ion-chip outline=\"true\" (click)=\"addAllClipsToStack($event)\">\n <ion-label>{{ 'CLIP.USE_ALL_CLIPS' | translate }}</ion-label>\n </ion-chip>\n <ion-chip outline=\"true\" (click)=\"addClipToStack($event)\">\n <ion-label>{{ 'CLIP.USE_THIS_CLIP' | translate }}</ion-label>\n </ion-chip>\n </ion-fab-list>\n </ion-fab>\n </div> \n <!-- end .content -->\n </div>\n\n <!-- todo: enableExplore\n <div *ngIf=\"enableExplore\" hidden slot=\"fixed\" class=\"explore-panel\" [class.explore-expanded]=\"isExploreOpen\">\n <div *ngIf=\"stack.stackId\" class=\"explore-panel-contents\" scrollY=\"true\" #explorePanelScroller #fitContentHeight>\n <div class=\"panel-action-close\" *ngIf=\"isExploreOpen\">\n <ion-button class=\"explore-action-btn ion-text-uppercase\" color=\"medium\" (click)=\"toggleExplore()\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.STORYLINES' | translate }}\n </ion-button>\n </div>\n <div>\n <app-explore-ui drawerId=\"playerId\" [helpText]=\"\" [scroller]=\"explorePanelScroller\"></app-explore-ui>\n </div>\n </div>\n </div> -->\n\n\n <fs-tab-fab-container>\n <!-- Moved the tab to actions container MVP-1336 -->\n <!-- <ion-fab *ngIf=\"stack.stackId\" class=\"tab-fab\" #tabFabPlayer>\n <ion-fab-button (click)=\"fabClick($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-list side=\"top\">\n <ion-chip outline=\"true\" (click)=\"addAllClipsToStack($event)\">\n <ion-label>{{ 'CLIP.USE_ALL_CLIPS' | translate }}</ion-label>\n </ion-chip>\n <ion-chip outline=\"true\" (click)=\"addClipToStack($event)\">\n <ion-label>{{ 'CLIP.USE_THIS_CLIP' | translate }}</ion-label>\n </ion-chip>\n </ion-fab-list>\n </ion-fab> -->\n </fs-tab-fab-container>\n </ng-container>\n</ion-content>\n\n<ng-template #loading>\n <ion-card>\n <ion-card-content>\n <div style=\"height: 200px\">\n <ion-skeleton-text animated></ion-skeleton-text>\n </div>\n </ion-card-content>\n <ion-item>\n <ion-label>\n <h3>\n <ion-skeleton-text animated style=\"width: 50%\"></ion-skeleton-text>\n </h3>\n <p>\n <ion-skeleton-text animated style=\"width: 80%\"></ion-skeleton-text>\n </p>\n <p>\n <ion-skeleton-text animated style=\"width: 60%\"></ion-skeleton-text>\n </p>\n </ion-label>\n </ion-item>\n </ion-card>\n</ng-template>\n\n<ng-template #noClips>\n <div *ngIf=\"errorMessage\" class=\"error-message ion-padding\">{{ errorMessage }}</div>\n <app-no-stack-clips-disclaimer></app-no-stack-clips-disclaimer>\n\n <div class=\"ion-padding ion-margin-vertical\">\n <fs-carousel-guides></fs-carousel-guides>\n </div>\n</ng-template>","/** @format */\n\nimport { ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core';\nimport { NgIf, NgFor, AsyncPipe } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { ActivatedRoute, Router, RouterLink } from '@angular/router';\nimport {\n IonContent,\n Platform,\n AlertController,\n IonFab,\n IonHeader,\n IonButton,\n IonIcon,\n IonItem,\n IonThumbnail,\n IonLabel,\n IonSpinner,\n IonText,\n IonToggle,\n IonNote,\n IonFabButton,\n IonFabList,\n IonChip,\n IonCard,\n IonCardContent,\n IonSkeletonText,\n} from '@ionic/angular/standalone';\nimport { TranslateService, TranslatePipe } from '@ngx-translate/core';\nimport { BehaviorSubject, Observable, Subject } from 'rxjs';\nimport { distinctUntilChanged, filter, shareReplay, take, takeUntil, tap } from 'rxjs/operators';\nimport { Store } from '@ngrx/store';\nimport { State } from '@store/reducers';\nimport * as stackActions from '@store/actions/stacks.actions';\nimport * as ClipActions from '@store/actions/clips.actions';\nimport { loadMembers } from '@store/actions/members.actions';\nimport { getSelectedStackCurrentPlayClip, selectCurrentPlayIndex } from '@store/selectors/stacks.selectors';\n\nimport { UserService } from '@app/core/services/user.service';\nimport { ToasterService } from '@app/core/services/toaster.service';\nimport { VideoService } from '@app/core/services/video.service';\nimport { ThumbnailPosterComponent } from '@app/shared/components/thumbnail-poster/thumbnail-poster.component';\nimport { UploaderStatsComponent } from '@app/shared/components/ui/upload-stats/uploader-stats.component';\nimport { AvatarStackComponent } from '@app/shared/components/ui/avatar-stack/avatar-stack.component';\nimport { TabFabContainerComponent } from '@app/shared/components/tab-fab-container/tab-fab-container.component';\nimport { TopNavbarComponent } from '@app/shared/components/top-navbar/top-navbar.component';\nimport { Clip } from '@app/shared/models/clip.model';\nimport { HLS_META_UPGRADE_PROP } from '@app/shared/models/clip.model';\nimport { Stack, STACK_PRIVACY } from '@app/shared/models/stack.model';\nimport { User } from '@app/shared/models/user.model';\nimport { StackPopoverActionsComponent } from '@app/shared/components/fs-carousel/fs-slide/stack-slide/stack-popover-actions/stack-popover-actions.component';\nimport { Utils } from '@app/shared/utils';\nimport { ClipsService } from '@app/clips/shared/services/clips.service';\nimport { StackService } from '@app/stacks/shared/services/stack.service';\nimport { CarouselGuidesComponent } from '@app/stacks/carousels/carousel-guides/carousel-guides.component';\nimport { NoStackClipsDisclaimerComponent } from '@app/stacks/shared/components/no-stack-clips-disclaimer/no-stack-clips-disclaimer.component';\nimport { Project } from '@app/projects/shared/project.model';\nimport { ProjectService } from '@app/projects/shared/services/project.service';\nimport { ProjectMemberService } from '@app/project-members/shared/services/project-member.service';\nimport { getInviteTypeFromProject } from '@app/onboarding/shared/onboarding.model';\nimport { isTokenExpired, Token } from '@app/tokens/shared/tokens.model';\nimport { TokensService } from '@app/tokens/shared/services/tokens.service';\nimport { VideoPlayerService } from '@app/modules/video-player/shared/services/video-player.service';\nimport { VideoPlayerComponent } from '@app/modules/video-player/video-player.component';\nimport { PROJECT_DETAIL_ROUTE } from '@app/app.routes';\nimport { ENABLE_EXPLORE } from '@app/app.config';\nimport { environment } from 'src/environments/environment';\n\nconst DEBUG_LOGS = false;\n/**\n * if the stack is ready for transcoding, do we send it?\n * Maybe not... allow the Plyr to handle it? But what about non-optimized stacks?\n */\nconst DO_TRANSCODE_IF_CAN = true;\n\n/** works well in theory, but glitchy in ios */\nconst DO_SCROLL_TO_ITEM = false;\nconst ENABLE_CLIP_DETAILS = true;\n\nconst ITEM_EL_HEIGHT = 125 + 12; // the px height of each item (poster + margin)\nexport const STACK_PLAY_PLAYER_ID = 'stack-play';\n@Component({\n selector: 'app-stack-play',\n templateUrl: './stack-play.page.html',\n styleUrls: ['./stack-play.page.scss'],\n standalone: true,\n imports: [\n NgIf,\n NgFor,\n RouterLink,\n AsyncPipe,\n TranslatePipe,\n FormsModule,\n StackPopoverActionsComponent,\n TopNavbarComponent,\n ThumbnailPosterComponent,\n UploaderStatsComponent,\n AvatarStackComponent,\n TabFabContainerComponent,\n NoStackClipsDisclaimerComponent,\n CarouselGuidesComponent,\n VideoPlayerComponent,\n IonHeader,\n IonContent,\n IonButton,\n IonIcon,\n IonItem,\n IonThumbnail,\n IonLabel,\n IonSpinner,\n IonText,\n IonToggle,\n IonNote,\n IonFab,\n IonFabButton,\n IonFabList,\n IonChip,\n IonCard,\n IonCardContent,\n IonSkeletonText,\n ],\n})\nexport class StackPlayPage implements OnInit, OnDestroy {\n /** @todo for dev, to be removed */\n doHlsDestroy = true;\n doHlsDebug = false;\n\n stack$: Observable<Stack>;\n project$: Observable<Project>;\n currentPlaylistIndex$: Observable<number>;\n currentClip$: Observable<Clip>;\n currentClip: Clip;\n currentPlaylistIndex: number;\n\n public contributors: Partial<User>[];\n\n pageTitle = 'Stack';\n playerId = STACK_PLAY_PLAYER_ID;\n enableClipDetails = ENABLE_CLIP_DETAILS;\n isShowingClipDetails = false;\n enableExplore = ENABLE_EXPLORE;\n isExploreOpen = false;\n isPlaylistOpen = false;\n hasStackClips = false;\n isStackLoading = true;\n isVideoPlaying = false;\n errorMessage = '';\n\n /** MVP-1003 Project.isModerated */\n isProjectAdmin = false;\n isProjectMember = false;\n isProjectModerated = false;\n approvingStack = false;\n isStackPublic = false;\n\n currentUserId$: Observable<string> = this.userService.userId$;\n\n inviteType = '';\n\n get projectId() {\n return this.activatedRoute.snapshot.paramMap.get('projectId');\n }\n get stackId() {\n return this.activatedRoute.snapshot.paramMap.get('stackId');\n }\n\n get canApprove(): boolean {\n return this.isProjectModerated && this.isProjectAdmin;\n }\n\n get routerLinkJoin() {\n return '/events' + (this.inviteType ? '/' + this.inviteType.toLowerCase() : '') + '/accept/' + this.projectId || '';\n }\n routeProjectDetail = `/${PROJECT_DETAIL_ROUTE}`;\n\n showJoinButton = false;\n // topDrawerExpand = false;\n selectedItemSuccess$: BehaviorSubject<boolean> = new BehaviorSubject(false);\n topDrawerExpand$: BehaviorSubject<{ i: number; showCreateForm?: boolean }> = new BehaviorSubject({ i: 0 });\n topDrawerClose$: BehaviorSubject<number> = new BehaviorSubject(0);\n\n /**\n * Stack Playlist HLS Upgrades MVP-983\n */\n isSiteAdmin = false;\n isAllClipsHls = false;\n hasYoutubeClips = false;\n optimizingStack = false;\n\n @ViewChild(IonContent, { read: IonContent }) content: IonContent;\n @ViewChild('tabFabPlayer') tabFab: IonFab;\n @ViewChild('playlistScroller') playlistScroller: ElementRef;\n\n /** for autoplay logic, based on ionViewEnter/Leave */\n isPageShowing = true;\n avatarStackThreshold = null;\n private _wasPageShowing = true;\n private isFabOpen = false;\n private onDestroy$ = new Subject<void>();\n private loadingTimeout;\n private contributorTimeout;\n private itemSelectedTimeout;\n private _playlistSelected = [];\n private _incExpandEvent = 0;\n private _incCloseEvent = 0;\n\n private token$: Observable<Token> = this.tokensService.token$;\n\n constructor(\n private activatedRoute: ActivatedRoute,\n private platform: Platform,\n private alertCtrl: AlertController,\n private toaster: ToasterService,\n private projectService: ProjectService,\n private projectMemberService: ProjectMemberService,\n private stackService: StackService,\n private clipsService: ClipsService,\n private userService: UserService,\n private store: Store<State>,\n private videoPlayerService: VideoPlayerService,\n private videoService: VideoService,\n private tokensService: TokensService,\n private translate: TranslateService,\n private router: Router,\n private changeDetectorRef: ChangeDetectorRef,\n public renderer: Renderer2\n ) {}\n\n ngOnInit(): void {\n this.platform.ready().then(() => {\n /**\n * To not break layout show max of 3 avatars of stack.contributors on desktop\n * https://filmstacker.atlassian.net/browse/MVP-1236\n */\n this.avatarStackThreshold = this.platform.is('desktop') ? 3 : null;\n });\n // const projectId = this.activatedRoute.snapshot.paramMap.get('projectId');\n // const stackId = this.activatedRoute.snapshot.paramMap.get('stackId');\n this.stack$ = this.stackService.selectAndGetPlay(this.projectId, this.stackId).pipe(\n takeUntil(this.onDestroy$),\n distinctUntilChanged(\n (x, y) =>\n x &&\n y &&\n x.stackId === y.stackId &&\n x.views === y.views &&\n x.shares === y.shares &&\n x.clips &&\n y.clips &&\n x.clips.length === y.clips.length &&\n x.playlist &&\n y.playlist &&\n x.playlist.length === y.playlist.length &&\n x.hlsSrc === y.hlsSrc &&\n x.error === y.error &&\n // get changes for playlist\n JSON.stringify(x.playlist) === JSON.stringify(y.playlist) &&\n x.isApproved === y.isApproved &&\n // include hlsMeta changes\n x.hlsMeta &&\n y.hlsMeta &&\n (typeof x.hlsMeta === 'string'\n ? x.hlsMeta === y.hlsMeta\n : JSON.stringify(x.hlsMeta) === JSON.stringify(y.hlsMeta))\n ),\n tap((stack: Stack) => {\n DEBUG_LOGS && console.log(`[Play] Stack updated:`, stack);\n try {\n if (stack) {\n //typeof stack !== 'undefined') {\n this.hasStackClips = stack.clips && !!stack.clips.length;\n this.pageTitle = stack && stack.title ? stack.title : this.pageTitle;\n\n this.contributors = stack.contributors;\n if (stack.contributors?.length > 0) {\n clearTimeout(this.contributorTimeout);\n this.contributorTimeout = setTimeout(() => {\n this.store.dispatch(loadMembers({ userIds: stack.contributors.map((c) => c.userId) }));\n }, 600);\n } else {\n this.contributors = [{ userId: stack.userId }];\n }\n\n this.isStackPublic = stack.privacy === STACK_PRIVACY.PUBLIC;\n\n if (stack.projectId) {\n this.project$ = this.projectService.getProjectPreview(stack.projectId).pipe(\n filter((p) => p && p.id && p.id.length > 0),\n take(1), // make sure you only take 1\n tap((project) => {\n // check if project isModerated and if so am i an admin?\n this.isProjectModerated = !!project.isModerated;\n this.isProjectAdmin = this.projectService.isProjectAdmin(project);\n this.isProjectMember = this.projectService.isProjectMember(project);\n // check if it's a wedding\n this.inviteType = getInviteTypeFromProject(project);\n !environment.production &&\n this.inviteType &&\n console.log(`check if it's a wedding`, { inviteType: this.inviteType, project });\n }),\n shareReplay(1)\n );\n }\n // now done loading if ready\n if (this.hasStackClips) {\n clearTimeout(this.loadingTimeout);\n this.loadingTimeout = setTimeout(() => {\n this.isStackLoading = false;\n }, 400); // just a slight delay so we don't show the carousel content...\n } else {\n // delay a doneLoading...\n clearTimeout(this.loadingTimeout);\n this.loadingTimeout = setTimeout(() => {\n this.isStackLoading = false;\n }, 1200);\n }\n\n // check if all clips are hls MVP-983\n if (this.hasStackClips) {\n if (stack.hlsSrc) {\n this.optimizingStack = false;\n } else {\n // !stack.hlsSrc\n this.optimizingStack = false;\n this.hasYoutubeClips = stack.clips.filter((c) => c && (c.providerId || c.youtube_id)).length > 0;\n this.isAllClipsHls = stack.clips.filter((c) => c && !c.hlsSrc).length < 1 && !this.hasYoutubeClips;\n // if all the clips have hlsSrc and there's no youtube, do it automatically\n // there's no hlsSrc right now, so if there's not a upgrade prop set, upgrade..\n // & if this is NOT A DRAFT (pending MVP-1091)\n if (\n stack.dtePublished &&\n DO_TRANSCODE_IF_CAN &&\n this.isAllClipsHls &&\n (!stack.hlsMeta || !stack.hlsMeta[HLS_META_UPGRADE_PROP])\n ) {\n // not currently set to be upgraded, do it\n this.optimizingStack = true;\n // the stack is ready to be upgraded, all clips are already done...\n this.sendStackForHLSTranscode();\n }\n }\n }\n }\n if (stack && stack.error) {\n this.errorMessage = stack.error;\n console.warn(`stackService.selectAndGetPlay Error: ${this.errorMessage}`);\n } else {\n this.errorMessage = '';\n }\n } catch (error) {\n console.warn(`[Watch] Caught error in stack$.tap`, error);\n }\n }),\n shareReplay(1)\n );\n\n this.currentPlaylistIndex$ = this.store.select(selectCurrentPlayIndex).pipe(\n tap((index) => {\n this.currentPlaylistIndex = index;\n if (DO_SCROLL_TO_ITEM) {\n this.scrollToItem(index);\n }\n })\n );\n this.currentClip$ = this.store.select(getSelectedStackCurrentPlayClip).pipe(\n filter((res) => typeof res !== 'undefined'),\n tap((clip) => {\n this.currentClip = clip;\n this.store.dispatch(ClipActions.play({ clip }));\n })\n );\n\n // not crew, check if token for join\n this.token$\n .pipe(\n takeUntil(this.onDestroy$),\n filter((t) => t && t.id && !isTokenExpired(t))\n )\n .subscribe((token: Token) => {\n const {\n projectId,\n projectRole,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n eventType = '',\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n payload: { returnUrl = '', message = '' },\n } = token;\n\n this.showJoinButton = projectRole && projectId === this.projectId;\n !environment.production &&\n console.log(`[Token] payload roleMatching:`, { showJoinButton: this.showJoinButton, token });\n });\n\n this.platform.resize.subscribe(async () => {\n if (this.platform.isLandscape() && this.platform.is('desktop')) {\n /** why was this here? i can think of instances why i wondered why this opened... */\n // this.isExploreOpen = true;\n }\n });\n\n /**\n * Check currentUser Cognito Groups for Admin access to platform\n * MVP-983\n */\n this.userService.userIsGlobalAdmin$\n .pipe(\n takeUntil(this.onDestroy$)\n // filter((isAdmin) => !!isAdmin)\n )\n .subscribe((isAdmin) => {\n this.isSiteAdmin = !!isAdmin;\n });\n\n /**\n * MVP-989 Stop Video Player when not active\n * https://developer.mozilla.org/en-US/docs/Web/API/Window/blur_event\n */\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n window.addEventListener('blur', (evt) => {\n this._wasPageShowing = !!this.isPageShowing;\n this.isPageShowing = false;\n });\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n window.addEventListener('focus', (evt) => {\n this.isPageShowing = !!this._wasPageShowing;\n });\n } catch (error) {\n console.warn(`No Window, no eventListener`, error);\n }\n }\n\n ionViewWillEnter() {\n this.isPageShowing = true;\n }\n ionViewWillLeave() {\n !environment.production && console.log(`[DEV] player autoplay should now be false..`);\n\n // MVP-989 note that this was ngIf for video-player element in template, causing it to restart from the beginning\n this.isPageShowing = false; // MVP-989\n this.closeTabFab();\n this.pausePlayer();\n this.changeDetectorRef.detectChanges();\n\n // reset any lingering topnav-drawer playlist actions\n this.store.dispatch(stackActions.resetAddToStackPlaylist());\n }\n\n ngOnDestroy() {\n this.onDestroy$.next();\n this.onDestroy$.complete();\n }\n\n pausePlayer() {\n this.videoPlayerService.pause(this.playerId);\n }\n\n playIndex(index: number) {\n if (index === this.currentPlaylistIndex) {\n if (this.isVideoPlaying) {\n this.videoPlayerService.pause(this.playerId);\n } else {\n this.videoPlayerService.play(this.playerId);\n }\n } else {\n this.store.dispatch(stackActions.playCurrentIndex({ index }));\n }\n }\n scrollToItem(index: number) {\n try {\n // if not isPlaylistOpen, avoid any waste of processing to scroll unneccessarily\n if (!this.playlistScroller || !this.playlistScroller.nativeElement || !this.isPlaylistOpen) {\n return;\n }\n const scrollSpeed = 1000;\n // subtract 1 to keep one played item above, instead of current at top\n const scrollTop = index === 0 ? 0 : (index - 1) * ITEM_EL_HEIGHT;\n Utils.smoothScrollTo(this.playlistScroller.nativeElement, scrollTop, scrollSpeed);\n } catch (error) {\n console.error('Scroll to item failed:', error);\n }\n }\n toggleExplore() {\n this.isExploreOpen = !this.isExploreOpen;\n }\n togglePlaylist() {\n this.isPlaylistOpen = !this.isPlaylistOpen;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onPlaylistDone(event) {\n this.isShowingClipDetails = false;\n this.isExploreOpen = true;\n this.stack$.pipe(take(1)).subscribe((stack) => {\n this.store.dispatch(stackActions.watchComplete({ projectId: stack.projectId, stackId: stack.stackId }));\n });\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onOrientationChange = (orient) => {\n this.isExploreOpen = false;\n };\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onPlayerEnded(event) {\n this.store.dispatch(stackActions.playNextClip());\n }\n onVideoPlaying(isVideoPlaying: boolean) {\n !environment.production &&\n console.log(`[DEV] onVideoPlaying=${isVideoPlaying} isPageShowing=${this.isPageShowing}`);\n if (this.isPageShowing) {\n this.isVideoPlaying = isVideoPlaying;\n if (!this.isShowingClipDetails) {\n this.isShowingClipDetails = true;\n }\n } else {\n // MVP-989 pause if the page is not showing (view not active or window blurred)\n this.videoPlayerService.pause(this.playerId);\n this.isVideoPlaying = false;\n }\n }\n\n /**\n * user isProjectAdmin and project.isModerated and !stack.isApproved\n */\n approveStack(stack: Stack) {\n //console.log(`set stack.isApproved`, stack);\n this.store.dispatch(\n stackActions.setApproved({ projectId: stack.projectId, stackId: stack.stackId, isApproved: true })\n );\n }\n\n expandDraftDrawer(showCreateForm = false) {\n this.topDrawerExpand$.next({ i: ++this._incExpandEvent, showCreateForm });\n }\n closeDraftDrawer() {\n this.topDrawerClose$.next(++this._incCloseEvent);\n }\n\n /**\n * Event: StatckPopoverActions.addToStack emitted when that is selected,\n * open tab fab\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n openTabFab(event) {\n if (this.tabFab) {\n this.tabFab.activated = true;\n this.isFabOpen = true;\n }\n }\n closeTabFab() {\n this.tabFab?.close();\n this.isFabOpen = false;\n // this.store.dispatch(stackActions.resetAddToStackPlaylist()); // this should be in the drawer?\n }\n\n /**\n * FAB Click appears to come just before the element changes its value\n * fab is open if it is not currently activated\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n fabClick(event) {\n this.isFabOpen = !this.tabFab.activated; // !this.isFabOpen;\n // console.log(`fabClick`, { isFabOpen: this.isFabOpen, activated: this.tabFab.activated });\n if (!this.isFabOpen) {\n this.store.dispatch(stackActions.resetAddToStackPlaylist());\n // this.closeDraftDrawer();// already happens when playlist resets\n } // else don't open until you get the action click\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n addClipToStack(event) {\n this.stack$.pipe(take(1)).subscribe((stack) => {\n if (stack && Array.isArray(stack.playlist) && stack.playlist.length > this.currentPlaylistIndex) {\n // this.isFabOpen = false;\n // expandDraftDrawer();// already happens when playlist exists\n const clip = stack.playlist[this.currentPlaylistIndex];\n // console.log(`addClipToStack`, { currentPlaylistIndex: this.currentPlaylistIndex, clip, stack, event });\n this.store.dispatch(stackActions.addToStackDrawer({ playlist: [clip] }));\n } else {\n !environment.production &&\n console.log(`No Playlist.`, { stack, currentPlaylistIndex: this.currentPlaylistIndex });\n }\n });\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n addAllClipsToStack(event) {\n this.stack$.pipe(take(1)).subscribe((stack) => {\n if (stack && Array.isArray(stack.playlist) && stack.playlist.length > 0) {\n // this.isFabOpen = false;\n // this.expandDraftDrawer();// already happens when playlist exists\n\n // MVP-1342 add title and description if create new (Restack)\n this.store.dispatch(\n stackActions.addToStackDrawer({\n playlist: stack.playlist,\n isCreateNew: false,\n projectId: stack.projectId,\n title: stack.title,\n description: stack.description,\n poster: stack.poster,\n })\n );\n // console.log(`addAllClipsToStack`, { stack, event });\n } else {\n !environment.production && console.log(`No Playlist.`, stack);\n }\n });\n }\n\n /**\n * Close FAB when drawer closes\n */\n draftDrawerExpanded(event) {\n if (!event) {\n // closed, close fab?\n this.closeTabFab();\n }\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n draftDrawerSelected(event) {\n // console.log(`Player draft selected`, event);\n this.closeTabFab();\n }\n draftDrawerNewItem(event: Partial<Stack> = {}) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { projectId, stackId, title } = event;\n // console.log(`Player draft new item`);\n this.closeTabFab();\n this.router.navigate(['/stack/edit', projectId, stackId]);\n }\n\n /**\n * Stack Playlist HLS Upgrades MVP-983\n * @todo remove eventually\n */\n sendStackForHLSTranscode(): void {\n this.stack$.pipe(take(1)).subscribe(async (stack) => {\n try {\n await this.videoService.sendStackForHLSTranscode(stack);\n // this.toaster.present(`Submitted for Transcoding...`);\n } catch (error) {\n console.warn(`[StackPopover] confirmTranscode caught:`, error);\n this.toaster.present(this.translate.instant('ERRORS.STACK_OPTIMIZE'));\n }\n });\n }\n\n /**\n *\n * Stack Playlist HLS Upgrades MVP-983\n */\n async confirmTranscode() {\n const alert = await this.alertCtrl.create({\n header: this.translate.instant('STACK.CONFIRM_OPTIMIZE'),\n subHeader: this.isAllClipsHls\n ? this.translate.instant('STACK.SUBMIT_CONFIRM')\n : this.translate.instant('STACK.SUBMIT_CONFIRM_CLIPS'),\n message: this.translate.instant('STACK.SUBMIT_MESSAGE'),\n buttons: [\n {\n text: this.translate.instant('COMMON.CANCEL'),\n role: 'cancel',\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n handler: (_) => {\n console.log('Confirm Canceled...');\n },\n },\n {\n text: this.translate.instant('COMMON.TRANSCODE'),\n cssClass: 'ion-color-secondary',\n handler: () => {\n this.sendStackForHLSTranscode();\n this.toaster.present(this.translate.instant('STACK.TRANSCODE_SUBMITTED'));\n },\n },\n ],\n });\n return await alert.present();\n }\n}\n"],"x_google_ignoreList":[]}