diff --git a/android/app/src/main/java/com/soniox/remotemic/MainActivity.kt b/android/app/src/main/java/com/soniox/remotemic/MainActivity.kt index 89adf57..b97ee0f 100644 --- a/android/app/src/main/java/com/soniox/remotemic/MainActivity.kt +++ b/android/app/src/main/java/com/soniox/remotemic/MainActivity.kt @@ -25,6 +25,8 @@ import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.lifecycle.lifecycleScope import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.button.MaterialButton @@ -73,6 +75,7 @@ class MainActivity : AppCompatActivity() { binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) + setupKeyboardInsetHandling() setupUI() checkPermissions() @@ -140,6 +143,29 @@ class MainActivity : AppCompatActivity() { ) } + /** + * Dynamically adjusts the layout when virtual keyboard opens or closes + */ + private fun setupKeyboardInsetHandling() { + ViewCompat.setOnApplyWindowInsetsListener(binding.rootLayout) { _, insets -> + val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) + + if (imeVisible) { + // Keyboard OPEN: Hide huge bottom circle, expand editor box to full height directly above keyboard + binding.bottomVoiceSection.visibility = View.GONE + binding.tvSubtitle.visibility = View.GONE + binding.btnMiniMic.visibility = View.VISIBLE + } else { + // Keyboard CLOSED: Restore spacious layout with large glowing mic button + binding.bottomVoiceSection.visibility = View.VISIBLE + binding.tvSubtitle.visibility = View.VISIBLE + binding.btnMiniMic.visibility = View.GONE + } + + insets + } + } + /** * Slices speech text right at the exact cursor/selection location */ @@ -245,30 +271,39 @@ class MainActivity : AppCompatActivity() { showLogsBottomSheet() } - // Touch listener for Hold to Speak (Captures cursor position on touch) + // Touch listener for Large Main Mic Button binding.btnMic.setOnTouchListener { _, event -> - when (event.action) { - MotionEvent.ACTION_DOWN -> { - if (checkAudioPermission()) { - val selStart = binding.etTranscript.selectionStart - val selEnd = binding.etTranscript.selectionEnd - val totalLen = binding.etTranscript.text?.length ?: 0 - - voiceInsertionCursorStart = if (selStart >= 0) selStart else totalLen - voiceInsertionCursorEnd = if (selEnd >= 0) selEnd else totalLen - - startRecording() - } - true + handleMicTouch(event) + } + + // Touch listener for Compact Mini Mic Button (above keyboard) + binding.btnMiniMic.setOnTouchListener { _, event -> + handleMicTouch(event) + } + } + + private fun handleMicTouch(event: MotionEvent): Boolean { + return when (event.action) { + MotionEvent.ACTION_DOWN -> { + if (checkAudioPermission()) { + val selStart = binding.etTranscript.selectionStart + val selEnd = binding.etTranscript.selectionEnd + val totalLen = binding.etTranscript.text?.length ?: 0 + + voiceInsertionCursorStart = if (selStart >= 0) selStart else totalLen + voiceInsertionCursorEnd = if (selEnd >= 0) selEnd else totalLen + + startRecording() } - MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { - if (isCurrentlyRecording) { - stopRecordingAndProcess() - } - true + true + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + if (isCurrentlyRecording) { + stopRecordingAndProcess() } - else -> false + true } + else -> false } } @@ -366,6 +401,7 @@ class MainActivity : AppCompatActivity() { binding.tvInstruction.text = getString(R.string.release_to_type) binding.tvInstruction.setTextColor(ContextCompat.getColor(this, R.color.accent_red)) binding.btnMic.setBackgroundResource(R.drawable.bg_mic_button_active) + binding.btnMiniMic.setBackgroundColor(ContextCompat.getColor(this, R.color.accent_red)) startPulseAnimation() streamDictationClient?.startRecording(voiceInsertionCursorStart) @@ -377,6 +413,7 @@ class MainActivity : AppCompatActivity() { stopPulseAnimation() binding.btnMic.setBackgroundResource(R.drawable.bg_mic_button) + binding.btnMiniMic.setBackgroundColor(ContextCompat.getColor(this, R.color.accent_blue)) binding.tvInstruction.text = "⏳ در حال درج و همگام‌سازی..." binding.tvInstruction.setTextColor(ContextCompat.getColor(this, R.color.accent_yellow)) diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index 7cf5955..1cec95f 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -2,10 +2,11 @@ + android:padding="12dp"> + android:textSize="11sp" /> @@ -61,7 +64,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="6dp" - android:text="متصل ✅" + android:text="متصل به مک ✅" android:textColor="@color/text_primary" android:textSize="11sp" android:textStyle="bold" /> @@ -70,8 +73,8 @@ @@ -104,7 +107,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="📝 متن گفتار و ویرایشگر مک" + android:text="📝 ویرایشگر همگام با مک" android:textColor="@color/text_secondary" android:textSize="12sp" android:textStyle="bold" /> @@ -134,11 +137,11 @@ android:id="@+id/etTranscript" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_marginTop="8dp" + android:layout_marginTop="6dp" android:layout_weight="1" android:background="@null" android:gravity="top|start" - android:hint="صحبت کنید یا متن خود را در اینجا بنویسید و ویرایش کنید..." + android:hint="متن مک در اینجا نمایش داده می‌شود؛ صحبت کنید یا بنویسید..." android:inputType="textMultiLine|textCapSentences" android:lineSpacingExtra="4dp" android:scrollbars="vertical" @@ -149,11 +152,12 @@ - + + + + - - + + - - - - + - - + + + + android:alpha="0.3" + android:background="@drawable/bg_mic_button" /> + + + + + + - - - + + +