diff --git a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt index 2b2a203..7bfe64b 100644 --- a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt +++ b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt @@ -7,9 +7,7 @@ import androidx.annotation.StringRes import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* -import androidx.compose.material.icons.outlined.Calculate -import androidx.compose.material.icons.outlined.List -import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material.icons.outlined.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier @@ -27,12 +25,24 @@ import androidx.navigation.compose.rememberNavController import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import me.zobrist.tichucounter.domain.TopBarAction +import me.zobrist.tichucounter.repository.GameRepository +import me.zobrist.tichucounter.ui.MainViewModel import me.zobrist.tichucounter.ui.counter.* +import me.zobrist.tichucounter.ui.history.HistoryList +import me.zobrist.tichucounter.ui.history.HistoryViewModel +import javax.inject.Inject @AndroidEntryPoint class MainActivity : BaseActivity() { + @Inject + lateinit var gameRepository: GameRepository + private val counterViewModel: CounterViewModel by viewModels() + private val historyViewModel: HistoryViewModel by viewModels() + private val mainViewModel: MainViewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -52,7 +62,7 @@ class MainActivity : BaseActivity() { MaterialTheme() { Scaffold( - topBar = { TopBar(drawerState, scope) }) { + topBar = { TopBar(drawerState, scope, mainViewModel.topBarActions) }) { NavHost( navController = navController, @@ -61,16 +71,18 @@ class MainActivity : BaseActivity() { ) { composable("counter") { Counter(counterViewModel) + mainViewModel.setActions(listOf(undoAction, newGameAction)) } composable("history") { - Column() { - Text("History") - } + HistoryList(historyViewModel) + mainViewModel.setActions(emptyList()) + } composable("settings") { Column() { Text("Settings") } + mainViewModel.setActions(emptyList()) } } } @@ -79,11 +91,15 @@ class MainActivity : BaseActivity() { @OptIn(ExperimentalMaterial3Api::class) @Composable - private fun TopBar(drawerState: DrawerState, scope: CoroutineScope) { + private fun TopBar( + drawerState: DrawerState, + scope: CoroutineScope, + actions: List + ) { CenterAlignedTopAppBar( title = { Text( - "Centered TopAppBar", + stringResource(R.string.app_name), maxLines = 1, overflow = TextOverflow.Ellipsis ) @@ -97,11 +113,13 @@ class MainActivity : BaseActivity() { } }, actions = { - IconButton(onClick = { /* doSomething() */ }) { - Icon( - imageVector = Icons.Filled.Favorite, - contentDescription = "Localized description" - ) + actions.forEach { + IconButton(onClick = { it.action() }) { + Icon( + imageVector = it.imageVector, + contentDescription = null + ) + } } } ) @@ -160,4 +178,9 @@ class MainActivity : BaseActivity() { object Settings : Screen("settings", Icons.Outlined.Settings, R.string.menu_settings) } + + + private val undoAction = TopBarAction(Icons.Outlined.Undo) { mainViewModel.undoLastRound() } + private val newGameAction = TopBarAction(Icons.Outlined.Add) { mainViewModel.newGame() } + } \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/domain/TopBarAction.kt b/app/src/main/java/me/zobrist/tichucounter/domain/TopBarAction.kt new file mode 100644 index 0000000..9770f28 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/domain/TopBarAction.kt @@ -0,0 +1,5 @@ +package me.zobrist.tichucounter.domain + +import androidx.compose.ui.graphics.vector.ImageVector + +class TopBarAction(val imageVector: ImageVector, val action: () -> Unit) \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/MainViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/ui/MainViewModel.kt new file mode 100644 index 0000000..fddb18a --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/ui/MainViewModel.kt @@ -0,0 +1,40 @@ +package me.zobrist.tichucounter.ui + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import me.zobrist.tichucounter.domain.TopBarAction +import me.zobrist.tichucounter.repository.GameRepository +import javax.inject.Inject + +@HiltViewModel +class MainViewModel @Inject constructor(private val gameRepository: GameRepository) : ViewModel() { + + var topBarTitle by mutableStateOf("") + var topBarActions by mutableStateOf(emptyList()) + private set + + fun setActions(actions: List) { + topBarActions = actions + } + + fun setTitle(title: String) { + topBarTitle = title + } + + fun undoLastRound() { + viewModelScope.launch { + gameRepository.revertLastRound() + } + } + + fun newGame() { + viewModelScope.launch { + gameRepository.newGame() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragment.kt b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragment.kt deleted file mode 100644 index d8821ec..0000000 --- a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragment.kt +++ /dev/null @@ -1,126 +0,0 @@ -package me.zobrist.tichucounter.ui.history - - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Card -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.ViewCompositionStrategy -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.fragment.app.Fragment -import androidx.fragment.app.activityViewModels -import dagger.hilt.android.AndroidEntryPoint -import me.zobrist.tichucounter.data.GameAndScore -import java.text.DateFormat -import java.util.* - - -/** - * A fragment representing a list of Items. - */ -@AndroidEntryPoint -class HistoryFragment : Fragment() { - - private val viewModel: HistoryFragmentViewModel by activityViewModels() - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return ComposeView(requireContext()).apply { - // Dispose of the Composition when the view's LifecycleOwner - // is destroyed - setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - setContent { - MaterialTheme { - HistoryList(viewModel) - } - } - } - } - - @Composable - fun HistoryList(viewModel: HistoryFragmentViewModel) { - HistoryList(viewModel.gameAndHistory) - } - - @Composable - fun HistoryList(games: List) { - LazyColumn { - items(games) { - HistoryListItem(it) - } - } - } - - @Composable - fun HistoryListItem(game: GameAndScore) { - val format = - DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault()) - - Card( - modifier = Modifier - .fillMaxWidth() - .padding(all = 4.dp), - ) { - Column( - Modifier - .padding(all = 12.dp), - ) { - Row() { - Text( - text = game.nameA, - style = MaterialTheme.typography.headlineSmall - ) - Text( - text = game.scoreA.toString(), - style = MaterialTheme.typography.headlineSmall - ) - } - Row() { - Text( - text = game.nameB, - style = MaterialTheme.typography.headlineSmall - ) - Text( - text = game.scoreB.toString(), - style = MaterialTheme.typography.headlineSmall - ) - } - Row() { - Text( - text = format.format(game.modified), - style = MaterialTheme.typography.labelSmall - ) - } - } - } - } - - @Preview - @Composable - private fun HistoryListPreview() { - val tempData = listOf( - GameAndScore(false, "abc", "def", Date(), Date(), 1, 10, 50), - GameAndScore(true, "ADTH", "dogfg", Date(), Date(), 2, 20, 60), - GameAndScore(false, "TeamA3", "TeamB3", Date(), Date(), 3, 30, 70), - GameAndScore(false, "TeamA4", "TeamB4", Date(), Date(), 4, 40, 80), - GameAndScore(false, "TeamA5", "TeamB5", Date(), Date(), 5, 50, 90) - ) - HistoryList(tempData) - } -} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryView.kt b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryView.kt new file mode 100644 index 0000000..d965100 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryView.kt @@ -0,0 +1,91 @@ +package me.zobrist.tichucounter.ui.history + + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Card +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import me.zobrist.tichucounter.data.GameAndScore +import java.text.DateFormat +import java.util.* + + +@Composable +fun HistoryList(viewModel: HistoryViewModel) { + HistoryList(viewModel.gameAndHistory) +} + +@Composable +fun HistoryList(games: List) { + LazyColumn { + items(games) { + HistoryListItem(it) + } + } +} + +@Composable +fun HistoryListItem(game: GameAndScore) { + val format = + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault()) + + Card( + modifier = Modifier + .fillMaxWidth() + .padding(all = 4.dp), + ) { + Column( + Modifier + .padding(all = 12.dp), + ) { + Row() { + Text( + text = game.nameA, + style = MaterialTheme.typography.headlineSmall + ) + Text( + text = game.scoreA.toString(), + style = MaterialTheme.typography.headlineSmall + ) + } + Row() { + Text( + text = game.nameB, + style = MaterialTheme.typography.headlineSmall + ) + Text( + text = game.scoreB.toString(), + style = MaterialTheme.typography.headlineSmall + ) + } + Row() { + Text( + text = format.format(game.modified), + style = MaterialTheme.typography.labelSmall + ) + } + } + } +} + +@Preview +@Composable +private fun HistoryListPreview() { + val tempData = listOf( + GameAndScore(false, "abc", "def", Date(), Date(), 1, 10, 50), + GameAndScore(true, "ADTH", "dogfg", Date(), Date(), 2, 20, 60), + GameAndScore(false, "TeamA3", "TeamB3", Date(), Date(), 3, 30, 70), + GameAndScore(false, "TeamA4", "TeamB4", Date(), Date(), 4, 40, 80), + GameAndScore(false, "TeamA5", "TeamB5", Date(), Date(), 5, 50, 90) + ) + HistoryList(tempData) +} diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragmentViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryViewModel.kt similarity index 93% rename from app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragmentViewModel.kt rename to app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryViewModel.kt index bece052..20a1bdb 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragmentViewModel.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryViewModel.kt @@ -13,7 +13,7 @@ import javax.inject.Inject @HiltViewModel -class HistoryFragmentViewModel @Inject constructor( +class HistoryViewModel @Inject constructor( private val gameDao: GameDao ) : ViewModel() {