Skip to content
This repository has been archived by the owner on Dec 28, 2024. It is now read-only.

Manage Account // fix add account #10

Merged
merged 4 commits into from
May 5, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Features/Daily Note/View/InAppDailyNoteCardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ private struct NoteView: View {
// MARK: - ErrorView

private struct ErrorView: View {
// MARK: Internal

let account: Account
let error: Error

@State private var isEditAccountSheetShown: Bool = false

var body: some View {
Section {
ZStack {
Expand All @@ -136,9 +136,13 @@ private struct ErrorView: View {
isEditAccountSheetShown.toggle()
}
.sheet(isPresented: $isEditAccountSheetShown) {
ManageAccountSheetView(account: account, isShown: $isEditAccountSheetShown)
CreateAccountSheetView(account: account, isShown: $isEditAccountSheetShown)
}
}

// MARK: Private

@State private var isEditAccountSheetShown: Bool = false
}

private let dateFormatter: DateFormatter = {
Expand Down
Binary file removed Features/Manage Accounts/Model/.DS_Store
Binary file not shown.
24 changes: 24 additions & 0 deletions Features/Manage Accounts/Model/Account+CoreDataClass.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// Account+CoreDataClass.swift
// HSRPizzaHelper
//
// Created by 戴藏龙 on 2023/5/5.
//
//

import CoreData
import Foundation
import HBMihoyoAPI

@objc(Account)
public class Account: NSManagedObject {
public override func awakeFromInsert() {
super.awakeFromInsert()
uuid = UUID()
serverRawValue = Server.china.rawValue
name = name ?? ""
cookie = cookie ?? ""
priority = 0
uid = uid ?? ""
}
}
32 changes: 32 additions & 0 deletions Features/Manage Accounts/Model/Account+CoreDataProperties.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Account+CoreDataProperties.swift
// HSRPizzaHelper
//
// Created by 戴藏龙 on 2023/5/5.
//
//

import CoreData
import Foundation

extension Account {
@nonobjc
public class func fetchRequest() -> NSFetchRequest<Account> {
NSFetchRequest<Account>(entityName: "Account")
}

@NSManaged public var cookie: String!
@NSManaged public var name: String!
@NSManaged public var priority: NSNumber!
@NSManaged public var serverRawValue: String!
@NSManaged public var uid: String!
@NSManaged public var uuid: UUID!
}

// MARK: - Account + Identifiable

extension Account: Identifiable {
public var id: UUID {
uuid
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21754" systemVersion="22E261" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
<entity name="Account" representedClassName="Account" syncable="YES" codeGenerationType="class">
<entity name="Account" representedClassName="Account" syncable="YES">
<attribute name="cookie" optional="YES" attributeType="String"/>
<attribute name="name" optional="YES" attributeType="String"/>
<attribute name="priority" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,18 @@
import HBMihoyoAPI
import SwiftUI

// MARK: - ManageAccountSheetView
// MARK: - CreateAccountSheetView

struct ManageAccountSheetView: View {
struct CreateAccountSheetView: View {
// MARK: Lifecycle

/// Init when a new account
init(isShown: Binding<Bool>) {
_isShown = isShown
let account = Account(context: AccountPersistenceController.shared.container.viewContext)
account.uuid = UUID()
account.priority = 0
account.serverRawValue = Server.china.rawValue
_account = StateObject(wrappedValue: account)
self.isCreatingAccount = true
self.status = .pending
}

/// Init with an existed account for setting
init(account: Account, isShown: Binding<Bool>) {
_isShown = isShown
_account = StateObject(wrappedValue: account)
self.isCreatingAccount = false
self.status = .gotAccount
self._isShown = isShown
self._account = StateObject(wrappedValue: account)
}

// MARK: Internal

@Binding var isShown: Bool

@StateObject var account: Account

var body: some View {
NavigationView {
List {
Expand All @@ -61,6 +42,7 @@ struct ManageAccountSheetView: View {
}
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
viewContext.delete(account)
isShown.toggle()
}
}
Expand All @@ -78,11 +60,6 @@ struct ManageAccountSheetView: View {
return
}
}
.onDisappear {
if isCreatingAccount {
viewContext.delete(account)
}
}
}
}

Expand All @@ -92,12 +69,14 @@ struct ManageAccountSheetView: View {
isSaveAccountFailAlertShown.toggle()
return
}
do {
try viewContext.save()
isShown.toggle()
} catch {
saveAccountError = .saveDataError(error)
isSaveAccountFailAlertShown.toggle()
viewContext.performAndWait {
do {
try viewContext.save()
isShown.toggle()
} catch {
saveAccountError = .saveDataError(error)
isSaveAccountFailAlertShown.toggle()
}
}
}

Expand Down Expand Up @@ -158,65 +137,21 @@ struct ManageAccountSheetView: View {

@ViewBuilder
func gotAccountView() -> some View {
Section {
RequireLoginView(unsavedCookie: $account.cookie, region: $region)
}

Section {
HStack {
Text("Nickname")
Spacer()
TextField("Nickname", text: name, prompt: nil)
.multilineTextAlignment(.trailing)
}
} header: {
HStack {
Text("UID: " + (account.uid ?? ""))
Spacer()
Text(account.server.description)
}
}
Section {
// 如果该帐号绑定的UID不止一个,则显示Picker选择帐号
if accountsForSelected.count > 1 {
Picker("请选择帐号", selection: selectedAccount) {
ForEach(
accountsForSelected,
id: \.gameUid
) { account in
Text(account.nickname + "(\(account.gameUid))")
.tag(account as FetchedAccount?)
}
}
}
}
Section {
NavigationLink {
AddAccountDetailView(
unsavedName: $account.name,
unsavedUid: $account.uid,
unsavedCookie: $account.cookie,
unsavedServer: $account.server
)
} label: {
Text("Account Detail")
}
}
Section {
TestAccountView(account: account)
}
EditAccountView(account: account)
}

// MARK: Private

private let isCreatingAccount: Bool
@Binding private var isShown: Bool

@StateObject private var account: Account

@Environment(\.managedObjectContext) private var viewContext

@State private var isSaveAccountFailAlertShown: Bool = false
@State private var saveAccountError: SaveAccountError?

@State private var status: AddAccountStatus
@State private var status: AddAccountStatus = .pending

@State private var accountsForSelected: [FetchedAccount] = []

Expand Down Expand Up @@ -247,7 +182,7 @@ struct ManageAccountSheetView: View {

// MARK: - RequireLoginView

struct RequireLoginView: View {
private struct RequireLoginView: View {
@State var getCookieWebViewRegion: Region?

@Binding var unsavedCookie: String?
Expand Down Expand Up @@ -437,110 +372,3 @@ struct AddAccountDetailView: View {
.navigationBarTitle("Account Detail", displayMode: .inline)
}
}

// MARK: - TestAccountView

private struct TestAccountView: View {
// MARK: Internal

let account: Account

var body: some View {
Button {
withAnimation {
status = .testing
}
Task {
do {
_ = try await MiHoYoAPI.note(
server: account.server,
uid: account.uid ?? "",
cookie: account.cookie ?? ""
)
withAnimation {
status = .succeeded
}
} catch {
withAnimation {
status = .failure(error)
}
}
}
} label: {
HStack {
Text("Test account")
Spacer()
buttonIcon()
}
}
.disabled(status == .testing)
if case let .failure(error) = status {
FailureView(error: error)
}
}

@ViewBuilder
func buttonIcon() -> some View {
Group {
switch status {
case .succeeded:
Image(systemSymbol: .checkmarkCircle)
.foregroundColor(.green)
case .failure:
Image(systemSymbol: .xmarkCircle)
.foregroundColor(.red)
case .testing:
ProgressView()
default:
EmptyView()
}
}
}

// MARK: Private

private enum TestStatus: Identifiable, Equatable {
case pending
case testing
case succeeded
case failure(Error)

// MARK: Internal

var id: Int {
switch self {
case .pending:
return 0
case .testing:
return 1
case .succeeded:
// swiftlint:disable:next no_magic_numbers
return 2
case let .failure(error):
return error.localizedDescription.hashValue
}
}

static func == (lhs: TestAccountView.TestStatus, rhs: TestAccountView.TestStatus) -> Bool {
lhs.id == rhs.id
}
}

private struct FailureView: View {
let error: Error

var body: some View {
Text(error.localizedDescription)
if let error = error as? LocalizedError {
if let failureReason = error.failureReason {
Text(failureReason)
}
if let recoverySuggestion = error.recoverySuggestion {
Text(recoverySuggestion)
}
}
}
}

@State private var status: TestStatus = .pending
}
Loading