mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-20 04:42:04 +00:00
feat: support for pasting images, w2g lobby links
fix: banner image darken not working fix: make banner take up less space
This commit is contained in:
parent
d89b007c9e
commit
16c57f1fb6
7 changed files with 69 additions and 56 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ui",
|
||||
"version": "6.4.5",
|
||||
"version": "6.4.6",
|
||||
"license": "BUSL-1.1",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.14.4",
|
||||
|
|
|
|||
1
src/app.d.ts
vendored
1
src/app.d.ts
vendored
|
|
@ -182,6 +182,7 @@ declare global {
|
|||
|
||||
interface PageState {
|
||||
search?: VariablesOf<typeof Search>
|
||||
image?: File | string
|
||||
}
|
||||
// interface Platform {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,6 @@
|
|||
left: 0 ; top: 0;
|
||||
width: 100%; height: 23rem;
|
||||
z-index: 0;
|
||||
border-image: fill 0 linear-gradient(rgba(0, 0, 0, .4));
|
||||
background: rgba(0, 0, 0, .4);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
if (get(query.isPaused$)) query.resume()
|
||||
</script>
|
||||
|
||||
<div class='w-full h-[450px] relative'>
|
||||
<div class='w-full h-[400px] relative'>
|
||||
<!-- really shit and hacky way of fixing scroll position jumping when banner changes height -->
|
||||
<div class='absolute top-0 transparent h-full opacity-0'>.</div>
|
||||
{#if $query.fetching}
|
||||
|
|
|
|||
|
|
@ -223,45 +223,23 @@ export interface TraceAnime {
|
|||
image: string
|
||||
}
|
||||
|
||||
export async function traceAnime (image: File) { // WAIT lookup logic
|
||||
const options = {
|
||||
method: 'POST',
|
||||
body: image,
|
||||
headers: { 'Content-type': image.type }
|
||||
export async function traceAnime (image: File | string) { // WAIT lookup logic
|
||||
let res: Response
|
||||
if (image instanceof File) {
|
||||
res = await fetch('https://api.trace.moe/search?cutBorders', {
|
||||
method: 'POST',
|
||||
body: image,
|
||||
headers: { 'Content-type': image.type }
|
||||
})
|
||||
} else {
|
||||
res = await fetch(`https://api.trace.moe/search?cutBorders&url=${image}`)
|
||||
}
|
||||
const url = 'https://api.trace.moe/search'
|
||||
// let url = `https://api.trace.moe/search?cutBorders&url=${image}`
|
||||
|
||||
const res = await fetch(url, options)
|
||||
const { result } = await res.json() as { result: TraceAnime[] }
|
||||
|
||||
if (result.length) {
|
||||
return result
|
||||
// search.value = {
|
||||
// clearNext: true,
|
||||
// load: (page = 1, perPage = 50, variables = {}) => {
|
||||
// const res = anilistClient.searchIDS({ page, perPage, id: ids, ...SectionsManager.sanitiseObject(variables) }).then(res => {
|
||||
// for (const index in res.data?.Page?.media) {
|
||||
// const media = res.data.Page.media[index]
|
||||
// const counterpart = result.find(({ anilist }) => anilist === media.id)
|
||||
// res.data.Page.media[index] = {
|
||||
// media,
|
||||
// episode: counterpart.episode,
|
||||
// similarity: counterpart.similarity,
|
||||
// episodeData: {
|
||||
// image: counterpart.image,
|
||||
// video: counterpart.video
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// res.data?.Page?.media.sort((a, b) => b.similarity - a.similarity)
|
||||
// return res
|
||||
// })
|
||||
// return SectionsManager.wrapResponse(res, result.length, 'episode')
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
throw new Error('Search Failed \n Couldn\'t find anime for specified image! Try to remove black bars, or use a more detailed image.')
|
||||
throw new Error('Search Failed\nCouldn\'t find anime for specified image! Try to remove black bars, or use a more detailed image.')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,37 @@
|
|||
const targetValue = NAVIGATE_TARGETS[target as keyof typeof NAVIGATE_TARGETS]
|
||||
goto(`/app/${targetValue}/${value ?? ''}`)
|
||||
})
|
||||
|
||||
const imageRx = /\.(jpeg|jpg|gif|png|webp)/i
|
||||
|
||||
const w2gRx = /hayase(?:(?:\.watch)|(?::\/))\/w2g\/(.+)/
|
||||
|
||||
async function handleTransfer (e: { dataTransfer?: DataTransfer | null, clipboardData?: DataTransfer | null } & Event) {
|
||||
e.preventDefault()
|
||||
const promises = [...(e.dataTransfer ?? e.clipboardData)!.items].map(item => {
|
||||
const type = item.type
|
||||
return new Promise<File | { text: string, type: string }>(resolve => item.kind === 'string' ? item.getAsString(text => resolve({ text, type })) : resolve(item.getAsFile()!))
|
||||
})
|
||||
|
||||
for (const file of await Promise.all(promises)) {
|
||||
if (file instanceof Blob) {
|
||||
if (file.type.startsWith('image') || imageRx.test(file.name)) {
|
||||
goto('/app/search', { state: { image: file } })
|
||||
}
|
||||
} else if (file.type === 'text/plain') {
|
||||
if (imageRx.test(file.text)) {
|
||||
goto('/app/search', { state: { image: file.text } })
|
||||
} else if (w2gRx.test(file.text)) {
|
||||
const match = file.text.match(w2gRx)
|
||||
if (match?.[1])goto('/app/w2g/' + match[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:dragover|preventDefault on:drop={handleTransfer} on:paste={handleTransfer} />
|
||||
|
||||
<BannerImage class='absolute top-0 left-0 -z-[1]' />
|
||||
<SearchModal />
|
||||
<div class='flex flex-row grow h-full overflow-clip group/fullscreen min-h-0' id='episodeListTarget'>
|
||||
|
|
|
|||
|
|
@ -168,30 +168,35 @@
|
|||
|
||||
let trace: TraceAnime[] | undefined
|
||||
|
||||
async function traceReq (file: File | string) {
|
||||
const promise = traceAnime(file)
|
||||
toast.promise(promise, {
|
||||
description: 'You can also paste an URL to an image.',
|
||||
loading: 'Looking up anime for image...',
|
||||
success: 'Found anime for image!',
|
||||
error: 'Couldn\'t find anime for specified image! Try to remove black bars, or use a more detailed image.'
|
||||
})
|
||||
|
||||
try {
|
||||
const res = await promise
|
||||
|
||||
clear()
|
||||
|
||||
trace = res
|
||||
search.ids = [...new Set(res.map(r => r.anilist))]
|
||||
// TODO: sort by similarity, finish
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
if ($page.state.image) traceReq($page.state.image)
|
||||
|
||||
async function imagePicker (e: Event) {
|
||||
const target = e.target as HTMLInputElement
|
||||
const { files } = target
|
||||
if (files?.[0]) {
|
||||
const promise = traceAnime(files[0])
|
||||
toast.promise(promise, {
|
||||
description: 'You can also paste an URL to an image.',
|
||||
loading: 'Looking up anime for image...',
|
||||
success: 'Found anime for image!',
|
||||
error: 'Couldn\'t find anime for specified image! Try to remove black bars, or use a more detailed image.'
|
||||
})
|
||||
target.value = ''
|
||||
|
||||
try {
|
||||
const res = await promise
|
||||
|
||||
clear()
|
||||
|
||||
trace = res
|
||||
search.ids = [...new Set(res.map(r => r.anilist))]
|
||||
// TODO: sort by similarity, finish
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
traceReq(files[0])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue