Skip to content

Commit

Permalink
Merge pull request #3933 from omnivore-app/feat/ios-enable-digest
Browse files Browse the repository at this point in the history
Start adding a view to configure digest
  • Loading branch information
jacksonh committed May 13, 2024
2 parents 036889e + bcae91e commit bbaed7e
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 0 deletions.
161 changes: 161 additions & 0 deletions apple/OmnivoreKit/Sources/App/Views/AI/DigestConfigView.swift
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)
}
}
19 changes: 19 additions & 0 deletions apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ struct AnimatingCellHeight: AnimatableModifier {
@State var listTitle = ""
@State var showExpandedAudioPlayer = false
@State var showLibraryDigest = false
@State var showDigestConfig = false

@Binding var isEditMode: EditMode

Expand Down Expand Up @@ -330,6 +331,15 @@ struct AnimatingCellHeight: AnimatableModifier {
Text("Sorry digest is only available on iOS 17 and above")
}
}
.sheet(isPresented: $showDigestConfig) {
if #available(iOS 17.0, *) {
NavigationView {
DigestConfigView(dataService: dataService)
}
} else {
Text("Sorry digest is only available on iOS 17 and above")
}
}
.toolbar {
toolbarItems
}
Expand Down Expand Up @@ -405,6 +415,15 @@ struct AnimatingCellHeight: AnimatableModifier {
.buttonStyle(.plain)
.padding(.trailing, 4)
}
if #available(iOS 17.0, *), !dataService.featureFlags.digestEnabled, !viewModel.digestHidden {
// Give the user an opportunity to enable digest
Button(
action: { showDigestConfig = true },
label: { Image.tabDigestSelected }
)
.buttonStyle(.plain)
.padding(.trailing, 4)
}
if prefersListLayout {
Button(
action: { isEditMode = isEditMode == .active ? .inactive : .active },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ enum LoadingBarStyle {
@AppStorage(UserDefaultKey.stopUsingFollowingPrimer.rawValue) var stopUsingFollowingPrimer = false
@AppStorage("LibraryTabView::hideFollowingTab") var hideFollowingTab = false
@AppStorage(UserDefaultKey.lastVisitedDigestId.rawValue) var lastVisitedDigestId = ""
@AppStorage("LibraryTabView::digestHidden") var digestHidden = false

@AppStorage(UserDefaultKey.lastSelectedFeaturedItemFilter.rawValue) var featureFilter = FeaturedItemFilter.continueReading.rawValue

Expand Down

0 comments on commit bbaed7e

Please sign in to comment.