Skip to content

Simplify text sharing with direct delivery and prepare preview 0.3.0 - #18

Merged
CodePandaaAI merged 1 commit into
masterfrom
refactor-networking
Aug 27, 2026
Merged

Simplify text sharing with direct delivery and prepare preview 0.3.0#18
CodePandaaAI merged 1 commit into
masterfrom
refactor-networking

Conversation

@CodePandaaAI

Copy link
Copy Markdown
Owner

Why this change exists

Sync360 originally treated text and files as two versions of the same transfer.

For both types of content, the sender first created an offer. The receiver then had up to 50 seconds to accept or decline it. After acceptance, the sender continued with another request or connection to deliver the actual content.

That approach gave text and files a shared structure, but it also made text inherit machinery that it did not really need:

  • an offer
  • an Accept or Decline decision
  • an operation ID
  • a waiting state
  • decision timeouts
  • remote cancellation
  • a Cancel action
  • a second request carrying the actual text

While reviewing this flow, we stopped asking how to make the shared system smaller and asked a more useful question:

Does text need to be an operation at all?

For Sync360, the answer was no.

Text is small, immediate, and does not create files or consume lasting storage. Files are different: they can be large, take time, use disk space, and need visible receiver approval.

Instead of continuing to force both features through one design, this change separates them.

The new text flow

Text now uses one direct HTTP request:

enter text
  -> select a nearby device
  -> send the text and sender device name
  -> receiver accepts it only while idle
  -> receiver displays the text

There is no text offer and no second transfer request.

The receiver responds with one clear result:

  • DELIVERED
  • RECEIVER_BUSY
  • TEXT_TOO_LARGE

This makes the text path much easier to follow. The request either delivers the complete text, receives a known rejection, or fails through the normal network error path.

Keeping the simple flow safe and bounded

Direct delivery does not mean accepting unlimited text.

Text is limited to 100,000 Kotlin String.length units. The limit is checked in several places:

  • Send screen state prevents the UI from starting an oversized send.
  • SendScreenViewModel checks before beginning the request.
  • OutgoingRequestsController validates before using the HTTP client.
  • IncomingServerRequestsController validates again on the receiving device.

The receiver accepts text only while ClientServerState is Idle.

The Idle check and the change to TextReceived happen together under the existing operation mutex. A text request and file offer therefore cannot both observe an idle receiver and start at the same time.

Received text includes the sender device name and provides Copy and Clear & Close actions.

What was removed from text

Text no longer has:

  • a preview offer
  • Accept or Decline
  • an operation ID
  • CompletableDeferred<UserDecision>
  • a waiting-for-text state
  • a preparation timeout
  • remote cancellation
  • a Cancel button

These were removed because the text flow no longer represents a multi-stage operation.

What remains unchanged for files

This is not a removal of the file-transfer safety flow.

Files still retain:

  • metadata offers
  • receiver Accept or Decline
  • operation IDs
  • sender and receiver identity checks
  • offer-decision timeouts
  • accepted-transfer preparation timeouts
  • best-effort remote cancellation
  • sender and receiver progress
  • raw TCP streaming
  • operation-scoped file framing
  • incomplete-file cleanup
  • completed-file preservation

CompletableDeferred<UserDecision> remains in the incoming controller, but it is now clearly named and owned as file-only plumbing.

Separating text also lets future file-transfer work focus only on the needs of files instead of preserving a generic design for two very different kinds of content.

Why this is simpler

The goal was not to reduce line count for its own sake.

The goal was to make the behavior easier to understand:

  • one text request instead of an offer followed by delivery
  • one complete receiver state update instead of a partially completed text operation
  • no text cancellation race
  • no text decision timeout
  • no possibility of accepting an offer and then waiting for a missing text payload
  • no shared decision plumbing pretending that text and files have identical needs

This leaves a smaller path with fewer intermediate states and fewer ways for text delivery to become stuck.

Important compatibility warning

This is a breaking preview-stage protocol change even though the advertised protocol version intentionally remains 1.

Sync360 0.2.0 and older text implementations use:

  • POST /sync360/text/offer
  • POST /sync360/text/transfer

Sync360 0.3.0 uses:

  • POST /sync360/text/deliver

Old and new builds can still discover each other because the advertised protocol version has not been increased, but text delivery between them is incompatible.

Users testing 0.3.0 should update Sync360 on every participating device. Mixed 0.2.x/0.3.0 setups are not supported.

The protocol version is being kept at 1 deliberately while the project remains in preview and its networking design is still evolving. Compatibility gating can be introduced when the protocol becomes stable enough to support it honestly.

Version update

This prepares preview version 0.3.0 across the current package targets:

  • Android versionName: 0.3.0
  • Android versionCode: 3
  • Desktop package version: 0.3.0
  • iOS marketing version: 0.3.0
  • iOS build version: 3

The permanent Windows MSI upgrade UUID is unchanged.

Documentation

The following documentation now describes direct text delivery separately from receiver-approved files:

  • README
  • changelog
  • project context
  • architecture guide
  • development guide
  • roadmap

The security documentation remains explicit that Sync360 currently uses cleartext local HTTP and raw TCP. Direct text has no receiver approval, and neither text nor files currently have peer authentication or encryption.

Replace the text offer and follow-up transfer handshake with one POST /sync360/text/deliver request carrying the sender device name and complete text payload. Return explicit delivered, receiver-busy, and text-too-large statuses so the sender can report predictable outcomes without a text operation ID or decision phase.

Enforce the 100,000-character limit in send UI state, the Send ViewModel, outgoing coordination, and incoming coordination. Admit received text only while ClientServerState is Idle, with the Idle check and TextReceived publication performed atomically under the existing operation mutex.

Remove text Accept/Decline, waiting state, deferred decision plumbing, remote cancellation, and Cancel UI while preserving sender progress/result feedback, received-text navigation, sender-name presentation, Copy, and Clear & Close.

Keep file offers, user decisions, operation IDs, cancellation, decision and preparation timeouts, progress reporting, and raw TCP batch streaming file-specific. Rename shared incoming decision plumbing to make its file-only ownership explicit.

Update README, changelog, project context, architecture, development, and roadmap documentation to describe direct text delivery separately from receiver-approved files. Set Android, Desktop, and iOS package versions to 0.3.0 with build/version code 3 while intentionally retaining discovery protocol version 1 for the preview stage.

Gradle builds and tests were not run as part of this commit.
@CodePandaaAI
CodePandaaAI merged commit 0417fa9 into master Aug 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant