New Welcome screen
This commit is contained in:
parent
794fe46b45
commit
cba93c6069
7 changed files with 221 additions and 18 deletions
|
@ -69,4 +69,5 @@ dependencies {
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
|
implementation 'nl.dionsegijn:konfetti-xml:2.0.2' // This library holds the fabric of reality together please dont remove it at any costs >:3
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,14 @@
|
||||||
android:theme="@style/Theme.Pulse">
|
android:theme="@style/Theme.Pulse">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".WelcomeActivity"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name=".MainActivity" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".CallRedirectionService"
|
android:name=".CallRedirectionService"
|
||||||
|
|
|
@ -22,14 +22,10 @@ import partisan.weforge.xyz.pulse.setServicePriority
|
||||||
import partisan.weforge.xyz.pulse.isServiceEnabled
|
import partisan.weforge.xyz.pulse.isServiceEnabled
|
||||||
import partisan.weforge.xyz.pulse.setServiceEnabled
|
import partisan.weforge.xyz.pulse.setServiceEnabled
|
||||||
import partisan.weforge.xyz.pulse.databinding.ActivityMainBinding
|
import partisan.weforge.xyz.pulse.databinding.ActivityMainBinding
|
||||||
|
import partisan.weforge.xyz.pulse.REQUIRED_PERMISSIONS
|
||||||
|
import partisan.weforge.xyz.pulse.hasGeneralPermissions
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
companion object {
|
|
||||||
private val PERMISSIONS = arrayOf(
|
|
||||||
Manifest.permission.READ_CONTACTS,
|
|
||||||
Manifest.permission.CALL_PHONE,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
private lateinit var prefs: Preferences
|
private lateinit var prefs: Preferences
|
||||||
|
@ -156,28 +152,22 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private fun requestPermissions() {
|
private fun requestPermissions() {
|
||||||
when {
|
when {
|
||||||
!hasGeneralPermissions() -> requestGeneralPermissions()
|
!hasGeneralPermissions(this) -> registerForGeneralPermissions.launch(REQUIRED_PERMISSIONS)
|
||||||
!hasDrawOverlays() -> requestDrawOverlays()
|
!hasDrawOverlays() -> requestDrawOverlays()
|
||||||
!hasCallRedirectionRole() -> requestCallRedirectionRole()
|
!hasCallRedirectionRole() -> requestCallRedirectionRole()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasPermissions(): Boolean {
|
private fun hasPermissions(): Boolean {
|
||||||
return hasGeneralPermissions() && hasDrawOverlays() && hasCallRedirectionRole()
|
return hasGeneralPermissions(this) &&
|
||||||
|
hasDrawOverlays(this) &&
|
||||||
|
hasCallRedirectionRole(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestDrawOverlays() {
|
private fun requestDrawOverlays() {
|
||||||
registerForDrawOverlays.launch(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))
|
registerForDrawOverlays.launch(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestGeneralPermissions() {
|
|
||||||
registerForGeneralPermissions.launch(PERMISSIONS)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasGeneralPermissions(): Boolean {
|
|
||||||
return !PERMISSIONS.any { checkSelfPermission(it) != PackageManager.PERMISSION_GRANTED }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasDrawOverlays(): Boolean {
|
private fun hasDrawOverlays(): Boolean {
|
||||||
return Settings.canDrawOverlays(this)
|
return Settings.canDrawOverlays(this)
|
||||||
}
|
}
|
||||||
|
|
28
app/src/main/java/partisan/weforge/xyz/pulse/Permissions.kt
Normal file
28
app/src/main/java/partisan/weforge/xyz/pulse/Permissions.kt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
package partisan.weforge.xyz.pulse
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.app.role.RoleManager
|
||||||
|
|
||||||
|
val REQUIRED_PERMISSIONS = arrayOf(
|
||||||
|
Manifest.permission.READ_CONTACTS,
|
||||||
|
Manifest.permission.CALL_PHONE,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun hasGeneralPermissions(context: Context): Boolean {
|
||||||
|
return REQUIRED_PERMISSIONS.all {
|
||||||
|
context.checkSelfPermission(it) == PackageManager.PERMISSION_GRANTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasDrawOverlays(context: Context): Boolean {
|
||||||
|
return Settings.canDrawOverlays(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasCallRedirectionRole(context: Context): Boolean {
|
||||||
|
val roleManager = context.getSystemService(RoleManager::class.java)
|
||||||
|
return roleManager?.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION) ?: false
|
||||||
|
}
|
107
app/src/main/java/partisan/weforge/xyz/pulse/WelcomeActivity.kt
Normal file
107
app/src/main/java/partisan/weforge/xyz/pulse/WelcomeActivity.kt
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
package partisan.weforge.xyz.pulse
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.role.RoleManager
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.view.View
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
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 partisan.weforge.xyz.pulse.databinding.ActivityWelcomeBinding
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import partisan.weforge.xyz.pulse.hasGeneralPermissions
|
||||||
|
import partisan.weforge.xyz.pulse.hasDrawOverlays
|
||||||
|
import partisan.weforge.xyz.pulse.hasCallRedirectionRole
|
||||||
|
import partisan.weforge.xyz.pulse.REQUIRED_PERMISSIONS
|
||||||
|
|
||||||
|
class WelcomeActivity : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityWelcomeBinding
|
||||||
|
private lateinit var prefs: Preferences
|
||||||
|
private var roleManager: RoleManager? = null
|
||||||
|
|
||||||
|
private val requestPermissionsLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.RequestMultiplePermissions()
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private val requestOverlayLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private val requestRoleLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) {}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
if (hasGeneralPermissions(this) && hasDrawOverlays(this) && hasCallRedirectionRole(this)) {
|
||||||
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
binding = ActivityWelcomeBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
prefs = Preferences(this)
|
||||||
|
roleManager = getSystemService(RoleManager::class.java)
|
||||||
|
|
||||||
|
binding.activateButton.setOnClickListener {
|
||||||
|
when {
|
||||||
|
!hasGeneralPermissions(this) -> {
|
||||||
|
requestPermissionsLauncher.launch(REQUIRED_PERMISSIONS)
|
||||||
|
}
|
||||||
|
!hasDrawOverlays(this) -> {
|
||||||
|
requestOverlayLauncher.launch(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))
|
||||||
|
}
|
||||||
|
!hasCallRedirectionRole(this) -> {
|
||||||
|
requestRoleLauncher.launch(roleManager?.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
prefs.isEnabled = true
|
||||||
|
showConfettiAndContinue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showConfettiAndContinue() {
|
||||||
|
binding.appIcon.post {
|
||||||
|
val iconLocation = IntArray(2)
|
||||||
|
binding.appIcon.getLocationOnScreen(iconLocation)
|
||||||
|
|
||||||
|
val iconCenterX = iconLocation[0] + binding.appIcon.width / 2f
|
||||||
|
val iconCenterY = iconLocation[1] + binding.appIcon.height / 2f
|
||||||
|
|
||||||
|
val rootWidth = binding.root.width.toFloat()
|
||||||
|
val rootHeight = binding.root.height.toFloat()
|
||||||
|
|
||||||
|
val relativeX = (iconCenterX / rootWidth).toDouble()
|
||||||
|
val relativeY = (iconCenterY / rootHeight).toDouble()
|
||||||
|
|
||||||
|
binding.konfettiView.visibility = View.VISIBLE
|
||||||
|
binding.konfettiView.start(
|
||||||
|
Party(
|
||||||
|
speed = 30f,
|
||||||
|
maxSpeed = 50f,
|
||||||
|
damping = 0.9f,
|
||||||
|
spread = 360,
|
||||||
|
colors = listOf(0xfce18a, 0xff726d, 0xf4306d, 0xb48def),
|
||||||
|
position = Position.Relative(relativeX, relativeY),
|
||||||
|
emitter = Emitter(duration = 2, TimeUnit.SECONDS).perSecond(100)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.konfettiView.postDelayed({
|
||||||
|
startActivity(Intent(this, MainActivity::class.java))
|
||||||
|
finish()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
app/src/main/res/layout/activity_welcome.xml
Normal file
74
app/src/main/res/layout/activity_welcome.xml
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/rootLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="32dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/contentWrapper"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/appIcon"
|
||||||
|
android:layout_width="96dp"
|
||||||
|
android:layout_height="96dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:contentDescription="@string/app_name"
|
||||||
|
android:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/appName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginTop="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/appDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/description"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:layout_marginTop="8dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/activateButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/activate"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
app:cornerRadius="24dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/activateDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/activate_description"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<nl.dionsegijn.konfetti.xml.KonfettiView
|
||||||
|
android:id="@+id/konfettiView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</FrameLayout>
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Pulse</string>
|
<string name="app_name">Pulse</string>
|
||||||
<string name="description">The app will try to redirect outgoing calls to Signal/Telegram/Threema/WhatsApp if available. For work it requires many permissions. Click on the toggle and grant permissions until it turns ON.</string>
|
<string name="description">App will try to redirect outgoing calls to E2EE apps if available.</string>
|
||||||
<string name="popup">Redirecting to %1$s</string>
|
<string name="popup">Redirecting to %1$s</string>
|
||||||
<string name="destination_signal">Signal</string>
|
<string name="destination_signal">Signal</string>
|
||||||
<string name="destination_telegram">Telegram</string>
|
<string name="destination_telegram">Telegram</string>
|
||||||
|
@ -10,4 +10,6 @@
|
||||||
<string name="redirection_delay_description">The delay before a call will be redirected.</string>
|
<string name="redirection_delay_description">The delay before a call will be redirected.</string>
|
||||||
<string name="popup_position">Popup position</string>
|
<string name="popup_position">Popup position</string>
|
||||||
<string name="fallback">Fallback</string>
|
<string name="fallback">Fallback</string>
|
||||||
|
<string name="activate_description">To start, grant the required permissions and tap the Activate button.</string>
|
||||||
|
<string name="activate">Activate</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Add table
Add a link
Reference in a new issue