Private
Public Access
1
0

Start integration with app: adds Hilt for dep injection, implements a view model

This commit is contained in:
2023-08-17 00:37:11 -07:00
parent 28f2bfe580
commit 4eef98aef4
17 changed files with 149 additions and 32 deletions

View File

@@ -1,6 +1,8 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
}
android {
@@ -31,24 +33,31 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.0'
// Note: this is strictly tied to a kotlin version, but isn't the version of kotlin exactly.
// See: https://developer.android.com/jetpack/androidx/releases/compose-kotlin
kotlinCompilerExtensionVersion '1.4.8'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
buildToolsVersion '33.0.1'
}
kotlin {
jvmToolchain(8)
}
dependencies {
implementation 'androidx.compose.material3:material3:1.1.1'
implementation 'androidx.core:core-ktx:1.10.1'
implementation "androidx.compose.material3:material3:1.1.1"
implementation "androidx.core:core-ktx:${kotlin_version}"
// Kordophone lib
implementation project(':backend')
@@ -73,14 +82,23 @@ dependencies {
// Jetpack Compose Integration
implementation "androidx.navigation:navigation-compose:$nav_version"
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.4.3'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
implementation "androidx.compose.ui:ui:1.4.3"
implementation 'androidx.compose.material:material:1.4.3'
implementation "androidx.compose.foundation:foundation:1.4.3"
debugImplementation 'androidx.compose.ui:ui-tooling:1.4.3'
// Hilt (dependency injection)
implementation "com.google.dagger:hilt-android:${hilt_version}"
implementation "androidx.hilt:hilt-navigation-compose:1.0.0"
kapt "com.google.dagger:hilt-compiler:${hilt_version}"
}
debugImplementation 'androidx.compose.ui:ui-tooling:1.4.3'
}
// Allow references to generated code
kapt {
correctErrorTypes true
}

View File

@@ -12,6 +12,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.KordophoneDroid"
android:name=".KordophoneApplication"
android:networkSecurityConfig="@xml/network_security_config"
tools:targetApi="31">
<activity
android:name=".MainActivity"

View File

@@ -0,0 +1,25 @@
package net.buzzert.kordophonedroid
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import net.buzzert.kordophone.backend.db.CachedChatDatabase
import net.buzzert.kordophone.backend.server.ChatRepository
import net.buzzert.kordophone.backend.server.RetrofitAPIClient
import java.net.URL
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideChatRepository(): ChatRepository {
val host = "http://192.168.1.123:5738"
val client = RetrofitAPIClient(URL(host))
val apiInterface = client.getAPIInterface()
val database = CachedChatDatabase.liveDatabase()
return ChatRepository(apiInterface, database)
}
}

View File

@@ -1,9 +1,11 @@
package net.buzzert.kordophonedroid
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
import net.buzzert.kordophonedroid.data.AppContainer
import net.buzzert.kordophonedroid.data.AppContainerImpl
@HiltAndroidApp
class KordophoneApplication : Application() {
lateinit var container: AppContainer

View File

@@ -3,9 +3,11 @@ package net.buzzert.kordophonedroid
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import dagger.hilt.android.AndroidEntryPoint
import net.buzzert.kordophonedroid.data.AppContainerImpl
import net.buzzert.kordophonedroid.ui.KordophoneApp
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View File

@@ -1,10 +1,18 @@
package net.buzzert.kordophonedroid.data
interface AppContainer {
val something: String
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
import net.buzzert.kordophone.backend.server.ChatRepository
interface AppContainer: ViewModelStoreOwner {
val repository: ChatRepository
}
class AppContainerImpl() : AppContainer {
override val something: String
override val repository: ChatRepository
get() = TODO("Not yet implemented")
}
override val viewModelStore: ViewModelStore
get() = TODO("Not yet implemented")
}

View File

@@ -30,7 +30,7 @@ fun KordophoneApp(
startDestination = Destination.ConversationList.route,
) {
composable(route = Destination.ConversationList.route) {
ConversationListScreen(onMessageSelected = {
ConversationListScreen(onConversationSelected = {
navController.navigate(Destination.MessageList.createRoute(it))
})
}

View File

@@ -11,7 +11,8 @@ import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Info
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ComposeCompilerApi
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
@@ -20,15 +21,23 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import net.buzzert.kordophone.backend.model.Conversation
@Composable
fun ConversationListScreen(
onMessageSelected: (conversationID: String) -> Unit
viewModel: ConversationListViewModel = hiltViewModel(),
onConversationSelected: (conversationID: String) -> Unit
) {
val conversations by viewModel.conversations.collectAsState(initial = listOf())
ConversationListView(conversations = conversations, onConversationSelected = onConversationSelected)
}
@Composable
fun ConversationListView(
conversations: List<Conversation>,
onConversationSelected: (conversationID: String) -> Unit
) {
val convos = ArrayList<String>()
for (i in 0..200) {
convos += "Test"
}
val listState = rememberLazyListState()
@@ -42,12 +51,12 @@ fun ConversationListScreen(
}
) {
LazyColumn(state = listState, modifier = Modifier.padding(it)) {
items(convos) { conversation ->
items(conversations) { conversation ->
ConversationListItem(
name = "James Magahern",
id = "asdf",
isUnread = false,
onClick = { onMessageSelected("asdf") }
name = conversation.formattedDisplayName(),
id = conversation.guid,
isUnread = conversation.unreadCount > 0,
onClick = { onConversationSelected(conversation.guid) }
)
}
}
@@ -137,5 +146,5 @@ fun ConversationListItemPreview() {
@Preview
@Composable
fun ConversationListScreenPreview() {
ConversationListScreen(onMessageSelected = {})
ConversationListScreen(onConversationSelected = {})
}

View File

@@ -0,0 +1,24 @@
package net.buzzert.kordophonedroid.ui.conversationlist
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import net.buzzert.kordophone.backend.model.Conversation
import net.buzzert.kordophone.backend.server.ChatRepository
import javax.inject.Inject
@HiltViewModel
class ConversationListViewModel @Inject constructor(
private val repository: ChatRepository
) : ViewModel() {
val conversations: Flow<List<Conversation>>
get() = repository.conversationChanges
init {
viewModelScope.launch {
repository.synchronize()
}
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">192.168.1.123</domain>
</domain-config>
</network-security-config>