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.DBBill
|
||||||
import net.helcel.cowspent.model.DBMember
|
import net.helcel.cowspent.model.DBMember
|
||||||
import net.helcel.cowspent.model.DBProject
|
import net.helcel.cowspent.model.DBProject
|
||||||
|
import net.helcel.cowspent.model.ProjectType
|
||||||
import net.helcel.cowspent.model.SectionItem
|
import net.helcel.cowspent.model.SectionItem
|
||||||
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
||||||
import net.helcel.cowspent.util.IRefreshBillsListCallback
|
import net.helcel.cowspent.util.IRefreshBillsListCallback
|
||||||
@@ -137,6 +138,10 @@ fun BillsListScreen(
|
|||||||
onProjectAction(projectOptionsProjectId, 3)
|
onProjectAction(projectOptionsProjectId, 3)
|
||||||
viewModel.showProjectOptionsDialogByProjectId = null
|
viewModel.showProjectOptionsDialogByProjectId = null
|
||||||
},
|
},
|
||||||
|
onManageLabels = {
|
||||||
|
onProjectAction(projectOptionsProjectId, 8)
|
||||||
|
viewModel.showProjectOptionsDialogByProjectId = null
|
||||||
|
},
|
||||||
onStatistics = {
|
onStatistics = {
|
||||||
onProjectAction(projectOptionsProjectId, 4)
|
onProjectAction(projectOptionsProjectId, 4)
|
||||||
viewModel.showProjectOptionsDialogByProjectId = null
|
viewModel.showProjectOptionsDialogByProjectId = null
|
||||||
@@ -155,6 +160,7 @@ fun BillsListScreen(
|
|||||||
},
|
},
|
||||||
onDismiss = { viewModel.showProjectOptionsDialogByProjectId = null },
|
onDismiss = { viewModel.showProjectOptionsDialogByProjectId = null },
|
||||||
isArchived = proj?.isArchived == true,
|
isArchived = proj?.isArchived == true,
|
||||||
|
projectType = proj?.type ?: ProjectType.LOCAL,
|
||||||
accessLevel = proj?.myAccessLevel ?: DBProject.ACCESS_LEVEL_ADMIN,
|
accessLevel = proj?.myAccessLevel ?: DBProject.ACCESS_LEVEL_ADMIN,
|
||||||
isShareable = proj?.isShareable() ?: true
|
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.DBBill
|
||||||
import net.helcel.cowspent.model.DBProject
|
import net.helcel.cowspent.model.DBProject
|
||||||
import net.helcel.cowspent.model.GroupedBill
|
import net.helcel.cowspent.model.GroupedBill
|
||||||
|
import net.helcel.cowspent.model.ProjectType
|
||||||
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
import net.helcel.cowspent.persistence.CowspentSQLiteOpenHelper
|
||||||
import net.helcel.cowspent.persistence.CowspentServerSyncHelper
|
import net.helcel.cowspent.persistence.CowspentServerSyncHelper
|
||||||
import net.helcel.cowspent.theme.ThemeUtils
|
import net.helcel.cowspent.theme.ThemeUtils
|
||||||
@@ -254,13 +255,21 @@ class BillsListViewActivity :
|
|||||||
onProjectAction = { pid, actionIndex ->
|
onProjectAction = { pid, actionIndex ->
|
||||||
when (actionIndex) {
|
when (actionIndex) {
|
||||||
0 -> onEditProjectClick(pid)
|
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)
|
2 -> onManageMembersClick(pid)
|
||||||
3 -> onManageCurrenciesClick(pid)
|
3 -> onManageCurrenciesClick(pid)
|
||||||
4 -> onProjectStatisticsClick(pid)
|
4 -> onProjectStatisticsClick(pid)
|
||||||
5 -> onSettleProjectClick(pid)
|
5 -> onSettleProjectClick(pid)
|
||||||
6 -> onShareProjectClick(pid)
|
6 -> onShareProjectClick(pid)
|
||||||
7 -> onExportProjectClick(pid)
|
7 -> onExportProjectClick(pid)
|
||||||
|
8 -> { /* Manage Labels - Placeholder for now */ }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onAccountSwitcherClick = {
|
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) {
|
fun onManageMembersClick(projectId: Long) {
|
||||||
if (projectId == 0L) return
|
if (projectId == 0L) return
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import androidx.compose.foundation.clickable
|
|||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.Label
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
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.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import net.helcel.cowspent.R
|
import net.helcel.cowspent.R
|
||||||
|
|
||||||
import net.helcel.cowspent.model.DBProject
|
import net.helcel.cowspent.model.DBProject
|
||||||
|
import net.helcel.cowspent.model.ProjectType
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ProjectOptionsDialogContent(
|
fun ProjectOptionsDialogContent(
|
||||||
@@ -24,12 +25,14 @@ fun ProjectOptionsDialogContent(
|
|||||||
onRemoveProject: () -> Unit,
|
onRemoveProject: () -> Unit,
|
||||||
onManageMembers: () -> Unit,
|
onManageMembers: () -> Unit,
|
||||||
onManageCurrencies: () -> Unit,
|
onManageCurrencies: () -> Unit,
|
||||||
|
onManageLabels: () -> Unit,
|
||||||
onStatistics: () -> Unit,
|
onStatistics: () -> Unit,
|
||||||
onSettle: () -> Unit,
|
onSettle: () -> Unit,
|
||||||
onShareProject: () -> Unit,
|
onShareProject: () -> Unit,
|
||||||
onExportProject: () -> Unit,
|
onExportProject: () -> Unit,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
isArchived: Boolean = false,
|
isArchived: Boolean = false,
|
||||||
|
projectType: ProjectType = ProjectType.LOCAL,
|
||||||
accessLevel: Int = DBProject.ACCESS_LEVEL_ADMIN,
|
accessLevel: Int = DBProject.ACCESS_LEVEL_ADMIN,
|
||||||
isShareable: Boolean = true
|
isShareable: Boolean = true
|
||||||
) {
|
) {
|
||||||
@@ -49,41 +52,63 @@ fun ProjectOptionsDialogContent(
|
|||||||
modifier = Modifier.padding(bottom = 8.dp)
|
modifier = Modifier.padding(bottom = 8.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
val options = mutableListOf<ProjectOption>()
|
|
||||||
val isMaintainer = accessLevel >= DBProject.ACCESS_LEVEL_MAINTAINER || accessLevel == DBProject.ACCESS_LEVEL_UNKNOWN
|
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 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) {
|
if (!isArchived && isMaintainer) {
|
||||||
options.add(ProjectOption(stringResource(R.string.action_edit_project), Icons.Default.Edit, onEditProject))
|
row1.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))
|
|
||||||
}
|
}
|
||||||
if (isShareable && isParticipant) {
|
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
|
// Row 2: Manage Member, Manage Labels, Manage Currencies
|
||||||
for (i in options.indices step 2) {
|
if (!isArchived && isMaintainer) {
|
||||||
Row(modifier = Modifier.fillMaxWidth()) {
|
row2.add(ProjectOption(stringResource(R.string.fab_manage_members), Icons.Default.Group, onManageMembers))
|
||||||
ProjectOptionItem(
|
row2.add(ProjectOption(stringResource(R.string.fab_manage_labels), Icons.AutoMirrored.Filled.Label, onManageLabels))
|
||||||
option = options[i],
|
row2.add(ProjectOption(stringResource(R.string.fab_manage_currencies), Icons.Default.MonetizationOn, onManageCurrencies))
|
||||||
modifier = Modifier.weight(1f)
|
}
|
||||||
)
|
|
||||||
if (i + 1 < options.size) {
|
// 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(
|
ProjectOptionItem(
|
||||||
option = options[i + 1],
|
option = option,
|
||||||
modifier = Modifier.weight(1f)
|
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 = {},
|
onManageCurrencies = {},
|
||||||
onStatistics = {},
|
onStatistics = {},
|
||||||
onSettle = {},
|
onSettle = {},
|
||||||
|
onManageLabels = {},
|
||||||
onShareProject = {},
|
onShareProject = {},
|
||||||
onExportProject = {},
|
onExportProject = {},
|
||||||
onDismiss = {},
|
onDismiss = {},
|
||||||
isArchived = false,
|
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,
|
accessLevel = DBProject.ACCESS_LEVEL_ADMIN,
|
||||||
isShareable = true
|
isShareable = true
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
<string name="action_scan_qrcode">Scan QRCode from Cospend/Cowspent</string>
|
<string name="action_scan_qrcode">Scan QRCode from Cospend/Cowspent</string>
|
||||||
<string name="action_add_project">Add project</string>
|
<string name="action_add_project">Add project</string>
|
||||||
<string name="action_save_bill">Save bill</string>
|
<string name="action_save_bill">Save bill</string>
|
||||||
<string name="action_edit_project">Edit project</string>
|
<string name="action_edit_project">Edit</string>
|
||||||
<string name="action_share_project">Share project</string>
|
<string name="action_share_project">Share</string>
|
||||||
<string name="setting_what">What?</string>
|
<string name="setting_what">What?</string>
|
||||||
<string name="setting_payer">Who paid?</string>
|
<string name="setting_payer">Who paid?</string>
|
||||||
<string name="setting_all">All</string>
|
<string name="setting_all">All</string>
|
||||||
@@ -82,12 +82,15 @@
|
|||||||
<string name="simple_share_share">Share Cowspent link</string>
|
<string name="simple_share_share">Share Cowspent link</string>
|
||||||
<string name="menu_delete_project_remote">Delete project on server</string>
|
<string name="menu_delete_project_remote">Delete project on server</string>
|
||||||
<string name="menu_save_project">Save project</string>
|
<string name="menu_save_project">Save project</string>
|
||||||
<string name="fab_add_member">Add a member</string>
|
<string name="fab_add_member">Add member</string>
|
||||||
<string name="fab_rm_project">Remove Project</string>
|
<string name="fab_rm_project">Remove</string>
|
||||||
<string name="remove_project_confirmation">Project %1$s has been removed</string>
|
<string name="remove_project_confirmation">Project %1$s has been removed</string>
|
||||||
<string name="choose_project_management_action">Manage project</string>
|
<string name="choose_project_management_action">Project</string>
|
||||||
<string name="fab_manage_members">Manage members</string>
|
<string name="fab_manage_members">Members</string>
|
||||||
<string name="fab_export_project">Export project</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="drawer_last_sync_text">Last sync: %1$02d:%2$02d</string>
|
||||||
<string name="scan_qrcode">Scan QR code</string>
|
<string name="scan_qrcode">Scan QR code</string>
|
||||||
<string name="new_project_from_nextcloud_tooltip">Choose from Nextcloud account</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_paid">Paid</string>
|
||||||
<string name="stats_spent">Spent</string>
|
<string name="stats_spent">Spent</string>
|
||||||
<string name="stats_balance">Balance</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="fab_settle">Settle</string>
|
||||||
<string name="project_add_success_message">Project %1$s was successfully added</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>
|
<string name="project_create_success_message">Project %1$s was successfully created</string>
|
||||||
@@ -240,7 +243,7 @@
|
|||||||
|
|
||||||
<!-- QR Code Scanner -->
|
<!-- QR Code Scanner -->
|
||||||
<string name="error_scanning_bill_qr_code">QR code could not be scanned.</string>
|
<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>
|
<string name="setting_show_archived">Show archived projects</string>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user