2021-12-27 22:33:27 +08:00
|
|
|
//
|
|
|
|
// SettingsView.swift
|
|
|
|
// PushDeer
|
|
|
|
//
|
|
|
|
// Created by HEXT on 2021/12/25.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
2022-02-27 23:02:58 +08:00
|
|
|
import AuthenticationServices
|
2022-03-30 01:45:02 +08:00
|
|
|
import BetterSafariView
|
2022-01-10 00:26:29 +08:00
|
|
|
//import StoreKit
|
2021-12-27 22:33:27 +08:00
|
|
|
|
|
|
|
/// 设置界面
|
|
|
|
struct SettingsView: View {
|
2022-01-10 00:26:29 +08:00
|
|
|
@EnvironmentObject private var store: AppState
|
2022-03-02 13:06:01 +08:00
|
|
|
@State private var showUrl: URL?
|
2022-01-10 00:26:29 +08:00
|
|
|
|
2021-12-27 22:33:27 +08:00
|
|
|
var body: some View {
|
|
|
|
BaseNavigationView(title: "设置") {
|
2022-02-14 01:13:26 +08:00
|
|
|
ScrollView {
|
|
|
|
VStack {
|
|
|
|
SettingsItemView(title: NSLocalizedString("登录为", comment: "") + " " + userName(), button: NSLocalizedString("退出", comment: "退出登录按钮上的文字")) {
|
|
|
|
store.token = ""
|
|
|
|
}
|
|
|
|
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
|
|
|
|
|
2022-02-27 23:02:58 +08:00
|
|
|
#if !targetEnvironment(macCatalyst) && !APPCLIP && !SELFHOSTED
|
|
|
|
if WXApi.isWXAppInstalled() {
|
|
|
|
LoginInfoView()
|
|
|
|
.zIndex(-1)
|
|
|
|
.padding(EdgeInsets(top: -30, leading: 20, bottom: 0, trailing: 20))
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-02-14 01:13:26 +08:00
|
|
|
if Env.isSelfHosted {
|
|
|
|
SettingsItemView(title: NSLocalizedString("API endpoint", comment: ""), button: NSLocalizedString("重置", comment: "")) {
|
|
|
|
store.api_endpoint = ""
|
|
|
|
store.token = ""
|
|
|
|
}
|
|
|
|
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
|
|
|
|
}
|
|
|
|
|
|
|
|
SettingsItemView(title: NSLocalizedString("喜欢PushDeer?", comment: ""), button: NSLocalizedString("评分", comment: "")) {
|
|
|
|
let urlStr = "itms-apps://itunes.apple.com/app/id\(Env.appStoreId)?action=write-review"
|
|
|
|
UIApplication.shared.open(URL(string: urlStr)!, options: [:], completionHandler: nil)
|
|
|
|
// 直接弹出系统评分控件, 不过一年最多3次, 用户还可以在系统设置里面关
|
|
|
|
// SKStoreReviewController.requestReview()
|
|
|
|
}
|
|
|
|
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
|
|
|
|
|
2022-03-02 13:06:01 +08:00
|
|
|
SettingsItemView(title: NSLocalizedString("PushDeer官网", comment: ""), button: NSLocalizedString("查看", comment: "")) {
|
|
|
|
if store.isUseBuiltInBrowser {
|
|
|
|
showUrl = URL(string: Env.officialWebsite)
|
|
|
|
} else {
|
|
|
|
UIApplication.shared.open(URL(string: Env.officialWebsite)!, options: [:], completionHandler: nil)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
|
|
|
|
|
2022-02-27 23:02:58 +08:00
|
|
|
#if !targetEnvironment(macCatalyst)
|
|
|
|
CardView {
|
|
|
|
HStack{
|
|
|
|
Toggle(isOn: $store.isUseBuiltInBrowser) {
|
|
|
|
Text("使用内置浏览器打开链接")
|
|
|
|
.font(.system(size: 18))
|
|
|
|
.foregroundColor(Color("textColor"))
|
|
|
|
}
|
|
|
|
.padding(16)
|
|
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
|
|
}
|
|
|
|
.frame(height: 74)
|
|
|
|
}
|
|
|
|
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
|
|
|
|
#endif
|
|
|
|
|
2022-03-30 01:45:02 +08:00
|
|
|
CardView {
|
|
|
|
VStack(alignment: .leading, spacing: 5){
|
|
|
|
Text("MarkDown BaseURL: (Image/Link)")
|
|
|
|
.font(.system(size: 18))
|
|
|
|
.foregroundColor(Color("textColor"))
|
|
|
|
EditableText(placeholder: "https://example.com/", value: store.markDownBaseURL ?? "") { value in
|
|
|
|
if value.isEmpty {
|
|
|
|
store.markDownBaseURL = nil;
|
|
|
|
HToast.showSuccess(NSLocalizedString("保存成功", comment: ""))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if URL(string: value) == nil {
|
|
|
|
HToast.showError(NSLocalizedString("URL 格式不正确", comment: ""))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !value.lowercased().hasPrefix("http") {
|
|
|
|
HToast.showError(NSLocalizedString("请输入协议前缀: http:// 或 https://", comment: ""))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
store.markDownBaseURL = value
|
|
|
|
HToast.showSuccess(NSLocalizedString("保存成功", comment: ""))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.padding(16)
|
|
|
|
.frame(height: 74)
|
|
|
|
}
|
|
|
|
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
|
|
|
|
|
2022-02-14 01:13:26 +08:00
|
|
|
Spacer()
|
2021-12-27 22:33:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-10 00:26:29 +08:00
|
|
|
.onAppear {
|
|
|
|
if store.userInfo != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
Task {
|
|
|
|
store.userInfo = try await HttpRequest.getUserInfo()
|
|
|
|
}
|
|
|
|
}
|
2022-03-30 01:45:02 +08:00
|
|
|
.safariView(item: $showUrl, content: { url in
|
2022-03-02 13:06:01 +08:00
|
|
|
SafariView(url: url)
|
2022-03-30 01:45:02 +08:00
|
|
|
})
|
|
|
|
// .fullScreenCover(item: $showUrl) {
|
|
|
|
//
|
|
|
|
// } content: { url in
|
|
|
|
// HSafariView(url: url)
|
|
|
|
// }
|
2021-12-27 22:33:27 +08:00
|
|
|
}
|
2022-01-30 01:02:44 +08:00
|
|
|
|
|
|
|
func userName() -> String {
|
|
|
|
if let name = store.userInfo?.name {
|
|
|
|
if name.isEmpty {
|
|
|
|
return NSLocalizedString("苹果用户", comment: "")
|
|
|
|
} else {
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return "--"
|
|
|
|
}
|
|
|
|
}
|
2021-12-27 22:33:27 +08:00
|
|
|
}
|
|
|
|
|
2022-02-27 23:02:58 +08:00
|
|
|
struct LoginInfoView: View {
|
|
|
|
enum AlertType : Identifiable {
|
|
|
|
var id: Self { self }
|
|
|
|
case apple
|
|
|
|
case wechat
|
|
|
|
}
|
|
|
|
@EnvironmentObject private var store: AppState
|
|
|
|
@State private var alertType: AlertType? = nil
|
|
|
|
static private var coordinator: AppleSignInCoordinator? = nil
|
|
|
|
var body: some View {
|
|
|
|
CardView {
|
|
|
|
HStack(spacing: 16) {
|
|
|
|
Spacer()
|
|
|
|
Circle()
|
|
|
|
.frame(width: 10, height: 10, alignment: .center)
|
|
|
|
.foregroundColor(store.userInfo?.apple_id?.isEmpty ?? true ? .gray : .green)
|
|
|
|
Button {
|
|
|
|
if store.userInfo?.apple_id?.isEmpty ?? true {
|
|
|
|
alertType = .apple
|
|
|
|
} else {
|
|
|
|
HToast.showText(NSLocalizedString("当前已经绑定苹果账号", comment: ""))
|
|
|
|
}
|
|
|
|
} label: {
|
|
|
|
Image(systemName: "applelogo")
|
|
|
|
.resizable()
|
|
|
|
.scaledToFit()
|
|
|
|
.frame( height: 40, alignment: .center)
|
|
|
|
}
|
|
|
|
Spacer()
|
|
|
|
Circle()
|
|
|
|
.frame(width: 10, height: 10, alignment: .center)
|
|
|
|
.foregroundColor(store.userInfo?.wechat_id?.isEmpty ?? true ? .gray : .green)
|
|
|
|
Button {
|
|
|
|
if store.userInfo?.wechat_id?.isEmpty ?? true {
|
|
|
|
alertType = .wechat
|
|
|
|
} else {
|
|
|
|
HToast.showText(NSLocalizedString("当前已经绑定微信账号", comment: ""))
|
|
|
|
}
|
|
|
|
} label: {
|
|
|
|
Image("weixin-login")
|
|
|
|
.resizable()
|
|
|
|
.renderingMode(.template)
|
|
|
|
.scaledToFit()
|
|
|
|
.frame(height: 37, alignment: .center)
|
|
|
|
}
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
.padding(EdgeInsets(top: 32, leading: 0, bottom: 12, trailing: 0))
|
|
|
|
}
|
|
|
|
.alert(item: $alertType) { alertType in
|
|
|
|
var message = ""
|
|
|
|
switch alertType {
|
|
|
|
case .apple:
|
|
|
|
message = NSLocalizedString("准备绑定苹果账号, 如果你绑定的账号之前已经存在, 则会合并到当前账号. (之前的Key可能会被删除)", comment: "")
|
|
|
|
case .wechat:
|
|
|
|
message = NSLocalizedString("准备绑定微信账号, 如果你绑定的账号之前已经存在, 则会合并到当前账号. (之前的Key可能会被删除)", comment: "")
|
|
|
|
}
|
|
|
|
|
|
|
|
return Alert(
|
|
|
|
title: Text("温馨提示"),
|
|
|
|
message: Text(message),
|
|
|
|
primaryButton: .default(
|
|
|
|
Text("绑定"),
|
|
|
|
action: {
|
|
|
|
switch alertType {
|
|
|
|
case .apple:
|
|
|
|
LoginInfoView.coordinator = AppleSignInCoordinator(
|
|
|
|
onRequest: { request in
|
|
|
|
request.requestedScopes = [.fullName, .email]
|
|
|
|
},
|
|
|
|
onCompletion: { result in
|
|
|
|
do {
|
|
|
|
switch result {
|
|
|
|
case let .success(authorization):
|
|
|
|
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
|
|
|
|
let idToken = String(data:appleIDCredential.identityToken!, encoding: .utf8)
|
|
|
|
print(idToken as Any)
|
|
|
|
// 请求接口
|
|
|
|
let result = try await HttpRequest.mergeUser(type: "apple", tokenorcode: idToken!)
|
|
|
|
print(result)
|
|
|
|
// 合并成功, 更新数据
|
|
|
|
store.userInfo = try await HttpRequest.getUserInfo()
|
|
|
|
}
|
|
|
|
case let .failure(error):
|
|
|
|
if (error as NSError).code == 1001 {
|
|
|
|
HToast.showWarning(NSLocalizedString("你已取消授权", comment: ""))
|
|
|
|
} else {
|
|
|
|
HToast.showError(error.localizedDescription)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch {
|
|
|
|
HToast.showError(error.localizedDescription)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
LoginInfoView.coordinator?.performRequests()
|
|
|
|
|
|
|
|
case .wechat:
|
|
|
|
#if !targetEnvironment(macCatalyst) && !APPCLIP && !SELFHOSTED
|
|
|
|
let req = SendAuthReq()
|
|
|
|
req.scope = "snsapi_userinfo";
|
|
|
|
req.state = "bind";
|
|
|
|
WXApi.send(req) { b in
|
|
|
|
print("WXApi.send:", b)
|
|
|
|
}
|
|
|
|
// 微信登录请求发出去后面的逻辑在 AppDelegate 的 onResp 回调方法中处理
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
),
|
|
|
|
secondaryButton: .cancel(Text("稍后"))
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-27 22:33:27 +08:00
|
|
|
struct SettingsView_Previews: PreviewProvider {
|
|
|
|
static var previews: some View {
|
2022-01-10 00:26:29 +08:00
|
|
|
SettingsView().environmentObject(AppState.shared)
|
2021-12-27 22:33:27 +08:00
|
|
|
}
|
|
|
|
}
|