Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
# in both published modules (:reachable, :reachable-testing). Sample
# apps are deliberately excluded — see mise.toml.
# `mise run build` assembles Reachable.xcframework — the artifact that
# the sample apps under /iOSApp and /macOSApp consume via the root
# the sample apps under /apps/ios and /apps/macos consume via the root
# Package.swift. Maven Central publishing is a separate workflow
# (.github/workflows/release.yml). The CI version stamp is passed
# through to Gradle via ORG_GRADLE_PROJECT_version — the standard
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ jobs:
if: ${{ inputs.dryRun }}
env:
# Vanniktech reads these four properties; Gradle auto-populates
# them from ORG_GRADLE_PROJECT_* env vars. See docs/publishing.md.
# them from ORG_GRADLE_PROJECT_* env vars. See .github/PUBLISHING.md.
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
# In-memory GPG key: paste the full ASCII-armoured private key
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ DerivedData/
*.xccheckout

# --- Sample apps: Xcode projects are generated from project.yml via xcodegen ---
iOSApp/iOSApp.xcodeproj/
macOSApp/macOSApp.xcodeproj/
apps/ios/iOSApp.xcodeproj/
apps/macos/macOSApp.xcodeproj/

# --- mise: per-user version overrides ---
.mise.local.toml
Expand Down
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ Everything else we author — classes, files, top-level functions, top-level `va
/src/iosMain
/src/macosMain
/src/wasmJsMain stretch
/iOSApp Xcode project, native SwiftUI, consumes /shared via SPM
/androidApp Android entrypoint, native Jetpack Compose UI
/macOSApp macOS desktop, native SwiftUI/AppKit
/apps/ios Xcode project, native SwiftUI, consumes /shared via SPM
/apps/android Android entrypoint, native Jetpack Compose UI
/apps/macos macOS desktop, native SwiftUI/AppKit
/webApp native web (stretch)
```

Expand Down Expand Up @@ -323,7 +323,7 @@ Two channels, no overlap:
- Don't vendor `XCFramework` zips into the repo. Everything flows through GitHub Release assets + the committed `Package.swift`.
- `Package.swift` is generated (`kmmBridgePublish` writes the released form, `spmDevBuild` the local-dev form). Don't hand-edit it, and never commit the local-dev form.

**Local development override:** the sample apps consume the root `Package.swift` as a local package. Run `./gradlew :reachable:spmDevBuild` (`mise run spm:dev`) to rebuild the debug `XCFramework` and flip `Package.swift` to a local path; `mise run spm:restore` restores the committed version. Documented in `iOSApp/README.md`.
**Local development override:** the sample apps consume the root `Package.swift` as a local package. Run `./gradlew :reachable:spmDevBuild` (`mise run spm:dev`) to rebuild the debug `XCFramework` and flip `Package.swift` to a local path; `mise run spm:restore` restores the committed version. Documented in `apps/ios/README.md`.

---

Expand Down
10 changes: 5 additions & 5 deletions docs/contributing.md → CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ mise run build:android # Android AAR
./gradlew :reachable:linkDebugFrameworkMacosArm64
./gradlew :reachable:assembleReachableXCFramework
./gradlew :reachable:assemble
./gradlew :androidApp:assembleDebug
./gradlew :androidApp:assembleDebug # project is under apps/android
```

For the iOS and macOS samples, `mise run open:ios` (and `open:macos`) chains
`spm:dev` → `xcodegen` → opens the project in Xcode. See
[iOSApp/README.md](https://github.com/happycodelucky/reachable/blob/main/iOSApp/README.md)
and `macOSApp/README.md` for the iteration loop.
[apps/ios/README.md](https://github.com/happycodelucky/reachable/blob/main/apps/ios/README.md)
and `apps/macos/README.md` for the iteration loop.

## Building the docs

Expand All @@ -91,7 +91,7 @@ from the site navigation, every recipe has at least one code block.
## Pull request expectations

- `mise run check` passes locally.
- New public API has KDoc and an [API design](concepts/api-design.md)
- New public API has KDoc and an [API design](docs/concepts/api-design.md)
rationale (a sentence in the PR description is usually enough).
- New behavior has a test in `commonTest` or the relevant platform test
source set.
Expand All @@ -106,4 +106,4 @@ docs validation) on every PR.
Releases publish to Maven Central via vanniktech maven-publish, then tag
the commit and create a GitHub Release with auto-generated notes. The
mechanics, one-time credential setup, and the dry-run / live-publish
toggle live in [Publishing](publishing.md).
toggle live in [`.github/PUBLISHING.md`](.github/PUBLISHING.md).
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Highlights:
[Compose binding](docs/recipes/compose-binding.md),
[React to changes](docs/recipes/react-to-changes.md),
[Captive portals](docs/recipes/captive-portal.md).
- [Contributing](docs/contributing.md): development environment,
- [Contributing](CONTRIBUTING.md): development environment,
reporting bugs, PR expectations.

---
Expand Down Expand Up @@ -338,17 +338,17 @@ mise run build:ios # iOS device + simulator debug frameworks
mise run build:macos # macOS desktop debug framework
mise run build # release Reachable.xcframework (sample-app local SPM)
mise run build:android # Android AAR
mise run open:ios # spm:dev + xcodegen + open iOSApp in Xcode
mise run open:macos # spm:dev + xcodegen + open macOSApp in Xcode
mise run open:ios # spm:dev + xcodegen + open apps/ios in Xcode
mise run open:macos # spm:dev + xcodegen + open apps/macos in Xcode
```

Each task is a thin wrapper over `./gradlew` (or `xcodegen` for the
`open:*` tasks); see [`mise.toml`](./mise.toml) for the exact mapping, or
run `mise tasks` to list everything. Raw `./gradlew` invocations still
work — mise just ensures everyone (and CI) runs the same versions.

For the iOS and macOS sample apps see [`iOSApp/README.md`](./iOSApp/README.md)
and [`macOSApp/README.md`](./macOSApp/README.md).
For the iOS and macOS sample apps see [`apps/ios/README.md`](./apps/ios/README.md)
and [`apps/macos/README.md`](./apps/macos/README.md).

---

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@file:Suppress("UnstableApiUsage")

/*
* Reachable — androidApp sample.
* Reachable — apps/android sample.
*
* Minimal SwiftUI-equivalent: a Jetpack Compose UI that subscribes to
* `reachability.status` and renders the live ReachabilityStatus. Useful as
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Reachable — androidApp sample manifest.
Reachable — apps/android sample manifest.

ACCESS_NETWORK_STATE merges in from the `:reachable` library's manifest, so
this app doesn't need to redeclare it. INTERNET is also unnecessary for the
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion iOSApp/README.md → apps/ios/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Wi-Fi (Low Data Mode folds into the metered signal).

- Xcode 16+ (the project targets iOS 18.0). Xcode itself is not managed by
mise; install the latest stable Xcode that the current SKIE release
supports (see [docs/contributing.md](../docs/contributing.md)).
supports (see [CONTRIBUTING.md](../../CONTRIBUTING.md)).
- [`mise`](https://mise.jdx.dev) for everything else. From the repo root:
```bash
brew install mise
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions macOSApp/README.md → apps/macos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ renders the live `ReachabilityStatus`. Toggle Wi-Fi from the menu bar,
plug in or unplug Ethernet, or enable Low Data Mode in System Settings →
Network → Wi-Fi → Details to see live updates.

The implementation is the same as iOSApp; both consume the same
The implementation is the same as `apps/ios`; both consume the same
`appleMain` Kotlin source set in `:reachable`. Only the deployment target
(`macOS 15.0`) and a few SwiftUI window-sizing tweaks differ.

## Prerequisites

Same as iOSApp: Xcode 16+ and the mise-managed toolchain. Run
Same as `apps/ios`: Xcode 16+ and the mise-managed toolchain. Run
`brew install mise` then `mise install` from the repo root. See
[iOSApp/README.md](../iOSApp/README.md#prerequisites) for the full list.
[apps/ios/README.md](../ios/README.md#prerequisites) for the full list.

## First-time setup

Expand All @@ -32,7 +32,7 @@ mise run spm:dev
```

Then rebuild the macOSApp target in Xcode. See
[iOSApp/README.md](../iOSApp/README.md) for the local-SPM mechanics.
[apps/ios/README.md](../ios/README.md) for the local-SPM mechanics.

## Sandbox and entitlements

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ subprojects {
// ktlint + detekt wire onto the KMP plugin — i.e. onto the published
// library modules only. CLAUDE.md §3: "ktlint + detekt must pass."
//
// Deliberate scope: the sample apps (`:androidApp` here; /iOSApp and
// /macOSApp outside this Gradle build) are demo scaffolding, not shipped
// Deliberate scope: the sample apps (`:androidApp` here; /apps/ios and
// /apps/macos outside this Gradle build) are demo scaffolding, not shipped
// code, and are intentionally excluded from Kotlin lint and from CI's
// check task. Don't "fix" that by widening this hook — if a sample stops
// compiling, the fix is in the sample, not the gate.
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ repositories {
`mise run publish:local` overwrites the cached artifact; the consumer picks
up the change on the next Gradle sync.

See [Publishing](publishing.md) for the full local + Maven Central pipeline.
See [`.github/PUBLISHING.md`](https://github.com/happycodelucky/reachable/blob/main/.github/PUBLISHING.md) for the full local + Maven Central pipeline.

## Verification

Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ kotlinx-atomicfu = "0.33.0"
# :reachable so consumers don't need to add it themselves.
androidx-startup = "1.2.0"

# --- Sample-app deps (androidApp only — iOS / macOS samples consume via SPM) -
# --- Sample-app deps (apps/android only — iOS / macOS samples consume via SPM) -
androidx-activity-compose = "1.13.0"
androidx-lifecycle-runtime-compose = "2.10.0"
androidx-compose-bom = "2026.05.01"
Expand Down
40 changes: 22 additions & 18 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@
# mise install
#
# Xcode is NOT managed by mise. Install the latest stable Xcode that SKIE
# supports; the docs/contributing.md "Prerequisites" section records the
# supports; the CONTRIBUTING.md "Prerequisites" section records the
# current minimum.

[tools]
java = "temurin-21.0.11+10.0.LTS" # CLAUDE.md §2 — JDK 21 LTS, Apple Silicon aarch64.
gradle = "9.4.1" # Matches gradle/wrapper/gradle-wrapper.properties.
python = "3.12.13" # docs/requirements.txt mkdocs toolchain.
xcodegen = "2.45.4" # iOSApp/macOSApp project.yml → .xcodeproj.
xcodegen = "2.45.4" # apps/ios, apps/macos project.yml → .xcodeproj.
gh = "2.92.0" # release.yml uses `gh release create`.
swiftlint = "0.63.2" # iOSApp/macOSApp Swift lint.
swiftformat = "0.61.1" # iOSApp/macOSApp Swift formatter.
swiftlint = "0.63.2" # apps/ios, apps/macos Swift lint.
swiftformat = "0.61.1" # apps/ios, apps/macos Swift formatter.

# Deliberately NOT pinned here:
# - kotlin: gradle/libs.versions.toml owns it (CLAUDE.md §2).
Expand All @@ -43,7 +43,7 @@ swiftformat = "0.61.1" # iOSApp/macOSApp Swift formatter.

# Both published modules are listed explicitly. Gradle's `check` is
# per-project — `:reachable:check` alone never runs `:reachable-testing`'s
# test suite. The sample app (`:androidApp`) is deliberately NOT listed:
# test suite. The sample app (`:androidApp` at apps/android) is deliberately NOT listed:
# samples are demo scaffolding, excluded from lint and CI by policy (see
# the subprojects block in build.gradle.kts).
[tasks.check]
Expand All @@ -65,15 +65,15 @@ run = "./gradlew :reachable:ktlintFormat :reachable-testing:ktlintFormat"
[tasks."lint:swift"]
description = "Run swiftlint across the iOS and macOS sample apps."
run = """
swiftlint lint --strict iOSApp
swiftlint lint --strict macOSApp
swiftlint lint --strict apps/ios
swiftlint lint --strict apps/macos
"""

[tasks."format:swift"]
description = "Run swiftformat across the iOS and macOS sample apps."
run = """
swiftformat iOSApp
swiftformat macOSApp
swiftformat apps/ios
swiftformat apps/macos
"""

# --- build -----------------------------------------------------------------
Expand Down Expand Up @@ -122,27 +122,31 @@ description = "Restore the committed (released) /Package.swift after spm:dev rew
run = "git restore Package.swift"

[tasks."xcodeproj:ios"]
description = "Generate iOSApp/iOSApp.xcodeproj from project.yml."
dir = "iOSApp"
description = "Generate apps/ios/iOSApp.xcodeproj from project.yml."
dir = "apps/ios"
run = "xcodegen generate --spec project.yml"

[tasks."xcodeproj:macos"]
description = "Generate macOSApp/macOSApp.xcodeproj from project.yml."
dir = "macOSApp"
description = "Generate apps/macos/macOSApp.xcodeproj from project.yml."
dir = "apps/macos"
run = "xcodegen generate --spec project.yml"

[tasks."open:ios"]
description = "spm:dev + xcodegen + open iOSApp in Xcode."
description = "spm:dev + xcodegen + open apps/ios in Xcode."
depends = ["spm:dev", "xcodeproj:ios"]
dir = "iOSApp"
dir = "apps/ios"
run = "open iOSApp.xcodeproj"

[tasks."open:macos"]
description = "spm:dev + xcodegen + open macOSApp in Xcode."
description = "spm:dev + xcodegen + open apps/macos in Xcode."
depends = ["spm:dev", "xcodeproj:macos"]
dir = "macOSApp"
dir = "apps/macos"
run = "open macOSApp.xcodeproj"

[tasks."open:android"]
description = "Open apps/android in Android Studio."
run = "open -a 'Android Studio' ."

# --- docs ------------------------------------------------------------------

[tasks."docs:install"]
Expand Down Expand Up @@ -177,5 +181,5 @@ run = "mkdocs build --strict"
description = "Gradle clean + drop generated xcodeproj bundles."
run = """
./gradlew clean
rm -rf iOSApp/iOSApp.xcodeproj macOSApp/macOSApp.xcodeproj
rm -rf apps/ios/iOSApp.xcodeproj apps/macos/macOSApp.xcodeproj
"""
2 changes: 0 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ nav:
- platforms/ios.md
- platforms/macos.md
- platforms/android.md
- Contributing: contributing.md
- Publishing: publishing.md
- Changelog: changelog.md

# Strict mode: fail the build on a broken link or a dead anchor.
Expand Down
2 changes: 1 addition & 1 deletion reachable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ model.
## Testing this library locally

Toolchain bootstrap once per machine — `brew install mise && mise install`
from the repo root. See [docs/contributing.md](../docs/contributing.md) for
from the repo root. See [CONTRIBUTING.md](../CONTRIBUTING.md) for
the full prerequisite list (Xcode, Android SDK).

```bash
Expand Down
6 changes: 3 additions & 3 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ include(":reachable-testing")
// --- Sample apps (CLAUDE.md §4) -----------------------------------------------
// The Android sample is a normal Gradle subproject because Compose + AGP play
// best inside the same Gradle build that produces the AAR. The iOS and macOS
// samples are standalone Xcode projects under /iOSApp and /macOSApp; they
// samples are standalone Xcode projects under /apps/ios and /apps/macos; they
// consume the shared module via SPM, NOT Gradle, and so are deliberately not
// included here. See iOSApp/README.md and macOSApp/README.md.
// included here. See apps/ios/README.md and apps/macos/README.md.
include(":androidApp")
project(":androidApp").projectDir = file("androidApp")
project(":androidApp").projectDir = file("apps/android")