Skip to content

Commit 00c5421

Browse files
committed
Fix retain cycle with Jellyfin viewmodel
1 parent ac0867f commit 00c5421

File tree

2 files changed

+76
-33
lines changed

2 files changed

+76
-33
lines changed

BookPlayer/Jellyfin/Connection Screen/JellyfinConnectionViewModel.swift

+16-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ import SwiftUI
1515
class JellyfinConnectionViewModel: ViewModelProtocol, ObservableObject, BPLogger {
1616
enum Routes {
1717
case cancel
18-
case signInFinished(url: URL, userID: String, accessToken: String)
18+
case signInFinished(
19+
url: URL,
20+
userID: String,
21+
userName: String,
22+
accessToken: String,
23+
serverName: String,
24+
saveToKeychain: Bool
25+
)
1926
case signOut
2027
case showLibrary
2128
case showAlert(content: BPAlertContent)
@@ -145,7 +152,14 @@ class JellyfinConnectionViewModel: ViewModelProtocol, ObservableObject, BPLogger
145152
let authResult = try await apiClient.signIn(username: username, password: password)
146153
if let accessToken = authResult.accessToken, let userID = authResult.user?.id {
147154
self.connectionState = .connected
148-
self.onTransition?(.signInFinished(url: apiClient.configuration.url, userID: userID, accessToken: accessToken))
155+
self.onTransition?(.signInFinished(
156+
url: apiClient.configuration.url,
157+
userID: userID,
158+
userName: form.username,
159+
accessToken: accessToken,
160+
serverName: form.serverName ?? "",
161+
saveToKeychain: form.rememberMe
162+
))
149163
} else {
150164
self.showErrorAlert(message: JellyfinError.unexpectedResponse(code: nil).localizedDescription)
151165
}

BookPlayer/Jellyfin/JellyfinCoordinator.swift

+60-31
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@ class JellyfinCoordinator: Coordinator, AlertPresenter {
1919
private let jellyfinConnectionService: JellyfinConnectionService
2020
private var disposeBag = Set<AnyCancellable>()
2121
private var dismissing = false
22-
23-
init(flow: BPCoordinatorPresentationFlow, singleFileDownloadService: SingleFileDownloadService, jellyfinConnectionService: JellyfinConnectionService) {
22+
23+
init(
24+
flow: BPCoordinatorPresentationFlow,
25+
singleFileDownloadService: SingleFileDownloadService,
26+
jellyfinConnectionService: JellyfinConnectionService
27+
) {
2428
self.flow = flow
2529
self.singleFileDownloadService = singleFileDownloadService
2630
self.jellyfinConnectionService = jellyfinConnectionService
27-
31+
2832
bindObservers()
2933
}
30-
34+
3135
func bindObservers() {
3236
singleFileDownloadService.eventsPublisher.sink { [weak self] event in
3337
switch event {
@@ -46,24 +50,31 @@ class JellyfinCoordinator: Coordinator, AlertPresenter {
4650
}
4751
.store(in: &disposeBag)
4852
}
49-
53+
5054
func start() {
5155
let connectionVC = createJellyfinLoginScreen()
5256
flow.startPresentation(connectionVC, animated: true)
53-
57+
5458
tryShowLibraryView()
5559
}
5660

5761
private func createJellyfinLoginScreen() -> UIViewController {
5862
let viewModel = JellyfinConnectionViewModel(jellyfinConnectionService: jellyfinConnectionService)
59-
63+
6064
viewModel.coordinator = self
61-
viewModel.onTransition = { [viewModel] route in
65+
viewModel.onTransition = { route in
6266
switch route {
6367
case .cancel:
64-
viewModel.dismiss()
65-
case .signInFinished(let url, let userID, let accessToken):
66-
self.handleSignInFinished(url: url, userID: userID, accessToken: accessToken, connectionViewModel: viewModel)
68+
self.flow.finishPresentation(animated: true)
69+
case .signInFinished(let url, let userID, let userName, let accessToken, let serverName, let saveToKeychain):
70+
self.handleSignInFinished(
71+
url: url,
72+
userID: userID,
73+
userName: userName,
74+
accessToken: accessToken,
75+
serverName: serverName,
76+
saveToKeychain: saveToKeychain
77+
)
6778
case .signOut:
6879
self.jellyfinConnectionService.deleteConnection()
6980
case .showLibrary:
@@ -72,16 +83,22 @@ class JellyfinCoordinator: Coordinator, AlertPresenter {
7283
self.showAlert(content)
7384
}
7485
}
75-
86+
7687
let vc = UIHostingController(rootView: JellyfinConnectionView(viewModel: viewModel))
7788
return vc
7889
}
79-
80-
private func createJellyfinLibraryScreen(withLibraryName libraryName: String, userID: String, client: JellyfinClient) -> UIViewController {
81-
let viewModel = JellyfinLibraryViewModel(data: .topLevel(libraryName: libraryName, userID: userID),
82-
apiClient: client,
83-
singleFileDownloadService: singleFileDownloadService)
84-
90+
91+
private func createJellyfinLibraryScreen(
92+
withLibraryName libraryName: String,
93+
userID: String,
94+
client: JellyfinClient
95+
) -> UIViewController {
96+
let viewModel = JellyfinLibraryViewModel(
97+
data: .topLevel(libraryName: libraryName, userID: userID),
98+
apiClient: client,
99+
singleFileDownloadService: singleFileDownloadService
100+
)
101+
85102
viewModel.onTransition = { route in
86103
switch route {
87104
case .done:
@@ -95,26 +112,38 @@ class JellyfinCoordinator: Coordinator, AlertPresenter {
95112
return vc
96113
}
97114

98-
private func handleSignInFinished(url: URL, userID: String, accessToken: String, connectionViewModel viewModel: JellyfinConnectionViewModel) {
99-
let connectionData = JellyfinConnectionData(url: url,
100-
serverName: viewModel.form.serverName ?? "",
101-
userID: userID,
102-
userName: viewModel.form.username,
103-
accessToken: accessToken)
104-
jellyfinConnectionService.setConnection(connectionData, saveToKeychain: viewModel.form.rememberMe)
105-
115+
private func handleSignInFinished(
116+
url: URL,
117+
userID: String,
118+
userName: String,
119+
accessToken: String,
120+
serverName: String,
121+
saveToKeychain: Bool
122+
) {
123+
let connectionData = JellyfinConnectionData(
124+
url: url,
125+
serverName: serverName,
126+
userID: userID,
127+
userName: userName,
128+
accessToken: accessToken
129+
)
130+
jellyfinConnectionService.setConnection(connectionData, saveToKeychain: saveToKeychain)
131+
106132
self.tryShowLibraryView()
107133
}
108134

109135
private func tryShowLibraryView() {
110136
guard let connectionData = jellyfinConnectionService.connection,
111-
let apiClient = jellyfinConnectionService.createClient() else {
137+
let apiClient = jellyfinConnectionService.createClient()
138+
else {
112139
return
113140
}
114-
115-
let libraryVC = self.createJellyfinLibraryScreen(withLibraryName: connectionData.serverName,
116-
userID: connectionData.userID,
117-
client: apiClient)
141+
142+
let libraryVC = self.createJellyfinLibraryScreen(
143+
withLibraryName: connectionData.serverName,
144+
userID: connectionData.userID,
145+
client: apiClient
146+
)
118147
self.flow.pushViewController(libraryVC, animated: true)
119148
}
120149
}

0 commit comments

Comments
 (0)