Skip to content

Commit b07c17a

Browse files
Improve API for select image button
The picker launcher is not needed anymore
1 parent 7c2e2bb commit b07c17a

File tree

6 files changed

+55
-24
lines changed

6 files changed

+55
-24
lines changed

app/src/main/java/com/inky/fitnesscalendar/ui/components/imageComponents.kt

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.inky.fitnesscalendar.ui.components
22

33
import android.content.Context
44
import android.net.Uri
5-
import androidx.activity.compose.ManagedActivityResultLauncher
65
import androidx.activity.compose.rememberLauncherForActivityResult
76
import androidx.activity.result.PickVisualMediaRequest
87
import androidx.activity.result.contract.ActivityResultContracts
@@ -18,6 +17,9 @@ import androidx.compose.material3.Icon
1817
import androidx.compose.material3.MaterialTheme
1918
import androidx.compose.material3.Text
2019
import androidx.compose.runtime.Composable
20+
import androidx.compose.runtime.LaunchedEffect
21+
import androidx.compose.runtime.mutableStateListOf
22+
import androidx.compose.runtime.saveable.rememberSaveable
2123
import androidx.compose.ui.Modifier
2224
import androidx.compose.ui.draw.clip
2325
import androidx.compose.ui.layout.ContentScale
@@ -78,35 +80,65 @@ fun ActivityImage(
7880
)
7981
}
8082

83+
enum class ImageLimit {
84+
Single,
85+
Multiple
86+
}
87+
8188
/**
8289
* A menu button that displays an image picker.
83-
* @param imagePickerLauncher: The launcher to run when the item is clicked. This launcher should be initialized unconditionally with [rememberImagePickerLauncher]
90+
* @param imageLimit: Whether multiple images or just one image can be picked
91+
* @param onImages: Callback for when images have been picked
8492
* @param onDismissMenu: Callback for when the menu should get dismissed
8593
*/
8694
@Composable
8795
fun SelectImageDropdownMenuItem(
88-
imagePickerLauncher: ManagedActivityResultLauncher<PickVisualMediaRequest, *>,
96+
imageLimit: ImageLimit,
97+
onImages: (NonEmptyList<ImageName>) -> Unit,
8998
onDismissMenu: () -> Unit,
9099
) {
100+
val selectedImages = rememberSaveable { mutableStateListOf<ImageName>() }
101+
102+
LaunchedEffect(selectedImages.size) {
103+
selectedImages.asNonEmptyOrNull()?.let {
104+
onImages(it)
105+
onDismissMenu()
106+
}
107+
}
108+
109+
val launcher = when (imageLimit) {
110+
ImageLimit.Single -> rememberImagePickerLauncher(onName = {
111+
selectedImages.add(it)
112+
})
113+
114+
ImageLimit.Multiple -> rememberMultipleImagePickerLauncher(onImages = {
115+
selectedImages.addAll(it)
116+
})
117+
}
118+
119+
val itemLabel = when (imageLimit) {
120+
ImageLimit.Single -> R.string.add_image
121+
ImageLimit.Multiple -> R.string.add_images
122+
}
123+
91124
DropdownMenuItem(
92-
text = { Text(stringResource(R.string.add_image)) },
125+
text = { Text(stringResource(itemLabel)) },
93126
leadingIcon = {
94127
Icon(
95128
painterResource(R.drawable.outline_add_image_24),
96129
stringResource(R.string.add_image)
97130
)
98131
},
99132
onClick = {
100-
imagePickerLauncher.launch(
133+
launcher.launch(
101134
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
102135
)
103-
onDismissMenu()
104136
}
105137
)
106138
}
107139

108140
@Composable
109-
fun rememberMultipleImagePickerLauncher(
141+
private fun rememberMultipleImagePickerLauncher(
110142
onImages: (NonEmptyList<ImageName>) -> Unit,
111143
context: Context = LocalContext.current
112144
) = rememberLauncherForActivityResult(ActivityResultContracts.PickMultipleVisualMedia()) { uris ->
@@ -117,7 +149,7 @@ fun rememberMultipleImagePickerLauncher(
117149
}
118150

119151
@Composable
120-
fun rememberImagePickerLauncher(
152+
private fun rememberImagePickerLauncher(
121153
onName: (ImageName) -> Unit,
122154
context: Context = LocalContext.current
123155
) =

app/src/main/java/com/inky/fitnesscalendar/ui/views/EditActivityView.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ import com.inky.fitnesscalendar.ui.components.DateTimePicker
7373
import com.inky.fitnesscalendar.ui.components.DescriptionTextInput
7474
import com.inky.fitnesscalendar.ui.components.FavoriteIcon
7575
import com.inky.fitnesscalendar.ui.components.FeelSelector
76+
import com.inky.fitnesscalendar.ui.components.ImageLimit
7677
import com.inky.fitnesscalendar.ui.components.ImageViewer
7778
import com.inky.fitnesscalendar.ui.components.OkayCancelDialog
7879
import com.inky.fitnesscalendar.ui.components.OptionGroup
7980
import com.inky.fitnesscalendar.ui.components.SelectImageDropdownMenuItem
8081
import com.inky.fitnesscalendar.ui.components.defaultTopAppBarColors
8182
import com.inky.fitnesscalendar.ui.components.optionGroupDefaultBackground
82-
import com.inky.fitnesscalendar.ui.components.rememberMultipleImagePickerLauncher
8383
import com.inky.fitnesscalendar.ui.util.Icons
8484
import com.inky.fitnesscalendar.util.asNonEmptyOrNull
8585
import com.inky.fitnesscalendar.util.someOrNone
@@ -201,11 +201,6 @@ fun NewActivity(
201201
(!isKeyboardVisible || isTest) && (editState.activityId == null || editState != initialState) && editState.isValid
202202
}
203203
}
204-
val imagePickerLauncher = rememberMultipleImagePickerLauncher(onImages = { images ->
205-
onState(editState.copy(images = editState.images + images.map {
206-
ActivityEditState.ImageState(it)
207-
}))
208-
})
209204

210205
BackHandler(enabled = editState != initialState) {
211206
showBackDialog = true
@@ -263,7 +258,12 @@ fun NewActivity(
263258
onDismissRequest = { contextMenuOpen = false }
264259
) {
265260
SelectImageDropdownMenuItem(
266-
imagePickerLauncher = imagePickerLauncher,
261+
imageLimit = ImageLimit.Multiple,
262+
onImages = { images ->
263+
onState(editState.copy(images = editState.images + images.map {
264+
ActivityEditState.ImageState(it)
265+
}))
266+
},
267267
onDismissMenu = { contextMenuOpen = false },
268268
)
269269
}

app/src/main/java/com/inky/fitnesscalendar/ui/views/EditDayDialog.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ import com.inky.fitnesscalendar.ui.components.ActivityImage
2929
import com.inky.fitnesscalendar.ui.components.BaseEditDialog
3030
import com.inky.fitnesscalendar.ui.components.DescriptionTextInput
3131
import com.inky.fitnesscalendar.ui.components.FeelSelector
32+
import com.inky.fitnesscalendar.ui.components.ImageLimit
3233
import com.inky.fitnesscalendar.ui.components.ImageViewer
3334
import com.inky.fitnesscalendar.ui.components.OptionGroup
3435
import com.inky.fitnesscalendar.ui.components.SelectImageDropdownMenuItem
35-
import com.inky.fitnesscalendar.ui.components.rememberImagePickerLauncher
3636
import com.inky.fitnesscalendar.ui.util.Icons
3737
import com.inky.fitnesscalendar.view_model.BaseViewModel
3838
import kotlinx.parcelize.Parcelize
@@ -64,9 +64,6 @@ fun EditDayDialog(
6464
var editState by rememberSaveable(day) { mutableStateOf(EditDayState(day)) }
6565
var showImageViewer by rememberSaveable { mutableStateOf(false) }
6666

67-
val imagePickerLauncher =
68-
rememberImagePickerLauncher(onName = { editState = editState.copy(imageName = it) })
69-
7067
BaseEditDialog(
7168
title = stringResource(R.string.edit_day),
7269
onNavigateBack = onNavigateBack,
@@ -82,7 +79,8 @@ fun EditDayDialog(
8279

8380
DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) {
8481
SelectImageDropdownMenuItem(
85-
imagePickerLauncher = imagePickerLauncher,
82+
imageLimit = ImageLimit.Single,
83+
onImages = { images -> editState = editState.copy(imageName = images.first()) },
8684
onDismissMenu = { showMenu = false },
8785
)
8886
}

app/src/main/java/com/inky/fitnesscalendar/ui/views/settings/EditPlaceDialog.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ import com.inky.fitnesscalendar.ui.components.ActivityImage
3333
import com.inky.fitnesscalendar.ui.components.BaseEditDialog
3434
import com.inky.fitnesscalendar.ui.components.ColorSelector
3535
import com.inky.fitnesscalendar.ui.components.DescriptionTextInput
36+
import com.inky.fitnesscalendar.ui.components.ImageLimit
3637
import com.inky.fitnesscalendar.ui.components.ImageViewer
3738
import com.inky.fitnesscalendar.ui.components.OptionGroup
3839
import com.inky.fitnesscalendar.ui.components.SelectImageDropdownMenuItem
3940
import com.inky.fitnesscalendar.ui.components.optionGroupDefaultBackground
40-
import com.inky.fitnesscalendar.ui.components.rememberImagePickerLauncher
4141
import com.inky.fitnesscalendar.ui.util.Icons
4242
import com.inky.fitnesscalendar.view_model.PlaceListViewModel
4343
import kotlinx.coroutines.flow.flowOf
@@ -74,8 +74,6 @@ private fun EditPlaceDialog(initialPlace: Place?, onDismiss: () -> Unit, onSave:
7474

7575
var imageName by rememberSaveable(initialPlace) { mutableStateOf(initialPlace?.imageName) }
7676
var showImageViewer by rememberSaveable { mutableStateOf(false) }
77-
val imagePickerLauncher =
78-
rememberImagePickerLauncher(onName = { imageName = it })
7977

8078
var name by rememberSaveable(initialPlace) { mutableStateOf(initialPlace?.name ?: "") }
8179
var color by rememberSaveable(initialPlace) { mutableStateOf(initialPlace?.color) }
@@ -112,7 +110,8 @@ private fun EditPlaceDialog(initialPlace: Place?, onDismiss: () -> Unit, onSave:
112110

113111
DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) {
114112
SelectImageDropdownMenuItem(
115-
imagePickerLauncher = imagePickerLauncher,
113+
imageLimit = ImageLimit.Single,
114+
onImages = { imageName = it.first() },
116115
onDismissMenu = { showMenu = false },
117116
)
118117
}

app/src/main/res/values-de/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,5 @@
335335
<string name="light_mode">Helles Design</string>
336336
<string name="no_overlay">Keine Überlagerung</string>
337337
<string name="setting_default_statistic">Initiale Statistik</string>
338+
<string name="add_images">Bilder hinzufügen</string>
338339
</resources>

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,4 +336,5 @@
336336
<string name="light_mode">Light mode</string>
337337
<string name="no_overlay">No overlay</string>
338338
<string name="setting_default_statistic">Default statistic</string>
339+
<string name="add_images">Add images</string>
339340
</resources>

0 commit comments

Comments
 (0)