mirror of
https://github.com/MustangYM/OSXChatGpt.git
synced 2025-11-25 11:29:43 +08:00
add cloud more Data
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
CB0F5A6029D059C4005B71D2 /* SplashCodeSyntaxHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0F5A5E29D059C4005B71D2 /* SplashCodeSyntaxHighlighter.swift */; };
|
CB0F5A6029D059C4005B71D2 /* SplashCodeSyntaxHighlighter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0F5A5E29D059C4005B71D2 /* SplashCodeSyntaxHighlighter.swift */; };
|
||||||
CB1DCAC629B4F09F00B1D4E1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB1DCAC529B4F09F00B1D4E1 /* Assets.xcassets */; };
|
CB1DCAC629B4F09F00B1D4E1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB1DCAC529B4F09F00B1D4E1 /* Assets.xcassets */; };
|
||||||
CB1DCAC929B4F09F00B1D4E1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB1DCAC829B4F09F00B1D4E1 /* Preview Assets.xcassets */; };
|
CB1DCAC929B4F09F00B1D4E1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB1DCAC829B4F09F00B1D4E1 /* Preview Assets.xcassets */; };
|
||||||
|
CB1F1DD029DDBA0B008CFD0B /* AIPromptPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB1F1DCF29DDBA0B008CFD0B /* AIPromptPopView.swift */; };
|
||||||
CB2449F829D721F3006EE829 /* SystemManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2449F729D721F3006EE829 /* SystemManager.swift */; };
|
CB2449F829D721F3006EE829 /* SystemManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2449F729D721F3006EE829 /* SystemManager.swift */; };
|
||||||
CB2449FA29D7FE38006EE829 /* ServerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2449F929D7FE38006EE829 /* ServerManager.swift */; };
|
CB2449FA29D7FE38006EE829 /* ServerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB2449F929D7FE38006EE829 /* ServerManager.swift */; };
|
||||||
CB27655C29D1C12C00897E0E /* MarkdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB27655B29D1C12C00897E0E /* MarkdownView.swift */; };
|
CB27655C29D1C12C00897E0E /* MarkdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB27655B29D1C12C00897E0E /* MarkdownView.swift */; };
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
CB1DCAC529B4F09F00B1D4E1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
CB1DCAC529B4F09F00B1D4E1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
CB1DCAC829B4F09F00B1D4E1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
CB1DCAC829B4F09F00B1D4E1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||||
CB1DCACA29B4F09F00B1D4E1 /* OSXChatGPT.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OSXChatGPT.entitlements; sourceTree = "<group>"; };
|
CB1DCACA29B4F09F00B1D4E1 /* OSXChatGPT.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OSXChatGPT.entitlements; sourceTree = "<group>"; };
|
||||||
|
CB1F1DCF29DDBA0B008CFD0B /* AIPromptPopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AIPromptPopView.swift; sourceTree = "<group>"; };
|
||||||
CB228EA129CD4949006B3559 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
CB228EA129CD4949006B3559 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||||
CB2449F729D721F3006EE829 /* SystemManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemManager.swift; sourceTree = "<group>"; };
|
CB2449F729D721F3006EE829 /* SystemManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemManager.swift; sourceTree = "<group>"; };
|
||||||
CB2449F929D7FE38006EE829 /* ServerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerManager.swift; sourceTree = "<group>"; };
|
CB2449F929D7FE38006EE829 /* ServerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerManager.swift; sourceTree = "<group>"; };
|
||||||
@@ -136,6 +138,7 @@
|
|||||||
CB2F972129CED6AE004EBD96 /* ChatRoomInputView.swift */,
|
CB2F972129CED6AE004EBD96 /* ChatRoomInputView.swift */,
|
||||||
182B436429BC5C8700F06778 /* UserInitializeView.swift */,
|
182B436429BC5C8700F06778 /* UserInitializeView.swift */,
|
||||||
CB27656529D1DA9800897E0E /* AIPromptView.swift */,
|
CB27656529D1DA9800897E0E /* AIPromptView.swift */,
|
||||||
|
CB1F1DCF29DDBA0B008CFD0B /* AIPromptPopView.swift */,
|
||||||
CB27657429D33D7A00897E0E /* AIPromptInputView.swift */,
|
CB27657429D33D7A00897E0E /* AIPromptInputView.swift */,
|
||||||
182B436129BC5C8700F06778 /* View.swift */,
|
182B436129BC5C8700F06778 /* View.swift */,
|
||||||
182B437A29BC5FBE00F06778 /* EnterAPIView.swift */,
|
182B437A29BC5FBE00F06778 /* EnterAPIView.swift */,
|
||||||
@@ -348,6 +351,7 @@
|
|||||||
CB2F972829CEFB65004EBD96 /* ChatRoomToolBar.swift in Sources */,
|
CB2F972829CEFB65004EBD96 /* ChatRoomToolBar.swift in Sources */,
|
||||||
CBC4B12329B8D28D00650296 /* Message+CoreDataClass.swift in Sources */,
|
CBC4B12329B8D28D00650296 /* Message+CoreDataClass.swift in Sources */,
|
||||||
CB27657329D30F1400897E0E /* AIPromptViewMdoel.swift in Sources */,
|
CB27657329D30F1400897E0E /* AIPromptViewMdoel.swift in Sources */,
|
||||||
|
CB1F1DD029DDBA0B008CFD0B /* AIPromptPopView.swift in Sources */,
|
||||||
CB27655C29D1C12C00897E0E /* MarkdownView.swift in Sources */,
|
CB27655C29D1C12C00897E0E /* MarkdownView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ class AIPromptSessionViewMdoel: ObservableObject {
|
|||||||
@Published var selectedItem :Prompt?
|
@Published var selectedItem :Prompt?
|
||||||
|
|
||||||
func fetchAllPrompts(session: Conversation) {
|
func fetchAllPrompts(session: Conversation) {
|
||||||
let completedDateSort = NSSortDescriptor(keyPath: \Prompt.createdDate, ascending: false)
|
let request: NSFetchRequest<Prompt> = Prompt.fetchRequest()
|
||||||
var aa: [Prompt] = CoreDataManager.shared.fetch("Prompt", sorting: [completedDateSort])
|
request.predicate = NSPredicate(format: "type == %d", 3)
|
||||||
if (aa.count == 0) {
|
let timestampSortDescriptor = NSSortDescriptor(key: "createdDate", ascending: false)
|
||||||
aa = AIPromptSessionViewMdoel.createDefaultPrompt()
|
request.sortDescriptors = [timestampSortDescriptor]
|
||||||
}
|
|
||||||
|
var aa: [Prompt] = CoreDataManager.shared.fetch(request: request)
|
||||||
|
|
||||||
if let prompt = session.prompt {
|
if let prompt = session.prompt {
|
||||||
if aa.contains(where: {$0.id == prompt.id && $0.type != 1}) {
|
if aa.contains(where: {$0.id == prompt.id && $0.type != 1}) {
|
||||||
selectedItem = prompt
|
selectedItem = prompt
|
||||||
@@ -35,88 +37,31 @@ class AIPromptSessionViewMdoel: ObservableObject {
|
|||||||
}
|
}
|
||||||
CoreDataManager.shared.saveData()
|
CoreDataManager.shared.saveData()
|
||||||
allPrompts = aa
|
allPrompts = aa
|
||||||
|
|
||||||
// 获取云端数据
|
|
||||||
HTTPClient.getPrompt { [weak self] datas, err in
|
|
||||||
print("获取云端数据成功")
|
|
||||||
guard let self = self else { return }
|
|
||||||
var temp: [Prompt] = []
|
|
||||||
datas.forEach { json in
|
|
||||||
if let jsonData = json as? [String: Any] {
|
|
||||||
if let idString = jsonData["idString"] as? String {
|
|
||||||
if !self.allPrompts.contains(where: {$0.idString == idString}) {
|
|
||||||
let p = Prompt(context: CoreDataManager.shared.container.viewContext)
|
|
||||||
p.id = UUID(uuidString: idString)
|
|
||||||
p.createdDate = Date()
|
|
||||||
p.author = jsonData["author"] as? String
|
|
||||||
p.title = jsonData["title"] as? String
|
|
||||||
p.prompt = jsonData["prompt"] as? String
|
|
||||||
p.hexColor = NSColor.randomColor().toHexString()
|
|
||||||
CoreDataManager.shared.saveData()
|
|
||||||
temp.append(p)
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
let p = Prompt(context: CoreDataManager.shared.container.viewContext)
|
|
||||||
p.id = UUID()
|
|
||||||
p.createdDate = Date()
|
|
||||||
p.author = jsonData["author"] as? String
|
|
||||||
p.title = jsonData["title"] as? String
|
|
||||||
p.prompt = jsonData["prompt"] as? String
|
|
||||||
p.hexColor = NSColor.randomColor().toHexString()
|
|
||||||
CoreDataManager.shared.saveData()
|
|
||||||
temp.append(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if temp.count > 0 {
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.allPrompts += temp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deletePrompt(prompt: Prompt) {
|
func deletePrompt(prompt: Prompt) {
|
||||||
if prompt.type == 1 {
|
if prompt.type == 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
allPrompts.removeAll(where: {$0.id == prompt.id})
|
prompt.type = 2
|
||||||
|
if let idx = allPrompts.firstIndex(where: {$0.id == prompt.id}) {
|
||||||
|
allPrompts[idx].type = 2
|
||||||
|
}
|
||||||
|
allPrompts.removeAll(where: {$0.type == 2 })
|
||||||
if prompt.id == selectedItem?.id {
|
if prompt.id == selectedItem?.id {
|
||||||
selectedItem = allPrompts.first
|
selectedItem = allPrompts.first
|
||||||
}
|
}
|
||||||
CoreDataManager.shared.delete(object: prompt)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func createDefaultPrompt() -> [Prompt] {
|
|
||||||
var temp: [Prompt] = []
|
|
||||||
let prompt1 = Prompt(context: CoreDataManager.shared.container.viewContext)
|
|
||||||
prompt1.id = UUID()
|
|
||||||
prompt1.createdDate = Date()
|
|
||||||
prompt1.title = "翻译"
|
|
||||||
prompt1.prompt = "翻译我说的任何中文或英文。只返回翻译结果,不解释它"
|
|
||||||
prompt1.hexColor = NSColor.randomColor().toHexString()
|
|
||||||
temp.append(prompt1)
|
|
||||||
|
|
||||||
|
|
||||||
CoreDataManager.shared.saveData()
|
CoreDataManager.shared.saveData()
|
||||||
return temp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AIPromptViewMdoel: ObservableObject {
|
class AIPromptViewMdoel: ObservableObject {
|
||||||
let isSession: Bool
|
|
||||||
@Published var allPrompts: [Prompt] = []
|
@Published var allPrompts: [Prompt] = []
|
||||||
@Published var prompts: [Prompt] = []
|
@Published var prompts: [Prompt] = []
|
||||||
|
|
||||||
init(isSession: Bool) {
|
init() {
|
||||||
self.isSession = isSession
|
fetchAllPrompts()
|
||||||
if isSession {
|
|
||||||
fetchPrompts()
|
|
||||||
}else {
|
|
||||||
fetchAllPrompts()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static func randomColor() -> Color {
|
static func randomColor() -> Color {
|
||||||
@@ -134,20 +79,111 @@ class AIPromptViewMdoel: ObservableObject {
|
|||||||
prompt.author = author
|
prompt.author = author
|
||||||
prompt.id = UUID()
|
prompt.id = UUID()
|
||||||
prompt.createdDate = Date()
|
prompt.createdDate = Date()
|
||||||
|
prompt.type = 2
|
||||||
|
allPrompts.insert(prompt, at: 0)
|
||||||
CoreDataManager.shared.saveData()
|
CoreDataManager.shared.saveData()
|
||||||
if isToggleOn {
|
if isToggleOn {
|
||||||
HTTPClient.uploadPrompt(prompt: prompt)
|
HTTPClient.uploadPrompt(prompt: prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func updatePrompt(prompt: Prompt, isToggleOn: Bool) {
|
||||||
|
if let idx = allPrompts.firstIndex(where: {$0.id == prompt.id}) {
|
||||||
|
allPrompts[idx] = prompt
|
||||||
|
}else {
|
||||||
|
allPrompts.append(prompt)
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreDataManager.shared.saveData()
|
||||||
|
if isToggleOn {
|
||||||
|
HTTPClient.uploadPrompt(prompt: prompt)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func deletePrompt(prompt: Prompt) {
|
||||||
|
allPrompts.removeAll(where: {$0.id == prompt.id})
|
||||||
|
CoreDataManager.shared.delete(object: prompt)
|
||||||
|
CoreDataManager.shared.saveData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AIPromptViewMdoel {
|
extension AIPromptViewMdoel {
|
||||||
private func fetchAllPrompts() {
|
private func fetchAllPrompts() {
|
||||||
let completedDateSort = NSSortDescriptor(keyPath: \Prompt.serial, ascending: false)
|
//删除云端数据
|
||||||
let aa: [Prompt] = CoreDataManager.shared.fetch("Prompt", sorting: [completedDateSort])
|
let deleteRequest: NSFetchRequest<Prompt> = Prompt.fetchRequest()
|
||||||
|
deleteRequest.predicate = NSPredicate(format: "type == 0")
|
||||||
|
CoreDataManager.shared.delete(request: deleteRequest)
|
||||||
|
|
||||||
|
//检索本地自定义数据
|
||||||
|
let request: NSFetchRequest<Prompt> = Prompt.fetchRequest()
|
||||||
|
let type2Predicate = NSPredicate(format: "type == %d", 2)
|
||||||
|
let type3Predicate = NSPredicate(format: "type == %d", 3)
|
||||||
|
let compoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [type2Predicate, type3Predicate])
|
||||||
|
request.predicate = compoundPredicate
|
||||||
|
|
||||||
|
|
||||||
|
let typeSortDescriptor = NSSortDescriptor(key: "type", ascending: false)
|
||||||
|
let timestampSortDescriptor = NSSortDescriptor(key: "createdDate", ascending: false)
|
||||||
|
request.sortDescriptors = [typeSortDescriptor, timestampSortDescriptor]
|
||||||
|
var aa: [Prompt] = CoreDataManager.shared.fetch(request: request)
|
||||||
|
|
||||||
|
//移除无效数据
|
||||||
|
let remove = aa.filter { $0.title == nil || $0.prompt == nil || $0.id == nil}
|
||||||
|
CoreDataManager.shared.delete(objects: remove)
|
||||||
|
aa.removeAll { $0.title == nil || $0.prompt == nil || $0.id == nil }
|
||||||
|
|
||||||
|
//赋值
|
||||||
allPrompts = aa
|
allPrompts = aa
|
||||||
|
|
||||||
|
|
||||||
|
// 获取云端数据
|
||||||
|
HTTPClient.getPrompt { [weak self] datas, err in
|
||||||
|
print("云端数据请求成功")
|
||||||
|
guard let self = self else { return }
|
||||||
|
var temp: [Prompt] = []
|
||||||
|
datas.forEach { json in
|
||||||
|
if let jsonData = json as? [String: Any] {
|
||||||
|
if let idString = jsonData["idString"] as? String {
|
||||||
|
if !self.allPrompts.contains(where: {$0.idString == idString}) {
|
||||||
|
let p = Prompt(context: CoreDataManager.shared.container.viewContext)
|
||||||
|
p.id = UUID(uuidString: idString)
|
||||||
|
p.type = 0
|
||||||
|
p.createdDate = Date()
|
||||||
|
p.author = jsonData["author"] as? String
|
||||||
|
p.title = jsonData["title"] as? String
|
||||||
|
p.prompt = jsonData["prompt"] as? String
|
||||||
|
p.hexColor = NSColor.randomColor().toHexString()
|
||||||
|
p.cloudId = jsonData["cloudId"] as? Int32 ?? 0
|
||||||
|
CoreDataManager.shared.saveData()
|
||||||
|
temp.append(p)
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
let p = Prompt(context: CoreDataManager.shared.container.viewContext)
|
||||||
|
p.id = UUID()
|
||||||
|
p.type = 0
|
||||||
|
p.createdDate = Date()
|
||||||
|
p.author = jsonData["author"] as? String
|
||||||
|
p.title = jsonData["title"] as? String
|
||||||
|
p.prompt = jsonData["prompt"] as? String
|
||||||
|
p.cloudId = jsonData["cloudId"] as? Int32 ?? 0
|
||||||
|
p.hexColor = NSColor.randomColor().toHexString()
|
||||||
|
CoreDataManager.shared.saveData()
|
||||||
|
temp.append(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if temp.count > 0 {
|
||||||
|
self.allPrompts.forEach { p in
|
||||||
|
temp.removeAll(where: {$0.cloudId == p.cloudId})
|
||||||
|
}
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.allPrompts += temp
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
print("获取云端数据失败!!!需要更新token")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchPrompts() {
|
private func fetchPrompts() {
|
||||||
|
|||||||
@@ -427,9 +427,9 @@ extension ViewModel {
|
|||||||
func fetchConversations() {
|
func fetchConversations() {
|
||||||
let completedDateSort = NSSortDescriptor(keyPath: \Conversation.updateData, ascending: false)
|
let completedDateSort = NSSortDescriptor(keyPath: \Conversation.updateData, ascending: false)
|
||||||
var aa: [Conversation] = CoreDataManager.shared.fetch("Conversation", sorting: [completedDateSort])
|
var aa: [Conversation] = CoreDataManager.shared.fetch("Conversation", sorting: [completedDateSort])
|
||||||
let remove = aa.filter { $0.lastMessage == nil}
|
let remove = aa.filter { $0.lastMessage == nil && $0.prompt == nil }
|
||||||
CoreDataManager.shared.delete(objects: remove)
|
CoreDataManager.shared.delete(objects: remove)
|
||||||
aa.removeAll { $0.lastMessage == nil}
|
aa.removeAll { $0.lastMessage == nil && $0.prompt == nil}
|
||||||
conversations = aa
|
conversations = aa
|
||||||
}
|
}
|
||||||
private func fetchConversation(sesstionId: String) -> Conversation? {
|
private func fetchConversation(sesstionId: String) -> Conversation? {
|
||||||
|
|||||||
@@ -26,4 +26,5 @@ public class Prompt: NSManagedObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import Foundation
|
|||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extension Prompt {
|
extension Prompt {
|
||||||
|
|
||||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<Prompt> {
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<Prompt> {
|
||||||
@@ -25,6 +27,7 @@ extension Prompt {
|
|||||||
@NSManaged public var type: Int16
|
@NSManaged public var type: Int16
|
||||||
@NSManaged public var hexColor: String?
|
@NSManaged public var hexColor: String?
|
||||||
@NSManaged public var sesstion: NSSet?
|
@NSManaged public var sesstion: NSSet?
|
||||||
|
@NSManaged public var cloudId: Int32
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -285,19 +285,22 @@ extension HTTPClient {
|
|||||||
code = response.statusCode
|
code = response.statusCode
|
||||||
}
|
}
|
||||||
if let data = data,
|
if let data = data,
|
||||||
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
||||||
let base64Str = json["content"] as? String {
|
if let base64Str = json["content"] as? String {
|
||||||
let base64String = base64Str.replacingOccurrences(of: "\n", with: "")
|
let base64String = base64Str.replacingOccurrences(of: "\n", with: "")
|
||||||
if let da = NSData(base64Encoded: base64String, options: NSData.Base64DecodingOptions.init(rawValue: 0)),
|
if let da = NSData(base64Encoded: base64String, options: NSData.Base64DecodingOptions.init(rawValue: 0)),
|
||||||
let dataString = String(data: da as Data, encoding: .utf8),
|
let dataString = String(data: da as Data, encoding: .utf8),
|
||||||
let jsonData = dataString.data(using: .utf8),
|
let jsonData = dataString.data(using: .utf8),
|
||||||
let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [Any] {
|
let jsonObject = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [Any] {
|
||||||
callback(jsonObject, nil)
|
callback(jsonObject, nil)
|
||||||
|
}else {
|
||||||
|
callback([], "data error code:\(code)")
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
|
//获取不到数据,需要更新token
|
||||||
callback([], "data error code:\(code)")
|
callback([], "data error code:\(code)")
|
||||||
|
|
||||||
}
|
}
|
||||||
}else {
|
|
||||||
callback([], "data error code:\(code)")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
task.resume()
|
task.resume()
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
</entity>
|
</entity>
|
||||||
<entity name="Prompt" representedClassName=".Prompt" syncable="YES">
|
<entity name="Prompt" representedClassName=".Prompt" syncable="YES">
|
||||||
<attribute name="author" optional="YES" attributeType="String"/>
|
<attribute name="author" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="cloudId" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||||
<attribute name="createdDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="createdDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<attribute name="hexColor" optional="YES" attributeType="String"/>
|
<attribute name="hexColor" optional="YES" attributeType="String"/>
|
||||||
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
|
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct AIPromptInputView: View {
|
struct AIPromptInputView: View {
|
||||||
@StateObject var viewModel = AIPromptViewMdoel(isSession: true)
|
@StateObject var viewModel: AIPromptViewMdoel
|
||||||
@Binding var isPresented: Bool
|
@Binding var isPresented: Bool
|
||||||
@State private var title: String = ""
|
@State private var title: String = ""
|
||||||
@State private var prompt: String = ""
|
@State private var content: String = ""
|
||||||
@State private var author: String = ""
|
@State private var author: String = ""
|
||||||
@State private var isToggleOn: Bool = true
|
@State private var isToggleOn: Bool = true
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
@@ -22,7 +22,7 @@ struct AIPromptInputView: View {
|
|||||||
VStack {
|
VStack {
|
||||||
VStack {
|
VStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Text("自定义提示")
|
Text("自定义添加")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.9) :.black.opacity(0.9))
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.9) :.black.opacity(0.9))
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -73,7 +73,7 @@ struct AIPromptInputView: View {
|
|||||||
}.padding(.top, 5)
|
}.padding(.top, 5)
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
TextEditor(text: $prompt)
|
TextEditor(text: $content)
|
||||||
.font(Font.system(size: 13))
|
.font(Font.system(size: 13))
|
||||||
.padding(8)
|
.padding(8)
|
||||||
.background((colorScheme == .dark) ? .gray.opacity(0.1) :.white.opacity(0.9))
|
.background((colorScheme == .dark) ? .gray.opacity(0.1) :.white.opacity(0.9))
|
||||||
@@ -90,12 +90,12 @@ struct AIPromptInputView: View {
|
|||||||
.padding(.leading, 20)
|
.padding(.leading, 20)
|
||||||
.padding(.bottom, 0)
|
.padding(.bottom, 0)
|
||||||
.frame(height: 18)
|
.frame(height: 18)
|
||||||
Text("(选填)")
|
// Text("(选填)")
|
||||||
.font(Font.system(size: 11))
|
// .font(Font.system(size: 11))
|
||||||
.padding(.top, 5)
|
// .padding(.top, 5)
|
||||||
.foregroundColor(.gray.opacity(0.6))
|
// .foregroundColor(.gray.opacity(0.6))
|
||||||
.frame(height: 18)
|
// .frame(height: 18)
|
||||||
Text("后台审核通过后可分享给其他人")
|
Text("分享您的修饰语到词库")
|
||||||
.font(Font.system(size: 10))
|
.font(Font.system(size: 10))
|
||||||
.padding(.top, 5)
|
.padding(.top, 5)
|
||||||
.foregroundColor(.gray.opacity(0.6))
|
.foregroundColor(.gray.opacity(0.6))
|
||||||
@@ -119,7 +119,7 @@ struct AIPromptInputView: View {
|
|||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
Toggle("是否上传至云端", isOn: $isToggleOn)
|
Toggle("是否分享", isOn: $isToggleOn)
|
||||||
.padding()
|
.padding()
|
||||||
.foregroundColor(.gray)
|
.foregroundColor(.gray)
|
||||||
.font(Font.system(size: 13))
|
.font(Font.system(size: 13))
|
||||||
@@ -132,7 +132,11 @@ struct AIPromptInputView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
viewModel.addPrompt(title: title, content: prompt, author: author, isToggleOn: isToggleOn)
|
if title.isEmpty || content.isEmpty {
|
||||||
|
self.isPresented = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
viewModel.addPrompt(title: title, content: content, author: author, isToggleOn: isToggleOn)
|
||||||
self.isPresented = false
|
self.isPresented = false
|
||||||
|
|
||||||
} label: {
|
} label: {
|
||||||
|
|||||||
154
OSXChatGPT/OSXChatGPT/WindowView/AIPromptPopView.swift
Normal file
154
OSXChatGPT/OSXChatGPT/WindowView/AIPromptPopView.swift
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
//
|
||||||
|
// AIPromptPopView.swift
|
||||||
|
// OSXChatGPT
|
||||||
|
//
|
||||||
|
// Created by CoderChan on 2023/4/5.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct AIPromptPopView: View {
|
||||||
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
@EnvironmentObject var viewModel: ViewModel
|
||||||
|
@StateObject var data = AIPromptSessionViewMdoel()
|
||||||
|
@Binding var showInputView: Bool
|
||||||
|
@Binding var showPopover: Bool
|
||||||
|
@State private var isPresented = false
|
||||||
|
|
||||||
|
var titleColor: Color {
|
||||||
|
switch colorScheme {
|
||||||
|
case .dark:
|
||||||
|
return Color.white.opacity(0.9)
|
||||||
|
default:
|
||||||
|
return Color.black.opacity(0.9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
Text("选择提示")
|
||||||
|
.font(.title3)
|
||||||
|
.foregroundColor(titleColor)
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
}
|
||||||
|
HStack {
|
||||||
|
Button {
|
||||||
|
if let prompt = data.selectedItem {
|
||||||
|
viewModel.updateConversation(sesstionId: viewModel.currentConversation!.sesstionId, prompt: prompt)
|
||||||
|
}
|
||||||
|
self.showPopover = false
|
||||||
|
} label: {
|
||||||
|
Text("确定")
|
||||||
|
}.padding(10)
|
||||||
|
Spacer()
|
||||||
|
Button {
|
||||||
|
self.showPopover = false
|
||||||
|
withAnimation {
|
||||||
|
viewModel.currentConversation = nil
|
||||||
|
viewModel.showAIPrompt = true
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Text("词库")
|
||||||
|
}
|
||||||
|
.padding(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List(data.allPrompts) { item in
|
||||||
|
AIPromptPopCellView(item: item, isSelected: data.selectedItem == item)
|
||||||
|
.onTapGesture {
|
||||||
|
data.selectedItem = item
|
||||||
|
}
|
||||||
|
.contextMenu {
|
||||||
|
Button(action: {
|
||||||
|
withAnimation {
|
||||||
|
data.deletePrompt(prompt: item)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("移除快捷方式")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.frame(width: 560, height: 380)
|
||||||
|
.onAppear {
|
||||||
|
if let conversation = viewModel.currentConversation {
|
||||||
|
data.fetchAllPrompts(session: conversation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AIPromptPopCellView: View {
|
||||||
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
let item: Prompt
|
||||||
|
let isSelected: Bool
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
if self.isSelected {
|
||||||
|
Image(systemName: "checkmark.square.fill")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.background(Color.blue)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.padding(5)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Circle()
|
||||||
|
.stroke(Color.blue, lineWidth: 1)
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.padding(5)
|
||||||
|
}
|
||||||
|
if item.type == 1 {
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
HStack {
|
||||||
|
Text("【默认无修饰语】")
|
||||||
|
.font(Font.system(size: 15))
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.padding(.trailing, 6)
|
||||||
|
.padding(.bottom, 6)
|
||||||
|
Text("当前选中的修饰语")
|
||||||
|
.font(Font.system(size: 14))
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.padding(.bottom, 6)
|
||||||
|
Spacer()
|
||||||
|
Text("(没有修饰语请到词库添加)")
|
||||||
|
.font(Font.system(size: 11))
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.padding(.bottom, 6)
|
||||||
|
}
|
||||||
|
Text("每个会话只能选择一个修饰语, 也可以自定义添加修饰语")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.6) : .white)
|
||||||
|
}.padding(.leading, 2)
|
||||||
|
}else {
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
Text(item.title ?? "")
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
.padding(.bottom, 6)
|
||||||
|
Text(item.prompt ?? "")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.6) : .white)
|
||||||
|
}.padding(.leading, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(height: 60)
|
||||||
|
.padding(.vertical, 5)
|
||||||
|
.padding(.horizontal, 10)
|
||||||
|
.background(
|
||||||
|
item.color.brightness((self.colorScheme == .dark) ? -0.5 : -0.2)
|
||||||
|
)
|
||||||
|
.cornerRadius(6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//struct AIPromptPopView_Previews: PreviewProvider {
|
||||||
|
// static var previews: some View {
|
||||||
|
// AIPromptPopView()
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -7,24 +7,144 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
struct AIPromptDetailView: View {
|
||||||
|
let prompt: Prompt
|
||||||
|
@StateObject var data: AIPromptViewMdoel
|
||||||
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
var body: some View {
|
||||||
|
GeometryReader { geometry in
|
||||||
|
ZStack {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
HStack {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(prompt.title ?? "")
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.padding(.bottom, 6)
|
||||||
|
HStack {
|
||||||
|
Button {
|
||||||
|
if prompt.type == 3 {
|
||||||
|
//移除,
|
||||||
|
prompt.type = 2
|
||||||
|
data.updatePrompt(prompt: prompt, isToggleOn: false)
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
}else {
|
||||||
|
//添加,
|
||||||
|
prompt.type = 3
|
||||||
|
data.updatePrompt(prompt: prompt, isToggleOn: false)
|
||||||
|
presentationMode.wrappedValue.dismiss()
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
if prompt.type == 3 {
|
||||||
|
Image(systemName: "minus.square")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 10, height: 10)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding(0)
|
||||||
|
Text("移除快捷方式")
|
||||||
|
.padding(0)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
}else {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "plus.app")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 10, height: 10)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding(0)
|
||||||
|
Text("添加快捷方式")
|
||||||
|
.padding(0)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(EdgeInsets(top: 6, leading: 10, bottom: 6, trailing: 10))
|
||||||
|
|
||||||
|
}
|
||||||
|
.buttonStyle(LinkButtonStyle())
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 20)
|
||||||
|
.stroke(Color.white, lineWidth: 0.5)
|
||||||
|
)
|
||||||
|
|
||||||
|
if prompt.type == 2 {
|
||||||
|
Button {
|
||||||
|
data.deletePrompt(prompt: prompt)
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "trash.slash")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 10, height: 10)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding(0)
|
||||||
|
Text("删除数据")
|
||||||
|
.padding(0)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
}
|
||||||
|
.padding(EdgeInsets(top: 6, leading: 10, bottom: 6, trailing: 10))
|
||||||
|
|
||||||
|
}.buttonStyle(LinkButtonStyle())
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 20)
|
||||||
|
.stroke(Color.white, lineWidth: 0.5)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}.padding(.leading, 6)
|
||||||
|
Spacer()
|
||||||
|
}.padding(.bottom, 10)
|
||||||
|
ScrollView {
|
||||||
|
HStack() {
|
||||||
|
Text(prompt.prompt ?? "")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.6) : .white)
|
||||||
|
.padding(10)
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.frame(width: geometry.size.width - 30, height: geometry.size.height - 120)
|
||||||
|
.background(.white.opacity(0.1))
|
||||||
|
.cornerRadius(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let author = prompt.author {
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Text("\(author)")
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.font(.system(size: 11))
|
||||||
|
.padding(.top, 5)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.frame(width: geometry.size.width, height: geometry.size.height)
|
||||||
|
.cornerRadius(6)
|
||||||
|
.background(
|
||||||
|
prompt.color.brightness((self.colorScheme == .dark) ? -0.5 : -0.2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.frame(width: 500, height: 350)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct AIPromptView: View {
|
struct AIPromptView: View {
|
||||||
let sesstionId: String? //有则表示在会话中打开
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AIPromptPopView: View {
|
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
@EnvironmentObject var viewModel: ViewModel
|
@EnvironmentObject var viewModel: ViewModel
|
||||||
@StateObject var data = AIPromptSessionViewMdoel()
|
@StateObject var data = AIPromptViewMdoel()
|
||||||
@Binding var showInputView: Bool
|
|
||||||
@Binding var showPopover: Bool
|
|
||||||
@State private var isPresented = false
|
@State private var isPresented = false
|
||||||
|
@State private var showInputView = false
|
||||||
|
|
||||||
var titleColor: Color {
|
var titleColor: Color {
|
||||||
switch colorScheme {
|
switch colorScheme {
|
||||||
@@ -36,109 +156,102 @@ struct AIPromptPopView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
GeometryReader { geometry in
|
||||||
VStack {
|
if data.allPrompts.count > 0 {
|
||||||
Spacer()
|
ScrollView {
|
||||||
Text("选择提示")
|
LazyVStack(spacing: 8) {
|
||||||
.font(.title3)
|
ForEach(data.allPrompts) { (item) in
|
||||||
.foregroundColor(titleColor)
|
AIPromptCellView(data: data, item: item)
|
||||||
Spacer()
|
}
|
||||||
|
}
|
||||||
}
|
.background(Color.clear)
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
Button {
|
|
||||||
self.showPopover = false
|
|
||||||
self.showInputView = true
|
|
||||||
} label: {
|
|
||||||
Text("自定义")
|
|
||||||
}
|
}
|
||||||
.padding(10)
|
.padding(.leading, 16)
|
||||||
|
.padding(.trailing, 16)
|
||||||
|
.frame(width: geometry.size.width, height: geometry.size.height - 50)
|
||||||
|
|
||||||
|
.onAppear {
|
||||||
|
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
VStack(alignment: .center) {
|
||||||
|
Text("请点击右上角自定义添加新的修饰语")
|
||||||
|
}.frame(width: geometry.size.width, height: geometry.size.height - 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.padding(.top, 1)
|
||||||
|
.toolbar {
|
||||||
|
Spacer()
|
||||||
|
Button(action: {
|
||||||
|
showInputView.toggle()
|
||||||
|
}) {
|
||||||
|
Image(systemName: "plus")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List(data.allPrompts) { item in
|
.sheet(isPresented: $showInputView) {
|
||||||
AIPromptPopCellView(item: item, isSelected: data.selectedItem == item) {
|
AIPromptInputView(viewModel: data, isPresented: $showInputView)
|
||||||
data.selectedItem = item
|
}
|
||||||
}.contextMenu {
|
|
||||||
Button(action: {
|
|
||||||
data.deletePrompt(prompt: item)
|
|
||||||
}) {
|
|
||||||
Text("删除")
|
|
||||||
}
|
|
||||||
// Button(action: {
|
|
||||||
//
|
|
||||||
// }) {
|
|
||||||
// Text("编辑")
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}.frame(width: 560, height: 380)
|
|
||||||
.onAppear {
|
|
||||||
if let conversation = viewModel.currentConversation {
|
|
||||||
data.fetchAllPrompts(session: conversation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onDisappear {
|
|
||||||
viewModel.updateConversation(sesstionId: viewModel.currentConversation!.sesstionId, prompt: data.selectedItem!)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AIPromptPopCellView: View {
|
struct AIPromptCellView: View {
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
let item: Prompt
|
@StateObject var data: AIPromptViewMdoel
|
||||||
let isSelected: Bool
|
@State private var isTapped = false
|
||||||
let action: () -> Void
|
@State var item: Prompt
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
ZStack {
|
||||||
if self.isSelected {
|
VStack(alignment: .leading) {
|
||||||
Image(systemName: "checkmark.square.fill")
|
HStack {
|
||||||
.resizable()
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
.scaledToFit()
|
HStack {
|
||||||
.frame(width: 20, height: 20)
|
if item.type == 3 {
|
||||||
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
Image(systemName: "checkmark.square")
|
||||||
.background(Color.blue)
|
.resizable()
|
||||||
.clipShape(Circle())
|
.frame(width: 10, height: 10)
|
||||||
.padding(5)
|
.foregroundColor(.white)
|
||||||
|
.padding(.trailing, 0)
|
||||||
} else {
|
}else {
|
||||||
Circle()
|
Image(systemName: "plus.app")
|
||||||
.stroke(Color.blue, lineWidth: 1)
|
.resizable()
|
||||||
.frame(width: 20, height: 20)
|
.frame(width: 10, height: 10)
|
||||||
.padding(5)
|
.foregroundColor(.white)
|
||||||
}
|
.padding(.trailing, 0)
|
||||||
if item.type == 1 {
|
}
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
|
||||||
HStack {
|
Text(item.title ?? "")
|
||||||
Text("【默认无修饰语】")
|
.font(.headline)
|
||||||
.font(Font.system(size: 15))
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
.padding(.leading, 0)
|
||||||
.padding(.trailing, 6)
|
|
||||||
.padding(.bottom, 6)
|
}.padding(.bottom, 6)
|
||||||
Text("当前选中的修饰语")
|
Text(item.prompt ?? "")
|
||||||
.font(Font.system(size: 14))
|
.font(.subheadline)
|
||||||
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.6) : .white)
|
||||||
.padding(.bottom, 6)
|
}.padding(.leading, 2)
|
||||||
}
|
Spacer()
|
||||||
Text("每个会话只能选择一个修饰语, 也可以自定义添加修饰语")
|
}
|
||||||
.font(.subheadline)
|
|
||||||
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.6) : .white)
|
|
||||||
}.padding(.leading, 2)
|
|
||||||
}else {
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
|
||||||
Text(item.title ?? "")
|
|
||||||
.font(.headline)
|
|
||||||
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
|
||||||
.foregroundColor(.primary)
|
|
||||||
.padding(.bottom, 6)
|
|
||||||
Text(item.prompt ?? "")
|
|
||||||
.font(.subheadline)
|
|
||||||
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.6) : .white)
|
|
||||||
}.padding(.leading, 2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
if let author = item.author {
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Text("\(author)")
|
||||||
|
.foregroundColor((colorScheme == .dark) ? .white.opacity(0.8) : .white)
|
||||||
|
.font(.system(size: 11))
|
||||||
|
.padding(.top, 5)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.frame(height: 60)
|
.frame(height: 60)
|
||||||
.padding(.vertical, 5)
|
.padding(.vertical, 5)
|
||||||
@@ -148,13 +261,23 @@ struct AIPromptPopCellView: View {
|
|||||||
)
|
)
|
||||||
.cornerRadius(6)
|
.cornerRadius(6)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
self.action()
|
self.isTapped.toggle()
|
||||||
}
|
}
|
||||||
|
.sheet(isPresented: $isTapped) {
|
||||||
|
AIPromptDetailView(prompt: item, data: data)
|
||||||
|
.onTapGesture {
|
||||||
|
isTapped = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AIPromptView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
AIPromptView(sesstionId: nil)
|
//struct AIPromptView_Previews: PreviewProvider {
|
||||||
}
|
// static var previews: some View {
|
||||||
}
|
// AIPromptView(sesstionId: nil)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ struct ChatRoomToolBar: View {
|
|||||||
AIPromptPopView(showInputView: $showInputView, showPopover: $showPopover).environmentObject(viewModel)
|
AIPromptPopView(showInputView: $showInputView, showPopover: $showPopover).environmentObject(viewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button("清空消息") {
|
||||||
|
viewModel.messages.removeAll()
|
||||||
|
viewModel.deleteAllMessage(sesstionId: viewModel.currentConversation?.sesstionId ?? "")
|
||||||
|
viewModel.updateConversation(sesstionId: viewModel.currentConversation?.sesstionId ?? "", message: nil)
|
||||||
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
if viewModel.showStopAnswerBtn {
|
if viewModel.showStopAnswerBtn {
|
||||||
Button("停止生成") {
|
Button("停止生成") {
|
||||||
@@ -47,10 +53,6 @@ struct ChatRoomToolBar: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
.sheet(isPresented: $showInputView) {
|
|
||||||
// 在 sheet 中呈现表格
|
|
||||||
AIPromptInputView(isPresented: $showInputView)
|
|
||||||
}
|
}
|
||||||
.padding(.leading, 12)
|
.padding(.leading, 12)
|
||||||
.background(Color.clear)
|
.background(Color.clear)
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ struct SessionsView: View {
|
|||||||
}.buttonStyle(BorderlessButtonStyle())
|
}.buttonStyle(BorderlessButtonStyle())
|
||||||
Spacer()
|
Spacer()
|
||||||
Button(action: {
|
Button(action: {
|
||||||
|
viewModel.showUserInitialize = false
|
||||||
|
viewModel.showAIPrompt = false
|
||||||
|
|
||||||
// 点击 New Chat 按钮的操作
|
// 点击 New Chat 按钮的操作
|
||||||
viewModel.currentConversation = viewModel.addNewConversation()
|
viewModel.currentConversation = viewModel.addNewConversation()
|
||||||
viewModel.createNewChat = true
|
viewModel.createNewChat = true
|
||||||
@@ -37,13 +40,16 @@ struct SessionsView: View {
|
|||||||
}
|
}
|
||||||
.buttonStyle(BorderlessButtonStyle())
|
.buttonStyle(BorderlessButtonStyle())
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.padding(.leading,10)
|
.padding(.leading,0)
|
||||||
|
|
||||||
NavigationLink(destination: UserInitializeView().environmentObject(viewModel), isActive: $viewModel.showUserInitialize) {
|
NavigationLink(destination: UserInitializeView().environmentObject(viewModel), isActive: $viewModel.showUserInitialize) {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
// 点击右边按钮的操作
|
// 点击右边按钮的操作
|
||||||
viewModel.currentConversation = nil//先取消会话
|
if viewModel.currentConversation != nil {
|
||||||
// viewModel.showAIPrompt = false
|
viewModel.currentConversation = nil//先取消会话
|
||||||
|
}
|
||||||
|
viewModel.createNewChat = false
|
||||||
|
viewModel.showAIPrompt = false
|
||||||
viewModel.showUserInitialize = true
|
viewModel.showUserInitialize = true
|
||||||
KeyboardMonitor.shared.stopKeyMonitor()
|
KeyboardMonitor.shared.stopKeyMonitor()
|
||||||
KeyboardMonitor.shared.stopMonitorPasteboard()
|
KeyboardMonitor.shared.stopMonitorPasteboard()
|
||||||
@@ -55,27 +61,30 @@ struct SessionsView: View {
|
|||||||
.cornerRadius(5)
|
.cornerRadius(5)
|
||||||
}
|
}
|
||||||
.buttonStyle(PlainButtonStyle())
|
.buttonStyle(PlainButtonStyle())
|
||||||
.padding(.trailing, 20)
|
.padding(.trailing, 0)
|
||||||
}.buttonStyle(PlainButtonStyle())
|
}.buttonStyle(PlainButtonStyle())
|
||||||
|
|
||||||
// NavigationLink(destination: AIPromptView(sesstionId: nil), isActive: $viewModel.showAIPrompt) {
|
NavigationLink(destination: AIPromptView().environmentObject(viewModel), isActive: $viewModel.showAIPrompt) {
|
||||||
// Button(action: {
|
Button(action: {
|
||||||
// // 点击右边按钮的操作
|
// 点击右边按钮的操作
|
||||||
// viewModel.currentConversation = nil//先取消会话
|
if viewModel.currentConversation != nil {
|
||||||
// viewModel.showUserInitialize = false
|
viewModel.currentConversation = nil//先取消会话
|
||||||
// viewModel.showAIPrompt = true
|
}
|
||||||
// KeyboardMonitor.shared.stopKeyMonitor()
|
viewModel.createNewChat = false
|
||||||
// KeyboardMonitor.shared.stopMonitorPasteboard()
|
viewModel.showUserInitialize = false
|
||||||
// }) {
|
viewModel.showAIPrompt = true
|
||||||
// Image(systemName: "swift")
|
KeyboardMonitor.shared.stopKeyMonitor()
|
||||||
// .padding(10)
|
KeyboardMonitor.shared.stopMonitorPasteboard()
|
||||||
// .foregroundColor(.white)
|
}) {
|
||||||
// .background(Color.gray)
|
Image(systemName: "swift")
|
||||||
// .cornerRadius(5)
|
.padding(10)
|
||||||
// }
|
.foregroundColor(.white)
|
||||||
// .buttonStyle(PlainButtonStyle())
|
.background(Color.gray)
|
||||||
// .padding(.trailing, 10)
|
.cornerRadius(5)
|
||||||
// }.buttonStyle(PlainButtonStyle())
|
}
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
.padding(.trailing, 10)
|
||||||
|
}.buttonStyle(PlainButtonStyle())
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -99,6 +108,9 @@ struct SessionsView: View {
|
|||||||
.leftSessionContentSize()
|
.leftSessionContentSize()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
.onAppear {
|
||||||
|
let _ = ServerManager.shared.checkToken()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user