-
Notifications
You must be signed in to change notification settings - Fork 554
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3933 from omnivore-app/feat/ios-enable-digest
Start adding a view to configure digest
- Loading branch information
Showing
3 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
161 changes: 161 additions & 0 deletions
161
apple/OmnivoreKit/Sources/App/Views/AI/DigestConfigView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import SwiftUI | ||
import Models | ||
import Services | ||
import Views | ||
import MarkdownUI | ||
import Utils | ||
import Transmission | ||
|
||
@MainActor | ||
public class DigestConfigViewModel: ObservableObject { | ||
@Published var isLoading = false | ||
@Published var digest: DigestResult? | ||
@Published var chapterInfo: [(DigestChapter, DigestChapterData)]? | ||
@Published var presentedLibraryItem: String? | ||
@Published var presentWebContainer = false | ||
|
||
@AppStorage(UserDefaultKey.lastVisitedDigestId.rawValue) var lastVisitedDigestId = "" | ||
|
||
func load(dataService: DataService) async { | ||
isLoading = true | ||
if !digestNeedsRefresh() { | ||
if let digest = dataService.loadStoredDigest() { | ||
self.digest = digest | ||
} | ||
} else { | ||
do { | ||
if let digest = try await dataService.getLatestDigest(timeoutInterval: 10) { | ||
self.digest = digest | ||
} | ||
} catch { | ||
print("ERROR WITH DIGEST: ", error) | ||
self.digest = nil | ||
} | ||
} | ||
|
||
isLoading = false | ||
} | ||
|
||
func refreshDigest(dataService: DataService) async { | ||
do { | ||
try await dataService.refreshDigest() | ||
} catch { | ||
print("ERROR WITH DIGEST: ", error) | ||
} | ||
} | ||
|
||
func digestNeedsRefresh() -> Bool { | ||
let fileManager = FileManager.default | ||
let localURL = URL.om_cachesDirectory.appendingPathComponent("digest.json") | ||
do { | ||
let attributes = try fileManager.attributesOfItem(atPath: localURL.path) | ||
if let modificationDate = attributes[.modificationDate] as? Date { | ||
// Two hours ago | ||
let twoHoursAgo = Date().addingTimeInterval(-2 * 60 * 60) | ||
return modificationDate < twoHoursAgo | ||
} | ||
} catch { | ||
print("Error: \(error)") | ||
} | ||
return true | ||
} | ||
} | ||
|
||
@available(iOS 17.0, *) | ||
@MainActor | ||
struct DigestConfigView: View { | ||
@StateObject var viewModel = DigestConfigViewModel() | ||
let dataService: DataService | ||
|
||
@Environment(\.dismiss) private var dismiss | ||
|
||
public init(dataService: DataService) { | ||
self.dataService = dataService | ||
} | ||
|
||
var titleBlock: some View { | ||
HStack { | ||
Text("Omnivore Digest") | ||
.font(Font.system(size: 18, weight: .semibold)) | ||
Image.tabDigestSelected | ||
Spacer() | ||
closeButton | ||
} | ||
.padding(.top, 20) | ||
.padding(.horizontal, 20) | ||
} | ||
|
||
var body: some View { | ||
VStack { | ||
titleBlock | ||
.padding(.top, 10) | ||
itemBody | ||
.padding(15) | ||
|
||
Spacer() | ||
}.task { | ||
await viewModel.load(dataService: dataService) | ||
} | ||
} | ||
|
||
var closeButton: some View { | ||
Button(action: { | ||
dismiss() | ||
}, label: { | ||
Text("Close") | ||
.foregroundColor(Color.blue) | ||
}) | ||
.buttonStyle(.plain) | ||
} | ||
|
||
var logoBlock: some View { | ||
HStack { | ||
Image.coloredSmallOmnivoreLogo | ||
.resizable() | ||
.frame(width: 20, height: 20) | ||
Text("Omnivore.app") | ||
.font(Font.system(size: 14)) | ||
.foregroundColor(Color.themeLibraryItemSubtle) | ||
Spacer() | ||
} | ||
} | ||
|
||
@available(iOS 17.0, *) | ||
var itemBody: some View { | ||
VStack(alignment: .leading, spacing: 20) { | ||
logoBlock | ||
|
||
let description1 = | ||
""" | ||
Omnivore Digest is a free daily digest of your best recent library items. Omnivore | ||
filters and ranks all the items recently added to your library, uses AI to summarize them, | ||
and creates a short library item, email, or a daily podcast you can listen to in our iOS app. | ||
Note that if you sign up for Digest, your recent library items will be processed by an AI | ||
service (Anthropic, or OpenAI). Your highlights, notes, and labels will not be sent to the AI | ||
service. | ||
Digest is available to all users that have saved at least ten items and added two subscriptions. | ||
""" | ||
Markdown(description1) | ||
.lineSpacing(10) | ||
.accentColor(.appGraySolid) | ||
.font(.appSubheadline) | ||
.padding(5) | ||
.frame(maxWidth: .infinity, alignment: .leading) | ||
|
||
HStack { | ||
Spacer() | ||
|
||
Button(action: {}, label: { Text("Hide digest") }) | ||
.buttonStyle(RoundedRectButtonStyle()) | ||
|
||
Button(action: {}, label: { Text("Enable digest") }) | ||
.buttonStyle(RoundedRectButtonStyle(color: Color.blue, textColor: Color.white)) | ||
} | ||
} | ||
.padding(15) | ||
.background(Color.themeLabelBackground.opacity(0.6)) | ||
.cornerRadius(5) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters