Merge pull request #78 from PangMo5/PangMo5/binding-side-effect

Remove @Published used for input(keyboard) binding (side effect)
This commit is contained in:
aiden vigue 2021-06-19 11:05:18 -04:00 committed by GitHub
commit 31ba7a07d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 79 additions and 78 deletions

View File

@ -10,14 +10,17 @@ 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 +33,7 @@ struct ConnectToServerView: View {
}
}
SecureField("Password (optional)", text: $viewModel.password)
SecureField("Password (optional)", text: $password)
.disableAutocorrection(true)
.autocapitalization(.none)
}
@ -39,7 +42,7 @@ struct ConnectToServerView: View {
HStack {
Button {
if !viewModel.lastPublicUsers.isEmpty {
viewModel.username = ""
username = ""
viewModel.showPublicUsers()
} else {
viewModel.isConnectedServer = false
@ -62,7 +65,7 @@ struct ConnectToServerView: View {
Text("Login")
}
Spacer()
}.disabled(viewModel.isLoading || viewModel.username.isEmpty)
}.disabled(viewModel.isLoading || username.isEmpty)
}
}
} else {
@ -74,11 +77,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 +95,7 @@ struct ConnectToServerView: View {
Spacer()
Button {
viewModel.hidePublicUsers()
viewModel.username = ""
username = ""
} label: {
Text("Other User").font(.headline).fontWeight(.semibold)
}
@ -103,7 +106,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 +120,7 @@ struct ConnectToServerView: View {
ProgressView()
}
}
.disabled(viewModel.isLoading || viewModel.uri.isEmpty)
.disabled(viewModel.isLoading || uri.isEmpty)
}
}
}
@ -127,6 +130,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,8 +11,7 @@ import Combine
struct LatestMediaView: View {
@StateObject
var tempViewModel = ViewModel()
@StateObject var tempViewModel = ViewModel()
@State var items: [BaseItemDto] = []
private var library_id: String = ""
@State private var viewDidLoad: Bool = false

View File

@ -12,6 +12,9 @@ import SwiftUI
struct ConnectToServerView: View {
@StateObject var viewModel = ConnectToServerViewModel()
@State var username = ""
@State var password = ""
@State var uri = ""
var body: some View {
ZStack {
@ -19,10 +22,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 +38,7 @@ struct ConnectToServerView: View {
ProgressView()
}
}
}.disabled(viewModel.isLoading || viewModel.username.isEmpty)
}.disabled(viewModel.isLoading || username.isEmpty)
}
Section {
@ -56,10 +59,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 +91,7 @@ struct ConnectToServerView: View {
Section {
Button {
viewModel.publicUsers.removeAll()
viewModel.username = ""
username = ""
} label: {
HStack {
Text("Other User").font(.subheadline).fontWeight(.semibold)
@ -106,7 +109,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 +123,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

@ -10,8 +10,7 @@ import JellyfinAPI
import Combine
struct EpisodeItemView: View {
@StateObject
var viewModel: EpisodeItemViewModel
@StateObject var viewModel: EpisodeItemViewModel
@State private var orientation = UIDeviceOrientation.unknown
@Environment(\.horizontalSizeClass) var hSizeClass
@Environment(\.verticalSizeClass) var vSizeClass

View File

@ -11,16 +11,11 @@ import Foundation
import SwiftUI
struct HomeView: View {
@StateObject
var viewModel = HomeViewModel()
@State
private var orientation = UIDevice.current.orientation
@Environment(\.horizontalSizeClass)
var hSizeClass
@Environment(\.verticalSizeClass)
var vSizeClass
@State
var showingSettings = false
@StateObject var viewModel = HomeViewModel()
@State private var orientation = UIDevice.current.orientation
@Environment(\.horizontalSizeClass) var hSizeClass
@Environment(\.verticalSizeClass) var vSizeClass
@State var showingSettings = false
var body: some View {
ZStack {

View File

@ -10,8 +10,7 @@ import JellyfinAPI
import SwiftUI
struct LatestMediaView: View {
@StateObject
var viewModel: LatestMediaViewModel
@StateObject var viewModel: LatestMediaViewModel
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {

View File

@ -9,13 +9,10 @@ import JellyfinAPI
import SwiftUI
struct LibraryFilterView: View {
@Environment(\.presentationMode)
var presentationMode
@Binding
var filters: LibraryFilters
@Environment(\.presentationMode) var presentationMode
@Binding var filters: LibraryFilters
@StateObject
var viewModel: LibraryFilterViewModel
@StateObject var viewModel: LibraryFilterViewModel
init(filters: Binding<LibraryFilters>, enabledFilterType: [FilterType]) {
_filters = filters

View File

@ -9,8 +9,7 @@ import Foundation
import SwiftUI
struct LibraryListView: View {
@StateObject
var viewModel = LibraryListViewModel()
@StateObject var viewModel = LibraryListViewModel()
var body: some View {
List(viewModel.libraries, id: \.self) { library in

View File

@ -10,13 +10,11 @@ import JellyfinAPI
import SwiftUI
struct LibrarySearchView: View {
@StateObject
var viewModel: LibrarySearchViewModel
@StateObject var viewModel: LibrarySearchViewModel
@State var searchQuery = ""
// MARK: tracks for grid
@State
private var tracks: [GridItem] = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)
@State private var tracks: [GridItem] = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)
func recalcTracks() {
tracks = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)
@ -25,7 +23,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 +65,9 @@ struct LibrarySearchView: View {
}
}
}
.onChange(of: searchQuery) { query in
viewModel.searchQuerySubject.send(query)
}
.navigationBarTitle("Search", displayMode: .inline)
}
}

View File

@ -12,19 +12,15 @@ import NukeUI
import SwiftUI
struct LibraryView: View {
@StateObject
var viewModel: LibraryViewModel
@StateObject var viewModel: LibraryViewModel
var title: String
// MARK: tracks for grid
@State
var isShowingSearchView = false
@State
var isShowingFilterView = false
@State var isShowingSearchView = false
@State var isShowingFilterView = false
@State
private var tracks: [GridItem] = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)
@State private var tracks: [GridItem] = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)
func recalcTracks() {
tracks = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)

View File

@ -10,10 +10,8 @@ import JellyfinAPI
import SwiftUI
struct MovieItemView: View {
@StateObject
var viewModel: MovieItemViewModel
@State
private var orientation = UIDeviceOrientation.unknown
@StateObject var viewModel: MovieItemViewModel
@State private var orientation = UIDeviceOrientation.unknown
@Environment(\.horizontalSizeClass)
var hSizeClass
@Environment(\.verticalSizeClass)

View File

@ -10,8 +10,7 @@ import Combine
import JellyfinAPI
struct SeasonItemView: View {
@StateObject
var viewModel: SeasonItemViewModel
@StateObject var viewModel: SeasonItemViewModel
@State private var orientation = UIDeviceOrientation.unknown
@Environment(\.horizontalSizeClass) var hSizeClass
@Environment(\.verticalSizeClass) var vSizeClass

View File

@ -10,11 +10,9 @@ import JellyfinAPI
import Combine
struct SeriesItemView: View {
@StateObject
var viewModel: SeriesItemViewModel
@StateObject var viewModel: SeriesItemViewModel
@State
private var tracks: [GridItem] = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)
@State private var tracks: [GridItem] = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)
func recalcTracks() {
tracks = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 125)

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)