Fixed search inputs not working in Firefox/Safari. Added Stashes and Alerts to header menu. Indexing compilation tags as assigned tags in Manticore.

This commit is contained in:
2026-07-06 01:36:30 +02:00
parent 6f8d3b1ad2
commit ee1e347405
10 changed files with 143 additions and 20 deletions

View File

@@ -310,3 +310,23 @@
box-shadow: 0 0 3px var(--shadow-weak-10);
}
}
.search-cancel {
width: 2rem;
height: 2rem;
padding: .5rem;
.icon {
width: 1rem;
height: 1rem;
fill: var(--glass);
}
&:hover {
cursor: pointer;
.icon {
fill: var(--error);
}
}
}

View File

@@ -5,12 +5,19 @@
<!-- onsearch not compatible with FF and Safari -->
<input
v-model="q"
type="search"
type="input"
placeholder="Search actors"
class="input search"
@search="search"
@keydown.enter="search"
>
<Icon
v-if="q"
icon="cross2"
class="search-button"
@click="q = ''; search()"
/>
<Icon
icon="search"
class="search-button"

View File

@@ -187,6 +187,26 @@
</a>
</li>
<li class="menu-item">
<a
:href="`/user/${user.username}/stashes`"
class="menu-button nolink stashes"
>
<Icon icon="folder-heart" />
Stashes
</a>
</li>
<li class="menu-item">
<a
:href="`/user/${user.username}/alerts`"
class="menu-button nolink alerts"
>
<Icon icon="alarm" />
Alerts
</a>
</li>
<li
v-close-popper
class="menu-item menu-button"

View File

@@ -4,14 +4,28 @@
v-if="showFilters"
:class="{ loading }"
>
<div class="filter">
<div class="filter search-container">
<!-- onsearch not compatible with FF and Safari -->
<input
v-model="filters.search"
type="search"
type="input"
placeholder="Search movies"
class="search input"
@search="search"
@keydown.enter="search"
>
<Icon
v-if="filters.search"
icon="cross2"
class="search-button"
@click="filters.search = ''; search()"
/>
<Icon
icon="search"
class="search-button"
@click="search"
/>
</div>
<YearsFilter

View File

@@ -12,12 +12,19 @@
<!-- onsearch not compatible with FF and Safari -->
<input
v-model="filters.search"
type="search"
type="input"
placeholder="Search scenes"
class="search input"
@search="search"
@keydown.enter="search"
>
<Icon
v-if="filters.search"
icon="cross2"
class="search-button"
@click="filters.search = ''; search()"
/>
<Icon
icon="search"
class="search-button"

View File

@@ -1,13 +1,26 @@
<template>
<Admin class="page">
<div class="header">
<input
v-model="actorQuery"
type="search"
placeholder="Search actors"
class="input search"
@search="searchActors"
<form
class="search"
@submit.prevent="searchActors"
>
<input
v-model="actorQuery"
type="input"
placeholder="Search actors"
class="input search-input"
>
<button
v-if="actorQuery?.length"
type="button"
class="search-cancel nobutton"
@click="actorQuery = ''; searchActors()"
>
<Icon icon="cross2" />
</button>
</form>
<div class="header-actions">
<button
@@ -208,10 +221,16 @@ onMounted(() => {
<style scoped>
.search {
display: flex;
align-items: center;
max-width: 20rem;
flex-grow: 1;
}
.search-input {
flex-grow: 1;
}
.header {
display: flex;
gap: 1rem;

View File

@@ -6,16 +6,23 @@
>
<input
v-model="query"
type="search"
type="input"
placeholder="Search channels"
class="search input"
@search="search"
@keydown.enter="search"
>
<Icon
icon="search"
@click="search"
/>
<Icon
v-if="query"
icon="cross2"
class="search-button"
@click="query = ''; search()"
/>
</form>
<div

View File

@@ -35,19 +35,27 @@
class="search-container"
@submit.prevent="search"
>
<!-- onsearch not compatible with FF and Safari -->
<input
ref="searchInput"
v-model="query"
type="search"
type="input"
placeholder="Search tags"
class="search input"
@search="search"
@keydown.enter="search"
>
<Icon
icon="search"
@click="search"
/>
<Icon
v-if="query"
icon="cross2"
class="search-button"
@click="query = ''; search()"
/>
</form>
<div

View File

@@ -717,6 +717,12 @@ export async function mergeActors(targetActorId, sourceActorIds, reqUser) {
.whereIn('actor_id', sourceActorIds)
.returning('stash_id');
/* TODO: add revision entries
console.log('SOURCES', targetActor, sourceActors);
throw new Error('ABORT');
*/
await trx.commit();
} catch (error) {
await trx.rollback();

View File

@@ -187,13 +187,28 @@ export async function syncManticoreScenes(sceneIds) {
const flatTags = scene.tags.filter((tag) => tag.f3 > 6).flatMap((tag) => [tag.f2].concat(tag.f4)).filter(Boolean); // only make top tags searchable to minimize cluttered results
const filteredTitle = filterTitle(scene.title, [...flatActors, ...flatTags]);
const isCompilation = scene.tags.some((tag) => tag.f2 === 'compilation');
// use decimal packing with 5-decimal pad to allow for actor-specific tags, i.e. actor 135 tag 5 = 13500005
// all global tags are necessarily < 10,000, all tags for actor 135 are >= 13500000 and <= 13599999
// f1 = tag ID, f5 = actor ID
const assignedTagIds = scene.tags.map((tag) => (tag.f5 === null ? tag.f1 : tag.f5 * 1_000_00 + tag.f1));
const assignedTagIds = scene.tags.map((tag) => {
if (tag.f5) {
// tag is assigned to actor, pack tag ID with actor ID
return tag.f5 * 1_000_00 + tag.f1;
}
/*
if (sceneId === '187734') {
if (isCompilation && tag.f2 !== 'compilation') {
// tag is part of a compilation, pack with arbitrary large number that will never be an actor ID (famous last words)
return 900_000_000 * 1_000_00 + tag.f1;
}
// plain tag ID
return tag.f1;
});
/* abort to inspect
if (sceneId === '554480') {
console.log(scene, assignedTagIds);
throw new Error('ABORT');
}