Skip to content

Enable MollySocket provisioning and UnifiedPush for linked devices#706

Open
danielsoneg wants to merge 12 commits into
mollyim:mainfrom
danielsoneg:linked-mollysocket
Open

Enable MollySocket provisioning and UnifiedPush for linked devices#706
danielsoneg wants to merge 12 commits into
mollyim:mainfrom
danielsoneg:linked-mollysocket

Conversation

@danielsoneg

Copy link
Copy Markdown

Fixes #404

Linked devices cannot currently use UnifiedPush with MollySocket because this requires registering a separate set of device credentials.

This MR creates an alternate flow for this case which rides off the existing behavior for registering a linked device, re-using the flow for generating a QR code for the main device to scan to create and send the new device credentials to MollySocket.

I did my best to keep this to a relatively minimal changeset so it's easier to review - I'm re-using as much of the existing behavior around the linked device registration as I can. There's a couple areas where it'd probably benefit from some additional refactoring or abstraction, but I wanted to keep this clean enough that the change and idea itself was obvious enough to evaluate on its merits.

Changes:

  1. Pull out the linked device QR code provisioning UI so that it can be re-used for MollySocket provisioning
  2. Create a LinkProvisioningQrContract type to expose the link provisioning status with at least a bit of abstraction so it'll be obvious if it breaks later
  3. Add in a flow for provisioning another linked device for MollySocket if the current device is a linked device, wire this up across the app.
  4. Remove gates around using UnifiedPush while on a linked device

(This is a new codebase and environment for me, so I used LLM assistance quite a bit, but I've reviewed both the code and the design thoroughly. Also, I obviously didn't use the LLM to write this message, nor will you have to deal with lobster-speak in the comments.)

danielsoneg and others added 11 commits March 3, 2026 15:49
Move onSuccess/onFailure handling out of withContext(Dispatchers.IO)
so finishWithDevice() runs on the main thread. Reorder dialog checks
so errors take precedence over the progress indicator, preventing the
progress dialog from masking device creation failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename LinkProvisioningQrCard.kt to LinkProvisioningQrSection.kt to
match the composable it contains. Remove the unnecessary provisioning
property indirection in MollySocketProvisioningQrFragment and use
viewModel directly. Use the no-arg launch() extension consistently,
matching the existing convention in NotificationsSettingsFragment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A linked device cannot call getDeviceVerificationCode() directly,
so the background job should not attempt createDevice() when the
stored credential is lost. Instead, show a notification asking the
user to re-provision through notification settings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The @DayNightPreviews preview was present in the original code and
should have been carried over during the UI extraction. Also remove
an unused dp import in MollySocketProvisioningQrFragment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the changes in this file are from abstracting out the LinkProvisioningQrSection above

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a direct lift of the visual blocks from RegisterLinkDeviceQrFragment below

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface here isn't strictly necessary, but since we're now referencing the view modal in RegisterLinkDeviceQrViewModal in a completely separate place in the codebase, it felt like some bread crumbs to indicate the flow is being used elsewhere were warranted. If we want to proceed on a full refactor of the QR code, we can drop this, but for now, it felt like a good guardrail.

Comment on lines +73 to +76
it.copy(
isRegistering = false,
provisionMessage = null
)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we're using the flow in more than one place, cleanup to help avoid crosstalk.

Comment on lines +127 to +132
if (state.hasProvisioningError || error != null) {
Dialogs.SimpleMessageDialog(
message = error ?: stringResource(R.string.RestoreViaQr_qr_code_error),
onDismiss = onRetry,
dismiss = stringResource(android.R.string.ok)
)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling/messaging here is limited - again, this is because I'm taking a minimal cut/change set to make this legible, and the error handling in the standard Linked device flow was a little too tightly coupled to make it easy to expose.

@danielsoneg

Copy link
Copy Markdown
Author

Thanks for letting the build run - I was struggling to get the build running locally (well, not "struggling" so much as "it takes an hour and turns my laptop into a space heater," which makes the dev cycle a bit of a challenge). Build succeeds on my machine now.

@p1gp1g

p1gp1g commented Mar 4, 2026

Copy link
Copy Markdown
Member

Hey ! Thanks for the contribution.

If I understand correctly, you creates a new MollySocket linked device for the linked Molly (so a common setup would be 1. Main Device, 2. Linked device, 3. MollySocket for main device, 4. MollySocket for linked device). This is interesting, as it avoids modifying MollySocket - the solutions I had in mind required some changes on MollySocket. What I'm not sure is: what is the workflow for a linked device to get UnifiedPush, can you share the steps?

To be transparent, I plan to work on web push support for the Signal server in a few weeks. If that's accepted upstream, we won't have to deal with MollySocket anymore. And it would be a lot cleaner. So, if we can go that way, it will be preferred. If we can't go with an official support, then we will consider using MollySocket for linked device as you suggest here. So, if you want we can continue to gently review it, and talk about the UX too, but that's not sure it will be used.

@danielsoneg

Copy link
Copy Markdown
Author

Hah, yeah, I just want something that works - I'm fine if this code doesn't make it in.

You're reading the flow right - although my use case here is somewhat specific: I've got an iPhone which is primary on my signal account (and runs Signal), and then I've got an android running Molly I'd like to use UnifiedPush with. I specifically avoided modifying MollySocket, although I suspect your case (two Molly devices) implies two MollySockets.

The user flow is:

  1. Linked Device: settings -> Notifications -> push notifiactions -> delivery service, select UnifiedPush
  2. Linked Device: code path forks on "isLinkedDevice" - goes to new provisioning flow
  3. Linked Device: shows "new linked device" QR code
  4. Primary Device: scan device QR code, approve
  5. Linked Device: catches verification code, passes to normal linked device flow to get a device ID from Signal server
  6. Linked Device: now has device ID and password, resumes normal MollySocket configuration flow (which, honestly, I've never seen, because I've only got this linked Molly device 😄)

So the fork is that instead of the device the user is currently on (the linked device) running the full flow to register a new device, we use the linked device QR code registration machinery to offload that part over to the primary device to get the Signal verification code and then use that to jump back into the standard setup flow on the linked device.

@jangorecki

jangorecki commented May 29, 2026

Copy link
Copy Markdown

@p1gp1g any update on signal server work? Battery drain on carrier data makes molly not much usable for running in the background

@tennisballer

Copy link
Copy Markdown

I'm experiencing ghost 'media message' sync artifacts (#289) on linked devices using WebSocket. Would UnifiedPush on linked devices potentially help with this? I'd be happy to test a build if there's a pre‑release APK available

@PaperTobi

Copy link
Copy Markdown

Any update?

@p1gp1g

p1gp1g commented Jul 6, 2026

Copy link
Copy Markdown
Member

The server-side implementation is done, waiting for review: mollyim/flatline-whisper-service#20

I'll open a PR on signal once reviewed for flatline

@danielsoneg

Copy link
Copy Markdown
Author

@p1gp1g Out of curiosity, what's the relationship between flatline and signal itself? Looks like flatline is to run a completely separate signal "network", is that correct? Is there message interchange between flatline and signal?

(I swear I googled for all of this and read some stuff, just trying to check my understanding here)

@valldrac
valldrac force-pushed the main branch 4 times, most recently from b9022c4 to 51debd3 Compare July 13, 2026 10:08
@valldrac
valldrac force-pushed the main branch 3 times, most recently from 469424f to bf57ae5 Compare July 15, 2026 00:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Add UnifiedPush Support for Linked Devices

5 participants