@ -1,3 +0,0 @@
|
||||
# :app module
|
||||
|
||||
![Dependency graph](../docs/images/graphs/dep_graph_app.png)
|
@ -0,0 +1,3 @@
|
||||
# :app module
|
||||
|
||||
![Dependency graph](../../docs/images/graphs/dep_graph_app.png)
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
@ -0,0 +1 @@
|
||||
/build
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("nowinandroid.android.application")
|
||||
id("nowinandroid.android.application.compose")
|
||||
id("nowinandroid.android.hilt")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.google.samples.apps.nowinandroid.wear"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.google.samples.apps.nowinandroid.wear"
|
||||
versionCode = 1
|
||||
versionName = "0.0.1"
|
||||
minSdk = 26
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix = ".debug"
|
||||
}
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":feature:wear:news"))
|
||||
implementation(project(":sync:work"))
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.wear.compose.foundation)
|
||||
implementation(libs.androidx.wear.compose.material)
|
||||
implementation(libs.androidx.wear.compose.navigation)
|
||||
implementation(libs.coil.kt)
|
||||
}
|
@ -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
|
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-feature android:name="android.hardware.type.watch" />
|
||||
|
||||
<application
|
||||
android:name=".NiaWearApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@android:style/Theme.DeviceDefault">
|
||||
<uses-library
|
||||
android:name="com.google.android.wearable"
|
||||
android:required="true" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.wearable.standalone"
|
||||
android:value="true" />
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:theme="@android:style/Theme.DeviceDefault">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.lib_name"
|
||||
android:value="" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.wear
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import com.google.samples.apps.nowinandroid.wear.ui.NiaWearApp
|
||||
import com.google.samples.apps.nowinandroid.wear.ui.NiaWearTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
NiaWearTheme {
|
||||
NiaWearApp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.wear
|
||||
|
||||
import android.app.Application
|
||||
import coil.ImageLoader
|
||||
import coil.ImageLoaderFactory
|
||||
import com.google.samples.apps.nowinandroid.sync.initializers.Sync
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
/**
|
||||
* [Application] class for NiA
|
||||
*/
|
||||
@HiltAndroidApp
|
||||
class NiaWearApplication : Application(), ImageLoaderFactory {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
// Initialize Sync; the system responsible for keeping data in the app up to date.
|
||||
Sync.initialize(context = this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we're displaying SVGs in the app, Coil needs an ImageLoader which supports this
|
||||
* format. During Coil's initialization it will call `applicationContext.newImageLoader()` to
|
||||
* obtain an ImageLoader.
|
||||
*
|
||||
* @see https://github.com/coil-kt/coil/blob/main/coil-singleton/src/main/java/coil/Coil.kt#L63
|
||||
*/
|
||||
override fun newImageLoader(): ImageLoader = ImageLoader.Builder(this).build()
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.wear.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.wear.compose.navigation.SwipeDismissableNavHost
|
||||
import androidx.wear.compose.navigation.composable
|
||||
import androidx.wear.compose.navigation.rememberSwipeDismissableNavController
|
||||
import com.google.samples.apps.nowinandroid.feature.wear.news.NewsRoute
|
||||
|
||||
@Composable
|
||||
fun NiaWearApp() {
|
||||
val navController = rememberSwipeDismissableNavController()
|
||||
SwipeDismissableNavHost(
|
||||
navController = navController,
|
||||
startDestination = "news"
|
||||
) {
|
||||
composable("news") {
|
||||
NewsRoute()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.wear.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.wear.compose.material.MaterialTheme
|
||||
|
||||
@SuppressLint("DesignSystem")
|
||||
@Composable
|
||||
fun NiaWearTheme(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
MaterialTheme(content = content)
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:pathData="M0,0h108v108h-108z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:pathData="M65.08,84.13C64.01,84.13 63.13,83.26 63.13,82.18C63.13,81.11 64,80.24 65.08,80.24C66.15,80.24 67.02,81.11 67.02,82.18C67.02,83.26 66.15,84.13 65.08,84.13ZM43.6,84.13C42.53,84.13 41.65,83.26 41.65,82.18C41.65,81.11 42.52,80.24 43.6,80.24C44.66,80.24 45.54,81.11 45.54,82.18C45.54,83.26 44.67,84.13 43.6,84.13ZM65.77,72.44L69.66,65.73C69.88,65.35 69.74,64.85 69.36,64.63C68.97,64.41 68.48,64.54 68.25,64.93L64.32,71.73C61.31,70.36 57.94,69.59 54.33,69.59C50.73,69.59 47.35,70.36 44.34,71.73L40.41,64.93C40.19,64.54 39.69,64.41 39.31,64.63C38.92,64.85 38.79,65.35 39.01,65.73L42.89,72.44C36.22,76.07 31.67,82.81 31,90.77H77.67C77,82.8 72.44,76.06 65.77,72.44Z"
|
||||
android:fillColor="#FCFCFC"/>
|
||||
<path
|
||||
android:pathData="M46.57,35H46.57C46.1,35 45.72,35.38 45.72,35.85L45.72,43.15H44.19C43.35,43.15 42.67,43.83 42.67,44.68C42.67,45.52 43.35,46.2 44.19,46.2H45.72V43.15H47.42C48.17,43.15 48.78,42.54 48.78,41.79L48.78,37.72H49.97C50.43,37.72 50.81,37.34 50.81,36.87V35.85C50.81,35.38 50.43,35 49.97,35H47.42H46.57ZM46.57,54.35H46.57H47.42H49.97C50.43,54.35 50.81,53.97 50.81,53.5V52.48C50.81,52.02 50.43,51.64 49.97,51.64H48.78L48.78,47.56C48.78,46.81 48.17,46.2 47.42,46.2H45.72L45.72,53.5C45.72,53.97 46.1,54.35 46.57,54.35ZM61.54,35H61.54C62.01,35 62.39,35.38 62.39,35.85V43.15H63.92C64.76,43.15 65.44,43.83 65.44,44.68C65.44,45.52 64.76,46.2 63.92,46.2H62.39V43.15H60.69C59.94,43.15 59.33,42.54 59.33,41.79V37.72H58.15C57.68,37.72 57.3,37.34 57.3,36.87V35.85C57.3,35.38 57.68,35 58.15,35H60.69H61.54ZM61.54,54.35H61.54H60.69H58.15C57.68,54.35 57.3,53.97 57.3,53.5V52.48C57.3,52.02 57.68,51.64 58.15,51.64H59.33V47.56C59.33,46.81 59.94,46.2 60.69,46.2H62.39V53.5C62.39,53.97 62.01,54.35 61.54,54.35Z"
|
||||
android:fillColor="#FCFCFC"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
|
||||
<path
|
||||
android:pathData="M0,0h108v108h-108z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M65.08,84.13C64.01,84.13 63.13,83.26 63.13,82.18C63.13,81.11 64,80.24 65.08,80.24C66.15,80.24 67.02,81.11 67.02,82.18C67.02,83.26 66.15,84.13 65.08,84.13ZM43.6,84.13C42.53,84.13 41.65,83.26 41.65,82.18C41.65,81.11 42.52,80.24 43.6,80.24C44.66,80.24 45.54,81.11 45.54,82.18C45.54,83.26 44.67,84.13 43.6,84.13ZM65.77,72.44L69.66,65.73C69.88,65.35 69.74,64.85 69.36,64.63C68.97,64.41 68.48,64.54 68.25,64.93L64.32,71.73C61.31,70.36 57.94,69.59 54.33,69.59C50.73,69.59 47.35,70.36 44.34,71.73L40.41,64.93C40.19,64.54 39.69,64.41 39.31,64.63C38.92,64.85 38.79,65.35 39.01,65.73L42.89,72.44C36.22,76.07 31.67,82.81 31,90.77H77.67C77,82.8 72.44,76.06 65.77,72.44Z"
|
||||
android:fillColor="#FCFCFC"/>
|
||||
<path
|
||||
android:pathData="M46.57,35H46.57C46.1,35 45.72,35.38 45.72,35.85L45.72,43.15H44.19C43.35,43.15 42.67,43.83 42.67,44.68C42.67,45.52 43.35,46.2 44.19,46.2H45.72V43.15H47.42C48.17,43.15 48.78,42.54 48.78,41.79L48.78,37.72H49.97C50.43,37.72 50.81,37.34 50.81,36.87V35.85C50.81,35.38 50.43,35 49.97,35H47.42H46.57ZM46.57,54.35H46.57H47.42H49.97C50.43,54.35 50.81,53.97 50.81,53.5V52.48C50.81,52.02 50.43,51.64 49.97,51.64H48.78L48.78,47.56C48.78,46.81 48.17,46.2 47.42,46.2H45.72L45.72,53.5C45.72,53.97 46.1,54.35 46.57,54.35ZM61.54,35H61.54C62.01,35 62.39,35.38 62.39,35.85V43.15H63.92C64.76,43.15 65.44,43.83 65.44,44.68C65.44,45.52 64.76,46.2 63.92,46.2H62.39V43.15H60.69C59.94,43.15 59.33,42.54 59.33,41.79V37.72H58.15C57.68,37.72 57.3,37.34 57.3,36.87V35.85C57.3,35.38 57.68,35 58.15,35H60.69H61.54ZM61.54,54.35H61.54H60.69H58.15C57.68,54.35 57.3,53.97 57.3,53.5V52.48C57.3,52.02 57.68,51.64 58.15,51.64H59.33V47.56C59.33,46.81 59.94,46.2 60.69,46.2H62.39V53.5C62.39,53.97 62.01,54.35 61.54,54.35Z"
|
||||
android:fillColor="#FCFCFC"
|
||||
android:fillType="evenOdd"/>
|
||||
|
||||
</vector>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 982 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2021 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">Now in Android</string>
|
||||
</resources>
|
@ -0,0 +1 @@
|
||||
/build
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
plugins {
|
||||
id("nowinandroid.android.feature")
|
||||
id("nowinandroid.android.library.compose")
|
||||
id("nowinandroid.android.library.jacoco")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.google.samples.apps.nowinandroid.feature.wear.news"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":core:domain"))
|
||||
implementation(project(":core:ui"))
|
||||
implementation(libs.androidx.hilt.navigation.compose)
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.androidx.wear.compose.foundation)
|
||||
implementation(libs.androidx.wear.compose.material)
|
||||
implementation(libs.androidx.wear.compose.navigation)
|
||||
implementation(libs.kotlinx.datetime)
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest />
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.feature.wear.news
|
||||
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.gestures.scrollBy
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.input.rotary.onRotaryScrollEvent
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.wear.compose.material.CardDefaults
|
||||
import androidx.wear.compose.material.CircularProgressIndicator
|
||||
import androidx.wear.compose.material.PositionIndicator
|
||||
import androidx.wear.compose.material.Scaffold
|
||||
import androidx.wear.compose.material.ScalingLazyColumn
|
||||
import androidx.wear.compose.material.ScalingLazyListState
|
||||
import androidx.wear.compose.material.Text
|
||||
import androidx.wear.compose.material.TitleCard
|
||||
import androidx.wear.compose.material.items
|
||||
import androidx.wear.compose.material.rememberScalingLazyListState
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.google.samples.apps.nowinandroid.core.domain.model.SaveableNewsResource
|
||||
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
|
||||
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Loading
|
||||
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalLifecycleComposeApi::class)
|
||||
@Composable
|
||||
fun NewsRoute(
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: NewsViewModel = hiltViewModel(),
|
||||
) {
|
||||
val uiState: NewsFeedUiState by viewModel.feedState.collectAsStateWithLifecycle()
|
||||
|
||||
NewsScreen(
|
||||
feedUiState = uiState,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun NewsScreen(
|
||||
feedUiState: NewsFeedUiState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (feedUiState) {
|
||||
Loading -> Loading(modifier = modifier)
|
||||
is Success -> Content(news = feedUiState.feed, modifier = modifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Loading(modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = modifier.fillMaxSize()
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun Content(
|
||||
news: List<SaveableNewsResource>,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val focusRequester: FocusRequester = remember { FocusRequester() }
|
||||
val listState: ScalingLazyListState = rememberScalingLazyListState()
|
||||
val scope: CoroutineScope = rememberCoroutineScope()
|
||||
|
||||
Scaffold(positionIndicator = { PositionIndicator(scalingLazyListState = listState) }) {
|
||||
ScalingLazyColumn(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.onRotaryScrollEvent {
|
||||
scope.launch {
|
||||
listState.scrollBy(it.verticalScrollPixels)
|
||||
}
|
||||
true
|
||||
}
|
||||
.focusRequester(focusRequester)
|
||||
.focusable(),
|
||||
state = listState,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
items(news) { item ->
|
||||
NewsResourceItem(item = item)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NewsResourceItem(item: SaveableNewsResource) {
|
||||
TitleCard(
|
||||
onClick = { /* no-op */ },
|
||||
title = {
|
||||
Text(text = item.newsResource.title)
|
||||
},
|
||||
backgroundPainter = CardDefaults.imageWithScrimBackgroundPainter(
|
||||
backgroundImagePainter = rememberAsyncImagePainter(
|
||||
model = item.newsResource.headerImageUrl,
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
),
|
||||
content = { /* no-op */ }
|
||||
)
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.feature.wear.news
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.google.samples.apps.nowinandroid.core.domain.GetSaveableNewsResourcesStreamUseCase
|
||||
import com.google.samples.apps.nowinandroid.core.domain.model.SaveableNewsResource
|
||||
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
@HiltViewModel
|
||||
class NewsViewModel @Inject constructor(
|
||||
getSaveableNewsResourcesStream: GetSaveableNewsResourcesStreamUseCase
|
||||
) : ViewModel() {
|
||||
|
||||
val feedState: StateFlow<NewsFeedUiState> =
|
||||
getSaveableNewsResourcesStream().mapToFeedState()
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5_000),
|
||||
initialValue = NewsFeedUiState.Loading
|
||||
)
|
||||
}
|
||||
|
||||
private fun Flow<List<SaveableNewsResource>>.mapToFeedState(): Flow<NewsFeedUiState> =
|
||||
map<List<SaveableNewsResource>, NewsFeedUiState>(NewsFeedUiState::Success)
|
||||
.onStart { emit(NewsFeedUiState.Loading) }
|