diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml new file mode 100644 index 0000000..405a2b3 --- /dev/null +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -0,0 +1,10 @@ +name: "Validate Gradle Wrapper" +on: [push, pull_request] + +jobs: + validation: + name: "Validation" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: gradle/wrapper-validation-action@v1 diff --git a/README.md b/README.md index 0f756fe..1620cc5 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,10 @@ Redirect outgoing calls to Signal/Telegram/Threema. -[comment]: <> ([ ( src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png") - -[comment]: <> ( alt="Get it on F-Droid") - -[comment]: <> ( height="80">](https://f-droid.org/packages/me.lucky.red/)) +[Get it on F-Droid](https://f-droid.org/packages/me.lucky.red/) [Get it on Google Play R.string.destination_signal - TELEGRAM_MIMETYPE -> R.string.destination_telegram - THREEMA_MIMETYPE -> R.string.destination_threema - WHATSAPP_MIMETYPE -> R.string.fallback_destination_whatsapp - else -> return - }) + window.show(record.uri, MIMETYPE_TO_DST_NAME[record.mimetype] ?: return) } @RequiresPermission(Manifest.permission.READ_CONTACTS) @@ -83,7 +84,7 @@ class CallRedirectionService : CallRedirectionService() { val cursor = contentResolver.query( Uri.withAppendedPath( ContactsContract.PhoneLookup.CONTENT_FILTER_URI, - Uri.encode(phoneNumber) + Uri.encode(phoneNumber), ), arrayOf(ContactsContract.PhoneLookup._ID), null, @@ -109,8 +110,8 @@ class CallRedirectionService : CallRedirectionService() { arrayOf(ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE), "${ContactsContract.Data.CONTACT_ID} = ? AND " + "${ContactsContract.Data.MIMETYPE} IN " + - "(${MIMETYPES.keys.joinToString(",") { "?" }})", - arrayOf(contactId, *MIMETYPES.keys.toTypedArray()), + "(${MIMETYPE_TO_WEIGHT.keys.joinToString(",") { "?" }})", + arrayOf(contactId, *MIMETYPE_TO_WEIGHT.keys.toTypedArray()), null, ) cursor?.apply { diff --git a/app/src/main/java/me/lucky/red/MainActivity.kt b/app/src/main/java/me/lucky/red/MainActivity.kt index c9e3fd3..4861f27 100644 --- a/app/src/main/java/me/lucky/red/MainActivity.kt +++ b/app/src/main/java/me/lucky/red/MainActivity.kt @@ -23,6 +23,7 @@ class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var prefs: Preferences + private lateinit var window: PopupWindow private var roleManager: RoleManager? = null private val registerForCallRedirectionRole = @@ -42,14 +43,20 @@ class MainActivity : AppCompatActivity() { setup() } + override fun onDestroy() { + super.onDestroy() + window.cancel() + } + private fun init() { prefs = Preferences(this) + window = PopupWindow(this, null) roleManager = getSystemService(RoleManager::class.java) binding.apply { redirectionDelay.value = (prefs.redirectionDelay / 1000).toFloat() popupPosition.editText?.setText(prefs.popupPosition.toString()) fallback.isChecked = prefs.isFallbackChecked - toggle.isChecked = prefs.isServiceEnabled + toggle.isChecked = prefs.isEnabled } } @@ -61,6 +68,9 @@ class MainActivity : AppCompatActivity() { redirectionDelay.addOnChangeListener { _, value, _ -> prefs.redirectionDelay = (value * 1000).toLong() } + popupPosition.setEndIconOnClickListener { + window.preview() + } popupPosition.editText?.doAfterTextChanged { try { prefs.popupPosition = it?.toString()?.toInt() ?: return@doAfterTextChanged @@ -75,7 +85,7 @@ class MainActivity : AppCompatActivity() { requestPermissions() return@setOnCheckedChangeListener } - prefs.isServiceEnabled = isChecked + prefs.isEnabled = isChecked } } } diff --git a/app/src/main/java/me/lucky/red/PopupWindow.kt b/app/src/main/java/me/lucky/red/PopupWindow.kt index 7bfafe0..9476c39 100644 --- a/app/src/main/java/me/lucky/red/PopupWindow.kt +++ b/app/src/main/java/me/lucky/red/PopupWindow.kt @@ -1,6 +1,7 @@ package me.lucky.red import android.Manifest +import android.content.Context import android.content.Intent import android.graphics.PixelFormat import android.media.AudioManager @@ -10,20 +11,19 @@ import android.view.LayoutInflater import android.view.WindowManager import android.widget.TextView import androidx.annotation.RequiresPermission +import java.lang.ref.WeakReference import java.util.* import kotlin.concurrent.timerTask -class PopupWindow(private val service: CallRedirectionService) { - private val windowManager = service - .applicationContext - .getSystemService(WindowManager::class.java) - private val audioManager = service - .applicationContext - .getSystemService(AudioManager::class.java) +class PopupWindow( + private val ctx: Context, + private val service: WeakReference?, +) { + private val prefs = Preferences(ctx) + private val windowManager = ctx.getSystemService(WindowManager::class.java) + private val audioManager = ctx.getSystemService(AudioManager::class.java) @Suppress("InflateParams") - private val view = LayoutInflater - .from(service.applicationContext) - .inflate(R.layout.popup, null) + private val view = LayoutInflater.from(ctx).inflate(R.layout.popup, null) private val layoutParams = WindowManager.LayoutParams().apply { format = PixelFormat.TRANSLUCENT flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE @@ -31,18 +31,32 @@ class PopupWindow(private val service: CallRedirectionService) { gravity = Gravity.BOTTOM width = WindowManager.LayoutParams.WRAP_CONTENT height = WindowManager.LayoutParams.WRAP_CONTENT - y = service.prefs.popupPosition + y = prefs.popupPosition } private var timer: Timer? = null init { view.setOnClickListener { cancel() - service.placeCallUnmodified() + service?.get()?.placeCallUnmodified() } } + fun preview() { + remove() + layoutParams.y = prefs.popupPosition + val destinations = mutableListOf( + R.string.destination_signal, + R.string.destination_telegram, + R.string.destination_threema, + ) + if (prefs.isFallbackChecked) destinations.add(R.string.fallback_destination_whatsapp) + setDescription(destinations.random()) + add() + } + fun show(uri: Uri, destinationId: Int) { + val service = service?.get() ?: return if (!remove()) { service.placeCallUnmodified() return @@ -65,23 +79,27 @@ class PopupWindow(private val service: CallRedirectionService) { return@timerTask } service.cancelCall() - }, service.prefs.redirectionDelay) - view.findViewById(R.id.description).text = String.format( - service.getString(R.string.popup), - service.getString(destinationId), - ) + }, prefs.redirectionDelay) + setDescription(destinationId) if (!add()) { timer?.cancel() service.placeCallUnmodified() } } + private fun setDescription(id: Int) { + view.findViewById(R.id.description).text = ctx.getString( + R.string.popup, + ctx.getString(id), + ) + } + @RequiresPermission(Manifest.permission.CALL_PHONE) private fun call(data: Uri) { Intent(Intent.ACTION_VIEW).let { it.data = data it.flags = Intent.FLAG_ACTIVITY_NEW_TASK - service.startActivity(it) + ctx.startActivity(it) } } diff --git a/app/src/main/java/me/lucky/red/Preferences.kt b/app/src/main/java/me/lucky/red/Preferences.kt index 33b11b1..7948d8a 100644 --- a/app/src/main/java/me/lucky/red/Preferences.kt +++ b/app/src/main/java/me/lucky/red/Preferences.kt @@ -6,20 +6,23 @@ import androidx.preference.PreferenceManager class Preferences(ctx: Context) { companion object { - private const val SERVICE_ENABLED = "service_enabled" + private const val ENABLED = "enabled" private const val REDIRECTION_DELAY = "redirection_delay" private const val POPUP_POSITION = "popup_position_y" private const val FALLBACK_CHECKED = "fallback_checked" private const val DEFAULT_REDIRECTION_DELAY = 2000L private const val DEFAULT_POPUP_POSITION = 333 + + // migration + private const val SERVICE_ENABLED = "service_enabled" } private val prefs = PreferenceManager.getDefaultSharedPreferences(ctx) - var isServiceEnabled: Boolean - get() = prefs.getBoolean(SERVICE_ENABLED, false) - set(value) = prefs.edit { putBoolean(SERVICE_ENABLED, value) } + var isEnabled: Boolean + get() = prefs.getBoolean(ENABLED, prefs.getBoolean(SERVICE_ENABLED, false)) + set(value) = prefs.edit { putBoolean(ENABLED, value) } var redirectionDelay: Long get() = prefs.getLong(REDIRECTION_DELAY, DEFAULT_REDIRECTION_DELAY) diff --git a/app/src/main/res/drawable/ic_baseline_check_circle_24.xml b/app/src/main/res/drawable/ic_baseline_check_circle_24.xml new file mode 100644 index 0000000..5e111ca --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_check_circle_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 3753d2f..97ae04d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -55,6 +55,8 @@ diff --git a/app/src/main/res/values-fr/string.xml b/app/src/main/res/values-fr/strings.xml similarity index 100% rename from app/src/main/res/values-fr/string.xml rename to app/src/main/res/values-fr/strings.xml diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 88442f2..dd378e5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,7 +6,7 @@ Signal Telegram Threema - Delay before a call will be redirected. + The delay before a call will be redirected. Popup position Fallback Redirect to WhatsApp if no other available. diff --git a/build.gradle b/build.gradle index 9262dea..9d1ce67 100644 --- a/build.gradle +++ b/build.gradle @@ -5,8 +5,8 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.1' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10" + classpath 'com.android.tools.build:gradle:7.2.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/fastlane/metadata/android/en-US/changelogs/9.txt b/fastlane/metadata/android/en-US/changelogs/9.txt new file mode 100644 index 0000000..135fd01 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/9.txt @@ -0,0 +1 @@ +popup window preview diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png index 1c4e57e..8b9cbff 100644 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ diff --git a/fastlane/metadata/android/ru-RU/full_description.txt b/fastlane/metadata/android/ru-RU/full_description.txt index 3004d7f..933fa76 100644 --- a/fastlane/metadata/android/ru-RU/full_description.txt +++ b/fastlane/metadata/android/ru-RU/full_description.txt @@ -1,4 +1,4 @@ -Минимальное приложение для перенаправления исходящих вызовов в Signal/Telegram/Threema. +Мини приложение для перенаправления исходящих вызовов в Signal/Telegram/Threema. Вы можете отменить перенаправление, кликнув на всплывающее сообщение "Перенаправление в..". diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a2e01c0..4a48a57 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ +#Tue Jun 14 23:11:06 MSK 2022 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip distributionPath=wrapper/dists -distributionSha256Sum=f581709a9c35e9cb92e16f585d2c4bc99b2b1a5f85d2badbd3dc6bff59e1e6dd -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME