mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-08-12 00:19:48 +00:00
Feature: loading preview, better text popup preview (#8011)
This commit is contained in:
@@ -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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
)
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user