feat: prepare Sync360 v0.1.0 with native Windows/iOS support and new sharing UX - #17
Merged
Merged
Conversation
…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
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.
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.0release.The first downloadable release will include:
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
Runningstate.Native Windows discovery
dnsapi.dll.0so Windows can select applicable network interfaces.iOS implementation
Sharing UI and state
SendScreenState.SendScreenViewModel.File selection
FileItemCardimplementation.Receive UI and application shell
Branding and Desktop startup
Release preparation
0.1.0.keystore.properties.keystore.properties.examplewithout private credentials.packageMsitask for the first Windows release.Architecture preserved
This PR does not change Sync360’s core transfer architecture:
Validation status
Completed or previously observed:
Required before publishing
v0.1.0:No new Gradle build or automated test was run as part of the final UI and release-preparation changes.
Current limitations
v0.1.0.