mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Added option to invert thumbnails in dark mode
This commit is contained in:
		| @@ -1,7 +1,7 @@ | |||||||
| <div class="card mb-3 shadow-sm" [class.card-selected]="selected" [class.document-card]="selectable"> | <div class="card mb-3 shadow-sm" [class.card-selected]="selected" [class.document-card]="selectable"> | ||||||
|   <div class="row no-gutters"> |   <div class="row no-gutters"> | ||||||
|     <div class="col-md-2 d-none d-lg-block doc-img-background rounded-left" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)"> |     <div class="col-md-2 d-none d-lg-block doc-img-background rounded-left" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)"> | ||||||
|       <img [src]="getThumbUrl()" class="card-img doc-img border-right rounded-left"> |       <img [src]="getThumbUrl()" class="card-img {{ getIsThumbInverted() ? 'doc-img-inverted' : 'doc-img' }} border-right rounded-left"> | ||||||
|  |  | ||||||
|       <div style="top: 0; left: 0" class="position-absolute border-right border-bottom bg-light p-1" [class.document-card-check]="!selected"> |       <div style="top: 0; left: 0" class="position-absolute border-right border-bottom bg-light p-1" [class.document-card-check]="!selected"> | ||||||
|         <div class="custom-control custom-checkbox"> |         <div class="custom-control custom-checkbox"> | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|   overflow-wrap: anywhere; |   overflow-wrap: anywhere; | ||||||
| } | } | ||||||
|  |  | ||||||
| .doc-img { | .doc-img, .doc-img-inverted { | ||||||
|   object-fit: cover; |   object-fit: cover; | ||||||
|   object-position: top left; |   object-position: top left; | ||||||
|   height: 100%; |   height: 100%; | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; | |||||||
| import { DomSanitizer } from '@angular/platform-browser'; | import { DomSanitizer } from '@angular/platform-browser'; | ||||||
| import { PaperlessDocument } from 'src/app/data/paperless-document'; | import { PaperlessDocument } from 'src/app/data/paperless-document'; | ||||||
| import { DocumentService } from 'src/app/services/rest/document.service'; | import { DocumentService } from 'src/app/services/rest/document.service'; | ||||||
|  | import { SettingsService, SETTINGS_KEYS } from 'src/app/services/settings.service'; | ||||||
|  |  | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-document-card-large', |   selector: 'app-document-card-large', | ||||||
| @@ -10,7 +11,7 @@ import { DocumentService } from 'src/app/services/rest/document.service'; | |||||||
| }) | }) | ||||||
| export class DocumentCardLargeComponent implements OnInit { | export class DocumentCardLargeComponent implements OnInit { | ||||||
|  |  | ||||||
|   constructor(private documentService: DocumentService, private sanitizer: DomSanitizer) { } |   constructor(private documentService: DocumentService, private sanitizer: DomSanitizer, private settingsService: SettingsService) { } | ||||||
|  |  | ||||||
|   @Input() |   @Input() | ||||||
|   selected = false |   selected = false | ||||||
| @@ -53,6 +54,10 @@ export class DocumentCardLargeComponent implements OnInit { | |||||||
|   ngOnInit(): void { |   ngOnInit(): void { | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   getIsThumbInverted() { | ||||||
|  |     return this.settingsService.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   getDetailsAsString() { |   getDetailsAsString() { | ||||||
|     if (typeof this.details === 'string') { |     if (typeof this.details === 'string') { | ||||||
|       return this.details.substring(0, 500) |       return this.details.substring(0, 500) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <div class="col p-2 h-100"> | <div class="col p-2 h-100"> | ||||||
|   <div class="card h-100 shadow-sm document-card" [class.card-selected]="selected"> |   <div class="card h-100 shadow-sm document-card" [class.card-selected]="selected"> | ||||||
|     <div class="border-bottom doc-img-container" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)"> |     <div class="border-bottom doc-img-container" [class.doc-img-background-selected]="selected" (click)="this.toggleSelected.emit($event)"> | ||||||
|       <img class="card-img doc-img rounded-top" [src]="getThumbUrl()"> |       <img class="card-img {{ getIsThumbInverted() ? 'doc-img-inverted' : 'doc-img' }} rounded-top" [src]="getThumbUrl()"> | ||||||
|  |  | ||||||
|       <div class="border-right border-bottom bg-light p-1 rounded document-card-check"> |       <div class="border-right border-bottom bg-light p-1 rounded document-card-check"> | ||||||
|         <div class="custom-control custom-checkbox"> |         <div class="custom-control custom-checkbox"> | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| @import "/src/theme"; | @import "/src/theme"; | ||||||
|  |  | ||||||
| .doc-img { | .doc-img, .doc-img-inverted { | ||||||
|   object-fit: cover; |   object-fit: cover; | ||||||
|   object-position: top left; |   object-position: top left; | ||||||
|   height: 200px; |   height: 200px; | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; | |||||||
| import { map } from 'rxjs/operators'; | import { map } from 'rxjs/operators'; | ||||||
| import { PaperlessDocument } from 'src/app/data/paperless-document'; | import { PaperlessDocument } from 'src/app/data/paperless-document'; | ||||||
| import { DocumentService } from 'src/app/services/rest/document.service'; | import { DocumentService } from 'src/app/services/rest/document.service'; | ||||||
|  | import { SettingsService, SETTINGS_KEYS } from 'src/app/services/settings.service'; | ||||||
|  |  | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-document-card-small', |   selector: 'app-document-card-small', | ||||||
| @@ -10,7 +11,7 @@ import { DocumentService } from 'src/app/services/rest/document.service'; | |||||||
| }) | }) | ||||||
| export class DocumentCardSmallComponent implements OnInit { | export class DocumentCardSmallComponent implements OnInit { | ||||||
|  |  | ||||||
|   constructor(private documentService: DocumentService) { } |   constructor(private documentService: DocumentService, private settingsService: SettingsService) { } | ||||||
|  |  | ||||||
|   @Input() |   @Input() | ||||||
|   selected = false |   selected = false | ||||||
| @@ -32,6 +33,10 @@ export class DocumentCardSmallComponent implements OnInit { | |||||||
|   ngOnInit(): void { |   ngOnInit(): void { | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   getIsThumbInverted() { | ||||||
|  |     return this.settingsService.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   getThumbUrl() { |   getThumbUrl() { | ||||||
|     return this.documentService.getThumbUrl(this.document.id) |     return this.documentService.getThumbUrl(this.document.id) | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -96,6 +96,7 @@ | |||||||
|           <div class="col"> |           <div class="col"> | ||||||
|             <app-input-check i18n-title title="Use system settings" formControlName="darkModeUseSystem"></app-input-check> |             <app-input-check i18n-title title="Use system settings" formControlName="darkModeUseSystem"></app-input-check> | ||||||
|             <app-input-check [hidden]="settingsForm.value.darkModeUseSystem" i18n-title title="Enable dark mode" formControlName="darkModeEnabled"></app-input-check> |             <app-input-check [hidden]="settingsForm.value.darkModeUseSystem" i18n-title title="Enable dark mode" formControlName="darkModeEnabled"></app-input-check> | ||||||
|  |             <app-input-check i18n-title title="Invert Thumbnails in dark mode" formControlName="darkModeInvertThumbs"></app-input-check> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ export class SettingsComponent implements OnInit { | |||||||
|     'documentListItemPerPage': new FormControl(this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)), |     'documentListItemPerPage': new FormControl(this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)), | ||||||
|     'darkModeUseSystem': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM)), |     'darkModeUseSystem': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM)), | ||||||
|     'darkModeEnabled': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED)), |     'darkModeEnabled': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_ENABLED)), | ||||||
|  |     'darkModeInvertThumbs': new FormControl(this.settings.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED)), | ||||||
|     'useNativePdfViewer': new FormControl(this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)), |     'useNativePdfViewer': new FormControl(this.settings.get(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER)), | ||||||
|     'savedViews': this.savedViewGroup, |     'savedViews': this.savedViewGroup, | ||||||
|     'displayLanguage': new FormControl(this.settings.getLanguage()), |     'displayLanguage': new FormControl(this.settings.getLanguage()), | ||||||
| @@ -74,6 +75,7 @@ export class SettingsComponent implements OnInit { | |||||||
|     this.settings.set(SETTINGS_KEYS.DOCUMENT_LIST_SIZE, this.settingsForm.value.documentListItemPerPage) |     this.settings.set(SETTINGS_KEYS.DOCUMENT_LIST_SIZE, this.settingsForm.value.documentListItemPerPage) | ||||||
|     this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem) |     this.settings.set(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, this.settingsForm.value.darkModeUseSystem) | ||||||
|     this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString()) |     this.settings.set(SETTINGS_KEYS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString()) | ||||||
|  |     this.settings.set(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, (this.settingsForm.value.darkModeInvertThumbs == true).toString()) | ||||||
|     this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer) |     this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer) | ||||||
|     this.settings.set(SETTINGS_KEYS.DATE_LOCALE, this.settingsForm.value.dateLocale) |     this.settings.set(SETTINGS_KEYS.DATE_LOCALE, this.settingsForm.value.dateLocale) | ||||||
|     this.settings.set(SETTINGS_KEYS.DATE_FORMAT, this.settingsForm.value.dateFormat) |     this.settings.set(SETTINGS_KEYS.DATE_FORMAT, this.settingsForm.value.dateFormat) | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ export const SETTINGS_KEYS = { | |||||||
|   DOCUMENT_LIST_SIZE: 'general-settings:documentListSize', |   DOCUMENT_LIST_SIZE: 'general-settings:documentListSize', | ||||||
|   DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system', |   DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system', | ||||||
|   DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled', |   DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled', | ||||||
|  |   DARK_MODE_THUMB_INVERTED: 'general-settings:dark-mode:thumb-inverted', | ||||||
|   USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer', |   USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer', | ||||||
|   DATE_LOCALE: 'general-settings:date-display:date-locale', |   DATE_LOCALE: 'general-settings:date-display:date-locale', | ||||||
|   DATE_FORMAT: 'general-settings:date-display:date-format', |   DATE_FORMAT: 'general-settings:date-display:date-format', | ||||||
| @@ -36,6 +37,7 @@ const SETTINGS: PaperlessSettings[] = [ | |||||||
|   {key: SETTINGS_KEYS.DOCUMENT_LIST_SIZE, type: "number", default: 50}, |   {key: SETTINGS_KEYS.DOCUMENT_LIST_SIZE, type: "number", default: 50}, | ||||||
|   {key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true}, |   {key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true}, | ||||||
|   {key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false}, |   {key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false}, | ||||||
|  |   {key: SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED, type: "boolean", default: false}, | ||||||
|   {key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false}, |   {key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false}, | ||||||
|   {key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""}, |   {key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""}, | ||||||
|   {key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"}, |   {key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"}, | ||||||
|   | |||||||
| @@ -138,6 +138,16 @@ $border-color-dark-mode: #47494f; | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   .doc-img { |   .doc-img { | ||||||
|  |     mix-blend-mode: normal; | ||||||
|  |     border-radius: 0; | ||||||
|  |     border-color: $bg-dark-mode; | ||||||
|  |  | ||||||
|  |     &.border-right { | ||||||
|  |       border-right: none !important; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .doc-img-inverted { | ||||||
|     mix-blend-mode: normal; |     mix-blend-mode: normal; | ||||||
|     filter: invert(95%) hue-rotate(180deg); |     filter: invert(95%) hue-rotate(180deg); | ||||||
|     border-radius: 0; |     border-radius: 0; | ||||||
| @@ -148,7 +158,7 @@ $border-color-dark-mode: #47494f; | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .card-selected .doc-img { |   .card-selected .doc-img .doc-img-inverted { | ||||||
|     mix-blend-mode: luminosity; |     mix-blend-mode: luminosity; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Bolko Schreiber
					Bolko Schreiber