Add local delete of archived projects
This commit is contained in:
@@ -132,6 +132,10 @@ fun BillsListScreen(
|
|||||||
onProjectAction(projectOptionsProjectId, 1)
|
onProjectAction(projectOptionsProjectId, 1)
|
||||||
viewModel.showProjectOptionsDialogByProjectId = null
|
viewModel.showProjectOptionsDialogByProjectId = null
|
||||||
},
|
},
|
||||||
|
onForgetProject = {
|
||||||
|
onProjectAction(projectOptionsProjectId, 9)
|
||||||
|
viewModel.showProjectOptionsDialogByProjectId = null
|
||||||
|
},
|
||||||
onManageMembers = {
|
onManageMembers = {
|
||||||
onProjectAction(projectOptionsProjectId, 2)
|
onProjectAction(projectOptionsProjectId, 2)
|
||||||
viewModel.showProjectOptionsDialogByProjectId = null
|
viewModel.showProjectOptionsDialogByProjectId = null
|
||||||
@@ -408,11 +412,9 @@ fun BillsListScreen(
|
|||||||
.pullRefresh(pullRefreshState)) {
|
.pullRefresh(pullRefreshState)) {
|
||||||
when {
|
when {
|
||||||
viewModel.showNoProjects -> EmptyProjectsState(onAccountSwitcherClick, onAddProjectClick)
|
viewModel.showNoProjects -> EmptyProjectsState(onAccountSwitcherClick, onAddProjectClick)
|
||||||
|
(viewModel.isRefreshing || viewModel.isLoadingBills) && viewModel.bills.isEmpty() ->
|
||||||
|
LoadingBillsState()
|
||||||
viewModel.showNoMembers -> EmptyMembersState()
|
viewModel.showNoMembers -> EmptyMembersState()
|
||||||
// A large project takes a long time on its first sync. Until that finishes there
|
|
||||||
// is nothing stored for it yet, and reporting that as "no bills" tells the user
|
|
||||||
// the project is empty when it is still downloading.
|
|
||||||
viewModel.isRefreshing && viewModel.bills.isEmpty() -> LoadingBillsState()
|
|
||||||
viewModel.showNoBills -> EmptyBillsState()
|
viewModel.showNoBills -> EmptyBillsState()
|
||||||
viewModel.bills.isEmpty() -> EmptyState()
|
viewModel.bills.isEmpty() -> EmptyState()
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ class BillsListViewActivity :
|
|||||||
8 -> {
|
8 -> {
|
||||||
startActivity(net.helcel.cowspent.android.label.LabelManagementActivity.createIntent(this@BillsListViewActivity, pid))
|
startActivity(net.helcel.cowspent.android.label.LabelManagementActivity.createIntent(this@BillsListViewActivity, pid))
|
||||||
}
|
}
|
||||||
|
9 -> onRemoveProjectClick(pid)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onAccountSwitcherClick = {
|
onAccountSwitcherClick = {
|
||||||
@@ -377,6 +378,8 @@ class BillsListViewActivity :
|
|||||||
fun onProjectClick(projectId: Long) {
|
fun onProjectClick(projectId: Long) {
|
||||||
if (viewModel.selectedProjectId != projectId) {
|
if (viewModel.selectedProjectId != projectId) {
|
||||||
viewModel.selectedMemberId = null
|
viewModel.selectedMemberId = null
|
||||||
|
viewModel.bills = emptyList()
|
||||||
|
viewModel.isLoadingBills = true
|
||||||
}
|
}
|
||||||
setSelectedProject(projectId)
|
setSelectedProject(projectId)
|
||||||
navigationSelection = Category(null, null)
|
navigationSelection = Category(null, null)
|
||||||
@@ -410,6 +413,9 @@ class BillsListViewActivity :
|
|||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
db.deleteProject(projectId)
|
db.deleteProject(projectId)
|
||||||
|
// Otherwise the next account sync sees a project the account offers
|
||||||
|
// with no local row, and creates it again.
|
||||||
|
CowspentServerSyncHelper.forgetAccountProject(applicationContext, proj)
|
||||||
PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
||||||
.edit { remove(lastProjectSyncKey(projectId)) }
|
.edit { remove(lastProjectSyncKey(projectId)) }
|
||||||
val dbProjects = db.projects
|
val dbProjects = db.projects
|
||||||
@@ -621,76 +627,80 @@ class BillsListViewActivity :
|
|||||||
val selectedProjectId = PreferenceManager.getDefaultSharedPreferences(applicationContext).getLong("selected_project", 0)
|
val selectedProjectId = PreferenceManager.getDefaultSharedPreferences(applicationContext).getLong("selected_project", 0)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val (projId, projName) = withContext(Dispatchers.IO) {
|
try {
|
||||||
if (selectedProjectId != 0L) {
|
val (projId, projName) = withContext(Dispatchers.IO) {
|
||||||
db.getProject(selectedProjectId)?.let {
|
if (selectedProjectId != 0L) {
|
||||||
it.id to (if (it.name == "null" || it.name.isEmpty()) it.remoteId else it.name)
|
db.getProject(selectedProjectId)?.let {
|
||||||
} ?: (0L to "")
|
it.id to (if (it.name == "null" || it.name.isEmpty()) it.remoteId else it.name)
|
||||||
} else {
|
} ?: (0L to "")
|
||||||
0L to ""
|
} else {
|
||||||
}
|
0L to ""
|
||||||
}
|
}
|
||||||
|
|
||||||
val title = if (selectedProjectId != 0L) projName else getString(R.string.app_name)
|
|
||||||
|
|
||||||
setSelectedProject(selectedProjectId)
|
|
||||||
viewModel.title = title
|
|
||||||
val query = viewModel.searchQuery.ifEmpty { null }
|
|
||||||
|
|
||||||
val (ljItems, memberCount) = withContext(Dispatchers.IO) {
|
|
||||||
val db = CowspentSQLiteOpenHelper.getInstance(applicationContext)
|
|
||||||
val billList: List<DBBill> = if (projId != 0L) {
|
|
||||||
db.searchBills(query, projId)
|
|
||||||
} else {
|
|
||||||
ArrayList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val bills = billList.filter {
|
val title = if (selectedProjectId != 0L) projName else getString(R.string.app_name)
|
||||||
val mid = viewModel.selectedMemberId
|
|
||||||
mid == null || mid == it.payerId || it.billOwersIds.contains(mid)
|
setSelectedProject(selectedProjectId)
|
||||||
|
viewModel.title = title
|
||||||
|
val query = viewModel.searchQuery.ifEmpty { null }
|
||||||
|
|
||||||
|
val (ljItems, memberCount) = withContext(Dispatchers.IO) {
|
||||||
|
val db = CowspentSQLiteOpenHelper.getInstance(applicationContext)
|
||||||
|
val billList: List<DBBill> = if (projId != 0L) {
|
||||||
|
db.searchBills(query, projId)
|
||||||
|
} else {
|
||||||
|
ArrayList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val bills = billList.filter {
|
||||||
|
val mid = viewModel.selectedMemberId
|
||||||
|
mid == null || mid == it.payerId || it.billOwersIds.contains(mid)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.hasUnlabeledBills = bills.any { it.categoryId == 0L && it.state != DBBill.STATE_DELETED }
|
||||||
|
|
||||||
|
val projectMembers = db.getMembersOfProject(projId, null)
|
||||||
|
val memberMap = projectMembers.associateBy { it.id }
|
||||||
|
|
||||||
|
val projectPaymentModes = db.getPaymentModes(projId).associateBy { it.id }
|
||||||
|
val projectCategories = db.getCategories(projId).associateBy { it.id }
|
||||||
|
|
||||||
|
BillFormatter.formatBills(
|
||||||
|
bills,
|
||||||
|
memberMap,
|
||||||
|
projectCategories,
|
||||||
|
projectPaymentModes
|
||||||
|
)
|
||||||
|
|
||||||
|
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT)
|
||||||
|
val itemList = BillsListUtils.groupAndSectionBills(
|
||||||
|
bills,
|
||||||
|
memberMap,
|
||||||
|
sdf,
|
||||||
|
applicationContext
|
||||||
|
)
|
||||||
|
|
||||||
|
itemList to projectMembers.size
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.hasUnlabeledBills = bills.any { it.categoryId == 0L && it.state != DBBill.STATE_DELETED }
|
viewModel.showNoProjects = false
|
||||||
|
viewModel.showNoMembers = false
|
||||||
|
viewModel.showNoBills = false
|
||||||
|
|
||||||
val projectMembers = db.getMembersOfProject(projId, null)
|
when {
|
||||||
val memberMap = projectMembers.associateBy { it.id }
|
memberCount == 0 -> {
|
||||||
|
viewModel.showNoMembers = true
|
||||||
val projectPaymentModes = db.getPaymentModes(projId).associateBy { it.id }
|
}
|
||||||
val projectCategories = db.getCategories(projId).associateBy { it.id }
|
ljItems.isEmpty() -> {
|
||||||
|
viewModel.showNoBills = true
|
||||||
BillFormatter.formatBills(
|
viewModel.bills = emptyList()
|
||||||
bills,
|
}
|
||||||
memberMap,
|
else -> {
|
||||||
projectCategories,
|
viewModel.bills = ljItems
|
||||||
projectPaymentModes
|
}
|
||||||
)
|
|
||||||
|
|
||||||
val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT)
|
|
||||||
val itemList = BillsListUtils.groupAndSectionBills(
|
|
||||||
bills,
|
|
||||||
memberMap,
|
|
||||||
sdf,
|
|
||||||
applicationContext
|
|
||||||
)
|
|
||||||
|
|
||||||
itemList to projectMembers.size
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.showNoProjects = false
|
|
||||||
viewModel.showNoMembers = false
|
|
||||||
viewModel.showNoBills = false
|
|
||||||
|
|
||||||
when {
|
|
||||||
memberCount == 0 -> {
|
|
||||||
viewModel.showNoMembers = true
|
|
||||||
}
|
|
||||||
ljItems.isEmpty() -> {
|
|
||||||
viewModel.showNoBills = true
|
|
||||||
viewModel.bills = emptyList()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
viewModel.bills = ljItems
|
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
viewModel.isLoadingBills = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class BillsListViewModel : ViewModel() {
|
|||||||
var selectedMemberId by mutableStateOf<Long?>(null)
|
var selectedMemberId by mutableStateOf<Long?>(null)
|
||||||
var bills by mutableStateOf<List<Item>>(emptyList())
|
var bills by mutableStateOf<List<Item>>(emptyList())
|
||||||
var isRefreshing by mutableStateOf(false)
|
var isRefreshing by mutableStateOf(false)
|
||||||
|
var isLoadingBills by mutableStateOf(false)
|
||||||
var searchQuery by mutableStateOf("")
|
var searchQuery by mutableStateOf("")
|
||||||
var title by mutableStateOf("")
|
var title by mutableStateOf("")
|
||||||
var accountName by mutableStateOf("")
|
var accountName by mutableStateOf("")
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import net.helcel.cowspent.model.ProjectType
|
|||||||
fun ProjectOptionsDialogContent(
|
fun ProjectOptionsDialogContent(
|
||||||
onEditProject: () -> Unit,
|
onEditProject: () -> Unit,
|
||||||
onRemoveProject: () -> Unit,
|
onRemoveProject: () -> Unit,
|
||||||
|
onForgetProject: () -> Unit = {},
|
||||||
onManageMembers: () -> Unit,
|
onManageMembers: () -> Unit,
|
||||||
onManageCurrencies: () -> Unit,
|
onManageCurrencies: () -> Unit,
|
||||||
onManageLabels: () -> Unit,
|
onManageLabels: () -> Unit,
|
||||||
@@ -73,6 +74,15 @@ fun ProjectOptionsDialogContent(
|
|||||||
val archiveLabel = if (isArchived) stringResource(R.string.action_unarchive) else stringResource(R.string.action_archive)
|
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
|
val archiveIcon = if (isArchived) Icons.Default.Unarchive else Icons.Default.Archive
|
||||||
row1.add(ProjectOption(archiveLabel, archiveIcon, onRemoveProject))
|
row1.add(ProjectOption(archiveLabel, archiveIcon, onRemoveProject))
|
||||||
|
if (isArchived) {
|
||||||
|
row1.add(
|
||||||
|
ProjectOption(
|
||||||
|
stringResource(R.string.action_forget),
|
||||||
|
Icons.Default.Delete,
|
||||||
|
onForgetProject
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
row1.add(ProjectOption(stringResource(R.string.action_delete), Icons.Default.Delete, onRemoveProject))
|
row1.add(ProjectOption(stringResource(R.string.action_delete), Icons.Default.Delete, onRemoveProject))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<string name="simple_back">Back</string>
|
<string name="simple_back">Back</string>
|
||||||
<string name="action_archive">Archive</string>
|
<string name="action_archive">Archive</string>
|
||||||
<string name="action_unarchive">Unarchive</string>
|
<string name="action_unarchive">Unarchive</string>
|
||||||
|
<string name="action_forget">Delete locally</string>
|
||||||
<string name="action_export">Export</string>
|
<string name="action_export">Export</string>
|
||||||
<string name="action_stats">Stats</string>
|
<string name="action_stats">Stats</string>
|
||||||
<string name="action_settle">Settle</string>
|
<string name="action_settle">Settle</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user