feat: identicons, tap-to-copy fingerprint, recent rooms (Phase 1 backport)
Backport from desktop client to Android: Identicons: - New Identicon.kt composable: deterministic 5x5 symmetric Canvas pattern from fingerprint hash (same algorithm as desktop identicon.ts) - Participant list shows identicon + name + tappable fingerprint - Settings page shows identicon next to fingerprint CopyableFingerprint: - Tap any fingerprint text to copy to clipboard with Toast feedback - Used in participant list and settings page Recent rooms: - SettingsRepository: persists last 5 (relay, room) pairs - CallViewModel: saves on startCall, exposes as StateFlow - InCallScreen: clickable chips that fill room + select matching server Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ class SettingsRepository(context: Context) {
|
||||
private const val KEY_PREFER_IPV6 = "prefer_ipv6"
|
||||
private const val KEY_IDENTITY_SEED = "identity_seed_hex"
|
||||
private const val KEY_AEC_ENABLED = "aec_enabled"
|
||||
private const val KEY_RECENT_ROOMS = "recent_rooms"
|
||||
}
|
||||
|
||||
// --- Servers ---
|
||||
@@ -138,4 +139,33 @@ class SettingsRepository(context: Context) {
|
||||
fun saveSeedHex(hex: String) {
|
||||
prefs.edit().putString(KEY_IDENTITY_SEED, hex).apply()
|
||||
}
|
||||
|
||||
// --- Recent rooms ---
|
||||
|
||||
data class RecentRoom(val relay: String, val room: String)
|
||||
|
||||
fun addRecentRoom(relay: String, room: String) {
|
||||
val rooms = loadRecentRooms().toMutableList()
|
||||
rooms.removeAll { it.relay == relay && it.room == room }
|
||||
rooms.add(0, RecentRoom(relay, room))
|
||||
if (rooms.size > 5) rooms.subList(5, rooms.size).clear()
|
||||
val arr = JSONArray()
|
||||
rooms.forEach { arr.put(JSONObject().apply { put("relay", it.relay); put("room", it.room) }) }
|
||||
prefs.edit().putString(KEY_RECENT_ROOMS, arr.toString()).apply()
|
||||
}
|
||||
|
||||
fun loadRecentRooms(): List<RecentRoom> {
|
||||
val json = prefs.getString(KEY_RECENT_ROOMS, null) ?: return emptyList()
|
||||
return try {
|
||||
val arr = JSONArray(json)
|
||||
(0 until arr.length()).map { i ->
|
||||
val o = arr.getJSONObject(i)
|
||||
RecentRoom(o.getString("relay"), o.getString("room"))
|
||||
}
|
||||
} catch (_: Exception) { emptyList() }
|
||||
}
|
||||
|
||||
fun clearRecentRooms() {
|
||||
prefs.edit().remove(KEY_RECENT_ROOMS).apply()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user