Skip to content

Commit

Permalink
locker bottom sheet, add action buttons to watchface+watchapp components
Browse files Browse the repository at this point in the history
  • Loading branch information
crc-32 committed Sep 19, 2024
1 parent aa86384 commit 7f7dec6
Show file tree
Hide file tree
Showing 16 changed files with 350 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class KMPApiBridge @Inject constructor(
activity?.let {
Timber.d("Opening locker view")
val intent = Intent(activity.context, MainActivity::class.java)
intent.putExtra("navigationPath", Routes.Home.LOCKER)
intent.putExtra("navigationPath", Routes.Home.LOCKER_WATCHFACES)
activity.startActivity(intent)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ class LockerSyncJob: KoinComponent {
private val blobDBService: BlobDBService by inject()
suspend fun beginSync(): Boolean {
val locker = RWS.appstoreClient?.getLocker() ?: return false
lockerDao.clearAll()
val storedLocker = lockerDao.getAllEntries()

val changedEntries = locker.filter { new ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.rebble.cobble.shared.ui.common

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.isUnspecified
import androidx.compose.ui.unit.dp

@Composable
fun AppIconContainer(color: Color = Color.Unspecified, modifier: Modifier = Modifier, content: @Composable () -> Unit) {
val background = remember { if (color.isUnspecified) randomColor() else color }
Box(
modifier = Modifier.clip(RoundedCornerShape(8.dp)).background(background).size(48.dp).then(modifier),
contentAlignment = Alignment.Center
) {
content()
}
}

fun randomColor(): Color {
return listOf(
Color(0xFF41CBF7),
Color(0xFF008DFF),
Color(0xFF00A982),
Color(0xFFFFFF00),
Color(0xFF6B1D97)
).random()
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ object RebbleIcons {
@Composable
fun dragHandle(modifier: Modifier = Modifier.width(24.dp)) = TextIcon(font(), Char(0xe82b), "Drag handle", modifier = modifier)
@Composable
fun deleteTrash(modifier: Modifier = Modifier.width(24.dp)) = TextIcon(font(), Char(0xe82c), modifier = modifier)
fun deleteTrash(modifier: Modifier = Modifier.width(24.dp)) = TextIcon(font(), Char(0xe82c), "Delete", modifier = modifier)
@Composable
fun sendToWatchUnchecked(modifier: Modifier = Modifier.width(24.dp)) = TextIcon(font(), Char(0xe82d), modifier = modifier)
@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package io.rebble.cobble.shared.ui.common

import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.width
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.semantics.contentDescription
Expand All @@ -14,12 +16,12 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp

@Composable
fun TextIcon(font: FontFamily, char: Char, contentDescription: String = "Icon", modifier: Modifier = Modifier) {
fun TextIcon(font: FontFamily, char: Char, contentDescription: String = "Icon", modifier: Modifier = Modifier, tint: Color = LocalContentColor.current) {
BoxWithConstraints(modifier = modifier) {
val size = with(LocalDensity.current) { constraints.maxWidth.toSp() }
Text(
text = char.toString(),
style = TextStyle(fontFamily = font, fontSize = size),
style = TextStyle(fontFamily = font, fontSize = size, color = tint),
modifier = Modifier.semantics {
this.contentDescription = contentDescription
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.rebble.cobble.shared.ui.nav

object Routes {
object Home {
const val LOCKER = "locker"
const val LOCKER_APPS = "locker_apps"
const val LOCKER_WATCHFACES = "locker_watchfaces"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import androidx.navigation.compose.rememberNavController
import io.rebble.cobble.shared.ui.LocalTheme
import io.rebble.cobble.shared.ui.Theme
import io.rebble.cobble.shared.ui.nav.Routes
import io.rebble.cobble.shared.ui.view.home.HomePages
import io.rebble.cobble.shared.ui.view.home.HomePage
import io.rebble.cobble.shared.ui.view.home.HomeScaffold
import io.rebble.cobble.shared.ui.view.home.locker.LockerTabs
import org.koin.compose.KoinContext

@Composable
Expand All @@ -28,9 +29,12 @@ fun MainView(navController: NavHostController = rememberNavController()) {
MaterialTheme(
colorScheme = theme.materialColors
) {
NavHost(navController = navController, startDestination = Routes.Home.LOCKER) {
composable(Routes.Home.LOCKER) {
HomeScaffold(HomePages.Locker)
NavHost(navController = navController, startDestination = Routes.Home.LOCKER_WATCHFACES) {
composable(Routes.Home.LOCKER_WATCHFACES) {
HomeScaffold(HomePage.Locker(LockerTabs.Watchfaces), onNavChange = navController::navigate)
}
composable(Routes.Home.LOCKER_APPS) {
HomeScaffold(HomePage.Locker(LockerTabs.Apps), onNavChange = navController::navigate)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,30 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.rebble.cobble.shared.ui.common.RebbleIcons
import io.rebble.cobble.shared.ui.nav.Routes
import io.rebble.cobble.shared.ui.view.home.locker.Locker
import io.rebble.cobble.shared.ui.view.home.locker.LockerTabs

enum class HomePages {
Locker
open class HomePage {
class Locker(val tab: LockerTabs) : HomePage()
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScaffold(page: HomePages) {
fun HomeScaffold(page: HomePage, onNavChange: (String) -> Unit) {
Scaffold(
topBar = {
/*topBar = {
TopAppBar(
windowInsets = WindowInsets.statusBars,
title = { Text("Cobble") },
)
},
},*/
bottomBar = {
NavigationBar(
windowInsets = WindowInsets.navigationBars
) {
NavigationBarItem(
selected = page == HomePages.Locker,
onClick = { },
selected = page is HomePage.Locker,
onClick = { onNavChange(Routes.Home.LOCKER_WATCHFACES) },
icon = { RebbleIcons.locker() },
label = { Text("Locker") }
)
Expand All @@ -37,8 +38,10 @@ fun HomeScaffold(page: HomePages) {
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
when (page) {
HomePages.Locker -> {
Locker()
is HomePage.Locker -> {
Locker(page.tab, onTabChanged = {
onNavChange(it.navRoute)
})
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,53 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import io.rebble.cobble.shared.database.dao.LockerDao
import io.rebble.cobble.shared.database.entity.SyncedLockerEntryWithPlatforms
import io.rebble.cobble.shared.ui.nav.Routes
import io.rebble.cobble.shared.ui.viewmodel.LockerItemViewModel
import io.rebble.cobble.shared.ui.viewmodel.LockerViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.launch
import org.koin.compose.getKoin

enum class LockerTabs(val label: String) {
Apps("Apps"),
Watchfaces("Watchfaces"),
enum class LockerTabs(val label: String, val navRoute: String) {
Watchfaces("My watch faces", Routes.Home.LOCKER_WATCHFACES),
Apps("My apps", Routes.Home.LOCKER_APPS),
}

@Composable
fun Locker(lockerDao: LockerDao = getKoin().get(), viewModel: LockerViewModel = viewModel { LockerViewModel(lockerDao) }) {
fun Locker(page: LockerTabs, lockerDao: LockerDao = getKoin().get(), viewModel: LockerViewModel = viewModel { LockerViewModel(lockerDao) }, onTabChanged: (LockerTabs) -> Unit) {
val entriesState: LockerViewModel.LockerEntriesState by viewModel.entriesState.collectAsState()
val tab = remember { mutableStateOf(LockerTabs.Apps) }
val modalSheetState by viewModel.modalSheetState.collectAsState()

Column {
Surface {
Row(modifier = Modifier.fillMaxWidth().height(64.dp)) {
LockerTabs.entries.forEachIndexed { index, it ->
NavigationBarItem(
selected = tab.value == it,
onClick = { tab.value = it },
selected = page == it,
onClick = { onTabChanged(it) },
icon = { Text(it.label) },
)
}
}
}

if (entriesState is LockerViewModel.LockerEntriesState.Loaded) {
when (tab.value) {
when (page) {
LockerTabs.Apps -> {
LockerAppList(viewModel)
LockerAppList(viewModel, onOpenModalSheet = { viewModel.openModalSheet(it) })
}

LockerTabs.Watchfaces -> {
LockerWatchfaceList(viewModel)
LockerWatchfaceList(viewModel, onOpenModalSheet = { viewModel.openModalSheet(it) })
}
}
} else {
CircularProgressIndicator(modifier = Modifier.align(CenterHorizontally))
}
}
if (modalSheetState is LockerViewModel.ModalSheetState.Open) {
val sheetViewModel = (modalSheetState as LockerViewModel.ModalSheetState.Open).viewModel
LockerItemSheet(onDismissRequest = { viewModel.closeModalSheet() }, viewModel = sheetViewModel)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import sh.calvin.reorderable.rememberReorderableLazyListState

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun LockerAppList(viewModel: LockerViewModel) {
fun LockerAppList(viewModel: LockerViewModel, onOpenModalSheet: (LockerItemViewModel) -> Unit) {
val lazyListState = rememberLazyListState()
val koin = getKoin()
val entriesState by viewModel.entriesState.collectAsState()
Expand All @@ -40,7 +40,7 @@ fun LockerAppList(viewModel: LockerViewModel) {
LazyColumn(state = lazyListState, modifier = Modifier.fillMaxSize()) {
items(entries.size, key = { i -> entries[i].entry.id }) { i ->
ReorderableItem(state = reorderableLazyListState, key = entries[i].entry.id) { isDragging ->
LockerListItem(koin.get(), entries[i], trailingContent = {
LockerListItem(koin.get(), entries[i], onOpenModalSheet = onOpenModalSheet, dragHandle = {
IconButton(
modifier = Modifier.draggableHandle(),
content = { RebbleIcons.dragHandle() },
Expand Down
Loading

0 comments on commit 7f7dec6

Please sign in to comment.