Skip to content

Commit a39a996

Browse files
committed
Merge branch 'release/2.5'
2 parents 5ba2e08 + d178319 commit a39a996

File tree

16 files changed

+351
-65
lines changed

16 files changed

+351
-65
lines changed

README.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ OpenAI ChatGPT app for iOS, iPadOS, macoS
1010

1111
#### 更新说明
1212

13-
最新版本 v2.3
14-
- Create new conversation. (创建新的对话)
15-
- Save conversation records. (保存对话记录)
16-
- Switch to historical conversations. (切换历史对话)
17-
- Scroll to the top of the conversation list. (滚动到对话列表的顶部)
18-
- Auto-scroll to the bottom of the conversation list. (自动滚动到对话列表的底部)
19-
- Option to request conversations without historical records (click on the icon on the left side of the input box to toggle). (请求时可不带历史对话记录)
20-
- Support for additional languages (Traditional Chinese, Korean, Japanese, French, German, Russian, etc.). (支持更多语言(繁体中文、韩文、日文、法语、德语、俄语等))
13+
最新版本 v2.5
14+
15+
- Added chat room settings with Prompt and Temperature parameter configuration. (新增聊天室设置功能,支持 Prompt 和 Temperature 参数配置。)
16+
- Display current conversation identifier in the history list. (历史对话列表增加显示当前对话标识。)
17+
- Fixed potential crash when sending conversations. (修复发送对话时可能会崩溃的问题。)
18+
- Removed restrictions on creating new conversations and switching history when requesting a conversation. (请求对话时,取消创建新对话和切换历史对话的禁用限制。)
19+
- Improved multi-language translations for sharing feature. (完善分享功能的多语言翻译。)
20+
2121

2222
**支持功能**
2323

@@ -101,6 +101,19 @@ TestFlight 下载地址:[https://testflight.apple.com/join/GR4BOt2M](https://t
101101

102102
#### 3.4 历史更新功能
103103

104+
v2.4:
105+
- Add sharing function(增加分享功能)
106+
- Fix the history list is too high(修复历史列表过高)
107+
108+
v2.3:
109+
- Create new conversation. (创建新的对话)
110+
- Save conversation records. (保存对话记录)
111+
- Switch to historical conversations. (切换历史对话)
112+
- Scroll to the top of the conversation list. (滚动到对话列表的顶部)
113+
- Auto-scroll to the bottom of the conversation list. (自动滚动到对话列表的底部)
114+
- Option to request conversations without historical records (click on the icon on the left side of the input box to toggle). (请求时可不带历史对话记录)
115+
- Support for additional languages (Traditional Chinese, Korean, Japanese, French, German, Russian, etc.). (支持更多语言(繁体中文、韩文、日文、法语、德语、俄语等))
116+
104117
v2.2:
105118
- Increased request timeout from 30 seconds to 60 seconds.(请求超时从 30 秒增加到 60 秒。)
106119
- When sending dialog context, only send the first three Q&A rounds, and submit only the first 100 characters of the answer.(发送对话上下文时,只发送提问的前三轮问答,且答案只提交前100个字。)

iChatGPT.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@
569569
CODE_SIGN_IDENTITY = "Apple Development";
570570
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
571571
CODE_SIGN_STYLE = Manual;
572-
CURRENT_PROJECT_VERSION = 2023.04.05;
572+
CURRENT_PROJECT_VERSION = 2023.04.12;
573573
DEVELOPMENT_ASSET_PATHS = "\"iChatGPT/Preview Content\"";
574574
DEVELOPMENT_TEAM = "";
575575
ENABLE_PREVIEWS = YES;
@@ -587,7 +587,7 @@
587587
"$(inherited)",
588588
"@executable_path/Frameworks",
589589
);
590-
MARKETING_VERSION = 2.4;
590+
MARKETING_VERSION = 2.5;
591591
PRODUCT_BUNDLE_IDENTIFIER = com.37iOS.iChatGPT;
592592
PRODUCT_NAME = "$(TARGET_NAME)";
593593
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -609,7 +609,7 @@
609609
CODE_SIGN_IDENTITY = "Apple Development";
610610
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
611611
CODE_SIGN_STYLE = Manual;
612-
CURRENT_PROJECT_VERSION = 2023.04.05;
612+
CURRENT_PROJECT_VERSION = 2023.04.12;
613613
DEVELOPMENT_ASSET_PATHS = "\"iChatGPT/Preview Content\"";
614614
DEVELOPMENT_TEAM = "";
615615
ENABLE_PREVIEWS = YES;
@@ -627,7 +627,7 @@
627627
"$(inherited)",
628628
"@executable_path/Frameworks",
629629
);
630-
MARKETING_VERSION = 2.4;
630+
MARKETING_VERSION = 2.5;
631631
PRODUCT_BUNDLE_IDENTIFIER = com.37iOS.iChatGPT;
632632
PRODUCT_NAME = "$(TARGET_NAME)";
633633
PROVISIONING_PROFILE_SPECIFIER = "";

iChatGPT/AIChatView.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct AIChatView: View {
4747
})
4848
}
4949
.sheet(isPresented: $inputModel.isConfigChatRoom) {
50-
ChatRoomConfigView(isKeyPresented: $inputModel.isConfigChatRoom)
50+
ChatRoomConfigView(isKeyPresented: $inputModel.isConfigChatRoom, chatModel: chatModel)
5151
}
5252
.sheet(isPresented: $isSharing) {
5353
ActivityView(activityItems: $shareContent.activityItems)
@@ -192,12 +192,12 @@ extension AIChatView {
192192
}
193193

194194
func ShareContents() -> Alert {
195-
Alert(title: Text("Share"),
196-
message: Text("Choose a sharing format"),
197-
primaryButton: .default(Text("Image")) {
195+
Alert(title: Text("Share".localized()),
196+
message: Text("Choose a sharing format".localized()),
197+
primaryButton: .default(Text("Image".localized())) {
198198
screenshotAndShare(isImage: true)
199199
},
200-
secondaryButton: .default(Text("PDF")) {
200+
secondaryButton: .default(Text("PDF".localized())) {
201201
screenshotAndShare(isImage: false)
202202
}
203203
)

iChatGPT/ChatHistoryListView.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,21 @@ struct ChatHistoryListView: View {
8383
VStack(alignment: .leading) {
8484

8585
HStack() {
86-
Text(item.roomID.formatTimestamp())
86+
Text(item.roomName ?? item.roomID.formatTimestamp())
8787
.font(.headline)
8888

8989
Spacer()
9090

91+
if item.roomID == chatModel.roomID {
92+
Text(" \("Current Chat".localized()) ")
93+
.font(.footnote)
94+
.foregroundColor(.white)
95+
.padding([.top, .bottom], 3)
96+
.padding([.leading, .trailing], 4)
97+
.background(Color.red.opacity(0.8))
98+
.clipShape(Capsule())
99+
}
100+
91101
Text(" \(ChatMessageStore.shared.messages(forRoom: item.roomID).count) ")
92102
.font(.footnote)
93103
.foregroundColor(.white)

iChatGPT/ChatInputView.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ struct ChatInputView: View {
3030
.padding(.trailing, 5)
3131
.foregroundColor(.lightGray)
3232
.buttonStyle(PlainButtonStyle())
33-
.disabled(!chatModel.contents.filter({ $0.isResponse == false }).isEmpty)
3433

3534
if !chatModel.contents.isEmpty {
3635
Button(action: {
@@ -72,7 +71,6 @@ struct ChatInputView: View {
7271
.padding(.trailing, 5)
7372
.foregroundColor(.lightGray)
7473
.buttonStyle(PlainButtonStyle())
75-
.disabled(!chatModel.contents.filter({ $0.isResponse == false }).isEmpty)
7674

7775
Button(action: {
7876
model.isConfigChatRoom.toggle()
@@ -82,7 +80,6 @@ struct ChatInputView: View {
8280
.padding(.trailing, 8)
8381
.foregroundColor(.lightGray)
8482
.buttonStyle(PlainButtonStyle())
85-
.disabled(!chatModel.contents.filter({ $0.isResponse == false }).isEmpty)
8683

8784
if !chatModel.contents.isEmpty {
8885
Button(action: {

iChatGPT/ChatRoomConfigView.swift

Lines changed: 130 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,156 @@
77
//
88

99
import SwiftUI
10+
import Combine
11+
import SwiftUIX
1012

1113
struct ChatRoomConfigView: View {
1214

1315
@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+
}
1439

1540
var body: some View {
1641
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")
1951
}
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()
2567
}
68+
.onChange(of: [roomName, prompt, temperature, historyCount, model]) { _ in
69+
self.isDirty = true
70+
}
71+
.gesture(
72+
TapGesture().onEnded {
73+
hideKeyboard()
74+
}
75+
)
2676
}
2777
}
2878

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+
29110
private func onCloseButtonTapped() {
30111
isKeyPresented = false
31112
}
113+
114+
/// 当用户点击其他区域时隐藏软键盘
115+
private func hideKeyboard() {
116+
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
117+
}
32118
}
33119

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+
}
34156

35157
struct ChatRoomConfigView_Previews: PreviewProvider {
36158
static var previews: some View {
37-
ChatRoomConfigView(isKeyPresented: .constant(true))
159+
ChatRoomConfigView(isKeyPresented: .constant(true), chatModel: AIChatModel(roomID: nil))
38160
}
39161
}
40162

iChatGPT/Models/AIChatModel.swift

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,19 @@ class AIChatModel: ObservableObject {
3232
}
3333
/// room id
3434
var roomID: String
35-
/// api model
36-
var apiModel: String {
37-
didSet {
38-
saveRoomConfigData()
39-
}
40-
}
4135
/// 更新 token 时更新请求的会话
4236
var isRefreshSession: Bool = false
4337
private var bot: Chatbot?
4438

4539
init(roomID: String?) {
4640
let roomID = roomID ?? String(Int(Date().timeIntervalSince1970))
4741
self.roomID = roomID
48-
if let room = ChatRoomStore.shared.chatRoom(roomID) {
49-
apiModel = room.model ?? UserDefaults.standard.string(forKey: ChatGPTModelName) ?? "gpt-3.5-turbo"
42+
if ChatRoomStore.shared.chatRoom(roomID) != nil {
5043
let messages = ChatMessageStore.shared.messages(forRoom: roomID)
5144
contents.append(contentsOf: messages)
5245
} else {
53-
apiModel = UserDefaults.standard.string(forKey: ChatGPTModelName) ?? "gpt-3.5-turbo"
54-
ChatRoomStore.shared.addChatRoom(ChatRoom(roomID: roomID))
46+
let model = UserDefaults.standard.string(forKey: ChatGPTModelName) ?? "gpt-3.5-turbo"
47+
ChatRoomStore.shared.addChatRoom(ChatRoom(roomID: roomID, model: model))
5548
}
5649
loadChatbot()
5750
}
@@ -60,8 +53,8 @@ class AIChatModel: ObservableObject {
6053
let newRoomID = roomID ?? String(Int(Date().timeIntervalSince1970))
6154
self.roomID = newRoomID
6255
self.contents = ChatMessageStore.shared.messages(forRoom: newRoomID)
63-
apiModel = UserDefaults.standard.string(forKey: ChatGPTModelName) ?? "gpt-3.5-turbo"
64-
let room = ChatRoomStore.shared.chatRoom(newRoomID) ?? ChatRoom(roomID: newRoomID)
56+
let model = UserDefaults.standard.string(forKey: ChatGPTModelName) ?? "gpt-3.5-turbo"
57+
let room = ChatRoomStore.shared.chatRoom(newRoomID) ?? ChatRoom(roomID: newRoomID, model: model)
6558
ChatRoomStore.shared.addChatRoom(room)
6659
loadChatbot()
6760
}
@@ -70,27 +63,30 @@ class AIChatModel: ObservableObject {
7063
if isRefreshSession {
7164
loadChatbot()
7265
}
73-
let index = contents.count
7466
let userAvatarUrl = self.bot?.getUserAvatar() ?? ""
67+
let roomModel = ChatRoomStore.shared.chatRoom(roomID)
7568
let model = UserDefaults.standard.string(forKey: ChatGPTModelName) ?? "gpt-3.5-turbo"
7669
var chat = AIChat(datetime: Date().currentDateString(), issue: prompt, model: model, userAvatarUrl: userAvatarUrl)
7770
contents.append(chat)
7871
isScrollListBottom.toggle()
7972

80-
self.bot?.getChatGPTAnswer(prompts: contents, sendContext: isSendContext) { answer in
73+
self.bot?.getChatGPTAnswer(prompts: contents, sendContext: isSendContext, roomModel: roomModel) { answer in
8174
let content = answer
8275
DispatchQueue.main.async { [self] in
8376
chat.answer = content
8477
chat.isResponse = true
85-
contents[index] = chat
78+
// 找到要替换的元素在数组中的索引位置
79+
if let index = contents.lastIndex(where: { $0.datetime == chat.datetime && $0.issue == chat.issue }) {
80+
contents[index] = chat
81+
}
8682
}
8783
}
8884
}
8985

9086
func loadChatbot() {
9187
isRefreshSession = false
9288
let chatGPTOpenAIKey = UserDefaults.standard.string(forKey: ChatGPTOpenAIKey) ?? ""
93-
bot = Chatbot( openAIKey: chatGPTOpenAIKey)
89+
bot = Chatbot(openAIKey: chatGPTOpenAIKey)
9490
}
9591

9692
func saveMessagesData() {

0 commit comments

Comments
 (0)