fixed deploy and navigation
Some checks failed
Code Analysis and Production Deploy / deploy-production (push) Has been cancelled
Code Analysis and Production Deploy / analyze (push) Has been cancelled
Code Analysis and Production Deploy / deploy-test (push) Has been cancelled

This commit is contained in:
Torsten Schulz (local)
2026-06-10 16:36:50 +02:00
parent 7e533fae49
commit 14cd5f04d5
6 changed files with 97 additions and 8 deletions

View File

@@ -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" />

View File

@@ -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)
} }
} }

View File

@@ -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")
} }
} }

View File

@@ -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
}
} }

View File

@@ -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..."

View File

@@ -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..."