Ein Download sah aus wie eine Videodatei, nicht wie ein Film
Vier Dinge, die beim Ausprobieren auffielen. **Die Plakate blieben grau.** Sie lagen auf der Platte, der Lader wollte sie aber nicht: er verlangte von jeder Antwort eine HTTPURLResponse, und eine Datei antwortet nicht so. Jede lokale Adresse kam als `nil` zurück. **Eine Serie hatte ohnehin nie ein Plakat.** Heruntergeladen wird nie die Serie, nur ihre Folgen — und deren Bild ist das Szenenbild, quer. Jetzt kommt das Serienplakat unter dem Serienschlüssel mit und geht mit der letzten Folge wieder. **Zwanzig Folgen waren zwanzig Kacheln.** Jetzt steht die Serie einmal da, darunter wie viele Folgen bereitliegen; welche genau, zeigt ihre Seite — auch ohne Server, dann aus dem, was auf dem Gerät liegt. **Das Bild wurde schwarz, sobald jemand auf „Bildfüllend" wechselte.** Daran war ein eigener ViewModifier schuld, der zwischen `ignoresSafeArea()` und gar nichts umschaltete. Genau das ist in SwiftUI ein Zweig: der Baum darunter wurde neu gebaut, die Bildebene mit ihm. `edges: []` ignoriert nichts und bleibt doch derselbe Modifikator. Dazu „Als Nächstes": die Reihe begann am Anfang der Serie statt dort, wo der Benutzer steht. Wer bei Folge 2 war und Folge 1 nie abgehakt hatte, bekam Folge 1 vorgeschlagen — und das Abhaken half nicht, weil die Kachel sich nur selbst einen Haken malte, statt zu verschwinden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8f0568cb6c
commit
79d7d04583
@@ -395,9 +395,16 @@ public final class DownloadCoordinator {
|
||||
forgetTransfer(item.ratingKey)
|
||||
fileStore.remove(fileName: item.localFileName)
|
||||
fileStore.remove(fileName: item.artworkFileName)
|
||||
let serie = item.seriesKey
|
||||
context.delete(item)
|
||||
save()
|
||||
reloadItems()
|
||||
|
||||
// **Das Serienplakat geht mit der letzten Folge.** Es hängt an
|
||||
// keinem Eintrag — ohne diese Zeile bliebe es für immer liegen.
|
||||
if let serie, !items.contains(where: { $0.seriesKey == serie }) {
|
||||
fileStore.remove(fileName: fileStore.artworkFileName(forRatingKey: serie))
|
||||
}
|
||||
refreshUsage()
|
||||
}
|
||||
|
||||
@@ -427,10 +434,15 @@ public final class DownloadCoordinator {
|
||||
/// **Weil eine Reihe ohne Bilder keine Reihe ist.** Ohne Verbindung gibt
|
||||
/// es keine Adresse, von der ein Plakat nachzuladen wäre; was nicht beim
|
||||
/// Herunterladen mitkam, bleibt eine graue Fläche.
|
||||
/// **Nach der Datei gefragt, nicht nach dem Eintrag.** Hier wurde erst
|
||||
/// der Download gesucht und dann sein Dateiname gelesen — damit gab es
|
||||
/// nur Bilder zu Dingen, die selbst heruntergeladen wurden. Das Plakat
|
||||
/// einer **Serie** gehört aber keiner einzelnen Folge; es liegt unter
|
||||
/// dem Serienschlüssel, zu dem es keinen Eintrag gibt und nie geben
|
||||
/// wird.
|
||||
public func artworkURL(forRatingKey key: String) -> URL? {
|
||||
guard let name = items.first(where: { $0.ratingKey == key })?.artworkFileName,
|
||||
fileStore.exists(fileName: name)
|
||||
else { return nil }
|
||||
let name = fileStore.artworkFileName(forRatingKey: key)
|
||||
guard fileStore.exists(fileName: name) else { return nil }
|
||||
return fileStore.url(forFileName: name)
|
||||
}
|
||||
|
||||
@@ -439,19 +451,32 @@ public final class DownloadCoordinator {
|
||||
/// **Beim Anlegen, nicht erst beim Fertigwerden.** Die Liste zeigt den
|
||||
/// Eintrag, sobald er in der Warteschlange steht; bis dahin wäre sonst
|
||||
/// nichts zu sehen. Es sind ein paar Kilobyte.
|
||||
/// Der Schlüssel muss zu keinem Download gehören: unter dem Schlüssel
|
||||
/// einer Serie liegt ihr Plakat, obwohl die Serie selbst nie
|
||||
/// heruntergeladen wird.
|
||||
public func fetchArtwork(for ratingKey: String, from url: URL) async {
|
||||
guard let item = items.first(where: { $0.ratingKey == ratingKey }),
|
||||
item.artworkFileName == nil
|
||||
else { return }
|
||||
let name = fileStore.artworkFileName(forRatingKey: ratingKey)
|
||||
guard !fileStore.exists(fileName: name) else {
|
||||
vermerken(name, bei: ratingKey)
|
||||
return
|
||||
}
|
||||
|
||||
guard let (daten, antwort) = try? await URLSession.shared.data(from: url),
|
||||
(antwort as? HTTPURLResponse).map({ (200..<300).contains($0.statusCode) }) ?? true,
|
||||
!daten.isEmpty
|
||||
else { return }
|
||||
|
||||
let name = fileStore.artworkFileName(forRatingKey: ratingKey)
|
||||
guard fileStore.store(daten, as: name) != nil else { return }
|
||||
vermerken(name, bei: ratingKey)
|
||||
}
|
||||
|
||||
/// Hält am Eintrag fest, dass es ein Bild gibt — damit es beim Entfernen
|
||||
/// mitgeht. Zum Serienschlüssel gibt es keinen Eintrag; dann bleibt die
|
||||
/// Datei stehen, bis die letzte Folge der Serie geht.
|
||||
private func vermerken(_ name: String, bei ratingKey: String) {
|
||||
guard let item = items.first(where: { $0.ratingKey == ratingKey }),
|
||||
item.artworkFileName != name
|
||||
else { return }
|
||||
item.artworkFileName = name
|
||||
save()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user