Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Konnectivity library to access and monitor network state changes #53

Merged
merged 1 commit into from
Dec 8, 2023
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
2 changes: 2 additions & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ dependencies {
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.compose.material)

implementation(libs.androidx.startup.runtime)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.tooling.preview.Preview
import com.mirego.kmp.boilerplate.previews.PreviewContext
import kotlinx.coroutines.flow.Flow

@Composable
Expand All @@ -17,5 +18,7 @@ fun Greeting(textFlow: Flow<String>) {
@Preview(showSystemUi = true)
@Composable
fun PreviewGreeting() {
Greeting(Greeting().greeting())
PreviewContext {
Greeting(Greeting().greeting())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mirego.kmp.boilerplate.previews

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.startup.AppInitializer
import com.mirego.kmp.boilerplate.platform.AppContextInitializer

@Composable
fun PreviewContext(content: @Composable () -> Unit) {
// @Composable previews do not call AppInitializer. We must initialize our components manually.
AppInitializer.getInstance(LocalContext.current)
.initializeComponent(AppContextInitializer::class.java)

content()
}
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[versions]
androidComposeCompiler = "1.5.6"
androidGradlePlugin = "8.2.0"
androidxStartup = "1.1.1"
androidxActivityCompose = "1.8.1"
androidxAppcompat = "1.6.1"
androidxComposeBom = "2023.10.01"
konnectivity = "0.3.0"
kotlin = "1.9.21"
kotlinxCoroutines = "1.7.3"
kotlinxSerialization = "1.6.0"
Expand All @@ -16,6 +18,8 @@ androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", versi
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-compose-material = { group = "androidx.compose.material", name = "material" }
androidx-startup-runtime = { module = "androidx.startup:startup-runtime", version.ref = "androidxStartup" }
konnectivity = { module = "com.mirego:konnectivity", version.ref = "konnectivity" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
Expand Down
8 changes: 6 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
PODS:
- Shared (0.0.1)
- Reachability (3.2)
- Shared (0.0.1):
- Reachability (~> 3.2)
- SwiftLint (0.52.4)

DEPENDENCIES:
Expand All @@ -8,14 +10,16 @@ DEPENDENCIES:

SPEC REPOS:
trunk:
- Reachability
- SwiftLint

EXTERNAL SOURCES:
Shared:
:path: "../shared"

SPEC CHECKSUMS:
Shared: 4d22deb908e7a9ed9a64ea2d3fcc53255a207993
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
Shared: 394ccbb1a148f40e374cb91aa5b75c96b121a775
SwiftLint: 1cc5cd61ba9bacb2194e340aeb47a2a37fda00b3

PODFILE CHECKSUM: 83ebf5d7b61ce65029f18160027c7392430ee27f
Expand Down
4 changes: 4 additions & 0 deletions ios/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; };
7555FF83242A565900829871 /* GreetingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* GreetingView.swift */; };
9B8ACFDB4E332DFCA8B97CBB /* Pods_iosApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E4E1328B104D05A50A097EE /* Pods_iosApp.framework */; };
BC5700EB2B1A94D200525C22 /* PreviewContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC5700EA2B1A94D200525C22 /* PreviewContext.swift */; };
BC83B466276E4F080053E064 /* FlowUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC83B465276E4F080053E064 /* FlowUtils.swift */; };
/* End PBXBuildFile section */

Expand All @@ -24,6 +25,7 @@
7555FF7B242A565900829871 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF82242A565900829871 /* GreetingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GreetingView.swift; sourceTree = "<group>"; };
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BC5700EA2B1A94D200525C22 /* PreviewContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewContext.swift; sourceTree = "<group>"; };
BC83B465276E4F080053E064 /* FlowUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlowUtils.swift; sourceTree = "<group>"; };
E232C917135C2C1E3BC8748A /* Pods-iosApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosApp.release.xcconfig"; path = "Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand All @@ -44,6 +46,7 @@
isa = PBXGroup;
children = (
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */,
BC5700EA2B1A94D200525C22 /* PreviewContext.swift */,
);
path = "Preview Content";
sourceTree = "<group>";
Expand Down Expand Up @@ -240,6 +243,7 @@
files = (
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */,
7555FF83242A565900829871 /* GreetingView.swift in Sources */,
BC5700EB2B1A94D200525C22 /* PreviewContext.swift in Sources */,
BC83B466276E4F080053E064 /* FlowUtils.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
4 changes: 3 additions & 1 deletion ios/iosApp/GreetingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ struct GreetingView: View {
}

#Preview {
GreetingView()
PreviewContext {
GreetingView()
}
}
10 changes: 10 additions & 0 deletions ios/iosApp/Preview Content/PreviewContext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Shared
import SwiftUI

struct PreviewContext<Content>: View where Content: View {
let content: @MainActor () -> Content

var body: some View {
content()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it'll be used eventually to initialize things such as kword?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly! In #57, I use it to provide a ViewModelFactory to our Previews ๐Ÿ™‚

@Composable
fun PreviewContext(content: @Composable (ViewModelFactory) -> Unit) {
    val viewModelFactory = ViewModelFactory()

    content(viewModelFactory)
}

}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://s3.amazonaws.com/mirego-maven/public")
}
}

Expand Down
4 changes: 2 additions & 2 deletions shared/Shared.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Pod::Spec.new do |spec|
spec.summary = 'Project summary'
spec.vendored_frameworks = 'build/cocoapods/framework/Shared.framework'
spec.libraries = 'c++'
spec.ios.deployment_target = '15.0'
spec.dependency 'Reachability', '~> 3.2'

if !Dir.exist?('build/cocoapods/framework/Shared.framework') || Dir.empty?('build/cocoapods/framework/Shared.framework')
raise "
Expand Down
10 changes: 10 additions & 0 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ kotlin {
framework {
baseName = "Shared"
}
ios.deploymentTarget = "15.0"

pod("Reachability", "~> 3.2")
}

sourceSets {
Expand All @@ -45,6 +48,7 @@ kotlin {
dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
api(libs.konnectivity)
}
}

Expand All @@ -54,6 +58,12 @@ kotlin {
implementation(libs.kotlinx.coroutines.test)
}
}

androidMain {
dependencies {
implementation(libs.androidx.startup.runtime)
}
}
}

@OptIn(ExperimentalKotlinGradlePluginApi::class)
Expand Down
16 changes: 15 additions & 1 deletion shared/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest />
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.mirego.kmp.boilerplate.platform.AppContextInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mirego.kmp.boilerplate.platform

import android.content.Context
import androidx.startup.Initializer
import com.mirego.konnectivity.KonnectivityInitializer

internal lateinit var appContext: Context

class AppContextInitializer : Initializer<Unit> {
override fun create(context: Context) {
appContext = context
}

override fun dependencies() = listOf(
KonnectivityInitializer::class.java
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,33 @@ package com.mirego.kmp.boilerplate
import com.mirego.kmp.boilerplate.platform.Platform
import com.mirego.kmp.boilerplate.utils.CFlow
import com.mirego.kmp.boilerplate.utils.wrap
import kotlinx.coroutines.flow.flowOf
import com.mirego.konnectivity.Konnectivity
import com.mirego.konnectivity.NetworkState
import kotlinx.coroutines.flow.map

class Greeting {
private val platform = Platform()
private val konnectivity = Konnectivity()

private val greetingText = buildString {
appendLine("Hello! ๐Ÿ‘‹")
appendLine(platform.system)
appendLine(platform.locale)
appendLine(platform.version)
appendLine()
}

fun greeting(): CFlow<String> = flowOf(greetingText).wrap()
fun greeting(): CFlow<String> = konnectivity.networkState
.map { networkState ->
greetingText + networkState.asGreetingInfo()
}
.wrap()

private fun NetworkState.asGreetingInfo(): String = "By the way, you're " + when (this) {
NetworkState.Unreachable -> "offline. ๐Ÿ”Œ"
is NetworkState.Reachable -> when (metered) {
true -> "online, but your connection is metered. ๐Ÿ“ถ"
else -> "online! ๐Ÿ›œ"
}
}
}
Loading