Archiving and Label options
This commit is contained in:
@@ -65,6 +65,7 @@ import net.helcel.cowspent.android.statistics.ProjectStatisticsActivity
|
||||
import net.helcel.cowspent.model.DBBill
|
||||
import net.helcel.cowspent.model.DBMember
|
||||
import net.helcel.cowspent.model.DBProject
|
||||
import net.helcel.cowspent.model.ProjectType
|
||||
import net.helcel.cowspent.model.SectionItem
|
||||
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
||||
import net.helcel.cowspent.util.IRefreshBillsListCallback
|
||||
@@ -137,6 +138,10 @@ fun BillsListScreen(
|
||||
onProjectAction(projectOptionsProjectId, 3)
|
||||
viewModel.showProjectOptionsDialogByProjectId = null
|
||||
},
|
||||
onManageLabels = {
|
||||
onProjectAction(projectOptionsProjectId, 8)
|
||||
viewModel.showProjectOptionsDialogByProjectId = null
|
||||
},
|
||||
onStatistics = {
|
||||
onProjectAction(projectOptionsProjectId, 4)
|
||||
viewModel.showProjectOptionsDialogByProjectId = null
|
||||
@@ -155,6 +160,7 @@ fun BillsListScreen(
|
||||
},
|
||||
onDismiss = { viewModel.showProjectOptionsDialogByProjectId = null },
|
||||
isArchived = proj?.isArchived == true,
|
||||
projectType = proj?.type ?: ProjectType.LOCAL,
|
||||
accessLevel = proj?.myAccessLevel ?: DBProject.ACCESS_LEVEL_ADMIN,
|
||||
isShareable = proj?.isShareable() ?: true
|
||||
)
|
||||
|
||||
@@ -45,6 +45,7 @@ import net.helcel.cowspent.model.Category
|
||||
import net.helcel.cowspent.model.DBBill
|
||||
import net.helcel.cowspent.model.DBProject
|
||||
import net.helcel.cowspent.model.GroupedBill
|
||||
import net.helcel.cowspent.model.ProjectType
|
||||
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
||||
import net.helcel.cowspent.persistence.CowspentServerSyncHelper
|
||||
import net.helcel.cowspent.theme.ThemeUtils
|
||||
@@ -254,13 +255,21 @@ class BillsListViewActivity :
|
||||
onProjectAction = { pid, actionIndex ->
|
||||
when (actionIndex) {
|
||||
0 -> onEditProjectClick(pid)
|
||||
1 -> onRemoveProjectClick(pid)
|
||||
1 -> {
|
||||
val proj = db.getProject(pid)
|
||||
if (proj?.type == ProjectType.COSPEND) {
|
||||
onArchiveProjectClick(pid)
|
||||
} else {
|
||||
onRemoveProjectClick(pid)
|
||||
}
|
||||
}
|
||||
2 -> onManageMembersClick(pid)
|
||||
3 -> onManageCurrenciesClick(pid)
|
||||
4 -> onProjectStatisticsClick(pid)
|
||||
5 -> onSettleProjectClick(pid)
|
||||
6 -> onShareProjectClick(pid)
|
||||
7 -> onExportProjectClick(pid)
|
||||
8 -> { /* Manage Labels - Placeholder for now */ }
|
||||
}
|
||||
},
|
||||
onAccountSwitcherClick = {
|
||||
@@ -423,6 +432,38 @@ class BillsListViewActivity :
|
||||
}
|
||||
}
|
||||
|
||||
private fun onArchiveProjectClick(projectId: Long) {
|
||||
if (projectId == 0L) return
|
||||
lifecycleScope.launch {
|
||||
val proj = withContext(Dispatchers.IO) { db.getProject(projectId) } ?: return@launch
|
||||
val isArchiving = !proj.isArchived
|
||||
|
||||
val newArchivedTs = if (isArchiving) System.currentTimeMillis() / 1000 else 0L
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
db.updateProject(
|
||||
projId = projectId,
|
||||
newName = null,
|
||||
newEmail = null,
|
||||
newPassword = null,
|
||||
newLastPayerId = null,
|
||||
newLastSyncedTimestamp = null,
|
||||
newCurrencyName = null,
|
||||
newDeletionDisabled = null,
|
||||
newMyAccessLevel = null,
|
||||
newBearerToken = null,
|
||||
newArchivedTs = newArchivedTs
|
||||
)
|
||||
}
|
||||
|
||||
setupDrawerProjects()
|
||||
refreshLists()
|
||||
|
||||
val msgRes = if (isArchiving) R.string.action_archive else R.string.action_unarchive
|
||||
showToast(this@BillsListViewActivity, getString(msgRes))
|
||||
}
|
||||
}
|
||||
|
||||
fun onManageMembersClick(projectId: Long) {
|
||||
if (projectId == 0L) return
|
||||
lifecycleScope.launch {
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Label
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -15,8 +16,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import net.helcel.cowspent.R
|
||||
|
||||
import net.helcel.cowspent.model.DBProject
|
||||
import net.helcel.cowspent.model.ProjectType
|
||||
|
||||
@Composable
|
||||
fun ProjectOptionsDialogContent(
|
||||
@@ -24,12 +25,14 @@ fun ProjectOptionsDialogContent(
|
||||
onRemoveProject: () -> Unit,
|
||||
onManageMembers: () -> Unit,
|
||||
onManageCurrencies: () -> Unit,
|
||||
onManageLabels: () -> Unit,
|
||||
onStatistics: () -> Unit,
|
||||
onSettle: () -> Unit,
|
||||
onShareProject: () -> Unit,
|
||||
onExportProject: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
isArchived: Boolean = false,
|
||||
projectType: ProjectType = ProjectType.LOCAL,
|
||||
accessLevel: Int = DBProject.ACCESS_LEVEL_ADMIN,
|
||||
isShareable: Boolean = true
|
||||
) {
|
||||
@@ -49,41 +52,63 @@ fun ProjectOptionsDialogContent(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
)
|
||||
|
||||
val options = mutableListOf<ProjectOption>()
|
||||
val isMaintainer = accessLevel >= DBProject.ACCESS_LEVEL_MAINTAINER || accessLevel == DBProject.ACCESS_LEVEL_UNKNOWN
|
||||
val isParticipant = accessLevel >= DBProject.ACCESS_LEVEL_PARTICIPANT || accessLevel == DBProject.ACCESS_LEVEL_UNKNOWN
|
||||
|
||||
val row1 = mutableListOf<ProjectOption>()
|
||||
val row2 = mutableListOf<ProjectOption>()
|
||||
val row3 = mutableListOf<ProjectOption>()
|
||||
|
||||
// Row 1: Edit, Share, Remove/Archive
|
||||
if (!isArchived && isMaintainer) {
|
||||
options.add(ProjectOption(stringResource(R.string.action_edit_project), Icons.Default.Edit, onEditProject))
|
||||
}
|
||||
options.add(ProjectOption(stringResource(R.string.fab_rm_project), Icons.Default.Delete, onRemoveProject))
|
||||
if (!isArchived && isMaintainer) {
|
||||
options.add(ProjectOption(stringResource(R.string.fab_manage_members), Icons.Default.Group, onManageMembers))
|
||||
options.add(ProjectOption(stringResource(R.string.fab_manage_currencies), Icons.Default.MonetizationOn, onManageCurrencies))
|
||||
}
|
||||
options.add(ProjectOption(stringResource(R.string.fab_statistics), Icons.Default.BarChart, onStatistics))
|
||||
if (!isArchived && isParticipant) {
|
||||
options.add(ProjectOption(stringResource(R.string.fab_settle), Icons.Default.Handshake, onSettle))
|
||||
row1.add(ProjectOption(stringResource(R.string.action_edit_project), Icons.Default.Edit, onEditProject))
|
||||
}
|
||||
if (isShareable && isParticipant) {
|
||||
options.add(ProjectOption(stringResource(R.string.action_share_project), Icons.Default.Share, onShareProject))
|
||||
row1.add(ProjectOption(stringResource(R.string.action_share_project), Icons.Default.Share, onShareProject))
|
||||
}
|
||||
if (projectType == ProjectType.COSPEND) {
|
||||
val archiveLabel = if (isArchived) stringResource(R.string.action_unarchive) else stringResource(R.string.action_archive)
|
||||
val archiveIcon = if (isArchived) Icons.Default.Unarchive else Icons.Default.Archive
|
||||
row1.add(ProjectOption(archiveLabel, archiveIcon, onRemoveProject))
|
||||
} else {
|
||||
row1.add(ProjectOption(stringResource(R.string.fab_rm_project), Icons.Default.Delete, onRemoveProject))
|
||||
}
|
||||
options.add(ProjectOption(stringResource(R.string.fab_export_project), Icons.Default.Download, onExportProject))
|
||||
|
||||
// Simple 2-column grid using Rows
|
||||
for (i in options.indices step 2) {
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
ProjectOptionItem(
|
||||
option = options[i],
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
if (i + 1 < options.size) {
|
||||
// Row 2: Manage Member, Manage Labels, Manage Currencies
|
||||
if (!isArchived && isMaintainer) {
|
||||
row2.add(ProjectOption(stringResource(R.string.fab_manage_members), Icons.Default.Group, onManageMembers))
|
||||
row2.add(ProjectOption(stringResource(R.string.fab_manage_labels), Icons.AutoMirrored.Filled.Label, onManageLabels))
|
||||
row2.add(ProjectOption(stringResource(R.string.fab_manage_currencies), Icons.Default.MonetizationOn, onManageCurrencies))
|
||||
}
|
||||
|
||||
// Row 3: Statistics, Settle, Export
|
||||
row3.add(ProjectOption(stringResource(R.string.fab_statistics), Icons.Default.BarChart, onStatistics))
|
||||
if (!isArchived && isParticipant) {
|
||||
row3.add(ProjectOption(stringResource(R.string.fab_settle), Icons.Default.Handshake, onSettle))
|
||||
}
|
||||
row3.add(ProjectOption(stringResource(R.string.fab_export_project), Icons.Default.Download, onExportProject))
|
||||
|
||||
val allRows = listOf(row1, row2, row3).filter { it.isNotEmpty() }
|
||||
|
||||
allRows.forEach { rowOptions ->
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
val emptySpace = 3 - rowOptions.size
|
||||
if (emptySpace > 0) {
|
||||
Spacer(modifier = Modifier.weight(emptySpace / 2f))
|
||||
}
|
||||
|
||||
rowOptions.forEach { option ->
|
||||
ProjectOptionItem(
|
||||
option = options[i + 1],
|
||||
option = option,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
|
||||
if (emptySpace > 0) {
|
||||
Spacer(modifier = Modifier.weight(emptySpace / 2f))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,10 +170,59 @@ fun ProjectOptionsDialogPreview() {
|
||||
onManageCurrencies = {},
|
||||
onStatistics = {},
|
||||
onSettle = {},
|
||||
onManageLabels = {},
|
||||
onShareProject = {},
|
||||
onExportProject = {},
|
||||
onDismiss = {},
|
||||
isArchived = false,
|
||||
projectType = ProjectType.COSPEND,
|
||||
accessLevel = DBProject.ACCESS_LEVEL_ADMIN,
|
||||
isShareable = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun ProjectOptionsDialogPreview2() {
|
||||
MaterialTheme {
|
||||
ProjectOptionsDialogContent(
|
||||
onEditProject = {},
|
||||
onRemoveProject = {},
|
||||
onManageMembers = {},
|
||||
onManageCurrencies = {},
|
||||
onStatistics = {},
|
||||
onSettle = {},
|
||||
onManageLabels = {},
|
||||
onShareProject = {},
|
||||
onExportProject = {},
|
||||
onDismiss = {},
|
||||
isArchived = true,
|
||||
projectType = ProjectType.COSPEND,
|
||||
accessLevel = DBProject.ACCESS_LEVEL_ADMIN,
|
||||
isShareable = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun ProjectOptionsDialogPreview3() {
|
||||
MaterialTheme {
|
||||
ProjectOptionsDialogContent(
|
||||
onEditProject = {},
|
||||
onRemoveProject = {},
|
||||
onManageMembers = {},
|
||||
onManageCurrencies = {},
|
||||
onStatistics = {},
|
||||
onSettle = {},
|
||||
onManageLabels = {},
|
||||
onShareProject = {},
|
||||
onExportProject = {},
|
||||
onDismiss = {},
|
||||
isArchived = false,
|
||||
projectType = ProjectType.LOCAL,
|
||||
accessLevel = DBProject.ACCESS_LEVEL_ADMIN,
|
||||
isShareable = true
|
||||
)
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<string name="action_scan_qrcode">Scan QRCode from Cospend/Cowspent</string>
|
||||
<string name="action_add_project">Add project</string>
|
||||
<string name="action_save_bill">Save bill</string>
|
||||
<string name="action_edit_project">Edit project</string>
|
||||
<string name="action_share_project">Share project</string>
|
||||
<string name="action_edit_project">Edit</string>
|
||||
<string name="action_share_project">Share</string>
|
||||
<string name="setting_what">What?</string>
|
||||
<string name="setting_payer">Who paid?</string>
|
||||
<string name="setting_all">All</string>
|
||||
@@ -82,12 +82,15 @@
|
||||
<string name="simple_share_share">Share Cowspent link</string>
|
||||
<string name="menu_delete_project_remote">Delete project on server</string>
|
||||
<string name="menu_save_project">Save project</string>
|
||||
<string name="fab_add_member">Add a member</string>
|
||||
<string name="fab_rm_project">Remove Project</string>
|
||||
<string name="fab_add_member">Add member</string>
|
||||
<string name="fab_rm_project">Remove</string>
|
||||
<string name="remove_project_confirmation">Project %1$s has been removed</string>
|
||||
<string name="choose_project_management_action">Manage project</string>
|
||||
<string name="fab_manage_members">Manage members</string>
|
||||
<string name="fab_export_project">Export project</string>
|
||||
<string name="choose_project_management_action">Project</string>
|
||||
<string name="fab_manage_members">Members</string>
|
||||
<string name="fab_manage_labels">Labels</string>
|
||||
<string name="action_archive">Archive</string>
|
||||
<string name="action_unarchive">Unarchive</string>
|
||||
<string name="fab_export_project">Export</string>
|
||||
<string name="drawer_last_sync_text">Last sync: %1$02d:%2$02d</string>
|
||||
<string name="scan_qrcode">Scan QR code</string>
|
||||
<string name="new_project_from_nextcloud_tooltip">Choose from Nextcloud account</string>
|
||||
@@ -147,7 +150,7 @@
|
||||
<string name="stats_paid">Paid</string>
|
||||
<string name="stats_spent">Spent</string>
|
||||
<string name="stats_balance">Balance</string>
|
||||
<string name="fab_statistics">Statistics</string>
|
||||
<string name="fab_statistics">Stats</string>
|
||||
<string name="fab_settle">Settle</string>
|
||||
<string name="project_add_success_message">Project %1$s was successfully added</string>
|
||||
<string name="project_create_success_message">Project %1$s was successfully created</string>
|
||||
@@ -240,7 +243,7 @@
|
||||
|
||||
<!-- QR Code Scanner -->
|
||||
<string name="error_scanning_bill_qr_code">QR code could not be scanned.</string>
|
||||
<string name="fab_manage_currencies">Manage currencies</string>
|
||||
<string name="fab_manage_currencies">Currencies</string>
|
||||
<string name="setting_show_archived">Show archived projects</string>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user