Skip to content

Commit

Permalink
color picker sheet start
Browse files Browse the repository at this point in the history
  • Loading branch information
T8RIN committed Aug 15, 2023
1 parent b74398f commit 2e8a452
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 14 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ dependencies {
implementation(project(":drawbox"))
implementation(project(":avif-coder-coil"))
implementation(project(":avif-coder"))
implementation(project(":screenshot"))

implementation("org.burnoutcrew.composereorderable:reorderable:0.9.6")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
Expand All @@ -25,21 +28,26 @@ import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material.icons.rounded.AddPhotoAlternate
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Build
import androidx.compose.material.icons.rounded.Colorize
import androidx.compose.material.icons.rounded.ContentPaste
import androidx.compose.material.icons.rounded.Draw
import androidx.compose.material.icons.rounded.Redo
import androidx.compose.material.icons.rounded.Save
import androidx.compose.material.icons.rounded.Undo
import androidx.compose.material.icons.rounded.ZoomIn
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomSheetScaffold
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
Expand All @@ -48,7 +56,9 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedIconButton
import androidx.compose.material3.SheetValue
import androidx.compose.material3.Switch
Expand All @@ -71,19 +81,26 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
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.RectangleShape
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
import androidx.compose.ui.zIndex
import com.smarttoolfactory.colordetector.ImageColorDetector
import com.t8rin.dynamic.theme.LocalDynamicThemeState
import com.t8rin.dynamic.theme.getAppColorTuple
import com.t8rin.dynamic.theme.observeAsState
import dev.olshevski.navigation.reimagined.hilt.hiltViewModel
import dev.olshevski.navigation.reimagined.navigate
import dev.olshevski.navigation.reimagined.pop
import kotlinx.coroutines.launch
import ru.tech.imageresizershrinker.R
import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawAlphaSelector
Expand All @@ -93,24 +110,32 @@ import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawColo
import ru.tech.imageresizershrinker.presentation.draw_screen.components.DrawHost
import ru.tech.imageresizershrinker.presentation.draw_screen.components.LineWidthSelector
import ru.tech.imageresizershrinker.presentation.draw_screen.viewModel.DrawViewModel
import ru.tech.imageresizershrinker.presentation.pick_color_from_image_screen.copyColorIntoClipboard
import ru.tech.imageresizershrinker.presentation.pick_color_from_image_screen.format
import ru.tech.imageresizershrinker.presentation.root.theme.icons.Eraser
import ru.tech.imageresizershrinker.presentation.root.theme.icons.PaletteSwatch
import ru.tech.imageresizershrinker.presentation.root.theme.mixedColor
import ru.tech.imageresizershrinker.presentation.root.theme.onMixedColor
import ru.tech.imageresizershrinker.presentation.root.theme.outlineVariant
import ru.tech.imageresizershrinker.presentation.root.transformation.filter.SaturationFilter
import ru.tech.imageresizershrinker.presentation.root.utils.confetti.LocalConfettiController
import ru.tech.imageresizershrinker.presentation.root.utils.helper.Picker
import ru.tech.imageresizershrinker.presentation.root.utils.helper.localImagePickerMode
import ru.tech.imageresizershrinker.presentation.root.utils.helper.parseSaveResult
import ru.tech.imageresizershrinker.presentation.root.utils.helper.rememberImagePicker
import ru.tech.imageresizershrinker.presentation.root.utils.modifier.block
import ru.tech.imageresizershrinker.presentation.root.utils.modifier.drawHorizontalStroke
import ru.tech.imageresizershrinker.presentation.root.utils.modifier.fabBorder
import ru.tech.imageresizershrinker.presentation.root.utils.navigation.Screen
import ru.tech.imageresizershrinker.presentation.root.widget.controls.ExtensionGroup
import ru.tech.imageresizershrinker.presentation.root.widget.dialogs.ExitWithoutSavingDialog
import ru.tech.imageresizershrinker.presentation.root.widget.other.LoadingDialog
import ru.tech.imageresizershrinker.presentation.root.widget.other.LocalToastHost
import ru.tech.imageresizershrinker.presentation.root.widget.other.LockScreenOrientation
import ru.tech.imageresizershrinker.presentation.root.widget.other.TopAppBarEmoji
import ru.tech.imageresizershrinker.presentation.root.widget.sheets.SimpleSheet
import ru.tech.imageresizershrinker.presentation.root.widget.text.Marquee
import ru.tech.imageresizershrinker.presentation.root.widget.text.TitleItem
import ru.tech.imageresizershrinker.presentation.root.widget.utils.LocalSettingsState
import ru.tech.imageresizershrinker.presentation.root.widget.utils.LocalWindowSizeClass

Expand Down Expand Up @@ -360,6 +385,8 @@ fun DrawScreen(
}
}

val showPickColorSheet = rememberSaveable { mutableStateOf(false) }

AnimatedContent(
targetState = portrait && viewModel.drawBehavior !is DrawBehavior.None,
transitionSpec = {
Expand Down Expand Up @@ -442,6 +469,11 @@ fun DrawScreen(
viewModel.drawController?.let { drawController ->
LazyColumn {
item {
IconButton(
onClick = { viewModel.openColorPicker() }
) {
Icon(Icons.Rounded.Colorize, null)
}
if (viewModel.drawBehavior is DrawBehavior.Background) {
DrawBackgroundSelector(drawController)
} else {
Expand Down Expand Up @@ -476,6 +508,128 @@ fun DrawScreen(
LoadingDialog()
}

LaunchedEffect(viewModel.colorPickerBitmap) {
showPickColorSheet.value = viewModel.colorPickerBitmap != null
}

SimpleSheet(
sheetContent = {
Box {
remember(viewModel.colorPickerBitmap) { viewModel.colorPickerBitmap?.asImageBitmap() }?.let {
ImageColorDetector(
color = viewModel.color,
imageBitmap = it,
onColorChange = viewModel::updateColor,
modifier = Modifier
.padding(16.dp)
.align(Alignment.Center)
.block(resultPadding = 8.dp)
.clip(RoundedCornerShape(12.dp))
)
}
HorizontalDivider(
Modifier
.zIndex(100f)
.align(Alignment.BottomCenter)
)
HorizontalDivider()
}
},
confirmButton = {
OutlinedButton(
onClick = {
showPickColorSheet.value = false
},
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary
),
border = BorderStroke(
settingsState.borderWidth,
MaterialTheme.colorScheme.outlineVariant(onTopOf = MaterialTheme.colorScheme.primary)
)
) {
Text(stringResource(R.string.close))
}
},
title = {
val color = viewModel.color
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(
start = 16.dp,
end = 16.dp
)
) {
Box(
Modifier
.padding(end = 16.dp)
.background(
color = animateColorAsState(color).value,
shape = RoundedCornerShape(12.dp)
)
.size(40.dp)
.border(
width = settingsState.borderWidth,
color = MaterialTheme.colorScheme.outlineVariant(
onTopOf = animateColorAsState(color).value
),
shape = RoundedCornerShape(11.dp)
)
.clip(RoundedCornerShape(12.dp))
.clickable {
context.copyColorIntoClipboard(
context.getString(R.string.color),
color.format()
)
scope.launch {
toastHostState.showToast(
icon = Icons.Rounded.ContentPaste,
message = context.getString(R.string.color_copied)
)
}
}
)

Text(stringResource(R.string.color))

Text(
modifier = Modifier
.padding(horizontal = 8.dp)
.clip(RoundedCornerShape(8.dp))
.clickable {
context.copyColorIntoClipboard(
context.getString(R.string.color),
color.format()
)
scope.launch {
toastHostState.showToast(
icon = Icons.Rounded.ContentPaste,
message = context.getString(R.string.color_copied)
)
}
}
.background(MaterialTheme.colorScheme.secondaryContainer)
.border(
settingsState.borderWidth,
MaterialTheme.colorScheme.outlineVariant(
onTopOf = MaterialTheme.colorScheme.secondaryContainer
),
RoundedCornerShape(8.dp)
)
.padding(horizontal = 6.dp),
text = color.format(),
style = LocalTextStyle.current.copy(
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
)
}
},
visible = showPickColorSheet
)

ExitWithoutSavingDialog(
onExit = {
if (viewModel.drawBehavior !is DrawBehavior.None) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ class DrawViewModel @Inject constructor(
private val imageManager: ImageManager<Bitmap, ExifInterface>
) : ViewModel() {

private val _color: MutableState<Color> = mutableStateOf(Color.Black)
val color by _color

private val _colorPickerBitmap: MutableState<Bitmap?> = mutableStateOf(null)
val colorPickerBitmap by _colorPickerBitmap

var drawController: DrawController? by mutableStateOf(null)
private set

Expand Down Expand Up @@ -211,6 +217,12 @@ class DrawViewModel @Inject constructor(
return@withContext null
}

fun openColorPicker() {
viewModelScope.launch {
_colorPickerBitmap.value = getBitmapForSharing()
}
}

fun resetDrawBehavior() {
drawController?.apply {
setDrawBackground(Color.Transparent)
Expand Down Expand Up @@ -281,4 +293,8 @@ class DrawViewModel @Inject constructor(
image: Bitmap,
overlay: Bitmap
): Bitmap = imageManager.overlayImage(image, overlay)

fun updateColor(color: Color) {
_color.value = color
}
}
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@
<string name="font_scale">Font scale</string>
<string name="defaultt">Default</string>
<string name="using_large_fonts_warn">Using large font scales may cause ui brokes which will not be fixed, use it if you want only</string>
<string name="alphabet_and_numbers">AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789!?</string>
<string name="alphabet_and_numbers">Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz 0123456789 !?</string>
<string-array name="fab_alignment_sub">
<item>Start</item>
<item>Center</item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ fun ScreenshotBox(
mutableStateOf<Rect?>(null)
}

Box(modifier = modifier
.onGloballyPositioned {
composableBounds = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
it.boundsInWindow()
} else {
it.boundsInRoot()
}
}
) {
content()
}

DisposableEffect(Unit) {

screenshotState.callback = {
Expand Down Expand Up @@ -56,16 +68,4 @@ fun ScreenshotBox(
screenshotState.callback = null
}
}

Box(modifier = modifier
.onGloballyPositioned {
composableBounds = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
it.boundsInWindow()
} else {
it.boundsInRoot()
}
}
) {
content()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class ScreenshotState internal constructor(

val bitmapState = mutableStateOf<Bitmap?>(null)

internal var callback: (() -> Unit)? = null
var callback: (() -> Unit)? = null

/**
* Captures current state of Composables inside [ScreenshotBox]
Expand Down

0 comments on commit 2e8a452

Please sign in to comment.