Skip to content

Commit

Permalink
Prepare chat assistant
Browse files Browse the repository at this point in the history
  • Loading branch information
bourvill committed Jan 22, 2024
1 parent 0c078f9 commit 26a72f4
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,6 @@
import Factory
import SwiftUI

final class SynthesisEntryViewModel: ObservableObject {
@Injected(\.chatAssistant) private var chatAssistant
@Published var synthesis = ""
@Published var isLoading = false

@MainActor
func generateSynthesis(from entry: Entry) async throws {
defer {
isLoading = false
}
isLoading = true

guard let content = entry.content?.withoutHTML else { return }

synthesis = try await chatAssistant.generateSynthesis(content: content)
}
}

struct SynthesisEntryView: View {
@StateObject private var viewModel = SynthesisEntryViewModel()
let entry: Entry
Expand Down
27 changes: 27 additions & 0 deletions App/Features/AI/Synthesis/SynthesisEntryViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// SynthesisEntryViewModel.swift
// wallabag
//
// Created by maxime marinel on 22/01/2024.
//

import Factory
import Foundation

final class SynthesisEntryViewModel: ObservableObject {
@Injected(\.chatAssistant) private var chatAssistant
@Published var synthesis = ""
@Published var isLoading = false

@MainActor
func generateSynthesis(from entry: Entry) async throws {
defer {
isLoading = false
}
isLoading = true

guard let content = entry.content?.withoutHTML else { return }

synthesis = try await chatAssistant.generateSynthesis(content: content)
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,9 @@
import Factory
import SwiftUI

final class TagSuggestionViewModel: ObservableObject {
@Injected(\.chatAssistant) private var chatAssistant
@Published var suggestions: [String] = []
@Published var isLoading = false

@MainActor
func generateSynthesis(from entry: Entry) async throws {
defer {
isLoading = false
}
isLoading = true

guard let content = entry.content?.withoutHTML else { return }

suggestions = try await chatAssistant.generateTags(content: content)
}
}

struct TagSuggestionView: View {
@Environment(\.dismiss) private var dismiss
@StateObject private var viewModel = TagSuggestionViewModel()
@State private var selection = Set<String>()

let entry: Entry

Expand All @@ -34,18 +16,18 @@ struct TagSuggestionView: View {
List {
ForEach(viewModel.suggestions, id: \.self) { suggestion in
Button(action: {
if selection.contains(suggestion) {
selection.remove(suggestion)
if viewModel.tagSelections.contains(suggestion) {
viewModel.tagSelections.remove(suggestion)
} else {
selection.insert(suggestion)
viewModel.tagSelections.insert(suggestion)
}
}, label: {
HStack {
Text(suggestion)
.padding()
.fontDesign(.serif)
Spacer()
if selection.contains(suggestion) {
if viewModel.tagSelections.contains(suggestion) {
Image(systemName: "checkmark.circle.fill")
} else {
Image(systemName: "circle")
Expand All @@ -55,17 +37,28 @@ struct TagSuggestionView: View {
}
}
.listStyle(.plain)
if !selection.isEmpty {
Button(action: {}, label: {
Text("Add \(selection.count.formatted()) tags")
if !viewModel.tagSelections.isEmpty {
Button(action: {
Task {
try? await viewModel.addTags(to: entry)
dismiss()
}
}, label: {
if viewModel.addingTags {
ProgressView()
} else {
Text("Add \(viewModel.tagSelections.count.formatted()) tags")
}
})
.buttonStyle(.borderedProminent)
.disabled(viewModel.addingTags)
}
}
}
.navigationTitle("Tag suggestion")
.task {
do {
try await viewModel.generateSynthesis(from: entry)
try await viewModel.generateTags(from: entry)
} catch {
print(error)
}
Expand Down
41 changes: 41 additions & 0 deletions App/Features/AI/Tag/TagSuggestionViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// TagSuggestionViewModel.swift
// wallabag
//
// Created by maxime marinel on 22/01/2024.
//

import Factory
import Foundation

final class TagSuggestionViewModel: ObservableObject {
@Injected(\.wallabagSession) private var wallabagSession
@Injected(\.chatAssistant) private var chatAssistant
@Published var suggestions: [String] = []
@Published var isLoading = false
@Published var addingTags = false
@Published var tagSelections = Set<String>()

@MainActor
func generateTags(from entry: Entry) async throws {
defer {
isLoading = false
}
isLoading = true

guard let content = entry.content?.withoutHTML else { return }

suggestions = try await chatAssistant.generateTags(content: content)
}

@MainActor
func addTags(to entry: Entry) async throws {
defer {
addingTags = false
}
addingTags = true
for tag in tagSelections {
wallabagSession.add(tag: tag, for: entry)
}
}
}
2 changes: 1 addition & 1 deletion App/Features/Sync/AppSync.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ extension AppSync {

private func synchronizeTags() async {
do {
try await for wallabagTag in fetchTags() {
for wallabagTag in try await fetchTags() {
if let tag = try? backgroundContext.fetch(Tag.fetchOneById(wallabagTag.id)).first {
tags[tag.id] = tag
} else {
Expand Down
28 changes: 26 additions & 2 deletions wallabag.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
094AA03E2629EB1F006E5605 /* wallabagTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094AA03D2629EB1F006E5605 /* wallabagTests.swift */; };
094AA05A2629EB60006E5605 /* ImageCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094A9FED2629E6BB006E5605 /* ImageCacheTests.swift */; };
094AA0692629EB98006E5605 /* ImageDownloaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094AA00F2629E739006E5605 /* ImageDownloaderTests.swift */; };
094BE2B52B5E94F900DFBF5A /* SynthesisEntryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094BE2B42B5E94F900DFBF5A /* SynthesisEntryViewModel.swift */; };
094BE2B92B5E952C00DFBF5A /* TagSuggestionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 094BE2B82B5E952C00DFBF5A /* TagSuggestionViewModel.swift */; };
0951C61829CC2EB000D8E8C6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0951C61729CC2EB000D8E8C6 /* Assets.xcassets */; };
09564E0D2851C57200D39E95 /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09564E0C2851C57200D39E95 /* SettingView.swift */; };
09644AD125C94825000FFDA1 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644AD025C94825000FFDA1 /* ShareViewController.swift */; };
Expand Down Expand Up @@ -170,6 +172,8 @@
094AA03B2629EB1F006E5605 /* wallabagTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = wallabagTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
094AA03D2629EB1F006E5605 /* wallabagTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = wallabagTests.swift; sourceTree = "<group>"; };
094AA03F2629EB1F006E5605 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
094BE2B42B5E94F900DFBF5A /* SynthesisEntryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SynthesisEntryViewModel.swift; sourceTree = "<group>"; };
094BE2B82B5E952C00DFBF5A /* TagSuggestionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagSuggestionViewModel.swift; sourceTree = "<group>"; };
0951C61729CC2EB000D8E8C6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
09564E0C2851C57200D39E95 /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = "<group>"; };
09644ACE25C94825000FFDA1 /* bagit.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = bagit.appex; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -367,6 +371,24 @@
path = wallabagTests;
sourceTree = "<group>";
};
094BE2B22B5E94EA00DFBF5A /* Synthesis */ = {
isa = PBXGroup;
children = (
09B8C3A72B27AF62002AEA2C /* SynthesisEntryView.swift */,
094BE2B42B5E94F900DFBF5A /* SynthesisEntryViewModel.swift */,
);
path = Synthesis;
sourceTree = "<group>";
};
094BE2B62B5E951F00DFBF5A /* Tag */ = {
isa = PBXGroup;
children = (
09952D102B566EAB0059D24F /* TagSuggestionView.swift */,
094BE2B82B5E952C00DFBF5A /* TagSuggestionViewModel.swift */,
);
path = Tag;
sourceTree = "<group>";
};
09644ACF25C94825000FFDA1 /* bagit */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -699,9 +721,9 @@
09B8C3A42B27ACB4002AEA2C /* AI */ = {
isa = PBXGroup;
children = (
094BE2B62B5E951F00DFBF5A /* Tag */,
094BE2B22B5E94EA00DFBF5A /* Synthesis */,
09B8C3A52B27AD2D002AEA2C /* ChatAssistant.swift */,
09B8C3A72B27AF62002AEA2C /* SynthesisEntryView.swift */,
09952D102B566EAB0059D24F /* TagSuggestionView.swift */,
);
path = AI;
sourceTree = "<group>";
Expand Down Expand Up @@ -1047,6 +1069,7 @@
09644B7E25C98152000FFDA1 /* AppState.swift in Sources */,
09644C6E25C985A9000FFDA1 /* DeleteEntryButton.swift in Sources */,
09644B8C25C98176000FFDA1 /* Route.swift in Sources */,
094BE2B52B5E94F900DFBF5A /* SynthesisEntryViewModel.swift in Sources */,
09644BAD25C98213000FFDA1 /* CoreDataSync.swift in Sources */,
09644BDE25C9833E000FFDA1 /* WallabagSession.swift in Sources */,
09644C7125C985A9000FFDA1 /* FontSizeSelectorView.swift in Sources */,
Expand All @@ -1072,6 +1095,7 @@
09644C7F25C985B8000FFDA1 /* ImageDownloaderPublisher.swift in Sources */,
09644CE825C986CC000FFDA1 /* ServerView.swift in Sources */,
09B8C3A62B27AD2D002AEA2C /* ChatAssistant.swift in Sources */,
094BE2B92B5E952C00DFBF5A /* TagSuggestionViewModel.swift in Sources */,
09644CFD25C9870C000FFDA1 /* TagListFor.swift in Sources */,
09644BFA25C983F8000FFDA1 /* Podcast.swift in Sources */,
09644BAE25C98213000FFDA1 /* AppSync.swift in Sources */,
Expand Down

0 comments on commit 26a72f4

Please sign in to comment.