Skip to content

Commit 4a63b52

Browse files
authored
Stateful - Set cleanup and final classes (#1465)
* cleanup * Update Stateful.swift
1 parent 16efcbe commit 4a63b52

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+110
-139
lines changed

Shared/Objects/Stateful.swift

+2-15
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,11 @@
66
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
77
//
88

9-
import Foundation
10-
import OrderedCollections
11-
129
// TODO: documentation
1310
// TODO: find a better way to handle backgroundStates on action/state transitions
1411
// so that conformers don't have to manually insert/remove them
15-
// TODO: better/official way for subclasses of conformers to perform actions during
16-
// parent class actions
1712
// TODO: official way for a cleaner `respond` method so it doesn't have all Task
1813
// construction and get bloated
19-
// TODO: move backgroundStates to just a `Set`
2014

2115
protocol Stateful: AnyObject {
2216

@@ -27,9 +21,8 @@ protocol Stateful: AnyObject {
2721
/// Background states that the conformer can be in.
2822
/// Usually used to indicate background events that shouldn't
2923
/// set the conformer to a primary state.
30-
var backgroundStates: OrderedSet<BackgroundState> { get set }
24+
var backgroundStates: Set<BackgroundState> { get set }
3125

32-
var lastAction: Action? { get set }
3326
var state: State { get set }
3427

3528
/// Respond to a sent action and return the new state
@@ -44,21 +37,15 @@ protocol Stateful: AnyObject {
4437

4538
extension Stateful {
4639

47-
var lastAction: Action? {
48-
get { nil }
49-
set {}
50-
}
51-
5240
@MainActor
5341
func send(_ action: Action) {
5442
state = respond(to: action)
55-
lastAction = action
5643
}
5744
}
5845

5946
extension Stateful where BackgroundState == Never {
6047

61-
var backgroundStates: OrderedSet<Never> {
48+
var backgroundStates: Set<Never> {
6249
get {
6350
assertionFailure("Attempted to access `backgroundStates` when there are none")
6451
return []

Shared/ViewModels/AdminDashboard/APIKeysViewModel.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ final class APIKeysViewModel: ViewModel, Stateful {
3434
// MARK: Published Variables
3535

3636
@Published
37-
final var apiKeys: [AuthenticationInfo] = []
37+
var apiKeys: [AuthenticationInfo] = []
3838
@Published
39-
final var state: State = .initial
39+
var state: State = .initial
4040

4141
// MARK: Action Responses
4242

Shared/ViewModels/AdminDashboard/ActiveSessionsViewModel.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ final class ActiveSessionsViewModel: ViewModel, Stateful {
3636
}
3737

3838
@Published
39-
final var backgroundStates: OrderedSet<BackgroundState> = []
39+
var backgroundStates: Set<BackgroundState> = []
4040
@Published
41-
final var sessions: OrderedDictionary<String, BindingBox<SessionInfo?>> = [:]
41+
var sessions: OrderedDictionary<String, BindingBox<SessionInfo?>> = [:]
4242
@Published
43-
final var state: State = .initial
43+
var state: State = .initial
4444

4545
private let activeWithinSeconds: Int = 960
4646
private var sessionTask: AnyCancellable?
@@ -52,7 +52,7 @@ final class ActiveSessionsViewModel: ViewModel, Stateful {
5252

5353
sessionTask = Task { [weak self] in
5454
await MainActor.run {
55-
let _ = self?.backgroundStates.append(.gettingSessions)
55+
let _ = self?.backgroundStates.insert(.gettingSessions)
5656
}
5757

5858
do {

Shared/ViewModels/AdminDashboard/AddServerUserViewModel.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ final class AddServerUserViewModel: ViewModel, Eventful, Stateful, Identifiable
4545
}
4646

4747
@Published
48-
final var state: State = .initial
48+
var state: State = .initial
4949

5050
private var userTask: AnyCancellable?
5151
private var eventSubject: PassthroughSubject<Event, Never> = .init()

Shared/ViewModels/AdminDashboard/DeviceDetailViewModel.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Foundation
1111
import JellyfinAPI
1212
import OrderedCollections
1313

14-
class DeviceDetailViewModel: ViewModel, Stateful, Eventful {
14+
final class DeviceDetailViewModel: ViewModel, Stateful, Eventful {
1515

1616
enum Event {
1717
case error(JellyfinAPIError)
@@ -31,7 +31,7 @@ class DeviceDetailViewModel: ViewModel, Stateful, Eventful {
3131
}
3232

3333
@Published
34-
var backgroundStates: OrderedSet<BackgroundState> = []
34+
var backgroundStates: Set<BackgroundState> = []
3535
@Published
3636
var state: State = .initial
3737

@@ -57,7 +57,7 @@ class DeviceDetailViewModel: ViewModel, Stateful, Eventful {
5757

5858
Task {
5959
await MainActor.run {
60-
_ = backgroundStates.append(.updating)
60+
_ = backgroundStates.insert(.updating)
6161
}
6262

6363
do {

Shared/ViewModels/AdminDashboard/DevicesViewModel.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ final class DevicesViewModel: ViewModel, Eventful, Stateful {
4747
// MARK: Published Values
4848

4949
@Published
50-
final var backgroundStates: OrderedSet<BackgroundState> = []
50+
var backgroundStates: Set<BackgroundState> = []
5151
@Published
52-
final var devices: [DeviceInfo] = []
52+
var devices: [DeviceInfo] = []
5353
@Published
54-
final var state: State = .initial
54+
var state: State = .initial
5555

5656
var events: AnyPublisher<Event, Never> {
5757
eventSubject
@@ -69,7 +69,7 @@ final class DevicesViewModel: ViewModel, Eventful, Stateful {
6969
case .refresh:
7070
deviceTask?.cancel()
7171

72-
backgroundStates.append(.refreshing)
72+
backgroundStates.insert(.refreshing)
7373

7474
deviceTask = Task { [weak self] in
7575
do {
@@ -98,7 +98,7 @@ final class DevicesViewModel: ViewModel, Eventful, Stateful {
9898
case let .delete(ids):
9999
deviceTask?.cancel()
100100

101-
backgroundStates.append(.deleting)
101+
backgroundStates.insert(.deleting)
102102

103103
deviceTask = Task { [weak self] in
104104
do {

Shared/ViewModels/AdminDashboard/ServerTaskObserver.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ final class ServerTaskObserver: ViewModel, Stateful, Eventful, Identifiable {
4848
// MARK: Published Values
4949

5050
@Published
51-
final var backgroundStates: OrderedSet<BackgroundState> = []
51+
var backgroundStates: Set<BackgroundState> = []
5252
@Published
53-
final var state: State = .initial
53+
var state: State = .initial
5454
@Published
5555
private(set) var task: TaskInfo
5656

@@ -138,7 +138,7 @@ final class ServerTaskObserver: ViewModel, Stateful, Eventful, Identifiable {
138138
.appending(trigger)
139139

140140
await MainActor.run {
141-
_ = self.backgroundStates.append(.updatingTriggers)
141+
_ = self.backgroundStates.insert(.updatingTriggers)
142142
}
143143

144144
do {
@@ -165,7 +165,7 @@ final class ServerTaskObserver: ViewModel, Stateful, Eventful, Identifiable {
165165
updatedTriggers.removeAll { $0 == trigger }
166166

167167
await MainActor.run {
168-
_ = self.backgroundStates.append(.updatingTriggers)
168+
_ = self.backgroundStates.insert(.updatingTriggers)
169169
}
170170

171171
do {

Shared/ViewModels/AdminDashboard/ServerTasksViewModel.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ final class ServerTasksViewModel: ViewModel, Stateful {
4141
}
4242

4343
@Published
44-
final var backgroundStates: OrderedSet<BackgroundState> = []
44+
var backgroundStates: Set<BackgroundState> = []
4545
@Published
46-
final var state: State = .initial
46+
var state: State = .initial
4747
@Published
48-
final var tasks: OrderedDictionary<String, [ServerTaskObserver]> = [:]
48+
var tasks: OrderedDictionary<String, [ServerTaskObserver]> = [:]
4949

5050
private var getTasksCancellable: AnyCancellable?
5151

Shared/ViewModels/AdminDashboard/ServerUserAdminViewModel.swift

+7-7
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ final class ServerUserAdminViewModel: ViewModel, Eventful, Stateful, Identifiabl
4949
// MARK: - Published Values
5050

5151
@Published
52-
final var state: State = .initial
52+
var state: State = .initial
5353
@Published
54-
final var backgroundStates: OrderedSet<BackgroundState> = []
54+
var backgroundStates: Set<BackgroundState> = []
5555

5656
@Published
5757
private(set) var user: UserDto
@@ -99,7 +99,7 @@ final class ServerUserAdminViewModel: ViewModel, Eventful, Stateful, Identifiabl
9999
userTaskCancellable = Task {
100100
do {
101101
await MainActor.run {
102-
_ = backgroundStates.append(.refreshing)
102+
_ = backgroundStates.insert(.refreshing)
103103
}
104104

105105
try await loadDetails()
@@ -126,7 +126,7 @@ final class ServerUserAdminViewModel: ViewModel, Eventful, Stateful, Identifiabl
126126
userTaskCancellable = Task {
127127
do {
128128
await MainActor.run {
129-
_ = backgroundStates.append(.refreshing)
129+
_ = backgroundStates.insert(.refreshing)
130130
}
131131

132132
try await loadLibraries(isHidden: isHidden)
@@ -153,7 +153,7 @@ final class ServerUserAdminViewModel: ViewModel, Eventful, Stateful, Identifiabl
153153
userTaskCancellable = Task {
154154
do {
155155
await MainActor.run {
156-
_ = backgroundStates.append(.updating)
156+
_ = backgroundStates.insert(.updating)
157157
}
158158

159159
try await updatePolicy(policy: policy)
@@ -181,7 +181,7 @@ final class ServerUserAdminViewModel: ViewModel, Eventful, Stateful, Identifiabl
181181
userTaskCancellable = Task {
182182
do {
183183
await MainActor.run {
184-
_ = backgroundStates.append(.updating)
184+
_ = backgroundStates.insert(.updating)
185185
}
186186

187187
try await updateConfiguration(configuration: configuration)
@@ -209,7 +209,7 @@ final class ServerUserAdminViewModel: ViewModel, Eventful, Stateful, Identifiabl
209209
userTaskCancellable = Task {
210210
do {
211211
await MainActor.run {
212-
_ = backgroundStates.append(.updating)
212+
_ = backgroundStates.insert(.updating)
213213
}
214214

215215
try await updateUsername(username: username)

Shared/ViewModels/AdminDashboard/ServerUsersViewModel.swift

+7-7
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ final class ServerUsersViewModel: ViewModel, Eventful, Stateful, Identifiable {
5050
// MARK: Published Values
5151

5252
@Published
53-
final var backgroundStates: OrderedSet<BackgroundState> = []
53+
var backgroundStates: Set<BackgroundState> = []
5454

5555
@Published
56-
final var users: IdentifiedArrayOf<UserDto> = []
56+
var users: IdentifiedArrayOf<UserDto> = []
5757

5858
@Published
59-
final var state: State = .initial
59+
var state: State = .initial
6060

6161
var events: AnyPublisher<Event, Never> {
6262
eventSubject
@@ -88,7 +88,7 @@ final class ServerUsersViewModel: ViewModel, Eventful, Stateful, Identifiable {
8888
switch action {
8989
case let .refreshUser(userID):
9090
userTask?.cancel()
91-
backgroundStates.append(.gettingUsers)
91+
backgroundStates.insert(.gettingUsers)
9292

9393
userTask = Task {
9494
do {
@@ -114,7 +114,7 @@ final class ServerUsersViewModel: ViewModel, Eventful, Stateful, Identifiable {
114114

115115
case let .getUsers(isHidden, isDisabled):
116116
userTask?.cancel()
117-
backgroundStates.append(.gettingUsers)
117+
backgroundStates.insert(.gettingUsers)
118118

119119
userTask = Task {
120120
do {
@@ -140,7 +140,7 @@ final class ServerUsersViewModel: ViewModel, Eventful, Stateful, Identifiable {
140140

141141
case let .deleteUsers(ids):
142142
userTask?.cancel()
143-
backgroundStates.append(.deletingUsers)
143+
backgroundStates.insert(.deletingUsers)
144144

145145
userTask = Task {
146146
do {
@@ -167,7 +167,7 @@ final class ServerUsersViewModel: ViewModel, Eventful, Stateful, Identifiable {
167167

168168
case let .appendUser(user):
169169
userTask?.cancel()
170-
backgroundStates.append(.appendingUsers)
170+
backgroundStates.insert(.appendingUsers)
171171

172172
userTask = Task {
173173
do {

Shared/ViewModels/ConnectToServerViewModel.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ final class ConnectToServerViewModel: ViewModel, Eventful, Stateful {
4848
}
4949

5050
@Published
51-
var backgroundStates: OrderedSet<BackgroundState> = []
51+
var backgroundStates: Set<BackgroundState> = []
5252

5353
// no longer-found servers are not cleared, but not an issue
5454
@Published

Shared/ViewModels/FilterViewModel.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ final class FilterViewModel: ViewModel, Stateful {
4646

4747
/// ViewModel Background State(s)
4848
@Published
49-
var backgroundStates: OrderedSet<BackgroundState> = []
49+
var backgroundStates: Set<BackgroundState> = []
5050

5151
/// ViewModel State
5252
@Published
@@ -89,13 +89,13 @@ final class FilterViewModel: ViewModel, Stateful {
8989
queryFiltersTask = Task {
9090
do {
9191
await MainActor.run {
92-
_ = self.backgroundStates.append(.gettingQueryFilters)
92+
_ = self.backgroundStates.insert(.gettingQueryFilters)
9393
}
9494

9595
try await setQueryFilters()
9696
} catch {
9797
await MainActor.run {
98-
_ = self.backgroundStates.append(.failedToGetQueryFilters)
98+
_ = self.backgroundStates.insert(.failedToGetQueryFilters)
9999
}
100100
}
101101

Shared/ViewModels/HomeViewModel.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ final class HomeViewModel: ViewModel, Stateful {
4545
var resumeItems: OrderedSet<BaseItemDto> = []
4646

4747
@Published
48-
var backgroundStates: OrderedSet<BackgroundState> = []
49-
@Published
50-
var lastAction: Action? = nil
48+
var backgroundStates: Set<BackgroundState> = []
5149
@Published
5250
var state: State = .initial
5351

@@ -83,7 +81,7 @@ final class HomeViewModel: ViewModel, Stateful {
8381
case .backgroundRefresh:
8482

8583
backgroundRefreshTask?.cancel()
86-
backgroundStates.append(.refresh)
84+
backgroundStates.insert(.refresh)
8785

8886
backgroundRefreshTask = Task { [weak self] in
8987
do {

Shared/ViewModels/ItemAdministration/DeleteItemViewModel.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Combine
1010
import Foundation
1111
import JellyfinAPI
1212

13-
class DeleteItemViewModel: ViewModel, Stateful, Eventful {
13+
final class DeleteItemViewModel: ViewModel, Stateful, Eventful {
1414

1515
// MARK: - Events
1616

@@ -33,7 +33,7 @@ class DeleteItemViewModel: ViewModel, Stateful, Eventful {
3333
}
3434

3535
@Published
36-
final var state: State = .initial
36+
var state: State = .initial
3737

3838
// MARK: - Published Item
3939

Shared/ViewModels/ItemAdministration/IdentifyItemViewModel.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Get
1212
import JellyfinAPI
1313
import OrderedCollections
1414

15-
class IdentifyItemViewModel: ViewModel, Stateful, Eventful {
15+
final class IdentifyItemViewModel: ViewModel, Stateful, Eventful {
1616

1717
// MARK: - Events
1818

0 commit comments

Comments
 (0)