Compare commits

..

2 Commits

Author SHA1 Message Date
9082f15b63 通知更新 2025-10-20 22:57:32 +08:00
1ac177be8b 主视图优化 2025-10-20 22:57:32 +08:00
10 changed files with 52 additions and 60 deletions

View File

@@ -16,18 +16,25 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge() enableEdgeToEdge()
// 设置全屏显示 // 设置全屏显示
WindowCompat.setDecorFitsSystemWindows(window, true) WindowCompat.setDecorFitsSystemWindows(window, false)
// 设置状态栏图标颜色 // 设置状态栏图标颜色
val windowInsetsController = WindowInsetsControllerCompat(window, window.decorView) val controller = WindowInsetsControllerCompat(window, window.decorView)
// windowInsetsController.hide(WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.navigationBars()) // windowInsetsController.hide(WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.navigationBars())
// windowInsetsController.systemBarsBehavior = // windowInsetsController.systemBarsBehavior =
// WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// 显示状态栏和导航栏
// controller.show(WindowInsetsCompat.Type.systemBars())
// 设置系统栏行为:用户上滑时再显示(可选)
// controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_DEFAULT
// 使用系统原生方法检测暗色主题 // 使用系统原生方法检测暗色主题
val isDarkTheme = resources.configuration.uiMode and val isDarkTheme = resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
windowInsetsController.isAppearanceLightStatusBars = !isDarkTheme controller.isAppearanceLightStatusBars = isDarkTheme
controller.isAppearanceLightNavigationBars = isDarkTheme
setContent { setContent {
App() App()

View File

@@ -3,7 +3,7 @@ package com.taskttl.core.alarm
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import com.taskttl.core.notification.NotificationManager import com.taskttl.core.notification.AppNotificationManager
import com.taskttl.core.notification.NotificationPayload import com.taskttl.core.notification.NotificationPayload
import com.taskttl.core.notification.NotificationRepeatType import com.taskttl.core.notification.NotificationRepeatType
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -20,7 +20,7 @@ class AlarmReceiver : BroadcastReceiver() {
// 使用协程调用统一通知方法 // 使用协程调用统一通知方法
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
NotificationManager.scheduleNotification( AppNotificationManager.scheduleNotification(
NotificationPayload( NotificationPayload(
id = id, id = id,
title = title, title = title,
@@ -30,38 +30,5 @@ class AlarmReceiver : BroadcastReceiver() {
) )
) )
} }
// val id = intent.getStringExtra("id") ?: return
// val title = intent.getStringExtra("title") ?: "TaskTTL"
// val message = intent.getStringExtra("message") ?: ""
//
// val channelId = "taskttl_channel"
//
// // 确保通道存在
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager
// if (nm.getNotificationChannel(channelId) == null) {
// val channel = android.app.NotificationChannel(
// channelId,
// "TaskTTL Notifications",
// android.app.NotificationManager.IMPORTANCE_HIGH
// )
// channel.description = "TaskTTL 提醒通知"
// nm.createNotificationChannel(channel)
// }
// }
//
// // 构建通知
// val builder = NotificationCompat.Builder(context, channelId)
// .setContentTitle(title)
// .setContentText(message)
// .setSmallIcon(R.mipmap.ic_launcher)
// .setAutoCancel(true)
// .setPriority(NotificationCompat.PRIORITY_HIGH)
//
// val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager
// nm.notify(id.hashCode(), builder.build())
} }
} }

View File

@@ -3,6 +3,7 @@ package com.taskttl.core.notification
import android.Manifest import android.Manifest
import android.app.Activity import android.app.Activity
import android.app.AlarmManager import android.app.AlarmManager
import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@@ -12,7 +13,11 @@ import android.os.Build
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.work.* import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.taskttl.MainApplication import com.taskttl.MainApplication
import com.taskttl.R import com.taskttl.R
import com.taskttl.core.alarm.AlarmReceiver import com.taskttl.core.alarm.AlarmReceiver
@@ -20,7 +25,7 @@ import com.taskttl.core.utils.LogUtils
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.math.max import kotlin.math.max
actual object NotificationManager { actual object AppNotificationManager {
private val channelId = "taskttl_channel" private val channelId = "taskttl_channel"
@@ -35,13 +40,14 @@ actual object NotificationManager {
private fun setupNotificationChannel() { private fun setupNotificationChannel() {
val activity = MainApplication.currentActivity() ?: return val activity = MainApplication.currentActivity() ?: return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val nm = activity.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager val nm =
activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (nm.getNotificationChannel(channelId) == null) { if (nm.getNotificationChannel(channelId) == null) {
val channel = android.app.NotificationChannel( val channel = android.app.NotificationChannel(
channelId, channelId,
"TaskTTL Notifications", "TaskTTL Notifications",
android.app.NotificationManager.IMPORTANCE_HIGH NotificationManager.IMPORTANCE_HIGH
).apply { description = "TaskTTL 提醒通知" } )
nm.createNotificationChannel(channel) nm.createNotificationChannel(channel)
LogUtils.d("DevTTL_NotificationTest", "Notification channel created") LogUtils.d("DevTTL_NotificationTest", "Notification channel created")
} }
@@ -137,7 +143,8 @@ actual object NotificationManager {
else -> 24 * 60 * 60 * 1000L else -> 24 * 60 * 60 * 1000L
} }
val request = PeriodicWorkRequestBuilder<NotificationWorker>(interval, TimeUnit.MILLISECONDS) val request =
PeriodicWorkRequestBuilder<NotificationWorker>(interval, TimeUnit.MILLISECONDS)
.setInputData(data) .setInputData(data)
.addTag(payload.id) .addTag(payload.id)
.build() .build()
@@ -153,7 +160,8 @@ actual object NotificationManager {
/** 立即显示通知 */ /** 立即显示通知 */
private fun showImmediateNotification(payload: NotificationPayload) { private fun showImmediateNotification(payload: NotificationPayload) {
val activity = getActivity() val activity = getActivity()
val nm = activity.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager val nm =
activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notification = NotificationCompat.Builder(activity, channelId) val notification = NotificationCompat.Builder(activity, channelId)
.setContentTitle(payload.title) .setContentTitle(payload.title)
@@ -184,14 +192,16 @@ actual object NotificationManager {
) )
alarmManager.cancel(pendingIntent) alarmManager.cancel(pendingIntent)
val nm = activity.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager val nm =
activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
nm.cancel(id.hashCode()) nm.cancel(id.hashCode())
} }
actual suspend fun cancelAll() { actual suspend fun cancelAll() {
val activity = getActivity() val activity = getActivity()
WorkManager.getInstance(activity).cancelAllWork() WorkManager.getInstance(activity).cancelAllWork()
val nm = activity.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager val nm =
activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
nm.cancelAll() nm.cancelAll()
} }
} }

View File

@@ -1,5 +1,6 @@
package com.taskttl.core.notification package com.taskttl.core.notification
import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@@ -48,7 +49,7 @@ class NotificationWorker(
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)
val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
nm.notify(id.hashCode(), builder.build()) nm.notify(id.hashCode(), builder.build())
} }
} }

View File

@@ -4,9 +4,9 @@ package com.taskttl.core.notification
* 通知管理器 * 通知管理器
* @author admin * @author admin
* @date 2025/10/16 * @date 2025/10/16
* @constructor 创建[NotificationManager] * @constructor 创建[AppNotificationManager]
*/ */
expect object NotificationManager { expect object AppNotificationManager {
/** /**
* 日程通知 * 日程通知
* @param [payload] 有效载荷 * @param [payload] 有效载荷

View File

@@ -1,7 +1,9 @@
package com.taskttl.core.routes package com.taskttl.core.routes
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.List import androidx.compose.material.icons.automirrored.filled.List
@@ -14,6 +16,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.navigation.NavDestination.Companion.hasRoute import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
@@ -22,12 +25,12 @@ import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute import androidx.navigation.toRoute
import com.taskttl.core.routes.Routes.Main import com.taskttl.core.routes.Routes.Main
import com.taskttl.core.ui.CustomBottomBar import com.taskttl.core.ui.CustomBottomBar
import com.taskttl.presentation.category.CategoryEditScreen
import com.taskttl.presentation.category.CategoryScreen
import com.taskttl.presentation.countdown.CountdownDetailScreen import com.taskttl.presentation.countdown.CountdownDetailScreen
import com.taskttl.presentation.countdown.CountdownEditScreen import com.taskttl.presentation.countdown.CountdownEditScreen
import com.taskttl.presentation.countdown.CountdownScreen import com.taskttl.presentation.countdown.CountdownScreen
import com.taskttl.presentation.settings.AboutScreen import com.taskttl.presentation.settings.AboutScreen
import com.taskttl.presentation.category.CategoryEditScreen
import com.taskttl.presentation.category.CategoryScreen
import com.taskttl.presentation.settings.DataManagementScreen import com.taskttl.presentation.settings.DataManagementScreen
import com.taskttl.presentation.settings.FeedbackScreen import com.taskttl.presentation.settings.FeedbackScreen
import com.taskttl.presentation.settings.PrivacyScreen import com.taskttl.presentation.settings.PrivacyScreen
@@ -61,7 +64,8 @@ fun MainNav() {
val currentDestination by mainNavController.currentBackStackEntryAsState() val currentDestination by mainNavController.currentBackStackEntryAsState()
Scaffold( Scaffold(
modifier = Modifier.background(Color(0xffF9F9F9)), modifier = Modifier.fillMaxSize().background(Color(0xffF9F9F9)),
contentWindowInsets = WindowInsets(0.dp),
bottomBar = { bottomBar = {
CustomBottomBar( CustomBottomBar(
bottomItems = bottomItems, bottomItems = bottomItems,
@@ -80,7 +84,8 @@ fun MainNav() {
} }
) { paddingValues -> ) { paddingValues ->
NavHost( NavHost(
modifier = Modifier.fillMaxSize().padding(paddingValues), modifier = Modifier.fillMaxSize()
.padding(bottom = paddingValues.calculateBottomPadding()),
navController = mainNavController, navController = mainNavController,
startDestination = Main.Task startDestination = Main.Task
) { ) {

View File

@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -42,7 +43,7 @@ fun CustomBottomBar(
val barHeight = 56.dp val barHeight = 56.dp
Box( Box(
modifier = Modifier.fillMaxWidth().height(barHeight) modifier = Modifier.navigationBarsPadding().fillMaxWidth().height(barHeight)
.background(MaterialTheme.colorScheme.background) .background(MaterialTheme.colorScheme.background)
) { ) {
Row( Row(

View File

@@ -1,6 +1,5 @@
package com.taskttl.data.di package com.taskttl.data.di
import com.taskttl.core.notification.NotificationManager
import com.taskttl.data.repository.OnboardingRepository import com.taskttl.data.repository.OnboardingRepository
import com.taskttl.data.repository.SettingsRepository import com.taskttl.data.repository.SettingsRepository
import com.taskttl.data.repository.impl.OnboardingRepositoryImpl import com.taskttl.data.repository.impl.OnboardingRepositoryImpl

View File

@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -53,6 +54,7 @@ fun AppHeader(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.background(brush = gradient) .background(brush = gradient)
.statusBarsPadding()
.padding(horizontal = 20.dp, vertical = 15.dp), .padding(horizontal = 20.dp, vertical = 15.dp),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically

View File

@@ -2,7 +2,7 @@ package com.taskttl.core.notification
import platform.UserNotifications.* import platform.UserNotifications.*
actual class NotificationManager { actual object AppNotificationManager {
actual suspend fun scheduleNotification(payload: NotificationPayload) { actual suspend fun scheduleNotification(payload: NotificationPayload) {
val content = UNMutableNotificationContent().apply { val content = UNMutableNotificationContent().apply {
title = payload.title title = payload.title