Skip to content

Commit 93fd0d8

Browse files
committed
feat: prepare v0.1.0 and redesign the cross-platform send experience
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.
1 parent 823b87c commit 93fd0d8

32 files changed

Lines changed: 773 additions & 656 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ captures/
2424

2525
# Signing secrets
2626
*.jks
27+
*.jkis
2728
*.keystore
2829
keystore.properties
2930

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
2525
- Compose Desktop startup, platform DI implementations, native file dialog, clipboard, and Downloads actions.
2626
- Navigation 3 adaptive 50/50 Send/Receive scene for wider windows.
2727
- Application-lifetime network startup and state-driven connection repair.
28+
- Enabled iOS device and Apple-silicon Simulator targets with native Bonjour discovery, document selection, clipboard, Files-visible storage, and streamed TCP transfer implementations.
29+
- Added an iOS-only GitHub Actions workflow for an unsigned Simulator app and optional development-signed iPhone IPA.
30+
- Prepared version `0.1.0` across Android, Desktop, and iOS; added private Android release signing configuration and a permanent Windows MSI upgrade identity.
2831
- Public architecture, development, roadmap, security, privacy, and contribution documentation.
2932

3033
### Changed
@@ -52,4 +55,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5255
- No speed, ETA, retry, pause/resume, or interrupted-transfer recovery; transfer progress currently shows batch-wide whole-byte percentage.
5356
- Foreground/background and network-change lifecycle handling are incomplete.
5457
- Desktop support needs broader operating-system, adapter, firewall, and router validation.
55-
- Automated transfer coverage is minimal; iOS is inactive.
58+
- Automated transfer coverage is minimal; iOS physical-device discovery and transfer are unverified.

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Project maintainers may remove comments, close issues, reject contributions, or
3030

3131
If you see a problem, report it privately to the maintainer.
3232

33-
Maintainer contact: TODO: add private contact email
33+
Until a dedicated contact email is added, contact the maintainer privately through the GitHub or LinkedIn profile linked in `README.md`.
3434

3535
## Scope
3636

CONTRIBUTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ Implemented today:
1313
- Current macOS/Linux discovery and registration through JmDNS.
1414
- Direct text and multi-file transfer between nearby devices.
1515
- Shared Compose UI for Android and Desktop.
16+
- Enabled iOS source implementation for Bonjour discovery, text/file transfer, selection, clipboard, and Files-visible storage.
1617

1718
Important current limitations:
1819

1920
- Local transfers are not authenticated or encrypted.
2021
- Background and automatic network-change lifecycle handling is incomplete.
2122
- Desktop networking has not been broadly validated across operating systems, adapters, VPNs, and routers.
22-
- iOS platform implementations are inactive.
23+
- iOS physical-device discovery and transfer behavior is not yet validated.
2324

2425
Please keep that status in mind when opening issues or PRs.
2526

PRIVACY.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,35 @@
11
# Sync360 Privacy
22

3-
Last updated: June 29, 2026
3+
Last updated: August 3, 2026
44

5-
Sync360 is currently an early rebuild prototype. The current Android-first milestone supports local discovery and a simple Ktor request/response proof between nearby devices. Real text transfer, file transfer, production security, and public releases are not implemented yet.
5+
Sync360 sends text and files directly between nearby devices on the same reachable local network. It does not use a Sync360 account, cloud-storage service, analytics service, advertising service, or Sync360 transfer backend.
66

77
## Data Handling
88

99
- No account is required.
10-
- No cloud service is used by the current prototype flow.
10+
- No cloud service is used for discovery or transfer.
1111
- No analytics, advertising, tracking, or telemetry is included.
1212
- A random installation identifier is stored locally so devices can identify each other.
13-
- Nearby-device discovery data stays on the local device while the app is running.
14-
- The current prototype does not transfer or save user-selected files.
15-
- The current prototype does not send user content to the developer.
13+
- Nearby-device discovery information is exchanged only with devices on the reachable local network and is kept as runtime state.
14+
- Text and selected files are sent directly to the receiver chosen by the user after the receiver approves the offer.
15+
- Received files remain on the receiving device in its platform Downloads location.
16+
- Shared text and transfer state are temporary runtime state; Sync360 does not maintain chat or clipboard history.
17+
- Sync360 does not send shared content to the developer.
1618

1719
## Network Security
1820

19-
The current prototype uses cleartext HTTP on the local network for learning and testing. Final authentication, session validation, request signing, replay protection, and encryption are not implemented yet.
21+
Sync360 currently uses cleartext local HTTP for offers and text and raw TCP for file bytes. Sender authentication, session validation, request signing, replay protection, encryption, and cryptographic integrity verification are not implemented yet. Receiver approval exists in the UI but is not a complete security boundary.
2022

2123
Do not treat the current code as production-secure file-transfer software. Use it only on private networks you control while testing.
2224

2325
## Permissions
2426

25-
Sync360 uses network access for local discovery and request/response testing. Future versions may require additional Android permissions for reliable transfer sessions, notifications, foreground services, wake locks, Wi-Fi multicast behavior, and file access.
27+
Sync360 uses network access for local discovery and direct transfer. Android uses system file pickers and `MediaStore` for selected and received files. iOS source declares local-network and Bonjour usage and exposes its app Documents directory through Files. Future lifecycle work may require notification, foreground-service, wake-lock, or other platform permissions.
2628

2729
## Retention
2830

29-
The current prototype stores a local installation identifier. Discovery/request state is runtime state. Real transfer retention behavior will be documented when file transfer is implemented.
31+
Sync360 stores a local installation identifier. Discovery, offer, text, and transfer state are runtime state. Files successfully received remain in Downloads until the user removes them through the operating system. Incomplete current files are removed after receive failure or cancellation where the platform implementation supports it.
3032

3133
## Contact
3234

33-
Add a support email or website before publishing this policy.
35+
For privacy questions, contact the maintainer through the GitHub profile linked in `README.md`. Report security-sensitive findings through the private-contact guidance in `SECURITY.md`.

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Chat apps and cloud drives are great when the other person is far away. Sync360
4242

4343
## Current status
4444

45-
Sync360 has a working Android-to-Android MVP for text and multiple-file transfer. The Desktop/JVM app now uses the same shared flow, and Desktop-to-Android file transfer is working in manual testing. It is still an active rebuild, not a production-ready release.
45+
Sync360 has a working Android-to-Android MVP for text and multiple-file transfer. The Desktop/JVM app now uses the same shared flow, and Desktop-to-Android file transfer is working in manual testing. An initial iOS implementation is enabled in source and has opened successfully in a cloud simulator, but nearby discovery and transfer still need physical-device validation. It is still an active rebuild, not a production-ready release.
4646

4747
In an initial Windows 11 Ethernet test, the native Windows DNS-SD backend discovered the Android device quickly, removed it promptly after the Android app closed, appeared promptly on Android after Sync360 started, and disappeared from Android after the Desktop app closed. The Desktop discovery UI also left its initial loading state when the native browse operation started instead of continuing to show loading while resolved devices were already visible. These are manual observations from one setup, not broad Windows or laptop compatibility guarantees.
4848

@@ -67,6 +67,7 @@ In an initial Windows 11 Ethernet test, the native Windows DNS-SD backend discov
6767
- Save received Desktop files safely into Downloads through a temporary `.part` file, then move completed files into place without overwriting an existing name.
6868
- Copy received text and open the Downloads folder on Desktop.
6969
- Open connection troubleshooting from Send, Receive, or the top app bar, then manually restart local discovery and service advertising without resetting the app or removing received files.
70+
- Provide enabled iOS device and simulator targets with native Bonjour discovery, file selection, clipboard, Files-visible storage, and streamed TCP transfer implementations.
7071

7172
### Still needs work
7273

@@ -79,7 +80,8 @@ In an initial Windows 11 Ethernet test, the native Windows DNS-SD backend discov
7980
- Automated transfer coverage and broader device/router testing.
8081
- Broader Desktop validation across Windows, macOS, Linux, routers, firewalls, VPNs, and machines with multiple network adapters.
8182
- Desktop packaging and release testing.
82-
- iOS discovery, transfer, and storage implementations.
83+
- Physical iOS device testing for local-network permission, discovery, text/file transfer, cancellation, and Files behavior.
84+
- Public iOS packaging, signing, and distribution.
8385

8486
The current progress UI tracks the exact bytes transferred across the accepted batch and displays the resulting percentage.
8587

@@ -154,9 +156,10 @@ Compose screen -> ViewModel -> controller/service -> common contract -> platform
154156
- `shared/src/androidMain/` — Android NSD, file selection metadata, clipboard, local identity, raw TCP transfer, Downloads storage, and Android DI bindings.
155157
- `shared/src/jvmMain/` — Windows system DNS-SD and macOS/Linux JmDNS discovery/registration, native file selection metadata, clipboard, local identity, raw TCP transfer, Downloads storage, and Desktop DI bindings.
156158
- `desktopApp/` — Compose Desktop entry point and DMG/MSI/DEB packaging configuration.
157-
- `iosApp/` — iOS shell; iOS targets are currently disabled in the shared Gradle configuration.
159+
- `shared/src/iosMain/` — iOS Bonjour discovery/registration, file selection, clipboard, identity, streamed TCP transfer, Files-visible storage, and iOS DI bindings.
160+
- `iosApp/` — SwiftUI iOS host for the enabled device and Apple-silicon Simulator targets.
158161

159-
The project remains Android-first, but the current Desktop app reuses the shared UI, ViewModels, controllers, HTTP protocol, and transfer contracts. Platform source sets implement only the parts that require Android or JVM APIs.
162+
The project remains Android-first, but Desktop and iOS reuse the shared UI, ViewModels, controllers, HTTP protocol, and transfer contracts. Platform source sets implement only the parts that require Android, JVM, or iOS APIs.
160163

161164
## Tech stack
162165

@@ -262,7 +265,7 @@ Use the current app only for development and testing on private networks you con
262265
### Later: bring the same simple flow to more devices
263266

264267
- Desktop packaging, release workflow, and broader compatibility testing.
265-
- iOS investigation and implementation.
268+
- iOS physical-device validation, signing, and distribution.
266269
- More actionable connection errors and broader troubleshooting guidance.
267270
- Retry or resume support where the added protocol complexity is justified.
268271

SECURITY.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Security Policy
22

3-
Sync360 is an early local-network sharing app. It is not production-secure yet.
3+
Sync360 is an early local-network sharing app. It is not secure for untrusted networks yet.
44

5-
The current rebuild intentionally focuses on understanding local discovery and request/response before adding the final security model. Security work is planned, especially before real file transfer is treated as user-ready.
5+
The current rebuild implements local discovery, receiver-approved text sharing, and streamed file transfer before adding the final security model. Security work remains required before untrusted-network use.
66

77
## Supported versions
88

@@ -16,13 +16,7 @@ There are no stable supported releases yet.
1616

1717
Please do not open a public issue for security-sensitive reports.
1818

19-
Send private reports to:
20-
21-
```text
22-
TODO: add security contact email
23-
```
24-
25-
Until a contact email is added, please contact the maintainer privately through their GitHub/LinkedIn profile once available.
19+
Until a dedicated security email is added, contact the maintainer privately through the GitHub or LinkedIn profile linked in `README.md`. Do not include exploit details in a public issue.
2620

2721
## What to report privately
2822

@@ -43,16 +37,15 @@ General bugs, crashes, UI issues, documentation problems, and non-sensitive arch
4337

4438
## Current security status
4539

46-
Current implementation is a learning-stage prototype:
40+
Current implementation:
4741

48-
- Android NSD discovery works.
49-
- Ktor request/response proof exists.
50-
- Receiver Accept/Decline proof exists.
51-
- Real file transfer is not implemented yet.
52-
- Final authentication/session validation is not implemented yet.
53-
- Encryption is not implemented yet.
42+
- Android NSD, Windows system DNS-SD, macOS/Linux JmDNS, and an initial iOS Bonjour implementation exist.
43+
- Ktor carries text/file offers, receiver decisions, metadata, and accepted text.
44+
- Raw TCP streams accepted file batches to platform Downloads storage.
45+
- File names and promised sizes are validated, but a file socket is not bound to its approved offer with a session token.
46+
- Sender authentication, encryption, replay protection, and cryptographic integrity verification are not implemented.
5447

55-
Do not use the current code as a security model for production file transfer.
48+
Use current builds only on private local networks you control. Do not use the current code as a security model for production file transfer.
5649

5750
## Planned security work
5851

STORE_LISTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@ Share text and files directly between your Android and desktop devices over your
66

77
## Security Notice
88

9-
Sync360 currently uses trusted-network mode. Connections require device approval and authenticated session requests, but transferred content is not encrypted by Sync360.
9+
Sync360 currently uses trusted-network mode. The receiver approves offers in the UI, but requests and file sockets are not authenticated and transferred content is not encrypted by Sync360.
1010

1111
Use Sync360 only on a private home network or personal hotspot controlled by you. Do not use it on public or shared networks such as cafes, hotels, airports, schools, or offices.
1212

1313
## Privacy Summary
1414

1515
- Direct local-network transfer; no transfer cloud.
1616
- No account, ads, analytics, tracking, or telemetry.
17-
- Session approvals, tokens, and shared text are temporary.
17+
- Offer decisions, transfer state, and shared text are temporary runtime state.
1818
- Received files remain on the receiving device.
1919

2020
## Publishing Checklist
2121

22-
- Add support contact to `PRIVACY.md`.
22+
- Keep the maintainer contact in `PRIVACY.md` current.
2323
- Publish `PRIVACY.md` at a public URL for store submission.
2424
- Keep store data-safety answers consistent with shipped code and permissions.
2525
- Revisit this disclosure before adding crash reporting, analytics, cloud services, or encrypted pairing.

androidApp/build.gradle.kts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2+
import java.util.Properties
23

34
plugins {
45
alias(libs.plugins.androidApplication)
56
alias(libs.plugins.composeMultiplatform)
67
alias(libs.plugins.composeCompiler)
78
}
89

10+
val releaseSigningPropertiesFile = rootProject.file("keystore.properties")
11+
val releaseSigningProperties = Properties().apply {
12+
if (releaseSigningPropertiesFile.isFile) {
13+
releaseSigningPropertiesFile.inputStream().use(::load)
14+
}
15+
}
16+
val releaseSigningIsConfigured = listOf(
17+
"storeFile",
18+
"storePassword",
19+
"keyAlias",
20+
"keyPassword"
21+
).all { propertyName ->
22+
!releaseSigningProperties.getProperty(propertyName).isNullOrBlank()
23+
}
24+
925
kotlin {
1026
compilerOptions {
1127
jvmTarget.set(JvmTarget.JVM_17)
@@ -21,7 +37,7 @@ android {
2137
minSdk = libs.versions.android.minSdk.get().toInt()
2238
targetSdk = libs.versions.android.targetSdk.get().toInt()
2339
versionCode = 1
24-
versionName = "1.0"
40+
versionName = "0.1.0"
2541
}
2642

2743
buildFeatures {
@@ -34,11 +50,24 @@ android {
3450
}
3551
}
3652

53+
signingConfigs {
54+
if (releaseSigningIsConfigured) {
55+
create("release") {
56+
storeFile = rootProject.file(
57+
releaseSigningProperties.getProperty("storeFile")
58+
)
59+
storePassword = releaseSigningProperties.getProperty("storePassword")
60+
keyAlias = releaseSigningProperties.getProperty("keyAlias")
61+
keyPassword = releaseSigningProperties.getProperty("keyPassword")
62+
}
63+
}
64+
}
65+
3766
buildTypes {
3867
getByName("release") {
3968
isMinifyEnabled = true
4069
isShrinkResources = true
41-
signingConfig = signingConfigs.getByName("debug")
70+
signingConfig = signingConfigs.findByName("release")
4271
proguardFiles(
4372
getDefaultProguardFile("proguard-android-optimize.txt"),
4473
"proguard-rules.pro"

context.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ The old AI-generated sync implementation was removed. The current app is being r
2121
- Multiple files sent sequentially over one accepted-batch connection.
2222
- Android file access through `ContentResolver` and Downloads writing through `MediaStore`.
2323
- Desktop native file selection, Java file streams, and safe Downloads writing through temporary `.part` files.
24+
- iOS Bonjour discovery, native document selection, streamed Ktor TCP transfer, and Files-visible Downloads storage.
2425
- Best-effort cancellation and batch-wide byte percentage.
2526

26-
Android-to-Android text and multiple-file flows have manual validation. Desktop-to-Android transfer has initial manual validation. In one Windows 11 Ethernet test, native Windows discovery added and removed Android promptly as its app opened and closed, while Android added and removed Windows promptly as the Desktop app opened and closed. Laptop, macOS, Linux, and broader adapter/network behavior still need validation. The app is still development software, not a production-ready release.
27+
Android-to-Android text and multiple-file flows have manual validation. Desktop-to-Android transfer has initial manual validation. In one Windows 11 Ethernet test, native Windows discovery added and removed Android promptly as its app opened and closed, while Android added and removed Windows promptly as the Desktop app opened and closed. The enabled iOS implementation has opened successfully in a cloud simulator, but same-LAN discovery and transfer could not be tested there. Laptop, macOS, Linux, physical iOS, and broader adapter/network behavior still need validation. The app is still development software, not a production-ready release.
2728

2829
## Architecture rule
2930

@@ -37,7 +38,7 @@ Compose screen -> ViewModel -> controller/service -> common contract -> platform
3738
- Ktor DTOs remain at the HTTP boundary.
3839
- Blocking file/socket work runs on `Dispatchers.IO`.
3940
- Files are streamed; they are never loaded whole into memory.
40-
- Platform APIs stay in Android/JVM source sets.
41+
- Platform APIs stay in Android, JVM, and iOS source sets.
4142

4243
## Protocol summary
4344

0 commit comments

Comments
 (0)