Skip to content

Commit fc3dd4a

Browse files
committed
Update README for iOS target introduction
1 parent 47b8240 commit fc3dd4a

3 files changed

Lines changed: 90 additions & 11 deletions

File tree

README.md

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
The coverage report excludes code not intended to be covered.
1111

12-
This avoids the [“broken window” effect](https://blog.codinghorror.com/the-broken-window-theory/): whether coverage is at 43% or 56%, its perceived as equally low—so efforts to improve it are often dismissed. In contrast, high or near-100% coverage is seen as achievable and worth tracking.
12+
This avoids the [“broken window” effect](https://blog.codinghorror.com/the-broken-window-theory/): whether coverage is at 43% or 56%, it's perceived as equally low—so efforts to improve it are often dismissed. In contrast, high or near-100% coverage is seen as achievable and worth tracking.
1313

1414
Refer to the root project's [`build.gradle.kts`](build.gradle.kts#L55-L90) for details.
1515

@@ -36,13 +36,16 @@ Refer to the root project's [`build.gradle.kts`](build.gradle.kts#L55-L90) for d
3636

3737
[**Taskfolio**](https://opatry.github.io/taskfolio) is an Android task management app built using [Google Tasks API](https://developers.google.com/tasks/reference/rest). Developed to demonstrate my expertise in modern Android development, it highlights my skills in architecture, UI design with Jetpack Compose, OAuth authentication, and more—all packaged in a sleek, user-friendly interface.
3838

39-
> I set out to revisit the classical TODO app, local-first syncing with Google Tasks—aiming for an <abbr title="Minimum Viable Experience">MVE</abbr> in 2 weeks, focusing on the 80/20 rule to nail the essentials.
39+
> I set out to revisit the classical TODO app, 'local-first' syncing with Google Tasks—aiming for an <abbr title="Minimum Viable Experience">MVE</abbr> in 2 weeks, focusing on the 80/20 rule to nail the essentials.
4040
4141
| ![](assets/screens/task_lists_light.png) | ![](assets/screens/groceries_light.png) | ![](assets/screens/add_task_light.png) | ![](assets/screens/home_dark.png) |
4242
| --------------------------------------- |--------------------------------------- | ---------------------------------- | ---------------------------------- |
4343

4444
[![Taskfolio on Play Store](assets/GetItOnGooglePlay_Badge_Web_color_English.png)](https://play.google.com/store/apps/details?id=net.opatry.tasks.app)
4545

46+
> [!NOTE]
47+
> The application is also available as a desktop (Jvm) application and an iOS application as well (using [Compose Multi Platform (aka CMP)](https://www.jetbrains.com/compose-multiplatform/) as UI Toolkit).
48+
4649
## 🎯 Project intentions
4750

4851
- [x] Showcase my expertise in Android application development
@@ -76,9 +79,10 @@ I do not aim to implement advanced features beyond what is supported by the Goog
7679

7780
## 🛠️ Tech stack
7881

79-
- [Kotlin](https://kotlinlang.org/), [Multiplatform (aka KMP)](https://kotlinlang.org/docs/multiplatform.html) (currently Desktop & Android are supported)
80-
- iOS wasn’t initially planned, but I bootstrapped a [PR to evaluate the feasibility of the iOS target]((https://github.com/opatry/taskfolio/pull/269)). It turned out to be quite achievable and just needs some polishing.
81-
- Web is not planned any time soon (contribution are welcome 🤝)
82+
- [Kotlin](https://kotlinlang.org/), [Multiplatform (aka KMP)](https://kotlinlang.org/docs/multiplatform.html)
83+
- Android and Desktop are fully supported.
84+
- iOS wasn't initially planned, but a draft version is available (use it at your own risk, there might be dragons 🐉).
85+
- Web is not planned any time soon (contributions are welcome 🤝)
8286
- [Kotlin coroutines](https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html)
8387
- [Ktor client](https://ktor.io/) (+ [Kotlinx serialization](https://kotlinlang.org/docs/serialization.html))
8488
- [Room](https://developer.android.com/training/data-storage/room) for local persistence
@@ -123,6 +127,9 @@ I do not aim to implement advanced features beyond what is supported by the Goog
123127
- The Desktop application (thin layer fully reusing `:tasks-app-shared`)
124128
- [`:tasks-app-android`](tasks-app-android) <span style="color: #66FF00;">■■■■■■■■</span>□□ 80%
125129
- The Android application (thin layer fully reusing `:tasks-app-shared`)
130+
- [`:tasks-app-ios/Taskfolio`](tasks-app-ios/Taskfolio) <span style="color: #33FF00;">■■■■■■■■■</span>□ 90%
131+
- The iOS application (thin layer fully reusing `:tasks-app-shared`)
132+
- Xcode project, written in Swift
126133
- [`website/`](website) <span style="color: #00FF00;">■■■■■■■■■■</span> 100%
127134
- The [static site](https://opatry.github.io/taskfolio/) presenting the project
128135
- Made with [Jekyll](https://jekyllrb.com/) and served by [Github pages](https://pages.github.com/)
@@ -177,6 +184,68 @@ When clicking on it, it will open a new window with the hot reload status.
177184
![](assets/compose-hot-reload-console.png)
178185
</details>
179186

187+
## 🍎 Build for iOS target
188+
189+
The support of iOS works more or less _as-is_ and gets the job done. It's provided without guarantees, use at your own risk.
190+
Feedback and contributions are welcome though 🤝.
191+
192+
> [!NOTE]
193+
> iOS support is _opt-in_ and disabled by default to avoid unnecessary time and disk usage during the initial Gradle sync when the iOS target isn't required.
194+
> You can enable it by setting `ios.target` Gradle property to `all`, `simulator` or `device` from either `local.properties` or CLI using `-P`.
195+
> When building from Xcode, it automatically sets `-Pios.target=simulator` based on `Config.xcconfig`.
196+
197+
<details>
198+
<summary>See details…</summary>
199+
200+
You can build the `:tasks-app-shared` code for iOS using Gradle (to check if everything compiles on Kotlin side):
201+
202+
```bash
203+
./gradlew tasks-app-shared:linkDebugFrameworkIosSimulatorArm64 -Pios.target=simulator
204+
```
205+
206+
### Building & Running from IntelliJ/Android Studio
207+
208+
You can also use the incubating [Kotlin Multiplatform IntelliJ plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform) to build and launch the iOS app directly from IntelliJ/Android Studio (starting from Narwhal | 2025.1.1).
209+
This plugin allows you to choose whether to run the app on a device or simulator, and enables debugging of Kotlin code even when called from iOS/Swift.
210+
211+
It builds the Kotlin code as a native framework, then triggers the appropriate Gradle task to build Kotlin first, followed by `xcodebuild` for the Xcode and iOS-specific parts, ensuring a seamless integration between Kotlin and Swift code (see next section for details).
212+
213+
### Building & Running from Xcode
214+
215+
For full XCFramework build (to be consumed by the iOS application), you'll have to rely on `xcodebuild` (or build directly from Xcode):
216+
217+
```bash
218+
cd tasks-app-ios
219+
IOS_TARGET=simulator xcodebuild -project Taskfolio.xcodeproj \
220+
-scheme Taskfolio \
221+
-sdk iphonesimulator \
222+
-arch arm64 \
223+
-configuration Debug \
224+
build \
225+
CODE_SIGNING_ALLOWED=NO \
226+
CODE_SIGN_IDENTITY="" \
227+
CODE_SIGNING_REQUIRED=NO
228+
```
229+
This triggers the `:tasks-app-shared:embedAndSignAppleFrameworkForXcode` Gradle task under the hood.
230+
231+
For Xcode integration, it's recommended to install the [Xcode Kotlin plugin](https://touchlab.co/xcodekotlin):
232+
233+
```bash
234+
brew install xcode-kotlin
235+
xcode-kotlin install
236+
```
237+
238+
When you update Xcode, you'll have to sync the plugin:
239+
240+
```bash
241+
xcode-kotlin sync
242+
```
243+
244+
If you want to debug the Kotlin code from Xcode, you'll have to add the needed source sets in Xcode:
245+
Add Group > Add folders as **reference** > `tasks-app-shared/{commonMain,iosMain}` (or any other module you want to debug).
246+
If you properly installed the Xcode Kotlin plugin, you'll be able to set a breakpoint in the Kotlin code and see syntax coloring as well.
247+
</details>
248+
180249
## ⚖️ License
181250

182251
```

website/index.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ This project highlights the breadth of my Android knowledge, from API integratio
1414
It’s designed not just as a functioning task manager, but as a demonstration of my ability to deliver well-structured, maintainable,
1515
and scalable Android apps.
1616

17-
[![Taskfolio Android Application](assets/GetItOnGooglePlay_Badge_Web_color_English.png)](https://play.google.com/store/apps/details?id=net.opatry.tasks.app)
17+
[![Taskfolio on Play Store](assets/GetItOnGooglePlay_Badge_Web_color_English.png)](https://play.google.com/store/apps/details?id=net.opatry.tasks.app)
1818

19-
| --------------------------------------- |--------------------------------------- |--------------------------------------- | ---------------------------------- |
19+
| --------------------------------------- |--------------------------------------- | ---------------------------------- | ---------------------------------- |
2020
| ![](assets/screens/task_lists_light.png) | ![](assets/screens/groceries_light.png) | ![](assets/screens/add_task_light.png) | ![](assets/screens/home_dark.png) |
2121

22+
> ℹ️ The application is also available as a desktop (Jvm) application and an iOS application as well (using [Compose Multi Platform (aka CMP)](https://www.jetbrains.com/compose-multiplatform/) as UI Toolkit).
23+
2224
## 🎯 Project intentions
2325

2426
- [x] Showcase my expertise in Android application development
@@ -52,11 +54,13 @@ I do not aim to implement advanced features beyond what is supported by the Goog
5254

5355
## 🛠️ Tech stack
5456

55-
- [Kotlin](https://kotlinlang.org/), [Multiplatform (aka KMP)](https://kotlinlang.org/docs/multiplatform.html) (currently Desktop & Android are supported)
56-
- iOS & Web are not planned any time soon (contribution are welcome 🤝)
57+
- [Kotlin](https://kotlinlang.org/), [Multiplatform (aka KMP)](https://kotlinlang.org/docs/multiplatform.html)
58+
- Android and Desktop are fully supported.
59+
- iOS wasn't initially planned, but a draft version is available (use it at your own risk, there might be dragons 🐉).
60+
- Web is not planned any time soon (contributions are welcome 🤝)
5761
- [Kotlin coroutines](https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html)
5862
- [Ktor client](https://ktor.io/) (+ [Kotlinx serialization](https://kotlinlang.org/docs/serialization.html))
59-
- [Room](https://developer.android.com/training/data-storage/room) for local persistance
63+
- [Room](https://developer.android.com/training/data-storage/room) for local persistence
6064
- [Koin](https://insert-koin.io/) for dependency injection
6165
- [Material Design 3 Components](https://developer.android.com/develop/ui/compose/designsystems/material3)
6266
- [Jetpack Compose](https://developer.android.com/jetpack/compose), [Multiplatform (aka CMP)](https://www.jetbrains.com/compose-multiplatform/)

website/styles.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,10 @@ td {
152152
width: 50%;
153153
box-sizing: border-box;
154154
}
155-
}
155+
}
156+
157+
blockquote {
158+
margin-left: 0;
159+
padding-left: 1.5rem;
160+
border-left: 4px solid #6BEACA;
161+
}

0 commit comments

Comments
 (0)