mirror of
https://github.com/wismna/DoNext.git
synced 2025-12-06 00:02:40 -05:00
Compare commits
2 Commits
2962c459d1
...
4e2f3c720c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e2f3c720c | ||
|
|
571b82dc98 |
@@ -51,22 +51,23 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.4")
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.4")
|
||||||
implementation("androidx.activity:activity-compose:1.11.0")
|
implementation("androidx.activity:activity-compose:1.11.0")
|
||||||
implementation(platform("androidx.compose:compose-bom:2025.09.01"))
|
implementation(platform("androidx.compose:compose-bom:2025.10.00"))
|
||||||
implementation("androidx.compose.ui:ui")
|
implementation("androidx.compose.ui:ui")
|
||||||
implementation("androidx.compose.ui:ui-graphics")
|
implementation("androidx.compose.ui:ui-graphics")
|
||||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||||
implementation("androidx.compose.material3:material3")
|
implementation("androidx.compose.material3:material3")
|
||||||
|
implementation("androidx.compose.material3:material3-window-size-class:1.4.0")
|
||||||
implementation("androidx.compose.material:material-icons-extended:1.7.8")
|
implementation("androidx.compose.material:material-icons-extended:1.7.8")
|
||||||
implementation("androidx.navigation:navigation-compose:2.9.5")
|
implementation("androidx.navigation:navigation-compose:2.9.5")
|
||||||
implementation("androidx.hilt:hilt-navigation-compose:1.3.0")
|
implementation("androidx.hilt:hilt-navigation-compose:1.3.0")
|
||||||
implementation("androidx.test.ext:junit-ktx:1.3.0")
|
implementation("androidx.test.ext:junit-ktx:1.3.0")
|
||||||
implementation("sh.calvin.reorderable:reorderable:3.0.0")
|
implementation("sh.calvin.reorderable:reorderable:3.0.0")
|
||||||
androidTestImplementation(platform("androidx.compose:compose-bom:2025.09.01"))
|
androidTestImplementation(platform("androidx.compose:compose-bom:2025.10.00"))
|
||||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||||
|
|
||||||
val roomVersion = "2.8.1"
|
val roomVersion = "2.8.2"
|
||||||
implementation("androidx.room:room-runtime:$roomVersion")
|
implementation("androidx.room:room-runtime:$roomVersion")
|
||||||
ksp("androidx.room:room-compiler:$roomVersion")
|
ksp("androidx.room:room-compiler:$roomVersion")
|
||||||
|
|
||||||
|
|||||||
@@ -40,11 +40,24 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
db.execSQL("ALTER TABLE tasks ADD COLUMN duedate_temp INTEGER")
|
db.execSQL("ALTER TABLE tasks ADD COLUMN duedate_temp INTEGER")
|
||||||
// Populate temporary column
|
// Populate temporary column
|
||||||
db.execSQL("""
|
db.execSQL("""
|
||||||
|
WITH offset AS (
|
||||||
|
SELECT (strftime('%s', 'now', 'localtime') - strftime('%s', 'now')) / 3600.0 AS diff
|
||||||
|
)
|
||||||
UPDATE tasks
|
UPDATE tasks
|
||||||
SET duedate_temp =
|
SET duedate_temp =
|
||||||
CASE
|
CASE
|
||||||
WHEN duedate IS NULL OR duedate = '' THEN NULL
|
WHEN duedate IS NULL OR duedate = '' THEN NULL
|
||||||
ELSE (strftime('%s', duedate || 'T00:00:00Z') * 1000)
|
ELSE (
|
||||||
|
strftime(
|
||||||
|
'%s',
|
||||||
|
duedate || ' 00:00:00',
|
||||||
|
CASE
|
||||||
|
WHEN (SELECT diff FROM offset) >= 0
|
||||||
|
THEN '-' || (SELECT diff FROM offset) || ' hours'
|
||||||
|
ELSE '+' || abs((SELECT diff FROM offset)) || ' hours'
|
||||||
|
END
|
||||||
|
) * 1000
|
||||||
|
)
|
||||||
END
|
END
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,21 @@ import androidx.activity.ComponentActivity
|
|||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
|
||||||
|
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
|
||||||
import com.wismna.geoffroy.donext.presentation.screen.MainScreen
|
import com.wismna.geoffroy.donext.presentation.screen.MainScreen
|
||||||
import com.wismna.geoffroy.donext.presentation.ui.theme.DoNextTheme
|
import com.wismna.geoffroy.donext.presentation.ui.theme.DoNextTheme
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
DoNextTheme(darkTheme = isSystemInDarkTheme(), dynamicColor = false) { MainScreen() }
|
val windowSizeClass = calculateWindowSizeClass(this)
|
||||||
|
DoNextTheme(darkTheme = isSystemInDarkTheme(), dynamicColor = false) { MainScreen(windowSizeClass) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
package com.wismna.geoffroy.donext.presentation.screen
|
package com.wismna.geoffroy.donext.presentation.screen
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.slideInHorizontally
|
import androidx.compose.animation.slideInHorizontally
|
||||||
import androidx.compose.animation.slideOutHorizontally
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
@@ -24,6 +25,7 @@ import androidx.compose.material3.IconButton
|
|||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ModalNavigationDrawer
|
import androidx.compose.material3.ModalNavigationDrawer
|
||||||
|
import androidx.compose.material3.PermanentNavigationDrawer
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SnackbarDuration
|
import androidx.compose.material3.SnackbarDuration
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
@@ -34,6 +36,8 @@ import androidx.compose.material3.Text
|
|||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.rememberDrawerState
|
import androidx.compose.material3.rememberDrawerState
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowSizeClass
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -44,6 +48,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
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.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
@@ -62,10 +67,10 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainScreen(
|
fun MainScreen(
|
||||||
|
windowSizeClass: WindowSizeClass,
|
||||||
viewModel: MainViewModel = hiltViewModel()
|
viewModel: MainViewModel = hiltViewModel()
|
||||||
) {
|
) {
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val drawerState = rememberDrawerState(DrawerValue.Closed)
|
|
||||||
|
|
||||||
if (viewModel.isLoading) {
|
if (viewModel.isLoading) {
|
||||||
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
@@ -84,13 +89,36 @@ fun MainScreen(
|
|||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
viewModel.setCurrentDestination(navBackStackEntry)
|
viewModel.setCurrentDestination(navBackStackEntry)
|
||||||
|
|
||||||
|
val isExpandedScreen = windowSizeClass.widthSizeClass >= WindowWidthSizeClass.Medium
|
||||||
|
val orientation = LocalConfiguration.current.orientation
|
||||||
|
val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
val showPermanentDrawer = isExpandedScreen || isLandscape
|
||||||
|
|
||||||
|
if (showPermanentDrawer) {
|
||||||
|
PermanentNavigationDrawer(
|
||||||
|
drawerContent = {
|
||||||
|
MenuScreen(currentDestination = viewModel.currentDestination)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
AppContent(
|
||||||
|
viewModel = viewModel,
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val drawerState = rememberDrawerState(DrawerValue.Closed)
|
||||||
ModalNavigationDrawer(
|
ModalNavigationDrawer(
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
MenuScreen(currentDestination = viewModel.currentDestination)
|
MenuScreen(currentDestination = viewModel.currentDestination)
|
||||||
},
|
},
|
||||||
drawerState = drawerState
|
drawerState = drawerState
|
||||||
) {
|
) {
|
||||||
AppContent(viewModel = viewModel, navController = navController, drawerState = drawerState)
|
AppContent(
|
||||||
|
viewModel = viewModel,
|
||||||
|
navController = navController,
|
||||||
|
drawerState = drawerState
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +127,7 @@ fun AppContent(
|
|||||||
modifier : Modifier = Modifier,
|
modifier : Modifier = Modifier,
|
||||||
viewModel: MainViewModel,
|
viewModel: MainViewModel,
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
drawerState: DrawerState
|
drawerState: DrawerState? = null
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
@@ -108,7 +136,7 @@ fun AppContent(
|
|||||||
viewModel.uiEventBus.events.collectLatest { event ->
|
viewModel.uiEventBus.events.collectLatest { event ->
|
||||||
when (event) {
|
when (event) {
|
||||||
is UiEvent.Navigate -> {
|
is UiEvent.Navigate -> {
|
||||||
drawerState.close()
|
drawerState?.close()
|
||||||
navController.navigate(event.route)
|
navController.navigate(event.route)
|
||||||
}
|
}
|
||||||
is UiEvent.NavigateBack -> navController.popBackStack()
|
is UiEvent.NavigateBack -> navController.popBackStack()
|
||||||
@@ -140,10 +168,14 @@ fun AppContent(
|
|||||||
actionIconContentColor = MaterialTheme.colorScheme.onPrimaryContainer
|
actionIconContentColor = MaterialTheme.colorScheme.onPrimaryContainer
|
||||||
),
|
),
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
if (drawerState != null) {
|
||||||
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onPrimaryContainer) {
|
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onPrimaryContainer) {
|
||||||
if (viewModel.currentDestination.showBackButton) {
|
if (viewModel.currentDestination.showBackButton) {
|
||||||
IconButton(onClick = { viewModel.navigateBack() }) {
|
IconButton(onClick = { viewModel.navigateBack() }) {
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
Icon(
|
||||||
|
Icons.AutoMirrored.Default.ArrowBack,
|
||||||
|
contentDescription = "Back"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IconButton(onClick = { scope.launch { drawerState.open() } }) {
|
IconButton(onClick = { scope.launch { drawerState.open() } }) {
|
||||||
@@ -154,6 +186,7 @@ fun AppContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
when (viewModel.currentDestination) {
|
when (viewModel.currentDestination) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ fun MenuScreen(
|
|||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = "Task Lists",
|
text = "DoNext v2",
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier.padding(16.dp)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user