only ask for notifications after login

This commit is contained in:
greenart7c3
2024-04-10 10:31:40 -03:00
parent 729b2de90b
commit f36e64a8e8
3 changed files with 277 additions and 93 deletions
@@ -0,0 +1,178 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "5651f3201d3521ce45fda80b053e6722",
"entities": [
{
"tableName": "application",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `name` TEXT NOT NULL, `relays` TEXT NOT NULL, `url` TEXT NOT NULL, `icon` TEXT NOT NULL, `description` TEXT NOT NULL, `pubKey` TEXT NOT NULL, `isConnected` INTEGER NOT NULL, `secret` TEXT NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "relays",
"columnName": "relays",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "icon",
"columnName": "icon",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "description",
"columnName": "description",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "pubKey",
"columnName": "pubKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isConnected",
"columnName": "isConnected",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "secret",
"columnName": "secret",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"key"
]
},
"indices": [
{
"name": "index_key",
"unique": true,
"columnNames": [
"key"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_key` ON `${TABLE_NAME}` (`key`)"
},
{
"name": "index_name",
"unique": false,
"columnNames": [
"name"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_name` ON `${TABLE_NAME}` (`name`)"
}
],
"foreignKeys": []
},
{
"tableName": "applicationPermission",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER, `pkKey` TEXT NOT NULL, `type` TEXT NOT NULL, `kind` INTEGER, `acceptable` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`pkKey`) REFERENCES `application`(`key`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "pkKey",
"columnName": "pkKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "kind",
"columnName": "kind",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "acceptable",
"columnName": "acceptable",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"id"
]
},
"indices": [
{
"name": "permissions_by_pk_key",
"unique": false,
"columnNames": [
"pkKey"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `permissions_by_pk_key` ON `${TABLE_NAME}` (`pkKey`)"
},
{
"name": "permissions_unique",
"unique": true,
"columnNames": [
"pkKey",
"type",
"kind"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `permissions_unique` ON `${TABLE_NAME}` (`pkKey`, `type`, `kind`)"
}
],
"foreignKeys": [
{
"table": "application",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"pkKey"
],
"referencedColumns": [
"key"
]
}
]
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5651f3201d3521ce45fda80b053e6722')"
]
}
}
@@ -1,32 +1,20 @@
package com.greenart7c3.nostrsigner
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.core.content.ContextCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import com.greenart7c3.nostrsigner.database.AppDatabase
import com.greenart7c3.nostrsigner.models.IntentData
import com.greenart7c3.nostrsigner.service.IntentUtils
import com.greenart7c3.nostrsigner.service.PushNotificationUtils
import com.greenart7c3.nostrsigner.ui.AccountScreen
import com.greenart7c3.nostrsigner.ui.AccountStateViewModel
import com.greenart7c3.nostrsigner.ui.theme.NostrSignerTheme
@@ -38,46 +26,6 @@ import kotlinx.coroutines.withContext
fun Intent.isLaunchFromHistory(): Boolean = this.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
class MainActivity : AppCompatActivity() {
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
initNotifications()
} else {
if (LocalPreferences.shouldShowRationale() == null) {
LocalPreferences.updateShoulShowRationale(true)
}
}
}
private fun initNotifications() {
runBlocking {
PushNotificationUtils.init(LocalPreferences.allSavedAccounts())
}
}
private fun askNotificationPermission(onShouldShowRequestPermissionRationale: () -> Unit) {
// This is only necessary for API level >= 33 (TIRAMISU)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, "android.permission.POST_NOTIFICATIONS") != PackageManager.PERMISSION_GRANTED
) {
val shouldShowRationale = LocalPreferences.shouldShowRationale()
if (shouldShowRationale == null) {
requestPermissionLauncher.launch("android.permission.POST_NOTIFICATIONS")
return
}
if (!shouldShowRationale) {
return
}
onShouldShowRequestPermissionRationale()
}
} else {
requestPermissionLauncher.launch("android.permission.POST_NOTIFICATIONS")
}
}
private val intents = MutableStateFlow<List<IntentData>>(listOf())
override fun onCreate(savedInstanceState: Bundle?) {
@@ -85,14 +33,7 @@ class MainActivity : AppCompatActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false)
installSplashScreen()
initNotifications()
setContent {
var showDialog by remember { mutableStateOf(false) }
askNotificationPermission {
showDialog = true
}
if (intent.isLaunchFromHistory()) {
Log.d("isLaunchFromHistory", "Cleared intent history")
intent = Intent()
@@ -113,40 +54,6 @@ class MainActivity : AppCompatActivity() {
}
NostrSignerTheme {
if (showDialog) {
AlertDialog(
onDismissRequest = {
showDialog = false
},
title = {
Text(text = "Permission Needed")
},
text = {
Text(text = "Notifications are needed to use Amber as a nsec bunker.")
},
confirmButton = {
Button(
onClick = {
showDialog = false
requestPermissionLauncher.launch("android.permission.POST_NOTIFICATIONS")
}
) {
Text(text = "Allow")
}
},
dismissButton = {
Button(
onClick = {
showDialog = false
LocalPreferences.updateShoulShowRationale(false)
}
) {
Text(text = "Deny")
}
}
)
}
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
@@ -3,8 +3,13 @@ package com.greenart7c3.nostrsigner.ui
import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.widget.Toast
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
@@ -25,6 +30,8 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -44,6 +51,7 @@ import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.material3.rememberTooltipState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -64,6 +72,7 @@ import androidx.compose.ui.text.toUpperCase
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.core.content.ContextCompat
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@@ -443,6 +452,39 @@ fun EditAppDialog(permission: ApplicationEntity, onClose: () -> Unit, onPost: (S
}
}
private fun askNotificationPermission(
context: Context,
requestPermissionLauncher: ManagedActivityResultLauncher<String, Boolean>,
onShouldShowRequestPermissionRationale: () -> Unit
) {
if (ContextCompat.checkSelfPermission(context, "android.permission.POST_NOTIFICATIONS") == PackageManager.PERMISSION_GRANTED) {
initNotifications()
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val shouldShowRationale = LocalPreferences.shouldShowRationale()
if (shouldShowRationale == null) {
requestPermissionLauncher.launch("android.permission.POST_NOTIFICATIONS")
return
}
if (!shouldShowRationale) {
return
}
onShouldShowRequestPermissionRationale()
} else {
requestPermissionLauncher.launch("android.permission.POST_NOTIFICATIONS")
}
}
private fun initNotifications() {
runBlocking {
PushNotificationUtils.init(LocalPreferences.allSavedAccounts())
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(
@@ -466,6 +508,63 @@ fun MainScreen(
val interactionSource = remember { MutableInteractionSource() }
val clipboardManager = LocalClipboardManager.current
val requestPermissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
initNotifications()
} else {
if (LocalPreferences.shouldShowRationale() == null) {
LocalPreferences.updateShoulShowRationale(true)
}
}
}
val context = LocalContext.current
var showDialog by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
askNotificationPermission(
context,
requestPermissionLauncher
) {
showDialog = true
}
}
if (showDialog) {
AlertDialog(
onDismissRequest = {
showDialog = false
},
title = {
Text(text = "Permission Needed")
},
text = {
Text(text = "Notifications are needed to use Amber as a nsec bunker.")
},
confirmButton = {
Button(
onClick = {
showDialog = false
requestPermissionLauncher.launch("android.permission.POST_NOTIFICATIONS")
}
) {
Text(text = "Allow")
}
},
dismissButton = {
Button(
onClick = {
showDialog = false
LocalPreferences.updateShoulShowRationale(false)
}
) {
Text(text = "Deny")
}
}
)
}
Scaffold(
floatingActionButton = {
if (navBackStackEntry?.destination?.route == "Permissions") {