update
This commit is contained in:
@@ -122,7 +122,14 @@ def ziehen():
|
||||
if not eintraege:
|
||||
return None
|
||||
|
||||
treffer = random.randrange(len(eintraege))
|
||||
# Schon gelaufene Filme überspringen. Sind alle Vorschläge gesehen,
|
||||
# bleibt es bei der vollen Auswahl — sonst gäbe es keinen Gewinner.
|
||||
with connect() as conn:
|
||||
gesehen = {
|
||||
r["movie_id"] for r in conn.execute("SELECT movie_id FROM watched")
|
||||
}
|
||||
frisch = [i for i, e in enumerate(eintraege) if e["movie_id"] not in gesehen]
|
||||
treffer = random.choice(frisch) if frisch else random.randrange(len(eintraege))
|
||||
schritt = 360 / len(eintraege)
|
||||
runden = 5 + random.randrange(3)
|
||||
# Der Zeiger steht oben, also muss die Mitte des Zielsegments dorthin
|
||||
|
||||
@@ -331,6 +331,11 @@ async function ladeGesehen() {
|
||||
}
|
||||
}
|
||||
|
||||
// Für die Karten: nur die Kennungen, als Menge zum schnellen Nachschlagen
|
||||
const gesehenIds = computed(
|
||||
() => new Set(gesehen.value.map((e) => e.movie_id))
|
||||
)
|
||||
|
||||
// Ausgeblendete Filme zählen für Gäste nicht mit
|
||||
const gesehenZahl = computed(
|
||||
() => gesehen.value.filter((e) => host.value || !e.hidden).length
|
||||
@@ -659,12 +664,14 @@ onUnmounted(() => {
|
||||
<div v-if="activeTab === 'search' || activeTab === 'aehnlich'" class="layout">
|
||||
<SearchTab
|
||||
v-if="activeTab === 'search'"
|
||||
:gesehen-ids="gesehenIds"
|
||||
:filter="suchFilter"
|
||||
:ansicht="ansicht"
|
||||
@open="selected = $event"
|
||||
/>
|
||||
|
||||
<AehnlichTab
|
||||
:gesehen-ids="gesehenIds"
|
||||
v-else
|
||||
:filter="suchFilter"
|
||||
:ansicht="ansicht"
|
||||
@@ -696,6 +703,7 @@ onUnmounted(() => {
|
||||
:host="host"
|
||||
:merkliste="merkliste"
|
||||
:mine="meinVorschlag?.id ?? null"
|
||||
:gesehen-ids="gesehenIds"
|
||||
@open="selected = $event"
|
||||
@reset="meinVorschlag = null"
|
||||
/>
|
||||
@@ -709,6 +717,7 @@ onUnmounted(() => {
|
||||
|
||||
<MerklisteTab
|
||||
v-else-if="activeTab === 'merkliste'"
|
||||
:gesehen-ids="gesehenIds"
|
||||
:items="merkliste"
|
||||
:ich="ich"
|
||||
@open="selected = $event"
|
||||
@@ -743,6 +752,7 @@ onUnmounted(() => {
|
||||
<MovieCard
|
||||
v-if="entry.parts.length === 1"
|
||||
:movie="entry.parts[0]"
|
||||
:gesehen="gesehenIds.has(entry.parts[0].id)"
|
||||
:auf-dem-rad="aufDemRad.includes(entry.parts[0].id)"
|
||||
:ansicht="ansicht"
|
||||
@open="filmOeffnen"
|
||||
@@ -750,6 +760,7 @@ onUnmounted(() => {
|
||||
<SeriesCard
|
||||
v-else
|
||||
:parts="entry.parts"
|
||||
:gesehen-ids="gesehenIds"
|
||||
:start="entry.best"
|
||||
:auf-dem-rad="aufDemRad"
|
||||
:ansicht="ansicht"
|
||||
|
||||
@@ -13,6 +13,7 @@ const VORSCHLAEGE = { kompakt: 20, details: 8 }
|
||||
const props = defineProps({
|
||||
filter: { type: Object, default: () => ({}) },
|
||||
ansicht: { type: String, default: 'kompakt' },
|
||||
gesehenIds: { type: Set, default: () => new Set() },
|
||||
// Kommt aus der Filmansicht: von diesem Film soll es losgehen
|
||||
start: { type: Object, default: null },
|
||||
})
|
||||
@@ -177,6 +178,7 @@ async function oeffnen(movie) {
|
||||
:key="film.id"
|
||||
:movie="film"
|
||||
:ansicht="ansicht"
|
||||
:gesehen="gesehenIds.has(film.id)"
|
||||
@open="waehlen"
|
||||
/>
|
||||
</div>
|
||||
@@ -203,6 +205,7 @@ async function oeffnen(movie) {
|
||||
:key="film.id"
|
||||
:movie="film"
|
||||
:ansicht="ansicht"
|
||||
:gesehen="gesehenIds.has(film.id)"
|
||||
@open="oeffnen"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { posterUrl } from '../images'
|
||||
const props = defineProps({
|
||||
items: { type: Array, default: () => [] },
|
||||
ich: { type: Object, default: null },
|
||||
gesehenIds: { type: Set, default: () => new Set() },
|
||||
})
|
||||
|
||||
// Nach Person gruppiert, die eigene Sammlung zuerst
|
||||
@@ -87,7 +88,12 @@ async function oeffnen(item) {
|
||||
</h3>
|
||||
|
||||
<div class="grid">
|
||||
<article v-for="item in gefiltert(gruppe)" :key="item.id" class="karte">
|
||||
<article
|
||||
v-for="item in gefiltert(gruppe)"
|
||||
:key="item.id"
|
||||
class="karte"
|
||||
:class="{ gesehen: gesehenIds.has(item.movie_id) }"
|
||||
>
|
||||
<button type="button" class="cover" @click="oeffnen(item)">
|
||||
<img
|
||||
v-if="posterUrl(item.poster_path, 'w342')"
|
||||
@@ -126,6 +132,15 @@ async function oeffnen(item) {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
/* Schon gelaufen — die Karte tritt zurück, kommt beim Überfahren wieder */
|
||||
.karte.gesehen {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.karte.gesehen:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.karte {
|
||||
display: flex;
|
||||
gap: 0.9rem;
|
||||
|
||||
@@ -5,6 +5,8 @@ import { backdropUrl, posterUrl } from '../images'
|
||||
const props = defineProps({
|
||||
movie: { type: Object, required: true },
|
||||
aufDemRad: { type: Boolean, default: false },
|
||||
// Schon gelaufen — die Karte tritt dann zurück
|
||||
gesehen: { type: Boolean, default: false },
|
||||
ansicht: { type: String, default: 'kompakt' },
|
||||
})
|
||||
|
||||
@@ -30,7 +32,7 @@ const meta = computed(() =>
|
||||
<template>
|
||||
<button
|
||||
class="card"
|
||||
:class="[ansicht, { 'auf-dem-rad': aufDemRad }]"
|
||||
:class="[ansicht, { 'auf-dem-rad': aufDemRad, gesehen }]"
|
||||
type="button"
|
||||
@click="$emit('open', movie)"
|
||||
>
|
||||
@@ -69,6 +71,16 @@ const meta = computed(() =>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Schon gelaufen — die Karte tritt zurück, bleibt aber lesbar.
|
||||
Beim Überfahren kommt sie zurück. */
|
||||
.card.gesehen {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.card.gesehen:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Details: breite Karte, Poster links, alles lesbar statt abgeschnitten */
|
||||
.haupt {
|
||||
display: flex;
|
||||
|
||||
@@ -7,6 +7,7 @@ const props = defineProps({
|
||||
// Was die Filterleiste eingestellt hat
|
||||
filter: { type: Object, default: () => ({}) },
|
||||
ansicht: { type: String, default: 'kompakt' },
|
||||
gesehenIds: { type: Set, default: () => new Set() },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['open'])
|
||||
@@ -122,6 +123,7 @@ async function open(movie) {
|
||||
:key="movie.id"
|
||||
:movie="movie"
|
||||
:ansicht="ansicht"
|
||||
:gesehen="gesehenIds.has(movie.id)"
|
||||
@open="open"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,8 @@ const props = defineProps({
|
||||
// Die Karte öffnet mit dem stärksten Teil, nicht mit dem ersten
|
||||
start: { type: Number, default: 0 },
|
||||
aufDemRad: { type: Array, default: () => [] },
|
||||
// Kennungen der schon gelaufenen Filme
|
||||
gesehenIds: { type: Set, default: () => new Set() },
|
||||
ansicht: { type: String, default: 'kompakt' },
|
||||
})
|
||||
|
||||
@@ -21,6 +23,8 @@ const rating = computed(() =>
|
||||
|
||||
const stehtAufDemRad = computed(() => props.aufDemRad.includes(current.value.id))
|
||||
|
||||
const schonGesehen = computed(() => props.gesehenIds.has(current.value.id))
|
||||
|
||||
const shots = computed(() =>
|
||||
(current.value.images || []).slice(0, 4).map((pfad) => backdropUrl(pfad, 'w300'))
|
||||
)
|
||||
@@ -38,7 +42,7 @@ function step(delta) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="card" :class="[ansicht, { 'auf-dem-rad': stehtAufDemRad }]">
|
||||
<article class="card" :class="[ansicht, { 'auf-dem-rad': stehtAufDemRad, gesehen: schonGesehen }]">
|
||||
<span v-if="stehtAufDemRad" class="rad-marke" title="Steht auf dem Rad">Rad</span>
|
||||
<div class="haupt">
|
||||
<button class="poster" type="button" @click="$emit('open', current)">
|
||||
@@ -91,6 +95,16 @@ function step(delta) {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Schon gelaufen — die Karte tritt zurück, bleibt aber lesbar.
|
||||
Beim Überfahren kommt sie zurück. */
|
||||
.card.gesehen {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.card.gesehen:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
@@ -8,6 +8,7 @@ const props = defineProps({
|
||||
// Beides hält die App schon aktuell — auch nach einem Namenswechsel
|
||||
merkliste: { type: Array, default: () => [] },
|
||||
mine: { type: Number, default: null },
|
||||
gesehenIds: { type: Set, default: () => new Set() },
|
||||
})
|
||||
const emit = defineEmits(['open', 'reset'])
|
||||
|
||||
@@ -319,7 +320,7 @@ async function oeffnen(item) {
|
||||
<button
|
||||
type="button"
|
||||
class="eintrag"
|
||||
:class="{ eigen: item.id === mine }"
|
||||
:class="{ eigen: item.id === mine, gesehen: gesehenIds.has(item.movie_id) }"
|
||||
@click="oeffnen(item)"
|
||||
>
|
||||
<span
|
||||
@@ -563,6 +564,15 @@ async function oeffnen(item) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* Schon gelaufen — die Ziehung überspringt diesen Film */
|
||||
.eintrag.gesehen {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.eintrag.gesehen:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.eintrag:hover {
|
||||
background: var(--bg-soft);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user