Remove @Published used for input(keyboard) binding (side effect)

This commit is contained in:
PangMo5 2021-06-19 18:09:25 +09:00
parent 3f6e91ef2e
commit 368ac68005
5 changed files with 65 additions and 33 deletions

View File

@ -10,14 +10,20 @@ import SwiftUI
struct ConnectToServerView: View {
@StateObject var viewModel = ConnectToServerViewModel()
@State
var username = ""
@State
var password = ""
@State
var uri = ""
var body: some View {
VStack(alignment: .leading) {
if viewModel.isConnectedServer {
if viewModel.publicUsers.isEmpty {
Section(header: Text(viewModel.lastPublicUsers.isEmpty || viewModel.username == "" ? "Login to \(ServerEnvironment.current.server.name ?? "")": "")) {
if viewModel.lastPublicUsers.isEmpty || viewModel.username == "" {
TextField("Username", text: $viewModel.username)
Section(header: Text(viewModel.lastPublicUsers.isEmpty || username == "" ? "Login to \(ServerEnvironment.current.server.name ?? "")": "")) {
if viewModel.lastPublicUsers.isEmpty || username == "" {
TextField("Username", text: $username)
.disableAutocorrection(true)
.autocapitalization(.none)
} else {
@ -30,7 +36,7 @@ struct ConnectToServerView: View {
}
}
SecureField("Password (optional)", text: $viewModel.password)
SecureField("Password (optional)", text: $password)
.disableAutocorrection(true)
.autocapitalization(.none)
}
@ -39,7 +45,7 @@ struct ConnectToServerView: View {
HStack {
Button {
if !viewModel.lastPublicUsers.isEmpty {
viewModel.username = ""
username = ""
viewModel.showPublicUsers()
} else {
viewModel.isConnectedServer = false
@ -62,7 +68,7 @@ struct ConnectToServerView: View {
Text("Login")
}
Spacer()
}.disabled(viewModel.isLoading || viewModel.username.isEmpty)
}.disabled(viewModel.isLoading || username.isEmpty)
}
}
} else {
@ -74,11 +80,11 @@ struct ConnectToServerView: View {
let user = SessionManager.current.getSavedSession(userID: publicUser.id!)
SessionManager.current.loginWithSavedSession(user: user)
} else {
viewModel.username = publicUser.name ?? ""
username = publicUser.name ?? ""
viewModel.selectedPublicUser = publicUser
viewModel.hidePublicUsers()
if !(publicUser.hasPassword ?? true) {
viewModel.password = ""
password = ""
viewModel.login()
}
}
@ -92,7 +98,7 @@ struct ConnectToServerView: View {
Spacer()
Button {
viewModel.hidePublicUsers()
viewModel.username = ""
username = ""
} label: {
Text("Other User").font(.headline).fontWeight(.semibold)
}
@ -103,7 +109,7 @@ struct ConnectToServerView: View {
} else {
Form {
Section(header: Text("Server Information")) {
TextField("Jellyfin Server URL", text: $viewModel.uri)
TextField("Jellyfin Server URL", text: $uri)
.disableAutocorrection(true)
.autocapitalization(.none)
Button {
@ -117,7 +123,7 @@ struct ConnectToServerView: View {
ProgressView()
}
}
.disabled(viewModel.isLoading || viewModel.uri.isEmpty)
.disabled(viewModel.isLoading || uri.isEmpty)
}
}
}
@ -127,6 +133,15 @@ struct ConnectToServerView: View {
.alert(item: $viewModel.errorMessage) { _ in
Alert(title: Text("Error"), message: Text(viewModel.errorMessage ?? ""), dismissButton: .default(Text("Ok")))
}
.onChange(of: uri) { uri in
viewModel.uriSubject.send(uri)
}
.onChange(of: username) { username in
viewModel.usernameSubject.send(username)
}
.onChange(of: password) { password in
viewModel.passwordSubject.send(password)
}
.navigationTitle(viewModel.isConnectedServer ? "Who's watching?" : "Connect to Jellyfin")
}
}

View File

@ -11,7 +11,14 @@ import KeychainSwift
import SwiftUI
struct ConnectToServerView: View {
@StateObject var viewModel = ConnectToServerViewModel()
@StateObject
var viewModel = ConnectToServerViewModel()
@State
var username = ""
@State
var password = ""
@State
var uri = ""
var body: some View {
ZStack {
@ -19,10 +26,10 @@ struct ConnectToServerView: View {
if viewModel.isConnectedServer {
if viewModel.publicUsers.isEmpty {
Section(header: Text("Login to \(ServerEnvironment.current.server.name ?? "")")) {
TextField("Username", text: $viewModel.username)
TextField("Username", text: $username)
.disableAutocorrection(true)
.autocapitalization(.none)
SecureField("Password", text: $viewModel.password)
SecureField("Password", text: $password)
.disableAutocorrection(true)
.autocapitalization(.none)
Button {
@ -35,7 +42,7 @@ struct ConnectToServerView: View {
ProgressView()
}
}
}.disabled(viewModel.isLoading || viewModel.username.isEmpty)
}.disabled(viewModel.isLoading || username.isEmpty)
}
Section {
@ -56,10 +63,10 @@ struct ConnectToServerView: View {
ForEach(viewModel.publicUsers, id: \.id) { publicUser in
HStack {
Button(action: {
viewModel.username = publicUser.name ?? ""
username = publicUser.name ?? ""
viewModel.publicUsers.removeAll()
if !(publicUser.hasPassword ?? true) {
viewModel.password = ""
password = ""
viewModel.login()
}
}) {
@ -88,7 +95,7 @@ struct ConnectToServerView: View {
Section {
Button {
viewModel.publicUsers.removeAll()
viewModel.username = ""
username = ""
} label: {
HStack {
Text("Other User").font(.subheadline).fontWeight(.semibold)
@ -106,7 +113,7 @@ struct ConnectToServerView: View {
}
} else {
Section(header: Text("Server Information")) {
TextField("Jellyfin Server URL", text: $viewModel.uri)
TextField("Jellyfin Server URL", text: $uri)
.disableAutocorrection(true)
.autocapitalization(.none)
Button {
@ -120,11 +127,20 @@ struct ConnectToServerView: View {
ProgressView()
}
}
.disabled(viewModel.isLoading || viewModel.uri.isEmpty)
.disabled(viewModel.isLoading || uri.isEmpty)
}
}
}
}
.onChange(of: uri) { uri in
viewModel.uriSubject.send(uri)
}
.onChange(of: username) { username in
viewModel.usernameSubject.send(username)
}
.onChange(of: password) { password in
viewModel.passwordSubject.send(password)
}
.alert(item: $viewModel.errorMessage) { _ in
Alert(title: Text("Error"), message: Text("message"), dismissButton: .default(Text("Try again")))
}

View File

@ -12,7 +12,8 @@ import SwiftUI
struct LibrarySearchView: View {
@StateObject
var viewModel: LibrarySearchViewModel
@State
var searchQuery = ""
// MARK: tracks for grid
@State
@ -25,7 +26,7 @@ struct LibrarySearchView: View {
var body: some View {
VStack {
Spacer().frame(height: 6)
SearchBar(text: $viewModel.searchQuery)
SearchBar(text: $searchQuery)
ZStack {
ScrollView(.vertical) {
if !viewModel.items.isEmpty {
@ -67,6 +68,9 @@ struct LibrarySearchView: View {
}
}
}
.onChange(of: searchQuery) { query in
viewModel.searchQuerySubject.send(query)
}
.navigationBarTitle("Search", displayMode: .inline)
}
}

View File

@ -14,12 +14,10 @@ import JellyfinAPI
final class ConnectToServerViewModel: ViewModel {
@Published
var isConnectedServer = false
@Published
var uri = ""
@Published
var username = ""
@Published
var password = ""
var uriSubject = CurrentValueSubject<String, Never>("")
var usernameSubject = CurrentValueSubject<String, Never>("")
var passwordSubject = CurrentValueSubject<String, Never>("")
@Published
var lastPublicUsers = [UserDto]()
@ -57,7 +55,7 @@ final class ConnectToServerViewModel: ViewModel {
}
func connectToServer() {
ServerEnvironment.current.create(with: uri)
ServerEnvironment.current.create(with: uriSubject.value)
.sink(receiveCompletion: { result in
switch result {
case let .failure(error):
@ -72,7 +70,7 @@ final class ConnectToServerViewModel: ViewModel {
}
func login() {
SessionManager.current.login(username: username, password: password)
SessionManager.current.login(username: usernameSubject.value, password: passwordSubject.value)
.sink(receiveCompletion: { completion in
self.handleAPIRequestCompletion(completion: completion)
}, receiveValue: { _ in

View File

@ -15,15 +15,14 @@ final class LibrarySearchViewModel: ViewModel {
@Published
var items = [BaseItemDto]()
@Published
var searchQuery = ""
var searchQuerySubject = CurrentValueSubject<String, Never>("")
var parentID: String?
init(parentID: String?) {
self.parentID = parentID
super.init()
$searchQuery
searchQuerySubject
.debounce(for: 0.25, scheduler: DispatchQueue.main)
.sink(receiveValue: search(with:))
.store(in: &cancellables)