Skip to content

feat: prepare Sync360 v0.1.0 with native Windows/iOS support and new sharing UX - #17

Merged
CodePandaaAI merged 9 commits into
masterfrom
refactor-network-services
Aug 4, 2026
Merged

feat: prepare Sync360 v0.1.0 with native Windows/iOS support and new sharing UX#17
CodePandaaAI merged 9 commits into
masterfrom
refactor-network-services

Conversation

@CodePandaaAI

Copy link
Copy Markdown
Owner

Summary

This PR brings together nine commits that expand Sync360’s native platform support, improve discovery lifecycle handling, redesign the cross-platform sharing experience, refresh application branding, and prepare the project for its first public v0.1.0 release.

The first downloadable release will include:

  • Android release APK
  • Windows MSI

iOS is implemented in source and supported by an iOS CI workflow, but no public iOS artifact will be included in v0.1.0. macOS and Linux continue using the existing JmDNS fallback.

Network discovery and lifecycle

  • Made discovery and registration lifecycle state-driven.
  • Added explicit registration states alongside discovery states.
  • Derived the discovery timeout from the real Running state.
  • Improved restart and repair coordination.
  • Prevented late discovery results from repopulating stopped sessions.
  • Improved cleanup and retry behavior when platform shutdown operations fail.
  • Preserved multi-address discovery and connection fallback.

Native Windows discovery

  • Replaced JmDNS on Windows with the native Windows DNS-SD API from dnsapi.dll.
  • Added focused JDK Foreign Function and Memory bindings.
  • Added native registration, browsing, resolution, cancellation, and deregistration.
  • Used interface index 0 so Windows can select applicable network interfaces.
  • Handled service-removal callbacks and native resource lifetimes explicitly.
  • Kept JmDNS as the current macOS and Linux implementation.
  • Updated Desktop/JVM configuration for JDK 23 and native-access requirements.

iOS implementation

  • Enabled iOS device and Apple Silicon simulator targets.
  • Added iOS Koin setup and application startup wiring.
  • Added native Bonjour registration, browsing, resolution, and address handling.
  • Added iOS local identity and device information.
  • Added clipboard support.
  • Added native multi-file document selection.
  • Added Files-visible Downloads storage and folder opening.
  • Added streamed TCP file sending and receiving using the existing shared protocol.
  • Preserved explicit native callback and operation lifetimes.
  • Added an iOS-only GitHub Actions workflow for Simulator builds and optional development-signed device packages.
  • Corrected Kotlin/Native and Apple API compatibility issues found during source and CI validation.

Sharing UI and state

  • Redesigned the Send experience using Material 3 Expressive components.
  • Replaced the previous secondary tabs with an expressive button group.
  • Added explicit nearby-device selection.
  • Added contextual actions such as sending text or files to the selected device.
  • Kept selected-device state, send availability, and button labels in SendScreenState.
  • Kept transfer decisions and validation in SendScreenViewModel.
  • Automatically clears selection when a device disappears.
  • Simplified nearby-device cards and scanning presentation.
  • Added radio-selection accessibility semantics.
  • Improved text input, clear actions, and character feedback.

File selection

  • Added one shared file-selection presentation for Android, Desktop, and iOS.
  • Kept native picker wiring inside each platform source set.
  • Added responsive file thumbnails for phone, tablet, and desktop widths.
  • Added a horizontally scrollable selected-files row.
  • Added filename overlays and individual remove actions.
  • Added image previews through Coil with file-type fallbacks.
  • Deduplicated selected files using their stable URI.
  • Fixed Desktop file selection after the shared UI migration.
  • Preserved the AWT file dialog lifecycle.
  • Preserved the iOS document-picker delegate for the required native lifetime.
  • Removed the obsolete FileItemCard implementation.

Receive UI and application shell

  • Refined incoming text and file offer presentation.
  • Improved received-text and received-file result screens.
  • Refined transfer-progress presentation.
  • Updated shared surfaces and shapes while preserving the project’s established Material color hierarchy.
  • Improved compact and wide-screen sharing layouts.
  • Refined the floating navigation presentation.

Branding and Desktop startup

  • Refreshed Android launcher and Play Store artwork.
  • Refreshed Desktop PNG, ICO, and ICNS assets.
  • Updated the shared Compose application icon.
  • Added a smaller Desktop startup splash using the current Sync360 branding.
  • Preserved platform-appropriate icon formats and adaptive Android resources.

Release preparation

  • Set Android, Desktop, and iOS version metadata to 0.1.0.
  • Added optional Android release signing through ignored keystore.properties.
  • Added keystore.properties.example without private credentials.
  • Added a permanent Windows MSI upgrade UUID.
  • Kept the normal packageMsi task for the first Windows release.
  • Updated the Gradle, Kotlin, Android, and Compose toolchain configuration.
  • Updated README, architecture, development, security, privacy, roadmap, contribution, store-listing, and changelog documentation.
  • Corrected stale platform, privacy, security, and packaging claims.

Architecture preserved

This PR does not change Sync360’s core transfer architecture:

  • DNS-SD/mDNS handles nearby-device discovery.
  • Ktor HTTP remains the control plane for offers, decisions, metadata, and text.
  • Raw platform TCP sockets remain the file data plane.
  • Files continue to be streamed instead of loaded completely into memory.
  • Common state and behavior remain in shared code.
  • Native APIs and file pickers remain inside their platform source sets.
  • UI renders state and emits user actions; it does not own transfer or discovery state.

Validation status

Completed or previously observed:

  • Source-level review of the shared Send state and platform picker boundaries.
  • Initial Windows native DNS-SD behavior observed on Windows 11.
  • iOS Simulator build workflow and cloud-simulator startup previously exercised.
  • Existing Android and Desktop transfer paths have prior manual validation.

Required before publishing v0.1.0:

  • Build the final signed Android release APK.
  • Build the final normal Windows MSI.
  • Install the exact generated release artifacts.
  • Test Android-to-Windows and Windows-to-Android discovery.
  • Test text transfers in both directions.
  • Test single-file and multi-file transfers in both directions.
  • Test Accept, Decline, Cancel, Downloads storage, restart, and repair.
  • Verify the Android APK signature.
  • Upload the tested APK and MSI to the GitHub Release.

No new Gradle build or automated test was run as part of the final UI and release-preparation changes.

Current limitations

  • Transfers are not yet encrypted or authenticated.
  • Sync360 should currently be used only on trusted local networks.
  • Background lifecycle support remains incomplete.
  • Some networks block multicast discovery or isolate connected clients.
  • Windows firewall configuration can affect discovery and transfers.
  • The Windows MSI is currently unsigned and may show an unknown-publisher warning.
  • iOS still requires broader physical-device validation.
  • macOS and Linux retain JmDNS and do not yet use native discovery backends.
  • Automated discovery and transfer coverage remains limited.
  • No iOS, macOS, or Linux download will be published with v0.1.0.

…iven

Move network-service startup out of SendScreenViewModel and into the Android
and Desktop application entry points so the HTTP server, file receiver,
service registration, and discovery are started once for the application
lifetime rather than whenever the Send ViewModel is created.

Return the bound TCP port directly from FileTransferReceiver.start() on both
Android and JVM. This lets NetworkServicesController receive the final
OS-assigned port as part of startup instead of starting the receiver and then
reading mutable port state separately.

Add RegistrationStatus alongside DiscoveryStatus and expose both through the
NetworkServices contract. Track registration independently as Idle, Starting,
Running, or Stopping instead of using extra Boolean flags that can disagree
with platform callbacks.

Rework NetworkServicesController to:

- guard one-time application startup with the lifecycle mutex and hasStarted
- serialize lifecycle transitions for startup, restart, repair, and timed stop
- derive the 60-second discovery timeout from DiscoveryStatus.Running
- cancel the active timeout automatically when discovery leaves Running
- allow discovery restart only while discovery is Idle
- prevent duplicate repair requests with a separate repair request mutex
- wait until discovery and registration reach stable states before repairing
- reuse the already-running HTTP and TCP server ports during repair
- expose registration state to the shared UI

Rework Android NSD lifecycle handling to:

- separate discovery startup from service registration
- derive discovery and registration states from NsdManager callbacks
- return failed start, stop, registration, and unregistration operations to
  the state that matches the reported NSD outcome
- coordinate repair through pending state instead of callback timeouts and
  CompletableDeferred objects
- restart registration and discovery only after both previous operations have
  reached Idle
- cancel pending repair when an NSD operation fails
- ignore service-found and resolved callbacks after discovery has stopped
- clear stale nearby devices when discovery stops or fails
- track Android 14+ ServiceInfoCallbacks from registration time so every
  active callback can be unregistered during cleanup
- remove callbacks after registration failure, service loss, invalid service
  updates, or callback unregistration
- retain the existing resolver path for Android 13

Strengthen JVM JmDNS lifecycle handling by:

- tracking discovery and registration as separate state flows
- reusing registered JmDNS instances when only discovery is restarted
- closing and recreating all instances during full connection repair
- retaining instances whose close operation fails so later repair can retry
  cleanup instead of forgetting resources that may still be active
- cleaning up listeners already added when listener startup partially fails
- returning both lifecycle states to Idle after startup or cleanup failure
- ignoring late resolved-service callbacks after discovery has stopped
- clearing resolved and visible devices when listeners stop
- requiring active registration before restarting discovery
- removing the duplicate listenersAreRunning state

Add JVM IPv6 discovery and advertisement support by starting JmDNS on eligible
IPv4 and IPv6 addresses from active multicast-capable LAN interfaces. Include
resolved IPv6 addresses in nearby-device endpoints and restore the appropriate
interface scope for link-local IPv6 addresses when JmDNS does not provide one.

Update shared UI behavior so:

- registration state is collected into SendScreenState
- Reload is available only when discovery is Idle and registration is Running
- the empty-state message directs users to connection repair when a normal
  discovery restart is not currently valid
- connection repair is enabled only while transfers are idle and both network
  lifecycle states are stable
- the Settings repair explanation is clearer and uses a primary button

Update the README, architecture guide, development guide, and roadmap to
document multi-interface IPv4/IPv6 JmDNS behavior while keeping broader
platform, adapter, scoped-address, and transfer validation listed as ongoing
work.
Windows now uses its own DNS-SD service for finding and advertising
nearby devices instead of JmDNS.

This made discovery faster and more reliable in my Windows 11 testing.
Android appears quickly on Windows, and Windows appears quickly on
Android. When either app is closed, that device is also removed from
the nearby list without waiting for another full discovery scan.

The Desktop loading indicator now changes correctly when discovery
starts, so it no longer keeps showing loading after devices are already
visible.

Windows handles the available network interfaces and returns IPv4,
IPv6, ports, and device information. Discovery, registration, stopping,
and connection repair still follow the same shared states and app flow
used by Android.

JmDNS is still used on macOS and Linux for now.

Desktop now uses JDK 23 so the Windows API can be called directly
without adding JNA or another native library. The Kotlin, Gradle, AGP,
and related documentation versions were also updated.

This was manually tested between a Windows 11 desktop connected through
Ethernet and Android. Laptop, macOS, Linux, and more network setups
still need testing. A full Gradle build was not run.
- enable iosArm64 and iosSimulatorArm64 targets
- initialize Koin and network services from the iOS entry point
- render the shared Sync360 UI with the correct iOS theme
- add native Apple DNS-SD discovery and registration
- resolve IPv4, IPv6, ports, TXT records, and service removals
- preserve explicit DNS-SD callback and reference lifetimes
- add persistent device identity, device information, and clipboard support
- add native multi-file document picking
- stream file batches through Ktor TCP using the shared protocol
- save received files safely under Documents/Downloads
- clean incomplete files and avoid overwriting existing files
- expose received files through the iOS document browser
- encode scoped IPv6 hosts correctly in HTTP URLs
- add local-network, Bonjour, and Files app configuration
- target iOS 15 and later
- add an iOS-only GitHub Actions workflow
- upload an unsigned Simulator app for browser-based testing
- support optional development-signed IPA generation for registered iPhones

The native Bonjour source was compile-checked for iosArm64 and
iosSimulatorArm64 with Kotlin/Native 2.4.10. Full application
compilation, linking, signing, and runtime testing still require
the macOS GitHub runner or a Mac with Xcode.
- enable iosArm64 and iosSimulatorArm64 targets
- initialize Koin and network services from the iOS entry point
- render the shared Sync360 UI with the correct iOS theme
- add native Apple DNS-SD discovery and registration
- resolve IPv4, IPv6, ports, TXT records, and service removals
- preserve explicit DNS-SD callback and reference lifetimes
- add persistent device identity, device information, and clipboard support
- add native multi-file document picking
- stream file batches through Ktor TCP using the shared protocol
- save received files safely under Documents/Downloads
- clean incomplete files and avoid overwriting existing files
- expose received files through the iOS document browser
- encode scoped IPv6 hosts correctly in HTTP URLs
- add local-network, Bonjour, and Files app configuration
- target iOS 15 and later
- add an iOS-only GitHub Actions workflow
- upload an unsigned Simulator app for browser-based testing
- support optional development-signed IPA generation for registered iPhones

The native Bonjour source was compile-checked for iosArm64 and
iosSimulatorArm64 with Kotlin/Native 2.4.10. Full application
compilation, linking, signing, and runtime testing still require
the macOS GitHub runner or a Mac with Xcode.
- enable iosArm64 and iosSimulatorArm64 targets
- initialize Koin and network services from the iOS entry point
- render the shared Sync360 UI with the correct iOS theme
- add native Apple DNS-SD discovery and registration
- resolve IPv4, IPv6, ports, TXT records, and service removals
- preserve explicit DNS-SD callback and reference lifetimes
- add persistent device identity, device information, and clipboard support
- add native multi-file document picking
- stream file batches through Ktor TCP using the shared protocol
- save received files safely under Documents/Downloads
- clean incomplete files and avoid overwriting existing files
- expose received files through the iOS document browser
- encode scoped IPv6 hosts correctly in HTTP URLs
- add local-network, Bonjour, and Files app configuration
- target iOS 15 and later
- add an iOS-only GitHub Actions workflow
- upload an unsigned Simulator app for browser-based testing
- support optional development-signed IPA generation for registered iPhones

The native Bonjour source was compile-checked for iosArm64 and
iosSimulatorArm64 with Kotlin/Native 2.4.10. Full application
compilation, linking, signing, and runtime testing still require
the macOS GitHub runner or a Mac with Xcode.
Improve the transfer experience across the shared app screens and give the
Desktop app a clearer startup moment.

Desktop:
- Show a small white splash screen with the Sync360 logo while the packaged
  Desktop app starts.
- Package the splash image with the app so it is available to the launcher.

Android:
- Remove a nearby device from the list as soon as Android reports that its
  advertised service has disappeared.
- This prevents devices that have closed the app or left the network from
  remaining visible as stale entries.

Shared UI:
- Refresh text and file offer screens with clearer previews and balanced
  Accept and Decline actions.
- Keep action buttons together with the related content instead of separating
  them at the bottom of the screen.
- Make receive, send, progress, and result screens scroll safely on smaller
  windows and phone screens.
- Improve button sizing and long-label handling so controls stay usable in
  tighter layouts.
- Simplify the received-text flow with clear Copy and Clear & Close actions.
- Remove an unused visual import from the nearby-device card.

Ui.kt is intentionally excluded from this commit.
Adopt the new Sync360 logo across the Android and Desktop app experience.

Android:
- Update the Play Store image and launcher icons for every supported screen size.
- Refresh the normal, round, foreground, and monochrome icon variants.
- Keep the selected white icon background across the Android launcher artwork.

Desktop:
- Update the Windows, macOS, Linux, and Desktop-window icons with the new logo.
- Keep the Windows and macOS icon files sharp at both small and large system sizes.
- Refresh the small startup splash with the centered Sync360 logo on a clean white background.

UI:
- Give the shared floating navigation bar a more rounded appearance.

This commit updates the visible branding only. It does not change nearby-device discovery,
sharing, or transfer behavior.
Prepare Sync360 for its first public Android and Windows release while
improving the send flow across Android, desktop, and iOS.

Send experience:
- replace secondary send tabs with a Material 3 Expressive button group
- add explicit nearby-device selection before starting a transfer
- show contextual send actions using the selected device name
- keep selected-device state and derived send availability in screen state
- validate selected content and target device in the ViewModel
- clear device selection when the selected device is no longer available
- improve empty, scanning, selected, and unavailable device presentation
- add accessible radio-selection semantics to nearby-device cards
- simplify nearby-device information by hiding unnecessary technical details
- add text character count, clear action, and improved input guidance

File selection:
- introduce shared file-selection content across supported platforms
- replace the expanding vertical file list with a horizontal lazy row
- add larger file cards with filenames, sizes, previews, and remove actions
- display image thumbnails when available through Coil
- show suitable file-type fallbacks for files without image previews
- report selected file count and total size without misrepresenting unknown sizes
- prevent duplicate files from being added using their stable URI
- change the picker action from selecting files to adding more files
- keep picker implementations platform-specific while sharing presentation
- fix desktop file selection by reading files from the AWT dialog explicitly
- preserve the iOS document-picker delegate for the required native lifetime
- keep Android picker and URI handling inside the Android implementation

Architecture and state:
- keep UI components declarative and driven by immutable screen state
- route user actions through callbacks and ViewModel event handlers
- avoid platform ViewModel injection inside file-picker implementations
- centralize shared file presentation without changing transfer behavior
- use supported Material 3 Expressive button-group APIs
- preserve existing network discovery and transfer flows

Release preparation:
- set Android, desktop, and iOS version metadata to 0.1.0
- add optional Android release-signing configuration through ignored properties
- provide a safe example keystore-properties file
- configure Windows MSI packaging and stable upgrade identity
- resize the desktop splash artwork for a more appropriate launch window
- keep local signing credentials and generated release material out of Git

Documentation:
- update README platform and installation information
- document current Android and Windows packaging workflows
- clarify local-network behavior, privacy, and present security limitations
- update architecture, development, contribution, and open-source notes
- refresh roadmap, changelog, store listing, and security guidance
- remove or correct stale platform and implementation claims

No Gradle builds or automated tests were run.
- separate the Material 3 Expressive button group from send content
- simplify file selection around large, responsive previews
- scale file thumbnails for phone, tablet, and desktop widths
- overlay filenames directly on previews while preserving extensions
- add compact remove actions to individual file previews
- keep selected files inside a horizontally scrollable row
- simplify file-picker actions and selected-file information
- remove the obsolete FileItemCard component
- refine nearby-device card shapes, layering, and spacing
- align reload controls with the established surface hierarchy
- align the floating navigation bar with the scaffold background
- allow Sync360Surface callers to provide an appropriate corner shape
- preserve existing send state, device selection, picker, and transfer flows
@CodePandaaAI
CodePandaaAI merged commit 56c00cd into master Aug 4, 2026
4 checks passed
@CodePandaaAI
CodePandaaAI deleted the refactor-network-services branch August 18, 2026 13:26
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