Files
edgeever/apps/ios/EdgeEver/Features/Workspace/AccountPasswordPanel.swift
T

120 lines
4.8 KiB
Swift

import SwiftUI
struct AccountPasswordPanel: View {
@Environment(AppEnvironment.self) private var env
@State private var currentPassword = ""
@State private var newPassword = ""
@State private var confirmPassword = ""
@State private var message: String?
@State private var isError = false
@State private var busy = false
var body: some View {
VStack(alignment: .leading, spacing: 14) {
HStack(alignment: .top, spacing: 10) {
Image(systemName: "key.fill")
.font(.system(size: 18, weight: .semibold))
.foregroundStyle(AppTheme.accentStrong)
.padding(.top, 2)
VStack(alignment: .leading, spacing: 3) {
Text(env.preferences.t("修改密码", en: "Change password"))
.font(.system(size: 16, weight: .heavy))
.foregroundStyle(AppTheme.title)
Text(env.preferences.t(
"修改后会保留当前设备登录,并退出其他设备上的登录会话。",
en: "Keeps this device signed in and signs out other sessions."
))
.font(.system(size: 12))
.foregroundStyle(AppTheme.secondary)
.fixedSize(horizontal: false, vertical: true)
}
}
passwordField(env.preferences.t("当前密码", en: "Current password"), text: $currentPassword)
passwordField(env.preferences.t("新密码", en: "New password"), text: $newPassword)
passwordField(env.preferences.t("确认新密码", en: "Confirm password"), text: $confirmPassword)
if let message {
Text(message)
.font(.system(size: 13, weight: isError ? .regular : .bold))
.foregroundStyle(isError ? AppTheme.danger : AppTheme.accentStrong)
}
Button {
Task { await submit() }
} label: {
Text(busy
? env.preferences.t("正在修改…", en: "Updating…")
: env.preferences.t("修改密码", en: "Change password"))
.font(.system(size: 14, weight: .heavy))
.foregroundStyle(.white)
.frame(maxWidth: .infinity)
.frame(minHeight: 48)
.background(AppTheme.accentAction)
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.opacity(busy ? 0.45 : 1)
}
.buttonStyle(.plain)
.disabled(busy)
}
.padding(16)
.padding(.bottom, 8)
.background(AppTheme.card)
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
.overlay(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.stroke(AppTheme.border, lineWidth: 1)
)
}
private func passwordField(_ label: String, text: Binding<String>) -> some View {
VStack(alignment: .leading, spacing: 7) {
Text(label)
.font(.system(size: 13, weight: .bold))
.foregroundStyle(AppTheme.meta)
SecureField("", text: text)
.font(.system(size: 15))
.padding(.horizontal, 13)
.frame(minHeight: 48)
.background(AppTheme.card)
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
.overlay(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.stroke(AppTheme.border, lineWidth: 1)
)
}
}
private func submit() async {
message = nil
isError = false
if newPassword.count < 8 {
isError = true
message = env.preferences.t("新密码至少需要 8 个字符", en: "Password must be at least 8 characters")
return
}
if newPassword != confirmPassword {
isError = true
message = env.preferences.t("两次输入的新密码不一致", en: "Passwords do not match")
return
}
busy = true
defer { busy = false }
do {
try await env.session.client.changePassword(
current: currentPassword,
newPassword: newPassword,
confirm: confirmPassword
)
currentPassword = ""
newPassword = ""
confirmPassword = ""
isError = false
message = env.preferences.t("密码已修改成功。", en: "Password updated.")
} catch {
isError = true
message = error.localizedDescription
}
}
}