Merge pull request 'Notificaciones push, auto-update, admin panel v1.1.0' (#23) from feat/android-app-redesign into master
Reviewed-on: #23 Reviewed-by: rafaga21 <rafaelminaya20@hotmail.com>
This commit was merged in pull request #23.
This commit is contained in:
@@ -12,8 +12,8 @@ android {
|
|||||||
applicationId = "com.devlab.app"
|
applicationId = "com.devlab.app"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 37
|
targetSdk = 37
|
||||||
versionCode = 1
|
versionCode = 2
|
||||||
versionName = "1.0.0"
|
versionName = "1.1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -107,10 +107,17 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppRoot() {
|
fun AppRoot() {
|
||||||
|
val context = androidx.compose.ui.platform.LocalContext.current
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val loginViewModel: LoginViewModel = viewModel()
|
val loginViewModel: LoginViewModel = viewModel()
|
||||||
var isLoggedIn by remember { mutableStateOf(false) }
|
var isLoggedIn by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
LaunchedEffect(isLoggedIn) {
|
||||||
|
if (isLoggedIn) {
|
||||||
|
NotificationWorker.checkNow(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
val currentDestination = navBackStackEntry?.destination
|
val currentDestination = navBackStackEntry?.destination
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.devlab.app.worker
|
package com.devlab.app.worker
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import com.devlab.app.data.api.RetrofitClient
|
import com.devlab.app.data.api.RetrofitClient
|
||||||
import com.devlab.app.data.model.AppNotification
|
import com.devlab.app.data.model.AppNotification
|
||||||
@@ -21,37 +22,51 @@ class NotificationWorker(
|
|||||||
val token = prefs.getToken()
|
val token = prefs.getToken()
|
||||||
|
|
||||||
if (token.isBlank()) {
|
if (token.isBlank()) {
|
||||||
|
Log.d("NotificationWorker", "No token, skipping")
|
||||||
return@withContext Result.success()
|
return@withContext Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
val lastCheck = prefs.getLastNotificationCheck()
|
val lastCheck = prefs.getLastNotificationCheck()
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
|
||||||
|
Log.d("NotificationWorker", "Checking notifications since $lastCheck")
|
||||||
|
|
||||||
RetrofitClient.setToken(token)
|
RetrofitClient.setToken(token)
|
||||||
val service = RetrofitClient.getApiService()
|
val service = RetrofitClient.getApiService()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val response = service.getNotifications(page = 1, perPage = 50)
|
val response = service.getNotifications(page = 1, perPage = 50)
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
|
Log.d("NotificationWorker", "Got ${response.data.size} notifications, unread: ${response.unread_count}")
|
||||||
|
|
||||||
val newNotifications = response.data.filter { note ->
|
val newNotifications = response.data.filter { note ->
|
||||||
val noteTime = parseTime(note.created_at)
|
val noteTime = parseTime(note.created_at)
|
||||||
noteTime > lastCheck && note.is_read == 0
|
noteTime > lastCheck && note.is_read == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d("NotificationWorker", "New notifications to show: ${newNotifications.size}")
|
||||||
|
|
||||||
for (notification in newNotifications) {
|
for (notification in newNotifications) {
|
||||||
NotificationHelper.showNotification(applicationContext, notification)
|
NotificationHelper.showNotification(applicationContext, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
val lastTime = newNotifications.maxOfOrNull {
|
val maxTime = newNotifications.maxOfOrNull {
|
||||||
parseTime(it.created_at)
|
parseTime(it.created_at)
|
||||||
} ?: System.currentTimeMillis()
|
} ?: now
|
||||||
|
|
||||||
prefs.setLastNotificationCheck(
|
prefs.setLastNotificationCheck(
|
||||||
if (newNotifications.isNotEmpty()) lastTime else System.currentTimeMillis()
|
if (newNotifications.isNotEmpty()) maxTime else now
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
Log.d("NotificationWorker", "API returned success=false: ${response.error}")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("NotificationWorker", "API error: ${e.message}")
|
||||||
}
|
}
|
||||||
} catch (_: Exception) { }
|
|
||||||
|
|
||||||
Result.success()
|
Result.success()
|
||||||
} catch (_: Exception) {
|
} catch (e: Exception) {
|
||||||
|
Log.e("NotificationWorker", "Worker error: ${e.message}")
|
||||||
Result.retry()
|
Result.retry()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,9 +103,10 @@ class NotificationWorker(
|
|||||||
|
|
||||||
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
|
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
|
||||||
WORK_NAME,
|
WORK_NAME,
|
||||||
ExistingPeriodicWorkPolicy.KEEP,
|
ExistingPeriodicWorkPolicy.UPDATE,
|
||||||
request
|
request
|
||||||
)
|
)
|
||||||
|
Log.d("NotificationWorker", "Scheduled periodic check every 15 min")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkNow(context: Context) {
|
fun checkNow(context: Context) {
|
||||||
@@ -103,6 +119,7 @@ class NotificationWorker(
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
WorkManager.getInstance(context).enqueue(request)
|
WorkManager.getInstance(context).enqueue(request)
|
||||||
|
Log.d("NotificationWorker", "Scheduled immediate check")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -469,7 +469,17 @@ class ApiController
|
|||||||
public function appVersion(): void
|
public function appVersion(): void
|
||||||
{
|
{
|
||||||
$db = \ServerManager\Core\Database::getInstance();
|
$db = \ServerManager\Core\Database::getInstance();
|
||||||
|
|
||||||
|
try {
|
||||||
$configs = $db->fetchAll('SELECT * FROM app_config');
|
$configs = $db->fetchAll('SELECT * FROM app_config');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->view->json([
|
||||||
|
'success' => false,
|
||||||
|
'error' => 'Database error',
|
||||||
|
], 500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$config = [];
|
$config = [];
|
||||||
foreach ($configs as $row) {
|
foreach ($configs as $row) {
|
||||||
$config[$row['key']] = $row['value'];
|
$config[$row['key']] = $row['value'];
|
||||||
|
|||||||
Reference in New Issue
Block a user