diff --git a/.gitignore b/.gitignore index 4c9e69e4..d9cc0dcb 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ ios/fastlane/report.xml ios/Runner.app.dSYM.zip /symbols/ +/pub_cache/ diff --git a/android/build/.last_build_id b/android/build/.last_build_id new file mode 100644 index 00000000..e69de29b diff --git a/android/settings.gradle b/android/settings.gradle index 10a012a7..00eeb86f 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -24,4 +24,5 @@ plugins { id("com.google.gms.google-services") version "4.4.1" apply false } -include ":app" \ No newline at end of file +include ":app" +include ':wear' diff --git a/android/wear/.gitignore b/android/wear/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/android/wear/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/android/wear/build.gradle.kts b/android/wear/build.gradle.kts new file mode 100644 index 00000000..27d31dbc --- /dev/null +++ b/android/wear/build.gradle.kts @@ -0,0 +1,77 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" // this version matches your Kotlin version + +} + +android { + namespace = "com.codel1417.tailApp" + compileSdk = 34 + + defaultConfig { + applicationId = "com.codel1417.tailApp" + minSdk = 30 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + vectorDrawables { + useSupportLibrary = true + } + + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} +composeCompiler { + enableStrongSkippingMode = true + + reportsDestination = layout.buildDirectory.dir("compose_compiler") + //stabilityConfigurationFile = rootProject.layout.projectDirectory.file("stability_config.conf") +} +dependencies { + + implementation("com.google.android.gms:play-services-wearable:18.0.0") + implementation(platform("androidx.compose:compose-bom:2023.08.00")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.wear.compose:compose-material:1.2.1") + implementation("androidx.wear.compose:compose-foundation:1.2.1") + implementation("androidx.activity:activity-compose:1.7.2") + implementation("androidx.core:core-splashscreen:1.0.1") + implementation("androidx.wear.tiles:tiles:1.1.0") + implementation("androidx.wear.tiles:tiles-material:1.1.0") + implementation("com.google.android.horologist:horologist-compose-tools:0.4.8") + implementation("com.google.android.horologist:horologist-tiles:0.4.8") + implementation("androidx.wear.watchface:watchface-complications-data-source-ktx:1.1.1") + androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00")) + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + debugImplementation("androidx.compose.ui:ui-tooling") + debugImplementation("androidx.compose.ui:ui-test-manifest") +} \ No newline at end of file diff --git a/android/wear/lint.xml b/android/wear/lint.xml new file mode 100644 index 00000000..44fac75b --- /dev/null +++ b/android/wear/lint.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/android/wear/proguard-rules.pro b/android/wear/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/android/wear/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/android/wear/src/main/AndroidManifest.xml b/android/wear/src/main/AndroidManifest.xml new file mode 100644 index 00000000..16b10e0c --- /dev/null +++ b/android/wear/src/main/AndroidManifest.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/wear/src/main/java/com/codel1417/tailApp/complication/MainComplicationService.kt b/android/wear/src/main/java/com/codel1417/tailApp/complication/MainComplicationService.kt new file mode 100644 index 00000000..1e059ed6 --- /dev/null +++ b/android/wear/src/main/java/com/codel1417/tailApp/complication/MainComplicationService.kt @@ -0,0 +1,41 @@ +package com.codel1417.tailApp.complication + +import androidx.wear.watchface.complications.data.ComplicationData +import androidx.wear.watchface.complications.data.ComplicationType +import androidx.wear.watchface.complications.data.PlainComplicationText +import androidx.wear.watchface.complications.data.ShortTextComplicationData +import androidx.wear.watchface.complications.datasource.ComplicationRequest +import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService +import java.util.Calendar + +/** + * Skeleton for complication data source that returns short text. + */ +class MainComplicationService : SuspendingComplicationDataSourceService() { + + override fun getPreviewData(type: ComplicationType): ComplicationData? { + if (type != ComplicationType.SHORT_TEXT) { + return null + } + return createComplicationData("Mon", "Monday") + } + + override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData { + return when (Calendar.getInstance().get(Calendar.DAY_OF_WEEK)) { + Calendar.SUNDAY -> createComplicationData("Sun", "Sunday") + Calendar.MONDAY -> createComplicationData("Mon", "Monday") + Calendar.TUESDAY -> createComplicationData("Tue", "Tuesday") + Calendar.WEDNESDAY -> createComplicationData("Wed", "Wednesday") + Calendar.THURSDAY -> createComplicationData("Thu", "Thursday") + Calendar.FRIDAY -> createComplicationData("Fri!", "Friday!") + Calendar.SATURDAY -> createComplicationData("Sat", "Saturday") + else -> throw IllegalArgumentException("too many days") + } + } + + private fun createComplicationData(text: String, contentDescription: String) = + ShortTextComplicationData.Builder( + text = PlainComplicationText.Builder(text).build(), + contentDescription = PlainComplicationText.Builder(contentDescription).build() + ).build() +} \ No newline at end of file diff --git a/android/wear/src/main/java/com/codel1417/tailApp/presentation/theme/Theme.kt b/android/wear/src/main/java/com/codel1417/tailApp/presentation/theme/Theme.kt new file mode 100644 index 00000000..33f6509c --- /dev/null +++ b/android/wear/src/main/java/com/codel1417/tailApp/presentation/theme/Theme.kt @@ -0,0 +1,17 @@ +package com.codel1417.tailApp.presentation.theme + +import androidx.compose.runtime.Composable +import androidx.wear.compose.material.MaterialTheme + +@Composable +fun _androidTheme( + content: @Composable () -> Unit +) { + /** + * Empty theme to customize for your app. + * See: https://developer.android.com/jetpack/compose/designsystems/custom + */ + MaterialTheme( + content = content + ) +} \ No newline at end of file diff --git a/android/wear/src/main/java/com/codel1417/tailApp/tile/MainTileService.kt b/android/wear/src/main/java/com/codel1417/tailApp/tile/MainTileService.kt new file mode 100644 index 00000000..51e454a9 --- /dev/null +++ b/android/wear/src/main/java/com/codel1417/tailApp/tile/MainTileService.kt @@ -0,0 +1,70 @@ +package com.codel1417.tailApp.tile + +import android.content.Context +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Devices +import androidx.compose.ui.tooling.preview.Preview +import androidx.wear.protolayout.ColorBuilders.argb +import androidx.wear.protolayout.LayoutElementBuilders +import androidx.wear.protolayout.ResourceBuilders +import androidx.wear.protolayout.TimelineBuilders +import androidx.wear.protolayout.material.Colors +import androidx.wear.protolayout.material.Text +import androidx.wear.protolayout.material.Typography +import androidx.wear.protolayout.material.layouts.PrimaryLayout +import androidx.wear.tiles.RequestBuilders +import androidx.wear.tiles.TileBuilders +import com.google.android.horologist.annotations.ExperimentalHorologistApi +import com.google.android.horologist.compose.tools.LayoutRootPreview +import com.google.android.horologist.compose.tools.buildDeviceParameters +import com.google.android.horologist.tiles.SuspendingTileService + +private const val RESOURCES_VERSION = "0" + +/** + * Skeleton for a tile with no images. + */ +@OptIn(ExperimentalHorologistApi::class) +class MainTileService : SuspendingTileService() { + + override suspend fun resourcesRequest( + requestParams: RequestBuilders.ResourcesRequest + ): ResourceBuilders.Resources { + return ResourceBuilders.Resources.Builder().setVersion(RESOURCES_VERSION).build() + } + + override suspend fun tileRequest( + requestParams: RequestBuilders.TileRequest + ): TileBuilders.Tile { + val singleTileTimeline = TimelineBuilders.Timeline.Builder().addTimelineEntry( + TimelineBuilders.TimelineEntry.Builder().setLayout( + LayoutElementBuilders.Layout.Builder().setRoot(tileLayout(this)).build() + ).build() + ).build() + + return TileBuilders.Tile.Builder().setResourcesVersion(RESOURCES_VERSION) + .setTileTimeline(singleTileTimeline).build() + } +} + +private fun tileLayout(context: Context): LayoutElementBuilders.LayoutElement { + return PrimaryLayout.Builder(buildDeviceParameters(context.resources)) + .setContent( + Text.Builder(context, "Hello World!") + .setColor(argb(Colors.DEFAULT.onSurface)) + .setTypography(Typography.TYPOGRAPHY_CAPTION1) + .build() + ).build() +} + +@Preview( + device = Devices.WEAR_OS_SMALL_ROUND, + showSystemUi = true, + backgroundColor = 0xff000000, + showBackground = true +) +@Composable +fun TilePreview() { + LayoutRootPreview(root = tileLayout(LocalContext.current)) +} \ No newline at end of file diff --git a/android/wear/src/main/res/drawable-round/tile_preview.png b/android/wear/src/main/res/drawable-round/tile_preview.png new file mode 100644 index 00000000..474fac4d Binary files /dev/null and b/android/wear/src/main/res/drawable-round/tile_preview.png differ diff --git a/android/wear/src/main/res/drawable/splash_icon.xml b/android/wear/src/main/res/drawable/splash_icon.xml new file mode 100644 index 00000000..7874e83f --- /dev/null +++ b/android/wear/src/main/res/drawable/splash_icon.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + diff --git a/android/wear/src/main/res/drawable/tile_preview.png b/android/wear/src/main/res/drawable/tile_preview.png new file mode 100644 index 00000000..8cbe3ed5 Binary files /dev/null and b/android/wear/src/main/res/drawable/tile_preview.png differ diff --git a/android/wear/src/main/res/mipmap-hdpi/ic_launcher.webp b/android/wear/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 00000000..c209e78e Binary files /dev/null and b/android/wear/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/android/wear/src/main/res/mipmap-mdpi/ic_launcher.webp b/android/wear/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 00000000..4f0f1d64 Binary files /dev/null and b/android/wear/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/android/wear/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android/wear/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 00000000..948a3070 Binary files /dev/null and b/android/wear/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/android/wear/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android/wear/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 00000000..28d4b77f Binary files /dev/null and b/android/wear/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/android/wear/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android/wear/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 00000000..aa7d6427 Binary files /dev/null and b/android/wear/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/android/wear/src/main/res/values-round/strings.xml b/android/wear/src/main/res/values-round/strings.xml new file mode 100644 index 00000000..42f12297 --- /dev/null +++ b/android/wear/src/main/res/values-round/strings.xml @@ -0,0 +1,3 @@ + + From the Round world,\nHello, %1$s! + \ No newline at end of file diff --git a/android/wear/src/main/res/values/strings.xml b/android/wear/src/main/res/values/strings.xml new file mode 100644 index 00000000..be2d851e --- /dev/null +++ b/android/wear/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ + + The Tail Co + + From the Square world,\nHello, %1$s! + Example tile + Example complication + \ No newline at end of file diff --git a/android/wear/src/main/res/values/styles.xml b/android/wear/src/main/res/values/styles.xml new file mode 100644 index 00000000..dbf9c83a --- /dev/null +++ b/android/wear/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file