feat: add profile and contacts fetching from pubky#824
feat: add profile and contacts fetching from pubky#824ben-kaufman wants to merge 26 commits intomasterfrom
Conversation
app/src/main/java/to/bitkit/ui/screens/profile/ProfileViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/PubkyRingAuthViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/PubkyRingAuthViewModel.kt
Show resolved
Hide resolved
This comment has been minimized.
This comment has been minimized.
app/src/main/java/to/bitkit/ui/screens/profile/ProfileViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/PubkyRingAuthViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/PubkyRingAuthViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/PubkyRingAuthViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/ProfileScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/PubkyRingAuthViewModel.kt
Show resolved
Hide resolved
|
Starting review |
ovitrif
left a comment
There was a problem hiding this comment.
Submitted couple more pending comments and resolved the ones where code changes applied. The goal is to reach a state where agent can be asked to scan through non-resolved review comments and address those in a new pass.
This comment has been minimized.
This comment has been minimized.
|
resuming review... |
ovitrif
left a comment
There was a problem hiding this comment.
Overall great progress, this is getting closer to being ready.
For some reason my review comments of yesterday night didn't land to your side, likely it was a PEBKAC 🤦🏻 and I forgot to publish review.
There were more nits, but it was lacking the review of contacts review and retest of the new features stack. So this is more comprehensive anyways.
The biggest 2 issues are shown in this video:
https://github.com/user-attachments/assets/b582a575-39fe-4ddf-9e99-868de5a099f2
1. Crash when sharing pk from profile or contact details
1️⃣ 🔴 Basically 2 crash bugs, because shareText is used in viewModels instead of in view layer, the fix is described in comments on the lines which cause the crash. Should be fixed in profile details and contacts details.
2. Inconsistency and missing details on self (my) contact details
2️⃣ 🟠 The other bug (supposedly) is the contact details page for self, seems to be missing the right profile picture. Interesting that in iOS we show the profile page when tapping on the contact list item for self.
3. Inconsistency in sorting irregular profile names
3️⃣ 🔴 Then I noticed a difference between iOS and Android in sorting. iOS seems to do this better: Profiles with non-alphabet starting character are grouped at the top under section header #.
Android shows those at the end of the list, in a separate section for each glyph first char.
contacts.mp4
app/src/main/java/to/bitkit/ui/screens/profile/PubkyRingAuthViewModel.kt
Outdated
Show resolved
Hide resolved
| suspend fun initialize() = | ||
| ServiceQueue.CORE.background { paykitInitialize() } |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
app/src/main/java/to/bitkit/ui/screens/profile/ProfileViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/contacts/ContactDetailViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/contacts/ContactsIntroScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/contacts/ContactDetailScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/contacts/ContactsScreen.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/to/bitkit/ui/screens/profile/ProfileScreen.kt
Outdated
Show resolved
Hide resolved
|
Few issues/comments found during testing:
The capabilities in PubkyService are hardcoded to For dev/tnet/E2E builds we should be using staging.pubky.app / staging.paykit.app instead — Pubky Ring already distinguishes between staging and production based on homeserver. This will be needed for E2E test automation.
After hitting a profile load failure (possibly related to the staging mismatch above), the app gets stuck on an "Unable to load profile" screen with no way to disconnect/sign out. Resetting wallet and wiping app data from system settings do not clear it - only a full reinstall works. The session seems to persist somewhere that survives both of those operations (Keychain?). Screen_Recording_20260313_185242_Bitkit.Regtest.mp4
|
|
Also My profile in Contacts does not show profile details as opposed to iOS (checked on latest revision 78d16f7), also already mentioned by Ovi: Screen.Recording.2026-03-16.at.14.03.24.mov |
| Network.BITCOIN -> | ||
| "/pub/paykit.app/v0/:rw,/pub/pubky.app/profile.json:rw,/pub/pubky.app/follows/:rw" | ||
| else -> | ||
| "/pub/staging.paykit.app/v0/:rw,/pub/staging.pubky.app/profile.json:rw,/pub/pubky.app/follows/:rw" |
There was a problem hiding this comment.
/pub/pubky.app still in last entry…
should last entry also use …staging… ?!
maybe best to turn this strings-in-when to a string template, where the computing by network only applies to the app's name.
| contentAlignment = Alignment.Center, | ||
| modifier = Modifier.fillMaxSize() | ||
| ) { | ||
| CircularProgressIndicator(color = Colors.White32) |
There was a problem hiding this comment.
nit: should start using GradientCircularProgressIndicator in all new implementation from now on, instead of CircularProgressIndicator
| } | ||
|
|
||
| fun copyPublicKey() { | ||
| context.setClipboardText(publicKey, context.getString(R.string.profile__public_key)) |
There was a problem hiding this comment.
aside: this was the other option I didn't share as I am still skeptical on it, but I guess it's ok; the thing to fix was the crash, this alternative fixes it too, at the expense of having to bubble up N callbacks just to lift the copy-to-clipboard action to the viewModel without breaking the principle of not passing viewmodel to inner composables.
| private fun ActionButton( | ||
| iconRes: Int? = null, | ||
| imageVector: ImageVector? = null, | ||
| onClick: () -> Unit, | ||
| enabled: Boolean = true, | ||
| ) { | ||
| IconButton( | ||
| onClick = rememberDebouncedClick(onClick = onClick), | ||
| enabled = enabled, | ||
| modifier = Modifier | ||
| .size(48.dp) | ||
| .clip(CircleShape) | ||
| .background( | ||
| Brush.verticalGradient(listOf(Colors.Gray5, Colors.Gray6)), | ||
| CircleShape, | ||
| ) | ||
| .border(1.dp, Colors.White10, CircleShape) | ||
| ) { | ||
| val tint = if (enabled) Colors.White else Colors.White32 | ||
| when { | ||
| iconRes != null -> Icon( | ||
| painter = painterResource(iconRes), | ||
| contentDescription = null, | ||
| tint = tint, | ||
| modifier = Modifier.size(24.dp) | ||
| ) | ||
| imageVector != null -> Icon( | ||
| imageVector = imageVector, | ||
| contentDescription = null, | ||
| tint = tint, | ||
| modifier = Modifier.size(24.dp) | ||
| ) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
nit: it looks to me like these are the same implementations we have in contact detail page.
if this is 100% the same, we should extract to .ui.components, share and reuse.
Suggestion likely impacts:
ActionButtonProfileLinkRow
|
What is the best way to testing this? A Pubky Ring on staging? |
Test in prod, yolo! |
From what I see staging doesn't work still? Or maybe it is because of HTTP-auth required on staging 🤔 (IMO we should solve this and allow testing on staging): Screen.Recording.2026-03-16.at.18.22.17.mov |
Actually started to work after I http-auth'ed to staging.pubky.app in browser... 🤷 👍 |


Integrates Pubky decentralized identity into Bitkit, adding profile authentication, a contacts screen.
What's included
Pubky profile
pubkyauth://) with relay-based session exchange, session persistence in Keychain, and automatic session restoration on launchPubkyService— service layer wrappingpaykit(session management) andbitkit-core(auth relay, file fetching, profile/contacts)PubkyRepo— manages auth state, session lifecycle, profile, and contacts data with all I/O offloaded to background threadsPubkyImagecomponent for loadingpubky://URIs with two-tier (memory + disk) cachingPubkyStoreDataStore caches profile name and image URI for instant display before full profile loadsPubky contacts