From 68118519439ab0340a36f3bbcd57bbc348333fa6 Mon Sep 17 00:00:00 2001 From: aasandei-vsp Date: Mon, 11 May 2026 17:54:00 +0300 Subject: [PATCH] Fix unlisted-share preview flicker Resolve isUnlistedShare and ephemeralFolder before SharePreviewComponent renders so the first paint matches the share's actual type, instead of defaulting to the restricted-share UI and swapping after an async API call. - Add primeForToken / isUnlistedShareSync to ShareLinksService and invalidate the cache on token change and on navigation off /share/ - Have ShareUrlResolveService prime the share-links cache in parallel with checkShareLink via Promise.all - Add ShareUrlEphemeralFolderResolveService so ephemeralFolder is on route data before the component constructs - Read isUnlistedShare synchronously in SharePreviewComponent and FileListItemComponent so blurred / real thumbnails are correct on first paint Issue: PER-10352 --- .../file-list-item.component.spec.ts | 24 +++- .../file-list-item.component.ts | 16 +-- .../services/share-links.service.spec.ts | 111 ++++++++++++++++++ .../services/share-links.service.ts | 41 ++++++- .../share-preview.component.spec.ts | 17 +-- .../share-preview/share-preview.component.ts | 18 +-- ...re-url-ephemeral-folder-resolve.service.ts | 51 ++++++++ .../share-url-resolve.service.spec.ts | 106 +++++++++++++++++ .../resolves/share-url-resolve.service.ts | 49 ++++---- src/app/share-preview/share-preview.routes.ts | 3 + 10 files changed, 375 insertions(+), 61 deletions(-) create mode 100644 src/app/share-preview/resolves/share-url-ephemeral-folder-resolve.service.ts create mode 100644 src/app/share-preview/resolves/share-url-resolve.service.spec.ts diff --git a/src/app/file-browser/components/file-list-item/file-list-item.component.spec.ts b/src/app/file-browser/components/file-list-item/file-list-item.component.spec.ts index 1e78be409..8e41a18db 100644 --- a/src/app/file-browser/components/file-list-item/file-list-item.component.spec.ts +++ b/src/app/file-browser/components/file-list-item/file-list-item.component.spec.ts @@ -127,6 +127,7 @@ describe('FileListItemComponent', () => { provide: ShareLinksService, useValue: { isUnlistedShare: async () => await Promise.resolve(false), + isUnlistedShareSync: () => false, }, }, { provide: EditService, useValue: mockEditService }, @@ -317,9 +318,7 @@ describe('FileListItemComponent', () => { (router.routerState.snapshot as any).url = '/share/test'; const shareLinksService = TestBed.inject(ShareLinksService); - spyOn(shareLinksService, 'isUnlistedShare').and.returnValue( - Promise.resolve(false), - ); + spyOn(shareLinksService, 'isUnlistedShareSync').and.returnValue(false); component.item.isRecord = true; component.item.type = 'type.record.image'; @@ -333,7 +332,22 @@ describe('FileListItemComponent', () => { (router.routerState.snapshot as any).url = '/'; }); - it('should always set real thumbnail URL on init', async () => { + it('should set real thumbnail URL on init outside share preview', async () => { + component.item.isRecord = true; + component.item.type = 'type.record.image'; + component.item.thumbURL200 = 'https://example.com/thumb.jpg'; + + await component.ngOnInit(); + + expect(component.recordThumbnailUrl).toBe('https://example.com/thumb.jpg'); + }); + + it('should set real thumbnail URL on init for unlisted share records', async () => { + const router = TestBed.inject(Router); + (router.routerState.snapshot as any).url = '/share/test'; + + const shareLinksService = TestBed.inject(ShareLinksService); + spyOn(shareLinksService, 'isUnlistedShareSync').and.returnValue(true); component.item.isRecord = true; component.item.type = 'type.record.image'; component.item.thumbURL200 = 'https://example.com/thumb.jpg'; @@ -341,5 +355,7 @@ describe('FileListItemComponent', () => { await component.ngOnInit(); expect(component.recordThumbnailUrl).toBe('https://example.com/thumb.jpg'); + + (router.routerState.snapshot as any).url = '/'; }); }); diff --git a/src/app/file-browser/components/file-list-item/file-list-item.component.ts b/src/app/file-browser/components/file-list-item/file-list-item.component.ts index 21312a7d5..30194a251 100644 --- a/src/app/file-browser/components/file-list-item/file-list-item.component.ts +++ b/src/app/file-browser/components/file-list-item/file-list-item.component.ts @@ -250,12 +250,17 @@ export class FileListItemComponent ) {} async ngOnInit() { - this.recordThumbnailUrl = GetThumbnail(this.item); + this.isUnlistedShare = this.shareLinksService.isUnlistedShareSync(); + const isInSharePreview = + this.router.routerState.snapshot.url.includes('/share/'); + if (isInSharePreview && !this.isUnlistedShare) { + this.recordThumbnailUrl = this.getRandomPreviewImage(); + } else { + this.recordThumbnailUrl = GetThumbnail(this.item); + } const date = new Date(this.item.displayDT); this.date = getFormattedDate(date); - this.isUnlistedShare = await this.shareLinksService.isUnlistedShare(); - this.dataService.registerItem(this.item); if (this.item.type.includes('app')) { this.allowActions = false; @@ -266,10 +271,7 @@ export class FileListItemComponent this.isPublicArchive = true; } - if (this.router.routerState.snapshot.url.includes('/share/')) { - if (!this.isUnlistedShare) { - this.recordThumbnailUrl = this.getRandomPreviewImage(); - } + if (isInSharePreview) { this.allowActions = false; this.isInSharePreview = true; } diff --git a/src/app/share-links/services/share-links.service.spec.ts b/src/app/share-links/services/share-links.service.spec.ts index deaaffe73..fbb57cd43 100644 --- a/src/app/share-links/services/share-links.service.spec.ts +++ b/src/app/share-links/services/share-links.service.spec.ts @@ -1,4 +1,6 @@ import { TestBed } from '@angular/core/testing'; +import { NavigationEnd, Router } from '@angular/router'; +import { Subject } from 'rxjs'; import { ShareLink } from '../models/share-link'; import { ShareLinksService } from './share-links.service'; import { ShareLinksApiService } from './share-links-api.service'; @@ -6,16 +8,19 @@ import { ShareLinksApiService } from './share-links-api.service'; describe('ShareLinksService', () => { let service: ShareLinksService; let apiSpy: jasmine.SpyObj; + let routerEvents: Subject; beforeEach(() => { apiSpy = jasmine.createSpyObj('ShareLinksApiService', [ 'getShareLinksByToken', ]); + routerEvents = new Subject(); TestBed.configureTestingModule({ providers: [ ShareLinksService, { provide: ShareLinksApiService, useValue: apiSpy }, + { provide: Router, useValue: { events: routerEvents.asObservable() } }, ], }); @@ -84,4 +89,110 @@ describe('ShareLinksService', () => { expect(secondCall).toBeTrue(); expect(apiSpy.getShareLinksByToken).toHaveBeenCalledTimes(1); // no second fetch }); + + describe('primeForToken', () => { + it('should set the current token and populate shareLinks cache', async () => { + apiSpy.getShareLinksByToken.and.resolveTo([ + { accessRestrictions: 'none' } as ShareLink, + ]); + + await service.primeForToken('abc123'); + + expect(service.currentShareToken).toBe('abc123'); + expect(apiSpy.getShareLinksByToken).toHaveBeenCalledWith(['abc123']); + }); + + it('should swallow API errors and leave the cache empty', async () => { + apiSpy.getShareLinksByToken.and.rejectWith(new Error('boom')); + + await service.primeForToken('abc123'); + + expect(service.isUnlistedShareSync()).toBeFalse(); + }); + + it('should skip the API call when the token is empty', async () => { + await service.primeForToken(''); + + expect(apiSpy.getShareLinksByToken).not.toHaveBeenCalled(); + expect(service.isUnlistedShareSync()).toBeFalse(); + }); + }); + + describe('isUnlistedShareSync', () => { + it('should return false before priming', () => { + expect(service.isUnlistedShareSync()).toBeFalse(); + }); + + it('should return true after priming an unlisted share', async () => { + apiSpy.getShareLinksByToken.and.resolveTo([ + { accessRestrictions: 'none' } as ShareLink, + ]); + await service.primeForToken('abc123'); + + expect(service.isUnlistedShareSync()).toBeTrue(); + }); + + it('should return false after priming a restricted share', async () => { + apiSpy.getShareLinksByToken.and.resolveTo([ + { accessRestrictions: 'approval' } as ShareLink, + ]); + await service.primeForToken('abc123'); + + expect(service.isUnlistedShareSync()).toBeFalse(); + }); + }); + + describe('currentShareToken setter', () => { + it('should clear the shareLinks cache when the token changes', async () => { + apiSpy.getShareLinksByToken.and.resolveTo([ + { accessRestrictions: 'none' } as ShareLink, + ]); + await service.primeForToken('abc123'); + + expect(service.isUnlistedShareSync()).toBeTrue(); + + service.currentShareToken = 'different'; + + expect(service.isUnlistedShareSync()).toBeFalse(); + }); + + it('should preserve the shareLinks cache when the token does not change', async () => { + apiSpy.getShareLinksByToken.and.resolveTo([ + { accessRestrictions: 'none' } as ShareLink, + ]); + await service.primeForToken('abc123'); + + service.currentShareToken = 'abc123'; + + expect(service.isUnlistedShareSync()).toBeTrue(); + }); + }); + + describe('router navigation cleanup', () => { + it('should clear cache when navigating off a share route', async () => { + apiSpy.getShareLinksByToken.and.resolveTo([ + { accessRestrictions: 'none' } as ShareLink, + ]); + await service.primeForToken('abc123'); + + expect(service.isUnlistedShareSync()).toBeTrue(); + + routerEvents.next(new NavigationEnd(1, '/app/private', '/app/private')); + + expect(service.currentShareToken).toBe(''); + expect(service.isUnlistedShareSync()).toBeFalse(); + }); + + it('should preserve cache when navigating within share routes', async () => { + apiSpy.getShareLinksByToken.and.resolveTo([ + { accessRestrictions: 'none' } as ShareLink, + ]); + await service.primeForToken('abc123'); + + routerEvents.next(new NavigationEnd(1, '/share/abc123', '/share/abc123')); + + expect(service.currentShareToken).toBe('abc123'); + expect(service.isUnlistedShareSync()).toBeTrue(); + }); + }); }); diff --git a/src/app/share-links/services/share-links.service.ts b/src/app/share-links/services/share-links.service.ts index db29a0a71..77dc3ff79 100644 --- a/src/app/share-links/services/share-links.service.ts +++ b/src/app/share-links/services/share-links.service.ts @@ -1,4 +1,6 @@ import { Injectable } from '@angular/core'; +import { NavigationEnd, Router } from '@angular/router'; +import { filter } from 'rxjs/operators'; import { ShareLink } from '../models/share-link'; import { ShareLinksApiService } from './share-links-api.service'; @@ -9,16 +11,53 @@ export class ShareLinksService { private _currentShareToken = ''; private _shareLinks: ShareLink[] = undefined; - constructor(private shareLinksApiService: ShareLinksApiService) {} + constructor( + private shareLinksApiService: ShareLinksApiService, + private router: Router, + ) { + this.router.events + .pipe(filter((event) => event instanceof NavigationEnd)) + .subscribe((event: NavigationEnd) => { + if (!event.urlAfterRedirects.startsWith('/share/')) { + this._currentShareToken = ''; + this._shareLinks = undefined; + } + }); + } public get currentShareToken() { return this._currentShareToken; } public set currentShareToken(token: string) { + if (this._currentShareToken !== token) { + this._shareLinks = undefined; + } this._currentShareToken = token; } + public async primeForToken(token: string): Promise { + this.currentShareToken = token; + if (!token) { + this._shareLinks = []; + return; + } + try { + this._shareLinks = await this.shareLinksApiService.getShareLinksByToken([ + token, + ]); + } catch { + this._shareLinks = []; + } + } + + public isUnlistedShareSync(): boolean { + if (!this._currentShareToken || !this._shareLinks?.length) { + return false; + } + return this._shareLinks[0].accessRestrictions === 'none'; + } + public async isUnlistedShare() { if (!this._currentShareToken) { return false; diff --git a/src/app/share-preview/components/share-preview/share-preview.component.spec.ts b/src/app/share-preview/components/share-preview/share-preview.component.spec.ts index 6239124e9..99e5db331 100644 --- a/src/app/share-preview/components/share-preview/share-preview.component.spec.ts +++ b/src/app/share-preview/components/share-preview/share-preview.component.spec.ts @@ -21,6 +21,7 @@ import { AccountVO, ArchiveVO, RecordVO } from '@root/app/models'; import { AuthResponse } from '@shared/services/api/auth.repo'; import { Subject } from 'rxjs'; import { ShareLinksService } from '@root/app/share-links/services/share-links.service'; +import { AccountService } from '@shared/services/account/account.service'; import { ApiService } from '@shared/services/api/api.service'; import { GoogleAnalyticsService } from '@shared/services/google-analytics/google-analytics.service'; import { ShareResponse } from '@shared/services/api/share.repo'; @@ -72,6 +73,7 @@ mockAccountService.accountChange = new Subject(); const mockShareLinksService = { currentShareToken: null, isUnlistedShare: () => true, + isUnlistedShareSync: () => true, }; const mockFilesystemService = { @@ -123,6 +125,11 @@ describe('SharePreviewComponent', () => { useValue: mockRoute, }); + config.providers.push({ + provide: AccountService, + useValue: mockAccountService, + }); + config.providers.push({ provide: ShareLinksService, useValue: mockShareLinksService, @@ -159,15 +166,9 @@ describe('SharePreviewComponent', () => { expect(component).toBeTruthy(); }); - it('should mark it as unlisted share if restrictions are none', fakeAsync(() => { - spyOn(mockShareLinksService, 'isUnlistedShare').and.returnValue(true); - component.ngOnInit(); - - expect(mockShareLinksService.isUnlistedShare).toHaveBeenCalled(); - tick(1005); - + it('should mark it as unlisted share synchronously when restrictions are none', () => { expect(component.isUnlistedShare).toEqual(true); - })); + }); it('should open dialog shortly after loading if user is logged out and it is not an unlisted share', fakeAsync(() => { const dialogRefSpy = jasmine.createSpyObj('DialogRef', ['close']); diff --git a/src/app/share-preview/components/share-preview/share-preview.component.ts b/src/app/share-preview/components/share-preview/share-preview.component.ts index ec15a5680..f3ffbd098 100644 --- a/src/app/share-preview/components/share-preview/share-preview.component.ts +++ b/src/app/share-preview/components/share-preview/share-preview.component.ts @@ -121,6 +121,8 @@ export class SharePreviewComponent implements OnInit, OnDestroy { private dataService: DataService, ) { this.shareToken = this.route.snapshot.params.shareToken; + this.isUnlistedShare = this.shareLinksService.isUnlistedShareSync(); + this.ephemeralFolder = this.route.snapshot.data.ephemeralFolder ?? null; this.signupForm = fb.group({ invitation: [this.isInvite ? this.sharePreviewVO.token : ''], @@ -192,19 +194,7 @@ export class SharePreviewComponent implements OnInit, OnDestroy { } async ngOnInit() { - this.shareLinksService.currentShareToken = this.shareToken; - this.isUnlistedShare = await this.shareLinksService.isUnlistedShare(); - - if (this.isUnlistedShare) { - if (this.route.snapshot.data.sharePreviewVO?.FolderVO) { - this.ephemeralFolder = await this.filesystemService.getFolder( - this.route.snapshot.data.sharePreviewVO.FolderVO, - ); - } else { - this.ephemeralFolder = this.route.snapshot.data.currentFolder; - this.ephemeralFolder.folderId = - this.route.snapshot.data.sharePreviewVO?.RecordVO?.parentFolderId; - } + if (this.ephemeralFolder) { this.dataService.ephemeralFolder = this.ephemeralFolder; this.dataService.pushBreadcrumbFolder(this.ephemeralFolder); } @@ -253,8 +243,6 @@ export class SharePreviewComponent implements OnInit, OnDestroy { } ngOnDestroy(): void { - this.shareLinksService.currentShareToken = undefined; - this.routerListener.unsubscribe(); this.accountListener.unsubscribe(); this.archiveListener.unsubscribe(); diff --git a/src/app/share-preview/resolves/share-url-ephemeral-folder-resolve.service.ts b/src/app/share-preview/resolves/share-url-ephemeral-folder-resolve.service.ts new file mode 100644 index 000000000..61fb72486 --- /dev/null +++ b/src/app/share-preview/resolves/share-url-ephemeral-folder-resolve.service.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { FolderVO, RecordVO, ShareByUrlVO } from '@models'; +import { DataStatus } from '@models/data-status.enum'; +import { FilesystemService } from '@root/app/filesystem/filesystem.service'; +import { ShareLinksService } from '@root/app/share-links/services/share-links.service'; + +@Injectable() +export class ShareUrlEphemeralFolderResolveService { + constructor( + private filesystemService: FilesystemService, + private shareLinksService: ShareLinksService, + ) {} + + async resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot, + ): Promise { + if (!this.shareLinksService.isUnlistedShareSync()) { + return null; + } + + const sharePreviewVO = route.parent?.data?.sharePreviewVO as ShareByUrlVO; + if (!sharePreviewVO) { + return null; + } + + if (sharePreviewVO.FolderVO) { + return await this.filesystemService.getFolder(sharePreviewVO.FolderVO); + } + + if (sharePreviewVO.RecordVO) { + const record = sharePreviewVO.RecordVO as RecordVO; + record.dataStatus = DataStatus.Full; + const recordFolder = new FolderVO({ + displayName: record.displayName, + description: record.description, + archiveId: record.archiveId, + type: 'type.folder.share', + ChildItemVOs: [record], + pathAsText: [record.displayName], + pathAsArchiveNbr: ['0000-0000'], + pathAsFolder_linkId: [0], + }); + recordFolder.folderId = record.parentFolderId; + return recordFolder; + } + + return null; + } +} diff --git a/src/app/share-preview/resolves/share-url-resolve.service.spec.ts b/src/app/share-preview/resolves/share-url-resolve.service.spec.ts new file mode 100644 index 000000000..e342a7e8d --- /dev/null +++ b/src/app/share-preview/resolves/share-url-resolve.service.spec.ts @@ -0,0 +1,106 @@ +import { TestBed } from '@angular/core/testing'; +import { + ActivatedRouteSnapshot, + Router, + RouterStateSnapshot, +} from '@angular/router'; + +import { AccountService } from '@shared/services/account/account.service'; +import { ApiService } from '@shared/services/api/api.service'; +import { DeviceService } from '@shared/services/device/device.service'; +import { MessageService } from '@shared/services/message/message.service'; +import { ShareResponse } from '@shared/services/api/share.repo'; +import { ShareLinksService } from '@root/app/share-links/services/share-links.service'; + +import { ShareUrlResolveService } from './share-url-resolve.service'; + +describe('ShareUrlResolveService', () => { + let service: ShareUrlResolveService; + let checkShareLinkSpy: jasmine.Spy; + let primeForTokenSpy: jasmine.Spy; + let routerNavigateSpy: jasmine.Spy; + let messageShowErrorSpy: jasmine.Spy; + + const buildRoute = (shareToken: string) => + ({ params: { shareToken } }) as unknown as ActivatedRouteSnapshot; + const buildState = () => ({}) as RouterStateSnapshot; + + beforeEach(() => { + checkShareLinkSpy = jasmine.createSpy('checkShareLink'); + primeForTokenSpy = jasmine + .createSpy('primeForToken') + .and.resolveTo(undefined); + routerNavigateSpy = jasmine.createSpy('navigate').and.resolveTo(true); + messageShowErrorSpy = jasmine.createSpy('showError'); + + TestBed.configureTestingModule({ + providers: [ + ShareUrlResolveService, + { + provide: ApiService, + useValue: { share: { checkShareLink: checkShareLinkSpy } }, + }, + { + provide: MessageService, + useValue: { showError: messageShowErrorSpy }, + }, + { provide: Router, useValue: { navigate: routerNavigateSpy } }, + { provide: DeviceService, useValue: {} }, + { + provide: AccountService, + useValue: { setRedirect: jasmine.createSpy() }, + }, + { + provide: ShareLinksService, + useValue: { primeForToken: primeForTokenSpy }, + }, + ], + }); + service = TestBed.inject(ShareUrlResolveService); + }); + + it('should resolve sharePreviewVO and prime the share-links cache in parallel', async () => { + const sharePreviewVO = { ArchiveVO: {} } as any; + const successResponse = { + isSuccessful: true, + getShareByUrlVO: () => sharePreviewVO, + } as unknown as ShareResponse; + checkShareLinkSpy.and.resolveTo(successResponse); + + const result = await service.resolve(buildRoute('abc123'), buildState()); + + expect(checkShareLinkSpy).toHaveBeenCalledWith('abc123'); + expect(primeForTokenSpy).toHaveBeenCalledWith('abc123'); + expect(result).toBe(sharePreviewVO); + }); + + it('should navigate to share/error when checkShareLink fails', async () => { + const failureResponse = { + isSuccessful: false, + getMessage: () => 'oops', + messageIncludes: () => false, + } as unknown as ShareResponse; + checkShareLinkSpy.and.rejectWith(failureResponse); + + await service.resolve(buildRoute('abc123'), buildState()); + + expect(routerNavigateSpy).toHaveBeenCalledWith(['share', 'error']); + expect(messageShowErrorSpy).toHaveBeenCalled(); + }); + + it('should still resolve sharePreviewVO when primeForToken fails', async () => { + const sharePreviewVO = { ArchiveVO: {} } as any; + const successResponse = { + isSuccessful: true, + getShareByUrlVO: () => sharePreviewVO, + } as unknown as ShareResponse; + checkShareLinkSpy.and.resolveTo(successResponse); + // primeForToken swallows its own errors and always resolves, + // so the resolver should never see a rejection from it. + primeForTokenSpy.and.resolveTo(undefined); + + const result = await service.resolve(buildRoute('abc123'), buildState()); + + expect(result).toBe(sharePreviewVO); + }); +}); diff --git a/src/app/share-preview/resolves/share-url-resolve.service.ts b/src/app/share-preview/resolves/share-url-resolve.service.ts index ead60200a..31b190616 100644 --- a/src/app/share-preview/resolves/share-url-resolve.service.ts +++ b/src/app/share-preview/resolves/share-url-resolve.service.ts @@ -9,6 +9,7 @@ import { ApiService } from '@shared/services/api/api.service'; import { MessageService } from '@shared/services/message/message.service'; import { DeviceService } from '@shared/services/device/device.service'; import { AccountService } from '@shared/services/account/account.service'; +import { ShareLinksService } from '@root/app/share-links/services/share-links.service'; import { ShareResponse } from '@shared/services/api/index.repo'; @@ -20,36 +21,32 @@ export class ShareUrlResolveService { private router: Router, private device: DeviceService, private accountService: AccountService, + private shareLinksService: ShareLinksService, ) {} async resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - return await this.api.share - .checkShareLink(route.params.shareToken) - .then((response: ShareResponse): any => { - if (response.isSuccessful) { - const shareByUrlVO = response.getShareByUrlVO(); + const shareToken = route.params.shareToken; + const [shareResponse] = await Promise.all([ + this.api.share + .checkShareLink(shareToken) + .catch((response: ShareResponse) => response), + this.shareLinksService.primeForToken(shareToken), + ]); - return shareByUrlVO; - } else { - throw response; - } - }) - .catch(async (response: ShareResponse) => { - if (response.getMessage) { - if (response.messageIncludes('warning.auth.mfaToken')) { - this.accountService.setRedirect([ - '/share', - route.params.shareToken, - ]); - return await this.router.navigate(['/app', 'auth', 'mfa']); - } else { - this.message.showError({ - message: response.getMessage(), - translate: true, - }); - } - } - return await this.router.navigate(['share', 'error']); + if (shareResponse.isSuccessful) { + return shareResponse.getShareByUrlVO(); + } + + if (shareResponse.getMessage) { + if (shareResponse.messageIncludes('warning.auth.mfaToken')) { + this.accountService.setRedirect(['/share', shareToken]); + return await this.router.navigate(['/app', 'auth', 'mfa']); + } + this.message.showError({ + message: shareResponse.getMessage(), + translate: true, }); + } + return await this.router.navigate(['share', 'error']); } } diff --git a/src/app/share-preview/share-preview.routes.ts b/src/app/share-preview/share-preview.routes.ts index 8a8557375..40ad745eb 100644 --- a/src/app/share-preview/share-preview.routes.ts +++ b/src/app/share-preview/share-preview.routes.ts @@ -13,6 +13,7 @@ import { PreviewArchiveResolveService } from './resolves/preview-archive-resolve import { PreviewResolveService } from './resolves/preview-resolve.service'; import { PreviewFolderResolveService } from './resolves/preview-folder-resolve.service'; import { ShareUrlResolveService } from './resolves/share-url-resolve.service'; +import { ShareUrlEphemeralFolderResolveService } from './resolves/share-url-ephemeral-folder-resolve.service'; import { ShareNotFoundComponent } from './components/share-not-found/share-not-found.component'; import { CreateAccountDialogComponent } from './components/create-account-dialog/create-account-dialog.component'; import { InviteShareResolveService } from './resolves/invite-share-resolve.service'; @@ -22,6 +23,7 @@ import { SharePreviewFooterComponent } from './components/share-preview-footer/s const previewResolve = { currentFolder: PreviewResolveService, + ephemeralFolder: ShareUrlEphemeralFolderResolveService, }; const shareResolve = { @@ -113,6 +115,7 @@ export const routes: Routes = [ PreviewArchiveResolveService, PreviewFolderResolveService, ShareUrlResolveService, + ShareUrlEphemeralFolderResolveService, InviteShareResolveService, RelationshipShareResolveService, ],