From 0eb0ff167bd286d334ce4b29cca262130416822e Mon Sep 17 00:00:00 2001 From: swapnil-verma-gl <92505353+swapnil-verma-gl@users.noreply.github.com> Date: Wed, 12 Apr 2023 19:32:34 +0530 Subject: [PATCH] [ACA-4676][ACA-4678] Added Non Responsive Preview Dialog to viewer component (#8428) * [ACA-4676] Added NonResponsivePreview dialog to download file incase file preview takes longer than a set period of time. * [ACA-4676] Updated button positioning for non responsive preview dialog * [ACA-4676] Added documentation for NonResponsivePreviewDialog functionality for viewer.component.ts * [ACA-4676] Added unit tests for NonResponsivePreviewDialog * [ACA-4676] Updated template of NonResponsivePreviewDialog to use components and directives from mat-dialog. Removed non-responsive-dialog.component.scss. Removed unused methods from non-responsive-dialog.component.ts * [ACA-4676] Corrected typo in NonResponsivePreviewDialog unit tests * [ACA-4676] Added test cases for NonResponsivePreviewDialog in viewer.component.ts. NOT WORKING * [ACA-4676] Fixed test cases for non-responsive preview dialog. Moved NonResponsivePreview dialog tests to separate describe block. Updated component code to make properties and methods visible to testing environment * [ACA-4676] Migrated viewer component test env setup from setupTestBed() to TestBed.configureTestingModule(). Moved NonResponsivePreviewDialog unit tests to inside parent Viewer component describe block * [ACA-4676] Removed unused async tag. Added license info to non-responsive-dialog.component.ts and non-responsive-preview-actions.enum.ts * [ACA-4676] Updated code to use "viewer" appConfig object instead of "preview-config". Added non-responsive-preview-actions.enum.ts to public-api.ts * [ACA-4676] Resolved potential lint issues * [ACA-4676] Updated non responsive preview to look for viewer config object inside app.config instead of preview-config * [ACA-4676] Removed duplicate import for @adf/core. Added NonResponsiveDialogComponent to adf/core exports * [ACA-4676] Renamed properties/config/documentation from nonResponsivePreview to downloadPrompt. Renamed NonResponsivePreviewActionsEnum to DownloadPromptActions. * [ACA-4676] Resolved linting and unit test failures * [ACA-4676] Changed dataType for timers to number. Updated code to use window.setTimeout(), instead of just setTimeout(). Added missing whitespace. Updated method names in demo shell to use 'downloadPrompt' naming scheme. * [ACA-4676] Fixed incorrect import statement in viewer.module.ts for download-prompt-dialog * [ACA-4676] Testing disabled by default behaviour of downloadPrompt feature * [ACA-4676] Changed default value for enableDownloadPrompt and enableDownloadPromptReminders to false in app.config.json * [ACA-4676] Removed un-needed AppConfig configurations from unit tests --- demo-shell/src/app.config.json | 4 + .../app/components/files/files.component.html | 24 ++++ .../app/components/files/files.component.ts | 24 ++++ docs/core/components/viewer.component.md | 25 ++++ lib/core/src/lib/i18n/en.json | 9 +- .../download-prompt-dialog.component.html | 23 ++++ .../download-prompt-dialog.component.spec.ts | 73 +++++++++++ .../download-prompt-dialog.component.ts | 27 ++++ .../components/viewer.component.spec.ts | 118 ++++++++++++++---- .../lib/viewer/components/viewer.component.ts | 97 +++++++++++++- .../viewer/models/download-prompt.actions.ts | 22 ++++ lib/core/src/lib/viewer/public-api.ts | 2 + lib/core/src/lib/viewer/viewer.module.ts | 4 +- 13 files changed, 423 insertions(+), 29 deletions(-) create mode 100644 lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.html create mode 100644 lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts create mode 100644 lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.ts create mode 100644 lib/core/src/lib/viewer/models/download-prompt.actions.ts diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index f055130a77..6a8abf7e33 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -1478,6 +1478,10 @@ ] }, "viewer": { + "enableDownloadPrompt": false, + "enableDownloadPromptReminder": false, + "downloadPromptDelay": 50, + "downloadPromptReminderDelay": 30, "enableFileAutoDownload": true, "fileAutoDownloadSizeThresholdInMB": 15 } diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html index a1de8a994f..207752d20d 100644 --- a/demo-shell/src/app/components/files/files.component.html +++ b/demo-shell/src/app/components/files/files.component.html @@ -653,6 +653,30 @@ +
+ + Enable Download Prompt + +
+
+ + + +
+ +
+ + Enable Download Prompt Reminders + +
+
+ + + +
+
diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts index 6980dcfa62..570f16e3ad 100644 --- a/demo-shell/src/app/components/files/files.component.ts +++ b/demo-shell/src/app/components/files/files.component.ts @@ -251,6 +251,10 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { selectedNodes = []; + enableDownloadPrompt: boolean = this.appConfig.get('viewer.enableDownloadPrompt', false); + enableDownloadPromptReminder: boolean = this.appConfig.get('viewer.enableDownloadPromptReminders', false); + downloadPromptDelay = this.appConfig.get('viewer.downloadPromptDelay', 50); + downloadPromptReminderDelay = this.appConfig.get('viewer.downloadPromptReminderDelay', 30); enableFileAutoDownload: boolean = this.appConfig.get('viewer.enableFileAutoDownload', true); fileAutoDownloadSizeThresholdInMB: number = this.appConfig.get('viewer.fileAutoDownloadSizeThresholdInMB', 15); @@ -780,6 +784,26 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { this.selectedNodes = []; } + onEnableDownloadPrompt() { + const previewConfig = this.appConfig?.config['viewer']; + previewConfig['enableDownloadPrompt'] = this.enableDownloadPrompt; + } + + onDownloadPromptDelayChange() { + const previewConfig = this.appConfig?.config['viewer']; + previewConfig['downloadPromptDelay'] = this.downloadPromptDelay; + } + + onEnableDownloadPromptReminderChange() { + const previewConfig = this.appConfig?.config['viewer']; + previewConfig['enableDownloadPromptReminder'] = this.enableDownloadPromptReminder; + } + + onDownloadPromptReminderChange() { + const previewConfig = this.appConfig?.config['viewer']; + previewConfig['downloadPromptReminderDelay'] = this.downloadPromptReminderDelay; + } + onEnableFileAutoDownloadChange() { const previewConfig = this.appConfig?.config['viewer']; previewConfig['enableFileAutoDownload'] = this.enableFileAutoDownload; diff --git a/docs/core/components/viewer.component.md b/docs/core/components/viewer.component.md index e3f815f1aa..e592f28bbc 100644 --- a/docs/core/components/viewer.component.md +++ b/docs/core/components/viewer.component.md @@ -380,6 +380,31 @@ In the same way you can set a default zoom scaling value for the image viewer by By default the viewer's zoom scaling is set to 100%. +## Handling non responsive file preview + +It is possible that trying to load a large file, especially over a slow network, can cause the viewer component to get stuck in the loading state. To handle such cases, +the viewer can be configured to display a prompt to ask the user to either download the file locally and then close the viewer, or wait for the viewer to load the file. +In case the user decides to wait, the viewer can further be configured to display subsequent reminder prompts asking the same options. + +In order to configure this feature, add the following code in `app.config.json`. + +``` + "viewer": { + "enableDownloadPrompt": true, + "enableDownloadPromptReminder": true, + "downloadPromptDelay": 50, + "downloadPromptReminderDelay": 30 + } +``` + +Here `enableDownloadPrompt: true` enables the dialog to be visible after a set period of time. This time can be configured by updating the value in the +`downloadPromptDelay` property. + +The second boolean flag `enableDownloadPromptReminder: true` can be used to configure whether the reminder prompts should be displayed or not. +`downloadPromptReminderDelay` property can be used to configure the time to wait between reminder prompts. + +Note: All times in this configuration must be provided in seconds + ## See also - [Document List component](../../content-services/components/document-list.component.md) diff --git a/lib/core/src/lib/i18n/en.json b/lib/core/src/lib/i18n/en.json index 426dcb40a3..362a9b32a7 100644 --- a/lib/core/src/lib/i18n/en.json +++ b/lib/core/src/lib/i18n/en.json @@ -391,7 +391,8 @@ "FULLSCREEN": "Activate full-screen mode", "CLOSE": "Close", "NEXT_FILE": "Next File", - "PREV_FILE": "Previous File" + "PREV_FILE": "Previous File", + "WAIT": "Wait" }, "ARIA": { "PREVIOUS_PAGE": "Previous page", @@ -429,7 +430,11 @@ "PLACEHOLDER": "Password", "ERROR": "Password is wrong" }, - "SUBTITLES": "Subtitles" + "SUBTITLES": "Subtitles", + "NON_RESPONSIVE_DIALOG": { + "HEADER": "Preview loading delayed", + "LABEL": "You can continue to wait, or download the document." + } }, "ERROR_CONTENT": { "UNKNOWN": { diff --git a/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.html b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.html new file mode 100644 index 0000000000..d84c16fc9e --- /dev/null +++ b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.html @@ -0,0 +1,23 @@ +
+

{{ 'ADF_VIEWER.NON_RESPONSIVE_DIALOG.HEADER' | translate }}

+
+ + {{ 'ADF_VIEWER.NON_RESPONSIVE_DIALOG.LABEL' | translate }} + + + + + diff --git a/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts new file mode 100644 index 0000000000..78bfeccda2 --- /dev/null +++ b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.spec.ts @@ -0,0 +1,73 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CoreTestingModule, DownloadPromptDialogComponent, DownloadPromptActions } from '@alfresco/adf-core'; +import { By } from '@angular/platform-browser'; +import { MatDialogRef } from '@angular/material/dialog'; +import { TranslateModule } from '@ngx-translate/core'; + +const mockDialog = { + close: jasmine.createSpy('close') +}; + +describe('DownloadPromptDialogComponent', () => { + let matDialogRef: MatDialogRef; + let fixture: ComponentFixture; + + const getButton = (buttonId: string) => { + return fixture.debugElement.query(By.css(buttonId)).nativeElement; + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [DownloadPromptDialogComponent], + imports: [ + TranslateModule.forRoot(), + CoreTestingModule + ], + providers: [ + { provide: MatDialogRef, useValue: mockDialog } + ] + }); + matDialogRef = TestBed.inject(MatDialogRef); + + fixture = TestBed.createComponent(DownloadPromptDialogComponent); + fixture.detectChanges(); + }); + + it('should emit DownloadPromptActions.WAIT and close dialog when clicking on the wait button', async () => { + const waitButton = getButton('#waitButton'); + waitButton.dispatchEvent(new Event('click')); + + await fixture.detectChanges(); + await fixture.whenStable(); + + expect(matDialogRef.close).toHaveBeenCalledWith(DownloadPromptActions.WAIT); + }); + + it('should emit DownloadPromptActions.DOWNLOAD and close dialog when clicking on the download button', async () => { + const waitButton = getButton('#downloadButton'); + waitButton.dispatchEvent(new Event('click')); + + await fixture.detectChanges(); + await fixture.whenStable(); + + expect(matDialogRef.close).toHaveBeenCalledWith(DownloadPromptActions.DOWNLOAD); + }); +}); diff --git a/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.ts b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.ts new file mode 100644 index 0000000000..9910e3472e --- /dev/null +++ b/lib/core/src/lib/viewer/components/download-prompt-dialog/download-prompt-dialog.component.ts @@ -0,0 +1,27 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component } from '@angular/core'; +import { DownloadPromptActions } from '../../models/download-prompt.actions'; + +@Component({ + selector: 'adf-download-prompt-dialog', + templateUrl: './download-prompt-dialog.component.html' +}) +export class DownloadPromptDialogComponent { + DownloadPromptActions = DownloadPromptActions; +} diff --git a/lib/core/src/lib/viewer/components/viewer.component.spec.ts b/lib/core/src/lib/viewer/components/viewer.component.spec.ts index 4d7e525a97..25f00b7b6f 100644 --- a/lib/core/src/lib/viewer/components/viewer.component.spec.ts +++ b/lib/core/src/lib/viewer/components/viewer.component.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { MatDialog } from '@angular/material/dialog'; @@ -24,12 +24,15 @@ import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { CoreTestingModule, - setupTestBed, EventMock, ViewerComponent, - ViewUtilService + ViewUtilService, + AppConfigService, + DownloadPromptDialogComponent, + DownloadPromptActions } from '@alfresco/adf-core'; import { Component } from '@angular/core'; +import { of } from 'rxjs'; @Component({ selector: 'adf-viewer-container-toolbar', @@ -135,35 +138,48 @@ describe('ViewerComponent', () => { let element: HTMLElement; let dialog: MatDialog; let viewUtilService: ViewUtilService; - - setupTestBed({ - imports: [ - NoopAnimationsModule, - TranslateModule.forRoot(), - CoreTestingModule, - MatButtonModule, - MatIconModule - ], - declarations: [ - ViewerWithCustomToolbarComponent, - ViewerWithCustomSidebarComponent, - ViewerWithCustomOpenWithComponent, - ViewerWithCustomMoreActionsComponent, - ViewerWithCustomToolbarActionsComponent - ], - providers: [ - MatDialog - ] - }); + let appConfigService: AppConfigService; beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + TranslateModule.forRoot(), + CoreTestingModule, + MatButtonModule, + MatIconModule + ], + declarations: [ + ViewerWithCustomToolbarComponent, + ViewerWithCustomSidebarComponent, + ViewerWithCustomOpenWithComponent, + ViewerWithCustomMoreActionsComponent, + ViewerWithCustomToolbarActionsComponent + ], + providers: [ + MatDialog, + { provide: DownloadPromptDialogComponent, useClass: DummyDialogComponent} + ] + }); + fixture = TestBed.createComponent(ViewerComponent); element = fixture.nativeElement; component = fixture.componentInstance; dialog = TestBed.inject(MatDialog); viewUtilService = TestBed.inject(ViewUtilService); + appConfigService = TestBed.inject(AppConfigService); component.fileName = 'test-file.pdf'; + + appConfigService.config = { + ...appConfigService.config, + 'viewer': { + 'enableDownloadPrompt': false, + 'enableDownloadPromptReminder': false, + 'downloadPromptDelay': 3, + 'downloadPromptReminderDelay': 2 + } + }; }); afterEach(() => { @@ -604,4 +620,60 @@ describe('ViewerComponent', () => { }); }); }); + + describe('Download Prompt Dialog',() => { + + let dialogOpenSpy: jasmine.Spy; + + beforeEach(() => { + appConfigService.config = { + ...appConfigService.config, + 'viewer': { + 'enableDownloadPrompt': true, + 'enableDownloadPromptReminder': true, + 'downloadPromptDelay': 3, + 'downloadPromptReminderDelay': 2 + } + }; + dialogOpenSpy = spyOn(dialog, 'open').and.returnValue({afterClosed: () => of(null)} as any); + component.urlFile = undefined; + component.clearDownloadPromptTimeouts(); + }); + + it('should configure initial timeout to display non responsive dialog when initialising component', (() => { + fixture.detectChanges(); + expect(component.downloadPromptTimer).toBeDefined(); + })); + + it('should configure reminder timeout to display non responsive dialog after initial dialog', fakeAsync( () => { + dialogOpenSpy.and.returnValue({ afterClosed: () => of(DownloadPromptActions.WAIT) } as any); + fixture.detectChanges(); + tick(3000); + expect(component.downloadPromptReminderTimer).toBeDefined(); + dialogOpenSpy.and.returnValue({ afterClosed: () => of(null) } as any); + flush(); + discardPeriodicTasks(); + })); + + it('should show initial non responsive dialog after initial timeout', fakeAsync( () => { + fixture.detectChanges(); + tick(3000); + fixture.detectChanges(); + expect(dialogOpenSpy).toHaveBeenCalled(); + })); + + it('should show reminder non responsive dialog after initial dialog', fakeAsync( () => { + dialogOpenSpy.and.returnValue({ afterClosed: () => of(DownloadPromptActions.WAIT) } as any); + fixture.detectChanges(); + tick(3000); + expect(dialogOpenSpy).toHaveBeenCalled(); + + dialogOpenSpy.and.returnValue({ afterClosed: () => of(null) } as any); + tick(2000); + expect(dialogOpenSpy).toHaveBeenCalledTimes(2); + + flush(); + discardPeriodicTasks(); + })); + }); }); diff --git a/lib/core/src/lib/viewer/components/viewer.component.ts b/lib/core/src/lib/viewer/components/viewer.component.ts index c769bb7182..364ab8a315 100644 --- a/lib/core/src/lib/viewer/components/viewer.component.ts +++ b/lib/core/src/lib/viewer/components/viewer.component.ts @@ -30,15 +30,25 @@ import { TemplateRef, ViewEncapsulation } from '@angular/core'; -import { fromEvent, Subject } from 'rxjs'; +import { fromEvent, Subject } from 'rxjs'; import { MatDialog } from '@angular/material/dialog'; import { ViewerToolbarComponent } from './viewer-toolbar.component'; import { ViewerOpenWithComponent } from './viewer-open-with.component'; import { ViewerMoreActionsComponent } from './viewer-more-actions.component'; import { ViewerSidebarComponent } from './viewer-sidebar.component'; -import { filter, skipWhile, takeUntil } from 'rxjs/operators'; +import { filter, first, skipWhile, takeUntil } from 'rxjs/operators'; import { Track } from '../models/viewer.model'; import { ViewUtilService } from '../services/view-util.service'; +import { DownloadPromptDialogComponent } from './download-prompt-dialog/download-prompt-dialog.component'; +import { AppConfigService } from '../../app-config'; +import { DownloadPromptActions } from '../models/download-prompt.actions'; + +const DEFAULT_NON_PREVIEW_CONFIG = { + enableDownloadPrompt: false, + enableDownloadPromptReminder: false, + downloadPromptDelay: 50, + downloadPromptReminderDelay: 30 +}; @Component({ selector: 'adf-viewer', @@ -160,6 +170,26 @@ export class ViewerComponent implements OnDestroy, OnInit, OnChanges { @Input() sidebarLeftTemplateContext: T = null; + /** + * Enable dialog box to allow user to download the previewed file, in case the preview is not responding for a set period of time. + * */ + enableDownloadPrompt: boolean = false; + + /** + * Enable reminder dialogs to prompt user to download the file, in case the preview is not responding for a set period of time. + * */ + enableDownloadPromptReminder: boolean = false; + + /** + * Initial time in seconds to wait before giving the first prompt to user to download the file + * */ + downloadPromptDelay: number = 50; + + /** + * Time in seconds to wait before giving the second and consequent reminders to the user to download the file. + * */ + downloadPromptReminderDelay: number = 15; + /** Emitted when user clicks 'Navigate Before' ("<") button. */ @Output() navigateBefore = new EventEmitter(); @@ -180,10 +210,14 @@ export class ViewerComponent implements OnDestroy, OnInit, OnChanges { private closeViewer = true; private keyDown$ = fromEvent(document, 'keydown'); + private isDialogVisible: boolean = false; + public downloadPromptTimer: number; + public downloadPromptReminderTimer: number; constructor(private el: ElementRef, public dialog: MatDialog, - private viewUtilsService: ViewUtilService + private viewUtilsService: ViewUtilService, + private appConfigService: AppConfigService ) { } @@ -202,6 +236,7 @@ export class ViewerComponent implements OnDestroy, OnInit, OnChanges { ngOnInit(): void { this.closeOverlayManager(); + this.configureAndInitDownloadPrompt(); } private closeOverlayManager() { @@ -304,8 +339,64 @@ export class ViewerComponent implements OnDestroy, OnInit, OnChanges { } ngOnDestroy() { + this.clearDownloadPromptTimeouts(); this.onDestroy$.next(true); this.onDestroy$.complete(); } + private configureAndInitDownloadPrompt() { + this.configureDownloadPromptProperties(); + if (this.enableDownloadPrompt) { + this.initDownloadPrompt(); + } + } + + private configureDownloadPromptProperties() { + const nonResponsivePreviewConfig = this.appConfigService.get('viewer', DEFAULT_NON_PREVIEW_CONFIG); + + this.enableDownloadPrompt = nonResponsivePreviewConfig.enableDownloadPrompt; + this.enableDownloadPromptReminder = nonResponsivePreviewConfig.enableDownloadPromptReminder; + this.downloadPromptDelay = nonResponsivePreviewConfig.downloadPromptDelay; + this.downloadPromptReminderDelay = nonResponsivePreviewConfig.downloadPromptReminderDelay; + } + + private initDownloadPrompt() { + this.downloadPromptTimer = window.setTimeout(() => { + this.showOrClearDownloadPrompt(); + }, this.downloadPromptDelay * 1000); + } + + private showOrClearDownloadPrompt() { + if (!this.urlFile) { + this.showDownloadPrompt(); + } else { + this.clearDownloadPromptTimeouts(); + } + } + + public clearDownloadPromptTimeouts() { + if (this.downloadPromptTimer) { + clearTimeout(this.downloadPromptTimer); + } + if (this.downloadPromptReminderTimer) { + clearTimeout(this.downloadPromptReminderTimer); + } + } + + private showDownloadPrompt() { + if (!this.isDialogVisible) { + this.isDialogVisible = true; + this.dialog.open(DownloadPromptDialogComponent, { disableClose: true }).afterClosed().pipe(first()).subscribe((result: DownloadPromptActions) => { + this.isDialogVisible = false; + if (result === DownloadPromptActions.WAIT) { + if (this.enableDownloadPromptReminder) { + this.clearDownloadPromptTimeouts(); + this.downloadPromptReminderTimer = window.setTimeout(() => { + this.showOrClearDownloadPrompt(); + }, this.downloadPromptReminderDelay * 1000); + } + } + }); + } + } } diff --git a/lib/core/src/lib/viewer/models/download-prompt.actions.ts b/lib/core/src/lib/viewer/models/download-prompt.actions.ts new file mode 100644 index 0000000000..294e48e874 --- /dev/null +++ b/lib/core/src/lib/viewer/models/download-prompt.actions.ts @@ -0,0 +1,22 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Enum listing the allowed actions that can be emitted from the NonResponsivePreview dialog component */ +export enum DownloadPromptActions { + 'WAIT', + 'DOWNLOAD' +} diff --git a/lib/core/src/lib/viewer/public-api.ts b/lib/core/src/lib/viewer/public-api.ts index 36687abbd7..f111371523 100644 --- a/lib/core/src/lib/viewer/public-api.ts +++ b/lib/core/src/lib/viewer/public-api.ts @@ -33,9 +33,11 @@ export * from './components/viewer-toolbar-actions.component'; export * from './components/viewer-toolbar-custom-actions.component'; export * from './components/viewer-render.component'; export * from './components/viewer.component'; +export * from './components/download-prompt-dialog/download-prompt-dialog.component'; export * from './directives/viewer-extension.directive'; export * from './viewer.module'; export * from './models/viewer.model'; +export * from './models/download-prompt.actions'; diff --git a/lib/core/src/lib/viewer/viewer.module.ts b/lib/core/src/lib/viewer/viewer.module.ts index 8c8db68b12..5a1ea401d2 100644 --- a/lib/core/src/lib/viewer/viewer.module.ts +++ b/lib/core/src/lib/viewer/viewer.module.ts @@ -45,6 +45,7 @@ import { DirectiveModule } from '../directives/directive.module'; import { A11yModule } from '@angular/cdk/a11y'; import { ViewerComponent } from './components/viewer.component'; import { ViewerToolbarCustomActionsComponent } from './components/viewer-toolbar-custom-actions.component'; +import { DownloadPromptDialogComponent } from './components/download-prompt-dialog/download-prompt-dialog.component'; @NgModule({ imports: [ @@ -77,7 +78,8 @@ import { ViewerToolbarCustomActionsComponent } from './components/viewer-toolbar ViewerMoreActionsComponent, ViewerToolbarActionsComponent, ViewerComponent, - ViewerToolbarCustomActionsComponent + ViewerToolbarCustomActionsComponent, + DownloadPromptDialogComponent ], exports: [ ViewerRenderComponent,