mirror of
https://github.com/gotson/komga.git
synced 2025-12-19 23:12:47 +01:00
fix(webui): duplicate page matches were not showing exact matches only
This commit is contained in:
parent
7a3f80ce92
commit
5844521286
9 changed files with 65 additions and 33 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ data class PageHashUnknown(
|
|||
val hash: String,
|
||||
val mediaType: String,
|
||||
val size: Long? = null,
|
||||
val matchCount: Int,
|
||||
val matchCount: Int = 0,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue