Skip to content

Commit

Permalink
Major Update: iOS app now uses native NavigationLink and has default …
Browse files Browse the repository at this point in the history
…navigation animation; added Desktop app
  • Loading branch information
dbaroncelli committed Jun 25, 2021
1 parent d316316 commit 0323eab
Show file tree
Hide file tree
Showing 66 changed files with 1,198 additions and 208 deletions.
18 changes: 9 additions & 9 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ plugins {

dependencies {
implementation(project(":shared"))
implementation("androidx.activity:activity-compose:1.3.0-alpha08")
implementation("androidx.activity:activity-compose:1.3.0-beta02")
implementation("androidx.lifecycle:lifecycle-process:2.3.1")
implementation("androidx.appcompat:appcompat:1.4.0-alpha01")
implementation("androidx.compose.ui:ui:${Versions.compose}")
implementation("androidx.compose.ui:ui-graphics:${Versions.compose}")
implementation("androidx.compose.ui:ui-tooling:${Versions.compose}")
implementation("androidx.compose.foundation:foundation-layout:${Versions.compose}")
implementation("androidx.compose.material:material:${Versions.compose}")
implementation("androidx.compose.material:material-icons-extended:${Versions.compose}")
implementation("androidx.appcompat:appcompat:1.4.0-alpha02")
implementation("androidx.compose.ui:ui:${Versions.jetpackCompose}")
implementation("androidx.compose.ui:ui-graphics:${Versions.jetpackCompose}")
implementation("androidx.compose.ui:ui-tooling:${Versions.jetpackCompose}")
implementation("androidx.compose.foundation:foundation-layout:${Versions.jetpackCompose}")
implementation("androidx.compose.material:material:${Versions.jetpackCompose}")
implementation("androidx.compose.material:material-icons-extended:${Versions.jetpackCompose}")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
}

Expand Down Expand Up @@ -65,7 +65,7 @@ android {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = Versions.compose
kotlinCompilerExtensionVersion = Versions.jetpackCompose
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fun Navigation.Router() {

if (!only1ScreenInBackstack) {
BackHandler { // catching the back button to update the DKMPViewModel
exitScreen(true)
exitScreen()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import androidx.compose.runtime.Composable
import eu.baroncelli.dkmpsample.android.composables.screens.countrydetail.CountryDetailScreen
import eu.baroncelli.dkmpsample.android.composables.screens.countrieslist.CountriesListScreen
import eu.baroncelli.dkmpsample.android.composables.screens.countrieslist.CountriesListTwoPaneDefaultDetail
import eu.baroncelli.dkmpsample.shared.viewmodel.Events
import eu.baroncelli.dkmpsample.shared.viewmodel.Navigation
import eu.baroncelli.dkmpsample.shared.viewmodel.ScreenIdentifier
import eu.baroncelli.dkmpsample.shared.viewmodel.StateProvider
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.Screen.*
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.countrieslist.selectFavorite
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.countrydetail.CountryDetailParams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ fun CountriesListScreen(
onListItemClick: (String) -> Unit,
onFavoriteIconClick : (String) -> Unit,
) {

if (countriesListState.isLoading) {

LoadingScreen()
Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ group = "eu.baroncelli.dkmpsample"
version = "1.0-SNAPSHOT"



buildscript {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.1.0-alpha01")
classpath("com.android.tools.build:gradle:7.1.0-alpha02")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}")
classpath("org.jetbrains.kotlin:kotlin-serialization:${Versions.kotlin}")
classpath("com.squareup.sqldelight:gradle-plugin:${Versions.sql_delight}")
Expand All @@ -23,5 +22,6 @@ allprojects {
google()
maven(url = "https://kotlin.bintray.com/kotlinx/")
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ plugins {
`kotlin-dsl`
}
repositories {
jcenter()
mavenCentral()
}
7 changes: 4 additions & 3 deletions buildSrc/src/main/java/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ object Versions {
const val min_sdk = 21
const val target_sdk = 30

const val compose = "1.0.0-beta07"
const val kotlin = "1.4.32"
const val ktor = "1.5.3"
const val jetpackCompose = "1.0.0-beta09"
const val jetbrainsCompose = "0.5.0-build226"
const val kotlin = "1.5.10"
const val ktor = "1.6.0"
const val sql_delight = "1.5.0"
}

Empty file added composables/build.gradle.kts
Empty file.
2 changes: 2 additions & 0 deletions composables/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="eu.baroncelli.dkmpsample.shared"/>
48 changes: 48 additions & 0 deletions desktopApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat

plugins {
kotlin("multiplatform")
id("org.jetbrains.compose") version Versions.jetbrainsCompose
}

repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}

kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
}
sourceSets {
all {
languageSettings.apply {
useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
useExperimentalAnnotation("androidx.compose.ui.ExperimentalComposeUiApi")
useExperimentalAnnotation("androidx.compose.foundation.ExperimentalFoundationApi")
}
}
val jvmMain by getting {
dependencies {
implementation(project(":shared"))
implementation(compose.desktop.currentOs)
}
}
}
}



compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "jvm"
packageVersion = "1.0.0"
}
}
}
Binary file not shown.
15 changes: 15 additions & 0 deletions desktopApp/src/jvmMain/kotlin/composables/MainComposable.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package eu.baroncelli.dkmpsample.desktop.composables.navigation

import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import eu.baroncelli.dkmpsample.shared.viewmodel.DKMPViewModel

@Composable
fun MainComposable(model: DKMPViewModel) {
val appState by model.stateFlow.collectAsState()
println("D-KMP-SAMPLE: recomposition Index: "+appState.recompositionIndex.toString())
val dkmpNav = appState.getNavigation(model)
dkmpNav.Router()
}

38 changes: 38 additions & 0 deletions desktopApp/src/jvmMain/kotlin/composables/navigation/Router.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package eu.baroncelli.dkmpsample.desktop.composables.navigation

import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.runtime.Composable
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.unit.dp
import eu.baroncelli.dkmpsample.desktop.composables.navigation.templates.OnePane
import eu.baroncelli.dkmpsample.desktop.composables.navigation.templates.TwoPane
import eu.baroncelli.dkmpsample.shared.viewmodel.*

@Composable
fun Navigation.Router() {

val screenUIsStateHolder = rememberSaveableStateHolder()

val twopaneWidthThreshold = 1000.dp
BoxWithConstraints() {
if (maxWidth < maxHeight || maxWidth<twopaneWidthThreshold) {
OnePane(screenUIsStateHolder)
} else {
TwoPane(screenUIsStateHolder)
}
}

screenStatesToRemove.forEach {
screenUIsStateHolder.removeState(it.URI)
println("D-KMP: removed UI screen "+it.URI)
}

/*
if (!only1ScreenInBackstack) {
BackHandler { // catching the back button to update the DKMPViewModel
exitScreen()
}
}
*/

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package eu.baroncelli.dkmpsample.desktop.composables.navigation

import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import eu.baroncelli.dkmpsample.desktop.composables.screens.countrydetail.CountryDetailScreen
import eu.baroncelli.dkmpsample.desktop.composables.screens.countrieslist.CountriesListScreen
import eu.baroncelli.dkmpsample.desktop.composables.screens.countrieslist.CountriesListTwoPaneDefaultDetail
import eu.baroncelli.dkmpsample.shared.viewmodel.Navigation
import eu.baroncelli.dkmpsample.shared.viewmodel.ScreenIdentifier
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.Screen.*
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.countrieslist.selectFavorite
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.countrydetail.CountryDetailParams


@Composable
fun Navigation.ScreenPicker(
screenIdentifier: ScreenIdentifier
) {

when (screenIdentifier.screen) {

CountriesList ->
CountriesListScreen(
countriesListState = stateProvider.get(screenIdentifier),
onListItemClick = { navigate(CountryDetail, CountryDetailParams(countryName = it)) },
onFavoriteIconClick = { events.selectFavorite(countryName = it) },
)

CountryDetail ->
CountryDetailScreen(
countryDetailState = stateProvider.get(screenIdentifier)
)

}

}



@Composable
fun Navigation.TwoPaneDefaultDetail(
screenIdentifier: ScreenIdentifier
) {

when (screenIdentifier.screen) {

CountriesList ->
CountriesListTwoPaneDefaultDetail()

else -> Box{}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package eu.baroncelli.dkmpsample.desktop.composables.screens.countrieslist

import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.BottomAppBar
import androidx.compose.material.BottomNavigationItem
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Star
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.sp
import eu.baroncelli.dkmpsample.shared.viewmodel.Navigation
import eu.baroncelli.dkmpsample.shared.viewmodel.ScreenIdentifier
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.Level1Navigation
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.countrieslist.CountriesListType


// this is the bottom horizontal navigation bar for 1-Pane visualization
// (used by small devices and in Portrait mode)

@Composable
fun Navigation.Level1BottomBar(
selectedTab: ScreenIdentifier
) {
BottomAppBar(content = {
BottomNavigationItem(
icon = { Icon(Icons.Default.Menu, "ALL") },
label = { Text("All Countries", fontSize = 13.sp) },
selected = selectedTab.URI == Level1Navigation.AllCountries.screenIdentifier.URI,
onClick = { navigateByLevel1Menu(Level1Navigation.AllCountries) }
)
BottomNavigationItem(
icon = { Icon(Icons.Default.Star, "FAVORITES") },
label = { Text("Favourites", fontSize = 13.sp) },
selected = selectedTab.URI == Level1Navigation.FavoriteCountries.screenIdentifier.URI,
onClick = { navigateByLevel1Menu(Level1Navigation.FavoriteCountries) }
)
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package eu.baroncelli.dkmpsample.desktop.composables.navigation.templates

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Star
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.baroncelli.dkmpsample.shared.viewmodel.Navigation
import eu.baroncelli.dkmpsample.shared.viewmodel.ScreenIdentifier
import eu.baroncelli.dkmpsample.shared.viewmodel.screens.Level1Navigation


// this is the left vertical navigation bar for 2-Pane visualization
// (used by bigger devices in landscape mode)

@Composable
fun Navigation.Level1NavigationRail(
selectedTab: ScreenIdentifier
) {
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
.background(MaterialTheme.colors.primary),
verticalArrangement = Arrangement.Center
) {
NavigationRailItem(
icon = { Icon(Icons.Default.Menu, "ALL") },
label = { Text("All Countries", fontSize = 13.sp) },
selected = selectedTab.URI == Level1Navigation.AllCountries.screenIdentifier.URI,
onClick = { navigateByLevel1Menu(Level1Navigation.AllCountries) }
)
NavigationRailItem(
icon = { Icon(Icons.Default.Star, "FAVORITES") },
label = { Text("Favourites", fontSize = 13.sp) },
selected = selectedTab.URI == Level1Navigation.FavoriteCountries.screenIdentifier.URI,
onClick = { navigateByLevel1Menu(Level1Navigation.FavoriteCountries) }
)
}
}



@Composable
fun ColumnScope.NavigationRailItem(icon : @Composable () -> Unit , label : @Composable () -> Unit, selected : Boolean, onClick : () -> Unit) {
CompositionLocalProvider(
LocalContentColor provides if (selected) MaterialTheme.colors.background else MaterialTheme.colors.primaryVariant
) {
Row(
modifier = Modifier
.clickable { onClick() }
.padding(top = 25.dp, bottom = 25.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
icon()
label()
}
}
}
}
Loading

0 comments on commit 0323eab

Please sign in to comment.