7da41a65ad
Add a resizable home-screen widget on iOS and Android showing recent
in-progress books with cover, reading progress, and tap-to-open.
- One responsive widget: Android resizable 1x1 to 4x3 (one book per
column, up to 3); iOS Small/Medium/Large families. Covers are cropped,
rounded, with a percent badge and a progress bar (baked into the bitmap
on Android, SwiftUI overlays on iOS).
- TTS controls (previous, play-pause, next) appear in 2+ row sizes when
TTS is active, wired to the existing media session. Reading progress
stays live during background TTS via a fraction computed from the baked
offline locations.
- Publishes a snapshot plus downsized cover thumbnails to the iOS App
Group and Android SharedPreferences through a new update_reading_widget
native-bridge command; refresh is debounced and driven by library and
progress changes, TTS, and app backgrounding.
- Tapping a cover opens readest://book/{hash}, switching the reader in
place when one is already open.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
35 lines
895 B
Swift
35 lines
895 B
Swift
import WidgetKit
|
|
import SwiftUI
|
|
|
|
struct ReadingWidget: Widget {
|
|
let kind = "ReadingWidget"
|
|
var body: some WidgetConfiguration {
|
|
StaticConfiguration(kind: kind, provider: ReadingProvider()) { entry in
|
|
ReadingWidgetEntryView(entry: entry)
|
|
}
|
|
.configurationDisplayName("Readest")
|
|
.description("Continue reading your recent books.")
|
|
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge])
|
|
}
|
|
}
|
|
|
|
struct ReadingWidgetEntryView: View {
|
|
@Environment(\.widgetFamily) var family
|
|
let entry: ReadingEntry
|
|
var body: some View {
|
|
content.widgetCardBackground()
|
|
}
|
|
|
|
@ViewBuilder private var content: some View {
|
|
switch family {
|
|
case .systemSmall: SmallReadingView(snapshot: entry.snapshot)
|
|
default: RowReadingView(snapshot: entry.snapshot)
|
|
}
|
|
}
|
|
}
|
|
|
|
@main
|
|
struct ReadestWidgetBundle: WidgetBundle {
|
|
var body: some Widget { ReadingWidget() }
|
|
}
|