Erster echter Reader-Use-Case in der App. Login → Feed laden → Lese-Liste filtern → Swipe-Actions zum Archivieren/Löschen. π-1 Feed-Tab: - Sources/Core/Domain/Topic.swift: 7 Topic-Cases mit Label + Emoji, Mirror von mana/packages/shared-rss/src/types.ts#ALL_TOPICS. Test enforced Sync zur Wire-Format-SOT. - Sources/Core/Domain/Article.swift: Article + FeedItem + ArticleStatus Codable-DTOs, ISO-strings für Datetimes (kein Custom-Decoder-Setup). - Sources/Core/API/PagetaAPI.swift: final class : Sendable wrap um AuthenticatedTransport (ManaCore). Pattern wie HerbatriumAPI — Views instanziieren per-View mit injiziertem AuthClient. Endpoints: fetchFeed, fetchArticles(status:), updateArticle, deleteArticle. - FeedTabView: List + FeedItemRow (Cover, Topic-Chip, Title, Excerpt), Pull-to-Refresh, empty/loading/error-State. π-2 Lese-Liste-Tab: - Status-Picker (SegmentedControl: unread/reading/finished/archived) re-loaded automatisch on selection-change via .task(id: status). - ArticleRow: Cover, SiteName, Reading-Time, Title, Excerpt, Favorit-Star. - Swipe-Actions: Löschen (destructive) + Archivieren (.indigo). Optimistic-Remove aus der lokalen Liste, kein Re-Fetch. - Per-Status leere Liste mit kontextueller Beschreibung (z.B. unread-empty → Hinweis auf ShareExt-π-6). Build green iOS-Sim + macOS, 9/9 Unit-Tests (4 AppConfig, 2 Topic, 2 DTO-Decoding, 1 ArticleStatus). Pattern-Drift-Guard: Topic-Test hardcoded die ALL_TOPICS-Liste — Server-Änderung der Topic-Enum muss hier nachgezogen werden. Bleibt MVP-offen: - π-3 Reader-Detail (HTML→AttributedString-Spike) - π-4 Highlights + Tags - Tap-on-Row öffnet noch nichts — wartet auf π-3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
42 lines
1 KiB
Swift
42 lines
1 KiB
Swift
import Foundation
|
|
|
|
/// Topic-Slugs aus `@mana/shared-rss` (re-exportiert via `@pageta/domain`).
|
|
/// Slugs sind stabile Identifier in `preferences.blockedSources` und
|
|
/// `reactions.topic` — Änderungen brechen User-Daten. Sync mit
|
|
/// `mana/packages/shared-rss/src/types.ts` halten.
|
|
enum Topic: String, CaseIterable, Codable, Sendable, Identifiable {
|
|
case tech
|
|
case wissenschaft
|
|
case weltgeschehen
|
|
case wirtschaft
|
|
case kultur
|
|
case gesundheit
|
|
case politik
|
|
|
|
var id: String { rawValue }
|
|
|
|
/// Anzeige-Label + Emoji. Mirror von `pageta-domain/sources.ts#TOPIC_LABELS`.
|
|
var label: String {
|
|
switch self {
|
|
case .tech: "Tech"
|
|
case .wissenschaft: "Wissenschaft"
|
|
case .weltgeschehen: "Weltgeschehen"
|
|
case .wirtschaft: "Wirtschaft"
|
|
case .kultur: "Kultur"
|
|
case .gesundheit: "Gesundheit"
|
|
case .politik: "Politik"
|
|
}
|
|
}
|
|
|
|
var emoji: String {
|
|
switch self {
|
|
case .tech: "💻"
|
|
case .wissenschaft: "🔬"
|
|
case .weltgeschehen: "🌍"
|
|
case .wirtschaft: "📈"
|
|
case .kultur: "🎭"
|
|
case .gesundheit: "🩺"
|
|
case .politik: "🏛️"
|
|
}
|
|
}
|
|
}
|