fixed deploy and navigation
This commit is contained in:
@@ -11,7 +11,8 @@
|
|||||||
android:theme="@style/Theme.HarheimerTC"
|
android:theme="@style/Theme.HarheimerTC"
|
||||||
android:usesCleartextTraffic="${usesCleartextTraffic}">
|
android:usesCleartextTraffic="${usesCleartextTraffic}">
|
||||||
<activity android:name="de.harheimertc.MainActivity"
|
<activity android:name="de.harheimertc.MainActivity"
|
||||||
android:exported="true">
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop">
|
||||||
<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" />
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package de.harheimertc
|
package de.harheimertc
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import de.harheimertc.ui.navigation.NavGraph
|
import de.harheimertc.ui.navigation.NavGraph
|
||||||
@@ -21,6 +24,8 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
private val notificationRoute = mutableStateOf<String?>(null)
|
||||||
|
|
||||||
private val notificationPermissionLauncher = registerForActivityResult(
|
private val notificationPermissionLauncher = registerForActivityResult(
|
||||||
ActivityResultContracts.RequestPermission(),
|
ActivityResultContracts.RequestPermission(),
|
||||||
) { granted ->
|
) { granted ->
|
||||||
@@ -30,26 +35,56 @@ class MainActivity : ComponentActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
requestNotificationPermissionIfNeeded()
|
requestNotificationPermissionIfNeeded()
|
||||||
|
notificationRoute.value = extractNotificationRoute(intent)
|
||||||
setContent {
|
setContent {
|
||||||
App()
|
App(
|
||||||
|
notificationRoute = notificationRoute.value,
|
||||||
|
onNotificationRouteConsumed = { notificationRoute.value = null },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
setIntent(intent)
|
||||||
|
notificationRoute.value = extractNotificationRoute(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractNotificationRoute(intent: Intent?): String? =
|
||||||
|
intent?.getStringExtra(EXTRA_NOTIFICATION_ROUTE)?.takeIf { it.isNotBlank() }
|
||||||
|
|
||||||
private fun requestNotificationPermissionIfNeeded() {
|
private fun requestNotificationPermissionIfNeeded() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !HarheimerNotifications.hasNotificationPermission(this)) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !HarheimerNotifications.hasNotificationPermission(this)) {
|
||||||
notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val EXTRA_NOTIFICATION_TYPE = "de.harheimertc.extra.NOTIFICATION_TYPE"
|
||||||
|
const val EXTRA_NOTIFICATION_ROUTE = "de.harheimertc.extra.NOTIFICATION_ROUTE"
|
||||||
|
const val EXTRA_NEWS_ID = "de.harheimertc.extra.NEWS_ID"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun App() {
|
fun App(
|
||||||
|
notificationRoute: String? = null,
|
||||||
|
onNotificationRouteConsumed: () -> Unit = {},
|
||||||
|
) {
|
||||||
HarheimerTheme {
|
HarheimerTheme {
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val ctx = LocalContext.current
|
val ctx = LocalContext.current
|
||||||
val activity = ctx as? ComponentActivity
|
val activity = ctx as? ComponentActivity
|
||||||
Log.i("HILT_FACTORY", "defaultViewModelProviderFactory=${activity?.defaultViewModelProviderFactory?.javaClass?.name}")
|
Log.i("HILT_FACTORY", "defaultViewModelProviderFactory=${activity?.defaultViewModelProviderFactory?.javaClass?.name}")
|
||||||
val navigationViewModel: NavigationViewModel = hiltViewModel()
|
val navigationViewModel: NavigationViewModel = hiltViewModel()
|
||||||
|
LaunchedEffect(notificationRoute) {
|
||||||
|
val route = notificationRoute?.takeIf { it.isNotBlank() } ?: return@LaunchedEffect
|
||||||
|
navController.navigate(route) {
|
||||||
|
launchSingleTop = true
|
||||||
|
popUpTo(Destinations.Home.route)
|
||||||
|
}
|
||||||
|
onNotificationRouteConsumed()
|
||||||
|
}
|
||||||
NavGraph(navController = navController, navigationViewModelParam = navigationViewModel)
|
NavGraph(navController = navController, navigationViewModelParam = navigationViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class HarheimerMessagingService : FirebaseMessagingService() {
|
|||||||
val notificationId = message.data["notificationId"]?.toIntOrNull()
|
val notificationId = message.data["notificationId"]?.toIntOrNull()
|
||||||
?: message.messageId?.hashCode()
|
?: message.messageId?.hashCode()
|
||||||
?: System.currentTimeMillis().toInt()
|
?: System.currentTimeMillis().toInt()
|
||||||
val shown = HarheimerNotifications.showBasicNotification(this, notificationId, title, body)
|
val shown = HarheimerNotifications.showBasicNotification(this, notificationId, title, body, message.data)
|
||||||
Log.d("HarheimerMessaging", "Push message received type=${message.data["type"]}, shown=$shown")
|
Log.d("HarheimerMessaging", "Push message received type=${message.data["type"]}, shown=$shown")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ package de.harheimertc.notifications
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import de.harheimertc.MainActivity
|
||||||
import de.harheimertc.R
|
import de.harheimertc.R
|
||||||
|
import de.harheimertc.ui.navigation.Destinations
|
||||||
|
|
||||||
object HarheimerNotifications {
|
object HarheimerNotifications {
|
||||||
const val DEFAULT_CHANNEL_ID = "harheimer_tc_updates"
|
const val DEFAULT_CHANNEL_ID = "harheimer_tc_updates"
|
||||||
@@ -35,6 +39,7 @@ object HarheimerNotifications {
|
|||||||
notificationId: Int,
|
notificationId: Int,
|
||||||
title: String,
|
title: String,
|
||||||
message: String,
|
message: String,
|
||||||
|
data: Map<String, String> = emptyMap(),
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (!hasNotificationPermission(context)) return false
|
if (!hasNotificationPermission(context)) return false
|
||||||
val notification = NotificationCompat.Builder(context, DEFAULT_CHANNEL_ID)
|
val notification = NotificationCompat.Builder(context, DEFAULT_CHANNEL_ID)
|
||||||
@@ -43,9 +48,31 @@ object HarheimerNotifications {
|
|||||||
.setContentText(message)
|
.setContentText(message)
|
||||||
.setStyle(NotificationCompat.BigTextStyle().bigText(message))
|
.setStyle(NotificationCompat.BigTextStyle().bigText(message))
|
||||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
.setContentIntent(createContentIntent(context, notificationId, data))
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.build()
|
.build()
|
||||||
NotificationManagerCompat.from(context).notify(notificationId, notification)
|
NotificationManagerCompat.from(context).notify(notificationId, notification)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createContentIntent(context: Context, notificationId: Int, payload: Map<String, String>): PendingIntent {
|
||||||
|
val route = destinationRoute(payload)
|
||||||
|
val intent = Intent(context, MainActivity::class.java).apply {
|
||||||
|
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||||
|
putExtra(MainActivity.EXTRA_NOTIFICATION_TYPE, payload["type"])
|
||||||
|
putExtra(MainActivity.EXTRA_NOTIFICATION_ROUTE, route)
|
||||||
|
payload["newsId"]?.let { putExtra(MainActivity.EXTRA_NEWS_ID, it) }
|
||||||
|
}
|
||||||
|
return PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
notificationId,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun destinationRoute(data: Map<String, String>): String = when (data["type"]) {
|
||||||
|
"news" -> Destinations.MemberNews.route
|
||||||
|
else -> Destinations.Home.route
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,9 +279,25 @@ use_project_node
|
|||||||
ensure_node_version
|
ensure_node_version
|
||||||
install_dependencies_if_needed
|
install_dependencies_if_needed
|
||||||
|
|
||||||
# 4. Remove old build (but keep data!)
|
# 4. Stop running apps before replacing build artifacts
|
||||||
echo ""
|
echo ""
|
||||||
echo "4. Cleaning build artifacts..."
|
echo "4. Stopping PM2 before replacing build artifacts..."
|
||||||
|
if command -v pm2 >/dev/null 2>&1; then
|
||||||
|
for instance_name in harheimertc harheimertc-3102; do
|
||||||
|
if pm2 describe "$instance_name" >/dev/null 2>&1; then
|
||||||
|
pm2 stop "$instance_name" || true
|
||||||
|
echo " ✓ $instance_name gestoppt"
|
||||||
|
else
|
||||||
|
echo " PM2-Prozess $instance_name läuft nicht"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " PM2 ist nicht verfügbar"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Remove old build (but keep data!)
|
||||||
|
echo ""
|
||||||
|
echo "5. Cleaning build artifacts..."
|
||||||
# Sicherstellen, dass .output vollständig gelöscht wird
|
# Sicherstellen, dass .output vollständig gelöscht wird
|
||||||
if [ -d ".output" ]; then
|
if [ -d ".output" ]; then
|
||||||
echo " Removing .output directory..."
|
echo " Removing .output directory..."
|
||||||
|
|||||||
@@ -285,9 +285,19 @@ use_project_node
|
|||||||
ensure_node_version
|
ensure_node_version
|
||||||
install_dependencies_if_needed
|
install_dependencies_if_needed
|
||||||
|
|
||||||
# 4. Remove old build (but keep data!)
|
# 4. Stop running app before replacing build artifacts
|
||||||
echo ""
|
echo ""
|
||||||
echo "4. Cleaning build artifacts..."
|
echo "4. Stopping PM2 before replacing build artifacts..."
|
||||||
|
if command -v pm2 >/dev/null 2>&1 && pm2 describe harheimertc.test >/dev/null 2>&1; then
|
||||||
|
pm2 stop harheimertc.test || true
|
||||||
|
echo " ✓ harheimertc.test gestoppt"
|
||||||
|
else
|
||||||
|
echo " PM2-Prozess harheimertc.test läuft nicht oder PM2 ist nicht verfügbar"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Remove old build (but keep data!)
|
||||||
|
echo ""
|
||||||
|
echo "5. Cleaning build artifacts..."
|
||||||
# Sicherstellen, dass .output vollständig gelöscht wird
|
# Sicherstellen, dass .output vollständig gelöscht wird
|
||||||
if [ -d ".output" ]; then
|
if [ -d ".output" ]; then
|
||||||
echo " Removing .output directory..."
|
echo " Removing .output directory..."
|
||||||
|
|||||||
Reference in New Issue
Block a user