Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AnkiDroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ android {
namespace = "com.ichi2.anki"

compileSdk = libs.versions.compileSdk.get().toInteger()
compileSdkMinor = libs.versions.compileSdkMinor.get().toInteger()

buildFeatures {
buildConfig = true
Expand Down
6 changes: 2 additions & 4 deletions AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@

package com.ichi2.anki.dialogs

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
Expand All @@ -31,6 +29,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.google.android.material.textfield.TextInputEditText
import com.ichi2.anki.Flag
import com.ichi2.anki.compat.showSoftInput
import com.ichi2.anki.databinding.ItemEditFlagBinding
import com.ichi2.utils.moveCursorToEnd
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -86,8 +85,7 @@ class FlagAdapter(
holder.flagNameEditLayout.visibility = View.VISIBLE
holder.flagNameEdit.requestFocus()
holder.flagNameEdit.moveCursorToEnd()
val inputMethodManager = holder.flagNameEdit.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(holder.flagNameEdit, InputMethodManager.SHOW_IMPLICIT)
holder.flagNameEdit.showSoftInput()
}

holder.saveButton.setOnClickListener {
Expand Down
7 changes: 3 additions & 4 deletions AnkiDroid/src/main/java/com/ichi2/utils/AndroidUiUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.view.View
import android.view.Window
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import com.ichi2.anki.compat.showSoftInput

object AndroidUiUtils {
/**
Expand All @@ -31,8 +32,7 @@ object AndroidUiUtils {
*/
fun Activity?.showSoftInput() {
val currentFocus = this?.currentFocus ?: return
val imm = this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(currentFocus, InputMethodManager.SHOW_IMPLICIT)
currentFocus.showSoftInput()
}

/**
Expand Down Expand Up @@ -61,8 +61,7 @@ object AndroidUiUtils {
// Required on some Android 9, 10 devices to show keyboard: https://stackoverflow.com/a/7784904
view.postDelayed({
view.requestFocus()
val imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
view.showSoftInput()
runnable?.run()
}, 200)
}
Expand Down
2 changes: 2 additions & 0 deletions api/src/test/java/com/ichi2/anki/api/ApiUtilsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package com.ichi2.anki.api
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import kotlin.test.assertEquals
import kotlin.test.assertNull

Expand All @@ -19,6 +20,7 @@ import kotlin.test.assertNull
* Slack: bresan
*/
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [35])
internal class ApiUtilsTest {
@Test
fun joinFieldsShouldJoinWhenListIsValid() {
Expand Down
4 changes: 4 additions & 0 deletions baselineprofile/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ configure<TestExtension> {
libs.versions.compileSdk
.get()
.toInt()
compileSdkMinor =
libs.versions.compileSdkMinor
.get()
.toInt()

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/ankidroid.android.api.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ plugins {

extensions.configure<LibraryExtension> {
compileSdk = libsVersionFor("compileSdk").toInt()
compileSdkMinor = libsVersionFor("compileSdkMinor").toInt()

compileOptions {
// API remains on VERSION_11 for consumer compatibility.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ plugins {

extensions.configure<LibraryExtension> {
compileSdk = libsVersionFor("compileSdk").toInt()
compileSdkMinor = libsVersionFor("compileSdkMinor").toInt()

defaultConfig {
minSdk = libsVersionFor("minSdk").toInt()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import android.graphics.Color
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
import kotlin.test.assertEquals

/** Tests for [darkenColor] and [lightenColorAbsolute] */
@RunWith(AndroidJUnit4::class)
@Config(sdk = [35])
class ColorUtilsTest {
@Test
fun darkenColor_withNoChange_returnsSameColor() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import android.view.KeyEvent.KEYCODE_STAR
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
import kotlin.test.assertEquals
import kotlin.test.assertNull

/** Tests for [KeyEvent.digit]. */
@RunWith(AndroidJUnit4::class)
@Config(sdk = [35])
class KeyUtilsTest {
@Test
fun `digit returns the digit for 0-9 keys`() {
Expand Down
7 changes: 7 additions & 0 deletions compat/src/main/java/com/ichi2/anki/compat/BaseCompat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import android.provider.MediaStore
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import androidx.annotation.AnimRes
import androidx.appcompat.widget.TooltipCompat
import com.ichi2.anki.common.utils.annotation.KotlinCleanup
Expand Down Expand Up @@ -54,6 +55,12 @@ open class BaseCompat : Compat {
)
}

// Until API36, SHOW_IMPLICIT marks the request as one the system may ignore
override fun showSoftInput(view: View): Boolean {
val imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
return imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
}

override fun overrideTransition(
activity: Activity,
@AnimRes enter: Int,
Expand Down
17 changes: 17 additions & 0 deletions compat/src/main/java/com/ichi2/anki/compat/Compat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,23 @@ interface Compat {

fun hideStatusBar(window: Window)

/**
* Request that the current input method's soft input area be shown to the
* user, if needed.
*
* Below Android 16, this is an implicit request: the window may not be
* shown, for example if a hardware keyboard is connected.
*
* @param view The currently focused view, which would like to receive soft keyboard input.
* Note that this view is only considered focused here if both it itself has
* [view focus][View.isFocused], and its containing window has
* [window focus][View.hasWindowFocus]. Otherwise the call fails and returns `false`.
* @return `true` if a request was sent to system_server, `false` otherwise. Note:
* this does not return result of the request.
* @see android.view.inputmethod.InputMethodManager.showSoftInput
*/
fun showSoftInput(view: View): Boolean

fun overrideTransition(
activity: Activity,
@AnimRes enter: Int,
Expand Down
8 changes: 8 additions & 0 deletions compat/src/main/java/com/ichi2/anki/compat/CompatHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class CompatHelper private constructor() {
@SuppressLint("NewApi")
private val compatValue: Compat =
when {
sdkVersion >= Build.VERSION_CODES.BAKLAVA -> CompatV36()
sdkVersion >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> CompatV34()
sdkVersion >= Build.VERSION_CODES.TIRAMISU -> CompatV33()
sdkVersion >= Build.VERSION_CODES.S -> CompatV31()
Expand Down Expand Up @@ -209,6 +210,13 @@ class CompatHelper private constructor() {
*/
fun View.setTooltipTextCompat(tooltipText: CharSequence?) = TooltipCompat.setTooltipText(this, tooltipText)

/**
* Request that the current input method's soft input area be shown to the user, if needed.
*
* @see Compat.showSoftInput
*/
fun View.showSoftInput(): Boolean = compat.showSoftInput(this)

inline fun <reified T : Serializable> Bundle.requireSerializableCompat(key: String): T =
requireNotNull(compat.getSerializable(this, key, T::class.java)) {
"key: '$key' not found or null"
Expand Down
6 changes: 3 additions & 3 deletions compat/src/main/java/com/ichi2/anki/compat/CompatV30.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ package com.ichi2.anki.compat

import android.view.Window
import androidx.annotation.RequiresApi
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat.Type.statusBars

@RequiresApi(30)
@Suppress("ktlint:standard:property-naming")
Expand All @@ -21,7 +22,6 @@ open class CompatV30 : CompatV29() {
if (view == null) {
return
}
val controller = view.windowInsetsController
controller?.hide(WindowInsetsCompat.Type.statusBars())
WindowCompat.getInsetsController(window, view).hide(statusBars())
}
}
17 changes: 17 additions & 0 deletions compat/src/main/java/com/ichi2/anki/compat/CompatV36.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: GPL-3.0-or-later

package com.ichi2.anki.compat

import android.content.Context
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.annotation.RequiresApi

@RequiresApi(36)
open class CompatV36 : CompatV34() {
// From API36, SHOW_IMPLICIT is a no-op (and deprecated in API37)
override fun showSoftInput(view: View): Boolean {
val imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
return imm.showSoftInput(view, 0)
}
}
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[versions]
compileSdk = "36"
compileSdk = "37"
compileSdkMinor = "0"

# Changing minSdk means newer AnkiDroid versions will not support older devices.
# However the Play Store will keep old AnkiDroid versions available for older
Expand Down
Loading