Skip to content

Commit dc40ed5

Browse files
agnersclaude
andcommitted
Include the still-preferred network name in the import-not-promoted message
When the device still prefers a different network after import, look up which app-added credential is currently preferred and surface its network name so the user can identify the lingering credential. Refactor appAddedIsPreferredCredentials into appAddedPreferredCredential so the preferred credential is reused for both the boolean check and the network-name lookup, and propagate the name via a new devicePreferredNetworkName field on AllHaveCredentials. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3508c46 commit dc40ed5

3 files changed

Lines changed: 30 additions & 17 deletions

File tree

app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class ThreadManagerImpl @Inject constructor(
7878
return if (getDeviceDataset == null) {
7979
ThreadManager.SyncResult.NoneHaveCredentials
8080
} else {
81-
val appIsDevicePreferred = appAddedIsPreferredCredentials(context)
81+
val appIsDevicePreferred = appAddedPreferredCredential(context) != null
8282
Timber.d("Thread: device ${if (appIsDevicePreferred) "prefers" else "doesn't prefer" } dataset from app")
8383

8484
return if (appIsDevicePreferred) {
@@ -128,14 +128,16 @@ class ThreadManagerImpl @Inject constructor(
128128
Timber.d(
129129
"Thread: device ${if (coreIsDevicePreferred) "prefers" else "doesn't prefer" } core preferred dataset",
130130
)
131-
val appIsDevicePreferred = coreIsDevicePreferred || appAddedIsPreferredCredentials(context)
131+
val appPreferredCredential = if (coreIsDevicePreferred) null else appAddedPreferredCredential(context)
132+
val appIsDevicePreferred = coreIsDevicePreferred || appPreferredCredential != null
132133
Timber.d(
133134
"Thread: device ${if (appIsDevicePreferred) "prefers" else "doesn't prefer" } dataset from app",
134135
)
135136

136137
var exportFromDevice = false
137138
var updated: Boolean? = null
138139
var deviceNowPrefersCore: Boolean? = null
140+
var devicePreferredNetworkName: String? = null
139141
if (!coreIsDevicePreferred) {
140142
if (appIsDevicePreferred) {
141143
// Update or remove the device preferred credential to match core state.
@@ -188,6 +190,9 @@ class ThreadManagerImpl @Inject constructor(
188190
}
189191
} core preferred dataset",
190192
)
193+
if (deviceNowPrefersCore == false) {
194+
devicePreferredNetworkName = appAddedPreferredCredential(context)?.networkName
195+
}
191196
true
192197
} else { // Core prefers imported from other app, this shouldn't be managed by HA
193198
localIds.forEach { baId ->
@@ -217,6 +222,7 @@ class ThreadManagerImpl @Inject constructor(
217222
fromApp = appIsDevicePreferred,
218223
updated = updated,
219224
deviceNowPrefersCore = deviceNowPrefersCore,
225+
devicePreferredNetworkName = devicePreferredNetworkName,
220226
exportIntent = if (exportFromDevice) deviceThreadIntent else null,
221227
)
222228
} catch (e: Exception) {
@@ -226,6 +232,7 @@ class ThreadManagerImpl @Inject constructor(
226232
fromApp = null,
227233
updated = null,
228234
deviceNowPrefersCore = null,
235+
devicePreferredNetworkName = null,
229236
exportIntent = null,
230237
)
231238
}
@@ -284,29 +291,25 @@ class ThreadManagerImpl @Inject constructor(
284291
}
285292

286293
@OptIn(ExperimentalStdlibApi::class)
287-
private suspend fun appAddedIsPreferredCredentials(context: Context): Boolean {
294+
private suspend fun appAddedPreferredCredential(context: Context): ThreadNetworkCredentials? {
288295
val appCredentials = suspendCoroutine { cont ->
289296
ThreadNetwork.getNetworkClient(context)
290297
.allCredentials
291298
.addOnSuccessListener { cont.resume(it) }
292299
.addOnFailureListener { cont.resume(null) }
293300
}
294301
return try {
295-
appCredentials?.any {
296-
val isPreferred = isPreferredCredentials(context, it)
297-
if (isPreferred) {
298-
Timber.d(
299-
"Thread device prefers app added dataset: %s (PAN %s, EXTPAN %s)",
300-
it.networkName,
301-
it.panId,
302-
it.extendedPanId.toHexString(HexFormat.UpperCase),
303-
)
304-
}
305-
isPreferred
306-
} ?: false
302+
appCredentials?.firstOrNull { isPreferredCredentials(context, it) }?.also {
303+
Timber.d(
304+
"Thread device prefers app added dataset: %s (PAN %s, EXTPAN %s)",
305+
it.networkName,
306+
it.panId,
307+
it.extendedPanId.toHexString(HexFormat.UpperCase),
308+
)
309+
}
307310
} catch (e: Exception) {
308311
Timber.e(e, "Thread app added credentials preferred check failed")
309-
false
312+
null
310313
}
311314
}
312315

app/src/main/kotlin/io/homeassistant/companion/android/settings/developer/DeveloperSettingsPresenterImpl.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,16 @@ class DeveloperSettingsPresenterImpl @Inject constructor(
101101
view.onThreadDebugResult(context.getString(commonR.string.thread_debug_result_match), true)
102102
} else if (syncResult.fromApp == true && syncResult.updated == true) {
103103
val message = if (syncResult.deviceNowPrefersCore == false) {
104-
context.getString(commonR.string.thread_debug_result_updated_not_preferred)
104+
val base = context.getString(commonR.string.thread_debug_result_updated_not_preferred)
105+
val name = syncResult.devicePreferredNetworkName
106+
if (name != null) {
107+
"$base ${context.getString(
108+
commonR.string.thread_debug_result_mismatch_detail,
109+
name,
110+
)}"
111+
} else {
112+
base
113+
}
105114
} else {
106115
context.getString(commonR.string.thread_debug_result_updated)
107116
}

app/src/main/kotlin/io/homeassistant/companion/android/thread/ThreadManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface ThreadManager {
1919
val fromApp: Boolean?,
2020
val updated: Boolean?,
2121
val deviceNowPrefersCore: Boolean?,
22+
val devicePreferredNetworkName: String?,
2223
val exportIntent: IntentSender?,
2324
) : SyncResult()
2425
object NoneHaveCredentials : SyncResult()

0 commit comments

Comments
 (0)