2025-06-20 17:39:06 +08:00
|
|
|
//
|
|
|
|
// MNNLLMiOSApp.swift
|
|
|
|
// MainTabView
|
|
|
|
//
|
|
|
|
// Created by 游薪渝(揽清) on 2025/06/20.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
struct MainTabView: View {
|
2025-06-23 16:48:23 +08:00
|
|
|
@State private var showHistory = false
|
|
|
|
@State private var selectedHistory: ChatHistory? = nil
|
|
|
|
@State private var histories: [ChatHistory] = ChatHistoryManager.shared.getAllHistory()
|
|
|
|
@State private var showHistoryButton = true
|
2025-06-24 17:11:07 +08:00
|
|
|
@State private var showSettings = false
|
|
|
|
@State private var showWebView = false
|
|
|
|
@State private var webViewURL: URL?
|
2025-06-24 17:42:40 +08:00
|
|
|
@StateObject private var modelListViewModel = ModelListViewModel()
|
|
|
|
@State private var selectedTab: Int = 0
|
|
|
|
@State private var titles = ["本地模型", "模型市场", "Benchmark"]
|
2025-06-23 16:48:23 +08:00
|
|
|
|
2025-06-20 17:39:06 +08:00
|
|
|
var body: some View {
|
2025-06-25 17:12:04 +08:00
|
|
|
ZStack {
|
|
|
|
NavigationView {
|
2025-06-24 17:42:40 +08:00
|
|
|
TabView(selection: $selectedTab) {
|
|
|
|
LocalModelListView(viewModel: modelListViewModel)
|
|
|
|
.tabItem {
|
|
|
|
Image(systemName: "house.fill")
|
|
|
|
Text("本地模型")
|
|
|
|
}
|
|
|
|
.tag(0)
|
|
|
|
ModelListView(viewModel: modelListViewModel)
|
|
|
|
.tabItem {
|
|
|
|
Image(systemName: "cart.fill")
|
|
|
|
Text("模型市场")
|
|
|
|
}
|
|
|
|
.tag(1)
|
|
|
|
BenchmarkView()
|
|
|
|
.tabItem {
|
|
|
|
Image(systemName: "clock.fill")
|
|
|
|
Text("Benchmark")
|
|
|
|
}
|
|
|
|
.tag(2)
|
|
|
|
}
|
2025-06-25 17:12:04 +08:00
|
|
|
.background(NavigationLink(destination: chatDestination, isActive: chatIsActiveBinding) { EmptyView() })
|
|
|
|
.navigationTitle(titles[selectedTab])
|
|
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
|
|
.navigationBarHidden(false)
|
|
|
|
.onAppear(perform: setupNavigationBarAppearance)
|
|
|
|
.toolbar {
|
|
|
|
ToolbarItem(placement: .navigationBarLeading) {
|
|
|
|
if showHistoryButton {
|
|
|
|
Button(action: {
|
|
|
|
showHistory = true
|
|
|
|
showHistoryButton = false
|
|
|
|
histories = ChatHistoryManager.shared.getAllHistory()
|
|
|
|
}) {
|
|
|
|
Image(systemName: "sidebar.left")
|
|
|
|
.resizable()
|
|
|
|
.aspectRatio(contentMode: .fit)
|
|
|
|
.frame(width: 20, height: 20)
|
2025-06-24 17:42:40 +08:00
|
|
|
}
|
|
|
|
}
|
2025-06-25 17:12:04 +08:00
|
|
|
}
|
|
|
|
ToolbarItem(placement: .navigationBarTrailing) {
|
2025-06-25 17:45:26 +08:00
|
|
|
if selectedTab == 1 {
|
|
|
|
Button(action: {
|
|
|
|
showSettings.toggle()
|
|
|
|
}) {
|
|
|
|
Image(systemName: "gear")
|
|
|
|
.resizable()
|
|
|
|
.aspectRatio(contentMode: .fit)
|
|
|
|
.frame(width: 20, height: 20)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Button(action: {
|
|
|
|
if let url = URL(string: "https://github.com/alibaba/MNN") {
|
|
|
|
UIApplication.shared.open(url)
|
|
|
|
}
|
|
|
|
}) {
|
|
|
|
Image(systemName: "star")
|
|
|
|
.aspectRatio(contentMode: .fit)
|
|
|
|
.frame(width: 20, height: 20)
|
|
|
|
}
|
2025-06-24 17:42:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-06-23 16:48:23 +08:00
|
|
|
}
|
2025-06-25 17:12:04 +08:00
|
|
|
|
|
|
|
if showHistory {
|
|
|
|
Color.black.opacity(0.5)
|
|
|
|
.edgesIgnoringSafeArea(.all)
|
|
|
|
.onTapGesture {
|
2025-06-23 16:48:23 +08:00
|
|
|
withAnimation {
|
2025-06-25 17:12:04 +08:00
|
|
|
showHistory = false
|
2025-06-23 16:48:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-06-25 17:12:04 +08:00
|
|
|
|
|
|
|
SideMenuView(isOpen: $showHistory, selectedHistory: $selectedHistory, histories: $histories)
|
|
|
|
.edgesIgnoringSafeArea(.all)
|
|
|
|
}
|
|
|
|
.onChange(of: showHistory) { newValue in
|
|
|
|
if !newValue {
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
|
|
|
withAnimation {
|
|
|
|
showHistoryButton = true
|
|
|
|
}
|
2025-06-20 17:39:06 +08:00
|
|
|
}
|
2025-06-23 16:48:23 +08:00
|
|
|
}
|
2025-06-25 17:12:04 +08:00
|
|
|
}
|
|
|
|
.sheet(isPresented: $showWebView) {
|
|
|
|
if let url = webViewURL {
|
|
|
|
WebView(url: url)
|
2025-06-24 17:11:07 +08:00
|
|
|
}
|
|
|
|
}
|
2025-06-25 17:12:04 +08:00
|
|
|
.actionSheet(isPresented: $showSettings) {
|
|
|
|
ActionSheet(title: Text("Settings"), buttons: [
|
|
|
|
.default(Text("Report an Issue")) {
|
|
|
|
webViewURL = URL(string: "https://github.com/alibaba/MNN/issues")
|
|
|
|
showWebView = true
|
|
|
|
},
|
|
|
|
.default(Text("Go to MNN Homepage")) {
|
|
|
|
webViewURL = URL(string: "https://github.com/alibaba/MNN")
|
|
|
|
showWebView = true
|
|
|
|
},
|
|
|
|
.default(Text(ModelSource.modelScope.description)) {
|
|
|
|
ModelSourceManager.shared.updateSelectedSource(.modelScope)
|
|
|
|
},
|
|
|
|
.default(Text(ModelSource.modeler.description)) {
|
|
|
|
ModelSourceManager.shared.updateSelectedSource(.modeler)
|
|
|
|
},
|
|
|
|
.default(Text(ModelSource.huggingFace.description)) {
|
|
|
|
ModelSourceManager.shared.updateSelectedSource(.huggingFace)
|
|
|
|
},
|
|
|
|
.cancel()
|
|
|
|
])
|
|
|
|
}
|
2025-06-24 17:42:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
@ViewBuilder
|
|
|
|
private var chatDestination: some View {
|
|
|
|
if let model = modelListViewModel.selectedModel {
|
|
|
|
LLMChatView(modelInfo: model)
|
|
|
|
} else if let history = selectedHistory {
|
|
|
|
let modelInfo = ModelInfo(
|
|
|
|
modelId: history.modelId,
|
|
|
|
createdAt: "",
|
|
|
|
downloads: 0,
|
|
|
|
tags: [],
|
|
|
|
isDownloaded: true
|
|
|
|
)
|
|
|
|
LLMChatView(modelInfo: modelInfo, history: history)
|
|
|
|
} else {
|
|
|
|
EmptyView()
|
2025-06-24 17:11:07 +08:00
|
|
|
}
|
2025-06-20 17:39:06 +08:00
|
|
|
}
|
2025-06-24 17:42:40 +08:00
|
|
|
|
|
|
|
private var chatIsActiveBinding: Binding<Bool> {
|
|
|
|
Binding<Bool>(
|
|
|
|
get: { modelListViewModel.selectedModel != nil || selectedHistory != nil },
|
|
|
|
set: { isActive in
|
|
|
|
if !isActive {
|
|
|
|
modelListViewModel.selectedModel = nil
|
|
|
|
selectedHistory = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
private func setupNavigationBarAppearance() {
|
|
|
|
let appearance = UINavigationBarAppearance()
|
|
|
|
appearance.configureWithOpaqueBackground()
|
|
|
|
appearance.backgroundColor = .white
|
|
|
|
appearance.shadowColor = .clear // Optional: remove the shadow
|
|
|
|
|
|
|
|
UINavigationBar.appearance().standardAppearance = appearance
|
|
|
|
UINavigationBar.appearance().compactAppearance = appearance
|
|
|
|
UINavigationBar.appearance().scrollEdgeAppearance = appearance
|
|
|
|
}
|
2025-06-20 17:39:06 +08:00
|
|
|
}
|