Clean up messages in digest onboarding
This commit is contained in:
@ -40,6 +40,7 @@ public class DigestConfigViewModel: ObservableObject {
|
||||
try await dataService.setupUserDigestConfig()
|
||||
try await dataService.refreshDigest()
|
||||
digestEnabled = true
|
||||
dataService.featureFlags.digestEnabled = true
|
||||
} catch {
|
||||
if error is IneligibleError {
|
||||
isIneligible = true
|
||||
@ -109,20 +110,17 @@ struct DigestConfigView: View {
|
||||
}
|
||||
.padding(.top, 50)
|
||||
} else if viewModel.digestEnabled {
|
||||
VStack(spacing: 15) {
|
||||
VStack(spacing: 25) {
|
||||
Spacer()
|
||||
Text("""
|
||||
You've been added to the AI Digest demo. Your first issue should be ready soon.
|
||||
When a new digest is ready the icon in the library header will change color.
|
||||
You can close this window now.
|
||||
""")
|
||||
// swiftlint:disable:next line_length
|
||||
Text("You've been added to the AI Digest demo. Your first issue should be ready soon. When a new digest is ready the icon in the library header will change color. You can close this window now.")
|
||||
if !viewModel.notificationsEnabled {
|
||||
if viewModel.isTryingToEnableNotifications {
|
||||
ProgressView()
|
||||
} else {
|
||||
Button(action: {
|
||||
viewModel.tryEnableNotifications(dataService: dataService)
|
||||
}, label: { Text("Notify me when its ready") })
|
||||
}, label: { Text("Enable digest notifications") })
|
||||
.buttonStyle(RoundedRectButtonStyle(color: Color.blue, textColor: Color.white))
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,17 +12,19 @@ func getChapterData(digest: DigestResult) -> [(DigestChapter, DigestChapterData)
|
||||
var currentAudioIndex = 0
|
||||
var currentWordCount = 0.0
|
||||
|
||||
for (index, speechFile) in digest.speechFiles.enumerated() {
|
||||
let chapter = digest.chapters[index]
|
||||
for (index, speechFile) in (digest.speechFiles ?? []).enumerated() {
|
||||
let chapter = digest.chapters?[index]
|
||||
let duration = currentWordCount / SpeechDocument.averageWPM / speed * 60.0
|
||||
|
||||
chapterData.append((chapter, DigestChapterData(
|
||||
time: formatTimeInterval(duration) ?? "00:00",
|
||||
start: Int(currentAudioIndex),
|
||||
end: currentAudioIndex + Int(speechFile.utterances.count)
|
||||
)))
|
||||
currentAudioIndex += Int(speechFile.utterances.count)
|
||||
currentWordCount += chapter.wordCount
|
||||
if let chapter = chapter {
|
||||
chapterData.append((chapter, DigestChapterData(
|
||||
time: formatTimeInterval(duration) ?? "00:00",
|
||||
start: Int(currentAudioIndex),
|
||||
end: currentAudioIndex + Int(speechFile.utterances.count)
|
||||
)))
|
||||
currentAudioIndex += Int(speechFile.utterances.count)
|
||||
currentWordCount += chapter.wordCount
|
||||
}
|
||||
}
|
||||
return chapterData
|
||||
}
|
||||
@ -39,6 +41,7 @@ func formatTimeInterval(_ time: TimeInterval) -> String? {
|
||||
public class FullScreenDigestViewModel: ObservableObject {
|
||||
@Published var isLoading = false
|
||||
@Published var hasError = false
|
||||
@Published var isRunning = false
|
||||
@Published var digest: DigestResult?
|
||||
@Published var chapterInfo: [(DigestChapter, DigestChapterData)]?
|
||||
@Published var presentedLibraryItem: String?
|
||||
@ -49,6 +52,7 @@ public class FullScreenDigestViewModel: ObservableObject {
|
||||
func load(dataService: DataService, audioController: AudioController) async {
|
||||
hasError = false
|
||||
isLoading = true
|
||||
isRunning = false
|
||||
|
||||
if !dataService.digestNeedsRefresh() {
|
||||
if let digest = dataService.loadStoredDigest() {
|
||||
@ -69,6 +73,8 @@ public class FullScreenDigestViewModel: ObservableObject {
|
||||
self.digest = digest
|
||||
self.chapterInfo = getChapterData(digest: digest)
|
||||
self.lastVisitedDigestId = digest.id
|
||||
self.isRunning = digest.jobState == "RUNNING" || digest.jobState == "PENDING"
|
||||
self.hasError = digest.jobState == "FAILED"
|
||||
|
||||
if let playingDigest = audioController.itemAudioProperties as? DigestAudioItem, playingDigest.digest.id == digest.id {
|
||||
// Don't think we need to do anything here
|
||||
@ -179,9 +185,11 @@ struct FullScreenDigestView: View {
|
||||
await viewModel.load(dataService: dataService, audioController: audioController)
|
||||
}
|
||||
}, label: { Text("Try again") })
|
||||
.buttonStyle(RoundedRectButtonStyle(color: Color.blue, textColor: Color.white))
|
||||
.buttonStyle(RoundedRectButtonStyle(color: Color.blue, textColor: Color.white))
|
||||
Spacer()
|
||||
}
|
||||
} else if viewModel.isRunning {
|
||||
jobRunningText
|
||||
} else {
|
||||
itemBody
|
||||
}
|
||||
@ -192,6 +200,19 @@ struct FullScreenDigestView: View {
|
||||
await viewModel.load(dataService: dataService, audioController: audioController)
|
||||
}
|
||||
}
|
||||
|
||||
var jobRunningText: some View {
|
||||
VStack {
|
||||
Spacer()
|
||||
Text("""
|
||||
You've been added to the AI Digest demo. Your first issue should be ready soon.
|
||||
When a new digest is ready the icon in the library header will change color.
|
||||
You can close this window now.
|
||||
""")
|
||||
.padding(20)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
var closeButton: some View {
|
||||
Button(action: {
|
||||
@ -218,7 +239,7 @@ struct FullScreenDigestView: View {
|
||||
Spacer()
|
||||
}
|
||||
if let digest = viewModel.digest {
|
||||
Text(digest.title)
|
||||
Text(digest.title ?? "")
|
||||
.font(Font.system(size: 17, weight: .semibold))
|
||||
.lineSpacing(5)
|
||||
.lineLimit(3)
|
||||
@ -274,14 +295,14 @@ struct FullScreenDigestView: View {
|
||||
.padding(.top, 20)
|
||||
}
|
||||
|
||||
if let digest = viewModel.digest {
|
||||
if let digest = viewModel.digest, let content = digest.content {
|
||||
Text("Transcript")
|
||||
.font(Font.system(size: 17, weight: .semibold))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.top, 20)
|
||||
|
||||
VStack {
|
||||
Markdown(digest.content)
|
||||
Markdown(content)
|
||||
.foregroundColor(Color.appGrayTextContrast)
|
||||
}
|
||||
.padding(15)
|
||||
|
||||
@ -44,7 +44,7 @@ public struct DigestAudioItem: AudioItemProperties {
|
||||
public init(digest: DigestResult, chapters: [DigestChapterData]) {
|
||||
self.digest = digest
|
||||
self.itemID = digest.id
|
||||
self.title = digest.title
|
||||
self.title = digest.title ?? "Omnivore digest"
|
||||
self.chapters = chapters
|
||||
|
||||
self.startIndex = 0
|
||||
@ -52,7 +52,7 @@ public struct DigestAudioItem: AudioItemProperties {
|
||||
|
||||
self.imageURL = nil
|
||||
|
||||
if let first = digest.speechFiles.first {
|
||||
if let first = digest.speechFiles?.first {
|
||||
self.language = first.language
|
||||
self.byline = digest.byline
|
||||
}
|
||||
@ -1033,7 +1033,7 @@ public struct DigestAudioItem: AudioItemProperties {
|
||||
}
|
||||
|
||||
func combineSpeechFiles(from digest: DigestResult) -> ([Utterance], Double) {
|
||||
let allUtterances = digest.speechFiles.flatMap { $0.utterances }
|
||||
let allUtterances = digest.speechFiles?.flatMap { $0.utterances } ?? []
|
||||
var updatedUtterances: [Utterance] = []
|
||||
var currentWordOffset = 0.0
|
||||
|
||||
@ -1053,7 +1053,7 @@ public struct DigestAudioItem: AudioItemProperties {
|
||||
}
|
||||
|
||||
func downloadDigestItemSpeechFile(itemID: String, priority: DownloadPriority) async throws -> SpeechDocument? {
|
||||
if let digestItem = itemAudioProperties as? DigestAudioItem, let firstFile = digestItem.digest.speechFiles.first {
|
||||
if let digestItem = itemAudioProperties as? DigestAudioItem, let firstFile = digestItem.digest.speechFiles?.first {
|
||||
let (utterances, wordCount) = combineSpeechFiles(from: digestItem.digest)
|
||||
|
||||
let document = SpeechDocument(
|
||||
|
||||
@ -9,16 +9,16 @@ struct AITaskRequest: Decodable {
|
||||
|
||||
public struct DigestResult: Codable {
|
||||
public let id: String
|
||||
public let title: String
|
||||
public let byline: String
|
||||
public let content: String
|
||||
public let description: String
|
||||
public let urlsToAudio: [String]
|
||||
public let chapters: [DigestChapter]
|
||||
public let speechFiles: [SpeechDocument]
|
||||
public let title: String?
|
||||
public let byline: String?
|
||||
public let content: String?
|
||||
public let description: String?
|
||||
public let urlsToAudio: [String]?
|
||||
public let chapters: [DigestChapter]?
|
||||
public let speechFiles: [SpeechDocument]?
|
||||
|
||||
public let jobState: String
|
||||
public let createdAt: String
|
||||
public let jobState: String?
|
||||
public let createdAt: String?
|
||||
}
|
||||
|
||||
public struct DigestChapter: Codable {
|
||||
@ -169,9 +169,10 @@ extension DataService {
|
||||
|
||||
do {
|
||||
let digest = try await networker.urlSession.performRequest(resource: resource)
|
||||
let oldDigest = loadStoredDigest()
|
||||
|
||||
saveDigest(digest)
|
||||
if digest.jobState == "SUCCEEDED" {
|
||||
saveDigest(digest)
|
||||
}
|
||||
|
||||
return digest
|
||||
} catch {
|
||||
|
||||
@ -40,7 +40,7 @@ public extension DataService {
|
||||
try $0.setUserPersonalization(
|
||||
input: InputObjects.SetUserPersonalizationInput(
|
||||
digestConfig: OptionalArgument(
|
||||
InputObjects.DigestConfigInput(channels: OptionalArgument([OptionalArgument("email")]))
|
||||
InputObjects.DigestConfigInput(channels: OptionalArgument([OptionalArgument("push")]))
|
||||
)
|
||||
),
|
||||
selection: selection
|
||||
|
||||
Reference in New Issue
Block a user