Feature: loading preview, better text popup preview (#8011)

This commit is contained in:
shamoon
2024-11-12 16:20:52 -08:00
committed by GitHub
parent 74d0c9fda5
commit a283a65813
15 changed files with 192 additions and 95 deletions

View File

@@ -350,14 +350,16 @@
</ng-template>
<ng-template #previewContent>
@if (!metadata) {
<div class="w-100 h-100 d-flex align-items-center justify-content-center">
<div class="thumb-preview position-absolute pe-none" [class.fade]="previewLoaded">
<img *ngIf="showThumbnailOverlay" [src]="thumbUrl | safeUrl" class="" width="100%" height="auto" alt="Document loading..." i18n-alt />
<div class="position-absolute top-0 start-0 m-2 p-2 d-flex align-items-center justify-content-center">
<div>
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
<ng-container i18n>Loading...</ng-container>
</div>
</div>
} @else {
</div>
@if (document) {
@switch (archiveContentRenderType) {
@case (ContentRenderType.PDF) {
@if (!useNativePdfViewer) {

View File

@@ -63,6 +63,27 @@ textarea.rtl {
object-fit: contain;
}
.whitespace-preserve {
white-space: preserve;
.thumb-preview {
top: 0;
left: 0;
width: 100%;
height: calc(100vh - 160px);
@media screen and (min-width: 768px) {
left: calc(.5 * var(--bs-gutter-x));
width: calc(100% - var(--bs-gutter-x));
}
overflow: hidden;
background-color: gray;
padding: 10px 8px; // border
z-index: 1000;
> div {
mix-blend-mode: difference;
}
> img {
filter: blur(1px);
}
}

View File

@@ -774,6 +774,15 @@ describe('DocumentDetailComponent', () => {
expect(component.previewNumPages).toEqual(1000)
})
it('should include delay of 300ms after previewloaded before showing pdf', fakeAsync(() => {
initNormally()
expect(component.previewLoaded).toBeFalsy()
component.pdfPreviewLoaded({ numPages: 1000 } as any)
expect(component.previewNumPages).toEqual(1000)
tick(300)
expect(component.previewLoaded).toBeTruthy()
}))
it('should support zoom controls', () => {
initNormally()
component.onZoomSelect({ target: { value: '1' } } as any) // from select
@@ -921,7 +930,7 @@ describe('DocumentDetailComponent', () => {
it('should display built-in pdf viewer if not disabled', () => {
initNormally()
component.metadata = { has_archive_version: true }
component.document.archived_file_name = 'file.pdf'
jest.spyOn(settingsService, 'get').mockReturnValue(false)
expect(component.useNativePdfViewer).toBeFalsy()
fixture.detectChanges()
@@ -930,7 +939,7 @@ describe('DocumentDetailComponent', () => {
it('should display native pdf viewer if enabled', () => {
initNormally()
component.metadata = { has_archive_version: true }
component.document.archived_file_name = 'file.pdf'
jest.spyOn(settingsService, 'get').mockReturnValue(true)
expect(component.useNativePdfViewer).toBeTruthy()
fixture.detectChanges()
@@ -1072,8 +1081,8 @@ describe('DocumentDetailComponent', () => {
})
it('should change preview element by render type', () => {
component.metadata = { has_archive_version: true }
initNormally()
component.document.archived_file_name = 'file.pdf'
fixture.detectChanges()
expect(component.archiveContentRenderType).toEqual(
component.ContentRenderType.PDF
@@ -1082,10 +1091,8 @@ describe('DocumentDetailComponent', () => {
fixture.debugElement.query(By.css('pdf-viewer-container'))
).not.toBeUndefined()
component.metadata = {
has_archive_version: false,
original_mime_type: 'text/plain',
}
component.document.archived_file_name = undefined
component.document.mime_type = 'text/plain'
fixture.detectChanges()
expect(component.archiveContentRenderType).toEqual(
component.ContentRenderType.Text
@@ -1094,10 +1101,7 @@ describe('DocumentDetailComponent', () => {
fixture.debugElement.query(By.css('div.preview-sticky'))
).not.toBeUndefined()
component.metadata = {
has_archive_version: false,
original_mime_type: 'image/jpg',
}
component.document.mime_type = 'image/jpeg'
fixture.detectChanges()
expect(component.archiveContentRenderType).toEqual(
component.ContentRenderType.Image
@@ -1105,13 +1109,9 @@ describe('DocumentDetailComponent', () => {
expect(
fixture.debugElement.query(By.css('.preview-sticky img'))
).not.toBeUndefined()
component.metadata = {
has_archive_version: false,
original_mime_type:
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
}
fixture.detectChanges()
;(component.document.mime_type =
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'),
fixture.detectChanges()
expect(component.archiveContentRenderType).toEqual(
component.ContentRenderType.Other
)

View File

@@ -131,9 +131,11 @@ export class DocumentDetailComponent
title: string
titleSubject: Subject<string> = new Subject()
previewUrl: string
thumbUrl: string
previewText: string
downloadUrl: string
downloadOriginalUrl: string
previewLoaded: boolean = false
correspondents: Correspondent[]
documentTypes: DocumentType[]
@@ -221,15 +223,17 @@ export class DocumentDetailComponent
}
get archiveContentRenderType(): ContentRenderType {
return this.getRenderType(
this.metadata?.has_archive_version
? 'application/pdf'
: this.metadata?.original_mime_type
)
return this.document?.archived_file_name
? this.getRenderType('application/pdf')
: this.getRenderType(this.document?.mime_type)
}
get originalContentRenderType(): ContentRenderType {
return this.getRenderType(this.metadata?.original_mime_type)
return this.getRenderType(this.document?.mime_type)
}
get showThumbnailOverlay(): boolean {
return this.settings.get(SETTINGS_KEYS.DOCUMENT_EDITING_OVERLAY_THUMBNAIL)
}
private getRenderType(mimeType: string): ContentRenderType {
@@ -339,6 +343,7 @@ export class DocumentDetailComponent
}`
},
})
this.thumbUrl = this.documentsService.getThumbUrl(documentId)
return this.documentsService.get(documentId)
})
)
@@ -537,6 +542,9 @@ export class DocumentDetailComponent
.subscribe({
next: (result) => {
this.metadata = result
if (this.archiveContentRenderType !== ContentRenderType.PDF) {
this.previewLoaded = true
}
},
error: (error) => {
this.metadata = {} // allow display to fallback to <object> tag
@@ -903,11 +911,15 @@ export class DocumentDetailComponent
pdfPreviewLoaded(pdf: PDFDocumentProxy) {
this.previewNumPages = pdf.numPages
if (this.password) this.requiresPassword = false
setTimeout(() => {
this.previewLoaded = true
}, 300)
}
onError(event) {
if (event.name == 'PasswordException') {
this.requiresPassword = true
this.previewLoaded = true
}
}