Skip to content

Commit

Permalink
add right & left click on browser
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-tennert committed Nov 13, 2023
1 parent 81c810f commit de435c0
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 131 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.github.jan.einkaufszettel.ui.screen.app.tabs.components

import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.ui.input.pointer.PointerInputScope

internal actual suspend fun PointerInputScope.handleClicks(
interactionSource: MutableInteractionSource,
onLeftClick: () -> Unit,
onRightClick: (x: Float, y: Float) -> Unit
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.github.jan.einkaufszettel.ui.screen.app.tabs

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import cafe.adriel.voyager.core.screen.Screen
import io.github.jan.einkaufszettel.collectAsStateWithLifecycle
import io.github.jan.einkaufszettel.ui.screen.app.AppState
import io.github.jan.einkaufszettel.ui.screen.app.AppStateErrorHandler
import io.github.jan.einkaufszettel.ui.screen.app.AppStateModel

interface AppStateScreen<ScreenModel : AppStateModel>: Screen {

@Composable
override fun Content() {
val screenModel = createScreenModel()
val appState by screenModel.state.collectAsStateWithLifecycle()
Content(screenModel, appState)

AppStateErrorHandler(
state = appState,
resetState = screenModel::resetState
)
}

@Composable
fun createScreenModel(): ScreenModel

@Composable
fun Content(screenModel: ScreenModel, state: AppState)

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.material3.DropdownMenu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.isSecondaryPressed
import androidx.compose.ui.input.pointer.PointerInputScope
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
Expand All @@ -27,10 +27,10 @@ import io.github.jan.supabase.PlatformTarget
fun ContextMenuScope(
modifier: Modifier = Modifier,
onItemClicked: () -> Unit = {},
items: @Composable ColumnScope.() -> Unit,
items: @Composable ColumnScope.(contextMenuVisible: MutableState<Boolean>) -> Unit,
content: @Composable (indication: InteractionSource) -> Unit
) {
var isContextMenuVisible by remember { mutableStateOf(false) }
val isContextMenuVisible = remember { mutableStateOf(false) }
var pressOffset by remember { mutableStateOf(DpOffset.Zero) }
var itemHeight by remember { mutableStateOf(0.dp) }
val density = LocalDensity.current
Expand All @@ -43,11 +43,11 @@ fun ContextMenuScope(
itemHeight = with(density) { it.height.toDp() }
}
.let {
if(CurrentPlatformTarget == PlatformTarget.ANDROID || true) {
if(CurrentPlatformTarget == PlatformTarget.ANDROID) {
it.pointerInput(Unit) {
detectTapGestures(
onLongPress = { offset ->
isContextMenuVisible = true
isContextMenuVisible.value = true
pressOffset = DpOffset(offset.x.toDp(), offset.y.toDp())
},
onPress = { offset ->
Expand All @@ -63,29 +63,35 @@ fun ContextMenuScope(
}
} else {
it.pointerInput(Unit) {
awaitPointerEventScope {
val event = awaitPointerEvent()
if (event.type == PointerEventType.Press &&
event.buttons.isSecondaryPressed
) {
event.changes.forEach { e -> e.consume() }
println("right click")
} else if (event.type == PointerEventType.Press && event.buttons.isSecondaryPressed) {
event.changes.forEach { e -> e.consume() }
handleClicks(
interactionSource = interactionSource,
onLeftClick = {
onItemClicked()
},
onRightClick = { x, y ->
isContextMenuVisible.value = true
pressOffset = DpOffset(x.dp, y.dp)
}
}
)
}
}
}
.then(modifier)
) {
content(interactionSource)
DropdownMenu(
expanded = isContextMenuVisible,
onDismissRequest = { isContextMenuVisible = false },
expanded = isContextMenuVisible.value,
onDismissRequest = { isContextMenuVisible.value = false },
offset = pressOffset.copy(y = pressOffset.y - itemHeight),
content = items
content = {
items(isContextMenuVisible)
}
)
}
}
}

internal expect suspend fun PointerInputScope.handleClicks(
interactionSource: MutableInteractionSource,
onLeftClick: () -> Unit,
onRightClick: (x: Float, y: Float) -> Unit
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import io.github.jan.einkaufszettel.Res
import io.github.jan.einkaufszettel.collectAsStateWithLifecycle
import io.github.jan.einkaufszettel.ui.screen.app.AppStateErrorHandler
import io.github.jan.einkaufszettel.ui.screen.app.AppState
import io.github.jan.einkaufszettel.ui.screen.app.tabs.AppStateScreen
import io.github.jan.einkaufszettel.ui.screen.app.tabs.components.ProductCard

data object HomeTab: Tab {
data object HomeTab: Tab, AppStateScreen<HomeScreenModel> {

override val options: TabOptions
@Composable
Expand All @@ -47,22 +48,20 @@ data object HomeTab: Tab {
}
}

@Composable
override fun createScreenModel(): HomeScreenModel {
return getScreenModel<HomeScreenModel>()
}

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
override fun Content() {
override fun Content(screenModel: HomeScreenModel, state: AppState) {
val windowSizeClass = calculateWindowSizeClass()
val screenModel = getScreenModel<HomeScreenModel>()
val screenModelState by screenModel.state.collectAsStateWithLifecycle()
val shopAndProducts by screenModel.shopAndProductFlow.collectAsStateWithLifecycle()
when(windowSizeClass.widthSizeClass) {
WindowWidthSizeClass.Compact, WindowWidthSizeClass.Medium -> CompactContent(shopAndProducts, screenModel)
WindowWidthSizeClass.Expanded -> ExpandedContent(shopAndProducts, screenModel)
}

AppStateErrorHandler(
state = screenModelState,
resetState = screenModel::resetState,
)
}

@OptIn(ExperimentalFoundationApi::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.QuestionMark
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -55,12 +59,18 @@ fun RecipeCard(
items = {
DropdownMenuItem(
text = { Text(Res.string.edit) },
onClick = onEdit,
onClick = {
onEdit()
it.value = false
},
enabled = isOwner
)
DropdownMenuItem(
text = { Text(Res.string.delete) },
onClick = onDelete,
onClick = {
onDelete()
it.value = false
},
enabled = isOwner
)
}
Expand All @@ -74,44 +84,47 @@ fun RecipeCard(
) {
Text(recipe.name, maxLines = 2, overflow = TextOverflow.Ellipsis)
Spacer(Modifier.height(4.dp))
if(CurrentPlatformTarget != PlatformTarget.JS) {
RecipeCardImage(recipe.imagePath, Modifier.weight(1f))
}
RecipeCardImage(recipe.imagePath, Modifier.weight(1f))
}
}
}
}

@Composable
private fun RecipeCardImage(imagePath: String?, modifier: Modifier) {
Box(modifier) {
if(imagePath != null) {
Box(modifier, contentAlignment = Alignment.Center) {
if (imagePath != null && CurrentPlatformTarget != PlatformTarget.JS) {
AutoSizeBox(
request = remember { ImageRequest(authenticatedStorageItem("recipes", imagePath)) {
scale(Scale.FIT)
size(SizeResolver {
Size(200f, 200f)
})
} },
modifier = modifier
request = remember {
ImageRequest(authenticatedStorageItem("recipes", imagePath)) {
scale(Scale.FIT)
size(SizeResolver {
Size(200f, 200f)
})
}
},
modifier = Modifier.matchParentSize()
) { action ->
when (action) {
is ImageAction.Loading -> {
LoadingCircle()
}

is ImageAction.Success -> {
Image(
painter = rememberImageSuccessPainter(action),
contentDescription = null
contentDescription = null,
modifier = Modifier.matchParentSize()
)
}

is ImageAction.Failure -> {
// TODO
}
}
}
} else {
// TODO question mark as icon
Icon(Icons.Filled.QuestionMark, modifier = Modifier.matchParentSize(), contentDescription = null, tint = MaterialTheme.colorScheme.onSurface)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,18 @@ fun ShopCard(
items = {
DropdownMenuItem(
text = { Text(Res.string.edit) },
onClick = onEdit,
onClick = {
onEdit()
it.value = false
},
enabled = isOwner
)
DropdownMenuItem(
text = { Text(Res.string.delete) },
onClick = onDelete,
onClick = {
onDelete()
it.value = false
},
enabled = isOwner
)
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package io.github.jan.einkaufszettel.ui.screen.app.tabs.shops.components

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
Expand Down Expand Up @@ -40,36 +45,39 @@ fun UserProfileList(
modifier: Modifier = Modifier
) {
var showAddUserDialog by remember { mutableStateOf(false) }
LazyColumn(
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
stickyHeader {
UserProfileListHeader()
}
items(profiles) {
UserProfileListItem(
profile = it,
selected = selectedUsers.contains(it.id),
modifier = Modifier.fillMaxWidth().padding(8.dp),
onSelectChange = { selected ->
if (selected) {
selectedUsers.add(it.id)
} else {
selectedUsers.remove(it.id)
UserProfileListHeader()
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.weight(1f)
) {
items(profiles) {
UserProfileListItem(
profile = it,
selected = selectedUsers.contains(it.id),
modifier = Modifier.fillMaxWidth().padding(8.dp),
onSelectChange = { selected ->
if (selected) {
selectedUsers.add(it.id)
} else {
selectedUsers.remove(it.id)
}
}
}
)
)
}
}
item {
Button(
onClick = {
showAddUserDialog = true
}
) {
Text(Res.string.add_user)

Button(
onClick = {
showAddUserDialog = true
}
) {
Text(Res.string.add_user)
}
Spacer(Modifier.height(8.dp))
}

if (showAddUserDialog) {
Expand Down Expand Up @@ -145,5 +153,10 @@ private fun UserProfileListItem(

@Composable
private fun UserProfileListHeader() {
Text(Res.string.authorized_users, style = MaterialTheme.typography.headlineSmall)
Box(
modifier = Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.background).padding(8.dp),
contentAlignment = Alignment.Center
) {
Text(Res.string.authorized_users, style = MaterialTheme.typography.headlineSmall)
}
}
Loading

0 comments on commit de435c0

Please sign in to comment.