* fix(#478): rework default login to use unified ConnectionProfile model - AuthManager: drop legacy auth_token path; getToken/setToken now delegate to the selected profile (profile token only, no global fallback) - setHost/setPort always write the selected profile (no top-level host/port branch) - Add DEFAULT_PROFILE_ID + ensureDefaultProfile()/ensureDefaultSelected() so the selected profile is never null; ensureDefaultSelected() only falls back when nothing is selected (never clobbers an existing choice); ensureDefaultProfile() only injects a Default profile on fresh install, never into an existing list - One-time migration folds legacy standalone auth_token into the Default profile, batched into a single SharedPreferences transaction (guarded by legacy_default_migrated) - ConnectViewModel.connect() persists via setToken/setHost/setPort (delegate to the selected profile) — keeps the existing persistence contract - Connect/Settings: remove the '(none)'/standalone profile option; deleteProfile falls back to Default profile instead of null selection - Update AuthManagerTest/ConnectViewModelTest to the unified model; fix test stub ordering + migration re-init; remove dead connect_profile_none / settings_profile_none strings Closes #478 * fix: stub AuthManager.ensureDefaultSelected() in E2eIntegrationTest The #478 ConnectViewModel.connect() success branch now calls AuthManager.ensureDefaultSelected() on the non-saveProfile path. E2eIntegrationTest.setUp() mocks AuthManager as a non-relaxed mockkObject but never stubs that method, so the unstubbed call throws MockKException inside viewModelScope.launch, leaving connectionSuccess unset and failing 3 tests: - testFullUserSessionFlow - testConnectViewModel_onPairingString_base64Format - testConnectViewModel_onPairingString_urlFormat Add the missing stub. Verified locally: full suite 322/322 passing. --------- Co-authored-by: ronia <ronia@m57>
This commit is contained in:
1 parent
b65d0297e0
commit
aa59e704a4
11 files changed
+229
-155
No files matched your search
@@ -154,13 +154,6 @@ fun ConnectScreen(
|
||||
onDismissRequest = { profilesExpanded = false },
|
||||
modifier = Modifier.fillMaxWidth(0.85f),
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.connect_profile_none)) },
|
||||
onClick = {
|
||||
viewModel.selectProfile(null)
|
||||
profilesExpanded = false
|
||||
},
|
||||
)
|
||||
state.profiles.forEach { profile ->
|
||||
DropdownMenuItem(
|
||||
text = { Text(profile.name) },
|
||||
|
||||
@@ -54,12 +54,7 @@ class ConnectViewModel(
|
||||
val selectedProfile = profiles.firstOrNull { it.id == selectedId }
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
token =
|
||||
if (selectedProfile != null) {
|
||||
AuthManager.getProfileToken(selectedProfile.id) ?: ""
|
||||
} else {
|
||||
savedToken
|
||||
},
|
||||
token = savedToken,
|
||||
host = selectedProfile?.host ?: savedHost,
|
||||
port = (selectedProfile?.port ?: savedPort).toString(),
|
||||
profiles = profiles,
|
||||
@@ -77,30 +72,17 @@ class ConnectViewModel(
|
||||
_uiState.update { it.copy(saveProfile = value) }
|
||||
}
|
||||
|
||||
fun selectProfile(profile: ConnectionProfile?) {
|
||||
if (profile == null) {
|
||||
AuthManager.setSelectedProfileId(null)
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
selectedProfile = null,
|
||||
profileName = "",
|
||||
token = "",
|
||||
host = "127.0.0.1",
|
||||
port = "9119",
|
||||
)
|
||||
}
|
||||
} else {
|
||||
AuthManager.setSelectedProfileId(profile.id)
|
||||
val token = AuthManager.getProfileToken(profile.id) ?: ""
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
selectedProfile = profile,
|
||||
profileName = profile.name,
|
||||
host = profile.host,
|
||||
port = profile.port.toString(),
|
||||
token = token,
|
||||
)
|
||||
}
|
||||
fun selectProfile(profile: ConnectionProfile) {
|
||||
AuthManager.setSelectedProfileId(profile.id)
|
||||
val token = AuthManager.getProfileToken(profile.id) ?: ""
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
selectedProfile = profile,
|
||||
profileName = profile.name,
|
||||
host = profile.host,
|
||||
port = profile.port.toString(),
|
||||
token = token,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +124,9 @@ class ConnectViewModel(
|
||||
}
|
||||
when (result) {
|
||||
is NetworkResult.Success -> {
|
||||
// Only persist credentials to global state upon successful verification
|
||||
// Persist credentials to the selected (Default) profile upon successful verification.
|
||||
// setToken/setHost/setPort delegate to the currently-selected profile, which is
|
||||
// always non-null after issue #478 (never the legacy standalone path).
|
||||
AuthManager.setToken(state.token)
|
||||
AuthManager.setHost(state.host)
|
||||
AuthManager.setPort(port)
|
||||
@@ -177,11 +161,10 @@ class ConnectViewModel(
|
||||
AuthManager.setSelectedProfileId(targetProfile.id)
|
||||
AuthManager.setProfileToken(targetProfile.id, state.token)
|
||||
} else {
|
||||
// Clear selected profile if we connected standalone and didn't check "save profile"
|
||||
AuthManager.setSelectedProfileId(null)
|
||||
AuthManager.setToken(state.token)
|
||||
AuthManager.setHost(state.host)
|
||||
AuthManager.setPort(port)
|
||||
// No explicit profile name — store the connection on the default profile.
|
||||
AuthManager.ensureDefaultSelected()
|
||||
AuthManager.setSelectedProfileId(AuthManager.DEFAULT_PROFILE_ID)
|
||||
AuthManager.setProfileToken(AuthManager.DEFAULT_PROFILE_ID, state.token)
|
||||
}
|
||||
ApiClient.rebuild()
|
||||
_uiState.update {
|
||||
|
||||
Reference in new issue
Block a user