From 78925dd61d67e5f8557411e646c05261ee0e1092 Mon Sep 17 00:00:00 2001 From: k1ngsterr1 Date: Sun, 12 Apr 2026 16:12:29 +0500 Subject: [PATCH] =?UTF-8?q?fix:=20magnifier=20=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=BE=D0=BE=D1=80?= =?UTF-8?q?=D0=B4=D0=B8=D0=BD=D0=B0=D1=82=D1=8B=20+=20haptic=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Magnifier: - Конвертация overlay-local → view-local координаты для Magnifier.show() - Builder: 240×64px, cornerRadius 12, elevation 4, offset -80 (над текстом) Haptic: - TEXT_HANDLE_MOVE при каждом изменении selectionStart/selectionEnd - Как в Telegram: вибрация при перемещении handle по словам Co-Authored-By: Claude Opus 4.6 (1M context) --- .../chats/components/TextSelectionHelper.kt | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) 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() {