fix(webui): duplicate page matches were not showing exact matches only

This commit is contained in:
Gauthier Roebroeck 2022-01-27 10:13:07 +08:00
parent 7a3f80ce92
commit 5844521286
9 changed files with 65 additions and 33 deletions

View file

@ -31,15 +31,15 @@
</template>
<script lang="ts">
import Vue from 'vue'
import Vue, {PropType} from 'vue'
import {bookPageThumbnailUrl} from '@/functions/urls'
import {PageHashMatchDto} from '@/types/komga-pagehashes'
import {PageHashMatchDto, PageHashUnknownDto} from '@/types/komga-pagehashes'
export default Vue.extend({
name: 'PageHashMatchesTable',
props: {
hash: {
type: String,
type: Object as PropType<PageHashUnknownDto>,
},
},
data() {
@ -73,7 +73,7 @@ export default Vue.extend({
},
},
methods: {
async loadData(hash: string) {
async loadData(hash: PageHashUnknownDto) {
this.loading = true
const {sortBy, sortDesc, page, itemsPerPage} = this.options

View file

@ -1,3 +1,5 @@
import {PageHashUnknownDto} from '@/types/komga-pagehashes'
const fullUrl = process.env.VUE_APP_KOMGA_API_URL
? process.env.VUE_APP_KOMGA_API_URL
: window.location.origin + window.resourceBaseUrl
@ -72,10 +74,10 @@ export function transientBookPageUrl(transientBookId: string, page: number): str
return `${urls.originNoSlash}/api/v1/transient-books/${transientBookId}/pages/${page}`
}
export function pageHashUnknownThumbnailUrl(hash: string, resize?: number): string {
let url = `${urls.originNoSlash}/api/v1/page-hashes/unknown/${hash}/thumbnail`
export function pageHashUnknownThumbnailUrl(pageHash: PageHashUnknownDto, resize?: number): string {
let url = `${urls.originNoSlash}/api/v1/page-hashes/unknown/${pageHash.hash}/thumbnail?media_type=${pageHash.mediaType}&size=${pageHash.sizeBytes || -1}`
if(resize) {
url += `?resize=${resize}`
url += `&resize=${resize}`
}
return url
}

View file

@ -27,10 +27,15 @@ export default class KomgaPageHashesService {
}
}
async getUnknownPageHashMatches(hash: string, pageRequest?: PageRequest): Promise<Page<PageHashMatchDto>> {
async getUnknownPageHashMatches(hash: PageHashUnknownDto, pageRequest?: PageRequest): Promise<Page<PageHashMatchDto>> {
try {
return (await this.http.get(`${API_PAGE_HASH}/unknown/${hash}`, {
params: pageRequest,
const params = {
...pageRequest,
media_type: hash.mediaType,
size: hash.sizeBytes || -1,
}
return (await this.http.get(`${API_PAGE_HASH}/unknown/${hash.hash}`, {
params: params,
paramsSerializer: params => qs.stringify(params, {indices: false}),
})).data
} catch (e) {

View file

@ -21,8 +21,8 @@
width="200"
height="300"
contain
@click="showDialogImage(element.hash)"
:src="pageHashUnknownThumbnailUrl(element.hash, 500)"
@click="showDialogImage(element)"
:src="pageHashUnknownThumbnailUrl(element, 500)"
style="cursor: zoom-in"
/>
@ -32,7 +32,7 @@
<div>{{ element.mediaType }}</div>
<div>{{ element.size || $t('duplicate_pages.unknown_size') }}</div>
<v-btn
@click="showDialogMatches(element.hash)"
@click="showDialogMatches(element)"
outlined
rounded
class="mt-2"
@ -59,7 +59,7 @@
<v-img
@click="dialogImage = false"
contain
:src="pageHashUnknownThumbnailUrl(dialogImageHash)"
:src="pageHashUnknownThumbnailUrl(dialogImagePageHash)"
style="cursor: zoom-out;"
/>
</v-card-text>
@ -73,7 +73,7 @@
<v-card>
<v-card-text>
<page-hash-matches-table
:hash="dialogMatchesHash"
:hash="dialogMatchesPageHash"
class="my-2"
/>
</v-card-text>
@ -102,8 +102,8 @@ export default Vue.extend({
totalPages: 1,
dialogImage: false,
dialogMatches: false,
dialogImageHash: '',
dialogMatchesHash: '',
dialogImagePageHash: {} as PageHashUnknownDto,
dialogMatchesPageHash: {} as PageHashUnknownDto,
pageHashUnknownThumbnailUrl,
}
},
@ -142,12 +142,12 @@ export default Vue.extend({
this.totalPages = itemsPage.totalPages
this.elements = itemsPage.content
},
showDialogImage(hash: string) {
this.dialogImageHash = hash
showDialogImage(pageHash: PageHashUnknownDto) {
this.dialogImagePageHash = pageHash
this.dialogImage = true
},
showDialogMatches(hash: string) {
this.dialogMatchesHash = hash
showDialogMatches(pageHash: PageHashUnknownDto) {
this.dialogMatchesPageHash = pageHash
this.dialogMatches = true
},
},

View file

@ -4,5 +4,5 @@ data class PageHashUnknown(
val hash: String,
val mediaType: String,
val size: Long? = null,
val matchCount: Int,
val matchCount: Int = 0,
)

View file

@ -10,7 +10,7 @@ interface PageHashRepository {
fun findAllKnown(actions: List<PageHash.Action>?, pageable: Pageable): Page<PageHash>
fun findAllUnknown(pageable: Pageable): Page<PageHashUnknown>
fun findMatchesByHash(hash: String, pageable: Pageable): Page<PageHashMatch>
fun findMatchesByHash(pageHash: PageHashUnknown, pageable: Pageable): Page<PageHashMatch>
fun getKnownThumbnail(hash: String): ByteArray?
}

View file

@ -1,6 +1,7 @@
package org.gotson.komga.domain.service
import org.gotson.komga.domain.model.BookPageContent
import org.gotson.komga.domain.model.PageHashUnknown
import org.gotson.komga.domain.persistence.BookRepository
import org.gotson.komga.domain.persistence.PageHashRepository
import org.springframework.data.domain.Pageable
@ -13,7 +14,7 @@ class PageHashLifecycle(
private val bookRepository: BookRepository,
) {
fun getPage(hash: String, resizeTo: Int? = null): BookPageContent? {
fun getPage(hash: PageHashUnknown, resizeTo: Int? = null): BookPageContent? {
val match = pageHashRepository.findMatchesByHash(hash, Pageable.ofSize(1)).firstOrNull() ?: return null
val book = bookRepository.findByIdOrNull(match.bookId) ?: return null

View file

@ -68,11 +68,16 @@ class PageHashDao(
)
}
override fun findMatchesByHash(hash: String, pageable: Pageable): Page<PageHashMatch> {
override fun findMatchesByHash(pageHash: PageHashUnknown, pageable: Pageable): Page<PageHashMatch> {
val query = dsl.select(p.BOOK_ID, b.URL, p.NUMBER)
.from(p)
.leftJoin(b).on(p.BOOK_ID.eq(b.ID))
.where(p.FILE_HASH.eq(hash))
.where(p.FILE_HASH.eq(pageHash.hash))
.and(p.MEDIA_TYPE.eq(pageHash.mediaType))
.apply {
if (pageHash.size == null) and(p.FILE_SIZE.isNull)
else and(p.FILE_SIZE.eq(pageHash.size))
}
val count = dsl.fetchCount(query)

View file

@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
import org.gotson.komga.domain.model.PageHash
import org.gotson.komga.domain.model.PageHashUnknown
import org.gotson.komga.domain.model.ROLE_ADMIN
import org.gotson.komga.domain.persistence.PageHashRepository
import org.gotson.komga.domain.service.PageHashLifecycle
@ -45,7 +46,7 @@ class PageHashController(
): Page<PageHashDto> =
pageHashRepository.findAllKnown(actions, page).map { it.toDto() }
@GetMapping("/{hash}/thumbnail", produces = [MediaType.IMAGE_JPEG_VALUE],)
@GetMapping("/{hash}/thumbnail", produces = [MediaType.IMAGE_JPEG_VALUE])
@ApiResponse(content = [Content(schema = Schema(type = "string", format = "binary"))])
fun getPageHashThumbnail(@PathVariable hash: String): ByteArray =
pageHashRepository.getKnownThumbnail(hash) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
@ -57,21 +58,39 @@ class PageHashController(
): Page<PageHashUnknownDto> =
pageHashRepository.findAllUnknown(page).map { it.toDto() }
@GetMapping("unknown/{hash}")
@GetMapping("unknown/{pageHash}")
@PageableAsQueryParam
fun getUnknownPageHashMatches(
@PathVariable hash: String,
@PathVariable pageHash: String,
@RequestParam("media_type") mediaType: String,
@RequestParam("size") size: Long,
@Parameter(hidden = true) page: Pageable,
): Page<PageHashMatchDto> =
pageHashRepository.findMatchesByHash(hash, page).map { it.toDto() }
pageHashRepository.findMatchesByHash(
PageHashUnknown(
hash = pageHash,
mediaType = mediaType,
size = if (size < 0) null else size,
),
page,
).map { it.toDto() }
@GetMapping("unknown/{hash}/thumbnail", produces = [MediaType.IMAGE_JPEG_VALUE],)
@GetMapping("unknown/{pageHash}/thumbnail", produces = [MediaType.IMAGE_JPEG_VALUE])
@ApiResponse(content = [Content(schema = Schema(type = "string", format = "binary"))])
fun getUnknownPageHashThumbnail(
@PathVariable hash: String,
@PathVariable pageHash: String,
@RequestParam("media_type") mediaType: String,
@RequestParam("size") size: Long,
@RequestParam("resize") resize: Int? = null,
): ResponseEntity<ByteArray> =
pageHashLifecycle.getPage(hash, resize)?.let {
pageHashLifecycle.getPage(
PageHashUnknown(
hash = pageHash,
mediaType = mediaType,
size = if (size < 0) null else size,
),
resize,
)?.let {
ResponseEntity.ok()
.contentType(getMediaTypeOrDefault(it.mediaType))
.body(it.content)