Skip to content
Open
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
24 changes: 24 additions & 0 deletions .github/workflows/verifyPr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,27 @@ jobs:
with:
name: failed-screenshot-tests
path: app-screenshot-tests/build/paparazzi/failures

build-ios:
runs-on: "macos-latest"
concurrency:
group: ${{ github.workflow }}-ios-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
lfs: false
submodules: recursive
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
java-version: '21'
distribution: temurin
- uses: burrunan/gradle-cache-action@663fbad34e03c8f12b27f4999ac46e3d90f87eca
with:
debug: false
concurrent: true
read-only: true
- name: Compile shared iOS framework
run: "./gradlew :app-ios:linkDebugFrameworkIosSimulatorArm64"
1 change: 1 addition & 0 deletions app-ios/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
22 changes: 22 additions & 0 deletions app-ios/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
plugins {
id("org.jetbrains.kotlin.multiplatform")
id("org.jetbrains.kotlin.plugin.compose")
id("org.jetbrains.compose")
}

kotlin {
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach { target ->
target.binaries.framework {
baseName = "Shared"
}
}

sourceSets {
iosMain.dependencies {
implementation(libs.compose.runtime)
implementation(libs.compose.foundation)
implementation(libs.compose.material3)
implementation(libs.compose.ui)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.matejdro.micropebble.ios

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.window.ComposeUIViewController
import platform.UIKit.UIViewController

fun MainViewController(): UIViewController = ComposeUIViewController {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("microPebble — running on iOS")
}
}
}
}
1 change: 1 addition & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies {
implementation(libs.kotlin.plugin)
implementation(libs.kotlin.plugin.compose)
implementation(libs.kotlin.plugin.serialization)
implementation(libs.compose.gradlePlugin)
implementation(libs.kotlinova.gradle)
implementation(libs.metro.plugin)
implementation(libs.moduleGraphAssert)
Expand Down
54 changes: 54 additions & 0 deletions buildSrc/src/main/kotlin/library-kmp-module.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import dev.detekt.gradle.Detekt
import org.gradle.accessors.dm.LibrariesForLibs
import tasks.setupTooManyKotlinFilesTaskForCommon

val libs = the<LibrariesForLibs>()

plugins {
id("org.jetbrains.kotlin.multiplatform")
id("com.android.kotlin.multiplatform.library")
id("org.jetbrains.kotlin.plugin.compose")
id("org.jetbrains.compose")

id("checks")
}

val isMac = System.getProperty("os.name").contains("mac", ignoreCase = true)

kotlin {
jvmToolchain(21)

androidLibrary {
// Modules with resources must override this.
namespace = "com.matejdro.micropebble.noresources"
compileSdk = 36
minSdk = 30
}

if (isMac) {
iosX64()
iosArm64()
iosSimulatorArm64()
}

compilerOptions {
optIn.add("kotlin.time.ExperimentalTime")
optIn.add("kotlin.uuid.ExperimentalUuidApi")
optIn.add("kotlin.ExperimentalUnsignedTypes")
freeCompilerArgs.add("-Xannotation-default-target=param-property")
}

sourceSets {
commonMain.dependencies {
implementation(libs.compose.runtime)
}
}
}

if (name.startsWith("common-")) {
setupTooManyKotlinFilesTaskForCommon()
}

tasks.register("runDebugDetekt") {
dependsOn(tasks.withType<Detekt>())
}
3 changes: 3 additions & 0 deletions buildSrc/src/main/kotlin/util/PluginAccessors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ inline val PluginDependenciesSpec.androidAppModule: PluginDependencySpec
inline val PluginDependenciesSpec.androidLibraryModule: PluginDependencySpec
get() = id("library-android-module")

inline val PluginDependenciesSpec.kmpLibraryModule: PluginDependencySpec
get() = id("library-kmp-module")

inline val PluginDependenciesSpec.pureKotlinModule: PluginDependencySpec
get() = id("pure-kotlin-module")

Expand Down
27 changes: 17 additions & 10 deletions common-navigation/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
plugins {
androidLibraryModule
compose
parcelize
serialization
kmpLibraryModule
id("org.jetbrains.kotlin.plugin.serialization")
}

dependencies {
api(libs.kotlinova.navigation)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.core)
implementation(libs.androidx.compose.material3.sizeClasses)
implementation(libs.kotlinova.compose)
kotlin {
androidLibrary {
namespace = "com.matejdro.micropebble.navigation"
}

sourceSets {
androidMain.dependencies {
api(libs.kotlinova.navigation)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.core)
implementation(libs.kotlin.serialization.core)
implementation(libs.compose.animation)
implementation(libs.compose.ui)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.matejdro.micropebble.navigation.keys

import com.matejdro.micropebble.navigation.keys.base.Tab
import com.matejdro.micropebble.navigation.keys.base.TabKey
import kotlinx.serialization.Serializable
import si.inova.kotlinova.navigation.screenkeys.ScreenKey

@Serializable
data object NotificationAppListKey : ScreenKey(), TabKey {
override val tab get() = Tab.NOTIFICATIONS
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.matejdro.micropebble.navigation.keys

import com.matejdro.micropebble.navigation.keys.base.Tab
import com.matejdro.micropebble.navigation.keys.base.TabKey
import kotlinx.serialization.Serializable
import si.inova.kotlinova.navigation.screenkeys.ScreenKey

@Serializable
data object WatchListKey : ScreenKey(), TabKey {
override val tab get() = Tab.WATCHES
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.matejdro.micropebble.navigation.keys

import com.matejdro.micropebble.navigation.keys.base.Tab
import com.matejdro.micropebble.navigation.keys.base.TabKey
import com.matejdro.micropebble.navigation.keys.common.InputFile
import kotlinx.serialization.Serializable
import si.inova.kotlinova.navigation.screenkeys.ScreenKey

@Serializable
data class WatchappListKey(
val pbwFile: InputFile? = null,
) : ScreenKey() {
) : ScreenKey(), TabKey {
override val tab get() = Tab.WATCH_APPS

override fun getScopeTag(): String {
return this::class.java.name
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.matejdro.micropebble.navigation.keys.base

/**
* Key for a screen that shows a list of tabs + container. Container will be filled from the next entry on the backstack.
*/
interface TabContainerKey
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ package com.matejdro.micropebble.navigation.keys.base

import androidx.compose.runtime.Composable
import androidx.compose.runtime.staticCompositionLocalOf
import si.inova.kotlinova.navigation.screenkeys.ScreenKey

/**
* Key for a screen that shows a list of tabs + container. Container will be filled from the next entry on the backstack.
*/
interface TabContainerKey
enum class Tab {
WATCHES,
WATCH_APPS,
NOTIFICATIONS,
TOOLS,
}

/** Implemented by screen keys that act as a top-level tab destination. */
interface TabKey {
val tab: Tab
}

val LocalSelectedTabContent = staticCompositionLocalOf<SelectedTabContent> { error("SelectedTabContent not provided") }

data class SelectedTabContent(val content: @Composable () -> Unit, val key: ScreenKey, val contentKey: Any)
/** Content shown inside a tab container, plus which [Tab] is currently selected (null when none is). */
data class SelectedTabContent(val content: @Composable () -> Unit, val tab: Tab?, val contentKey: Any)

This file was deleted.

This file was deleted.

13 changes: 13 additions & 0 deletions config/libs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ androidx-test-runner = "1.7.0"
androidx-work = "2.11.2"
coil = "3.4.0"
composeDnd = "0.4.0"
# @pin CMP material3 tracks its own version; 1.10.0-alpha05 matches libpebble3 (1.11.x alpha is broken)
composeMaterial3 = "1.10.0-alpha05"
# @pin needs to match libpebble3's Compose Multiplatform version
composeMultiplatform = "1.10.1"
composePreference = "2.2.0"
composeWebview = "0.33.6"
dependencyAnalysis = "3.15.0"
Expand Down Expand Up @@ -102,6 +106,15 @@ androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref
coil = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
coil-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" }
composeDnd = { module = "com.mohamedrejeb.dnd:compose-dnd", version.ref = "composeDnd" }
# Compose Multiplatform artifacts (used by KMP modules; android variants relocate to androidx.compose)
compose-animation = { module = "org.jetbrains.compose.animation:animation", version.ref = "composeMultiplatform" }
compose-components-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "composeMultiplatform" }
compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "composeMultiplatform" }
# Compose Multiplatform Gradle plugin, used by the library-kmp-module convention plugin in buildSrc
compose-gradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "composeMultiplatform" }
compose-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "composeMaterial3" }
compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "composeMultiplatform" }
compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "composeMultiplatform" }
composePreference = { module = "me.zhanghai.compose.preference:preference", version.ref = "composePreference" }
composeWebview = { module = "io.github.kevinnzou:compose-webview", version.ref = "composeWebview" }
dependencyAnalysis = { module = "com.autonomousapps:dependency-analysis-gradle-plugin", version.ref = "dependencyAnalysis" }
Expand Down
Loading