Add several ui polish for media-send.

This commit is contained in:
Alex Hart
2026-08-11 11:20:20 -03:00
parent b99d6f74db
commit a47b55a1aa
6 changed files with 38 additions and 7 deletions
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -28,6 +29,7 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.pointer.changedToDown
import androidx.compose.ui.input.pointer.pointerInput
@@ -53,6 +55,9 @@ internal fun ImageEditor(
val state = controller.imageEditorState
val hapticFeedback = LocalHapticFeedback.current
// Masks everything outside the image, so it has to match the surface the editor is drawn on to read as a background.
val blackoutColor = MaterialTheme.colorScheme.surface.toArgb()
DisposableEffect(state) {
state.attach()
onDispose { state.detach() }
@@ -76,6 +81,7 @@ internal fun ImageEditor(
val nativeCanvas = drawContext.canvas.nativeCanvas
val rendererContext = state.getOrCreateRendererContext(context, nativeCanvas)
rendererContext.setBlackoutColor(blackoutColor)
rendererContext.save()
try {
rendererContext.canvasMatrix.initial(state.viewMatrix)
@@ -78,13 +78,13 @@ private fun ImageEditorNoneStateToolbar(
) {
MediaEditorToolbar(modifier) {
MediaEditorToolbarButton(
imageVector = SignalIcons.BrushPen.imageVector,
onClick = imageEditorController::beginDrawEdit
imageVector = SignalIcons.CropRotate.imageVector,
onClick = imageEditorController::beginCropAndRotateEdit
)
MediaEditorToolbarButton(
imageVector = SignalIcons.CropRotate.imageVector,
onClick = imageEditorController::beginCropAndRotateEdit
imageVector = SignalIcons.BrushPen.imageVector,
onClick = imageEditorController::beginDrawEdit
)
MediaEditorToolbarSharedButtons(
@@ -2,6 +2,7 @@ package org.signal.imageeditor.core;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
@@ -9,8 +10,10 @@ import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Build;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import org.signal.imageeditor.core.model.EditorElement;
@@ -50,6 +53,10 @@ public final class RendererContext {
private boolean isEditing = true;
@ColorInt
@Nullable
private Integer blackoutColor;
private List<EditorElement> children = Collections.emptyList();
private Paint maskPaint;
@@ -98,6 +105,24 @@ public final class RendererContext {
return Math.max(0, Math.min(255, (int) (fade * alpha)));
}
/**
* Overrides the blackout color the model was created with for this render, so that a caller whose background can
* change after the model exists -- a theme switch, for example -- can keep the two in step. Pass null to fall back to
* the model's own color.
*/
public void setBlackoutColor(@ColorInt @Nullable Integer blackoutColor) {
this.blackoutColor = blackoutColor;
}
/**
* Resolves a color derived from the model's blackout color against any override set for this render, preserving the
* alpha the caller baked in.
*/
@ColorInt
public int resolveBlackoutColor(@ColorInt int modelColor) {
return blackoutColor == null ? modelColor : ColorUtils.setAlphaComponent(blackoutColor, Color.alpha(modelColor));
}
/**
* Persist the current state on to a stack, must be complimented by a call to {@link #restore()}.
*/
@@ -43,7 +43,7 @@ public final class CropAreaRenderer implements Renderer {
Resources resources = rendererContext.context.getResources();
canvas.clipPath(cropClipPath);
canvas.drawColor(color);
canvas.drawColor(rendererContext.resolveBlackoutColor(color));
rendererContext.mapRect(dst, Bounds.FULL_BOUNDS);
@@ -35,7 +35,7 @@ public final class FillRenderer implements Renderer {
path.addRoundRect(dst, DimensionUnit.DP.toPixels(18), DimensionUnit.DP.toPixels(18), Path.Direction.CW);
rendererContext.canvas.clipPath(path);
rendererContext.canvas.drawColor(color);
rendererContext.canvas.drawColor(rendererContext.resolveBlackoutColor(color));
rendererContext.canvas.restore();
}
@@ -35,7 +35,7 @@ public final class InverseFillRenderer implements Renderer {
path.addRoundRect(dst, DimensionUnit.DP.toPixels(18), DimensionUnit.DP.toPixels(18), Path.Direction.CW);
rendererContext.canvas.clipPath(path);
rendererContext.canvas.drawColor(color);
rendererContext.canvas.drawColor(rendererContext.resolveBlackoutColor(color));
rendererContext.canvas.restore();
}