From 3fa2bc38ab53b5907a3fe086a0e2b9a0b7831358 Mon Sep 17 00:00:00 2001 From: partisan Date: Tue, 27 May 2025 19:07:25 +0200 Subject: [PATCH 1/8] Typos --- fastlane/metadata/android/en-US/changelogs/15.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fastlane/metadata/android/en-US/changelogs/15.txt b/fastlane/metadata/android/en-US/changelogs/15.txt index 54dbb99..9f159d6 100644 --- a/fastlane/metadata/android/en-US/changelogs/15.txt +++ b/fastlane/metadata/android/en-US/changelogs/15.txt @@ -17,6 +17,6 @@ Fixes: Misc: - Updated Gradle to v8.14.1 -- Updated screenshots to include new looks of the app. -- Updated description. -- Added temporary "v2.0" to store icon to indicate new version. \ No newline at end of file +- Updated screenshots to reflect the new look of the app +- Updated description +- Temporarily added "v2.0" to the store icon to indicate the new version \ No newline at end of file From 4c9b0a1b229b5e8879fda812ad1cc1ba19e1762b Mon Sep 17 00:00:00 2001 From: partisan Date: Wed, 28 May 2025 16:14:42 +0200 Subject: [PATCH 2/8] Fixed lock warning on NONE and RANDOM popup effects --- app/build.gradle | 4 ++-- .../partisan/weforge/xyz/pulse/PopupSettingsFragment.kt | 6 +++++- fastlane/metadata/android/en-US/changelogs/16.txt | 2 ++ fastlane/metadata/android/en-US/short_description.txt | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/16.txt diff --git a/app/build.gradle b/app/build.gradle index 6de77a6..f9bf50f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId = "partisan.weforge.xyz.pulse" minSdk = 29 targetSdk = 34 - versionCode = 14 - versionName = "2.0.0" + versionCode = 15 + versionName = "2.0.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt index 5a504d3..1150450 100644 --- a/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt +++ b/app/src/main/java/partisan/weforge/xyz/pulse/PopupSettingsFragment.kt @@ -133,7 +133,11 @@ class PopupSettingsFragment : Fragment() { binding.popupEffectSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) { val selectedEffect = allEffects[position] - if (!prefs.isDonationActivated && selectedEffect !in prefs.getAvailablePopupEffects()) { + if (!prefs.isDonationActivated && + selectedEffect !in prefs.getAvailablePopupEffects() && + selectedEffect != Preferences.PopupEffect.NONE && + selectedEffect != Preferences.PopupEffect.RANDOM + ) { Toast.makeText(requireContext(), getString(R.string.donate_lock), Toast.LENGTH_SHORT).show() binding.popupEffectSpinner.setSelection(prefs.popupEffect.ordinal) } else { diff --git a/fastlane/metadata/android/en-US/changelogs/16.txt b/fastlane/metadata/android/en-US/changelogs/16.txt new file mode 100644 index 0000000..19c988b --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/16.txt @@ -0,0 +1,2 @@ +v2.0.1 +- Fixed lock warning on NONE and RANDOM popup effects \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/short_description.txt b/fastlane/metadata/android/en-US/short_description.txt index aa3476a..3ffffd0 100644 --- a/fastlane/metadata/android/en-US/short_description.txt +++ b/fastlane/metadata/android/en-US/short_description.txt @@ -1 +1 @@ -Redirecting outgoing calls to E2EE apps. \ No newline at end of file +Redirecting outgoing calls to E2EE apps \ No newline at end of file From 042b079723c2c721a92417baea07ab749012666a Mon Sep 17 00:00:00 2001 From: partisan Date: Sat, 31 May 2025 19:14:58 +0200 Subject: [PATCH 3/8] Updated fastlane full desc --- .../android/en-US/full_description.txt | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 09bf845..491ea81 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -3,28 +3,47 @@ Redirect calls to Signal, Telegram, Threema, or WhatsApp. --- **Features:** + - Material You design + - Popup with cancel option + - Extensive settings panel: + - Toggle per-service support + - Redirection only on Wi-Fi/Data + - Allowlist specific contacts + - Change per-service priority + - Customize popup position, animation, and duration - ... + + - etc **Supports:** + - Signal + - Telegram + - Threema + - WhatsApp **Permissions required:** + - `CALL_PHONE` - initiate calls via messenger + - `READ_CONTACTS` - check contact compatibility + - `READ_PHONE_NUMBERS` - detect outgoing call + - `SYSTEM_ALERT_WINDOW` - show popup overlay + - `ACCESS_NETWORK_STATE` - check connectivity + - `INTERNET` - check connectivity and verify donates Currently all of the permissions are required. From a95a548e1fd8250b1fdc4520ad53c7a5e6c96168 Mon Sep 17 00:00:00 2001 From: partisan Date: Sat, 31 May 2025 17:22:50 +0000 Subject: [PATCH 4/8] Update fastlane/metadata/android/en-US/full_description.txt --- fastlane/metadata/android/en-US/full_description.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 491ea81..0d1ab15 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -48,5 +48,8 @@ Redirect calls to Signal, Telegram, Threema, or WhatsApp. Currently all of the permissions are required. +--- + **License:** GPL-3.0 + Free and open source From b981f41955679f1961d81951359683aa2d461317 Mon Sep 17 00:00:00 2001 From: partisan Date: Sat, 31 May 2025 20:01:50 +0000 Subject: [PATCH 5/8] Update fastlane/metadata/android/en-US/full_description.txt --- .../metadata/android/en-US/full_description.txt | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 0d1ab15..63a13d2 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -5,43 +5,28 @@ Redirect calls to Signal, Telegram, Threema, or WhatsApp. **Features:** - Material You design - - Popup with cancel option - - Extensive settings panel: - - Toggle per-service support - - Redirection only on Wi-Fi/Data - - Allowlist specific contacts - - Change per-service priority - - Customize popup position, animation, and duration - - etc **Supports:** - Signal - - Telegram - - Threema - - WhatsApp **Permissions required:** - `CALL_PHONE` - initiate calls via messenger - - `READ_CONTACTS` - check contact compatibility - - `READ_PHONE_NUMBERS` - detect outgoing call - - `SYSTEM_ALERT_WINDOW` - show popup overlay - - `ACCESS_NETWORK_STATE` - check connectivity - `INTERNET` - check connectivity and verify donates From 9750daaaa2d0ffc1f862206bc0beb724f3ec6768 Mon Sep 17 00:00:00 2001 From: partisan Date: Sun, 1 Jun 2025 08:57:23 +0000 Subject: [PATCH 6/8] Update fastlane/metadata/android/en-US/full_description.txt --- fastlane/metadata/android/en-US/full_description.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 63a13d2..e63bda7 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -28,7 +28,6 @@ Redirect calls to Signal, Telegram, Threema, or WhatsApp. - `READ_PHONE_NUMBERS` - detect outgoing call - `SYSTEM_ALERT_WINDOW` - show popup overlay - `ACCESS_NETWORK_STATE` - check connectivity - - `INTERNET` - check connectivity and verify donates Currently all of the permissions are required. From c8ede0d472a854e6e0fafb75a34193f3a5188149 Mon Sep 17 00:00:00 2001 From: partisan Date: Tue, 3 Jun 2025 21:13:38 +0200 Subject: [PATCH 7/8] Fixed minor bug and added warning text when app does not have sufficient permissions --- app/build.gradle | 4 +- .../weforge/xyz/pulse/ContactsFragment.kt | 16 +++-- .../weforge/xyz/pulse/MainFragment.kt | 72 +++++++++++++++---- .../partisan/weforge/xyz/pulse/SecretView.kt | 11 +-- app/src/main/res/layout/fragment_main.xml | 13 ++++ app/src/main/res/values/strings.xml | 4 ++ .../metadata/android/en-US/changelogs/17.txt | 3 + 7 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/17.txt diff --git a/app/build.gradle b/app/build.gradle index f9bf50f..7b72933 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId = "partisan.weforge.xyz.pulse" minSdk = 29 targetSdk = 34 - versionCode = 15 - versionName = "2.0.1" + versionCode = 16 + versionName = "2.0.2" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt index 370281d..39d236a 100644 --- a/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt +++ b/app/src/main/java/partisan/weforge/xyz/pulse/ContactsFragment.kt @@ -89,7 +89,9 @@ class ContactsFragment : Fragment() { } private fun getContacts(): List { + val results = mutableListOf() val resolver: ContentResolver = requireContext().contentResolver + val projection = arrayOf( ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER @@ -103,16 +105,16 @@ class ContactsFragment : Fragment() { "${ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME} ASC" ) - val results = mutableListOf() - cursor?.use { - val nameIndex = it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME) - val numberIndex = it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER) + val nameIndex = it.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME) + val numberIndex = it.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER) while (it.moveToNext()) { - val name = it.getString(nameIndex) ?: continue - val number = it.getString(numberIndex) ?: continue - results.add(ContactEntry(name, number)) + val name = it.getString(nameIndex) + val number = it.getString(numberIndex) + if (!name.isNullOrBlank() && !number.isNullOrBlank()) { + results.add(ContactEntry(name, number)) + } } } diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt b/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt index 9e8c3b4..72cc529 100644 --- a/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt +++ b/app/src/main/java/partisan/weforge/xyz/pulse/MainFragment.kt @@ -1,17 +1,20 @@ package partisan.weforge.xyz.pulse +import android.net.ConnectivityManager +import android.net.NetworkCapabilities import android.os.Bundle import android.os.SystemClock import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.TextView import androidx.fragment.app.Fragment import com.google.android.material.button.MaterialButton +import java.util.concurrent.TimeUnit import nl.dionsegijn.konfetti.core.Party import nl.dionsegijn.konfetti.core.Position import nl.dionsegijn.konfetti.core.emitter.Emitter import nl.dionsegijn.konfetti.xml.KonfettiView -import java.util.concurrent.TimeUnit class MainFragment : Fragment() { @@ -24,9 +27,9 @@ class MainFragment : Fragment() { } override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? ): View { val view = inflater.inflate(R.layout.fragment_main, container, false) prefs = Preferences(requireContext()) @@ -44,14 +47,16 @@ class MainFragment : Fragment() { if (isNowChecked && SystemClock.elapsedRealtime() - lastConfettiTime > 500) { konfetti.start( - Party( - emitter = Emitter(duration = 100, TimeUnit.MILLISECONDS).perSecond(100), - speed = 30f, - maxSpeed = 40f, - damping = 0.85f, - spread = 360, - position = Position.Relative(0.5, 0.5) - ) + Party( + emitter = + Emitter(duration = 100, TimeUnit.MILLISECONDS) + .perSecond(100), + speed = 30f, + maxSpeed = 40f, + damping = 0.85f, + spread = 360, + position = Position.Relative(0.5, 0.5) + ) ) lastConfettiTime = SystemClock.elapsedRealtime() } @@ -62,6 +67,49 @@ class MainFragment : Fragment() { } } + val warningText = view.findViewById(R.id.warningText) + val warnings = mutableListOf() + + // 1. Check if contacts are available + val contactCursor = + requireContext() + .contentResolver + .query( + android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + null, + null, + null, + null + ) + + if (contactCursor != null) { + contactCursor.use { + if (!it.moveToFirst()) { + warnings.add(getString(R.string.warn_no_contacts)) + } + } + } else { + warnings.add(getString(R.string.warn_no_contacts)) + } + + // 2. Check internet connectivity + if (!hasInternet()) { + warnings.add(getString(R.string.warn_no_internet)) + } + + // Show warning if needed + if (warnings.isNotEmpty()) { + warningText.text = warnings.joinToString("\n") + warningText.visibility = View.VISIBLE + } + return view } + + private fun hasInternet(): Boolean { + val cm = requireContext().getSystemService(ConnectivityManager::class.java) + val capabilities = cm?.getNetworkCapabilities(cm.activeNetwork) ?: return false + return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && + capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + } } diff --git a/app/src/main/java/partisan/weforge/xyz/pulse/SecretView.kt b/app/src/main/java/partisan/weforge/xyz/pulse/SecretView.kt index 64efcce..759e8aa 100644 --- a/app/src/main/java/partisan/weforge/xyz/pulse/SecretView.kt +++ b/app/src/main/java/partisan/weforge/xyz/pulse/SecretView.kt @@ -127,10 +127,13 @@ class SecretView @JvmOverloads constructor( com.google.android.material.R.attr.colorPrimaryVariant, com.google.android.material.R.attr.colorSecondary ) - context.obtainStyledAttributes(colorAttrs).use { - playerPaint.color = it.getColor(0, Color.CYAN) - enemyPaint.color = it.getColor(0, Color.CYAN) - colorSecondary = it.getColor(1, Color.GREEN) + val ta = context.obtainStyledAttributes(colorAttrs) + try { + playerPaint.color = ta.getColor(0, Color.CYAN) + enemyPaint.color = ta.getColor(0, Color.CYAN) + colorSecondary = ta.getColor(1, Color.GREEN) + } finally { + ta.recycle() } Choreographer.getInstance().postFrameCallback(this) diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 86b4dee..741fc5e 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -34,4 +34,17 @@ app:iconGravity="textTop" app:iconPadding="0dp" app:cornerRadius="48dp" /> + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2ebeab5..19b99a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -47,6 +47,10 @@ Random + + Unable to access contacts. + No internet connection. + Support Pulse Development πŸ’– Pulse is free and open-source. You can support future development through Ko-fi. As a thank-you, donors get special popup animation effects! diff --git a/fastlane/metadata/android/en-US/changelogs/17.txt b/fastlane/metadata/android/en-US/changelogs/17.txt new file mode 100644 index 0000000..d18ecdb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/17.txt @@ -0,0 +1,3 @@ +v2.0.2 +- Added warning text in case the app does not have sufficient permissions +- Fixed a bug related to tapping the Pulse logo in the About section, specific to MIUI \ No newline at end of file From 660637626e58ab2ba76d79ad597e5b750e6389c6 Mon Sep 17 00:00:00 2001 From: partisan Date: Tue, 3 Jun 2025 21:17:54 +0200 Subject: [PATCH 8/8] Pulled from main --- README.md | 44 +++++++++---------- .../android/en-US/full_description.txt | 19 ++------ 2 files changed, 25 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 9ac9d9e..5bcb4a7 100644 --- a/README.md +++ b/README.md @@ -48,22 +48,22 @@ Redirecting outgoing calls to E2EE apps. # Features -- Material You design -- Popup with cancel option +- Material You design +- Popup with cancel option - Extensive settings panel: - - Toggle per-service support - - Redirection only on Wi-Fi/Data - - Allowlist specific contacts - - Change per-service priority - - Customize popup position, animation, and duration + - Toggle per-service support + - Redirection only on Wi-Fi/Data + - Allowlist specific contacts + - Change per-service priority + - Customize popup position, animation, and duration - ... # Supports -- Signal -- Telegram -- Threema -- WhatsApp +- Signal +- Telegram +- Threema +- WhatsApp # How to Install @@ -73,7 +73,7 @@ Redirecting outgoing calls to E2EE apps. In the app, search for "Pulse" and install it. -*Pulse uses the IzzyOnDroid repo. Some F-Droid clients, such as F-Droid itself, do not include it by default. Please add the IzzyOnDroid repo: https://apt.izzysoft.de/fdroid/repo* +_Pulse uses the IzzyOnDroid repo. Some F-Droid clients, such as F-Droid itself, do not include it by default. Please add the IzzyOnDroid repo: https://apt.izzysoft.de/fdroid/repo_ ## Using Obtainium @@ -81,8 +81,8 @@ In the app, search for "Pulse" and install it. In the β€œAdd App” screen: -1. Add the following URL: https://weforge.xyz/partisan/Pulse -2. In **Override Source**, select **Forgejo (Codeberg)** +1. Add the following URL: https://weforge.xyz/partisan/Pulse +2. In **Override Source**, select **Forgejo (Codeberg)** 3. Tap the β€œAdd” button at the very top, and you’re done! ## Install directly @@ -91,16 +91,16 @@ Go to the [Releases page](https://weforge.xyz/partisan/Pulse/releases) and downl Install it, and you’re done! -*Please note that when installing directly, the app will not receive automatic updates.* +_Please note that when installing directly, the app will not receive automatic updates._ # Permissions -- `ACCESS_NETWORK_STATE` – check connectivity -- `CALL_PHONE` – make a call via messenger -- `READ_CONTACTS` – check if contact has a messenger -- `READ_PHONE_NUMBERS` – detect outgoing call -- `SYSTEM_ALERT_WINDOW` – show redirecting popup and launch from background -- `INTERNET` – check connectivity and verify donates +- `ACCESS_NETWORK_STATE` – check connectivity +- `CALL_PHONE` – make a call via messenger +- `READ_CONTACTS` – check if contact has a messenger +- `READ_PHONE_NUMBERS` – detect outgoing call +- `SYSTEM_ALERT_WINDOW` – show redirecting popup and launch from background +- `INTERNET` – check connectivity and verify donates Currently all of the permissions are required. @@ -120,4 +120,4 @@ Licensed under the [Public Domain](https://www.svgrepo.com/page/licensing/#PD). ## Original Author -[This software](https://github.com/x13a/Red) was originally developed by [x13a](https://github.com/x13a), but it has been archived by the owner on Jun 22, 2022. \ No newline at end of file +[This software](https://github.com/x13a/Red) was originally developed by [x13a](https://github.com/x13a), but it has been archived by the owner on Jun 22, 2022. diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 491ea81..e63bda7 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -5,48 +5,35 @@ Redirect calls to Signal, Telegram, Threema, or WhatsApp. **Features:** - Material You design - - Popup with cancel option - - Extensive settings panel: - - Toggle per-service support - - Redirection only on Wi-Fi/Data - - Allowlist specific contacts - - Change per-service priority - - Customize popup position, animation, and duration - - etc **Supports:** - Signal - - Telegram - - Threema - - WhatsApp **Permissions required:** - `CALL_PHONE` - initiate calls via messenger - - `READ_CONTACTS` - check contact compatibility - - `READ_PHONE_NUMBERS` - detect outgoing call - - `SYSTEM_ALERT_WINDOW` - show popup overlay - - `ACCESS_NETWORK_STATE` - check connectivity - - `INTERNET` - check connectivity and verify donates Currently all of the permissions are required. +--- + **License:** GPL-3.0 + Free and open source