|
|
|
|
@ -20,6 +20,8 @@ import androidx.compose.foundation.layout.imePadding
|
|
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
|
|
import androidx.compose.foundation.layout.size
|
|
|
|
|
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.Icon
|
|
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
|
|
@ -121,173 +123,194 @@ fun HomeScreen(
|
|
|
|
|
) {
|
|
|
|
|
val context = LocalContext.current
|
|
|
|
|
val scope = rememberCoroutineScope()
|
|
|
|
|
TaskListDrawer(
|
|
|
|
|
arrangement = if (state.menuQuery.isBlank()) Arrangement.Top else Arrangement.Bottom,
|
|
|
|
|
filters = if (state.menuQuery.isNotEmpty()) state.searchItems else state.drawerItems,
|
|
|
|
|
onClick = {
|
|
|
|
|
when (it) {
|
|
|
|
|
is DrawerItem.Filter -> {
|
|
|
|
|
viewModel.setFilter(it.filter)
|
|
|
|
|
scope.launch {
|
|
|
|
|
drawerState.close()
|
|
|
|
|
keyboard?.hide()
|
|
|
|
|
Box(modifier = Modifier.fillMaxSize()) {
|
|
|
|
|
TaskListDrawer(
|
|
|
|
|
arrangement = if (state.menuQuery.isBlank()) Arrangement.Top else Arrangement.Bottom,
|
|
|
|
|
filters = if (state.menuQuery.isNotEmpty()) state.searchItems else state.drawerItems,
|
|
|
|
|
onClick = {
|
|
|
|
|
when (it) {
|
|
|
|
|
is DrawerItem.Filter -> {
|
|
|
|
|
viewModel.setFilter(it.filter)
|
|
|
|
|
scope.launch {
|
|
|
|
|
drawerState.close()
|
|
|
|
|
keyboard?.hide()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
is DrawerItem.Header -> {
|
|
|
|
|
viewModel.toggleCollapsed(it.header)
|
|
|
|
|
is DrawerItem.Header -> {
|
|
|
|
|
viewModel.toggleCollapsed(it.header)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onAddClick = {
|
|
|
|
|
scope.launch {
|
|
|
|
|
drawerState.close()
|
|
|
|
|
when (it.header.addIntentRc) {
|
|
|
|
|
FilterProvider.REQUEST_NEW_FILTER ->
|
|
|
|
|
showNewFilterDialog()
|
|
|
|
|
},
|
|
|
|
|
onAddClick = {
|
|
|
|
|
scope.launch {
|
|
|
|
|
drawerState.close()
|
|
|
|
|
when (it.header.addIntentRc) {
|
|
|
|
|
FilterProvider.REQUEST_NEW_FILTER ->
|
|
|
|
|
showNewFilterDialog()
|
|
|
|
|
|
|
|
|
|
REQUEST_NEW_PLACE ->
|
|
|
|
|
newList.launch(Intent(context, LocationPickerActivity::class.java))
|
|
|
|
|
REQUEST_NEW_PLACE ->
|
|
|
|
|
newList.launch(Intent(context, LocationPickerActivity::class.java))
|
|
|
|
|
|
|
|
|
|
REQUEST_NEW_TAGS ->
|
|
|
|
|
newList.launch(Intent(context, TagSettingsActivity::class.java))
|
|
|
|
|
REQUEST_NEW_TAGS ->
|
|
|
|
|
newList.launch(Intent(context, TagSettingsActivity::class.java))
|
|
|
|
|
|
|
|
|
|
REQUEST_NEW_LIST ->
|
|
|
|
|
when (it.header.subheaderType) {
|
|
|
|
|
NavigationDrawerSubheader.SubheaderType.CALDAV,
|
|
|
|
|
NavigationDrawerSubheader.SubheaderType.TASKS ->
|
|
|
|
|
viewModel
|
|
|
|
|
.getAccount(it.header.id.toLong())
|
|
|
|
|
?.let {
|
|
|
|
|
newList.launch(
|
|
|
|
|
Intent(context, it.listSettingsClass())
|
|
|
|
|
.putExtra(EXTRA_CALDAV_ACCOUNT, it)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
REQUEST_NEW_LIST ->
|
|
|
|
|
when (it.header.subheaderType) {
|
|
|
|
|
NavigationDrawerSubheader.SubheaderType.CALDAV,
|
|
|
|
|
NavigationDrawerSubheader.SubheaderType.TASKS ->
|
|
|
|
|
viewModel
|
|
|
|
|
.getAccount(it.header.id.toLong())
|
|
|
|
|
?.let {
|
|
|
|
|
newList.launch(
|
|
|
|
|
Intent(context, it.listSettingsClass())
|
|
|
|
|
.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))
|
|
|
|
|
},
|
|
|
|
|
searchBar = {
|
|
|
|
|
MenuSearchBar(
|
|
|
|
|
begForMoney = state.begForMoney,
|
|
|
|
|
onDrawerAction = {
|
|
|
|
|
scope.launch {
|
|
|
|
|
drawerState.close()
|
|
|
|
|
when (it) {
|
|
|
|
|
DrawerAction.PURCHASE ->
|
|
|
|
|
if (TasksApplication.IS_GENERIC)
|
|
|
|
|
context.openUri(R.string.url_donate)
|
|
|
|
|
else
|
|
|
|
|
},
|
|
|
|
|
onErrorClick = {
|
|
|
|
|
context.startActivity(Intent(context, MainPreferences::class.java))
|
|
|
|
|
},
|
|
|
|
|
searchBar = {
|
|
|
|
|
MenuSearchBar(
|
|
|
|
|
begForMoney = state.begForMoney,
|
|
|
|
|
onDrawerAction = {
|
|
|
|
|
scope.launch {
|
|
|
|
|
drawerState.close()
|
|
|
|
|
when (it) {
|
|
|
|
|
DrawerAction.PURCHASE ->
|
|
|
|
|
if (TasksApplication.IS_GENERIC)
|
|
|
|
|
context.openUri(R.string.url_donate)
|
|
|
|
|
else
|
|
|
|
|
context.startActivity(
|
|
|
|
|
Intent(
|
|
|
|
|
context,
|
|
|
|
|
PurchaseActivity::class.java
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
DrawerAction.HELP_AND_FEEDBACK ->
|
|
|
|
|
context.startActivity(
|
|
|
|
|
Intent(
|
|
|
|
|
context,
|
|
|
|
|
PurchaseActivity::class.java
|
|
|
|
|
HelpAndFeedback::class.java
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
DrawerAction.HELP_AND_FEEDBACK ->
|
|
|
|
|
context.startActivity(
|
|
|
|
|
Intent(
|
|
|
|
|
context,
|
|
|
|
|
HelpAndFeedback::class.java
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
query = state.menuQuery,
|
|
|
|
|
onQueryChange = { viewModel.queryMenu(it) },
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
query = state.menuQuery,
|
|
|
|
|
onQueryChange = { viewModel.queryMenu(it) },
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
SystemBarScrim(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.windowInsetsTopHeight(WindowInsets.systemBars)
|
|
|
|
|
.align(Alignment.TopCenter)
|
|
|
|
|
)
|
|
|
|
|
SystemBarScrim(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.windowInsetsBottomHeight(WindowInsets.systemBars)
|
|
|
|
|
.align(Alignment.BottomCenter),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
val scope = rememberCoroutineScope()
|
|
|
|
|
ListDetailPaneScaffold(
|
|
|
|
|
directive = navigator.scaffoldDirective,
|
|
|
|
|
value = navigator.scaffoldValue,
|
|
|
|
|
listPane = {
|
|
|
|
|
key (state.filter) {
|
|
|
|
|
val fragment = remember { mutableStateOf<TaskListFragment?>(null) }
|
|
|
|
|
val keyboardOpen = rememberImeState()
|
|
|
|
|
AndroidFragment<TaskListFragment>(
|
|
|
|
|
fragmentState = rememberFragmentState(),
|
|
|
|
|
arguments = remember(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() }
|
|
|
|
|
Box(modifier = Modifier.fillMaxSize()) {
|
|
|
|
|
val scope = rememberCoroutineScope()
|
|
|
|
|
ListDetailPaneScaffold(
|
|
|
|
|
directive = navigator.scaffoldDirective,
|
|
|
|
|
value = navigator.scaffoldValue,
|
|
|
|
|
listPane = {
|
|
|
|
|
key (state.filter) {
|
|
|
|
|
val fragment = remember { mutableStateOf<TaskListFragment?>(null) }
|
|
|
|
|
val keyboardOpen = rememberImeState()
|
|
|
|
|
AndroidFragment<TaskListFragment>(
|
|
|
|
|
fragmentState = rememberFragmentState(),
|
|
|
|
|
arguments = remember(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
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LaunchedEffect(fragment, windowInsets, keyboardOpen.value) {
|
|
|
|
|
fragment.value?.applyInsets(
|
|
|
|
|
if (keyboardOpen.value) {
|
|
|
|
|
PaddingValues(
|
|
|
|
|
top = windowInsets.value.calculateTopPadding(),
|
|
|
|
|
},
|
|
|
|
|
detailPane = {
|
|
|
|
|
val direction = LocalLayoutDirection.current
|
|
|
|
|
Box(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
.padding(
|
|
|
|
|
top = windowInsets.value.calculateTopPadding(),
|
|
|
|
|
start = windowInsets.value.calculateStartPadding(direction),
|
|
|
|
|
end = windowInsets.value.calculateEndPadding(direction),
|
|
|
|
|
bottom = if (rememberImeState().value)
|
|
|
|
|
WindowInsets.ime.asPaddingValues().calculateBottomPadding()
|
|
|
|
|
else
|
|
|
|
|
windowInsets.value.calculateBottomPadding()
|
|
|
|
|
),
|
|
|
|
|
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(),
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
windowInsets.value
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
detailPane = {
|
|
|
|
|
val direction = LocalLayoutDirection.current
|
|
|
|
|
Box(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
.padding(
|
|
|
|
|
top = windowInsets.value.calculateTopPadding(),
|
|
|
|
|
start = windowInsets.value.calculateStartPadding(direction),
|
|
|
|
|
end = windowInsets.value.calculateEndPadding(direction),
|
|
|
|
|
bottom = if (rememberImeState().value)
|
|
|
|
|
WindowInsets.ime.asPaddingValues().calculateBottomPadding()
|
|
|
|
|
else
|
|
|
|
|
windowInsets.value.calculateBottomPadding()
|
|
|
|
|
),
|
|
|
|
|
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(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
SystemBarScrim(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.windowInsetsTopHeight(WindowInsets.systemBars)
|
|
|
|
|
.align(Alignment.TopCenter),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|