Give QuantumCast a public link too; versionCode 16 - #6
Merged
Merged
Conversation
QC drew the shared ListenQrDialog and always passed PublicLinkState.Off, because the tunnel lived in Telecloud's own folder. Now that it is a library module, QC gets the setting, the toggle and the wiring, and the dialog has something to show. The pieces mirror Telecloud: a tunnelEnabled DataStore key, a Public link switch under Web player with the same copy (the bandwidth cost and the fact that the link is world-reachable both belong in front of the switch), TunnelManager provided @singleton in AppModule, and PlaybackService starting the tunnel while the setting is on and the broadcast is up. One thing QC lacked: any observable broadcast liveness. It knew only `snapserverProcess != null && snapserverJob?.isActive`, which a flow cannot watch, so PlaybackState gains isBroadcasting, set in startSnapcast and cleared in stopSnapcast - the only two places that own the snapserver's lifetime. The collector is distinctUntilChanged because _state churns on every ICY title and buffering tick. onDestroy stops the tunnel explicitly rather than relying on the collector: cancelling the scope kills the collector, so an implicit stop would leave cloudflared running. Pinned to capullo-audio ac21187 like Telecloud - one pin, three modules.
The switch is otherwise UI-only, so the rig cannot exercise the tunnel without tapping through Settings. Mirrors fixport, and is gated to debuggable builds like every other dbg hook. am start -n tech.capullo.quantumcast/.MainActivity --es dbg tunnel --ez on true
gsalinaslopez
approved these changes
Aug 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on capullo-audio#5, and is pinned to that commit (
ac21187) — already published on jitpack, so this builds and CI passes independently of when that PR merges.QC drew the shared
ListenQrDialogand always passedPublicLinkState.Off, because the tunnel lived in Telecloud's own folder. Now that it is a library module, QC gets the setting, the toggle and the wiring, and the dialog has something to show.The pieces mirror Telecloud: a
tunnelEnabledDataStore key, a Public link switch under Web player with the same copy (the bandwidth cost and the fact that the link is world-reachable both belong in front of the switch),TunnelManagerprovided@SingletoninAppModule, andPlaybackServicestarting the tunnel while the setting is on and the broadcast is up.The one design decision
QC had no observable broadcast liveness. It knew only
snapserverProcess != null && snapserverJob?.isActive, which a flow cannot watch, soPlaybackStategainsisBroadcasting, set instartSnapcastand cleared instopSnapcast— the only two places that own the snapserver's lifetime. The collector isdistinctUntilChangedbecause_statechurns on every ICY title and buffering tick.onDestroystops the tunnel explicitly rather than relying on the collector: cancelling the scope kills the collector, so an implicit stop would leave cloudflared running.The second commit adds a
dbg tunnelhook, since the switch is otherwise UI-only and the rig cannot reach it. Gated to debuggable builds like every otherdbghook.Verification
Verified against the real pin (sibling aside,
--refresh-dependencies --rerun-tasks); the APK carrieslib/arm64-v8a/libcloudflared.soandtunnel_enabledis in the dex.Device-proven end to end on the OPPO, and this is the first time the tunnel has ever run from a QC build: with the toggle on and a broadcast up, QC spawned
libcloudflared.soand minted atrycloudflare.comhostname; fetching/over it returned the 112 KB Capullo web player (--http1.1, per the known HTTP/2 404 trap). Toggling back off killed cloudflared and left the snapserver running, so both directions of the wiring are proven.