Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F10494286
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Subscribers
None
View Options
diff --git a/Shared/Account/AccountLoginView.swift b/Shared/Account/AccountLoginView.swift
index cab3827..dfaeb99 100644
--- a/Shared/Account/AccountLoginView.swift
+++ b/Shared/Account/AccountLoginView.swift
@@ -1,104 +1,106 @@
import SwiftUI
struct AccountLoginView: View {
- @ObservedObject var account: AccountModel
+ @EnvironmentObject var model: WriteFreelyModel
@State private var isShowingAlert: Bool = false
@State private var alertMessage: String = ""
-
+ @State private var username: String = ""
+ @State private var password: String = ""
+ @State private var server: String = ""
var body: some View {
VStack {
HStack {
Image(systemName: "person.circle")
.foregroundColor(.gray)
#if os(iOS)
- TextField("Username", text: $account.username)
+ TextField("Username", text: $username)
.autocapitalization(.none)
.disableAutocorrection(true)
.textFieldStyle(RoundedBorderTextFieldStyle())
#else
- TextField("Username", text: $account.username)
+ TextField("Username", text: $username)
#endif
}
HStack {
Image(systemName: "lock.circle")
.foregroundColor(.gray)
#if os(iOS)
- SecureField("Password", text: $account.password)
+ SecureField("Password", text: $password)
.autocapitalization(.none)
.disableAutocorrection(true)
.textFieldStyle(RoundedBorderTextFieldStyle())
#else
- SecureField("Password", text: $account.password)
+ SecureField("Password", text: $password)
#endif
}
HStack {
Image(systemName: "link.circle")
.foregroundColor(.gray)
#if os(iOS)
- TextField("Server URL", text: $account.server)
+ TextField("Server URL", text: $server)
.keyboardType(.URL)
.autocapitalization(.none)
.disableAutocorrection(true)
.textFieldStyle(RoundedBorderTextFieldStyle())
#else
- TextField("Server URL", text: $account.server)
+ TextField("Server URL", text: $server)
#endif
}
Spacer()
- if account.isLoggingIn {
+ if model.isLoggingIn {
ProgressView("Logging in...")
.padding()
} else {
Button(action: {
- account.login(
- to: account.server,
- as: account.username, password: account.password,
- completion: loginHandler
+ model.login(
+ to: URL(string: server)!,
+ as: username, password: password
)
}, label: {
Text("Login")
})
- .disabled(account.isLoggedIn)
+ .disabled(model.account.isLoggedIn)
.padding()
}
}
.alert(isPresented: $isShowingAlert) {
Alert(
title: Text("Error Logging In"),
message: Text(alertMessage),
dismissButton: .default(Text("OK"))
)
}
}
func loginHandler(result: Result<UUID, AccountError>) {
do {
_ = try result.get()
} catch AccountError.serverNotFound {
alertMessage = """
The server could not be found. Please check that you've entered the information correctly and try again.
"""
isShowingAlert = true
} catch AccountError.invalidPassword {
alertMessage = """
Invalid password. Please check that you've entered your password correctly and try logging in again.
"""
isShowingAlert = true
} catch AccountError.usernameNotFound {
alertMessage = """
Username not found. Did you use your email address by mistake?
"""
isShowingAlert = true
} catch {
alertMessage = "An unknown error occurred. Please try again."
isShowingAlert = true
}
}
}
struct AccountLoginView_Previews: PreviewProvider {
static var previews: some View {
- AccountLoginView(account: AccountModel())
+ AccountLoginView()
+ .environmentObject(WriteFreelyModel())
}
}
diff --git a/Shared/Account/AccountLogoutView.swift b/Shared/Account/AccountLogoutView.swift
index bc84b50..16b9fd0 100644
--- a/Shared/Account/AccountLogoutView.swift
+++ b/Shared/Account/AccountLogoutView.swift
@@ -1,29 +1,30 @@
import SwiftUI
struct AccountLogoutView: View {
- @ObservedObject var account: AccountModel
+ @EnvironmentObject var model: WriteFreelyModel
var body: some View {
VStack {
Spacer()
VStack {
- Text("Logged in as \(account.username)")
- Text("on \(account.server)")
+ Text("Logged in as \(model.account.user?.username ?? "Anonymous")")
+ Text("on \(model.account.server)")
}
Spacer()
Button(action: logoutHandler, label: {
Text("Logout")
})
}
}
func logoutHandler() {
- account.logout()
+ model.logout()
}
}
struct AccountLogoutView_Previews: PreviewProvider {
static var previews: some View {
- AccountLogoutView(account: AccountModel())
+ AccountLogoutView()
+ .environmentObject(WriteFreelyModel())
}
}
diff --git a/Shared/Account/AccountModel.swift b/Shared/Account/AccountModel.swift
index 9d26b3c..c1ee3c8 100644
--- a/Shared/Account/AccountModel.swift
+++ b/Shared/Account/AccountModel.swift
@@ -1,71 +1,24 @@
import Foundation
+import WriteFreely
enum AccountError: Error {
case invalidPassword
case usernameNotFound
case serverNotFound
}
-class AccountModel: ObservableObject {
- @Published private(set) var id: UUID?
- @Published private(set) var isLoggedIn: Bool = false
- @Published private(set) var isLoggingIn: Bool = false
- @Published var username: String = ""
- @Published var password: String = ""
- @Published var server: String = ""
+struct AccountModel {
+ var server: String = ""
+ private(set) var user: WFUser?
+ private(set) var isLoggedIn: Bool = false
- func login(
- to server: String,
- as username: String,
- password: String,
- completion: @escaping (Result<UUID, AccountError>) -> Void
- ) {
- self.isLoggingIn = true
- let result: Result<UUID, AccountError>
-
- if server != validServer {
- result = .failure(.serverNotFound)
- } else if username != validCredentials["username"] {
- result = .failure(.usernameNotFound)
- } else if password != validCredentials["password"] {
- result = .failure(.invalidPassword)
- } else {
- self.id = UUID()
- self.username = username
- self.password = password
- self.server = server
- result = .success(self.id!)
- }
-
- #if DEBUG
- // Delay to simulate async network call
- DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
- self.isLoggingIn = false
- do {
- _ = try result.get()
- self.isLoggedIn = true
- } catch {
- self.isLoggedIn = false
- }
- completion(result)
- }
- #endif
+ mutating func login(_ user: WFUser) {
+ self.user = user
+ self.isLoggedIn = true
}
- func logout() {
- id = nil
- isLoggedIn = false
- isLoggingIn = false
- username = ""
- password = ""
- server = ""
+ mutating func logout() {
+ self.user = nil
+ self.isLoggedIn = false
}
}
-
-#if DEBUG
-let validCredentials = [
- "username": "test-writer",
- "password": "12345"
-]
-let validServer = "https://test.server.url"
-#endif
diff --git a/Shared/Account/AccountView.swift b/Shared/Account/AccountView.swift
index a0382d7..64f23a5 100644
--- a/Shared/Account/AccountView.swift
+++ b/Shared/Account/AccountView.swift
@@ -1,25 +1,26 @@
import SwiftUI
struct AccountView: View {
- @ObservedObject var account: AccountModel
+ @EnvironmentObject var model: WriteFreelyModel
var body: some View {
- if account.isLoggedIn {
+ if model.account.isLoggedIn {
HStack {
Spacer()
- AccountLogoutView(account: account)
+ AccountLogoutView()
Spacer()
}
.padding()
} else {
- AccountLoginView(account: account)
+ AccountLoginView()
.padding()
}
}
}
struct AccountLogin_Previews: PreviewProvider {
static var previews: some View {
- AccountView(account: AccountModel())
+ AccountView()
+ .environmentObject(WriteFreelyModel())
}
}
diff --git a/Shared/Models/WriteFreelyModel.swift b/Shared/Models/WriteFreelyModel.swift
index e84d65c..d926ee1 100644
--- a/Shared/Models/WriteFreelyModel.swift
+++ b/Shared/Models/WriteFreelyModel.swift
@@ -1,22 +1,65 @@
import Foundation
+import WriteFreely
// MARK: - WriteFreelyModel
class WriteFreelyModel: ObservableObject {
@Published var account = AccountModel()
@Published var preferences = PreferencesModel()
@Published var store = PostStore()
@Published var post: Post?
+ @Published var isLoggingIn: Bool = false
+
+ private var client: WFClient?
init() {
#if DEBUG
for post in testPostData { store.add(post) }
#endif
}
}
// MARK: - WriteFreelyModel API
extension WriteFreelyModel {
- // API goes here
+ func login(
+ to server: URL,
+ as username: String,
+ password: String
+ ) {
+ isLoggingIn = true
+ account.server = server.absoluteString
+ client = WFClient(for: server)
+ client?.login(username: username, password: password, completion: loginHandler)
+ }
+
+ func logout () {
+ guard let loggedInClient = client else { return }
+ loggedInClient.logout(completion: logoutHandler)
+ }
+}
+
+private extension WriteFreelyModel {
+ func loginHandler(result: Result<WFUser, Error>) {
+ isLoggingIn = false
+ do {
+ let user = try result.get()
+ account.login(user)
+ dump(user)
+ } catch {
+ dump(error)
+ }
+ }
+
+ func logoutHandler(result: Result<Bool, Error>) {
+ do {
+ let loggedOut = try result.get()
+ if loggedOut {
+ client = nil
+ account.logout()
+ }
+ } catch {
+ dump(error)
+ }
+ }
}
diff --git a/Shared/WriteFreely_MultiPlatformApp.swift b/Shared/WriteFreely_MultiPlatformApp.swift
index 804f6b1..63c1182 100644
--- a/Shared/WriteFreely_MultiPlatformApp.swift
+++ b/Shared/WriteFreely_MultiPlatformApp.swift
@@ -1,40 +1,41 @@
import SwiftUI
@main
struct WriteFreely_MultiPlatformApp: App {
@StateObject private var model = WriteFreelyModel()
#if os(macOS)
@State private var selectedTab = 0
#endif
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(model)
// .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info.
}
#if os(macOS)
Settings {
TabView(selection: $selectedTab) {
- MacAccountView(account: model.account)
+ MacAccountView()
+ .environmentObject(model)
.tabItem {
Image(systemName: "person.crop.circle")
Text("Account")
}
.tag(0)
MacPreferencesView(preferences: model.preferences)
.tabItem {
Image(systemName: "gear")
Text("Preferences")
}
.tag(1)
}
.frame(minWidth: 300, maxWidth: 300, minHeight: 200, maxHeight: 200)
.padding()
// .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info.
}
#endif
}
}
diff --git a/iOS/Settings/SettingsView.swift b/iOS/Settings/SettingsView.swift
index 0de3734..c4718c5 100644
--- a/iOS/Settings/SettingsView.swift
+++ b/iOS/Settings/SettingsView.swift
@@ -1,29 +1,29 @@
import SwiftUI
struct SettingsView: View {
@EnvironmentObject var model: WriteFreelyModel
@Binding var isPresented: Bool
var body: some View {
VStack {
SettingsHeaderView(isPresented: $isPresented)
Form {
Section(header: Text("Login Details")) {
- AccountView(account: model.account)
+ AccountView()
}
Section(header: Text("Appearance")) {
PreferencesView(preferences: model.preferences)
}
}
}
// .preferredColorScheme(preferences.selectedColorScheme) // See PreferencesModel for info.
}
}
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
SettingsView(isPresented: .constant(true))
.environmentObject(WriteFreelyModel())
}
}
diff --git a/macOS/Settings/MacAccountView.swift b/macOS/Settings/MacAccountView.swift
index b37b6da..e51dfd7 100644
--- a/macOS/Settings/MacAccountView.swift
+++ b/macOS/Settings/MacAccountView.swift
@@ -1,19 +1,20 @@
import SwiftUI
struct MacAccountView: View {
- @ObservedObject var account: AccountModel
+ @EnvironmentObject var model: WriteFreelyModel
var body: some View {
Form {
Section(header: Text("Login Details")) {
- AccountView(account: account)
+ AccountView()
}
}
}
}
struct MacAccountView_Previews: PreviewProvider {
static var previews: some View {
- MacAccountView(account: AccountModel())
+ MacAccountView()
+ .environmentObject(WriteFreelyModel())
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Mar 6, 10:41 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3168322
Attached To
rWFSUI WriteFreely SwiftUI
Event Timeline
Log In to Comment