From cdd2323c8812472a0435d5774bdfabb10cf75ac3 Mon Sep 17 00:00:00 2001 From: Songbum Bae Date: Tue, 12 May 2026 17:01:33 +0900 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=EB=AA=A8=EC=95=84=ED=82=A4=20?= =?UTF-8?q?=EB=AA=A8=EC=9D=8C=ED=82=A4=20=EC=9C=84=EB=A1=9C=20=EC=8A=A4?= =?UTF-8?q?=EC=99=80=EC=9D=B4=ED=94=84=20=EC=8B=9C=20=EC=9D=B4=EC=A4=91=20?= =?UTF-8?q?=EC=95=84=EB=9E=98=EC=95=84(=E1=86=A2)=20=EB=8C=80=EC=8B=A0=20?= =?UTF-8?q?=EB=8B=A8=EC=9D=BC=20=EC=95=84=EB=9E=98=EC=95=84(=E3=86=8D)=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OpenMoaView: moeumKey 위쪽 제스처(keyList[0]) 값을 ᆢ → ㆍ로 수정 - CrossKeyTouchListener: resolveKeyFromGesture 순수 함수 분리, require(size==4) 가드 추가 - CrossKeyTouchListenerTest: 방향별 구별 가능한 testKeyList 도입 및 경계값 테스트 추가 --- .../view/keyboardview/OpenMoaView.kt | 2 +- .../keytouchlistener/CrossKeyTouchListener.kt | 34 ++++++--- .../CrossKeyTouchListenerTest.kt | 73 +++++++++++++++++++ 3 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 app/src/test/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListenerTest.kt diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/view/keyboardview/OpenMoaView.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/view/keyboardview/OpenMoaView.kt index 3c5934f..14a1258 100644 --- a/app/src/main/kotlin/dev/bsb/moakeyvim/view/keyboardview/OpenMoaView.kt +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/view/keyboardview/OpenMoaView.kt @@ -330,7 +330,7 @@ class OpenMoaView : ConstraintLayout, KoinComponent { CrossKeyTouchListener( context, listOf( - StringKeyMessage("ᆢ"), + StringKeyMessage("ㆍ"), StringKeyMessage("ㅡ"), StringKeyMessage("ㆍ"), StringKeyMessage("ㅣ"), diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListener.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListener.kt index a56052f..c58eaa3 100644 --- a/app/src/main/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListener.kt +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListener.kt @@ -8,7 +8,27 @@ import dev.bsb.moakeyvim.view.message.StringKeyMessage import dev.bsb.moakeyvim.view.preview.KeyPreviewController import kotlin.math.* -// keyList 순서: [0]=위/왼, [1]=오른쪽, [2]=기본(탭), [3]=왼쪽/아래 +// keyList 순서: [0]=위, [1]=오른쪽, [2]=기본(탭/아래), [3]=왼쪽 +internal fun resolveKeyFromGesture( + startX: Float, + startY: Float, + currentX: Float, + currentY: Float, + gestureThreshold: Float, + keyList: List, +): StringKeyMessage { + require(keyList.size == 4) { "keyList must have exactly 4 entries: [up, right, center, left]" } + val distance = sqrt((currentX - startX).pow(2) + (currentY - startY).pow(2)) + if (distance <= gestureThreshold) return keyList[2] + val degree = ((atan2(currentY - startY, currentX - startX) * 180.0) / PI).toFloat() + // atan2 범위: (-180, 180]. abs >= 135도 = 왼쪽(keyList[3]) + return when { + abs(degree) < 45f -> keyList[1] + abs(degree) < 135f -> if (degree > 0) keyList[2] else keyList[0] + else -> keyList[3] + } +} + class CrossKeyTouchListener( context: Context, private val keyList: List, @@ -18,16 +38,8 @@ class CrossKeyTouchListener( private var startX: Float = 0f private var startY: Float = 0f - private fun resolveKey(currentX: Float, currentY: Float): StringKeyMessage { - val distance = sqrt((currentX - startX).pow(2) + (currentY - startY).pow(2)) - if (distance <= config.gestureThreshold) return keyList[2] - val degree = (atan2(currentY - startY, currentX - startX) * 180f) / PI - return when { - abs(degree) < 45f -> keyList[1] - abs(degree) < 135f -> if (degree > 0) keyList[2] else keyList[0] - else -> keyList[3] - } - } + private fun resolveKey(currentX: Float, currentY: Float): StringKeyMessage = + resolveKeyFromGesture(startX, startY, currentX, currentY, config.gestureThreshold, keyList) @SuppressLint("ClickableViewAccessibility") override fun onTouch(view: View, motionEvent: MotionEvent): Boolean { diff --git a/app/src/test/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListenerTest.kt b/app/src/test/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListenerTest.kt new file mode 100644 index 0000000..0b3f7e9 --- /dev/null +++ b/app/src/test/kotlin/dev/bsb/moakeyvim/view/keytouchlistener/CrossKeyTouchListenerTest.kt @@ -0,0 +1,73 @@ +package dev.bsb.moakeyvim.view.keytouchlistener + +import dev.bsb.moakeyvim.view.message.StringKeyMessage +import org.junit.Assert.assertEquals +import org.junit.Test + +class CrossKeyTouchListenerTest { + + private val threshold = 50f + + private fun testKeyList() = listOf( + StringKeyMessage("UP"), + StringKeyMessage("RIGHT"), + StringKeyMessage("CENTER"), + StringKeyMessage("LEFT"), + ) + + private fun moeumKeyList() = listOf( + StringKeyMessage("ㆍ"), + StringKeyMessage("ㅡ"), + StringKeyMessage("ㆍ"), + StringKeyMessage("ㅣ"), + ) + + @Test + fun `임계값 이하 이동은 CENTER키 반환`() { + val result = resolveKeyFromGesture(0f, 0f, 10f, 10f, threshold, testKeyList()) + assertEquals("CENTER", result.key) + } + + @Test + fun `위로 스와이프하면 keyList-0 반환`() { + val result = resolveKeyFromGesture(0f, 100f, 0f, 0f, threshold, testKeyList()) + assertEquals("UP", result.key) + } + + @Test + fun `오른쪽으로 스와이프하면 keyList-1 반환`() { + val result = resolveKeyFromGesture(0f, 0f, 100f, 0f, threshold, testKeyList()) + assertEquals("RIGHT", result.key) + } + + @Test + fun `아래로 스와이프하면 keyList-2 반환`() { + val result = resolveKeyFromGesture(0f, 0f, 0f, 100f, threshold, testKeyList()) + assertEquals("CENTER", result.key) + } + + @Test + fun `왼쪽으로 스와이프하면 keyList-3 반환`() { + val result = resolveKeyFromGesture(100f, 0f, 0f, 0f, threshold, testKeyList()) + assertEquals("LEFT", result.key) + } + + @Test + fun `임계값 경계값 - threshold 초과 시 방향 감지`() { + val justOver = resolveKeyFromGesture(0f, 100f, 0f, 49f, threshold, testKeyList()) + assertEquals("UP", justOver.key) + } + + @Test + fun `임계값 경계값 - threshold 이하 시 CENTER 반환`() { + val justUnder = resolveKeyFromGesture(0f, 0f, 0f, 50f, threshold, testKeyList()) + assertEquals("CENTER", justUnder.key) + } + + @Test + fun `모아키 모음키 위로 스와이프는 아래아 단일 반환 - 이중 아래아 아님`() { + val result = resolveKeyFromGesture(0f, 100f, 0f, 0f, threshold, moeumKeyList()) + assertEquals("ㆍ", result.key) + assert(result.key != "ᆢ") { "위로 스와이프에 아래아 이중(ᆢ)이 반환되면 안 됨" } + } +} From 3223c768de0d16911ac199f45ab17cb607f65472 Mon Sep 17 00:00:00 2001 From: Songbum Bae Date: Tue, 12 May 2026 17:05:24 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=EC=B6=94=EC=B2=9C=EB=8B=A8=EC=96=B4?= =?UTF-8?q?=20=EB=B0=94=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EC=83=89=EC=83=81?= =?UTF-8?q?=EC=9D=84=20=ED=85=8C=EB=A7=88=20=EA=B8=B0=EB=B0=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dimTextColor() 추가: HSV 명도를 88%로 낮춰 키 텍스트보다 약간 어둡게 표시 - setSuggestions/showSelectionActions에서 색상을 한 번만 계산해 각 뷰에 전달 (이전: buildWordView/buildActionView 호출마다 SharedPreferences 재조회) - applyColors() 루프에서 기존 TextView 업데이트 시 dimmed currentTextColor 사용 - applyColors() 자체도 currentTextColor에 dimTextColor 적용값 저장하도록 수정 --- .../view/suggestion/SuggestionBarView.kt | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt index bba46dc..3102756 100644 --- a/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt @@ -122,7 +122,11 @@ class SuggestionBarView @JvmOverloads constructor( val showFunctionKeys = words.isEmpty() leftActions.visibility = if (showFunctionKeys) VISIBLE else GONE rightActions.visibility = if (showFunctionKeys) VISIBLE else GONE - words.forEach { word -> container.addView(buildWordView(word, word in hotstringExpansions)) } + if (words.isNotEmpty()) { + val skin = SettingsPreferences.getKeyboardSkin(context) + val wordColor = dimTextColor(SkinApplier.fgColor(context, skin)) + words.forEach { word -> container.addView(buildWordView(word, word in hotstringExpansions, wordColor)) } + } } fun showClipboard(text: String, onPaste: (String) -> Unit) { @@ -171,12 +175,14 @@ class SuggestionBarView @JvmOverloads constructor( scrollView.scrollTo(0, 0) leftActions.visibility = VISIBLE rightActions.visibility = VISIBLE - container.addView(buildActionView(context.getString(R.string.key_cut), onCut)) - container.addView(buildActionView(context.getString(R.string.key_copy), onCopy)) + val skin = SettingsPreferences.getKeyboardSkin(context) + val actionColor = dimTextColor(SkinApplier.fgColor(context, skin)) + container.addView(buildActionView(context.getString(R.string.key_cut), onCut, actionColor)) + container.addView(buildActionView(context.getString(R.string.key_copy), onCopy, actionColor)) } fun applyColors(textColor: Int, bgColor: Int, keyBgColor: Int = Color.WHITE) { - currentTextColor = textColor + currentTextColor = dimTextColor(textColor) currentBgColor = bgColor currentKeyBgColor = keyBgColor setBackgroundColor(bgColor) @@ -193,17 +199,17 @@ class SuggestionBarView @JvmOverloads constructor( (child.getChildAt(1) as? TextView)?.setTextColor(textColor) child.background = buildChipBackground() } - child is TextView -> child.setTextColor(textColor) + child is TextView -> child.setTextColor(currentTextColor) child is ImageButton -> child.imageTintList = tintList } } } - private fun buildWordView(word: String, isHotstring: Boolean): TextView { + private fun buildWordView(word: String, isHotstring: Boolean, wordColor: Int): TextView { return TextView(context).apply { text = word textSize = TEXT_SIZE_SP - setTextColor(currentTextColor) + setTextColor(wordColor) setPadding(hPad, vPad, hPad, vPad) gravity = Gravity.CENTER isClickable = true @@ -271,11 +277,11 @@ class SuggestionBarView @JvmOverloads constructor( return buildIconButton(R.drawable.ic_content_paste) { onOpenClipboardPanel?.invoke() } } - private fun buildActionView(label: String, action: () -> Unit): TextView { + private fun buildActionView(label: String, action: () -> Unit, actionColor: Int): TextView { return TextView(context).apply { text = label textSize = TEXT_SIZE_SP - setTextColor(currentTextColor) + setTextColor(actionColor) setPadding(hPad, vPad, hPad, vPad) gravity = Gravity.CENTER isClickable = true @@ -336,6 +342,13 @@ class SuggestionBarView @JvmOverloads constructor( } } + private fun dimTextColor(color: Int): Int { + val hsv = FloatArray(3) + Color.colorToHSV(color, hsv) + hsv[2] *= 0.88f + return Color.HSVToColor(hsv) + } + private fun buildRipple(): RippleDrawable { return RippleDrawable(ColorStateList.valueOf(0x22000000), null, ColorDrawable(Color.WHITE)) } From d2f880d29cd8c2258165e5ba6695903f0c65ad1f Mon Sep 17 00:00:00 2001 From: Songbum Bae Date: Tue, 12 May 2026 17:32:53 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EA=B0=80=EB=A1=9C=20=EB=AA=A8?= =?UTF-8?q?=EB=93=9C=EC=97=90=EC=84=9C=20=EB=91=90=EB=B2=8C=EC=8B=9D=20?= =?UTF-8?q?=EB=8B=A8=EB=AA=A8=EC=9D=8C=20=EC=9E=85=EB=A0=A5=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EC=84=A0=ED=83=9D=20=EC=A7=80=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LandscapeKoLayout enum 신설 (NONE/QWERTY/QWERTY_SIMPLE) - 기존 boolean landscape_qwerty 설정을 enum으로 마이그레이션 - resolveKoLayout()에서 단모음 여부 전달하도록 수정 - 설정 화면: SwitchPreference → ListPreference (3-옵션) - 설정 타이틀: '가로 모드 입력 방식', NONE 라벨: '세로와 동일(기본)' - '쿼티' 표현 제거 --- .../kotlin/dev/bsb/moakeyvim/OpenMoaIME.kt | 5 +++-- .../bsb/moakeyvim/config/LandscapeKoLayout.kt | 17 +++++++++++++++++ .../moakeyvim/settings/SettingsFragment.kt | 4 +++- .../moakeyvim/settings/SettingsPreferences.kt | 19 +++++++++++++++++-- app/src/main/res/values/strings.xml | 3 ++- app/src/main/res/xml/preferences_main.xml | 10 +++++----- 6 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 app/src/main/kotlin/dev/bsb/moakeyvim/config/LandscapeKoLayout.kt diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/OpenMoaIME.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/OpenMoaIME.kt index e4d8417..71fed28 100644 --- a/app/src/main/kotlin/dev/bsb/moakeyvim/OpenMoaIME.kt +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/OpenMoaIME.kt @@ -1135,8 +1135,9 @@ class OpenMoaIME : InputMethodService(), KoinComponent { return KoLayout(useQwerty = true, simpleQwerty = savedMode.isSimpleQwerty) } val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - if (isLandscape && SettingsPreferences.getLandscapeQwerty(this)) { - return KoLayout(useQwerty = true, simpleQwerty = false) + val landscapeLayout = SettingsPreferences.getLandscapeKoLayout(this) + if (isLandscape && landscapeLayout.isQwerty) { + return KoLayout(useQwerty = true, simpleQwerty = landscapeLayout.isSimple) } return KoLayout(useQwerty = false, simpleQwerty = false) } diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/config/LandscapeKoLayout.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/config/LandscapeKoLayout.kt new file mode 100644 index 0000000..cc04a21 --- /dev/null +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/config/LandscapeKoLayout.kt @@ -0,0 +1,17 @@ +package dev.bsb.moakeyvim.config + +import dev.bsb.moakeyvim.R + +enum class LandscapeKoLayout(val labelResId: Int) { + NONE(R.string.settings_landscape_ko_layout_none), + QWERTY(R.string.settings_input_mode_qwerty), + QWERTY_SIMPLE(R.string.settings_input_mode_qwerty_simple); + + val isQwerty: Boolean get() = this != NONE + val isSimple: Boolean get() = this == QWERTY_SIMPLE + + companion object { + fun fromString(value: String?): LandscapeKoLayout = + values().find { it.name == value } ?: NONE + } +} diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsFragment.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsFragment.kt index 2505ea4..6850d37 100644 --- a/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsFragment.kt +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsFragment.kt @@ -28,6 +28,7 @@ import dev.bsb.moakeyvim.hotstring.HotstringRule import dev.bsb.moakeyvim.hotstring.HotstringRepository import dev.bsb.moakeyvim.config.EnterLongPressAction import dev.bsb.moakeyvim.config.HangulInputMode +import dev.bsb.moakeyvim.config.LandscapeKoLayout import dev.bsb.moakeyvim.config.HapticStrength import dev.bsb.moakeyvim.config.KeyboardSkin import dev.bsb.moakeyvim.config.KeypadHeight @@ -62,7 +63,6 @@ class SettingsFragment : PreferenceFragmentCompat() { SettingsPreferences.KEY_WORD_SUGGESTION_ENABLED, SettingsPreferences.KEY_KOREAN_WORD_SUGGESTION_ENABLED, SettingsPreferences.KEY_CLIPBOARD_ENABLED, - SettingsPreferences.KEY_LANDSCAPE_QWERTY, SettingsPreferences.KEY_FLOATING_INDICATOR_ENABLED, SettingsPreferences.KEY_OVERLAY_PERMISSION_NOTIFIED, SettingsPreferences.KEY_HW_CAPSLOCK_TO_CTRL, @@ -124,6 +124,8 @@ class SettingsFragment : PreferenceFragmentCompat() { setupClipboardListPreferences() pref(SettingsPreferences.KEY_HANGUL_INPUT_MODE) ?.setupEnum(HangulInputMode.values(), { it.labelResId }, HangulInputMode.TWO_HAND_MOAKEY) + pref(SettingsPreferences.KEY_LANDSCAPE_KO_LAYOUT) + ?.setupEnum(LandscapeKoLayout.values(), { it.labelResId }, LandscapeKoLayout.NONE) pref(SettingsPreferences.KEY_KEYBOARD_SKIN) ?.setupEnum(KeyboardSkin.values(), { it.labelResId }, KeyboardSkin.WHITE) pref(SettingsPreferences.KEY_KEYPAD_HEIGHT) diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsPreferences.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsPreferences.kt index cd21812..9f9b148 100644 --- a/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsPreferences.kt +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/settings/SettingsPreferences.kt @@ -5,6 +5,7 @@ import dev.bsb.moakeyvim.config.EnterLongPressAction import dev.bsb.moakeyvim.config.GestureAnglePreset import dev.bsb.moakeyvim.config.GestureAngles import dev.bsb.moakeyvim.config.HangulInputMode +import dev.bsb.moakeyvim.config.LandscapeKoLayout import dev.bsb.moakeyvim.config.HapticStrength import dev.bsb.moakeyvim.config.KeyboardSkin import dev.bsb.moakeyvim.config.SoundType @@ -45,6 +46,7 @@ object SettingsPreferences { const val KEY_CLIPBOARD_EXPIRY_MINUTES = "clipboard_expiry_minutes" const val KEY_MIN_LEARN_COUNT = "min_learn_count" const val KEY_LANDSCAPE_QWERTY = "landscape_qwerty" + const val KEY_LANDSCAPE_KO_LAYOUT = "landscape_ko_layout" const val KEY_FLOATING_INDICATOR_ENABLED = "floating_indicator_enabled" const val KEY_FLOATING_INDICATOR_X = "floating_indicator_x" const val KEY_FLOATING_INDICATOR_Y = "floating_indicator_y" @@ -79,6 +81,7 @@ object SettingsPreferences { KEY_CLIPBOARD_EXPIRY_MINUTES, KEY_MIN_LEARN_COUNT, KEY_LANDSCAPE_QWERTY, + KEY_LANDSCAPE_KO_LAYOUT, KEY_FLOATING_INDICATOR_ENABLED, KEY_FLOATING_INDICATOR_X, KEY_FLOATING_INDICATOR_Y, @@ -197,9 +200,21 @@ object SettingsPreferences { prefs(context).edit().putBoolean(KEY_CLIPBOARD_ENABLED, enabled).apply() } - fun getLandscapeQwerty(context: Context): Boolean = - prefs(context).getBoolean(KEY_LANDSCAPE_QWERTY, false) + fun getLandscapeKoLayout(context: Context): LandscapeKoLayout { + val p = prefs(context) + val saved = p.getString(KEY_LANDSCAPE_KO_LAYOUT, null) + if (saved != null) return LandscapeKoLayout.fromString(saved) + // 기존 boolean 설정 마이그레이션 + return if (p.getBoolean(KEY_LANDSCAPE_QWERTY, false)) { + LandscapeKoLayout.QWERTY + } else { + LandscapeKoLayout.NONE + } + } + + fun getLandscapeQwerty(context: Context): Boolean = getLandscapeKoLayout(context).isQwerty + @Deprecated("Use getLandscapeKoLayout() instead", ReplaceWith("getLandscapeKoLayout(context)")) fun setLandscapeQwerty(context: Context, enabled: Boolean) { prefs(context).edit().putBoolean(KEY_LANDSCAPE_QWERTY, enabled).apply() } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 16522eb..7aa36ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -113,7 +113,8 @@ 두벌식 두벌식 단모음 가로 모드 두벌식 - 가로 모드일 때 한글 자판을 쿼티로 표시합니다 + 가로 모드 입력 방식 + 세로와 동일(기본) 키보드 외형 키패드 높이 조절 diff --git a/app/src/main/res/xml/preferences_main.xml b/app/src/main/res/xml/preferences_main.xml index 96b556f..4a620d0 100644 --- a/app/src/main/res/xml/preferences_main.xml +++ b/app/src/main/res/xml/preferences_main.xml @@ -11,11 +11,11 @@ android:negativeButtonText="@string/dialog_close" app:icon="@drawable/ic_pref_keyboard" /> - Date: Tue, 12 May 2026 18:39:13 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=EC=B6=94=EC=B2=9C=EB=8B=A8=EC=96=B4?= =?UTF-8?q?=20=EB=B0=94=EC=97=90=EC=84=9C=20=EC=9E=90=EB=8F=99=EC=B9=98?= =?UTF-8?q?=ED=99=98=20=EB=8B=A8=EC=96=B4=EC=9D=98=20trailing=20space?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EB=A7=88=EC=A7=84=20=EB=B6=88?= =?UTF-8?q?=EA=B7=A0=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit buildWordView에서 word.trim()으로 표시해 자동치환 expansion의 trailing space가 시각적 간격 차이로 보이던 문제 해결. 입력 콜백엔 원본 word(trailing space 포함)를 유지해 자동치환 동작 보존. --- app/build.gradle | 2 +- .../dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 773ce60..3cd5340 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,7 +12,7 @@ android { minSdk = 30 targetSdk = 35 versionCode = 1 - versionName = "1.0" + versionName = "1.0.12" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt b/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt index 3102756..d73f2b3 100644 --- a/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt +++ b/app/src/main/kotlin/dev/bsb/moakeyvim/view/suggestion/SuggestionBarView.kt @@ -207,7 +207,7 @@ class SuggestionBarView @JvmOverloads constructor( private fun buildWordView(word: String, isHotstring: Boolean, wordColor: Int): TextView { return TextView(context).apply { - text = word + text = word.trim() textSize = TEXT_SIZE_SP setTextColor(wordColor) setPadding(hPad, vPad, hPad, vPad)