@ -7,6 +7,7 @@ import androidx.activity.compose.LocalActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity.RESULT_OK
import androidx.appcompat.app.AppCompatActivity.RESULT_OK
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.PaddingValues
@ -20,8 +21,6 @@ import androidx.compose.foundation.layout.imePadding
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.foundation.layout.systemBars
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.material3.DrawerState
import androidx.compose.material3.DrawerState
import androidx.compose.material3.Icon
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MaterialTheme
@ -44,6 +43,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.dp
import androidx.core.content.IntentCompat.getParcelableExtra
import androidx.core.content.IntentCompat.getParcelableExtra
import androidx.fragment.compose.AndroidFragment
import androidx.fragment.compose.AndroidFragment
@ -123,194 +123,183 @@ fun HomeScreen(
) {
) {
val context = LocalContext . current
val context = LocalContext . current
val scope = rememberCoroutineScope ( )
val scope = rememberCoroutineScope ( )
Box ( modifier = Modifier . fillMaxSize ( ) ) {
TaskListDrawer (
TaskListDrawer (
arrangement = if ( state . menuQuery . isBlank ( ) ) Arrangement . Top else Arrangement . Bottom ,
arrangement = if ( state . menuQuery . isBlank ( ) ) Arrangement . Top else Arrangement . Bottom ,
filters = if ( state . menuQuery . isNotEmpty ( ) ) state . searchItems else state . drawerItems ,
filters = if ( state . menuQuery . isNotEmpty ( ) ) state . searchItems else state . drawerItems ,
onClick = {
onClick = {
when ( it ) {
when ( it ) {
is DrawerItem . Filter -> {
is DrawerItem . Filter -> {
viewModel . setFilter ( it . filter )
viewModel . setFilter ( it . filter )
scope . launch {
scope . launch {
drawerState . close ( )
drawerState . close ( )
keyboard ?. hide ( )
keyboard ?. hide ( )
}
}
}
}
is DrawerItem . Header -> {
is DrawerItem . Header -> {
viewModel . toggleCollapsed ( it . header )
viewModel . toggleCollapsed ( it . header )
}
}
}
} ,
}
onAddClick = {
} ,
scope . launch {
onAddClick = {
drawerState . close ( )
scope . launch {
when ( it . header . addIntentRc ) {
drawerState . close ( )
FilterProvider . REQUEST _NEW _FILTER ->
when ( it . header . addIntentRc ) {
showNewFilterDialog ( )
FilterProvider . REQUEST _NEW _FILTER ->
showNewFilterDialog ( )
REQUEST _NEW _PLACE ->
REQUEST _NEW _PLACE ->
newList . launch ( Intent ( context , LocationPickerActivity :: class . java ) )
newList . launch ( Intent ( context , LocationPickerActivity :: class . java ) )
REQUEST _NEW _TAGS ->
REQUEST _NEW _TAGS ->
newList . launch ( Intent ( context , TagSettingsActivity :: class . java ) )
newList . launch ( Intent ( context , TagSettingsActivity :: class . java ) )
REQUEST _NEW _LIST ->
REQUEST _NEW _LIST ->
when ( it . header . subheaderType ) {
when ( it . header . subheaderType ) {
NavigationDrawerSubheader . SubheaderType . CALDAV ,
NavigationDrawerSubheader . SubheaderType . CALDAV ,
NavigationDrawerSubheader . SubheaderType . TASKS ->
NavigationDrawerSubheader . SubheaderType . TASKS ->
viewModel
viewModel
. getAccount ( it . header . id . toLong ( ) )
. getAccount ( it . header . id . toLong ( ) )
?. let {
?. let {
newList . launch (
newList . launch (
Intent ( context , it . listSettingsClass ( ) )
Intent ( context , it . listSettingsClass ( ) )
. putExtra ( EXTRA _CALDAV _ACCOUNT , it )
. putExtra ( EXTRA _CALDAV _ACCOUNT , it )
)
)
}
}
else -> { }
else -> { }
}
}
else -> Timber . e ( " Unhandled request code: $it " )
else -> Timber . e ( " Unhandled request code: $it " )
}
}
}
} ,
}
onErrorClick = {
} ,
context . startActivity ( Intent ( context , MainPreferences :: class . java ) )
onErrorClick = {
} ,
context . startActivity ( Intent ( context , MainPreferences :: class . java ) )
searchBar = {
} ,
MenuSearchBar (
searchBar = {
begForMoney = state . begForMoney ,
MenuSearchBar (
onDrawerAction = {
begForMoney = state . begForMoney ,
scope . launch {
onDrawerAction = {
drawerState . close ( )
scope . launch {
when ( it ) {
drawerState . close ( )
DrawerAction . PURCHASE ->
when ( it ) {
if ( TasksApplication . IS _GENERIC )
DrawerAction . PURCHASE ->
context . openUri ( R . string . url _donate )
if ( TasksApplication . IS _GENERIC )
else
context . openUri ( R . string . url _donate )
context . startActivity (
else
Intent (
context ,
PurchaseActivity :: class . java
)
)
DrawerAction . HELP _AND _FEEDBACK ->
context . startActivity (
context . startActivity (
Intent (
Intent (
context ,
context ,
HelpAndFeedback :: class . java
PurchaseActivity :: class . java
)
)
)
)
}
}
} ,
query = state . menuQuery ,
onQueryChange = { viewModel . queryMenu ( it ) } ,
)
} ,
)
SystemBarScrim (
DrawerAction . HELP _AND _FEEDBACK ->
modifier = Modifier
context . startActivity (
. windowInsetsTopHeight ( WindowInsets . systemBars )
Intent (
. align ( Alignment . TopCenter )
context ,
)
HelpAndFeedback :: class . java
SystemBarScrim (
)
modifier = Modifier
)
. windowInsetsBottomHeight ( WindowInsets . systemBars )
}
. align ( Alignment . BottomCenter ) ,
}
)
} ,
}
query = state . menuQuery ,
onQueryChange = { viewModel . queryMenu ( it ) } ,
)
} ,
)
}
}
}
}
) {
) {
Box ( modifier = Modifier . fillMaxSize ( ) ) {
val scope = rememberCoroutineScope ( )
val scope = rememberCoroutineScope ( )
ListDetailPaneScaffold (
directive = navigator . scaffoldDirective ,
ListDetailPaneScaffold (
value = navigator . scaffoldValue ,
directive = navigator . scaffoldDirective ,
listPane = {
value = navigator . scaffoldValue ,
key ( state . filter ) {
listPane = {
val fragment = remember { mutableStateOf < TaskListFragment ? > ( null ) }
key ( state . filter ) {
val keyboardOpen = rememberImeState ( )
val fragment = remember { mutableStateOf < TaskListFragment ? > ( null ) }
AndroidFragment < TaskListFragment > (
val keyboardOpen = rememberImeState ( )
fragmentState = rememberFragmentState ( ) ,
AndroidFragment < TaskListFragment > (
arguments = remember ( state . filter ) {
fragmentState = rememberFragmentState ( ) ,
Bundle ( )
arguments = remember ( state . filter ) {
. apply { putParcelable ( EXTRA _FILTER , state . filter ) }
Bundle ( )
} ,
. apply { putParcelable ( EXTRA _FILTER , state . filter ) }
modifier = Modifier
} ,
. fillMaxSize ( )
. imePadding ( ) ,
) { tlf ->
fragment . value = tlf
tlf . applyInsets ( windowInsets . value )
tlf . setNavigationClickListener {
scope . launch { drawerState . open ( ) }
}
}
LaunchedEffect ( fragment , windowInsets , keyboardOpen . value ) {
fragment . value ?. applyInsets (
if ( keyboardOpen . value ) {
PaddingValues (
top = windowInsets . value . calculateTopPadding ( ) ,
)
} else {
windowInsets . value
}
)
}
}
} ,
detailPane = {
val direction = LocalLayoutDirection . current
Box (
modifier = Modifier
modifier = Modifier
. fillMaxSize ( )
. fillMaxSize ( )
. padding (
. imePadding ( ) ,
top = windowInsets . value . calculateTopPadding ( ) ,
) { tlf ->
start = windowInsets . value . calculateStartPadding ( direction ) ,
fragment . value = tlf
end = windowInsets . value . calculateEndPadding ( direction ) ,
tlf . applyInsets ( windowInsets . value )
bottom = if ( rememberImeState ( ) . value )
tlf . setNavigationClickListener {
WindowInsets . ime . asPaddingValues ( ) . calculateBottomPadding ( )
scope . launch { drawerState . open ( ) }
else
}
windowInsets . value . calculateBottomPadding ( )
}
) ,
LaunchedEffect ( fragment , windowInsets , keyboardOpen . value ) {
contentAlignment = Alignment . Center ,
fragment . value ?. applyInsets (
) {
if ( keyboardOpen . value ) {
if ( state . task == null ) {
PaddingValues (
if ( isListVisible && isDetailVisible ) {
top = windowInsets . value . calculateTopPadding ( ) ,
Icon (
painter = painterResource ( org . tasks . kmp . R . drawable . ic _launcher _no _shadow _foreground ) ,
contentDescription = null ,
modifier = Modifier . size ( 192. dp ) ,
tint = MaterialTheme . colorScheme . onSurfaceVariant ,
)
}
} else {
key ( state . task ) {
AndroidFragment < TaskEditFragment > (
fragmentState = rememberFragmentState ( ) ,
arguments = remember ( state . task ) {
Bundle ( )
. apply { putParcelable ( EXTRA _TASK , state . task ) }
} ,
modifier = Modifier . fillMaxSize ( ) ,
)
)
} else {
windowInsets . value
}
}
}
)
}
}
} ,
}
)
} ,
detailPane = {
val direction = LocalLayoutDirection . current
val imeOpen = rememberImeState ( ) . value
val insets = windowInsets . value
val topPad = insets . calculateTopPadding ( )
val startPad = insets . calculateStartPadding ( direction )
val endPad = insets . calculateEndPadding ( direction )
val bottomPad = if ( imeOpen )
WindowInsets . ime . asPaddingValues ( ) . calculateBottomPadding ( )
else
insets . calculateBottomPadding ( )
SystemBarScrim (
Box (
modifier = Modifier
modifier = Modifier
. windowInsetsTopHeight ( WindowInsets . systemBars )
. fillMaxSize ( )
. align ( Alignment . TopCenter ) ,
)
. padding (
}
top = topPad ,
start = startPad ,
end = endPad ,
bottom = bottomPad
) ,
contentAlignment = Alignment . Center ,
) {
if ( state . task == null ) {
if ( isListVisible && isDetailVisible ) {
Icon (
painter = painterResource ( org . tasks . kmp . R . drawable . ic _launcher _no _shadow _foreground ) ,
contentDescription = null ,
modifier = Modifier . size ( 192. dp ) ,
tint = MaterialTheme . colorScheme . onSurfaceVariant ,
)
}
} else {
key ( state . task ) {
AndroidFragment < TaskEditFragment > (
fragmentState = rememberFragmentState ( ) ,
arguments = remember ( state . task ) {
Bundle ( )
. apply { putParcelable ( EXTRA _TASK , state . task ) }
} ,
modifier = Modifier . fillMaxSize ( ) ,
)
}
}
}
} ,
)
}
}
}
}
}
}