{"version":3,"file":"8701.e10431d395badfbc.js","mappings":"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","names":["CaptureClipButtonComponent","_CaptureClipButtonComponent","startUpload","val","this","clickButton","constructor","userService","clipsService","toaster","translate","sentryService","isShowing","uploadSuccess","EventEmitter","uploadError","userId$","uploadBtn","nativeElement","click","error","console","warn","present","instant","onUploadDone","res","captureMessage","Error","filesFailed","filesUploaded","length","num","interval","pipe","take","subscribe","emit","message","onFileUploadFinished","userId","createClipFromFilestack","projectId","onFileUploadFailed","log","captureError","i0","i1","i2","i3","i4","i5","selectors","viewQuery","rf","ctx","ElementRef","$event","_r1","IonButton","ClipUploadDirective","IonIcon","AsyncPipe","TranslatePipe","_r2","ctx_r2","projectChanged","CaptureClipModalComponent_ng_container_9_ng_container_1_Template","CaptureClipModalComponent_ng_container_9_app_form_select_myprojects_8_Template","modal_r4","dismiss","onFileUploadDone","isCaptureEnabled","showProjectSelect","selectedProjectId$","isLoading","tmp_18_0","_r5","_c2","_c3","CaptureClipModalComponent","_CaptureClipModalComponent","_selectedProjectId$","asObservable","alertCtrl","projectService","environService","configService","showBetaInvite","BehaviorSubject","onDestroy$","Subject","ngOnInit","userHasUploadAccess$","takeUntil","isAllowed","isCaptureAllowed$","map","projects","find","p","id","ngOnDestroy","next","complete","project","showProjectAlert","_this","_asyncToGenerator","create","header","subHeader","buttons","modal","role","data","selectedProjectId","info","i6","i7","i8","i9","BaseModalComponent","CaptureClipModalComponent_div_6_Template","CaptureClipModalComponent_ng_template_7_Template","CaptureClipModalComponent_ng_container_9_Template","CaptureClipModalComponent_div_11_Template","joinACrew_r6","NgIf","RouterLink","FormSelectMyProjects","TermsPolicyModalsComponent","IonSpinner","styles","TabFabContainerComponent","_TabFabContainerComponent","_viewContainerRef","router","initialUrl","url","subscriptions","Subscription","ngAfterViewInit","attachPortal","subscription","events","filter","e","NavigationEnd","distinctUntilChanged","route","setTimeout","outlet","hasAttached","detach","add","unsubscribe","DomPortalOutlet","document","querySelector","portal","TemplatePortal","portalContent","attachTemplatePortal","TabFabContainerComponent_ng_template_0_Template","PortalModule","encapsulation"],"ignoreList":[],"sourceRoot":"webpack:///","sources":["./src/app/clips/shared/components/capture-clip-button/capture-clip-button.component.ts","./src/app/clips/shared/components/capture-clip-button/capture-clip-button.component.html","./src/app/clips/shared/components/capture-clip-modal/capture-clip-modal.component.html","./src/app/clips/shared/components/capture-clip-modal/capture-clip-modal.component.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"],"sourcesContent":["/** @format */\n\nimport { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';\nimport { AsyncPipe } from '@angular/common';\nimport { interval } from 'rxjs';\nimport { take } from 'rxjs/operators';\nimport { TranslateService, TranslatePipe } from '@ngx-translate/core';\nimport { IonButton, IonIcon } from '@ionic/angular/standalone';\nimport { SentryService } from '@app/core/services/sentry.service';\nimport { ToasterService } from '@app/core/services/toaster.service';\nimport { UserService } from '@app/core/services/user.service';\nimport { PickerFileError, PickerFileMetadata, PickerUploadDone } from '@app/core/filestack/filestack.service';\nimport { ClipUploadDirective } from '@app/core/filestack/directives/clip-upload.directive';\nimport { ClipsService } from '@app/clips/shared/services/clips.service';\n\n@Component({\n  selector: 'app-capture-clip-button',\n  templateUrl: './capture-clip-button.component.html',\n  styleUrls: ['./capture-clip-button.component.scss'],\n  standalone: true,\n  imports: [IonButton, ClipUploadDirective, IonIcon, AsyncPipe, TranslatePipe],\n})\nexport class CaptureClipButtonComponent {\n  @Input() projectId: string;\n  @Input() isShowing = false;\n  @Input()\n  set startUpload(val) {\n    if (val) {\n      this.clickButton();\n    }\n  }\n  @Output() uploadSuccess = new EventEmitter<PickerFileMetadata[]>();\n  @Output() uploadError = new EventEmitter<Error>();\n\n  @ViewChild('uploadBtn', { read: ElementRef }) uploadBtn: ElementRef;\n\n  userId$ = this.userService.userId$;\n\n  constructor(\n    private userService: UserService,\n    private clipsService: ClipsService,\n    private toaster: ToasterService,\n    private translate: TranslateService,\n    private sentryService: SentryService\n  ) {}\n\n  clickButton() {\n    // console.log(`Capturing to project: ${this.projectId}`)\n    try {\n      this.uploadBtn.nativeElement.click();\n    } catch (error) {\n      console.warn(error);\n      this.toaster.present(this.translate.instant('ERRORS.GENERIC_OOPS'));\n    }\n  }\n\n  /**\n   * Filestack is done with all\n   * {\n   *    filesFailed: PickerFileMetadata[],\n   *    filesUploaded: PickerFileMetadata[]}\n   * }\n   */\n  onUploadDone(res: PickerUploadDone) {\n    try {\n      if (!res) {\n        console.error(`onUploadDone no filestackResult?!?`);\n        this.sentryService.captureMessage(`onUploadDone no filestackResult?`);\n        throw new Error(this.translate.instant('ERRORS.CLIP_CREATE'));\n      }\n      const { filesFailed = [], filesUploaded = [] } = res;\n      if (filesFailed.length > 0) {\n        this.toaster.present(this.translate.instant('CLIP.CAPTURE.ERROR_UPLOADING_CLIPS', { num: filesFailed.length }));\n      }\n      // this.success.emit(filesUploaded);\n      // // do we need a delay here to await the actions being done?\n      interval(300)\n        .pipe(take(1))\n        .subscribe(() => {\n          this.uploadSuccess.emit(filesUploaded);\n        });\n    } catch (error) {\n      if (error && error.message) {\n        this.toaster.present(error.message);\n      }\n      this.uploadError.emit(error);\n    }\n  }\n\n  /**\n   * Filestack is done with one or more\n   * @see capture.page original implementation\n   */\n  onFileUploadFinished(res: PickerFileMetadata) {\n    try {\n      if (!res) {\n        console.error(`onFileUploadFinished no filestackResult?!?`);\n        this.sentryService.captureMessage(`onFileUploadFinished no filestackResult?`);\n        throw new Error(this.translate.instant('ERRORS.CLIP_CREATE'));\n      }\n\n      this.userId$.pipe(take(1)).subscribe((userId) => {\n        this.clipsService.createClipFromFilestack(res, this.projectId, userId);\n      });\n    } catch (error) {\n      if (error && error.message) {\n        this.toaster.present(error.message);\n      } else {\n        this.toaster.present(this.translate.instant('ERRORS.CLIP_CREATE'));\n        // this.toaster.present(this.translate.instant('ERRORS.GENERIC_OOPS'));\n      }\n      this.uploadError.emit(error);\n    }\n  }\n\n  onFileUploadFailed(res: PickerFileError) {\n    console.log('### fileUploadFailed', res);\n    this.sentryService.captureError(`Filestack onFileUploadFailed`);\n    if (res && res.error.message) {\n      this.toaster.present(res.error.message);\n    } else {\n      this.toaster.present(this.translate.instant('ERRORS.CLIP_CREATE'));\n    }\n    this.uploadError.emit(res.error);\n  }\n}\n","<ion-button #uploadBtn clipUpload \n  class=\"upload-btn\" \n  [class.hidden]=\"!isShowing\"\n  [title]=\"'FILE_UPLOAD.UPLOAD_CLIPS' | translate\"\n  [projectId]=\"projectId\"\n  [userId]=\"userId$ | async\"\n  (uploadDone)=\"onUploadDone($event)\"\n  (fileUploadFinished)=\"onFileUploadFinished($event)\"\n  (fileUploadFailed)=\"onFileUploadFailed($event)\"\n  [disabled]=\"true\"\n>\n  {{ 'FILE_UPLOAD.UPLOAD_CLIPS' | translate }}\n  <ion-icon slot=\"end\" name=\"cloud-upload-outline\"></ion-icon>\n</ion-button>\n","<fs-base-modal title=\"\" mode=\"dark\" #modal>\n\n  <div class=\"ion-text-center skinny-limit-width capture-clip-modal\">\n    <h1>{{ 'CLIP.CAPTURE.TITLE' | translate }}</h1>\n    \n    <div *ngIf=\"isLoading\" class=\"ion-padding ion-text-center\">\n      <ion-spinner name=\"crescent\"></ion-spinner>\n    </div>\n\n    <ng-template #joinACrew>\n      <div class=\"ion-padding ion-text-center skinny-limit-width\">\n        <h1 class=\"ion-padding-top ion-text-center\">{{ 'CLIP.CAPTURE.JOIN_A_CREW' | translate }}</h1>\n  \n        <p class=\"ion-text-center\">\n          {{ 'CLIP.CAPTURE.JOIN_A_CREW_BODY_1' | translate }}\n          <!-- {{ 'CLIP.CAPTURE.JOIN_A_CREW_BODY' | translate:{ onlineTypes: onlineTypesAsText } }} -->\n          <!-- Once you're on a Project Crew or have your own Project, you can upload videos or capture from \n          {{ onlineTypesAsText }}. -->\n        </p>\n  \n        <!-- <div class=\"ion-padding ion-text-center action-buttons\">\n          <ion-button size=\"large\" fill=\"outline\" shape=\"round\" color=\"primary\" (click)=\"openProjectsPage()\">\n            {{ 'COMMON.DISCOVER' | translate }}&nbsp;{{ 'COMMON.PROJECTS' | translate }}\n          </ion-button>\n        </div> -->\n      </div>\n    </ng-template>\n\n    <ng-container *ngIf=\"(isCaptureAllowed$ | async) === true || isLoading; else joinACrew\">\n      <ng-container *ngIf=\"!isCaptureEnabled\">\n        <p class=\"capture-message\">\n          {{ 'CLIP.CAPTURE.DISABLED_MESSAGE' | translate }}\n        </p>\n      </ng-container>\n      <p>\n        {{ 'CLIP.CAPTURE.SUBTITLE' | translate }}\n        <br />\n        {{ 'CLIP.CAPTURE.LIMITS' | translate }}\n      </p>\n\n      <app-form-select-myprojects\n        *ngIf=\"showProjectSelect\"\n        [isCapture]=\"true\"\n        [defaultProjectId]=\"projectId\"\n        (selected)=\"projectChanged($event)\"\n      >\n      </app-form-select-myprojects>\n  \n      <div class=\"capture-helpful-tips ion-padding-vertical ion-margin-top\">\n        <h2>{{ 'CLIP.CAPTURE.TIPS.HEADING' | translate }}</h2>\n        <ul>\n          <li>\n            {{ 'CLIP.CAPTURE.TIPS.TIP_1' | translate }}\n          </li>\n          <li>\n            {{ 'CLIP.CAPTURE.TIPS.TIP_2' | translate }}\n          </li>\n          <li>\n            {{ 'CLIP.CAPTURE.TIPS.TIP_3' | translate }}\n          </li>\n          <li>\n            {{ 'CLIP.CAPTURE.TIPS.TIP_4' | translate }}\n          </li>\n        </ul>\n      </div>\n  \n      <div class=\"ion-text-center ion-padding\">\n        <app-terms-policy-modals\n          [agreeTo] = \"'POLICIES.AGREE_TO_TERMS_PREFIX' | translate\"\n        ></app-terms-policy-modals>\n      </div>\n      <div class=\"btn-wrapper ion-padding-top\">\n        <ion-button fill=\"clear\" color=\"light\" (click)=\"modal.dismiss()\">\n          {{ 'COMMON.CANCEL' | translate }}\n        </ion-button>\n        \n        <ion-button #uploadBtn clipUpload size=\"large\" color=\"primary\" \n          [title]=\"'FILE_UPLOAD.UPLOAD_CLIPS' | translate\"\n          [projectId]=\"selectedProjectId$ | async\"\n          [userId]=\"userId$ | async\"\n          (uploadDone)=\"onFileUploadDone($event)\"\n          (fileUploadFinished)=\"onFileUploadFinished($event)\"\n          (fileUploadFailed)=\"onFileUploadFailed($event)\"\n          [disabled]=\"isLoading || (selectedProjectId$ | async)?.length < 1 || !isCaptureEnabled\"\n        >\n          {{ 'FILE_UPLOAD.UPLOAD_CLIPS' | translate }}\n          <ion-icon slot=\"end\" name=\"cloud-upload-outline\"></ion-icon>\n        </ion-button>\n      </div>\n    </ng-container>\n\n    <div *ngIf=\"showBetaInvite\" class=\"ion-padding ion-text-center\">\n      <div class=\"announcement ion-padding\">\n        <h1>\n          {{ 'CLIP.CAPTURE.BETA_HEADING' | translate }}\n          <!-- We're actively developing new features for Capture! -->\n          <!-- Be part of our community -->\n        </h1>\n        <p class=\"ion-text-center\">\n          {{ 'CLIP.CAPTURE.BETA_SUBHEAD' | translate }}\n          <!-- Join us as we build a collaborative storytelling vision. -->\n          <!-- Interested in helping us test new features? -->\n        </p>\n        <p class=\"ion-text-center\">\n          <ion-button\n            size=\"small\"\n            class=\"ion-text-uppercase btn-link-inline\"\n            fill=\"clear\"\n            color=\"primary\"\n            [routerLink]=\"['/contact']\"\n            [queryParams]=\"{ topic: 'CLIP.CAPTURE.BETA_CONTACT_TOPIC' | translate }\"\n            routerDirection=\"forward\"\n            (click)=\"modal.dismiss()\"\n            >{{ 'CLIP.CAPTURE.BETA_CONTACT_US_BUTTON' | translate }}</ion-button\n          >\n          {{ 'CLIP.CAPTURE.BETA_CONTACT_US_TEXT' | translate }}\n        </p>\n      </div>\n    </div>\n  </div>\n\n</fs-base-modal>\n","/** @format */\n\nimport { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';\nimport { NgIf, AsyncPipe } from '@angular/common';\nimport { RouterLink } from '@angular/router';\nimport { BehaviorSubject, interval, Observable, Subject } from 'rxjs';\nimport { map, take, takeUntil } from 'rxjs/operators';\nimport { TranslateService, TranslatePipe } from '@ngx-translate/core';\nimport { AlertController, IonSpinner, IonButton, IonIcon } from '@ionic/angular/standalone';\nimport { ConfigService } from '@app/core/config/config.service';\nimport { EnvironService } from '@app/core/services/environ.service';\nimport { SentryService } from '@app/core/services/sentry.service';\nimport { ToasterService } from '@app/core/services/toaster.service';\nimport { UserService } from '@app/core/services/user.service';\nimport { PickerFileError, PickerFileMetadata, PickerUploadDone } from '@app/core/filestack/filestack.service';\nimport { ClipUploadDirective } from '@app/core/filestack/directives/clip-upload.directive';\nimport { ClipsService } from '@app/clips/shared/services/clips.service';\nimport { ProjectService } from '@app/projects/shared/services/project.service';\nimport { BaseModalComponent } from '@app/shared/components/ui/modal/base-modal.component';\nimport { FormSelectMyProjects } from '@app/shared/components/form-select-myprojects/form-select-myprojects.component';\nimport { TermsPolicyModalsComponent } from '@app/shared/components/terms-policy-modals/terms-policy-modals.component';\n\nconst DEBUG_LOGS = false;\n\n@Component({\n  selector: 'app-capture-clip-modal',\n  templateUrl: './capture-clip-modal.component.html',\n  styleUrls: ['./capture-clip-modal.component.scss'],\n  standalone: true,\n  imports: [\n    NgIf,\n    RouterLink,\n    AsyncPipe,\n    TranslatePipe,\n    ClipUploadDirective,\n    BaseModalComponent,\n    FormSelectMyProjects,\n    TermsPolicyModalsComponent,\n    IonSpinner,\n    IonButton,\n    IonIcon,\n  ],\n})\nexport class CaptureClipModalComponent implements OnInit, OnDestroy {\n  @Input() projectId: string = '';\n  @Input() showProjectSelect = true;\n  @Output() uploadSuccess = new EventEmitter<PickerFileMetadata[]>();\n\n  @ViewChild('modal', { static: false, read: BaseModalComponent })\n  modal: BaseModalComponent;\n  // @ViewChild('uploadBtn', { static: false, read: IonButton }) uploadBtn: IonButton;\n  @ViewChild('uploadBtn', { read: ElementRef }) uploadBtn: ElementRef;\n\n  userId$ = this.userService.userId$;\n\n  isCaptureEnabled = false;\n  isCaptureAllowed$: Observable<boolean>;\n  isLoading = true;\n  showBetaInvite = false; // toggle the beta tester invitation panel\n  // selectedProjectId: string = '';\n  private _selectedProjectId$: BehaviorSubject<string> = new BehaviorSubject('');\n  get selectedProjectId$(): Observable<string> {\n    return this._selectedProjectId$.asObservable();\n  }\n\n  // private get captureToProjectId (): string {\n  //   return this.projectSelected && this.projectSelected.id ? this.projectSelected.id : '';\n  // }\n  private onDestroy$ = new Subject<void>();\n\n  constructor(\n    private toaster: ToasterService,\n    private alertCtrl: AlertController,\n    private clipsService: ClipsService,\n    private projectService: ProjectService,\n    private userService: UserService,\n    private environService: EnvironService,\n    private configService: ConfigService,\n    private sentryService: SentryService,\n    // private cdref: ChangeDetectorRef,\n    private translate: TranslateService\n  ) {}\n\n  ngOnInit(): void {\n    // take myProjects and the projectId passed as input\n    // choose the projectId to select if projectId input || active || most recent\n    // if no projectId, we need to show the project selector\n\n    /**\n     * @todo refactor this to billing status\n     */\n    this.userService.userHasUploadAccess$.pipe(takeUntil(this.onDestroy$)).subscribe((isAllowed) => {\n      this.isCaptureEnabled = isAllowed; // !!isAdmin || !!isDeveloper || !!isKickstarter || !!isWeddingPilot || !!isBeta;\n      if (!this.isCaptureEnabled) {\n        this.showBetaInvite = true;\n      }\n    });\n\n    /**\n     *\n     * isCaptureAllowed: appConfig.allowCapture || hasProjects\n     * if isLoading then disable capture buttons\n     * if !isCaptureAllowed then show tpl joinACrew\n     */\n    this.isCaptureAllowed$ = this.userService.isCaptureAllowed$.pipe(\n      takeUntil(this.onDestroy$),\n      map(({ isAllowed, projects }) => {\n        // console.log(`isCaptureAllowed?`, { projectId: this.projectId, projects, appConfig, userId, activeProjectId })\n        // note: this gets called ~3x times due to getMyProjects returning multiple times as it gets all your projects & memberProjects\n        this.isLoading = false;\n        if (!isAllowed) {\n          this.showBetaInvite = true;\n        } else if (this.projectId) {\n          if (!this.showProjectSelect) {\n            // console.log(`!showProjectSelect do we care?`);\n            // if !showProjectSelect then the selector never loads therefore does not trigger change\n          }\n          // since hasProjects we could assume that's the selectedOne since the parent manages display\n          const exists = projects.find((p) => p && p.id === this.projectId);\n          if (exists) {\n            try {\n              //click the button here?\n              // this.uploadBtn.nativeElement.click();\n\n              // causing ExpressionChangedAfterItHasBeenCheckedError\n              this.projectChanged({ id: this.projectId });\n            } catch (error) {\n              console.warn(`Caught Error:`, error);\n            }\n          }\n        }\n        return isAllowed;\n      })\n    );\n  }\n\n  ngOnDestroy() {\n    this.onDestroy$.next();\n    this.onDestroy$.complete();\n  }\n\n  /**\n   * Project was selected, update with this value\n   */\n  projectChanged(project) {\n    if (project && project.id) {\n      // && !this.isLoading\n      this._selectedProjectId$.next(project.id);\n      DEBUG_LOGS && console.log(`selectedProjectId:`, project.id);\n\n      // set the activeProject in EnvironStore to save it for next Capture\n      // this.environService.setActiveProjectId(event.target.value.id);\n    }\n  }\n\n  async showProjectAlert() {\n    const alert = await this.alertCtrl.create({\n      header: 'Filmstacker',\n      subHeader: 'Please select a Project',\n      message: `Clips must be uploaded to a Project, please select one and try again.`,\n      buttons: ['Ok'],\n    });\n    return await alert.present();\n  }\n\n  /**\n   * Filestack is done with all\n   * {\n   *    filesFailed: PickerFileMetadata[],\n   *    filesUploaded: PickerFileMetadata[]}\n   * }\n   */\n  onFileUploadDone(res: PickerUploadDone) {\n    try {\n      if (!res) {\n        console.error(`onFileUploadDone no filestackResult?!?`);\n        this.sentryService.captureMessage(`onFileUploadDone no filestackResult?`);\n        throw new Error(this.translate.instant('ERRORS.CLIP_CREATE'));\n      }\n\n      const { filesFailed = [], filesUploaded = [] } = res;\n      if (filesFailed.length > 0) {\n        this.toaster.present(`There might have been an issue uploading ${filesFailed.length} of the clips...`);\n      }\n\n      // do we need a delay here to await the actions being done?\n      interval(300)\n        .pipe(take(1))\n        .subscribe(() => {\n          this.uploadSuccess.emit(filesUploaded);\n          this.modal.dismiss({ role: 'success', data: filesUploaded });\n        });\n    } catch (error) {\n      if (error && error.message) {\n        this.toaster.present(error.message);\n      }\n    }\n  }\n\n  /**\n   * Filestack is done with one or more\n   * @see capture.page original implementation\n   */\n  onFileUploadFinished(res: PickerFileMetadata) {\n    try {\n      if (!res) {\n        console.error(`onFileUploadFinished no filestackResult?!?`);\n        this.sentryService.captureMessage(`onFileUploadFinished no filestackResult?`);\n        throw new Error(this.translate.instant('ERRORS.CLIP_CREATE'));\n      }\n\n      this.selectedProjectId$.pipe(take(1)).subscribe((selectedProjectId) => {\n        if (!selectedProjectId) {\n          console.info(`[CaptureClip] NO captureToProject ('${selectedProjectId}'), use personal studio?`);\n          this.showProjectAlert();\n          throw new Error(''); // don't show toaster here, alert instead\n        }\n        this.userId$.pipe(take(1)).subscribe((userId) => {\n          this.clipsService.createClipFromFilestack(res, selectedProjectId, userId);\n        });\n      });\n    } catch (error) {\n      if (error && error.message) {\n        this.toaster.present(error.message);\n      } else {\n        this.toaster.present(this.translate.instant('ERRORS.GENERIC_OOPS'));\n      }\n    }\n  }\n\n  onFileUploadFailed(res: PickerFileError) {\n    console.log('### fileUploadFailed', res);\n    this.sentryService.captureError(`Filestack onFileUploadFailed`);\n    if (res && res.error.message) {\n      this.toaster.present(res.error.message);\n    } else {\n      this.toaster.present(this.translate.instant('ERRORS.GENERIC_OOPS'));\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"],"x_google_ignoreList":[]}