Some final changes

This commit is contained in:
partisan 2025-05-27 18:56:59 +02:00
parent 9dcfe80a26
commit f8aeb6da10
26 changed files with 154 additions and 62 deletions

View file

@ -1,9 +1,6 @@
name: Android Release Build name: Android Release Build
on: on:
push:
tags:
- '*'
workflow_dispatch: {} workflow_dispatch: {}
jobs: jobs:

3
.gitignore vendored
View file

@ -14,4 +14,5 @@
.cxx .cxx
local.properties local.properties
release-key.jks release-key.jks
check.py check.py
round.sh

View file

@ -30,11 +30,19 @@ Redirecting outgoing calls to E2EE apps.
<p align="center"> <p align="center">
<span> <span>
<img src="https://weforge.xyz/partisan/Pulse/raw/branch/main/data/screenshot.png" alt="Main screen" height="500" style="border-radius: 8px;"> <img src="https://weforge.xyz/partisan/Pulse/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png" alt="Main screen" height="500" style="border-radius: 8px;">
</span> </span>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
<span> <span>
<img src="https://weforge.xyz/partisan/Pulse/raw/branch/main/data/screenshot-redirecting.png" alt="Redirecting popup" height="500" style="border-radius: 8px;"> <img src="https://weforge.xyz/partisan/Pulse/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png" alt="Redirecting popup" height="500" style="border-radius: 8px;">
</span>
&nbsp;&nbsp;&nbsp;&nbsp;
<span>
<img src="https://weforge.xyz/partisan/Pulse/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png" alt="Redirecting popup" height="500" style="border-radius: 8px;">
</span>
&nbsp;&nbsp;&nbsp;&nbsp;
<span>
<img src="https://weforge.xyz/partisan/Pulse/raw/branch/main/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png" alt="Redirecting popup" height="500" style="border-radius: 8px;">
</span> </span>
</p> </p>

View file

@ -28,6 +28,8 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
prefs = Preferences(this)
updateDonationIcon()
setContentView(binding.root) setContentView(binding.root)
prefs = Preferences(this) prefs = Preferences(this)
setSupportActionBar(binding.topAppBar) setSupportActionBar(binding.topAppBar)
@ -50,6 +52,13 @@ class MainActivity : AppCompatActivity() {
binding.navigationView.setNavigationItemSelectedListener { item -> binding.navigationView.setNavigationItemSelectedListener { item ->
when (item.itemId) { when (item.itemId) {
R.id.action_home -> {
supportFragmentManager.popBackStack(null, androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE)
supportFragmentManager.beginTransaction()
.replace(R.id.fragmentContainer, MainFragment())
.commit()
true
}
R.id.action_popup_settings -> { R.id.action_popup_settings -> {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.fragmentContainer, PopupSettingsFragment()) .replace(R.id.fragmentContainer, PopupSettingsFragment())
@ -122,6 +131,16 @@ class MainActivity : AppCompatActivity() {
} }
} }
private fun updateDonationIcon() {
val donateItem = binding.navigationView.menu.findItem(R.id.action_donate)
donateItem.setIcon(
if (prefs.isDonationActivated)
R.drawable.heart_filled_24
else
R.drawable.heart_24
)
}
fun setAppBarTitle(vararg parts: String) { fun setAppBarTitle(vararg parts: String) {
binding.topAppBar.title = parts.joinToString(" > ") binding.topAppBar.title = parts.joinToString(" > ")
} }

View file

@ -11,6 +11,7 @@ import android.widget.ArrayAdapter
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.CompoundButton import android.widget.CompoundButton
import android.widget.Spinner import android.widget.Spinner
import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import partisan.weforge.xyz.pulse.databinding.FragmentPopupSettingsBinding import partisan.weforge.xyz.pulse.databinding.FragmentPopupSettingsBinding
@ -34,6 +35,7 @@ class PopupSettingsFragment : Fragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
updateSpinner()
(requireActivity() as? MainActivity)?.apply { (requireActivity() as? MainActivity)?.apply {
setAppBarTitle(getString(R.string.settings_name), getString(R.string.popup_name)) setAppBarTitle(getString(R.string.settings_name), getString(R.string.popup_name))
setupPopupToggle(true, prefs.popupEnabled) { isChecked -> setupPopupToggle(true, prefs.popupEnabled) { isChecked ->
@ -71,21 +73,7 @@ class PopupSettingsFragment : Fragment() {
prefs.redirectionDelay = (value * 1000).toLong() prefs.redirectionDelay = (value * 1000).toLong()
} }
val effectNames = resources.getStringArray(R.array.popup_effects) updateSpinner()
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, effectNames)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.popupEffectSpinner.adapter = adapter
// Select current setting
binding.popupEffectSpinner.setSelection(prefs.popupEffect.ordinal)
binding.popupEffectSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
prefs.popupEffect = Preferences.PopupEffect.values()[position]
}
override fun onNothingSelected(parent: AdapterView<*>) {}
}
val screenHeight = getScreenHeightPx() val screenHeight = getScreenHeightPx()
binding.popupHeightSlider.valueFrom = 0f binding.popupHeightSlider.valueFrom = 0f
@ -119,6 +107,44 @@ class PopupSettingsFragment : Fragment() {
} }
} }
private fun updateSpinner() {
val allEffects = Preferences.PopupEffect.values()
val effectLabels = resources.getStringArray(R.array.popup_effects)
val availableEffects = prefs.getAvailablePopupEffects() + listOf(
Preferences.PopupEffect.NONE,
Preferences.PopupEffect.RANDOM
)
val displayNames = allEffects.mapIndexed { index, effect ->
val baseName = effectLabels.getOrElse(index) { effect.name }
if (!prefs.isDonationActivated && effect !in availableEffects)
"$baseName 🔒"
else
baseName
}
val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, displayNames)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.popupEffectSpinner.adapter = adapter
binding.popupEffectSpinner.setSelection(prefs.popupEffect.ordinal)
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()) {
Toast.makeText(requireContext(), getString(R.string.donate_lock), Toast.LENGTH_SHORT).show()
binding.popupEffectSpinner.setSelection(prefs.popupEffect.ordinal)
} else {
prefs.popupEffect = selectedEffect
}
}
override fun onNothingSelected(parent: AdapterView<*>) {}
}
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null

View file

@ -174,7 +174,7 @@ class PopupWindow(
} }
val effect = when (prefs.popupEffect) { val effect = when (prefs.popupEffect) {
PopupEffect.RANDOM -> PopupEffect.values().filter { it != PopupEffect.RANDOM && it != PopupEffect.NONE }.random() PopupEffect.RANDOM -> prefs.getAvailablePopupEffects().random()
else -> prefs.popupEffect else -> prefs.popupEffect
} }
currentEffect = effect currentEffect = effect

View file

@ -31,7 +31,7 @@ class Preferences(private val context: Context) {
// Whether user enabled/disabled the service manually by tiggle button // Whether user enabled/disabled the service manually by tiggle button
var isServiceEnabledByUser: Boolean var isServiceEnabledByUser: Boolean
get() = prefs.getBoolean(SERVICE_ENABLED, false) get() = prefs.getBoolean(SERVICE_ENABLED, true)
set(value) = prefs.edit { putBoolean(SERVICE_ENABLED, value) } set(value) = prefs.edit { putBoolean(SERVICE_ENABLED, value) }
// True only if all required permissions + toggle are satisfied // True only if all required permissions + toggle are satisfied
@ -110,6 +110,18 @@ class Preferences(private val context: Context) {
private fun makeKeyEnabled(mimetype: String) = "enabled_$mimetype" private fun makeKeyEnabled(mimetype: String) = "enabled_$mimetype"
private fun makeKeyPriority(mimetype: String) = "priority_$mimetype" private fun makeKeyPriority(mimetype: String) = "priority_$mimetype"
fun getAvailablePopupEffects(): List<PopupEffect> {
val locked = listOf(
PopupEffect.FLOP,
PopupEffect.MATRIX,
PopupEffect.SLIDE_SNAP,
PopupEffect.GAMER_MODE
)
return PopupEffect.values().filter {
isDonationActivated || it !in locked
}.filter { it != PopupEffect.RANDOM && it != PopupEffect.NONE }
}
fun isServiceEnabled(mimetype: String): Boolean { fun isServiceEnabled(mimetype: String): Boolean {
return prefs.getBoolean(makeKeyEnabled(mimetype), true) return prefs.getBoolean(makeKeyEnabled(mimetype), true)
} }

View file

@ -85,20 +85,20 @@ class WelcomeActivity : AppCompatActivity() {
binding.konfettiView.visibility = View.VISIBLE binding.konfettiView.visibility = View.VISIBLE
binding.konfettiView.start( binding.konfettiView.start(
Party( Party(
speed = 30f, speed = 25f,
maxSpeed = 50f, maxSpeed = 50f,
damping = 0.9f, damping = 0.9f,
spread = 360, spread = 360,
colors = listOf(0xfce18a, 0xff726d, 0xf4306d, 0xb48def), colors = listOf(0xfce18a, 0xff726d, 0xf4306d, 0xb48def),
position = Position.Relative(relativeX, relativeY), position = Position.Relative(relativeX, relativeY),
emitter = Emitter(duration = 2, TimeUnit.SECONDS).perSecond(100) emitter = Emitter(duration = 1, TimeUnit.SECONDS).perSecond(80)
) )
) )
binding.konfettiView.postDelayed({ binding.konfettiView.postDelayed({
startActivity(Intent(this, MainActivity::class.java)) startActivity(Intent(this, MainActivity::class.java))
finish() finish()
}, 2000) }, 1500)
} }
} }
} }

View file

@ -39,6 +39,14 @@
android:clickable="true" android:clickable="true"
android:focusable="true" /> android:focusable="true" />
<TextView
android:id="@+id/reminderText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/donate_toast_reminder"
android:textSize="16sp"
android:layout_marginBottom="12dp" />
<Button <Button
android:id="@+id/kofiButton" android:id="@+id/kofiButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -1,45 +1,58 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- Home (main screen toggle) -->
<group android:checkableBehavior="none">
<item
android:id="@+id/action_home"
android:title="@string/home_name"
android:icon="@drawable/ic_power_settings_new_24"
app:showAsAction="never" />
</group>
<!-- Settings section --> <!-- Settings section -->
<item <!-- <item
android:id="@+id/section_settings" android:id="@+id/section_settings"
android:title="@string/settings_name" android:title="@string/settings_name"
android:enabled="false" /> android:enabled="false" /> -->
<item <group android:checkableBehavior="none">
android:id="@+id/action_contacts" <item
android:title="@string/whitelist_name" android:id="@+id/action_contacts"
android:icon="@drawable/group_24px" android:title="@string/whitelist_name"
app:showAsAction="never" /> android:icon="@drawable/group_24px"
<item app:showAsAction="never" />
android:id="@+id/action_popup_settings" <item
android:title="@string/popup_name" android:id="@+id/action_popup_settings"
android:icon="@drawable/tooltip_24px" android:title="@string/popup_name"
app:showAsAction="never" /> android:icon="@drawable/tooltip_24px"
<item app:showAsAction="never" />
android:id="@+id/action_services" <item
android:title="@string/services_name" android:id="@+id/action_services"
android:icon="@drawable/services_24" android:title="@string/services_name"
app:showAsAction="never" /> android:icon="@drawable/services_24"
<item app:showAsAction="never" />
android:id="@+id/action_redirect_settings" <item
android:title="@string/redirect_name" android:id="@+id/action_redirect_settings"
android:icon="@drawable/call_split_24px" android:title="@string/redirect_name"
app:showAsAction="never" /> android:icon="@drawable/call_split_24px"
app:showAsAction="never" />
</group>
<!-- About section --> <!-- About section -->
<item <!-- <item
android:id="@+id/section_about" android:id="@+id/section_about"
android:title="@string/about_name" android:title="@string/about_name"
android:enabled="false" /> android:enabled="false" /> -->
<item <group android:checkableBehavior="none">
android:id="@+id/action_donate" <item
android:title="Donate" android:id="@+id/action_donate"
android:icon="@drawable/heart_24" android:title="Donate"
app:showAsAction="never" /> android:icon="@drawable/heart_24"
<item app:showAsAction="never" />
android:id="@+id/action_about" <item
android:title="@string/about_name" android:id="@+id/action_about"
android:icon="@drawable/info_24px" android:title="@string/about_name"
app:showAsAction="never" /> android:icon="@drawable/info_24px"
app:showAsAction="never" />
</group>
</menu> </menu>

View file

@ -3,6 +3,7 @@
<string name="app_name">Pulse</string> <string name="app_name">Pulse</string>
<string name="description">Redirecting outgoing calls to E2EE apps.</string> <string name="description">Redirecting outgoing calls to E2EE apps.</string>
<string name="popup">Redirecting to %1$s</string> <string name="popup">Redirecting to %1$s</string>
<string name="home_name">Home</string>
<string name="settings_name">Settings</string> <string name="settings_name">Settings</string>
<string name="popup_name">Popup</string> <string name="popup_name">Popup</string>
<string name="services_name">Services</string> <string name="services_name">Services</string>
@ -55,6 +56,7 @@
<string name="donate_token_instruction">Enter your Ko-fi token:</string> <string name="donate_token_instruction">Enter your Ko-fi token:</string>
<string name="donate_token_hint">token: abcd1234efgh5678</string> <string name="donate_token_hint">token: abcd1234efgh5678</string>
<string name="donate_token_activate">Activate Token</string> <string name="donate_token_activate">Activate Token</string>
<string name="donate_lock">Donate to unlock this effect</string>
<!-- DonateFragment --> <!-- DonateFragment -->
<string name="donate_token_copied">Token copied to clipboard</string> <string name="donate_token_copied">Token copied to clipboard</string>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

View file

@ -14,3 +14,9 @@ v2.0.0
Fixes: Fixes:
- Popup now uses system Material colors - Popup now uses system Material colors
- Fixed issue where service priority changes didn't work - Fixed issue where service priority changes didn't work
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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 142 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 163 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Before After
Before After

Binary file not shown.

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-milestone-8-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-all.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

2
gradlew vendored
View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright © 2015 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.