Skip to content

Commit ba53c27

Browse files
committed
Allow generating restorable tab data
1 parent 106417c commit ba53c27

File tree

7 files changed

+65
-5
lines changed

7 files changed

+65
-5
lines changed

Core/Sources/ChatGPTChatTab/ChatGPTChatTab.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ChatService
22
import ChatTab
33
import Combine
44
import Foundation
5+
import OpenAIService
56
import Preferences
67
import SwiftUI
78

@@ -13,6 +14,11 @@ public class ChatGPTChatTab: ChatTab {
1314
public let provider: ChatProvider
1415
private var cancellable = Set<AnyCancellable>()
1516

17+
struct RestorableState: Codable {
18+
var history: [OpenAIService.ChatMessage]
19+
var configuration: OverridingChatGPTConfiguration.Overriding
20+
}
21+
1622
struct Builder: ChatTabBuilder {
1723
var title: String
1824
var buildable: Bool { true }
@@ -37,6 +43,28 @@ public class ChatGPTChatTab: ChatTab {
3743
ChatContextMenu(chat: provider)
3844
}
3945

46+
public func restorableState() async -> Data {
47+
let state = RestorableState(
48+
history: await service.memory.history,
49+
configuration: service.configuration.overriding
50+
)
51+
return (try? JSONEncoder().encode(state)) ?? Data()
52+
}
53+
54+
public static func restore(
55+
from data: Data,
56+
externalDependency: Void
57+
) async throws -> any ChatTab {
58+
let state = try JSONDecoder().decode(RestorableState.self, from: data)
59+
let tab = ChatGPTChatTab()
60+
tab.service.configuration.overriding = state.configuration
61+
await tab.service.memory.mutateHistory { history in
62+
history = state.history
63+
}
64+
65+
return tab
66+
}
67+
4068
public static func chatBuilders(externalDependency: Void) -> [ChatTabBuilder] {
4169
let customCommands = UserDefaults.shared.value(for: \.customCommands).compactMap {
4270
command in

Core/Sources/ChatService/ChatService.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Preferences
77

88
public final class ChatService: ObservableObject {
99
public let memory: ContextAwareAutoManagedChatGPTMemory
10-
public let configuration: ChatGPTConfiguration
10+
public let configuration: OverridingChatGPTConfiguration
1111
public let chatGPTService: any ChatGPTServiceType
1212
public var allPluginCommands: [String] { allPlugins.map { $0.command } }
1313
@Published public internal(set) var isReceivingMessage = false
@@ -20,7 +20,7 @@ public final class ChatService: ObservableObject {
2020

2121
init<T: ChatGPTServiceType>(
2222
memory: ContextAwareAutoManagedChatGPTMemory,
23-
configuration: ChatGPTConfiguration,
23+
configuration: OverridingChatGPTConfiguration,
2424
chatGPTService: T
2525
) {
2626
self.memory = memory

Core/Sources/SuggestionWidget/ChatWindowView.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,14 @@ class FakeChatTab: ChatTab {
386386
)
387387
}
388388

389+
func restorableState() async -> Data {
390+
return Data()
391+
}
392+
393+
static func restore(from data: Data, externalDependency: ()) async throws -> any ChatTab {
394+
return FakeChatTab(id: "id", title: "Title")
395+
}
396+
389397
override init(id: String, title: String) {
390398
super.init(id: id, title: title)
391399
}

Pro

Submodule Pro updated from 57d7766 to 716773b

Tool/Sources/ChatTab/ChatTab.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import ComposableArchitecture
22
import Foundation
33
import SwiftUI
44

5+
public extension Notification.Name {
6+
static let chatTabDidChange = Notification.Name("chatTabDidChange")
7+
}
8+
59
public struct ChatTabInfo: Identifiable, Equatable {
610
public var id: String
711
public var title: String
@@ -126,6 +130,15 @@ public protocol ChatTabType {
126130
/// Available builders for this chat tab.
127131
/// It's used to generate a list of tab types for user to create.
128132
static func chatBuilders(externalDependency: ExternalDependency) -> [ChatTabBuilder]
133+
/// Restorable state
134+
func restorableState() async -> Data
135+
/// Restore state
136+
static func restore(from data: Data, externalDependency: ExternalDependency) async throws
137+
-> any ChatTab
138+
}
139+
140+
public extension ChatTabType {
141+
var name: String { Self.name }
129142
}
130143

131144
public extension ChatTabType where ExternalDependency == Void {
@@ -165,5 +178,16 @@ public class EmptyChatTab: ChatTab {
165178
public init(id: String = UUID().uuidString) {
166179
super.init(id: id, title: "Empty")
167180
}
181+
182+
public func restorableState() async -> Data {
183+
return Data()
184+
}
185+
186+
public static func restore(
187+
from data: Data,
188+
externalDependency: Void
189+
) async throws -> any ChatTab {
190+
return Builder(title: "Empty").build()
191+
}
168192
}
169193

Tool/Sources/OpenAIService/Configuration/UserPreferenceChatGPTConfiguration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public struct UserPreferenceChatGPTConfiguration: ChatGPTConfiguration {
4444
}
4545

4646
public class OverridingChatGPTConfiguration: ChatGPTConfiguration {
47-
public struct Overriding {
47+
public struct Overriding: Codable {
4848
public var featureProvider: ChatFeatureProvider?
4949
public var temperature: Double?
5050
public var model: String?
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public enum ChatFeatureProvider: String, CaseIterable {
1+
public enum ChatFeatureProvider: String, CaseIterable, Codable {
22
case openAI
33
case azureOpenAI
44
}

0 commit comments

Comments
 (0)