diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/components/TextSelectionHelper.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/components/TextSelectionHelper.kt index 5ab7aa9..513faf4 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/components/TextSelectionHelper.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/components/TextSelectionHelper.kt @@ -127,7 +127,9 @@ class TextSelectionHelper { var newStart = charOffset.coerceIn(0, text.length) while (newStart > 0 && Character.isLetterOrDigit(text[newStart - 1])) newStart-- if (newStart >= selectionEnd) return + val changed = newStart != selectionStart selectionStart = newStart + if (changed) hapticOnSelectionChange() } fun updateSelectionEnd(charOffset: Int) { @@ -136,7 +138,16 @@ class TextSelectionHelper { var newEnd = charOffset.coerceIn(0, text.length) while (newEnd < text.length && Character.isLetterOrDigit(text[newEnd])) newEnd++ if (newEnd <= selectionStart) return + val changed = newEnd != selectionEnd selectionEnd = newEnd + if (changed) hapticOnSelectionChange() + } + + private fun hapticOnSelectionChange() { + magnifierView?.performHapticFeedback( + HapticFeedbackConstants.TEXT_HANDLE_MOVE, + HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING + ) } fun beginHandleDrag(isStart: Boolean, touchX: Float, touchY: Float) { @@ -180,24 +191,30 @@ class TextSelectionHelper { magnifierView = view } - fun showMagnifier(x: Float, y: Float) { + fun showMagnifier(overlayLocalX: Float, overlayLocalY: Float) { if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.P) return val view = magnifierView ?: return if (!movingHandle) return if (magnifier == null) { magnifier = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { android.widget.Magnifier.Builder(view) - .setSize(200, 80) - .setCornerRadius(16f) + .setSize(240, 64) + .setCornerRadius(12f) + .setElevation(4f) + .setDefaultSourceToMagnifierOffset(0, -80) .build() } else { + @Suppress("DEPRECATION") android.widget.Magnifier(view) } } val info = layoutInfo ?: return - val localX = (x - info.windowX).coerceIn(0f, view.width.toFloat()) - val localY = (y - info.windowY).coerceIn(0f, view.height.toFloat()) - magnifier?.show(localX, localY) + // Convert overlay-local → view-local (magnifierView coords) + val viewLoc = IntArray(2) + view.getLocationInWindow(viewLoc) + val sourceX = (overlayLocalX + overlayWindowX - viewLoc[0]).coerceIn(0f, view.width.toFloat()) + val sourceY = (overlayLocalY + overlayWindowY - viewLoc[1]).coerceIn(0f, view.height.toFloat()) + magnifier?.show(sourceX, sourceY) } fun hideMagnifier() {