|
7 | 7 | // |
8 | 8 |
|
9 | 9 | import SwiftUI |
| 10 | +import Combine |
| 11 | +import SwiftUIX |
10 | 12 |
|
11 | 13 | struct ChatRoomConfigView: View { |
12 | 14 |
|
13 | 15 | @Binding var isKeyPresented: Bool |
| 16 | + @StateObject var chatModel: AIChatModel |
| 17 | + |
| 18 | + @State var roomName: String = "" |
| 19 | + @State var prompt: String = "" |
| 20 | + @State var temperature: String = "" |
| 21 | + @State var historyCount: String = "" |
| 22 | + @State var model: String = "" |
| 23 | + @State var isDirty: Bool = false |
| 24 | + @State var showingAlert: Bool = false |
| 25 | + @State var alertMessage: String = "" |
| 26 | + |
| 27 | + init(isKeyPresented: Binding<Bool>, chatModel: AIChatModel) { |
| 28 | + _isKeyPresented = isKeyPresented |
| 29 | + _chatModel = StateObject(wrappedValue: chatModel) |
| 30 | + |
| 31 | + let room = ChatRoomStore.shared.chatRoom(chatModel.roomID) |
| 32 | + _roomName = State(initialValue: room?.roomName ?? room?.roomID.formatTimestamp() ?? "") |
| 33 | + _prompt = State(initialValue: room?.prompt ?? "") |
| 34 | + _temperature = State(initialValue: "\(room?.temperature ?? 0.7)") |
| 35 | + _historyCount = State(initialValue: "\(room?.historyCount ?? 0)") |
| 36 | + _model = State(initialValue: room?.model ?? "") |
| 37 | + _isDirty = State(initialValue: false) |
| 38 | + } |
14 | 39 |
|
15 | 40 | var body: some View { |
16 | 41 | NavigationView { |
17 | | - VStack { |
18 | | - Text("Coming soon..".localized()).font(.title2) |
| 42 | + List { |
| 43 | + ConfigCellView(title: "Room Name".localized(), |
| 44 | + subtitle: "", |
| 45 | + value: $roomName, |
| 46 | + description: "The name of the room".localized()) |
| 47 | + ConfigCellView(title: "Prompt".localized(), subtitle: "Prompt description.".localized(), value: $prompt, description: "Prompt text to generate contextual information for the corresponding text.".localized()) |
| 48 | + ConfigCellView(title: "Temperature".localized(), subtitle: "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.".localized(), value: $temperature, description: "The default temperature is 0.7".localized()) |
| 49 | + ConfigCellView(title: "Chat History".localized(), subtitle: "How much context information is carried when sending a dialog.".localized(), value: $historyCount, description: "Default is the last 3 conversations.".localized()) |
| 50 | + //ConfigCellView(title: "Model", subtitle: "ChatGPT 模型", value: $model, description: "The model used for processing") |
19 | 51 | } |
20 | | - .navigationTitle("Room Settings".localized()) |
21 | | - .toolbar { |
22 | | - Button(action: onCloseButtonTapped) { |
23 | | - Image(systemName: "xmark.circle").imageScale(.large) |
24 | | - } |
| 52 | + .navigationBarTitle(Text("Room Settings".localized())) |
| 53 | + .navigationBarItems( |
| 54 | + trailing: |
| 55 | + HStack { |
| 56 | + Button(action: onSaveButtonTapped, label: { |
| 57 | + Text("Save".localized()).bold() |
| 58 | + }).disabled(!isDirty) |
| 59 | + |
| 60 | + Button(action: onCloseButtonTapped) { |
| 61 | + Image(systemName: "xmark.circle").imageScale(.large) |
| 62 | + } |
| 63 | + } |
| 64 | + ) |
| 65 | + .alert(isPresented: $showingAlert) { |
| 66 | + ShowAlterView() |
25 | 67 | } |
| 68 | + .onChange(of: [roomName, prompt, temperature, historyCount, model]) { _ in |
| 69 | + self.isDirty = true |
| 70 | + } |
| 71 | + .gesture( |
| 72 | + TapGesture().onEnded { |
| 73 | + hideKeyboard() |
| 74 | + } |
| 75 | + ) |
26 | 76 | } |
27 | 77 | } |
28 | 78 |
|
| 79 | + private func onSaveButtonTapped() { |
| 80 | + // 检查 temperature 数据格式是否符合 |
| 81 | + guard let tempValue = Double(temperature), 0.0 <= tempValue && tempValue <= 2.0 else { |
| 82 | + alertMessage = "Temperature is between 0 and 2.".localized() |
| 83 | + showingAlert = true |
| 84 | + return |
| 85 | + } |
| 86 | + |
| 87 | + // 检查 historyCount 数据格式是否符合 |
| 88 | + guard let histCountValue = Int(historyCount), histCountValue >= 0 else { |
| 89 | + alertMessage = "History message count must be an integer greater than or equal to 0.".localized() |
| 90 | + showingAlert = true |
| 91 | + return |
| 92 | + } |
| 93 | + |
| 94 | + let room = ChatRoom(roomID: chatModel.roomID, roomName: roomName, model: model, prompt: prompt.isEmpty ? nil : prompt, temperature: tempValue, historyCount: histCountValue) |
| 95 | + ChatRoomStore.shared.updateChatRoom(for: chatModel.roomID, room: room) |
| 96 | + self.isDirty = false |
| 97 | + |
| 98 | + alertMessage = "Settings have been updated~".localized() |
| 99 | + showingAlert = true |
| 100 | + } |
| 101 | + |
| 102 | + func ShowAlterView() -> Alert { |
| 103 | + Alert( |
| 104 | + title: Text("Tips".localized()), |
| 105 | + message: Text(alertMessage), |
| 106 | + dismissButton: .default(Text("OK".localized())) |
| 107 | + ) |
| 108 | + } |
| 109 | + |
29 | 110 | private func onCloseButtonTapped() { |
30 | 111 | isKeyPresented = false |
31 | 112 | } |
| 113 | + |
| 114 | + /// 当用户点击其他区域时隐藏软键盘 |
| 115 | + private func hideKeyboard() { |
| 116 | + UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) |
| 117 | + } |
32 | 118 | } |
33 | 119 |
|
| 120 | +struct ConfigCellView: View { |
| 121 | + let title: String |
| 122 | + let subtitle: String |
| 123 | + @Binding var value: String |
| 124 | + let description: String |
| 125 | + |
| 126 | + var body: some View { |
| 127 | + VStack(alignment: .leading) { |
| 128 | + Text(title) |
| 129 | + .font(.headline) |
| 130 | + .padding(.top, 10) |
| 131 | + |
| 132 | + if !subtitle.isEmpty { |
| 133 | + Text(subtitle) |
| 134 | + .font(.body) |
| 135 | + .foregroundColor(.secondaryLabel) |
| 136 | + .padding(.top, 0.5) |
| 137 | + .padding(.bottom, 10) |
| 138 | + .fixedSize(horizontal: false, vertical: true) |
| 139 | + } |
| 140 | + |
| 141 | + TextView(description, text: $value, onEditingChanged: {_ in |
| 142 | + |
| 143 | + }, onCommit: { |
| 144 | + |
| 145 | + }) |
| 146 | + .returnKeyType(.default) |
| 147 | + .padding(10) |
| 148 | + .maxHeight(90) |
| 149 | + .border(.blue.opacity(0.8), cornerRadius: 10) |
| 150 | + |
| 151 | + Spacer() |
| 152 | + .height(15) |
| 153 | + } |
| 154 | + } |
| 155 | +} |
34 | 156 |
|
35 | 157 | struct ChatRoomConfigView_Previews: PreviewProvider { |
36 | 158 | static var previews: some View { |
37 | | - ChatRoomConfigView(isKeyPresented: .constant(true)) |
| 159 | + ChatRoomConfigView(isKeyPresented: .constant(true), chatModel: AIChatModel(roomID: nil)) |
38 | 160 | } |
39 | 161 | } |
40 | 162 |
|
0 commit comments