498 lines
20 KiB
Swift
498 lines
20 KiB
Swift
//
|
|
// SideMenuView.swift
|
|
// SFI
|
|
//
|
|
// Created by Mac on 2024/10/12.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import ApplicationLibrary
|
|
import WebKit
|
|
|
|
import Libbox
|
|
import Library
|
|
|
|
struct SideMenuView: View {
|
|
|
|
@Binding var isPresented: Bool
|
|
@Binding var isLoggedIn: Bool
|
|
|
|
@State private var isLoading = false
|
|
@State private var errorMessage: String?
|
|
|
|
@State private var plandes: SubscribeReponseClass?
|
|
@State private var size: CGSize = .zero
|
|
@State private var avator = UserManager.shared.getUserInfo().avator
|
|
@State private var emailid = UserManager.shared.getUserInfo().email
|
|
|
|
@EnvironmentObject private var environments: ExtensionEnvironments
|
|
@State private var alert: Alert?
|
|
|
|
|
|
@State private var showAlert = false
|
|
@State private var isInviteActive = false
|
|
|
|
@State private var isLogouting = false
|
|
|
|
|
|
@AppStorage("paymentURLKey") private var paymentURLKey = ""
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
VStack() {
|
|
|
|
// Navigation Bar
|
|
// 用户信息区域
|
|
ZStack{
|
|
|
|
HStack{
|
|
Button(action: {
|
|
isPresented = false // Close the side menu
|
|
}, label: {
|
|
|
|
Image(systemName: "chevron.left")
|
|
.foregroundColor(.white)
|
|
|
|
Text("返回")
|
|
.foregroundColor(.white)
|
|
}).padding(10) // 增加可点击区域
|
|
Spacer(minLength: 0)
|
|
}
|
|
|
|
Text("设置")
|
|
.fontWeight(.bold).lineLimit(1)
|
|
}
|
|
.padding()
|
|
// .padding(.top,edges.top)
|
|
.foregroundColor(.white)
|
|
ScrollView(.vertical, showsIndicators: false) {
|
|
|
|
// Profile Section
|
|
VStack {
|
|
|
|
|
|
HStack {
|
|
|
|
// AsyncImage(url: URL(string: avator)){ phase in
|
|
// if let image = phase.image {
|
|
// image // Displays the loaded image.
|
|
// } else if phase.error != nil {
|
|
// Color.red // Indicates an error.
|
|
// } else {
|
|
// Color.blue // Acts as a placeholder.
|
|
// }
|
|
// }.frame(width: 50, height: 50)
|
|
// .clipShape(Circle())
|
|
// Image("applogo").resizable().frame(width: 50, height: 50).clipShape(Circle())
|
|
|
|
VStack(alignment: .leading, spacing: 5) {
|
|
Text("账户信息:")
|
|
.font(.headline).fontWeight(.light)
|
|
|
|
Text(emailid)
|
|
.font(.headline)
|
|
.bold()
|
|
|
|
}
|
|
Spacer()
|
|
/*
|
|
Spacer()
|
|
Button {
|
|
showAlert = true
|
|
} label: {
|
|
|
|
Text("退出登录").foregroundColor(.red)
|
|
Image(systemName: "rectangle.portrait.and.arrow.forward")
|
|
.foregroundColor(.red)
|
|
.aspectRatio(contentMode: .fill)
|
|
.frame(width: 4, height: 4)
|
|
|
|
}*/
|
|
|
|
}
|
|
.padding()
|
|
.background(Color.white.opacity(0.1))
|
|
.cornerRadius(12)
|
|
.shadow(color: .gray.opacity(0.1), radius: 5, x: 0, y: 5)
|
|
|
|
if (paymentURLKey.count > 3){
|
|
HStack {
|
|
|
|
if isLoading {
|
|
ProgressView()
|
|
.progressViewStyle(CircularProgressViewStyle())
|
|
.padding()
|
|
}
|
|
|
|
if let errorMessage = errorMessage {
|
|
Text(errorMessage)
|
|
.bold()
|
|
.foregroundColor(.red)
|
|
.multilineTextAlignment(.center) // 确保多行文本居中
|
|
.padding()
|
|
}else{
|
|
|
|
if let plandesss = self.plandes {
|
|
if plandesss.transferEnable > 0 {
|
|
VStack(alignment: .leading, spacing: 5) {
|
|
|
|
// Text("订阅详情:") .font(.subheadline)
|
|
|
|
|
|
Text(plandesss.plan?.name ?? "")
|
|
.font(.subheadline)
|
|
let u = plandesss.d/1024/1024/1024
|
|
let t = plandesss.transferEnable/1024/1024/1024
|
|
|
|
Spacer().frame(height: 10)
|
|
|
|
Text("已用: \(u) GB / 总计:\(t) GB")
|
|
.font(.subheadline).bold()
|
|
|
|
HStack {
|
|
// White bar on the left
|
|
// RoundedRectangle(cornerRadius: 10)
|
|
// .fill(Color.red)
|
|
// .frame(width: 300*CGFloat(plandesss.d)/CGFloat(plandesss.transferEnable), height: 20)
|
|
//
|
|
Text("").frame(height: 20).frame(minWidth: (CGFloat(plandesss.d)/CGFloat(plandesss.transferEnable))<=0.1 ? 20 : 300*(CGFloat(plandesss.d)/CGFloat(plandesss.transferEnable))).background(
|
|
RoundedRectangle(cornerRadius: 10)
|
|
.fill(
|
|
Color.red
|
|
)
|
|
)
|
|
Spacer() // Fill the remaining space to push the white rectangle to the left
|
|
}
|
|
.frame(height: 20) // Set the total width and height for the bar
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 10)
|
|
.fill(
|
|
Color.gray.opacity(0.5)
|
|
)
|
|
)
|
|
.padding()
|
|
|
|
|
|
|
|
|
|
// ScrollView {
|
|
// }.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
|
|
// AttributedText(htmlContent: plan.content, size: $size)
|
|
// .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, idealHeight: size.height, maxHeight: .infinity)
|
|
// .background(.clear)
|
|
|
|
}
|
|
Spacer()
|
|
}else{
|
|
Spacer()
|
|
Text("暂无订阅")
|
|
.font(.subheadline)
|
|
Spacer()
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}.padding()
|
|
.background(Color.white.opacity(0.1))
|
|
.cornerRadius(12)
|
|
.shadow(color: .gray.opacity(0.1), radius: 5, x: 0, y: 5)
|
|
}
|
|
} .frame(maxWidth: .infinity)
|
|
.padding()
|
|
.foregroundColor(.white)
|
|
|
|
// Menu Items
|
|
// List {
|
|
// NavigationLink(destination: WebShuntView()) {
|
|
// MenuItem(icon: "globe", title: "App日志", color: .white, isNew: false)
|
|
// }
|
|
LazyVStack(spacing: 10, content: {
|
|
NavigationLink(destination: SupportTicketView()) {
|
|
MenuItem(icon: "listclipboard", title: "我的工单", color: .white, isNew: false)
|
|
}
|
|
Divider() // 分隔线
|
|
|
|
if (paymentURLKey.count > 3){
|
|
|
|
NavigationLink(destination: UpgradeView()) {
|
|
MenuItem(icon: "crown.fill", title: "升级套餐", color: .yellow, isNew: true)
|
|
}
|
|
Divider() // 分隔线
|
|
NavigationLink(destination: OrderListView()) {
|
|
MenuItem(icon: "checkout", title: "我的订单", color: .white, isNew: false)
|
|
}
|
|
|
|
Divider() // 分隔线
|
|
NavigationLink(destination: InviteListView(isPresented: $isInviteActive)) {
|
|
MenuItem(icon: "star.fill", title: "邀请中心", color: .white, isNew: false)
|
|
}
|
|
Divider() // 分隔线
|
|
|
|
|
|
}else{
|
|
|
|
NavigationLink(destination: MessageCenterView()) {
|
|
MenuItem(icon: "message.badge.circle", title: "消息通知", color: .white, isNew: false)
|
|
}
|
|
Divider() // 分隔线
|
|
}
|
|
|
|
|
|
NavigationLink(destination: QuestionView()) {
|
|
MenuItem(icon: "questionmark.app", title: "问题解答", color: .white, isNew: false)
|
|
}
|
|
|
|
Divider() // 分隔线
|
|
|
|
NavigationLink(destination: SupportView()) {
|
|
MenuItem(icon: "headphones", title: "联系客服", color: .white, isNew: false)
|
|
}
|
|
Divider() // 分隔线
|
|
NavigationLink(destination: AboutUsView()) {
|
|
MenuItem(icon: "info.circle.fill", title: "关于我们", color: .white, isNew: false)
|
|
}
|
|
Divider() // 分隔线
|
|
}).padding()
|
|
|
|
Button(action: {
|
|
// Trigger the payment action
|
|
// showAlert = true
|
|
|
|
alert = Alert(YesOrNOMessage: "确定退出登录吗?", {
|
|
isLogouting=true
|
|
UserManager.shared.clearUserData()
|
|
//删除订阅信息
|
|
Task {
|
|
//await reloadSubscribe()
|
|
|
|
}
|
|
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
|
|
isLoggedIn = false
|
|
}
|
|
|
|
})
|
|
|
|
}, label: {
|
|
HStack {
|
|
Image(systemName: "trash.fill")
|
|
Text("退出登录")
|
|
|
|
}
|
|
.font(.headline)
|
|
.foregroundColor(.white)
|
|
.frame(maxWidth: .infinity)
|
|
.padding()
|
|
.background(Color.blue)
|
|
.cornerRadius(10)
|
|
|
|
}).padding()
|
|
|
|
}
|
|
|
|
// }
|
|
// .listStyle(PlainListStyle())
|
|
|
|
}.background(
|
|
BackgroundBg()
|
|
).modifier(ActivityIndicatorModifier(isLoading: isLogouting, color: Color.black.opacity(0.8), lineWidth: 1))
|
|
.onAppear {
|
|
Task {
|
|
await reloadSubscribe()
|
|
}
|
|
}.navigationBarHidden(true)
|
|
|
|
}.alertBinding($alert)
|
|
|
|
}
|
|
|
|
private func writeProfilePreviewList() async throws {
|
|
let profiles = try await ProfileManager.list()
|
|
|
|
for profile in profiles {
|
|
print("detele : \(profile.path) \(profile.remoteURL ?? "" )")
|
|
await deleteProfile(profile)
|
|
}
|
|
}
|
|
|
|
private func deleteProfile(_ profile: Profile) async {
|
|
do {
|
|
_ = try await ProfileManager.delete(profile)
|
|
} catch {
|
|
alert = Alert(error)
|
|
return
|
|
}
|
|
environments.profileUpdate.send()
|
|
}
|
|
|
|
|
|
@MainActor
|
|
public func reloadSubscribe() async {
|
|
|
|
isLoading = true
|
|
errorMessage = nil
|
|
|
|
let userInfoUrl = URL(string: "\(UserManager.shared.baseURL())user/getSubscribe")!
|
|
var request = URLRequest(url: userInfoUrl)
|
|
request.httpMethod = "GET"
|
|
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
request.addValue(UserManager.shared.getAutoData(), forHTTPHeaderField: "Authorization")
|
|
|
|
let task = URLSession.shared.dataTask(with: request) { data, response, error in
|
|
DispatchQueue.main.async {
|
|
self.isLoading = false
|
|
|
|
if let error = error {
|
|
self.errorMessage = "套餐数据请求失败: \(error.localizedDescription)"
|
|
return
|
|
}
|
|
|
|
guard let data = data else {
|
|
self.errorMessage = "套餐数据请求失败:数据为空"
|
|
return
|
|
}
|
|
// Parse the user info response
|
|
if let Subscribe = try? JSONDecoder().decode(SubscribeReponse.self, from: data) {
|
|
|
|
if let data = Subscribe.data {
|
|
|
|
plandes = data
|
|
emailid = data.email
|
|
|
|
UserManager.shared.storeUserInfo(email: emailid, avator: "")
|
|
// UserManager.shared.storeSuburlData(data: data.subscribeURL)
|
|
|
|
}else{
|
|
self.errorMessage = Subscribe.message ?? ""
|
|
}
|
|
|
|
|
|
}else{
|
|
self.errorMessage = "套餐数据请求失败"
|
|
}
|
|
}
|
|
}
|
|
|
|
task.resume()
|
|
}
|
|
|
|
|
|
|
|
// Sample Destination Views for each menu item
|
|
struct UpgradeView: View {
|
|
@State private var isSubscriptionActive = false
|
|
var body: some View {
|
|
SubscriptionView(isPresented: $isSubscriptionActive)
|
|
}
|
|
}
|
|
|
|
|
|
struct WebShuntView: View {
|
|
var body: some View {
|
|
VStack(alignment: .trailing, content: {
|
|
LogView()
|
|
ProfileView()
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Free30DaysView: View {
|
|
@State private var islogined = false
|
|
var body: some View {
|
|
InviteView(isPresented: $islogined)
|
|
}
|
|
}
|
|
|
|
struct AboutUsView: View {
|
|
var body: some View {
|
|
SettingsAboutView()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
struct MenuItem: View {
|
|
let icon: String
|
|
let title: String
|
|
let color: Color
|
|
let isNew: Bool?
|
|
|
|
var body: some View {
|
|
// Button {
|
|
//
|
|
// } label: {
|
|
//
|
|
// }
|
|
|
|
HStack {
|
|
|
|
if UIImage(systemName: icon) != nil{
|
|
|
|
Image(systemName: icon)
|
|
.foregroundColor(color).tint(.white)
|
|
.frame(width: 24, height: 24)
|
|
|
|
}else{
|
|
|
|
Image(icon).resizable()
|
|
.foregroundColor(.white).tint(.white)
|
|
.frame(width: 24, height: 24)
|
|
|
|
}
|
|
Text(title)
|
|
.foregroundColor(.white)
|
|
.font(.system(size: 18))
|
|
Spacer()
|
|
|
|
if isNew == true {
|
|
Circle()
|
|
.fill(Color.red)
|
|
.frame(width: 8, height: 8)
|
|
}
|
|
}
|
|
|
|
.padding(.vertical, 10)
|
|
|
|
}
|
|
}
|
|
|
|
struct AttributedText: UIViewRepresentable {
|
|
let htmlContent: String
|
|
@Binding var size: CGSize
|
|
|
|
private let webView = WKWebView()
|
|
var sizeObserver: NSKeyValueObservation?
|
|
|
|
func makeUIView(context: Context) -> WKWebView {
|
|
webView.scrollView.isScrollEnabled = false //<-- Here
|
|
webView.navigationDelegate = context.coordinator
|
|
return webView
|
|
}
|
|
|
|
func updateUIView(_ uiView: WKWebView, context: Context) {
|
|
uiView.loadHTMLString(htmlContent, baseURL: nil)
|
|
}
|
|
|
|
func makeCoordinator() -> Coordinator {
|
|
Coordinator(parent: self)
|
|
}
|
|
|
|
class Coordinator: NSObject, WKNavigationDelegate {
|
|
let parent: AttributedText
|
|
var sizeObserver: NSKeyValueObservation?
|
|
|
|
init(parent: AttributedText) {
|
|
self.parent = parent
|
|
sizeObserver = parent.webView.scrollView.observe(\.contentSize, options: [.new], changeHandler: { (object, change) in
|
|
parent.size = change.newValue ?? .zero
|
|
})
|
|
}
|
|
}
|
|
}
|