Implement article actions on the library
This commit is contained in:
@ -9,6 +9,7 @@ import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material.icons.outlined.Close
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
@ -58,49 +59,147 @@ fun LibraryNavigationBar(
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
if (actionsMenuItem != null) {
|
||||
IconButton(onClick = onSearchClicked) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.archive_outline),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = onSearchClicked) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tag),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = onSearchClicked) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Delete,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = onSettingsIconClick) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
IconButton(onClick = onSearchClicked) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Search,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
actionsMenuItem?.let {
|
||||
IconButton(onClick = {
|
||||
savedItemViewModel.handleSavedItemAction(
|
||||
it.savedItemId,
|
||||
if (it.isArchived) SavedItemAction.Unarchive else SavedItemAction.Archive
|
||||
) }) {
|
||||
if (it.isArchived) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.unarchive),
|
||||
contentDescription = null
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.archive_outline),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
IconButton(onClick = { savedItemViewModel.handleSavedItemAction(it.savedItemId, SavedItemAction.EditLabels) }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.tag),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { savedItemViewModel.handleSavedItemAction(it.savedItemId, SavedItemAction.Delete) }) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Delete,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
// IconButton(onClick = onSettingsIconClick) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Default.MoreVert,
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
} ?: run {
|
||||
IconButton(onClick = onSearchClicked) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Search,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
|
||||
IconButton(onClick = onSettingsIconClick) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null
|
||||
)
|
||||
IconButton(onClick = onSettingsIconClick) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
//
|
||||
//@OptIn(ExperimentalMaterial3Api::class)
|
||||
//@Composable
|
||||
//fun LibraryBottomBar(
|
||||
// savedItemViewModel: SavedItemViewModel,
|
||||
// onSearchClicked: () -> Unit,
|
||||
// onSettingsIconClick: () -> Unit
|
||||
//) {
|
||||
// val actionsMenuItem: SavedItemCardData? by savedItemViewModel.actionsMenuItemLiveData.observeAsState(null)
|
||||
//
|
||||
// BottomAppBar(
|
||||
//// colors = TopAppBarDefaults.topAppBarColors(
|
||||
//// containerColor = if (actionsMenuItem == null) MaterialTheme.colorScheme.background else MaterialTheme.colorScheme.surfaceVariant
|
||||
//// ),
|
||||
//// trailingIcon = {
|
||||
//// if (actionsMenuItem != null) {
|
||||
//// IconButton(onClick = {
|
||||
//// savedItemViewModel.actionsMenuItemLiveData.postValue(null)
|
||||
//// }) {
|
||||
//// Icon(
|
||||
//// imageVector = androidx.compose.material.icons.Icons.Filled.ArrowBack,
|
||||
//// modifier = Modifier,
|
||||
//// contentDescription = "Back"
|
||||
//// )
|
||||
//// }
|
||||
//// }
|
||||
//// },
|
||||
// floatingActionButton = {
|
||||
// IconButton(onClick = onSearchClicked) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Outlined.Close,
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
// },
|
||||
// actions = {
|
||||
// actionsMenuItem?.let {
|
||||
// IconButton(onClick = onSearchClicked) {
|
||||
// if (it.isArchived) {
|
||||
// Icon(
|
||||
// painter = painterResource(id = R.drawable.unarchive),
|
||||
// contentDescription = null
|
||||
// )
|
||||
// } else {
|
||||
// Icon(
|
||||
// painter = painterResource(id = R.drawable.archive_outline),
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// IconButton(onClick = onSearchClicked) {
|
||||
// Icon(
|
||||
// painter = painterResource(id = R.drawable.tag),
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
// IconButton(onClick = onSearchClicked) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Outlined.Delete,
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
// IconButton(onClick = onSettingsIconClick) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Default.MoreVert,
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
// } ?: run {
|
||||
// IconButton(onClick = onSearchClicked) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Filled.Search,
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// IconButton(onClick = onSettingsIconClick) {
|
||||
// Icon(
|
||||
// imageVector = Icons.Default.MoreVert,
|
||||
// contentDescription = null
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class)
|
||||
|
||||
@ -2,30 +2,44 @@ package app.omnivore.omnivore.ui.library
|
||||
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ModalBottomSheetLayout
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import app.omnivore.omnivore.R
|
||||
import app.omnivore.omnivore.Routes
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemCardData
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemCardDataWithLabels
|
||||
import app.omnivore.omnivore.ui.components.LabelsSelectionSheet
|
||||
import app.omnivore.omnivore.ui.savedItemViews.SavedItemCard
|
||||
import app.omnivore.omnivore.ui.reader.PDFReaderActivity
|
||||
import app.omnivore.omnivore.ui.reader.WebReaderLoadingContainerActivity
|
||||
import app.omnivore.omnivore.ui.save.SaveSheetActivityBase
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
|
||||
|
||||
@ -35,6 +49,9 @@ fun LibraryView(
|
||||
libraryViewModel: LibraryViewModel,
|
||||
navController: NavHostController
|
||||
) {
|
||||
|
||||
val actionsMenuItem: SavedItemCardData? by libraryViewModel.actionsMenuItemLiveData.observeAsState(null)
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
LibraryNavigationBar(
|
||||
@ -43,19 +60,19 @@ fun LibraryView(
|
||||
onSettingsIconClick = { navController.navigate(Routes.Settings.route) }
|
||||
)
|
||||
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
LibraryViewContent(
|
||||
libraryViewModel,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = paddingValues.calculateTopPadding()
|
||||
)
|
||||
)
|
||||
LibraryViewContent(
|
||||
libraryViewModel,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
top = paddingValues.calculateTopPadding()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LibraryViewContent(libraryViewModel: LibraryViewModel, modifier: Modifier) {
|
||||
val context = LocalContext.current
|
||||
@ -66,7 +83,9 @@ fun LibraryViewContent(libraryViewModel: LibraryViewModel, modifier: Modifier) {
|
||||
onRefresh = { libraryViewModel.refresh() }
|
||||
)
|
||||
|
||||
val cardsData: List<SavedItemCardDataWithLabels> by libraryViewModel.itemsLiveData.observeAsState(listOf())
|
||||
val cardsData: List<SavedItemCardDataWithLabels> by libraryViewModel.itemsLiveData.observeAsState(
|
||||
listOf()
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@ -91,12 +110,18 @@ fun LibraryViewContent(libraryViewModel: LibraryViewModel, modifier: Modifier) {
|
||||
cardData = cardDataWithLabels.cardData,
|
||||
labels = cardDataWithLabels.labels,
|
||||
onClickHandler = {
|
||||
val activityClass = if (cardDataWithLabels.cardData.isPDF()) PDFReaderActivity::class.java else WebReaderLoadingContainerActivity::class.java
|
||||
val activityClass =
|
||||
if (cardDataWithLabels.cardData.isPDF()) PDFReaderActivity::class.java else WebReaderLoadingContainerActivity::class.java
|
||||
val intent = Intent(context, activityClass)
|
||||
intent.putExtra("SAVED_ITEM_SLUG", cardDataWithLabels.cardData.slug)
|
||||
context.startActivity(intent)
|
||||
},
|
||||
actionHandler = { libraryViewModel.handleSavedItemAction(cardDataWithLabels.cardData.savedItemId, it) }
|
||||
actionHandler = {
|
||||
libraryViewModel.handleSavedItemAction(
|
||||
cardDataWithLabels.cardData.savedItemId,
|
||||
it
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -110,7 +135,7 @@ fun LibraryViewContent(libraryViewModel: LibraryViewModel, modifier: Modifier) {
|
||||
libraryViewModel.loadUsingSearchAPI()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PullRefreshIndicator(
|
||||
refreshing = libraryViewModel.isRefreshing,
|
||||
state = pullRefreshState,
|
||||
|
||||
@ -248,7 +248,7 @@ class LibraryViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun handleSavedItemAction(itemID: String, action: SavedItemAction) {
|
||||
override fun handleSavedItemAction(itemID: String, action: SavedItemAction) {
|
||||
when (action) {
|
||||
SavedItemAction.Delete -> {
|
||||
viewModelScope.launch {
|
||||
@ -270,6 +270,7 @@ class LibraryViewModel @Inject constructor(
|
||||
showLabelsSelectionSheetLiveData.value = true
|
||||
}
|
||||
}
|
||||
actionsMenuItemLiveData.postValue(null)
|
||||
}
|
||||
|
||||
fun updateSavedItemLabels(savedItemID: String, labels: List<SavedItemLabel>) {
|
||||
|
||||
@ -8,4 +8,5 @@ interface SavedItemViewModel {
|
||||
val actionsMenuItemLiveData: MutableLiveData<SavedItemCardData?>
|
||||
get() = MutableLiveData<SavedItemCardData?>(null)
|
||||
|
||||
fun handleSavedItemAction(itemID: String, action: SavedItemAction)
|
||||
}
|
||||
|
||||
@ -144,28 +144,28 @@ class SearchViewModel @Inject constructor(
|
||||
isRefreshing.postValue(false)
|
||||
}
|
||||
|
||||
fun handleSavedItemAction(itemID: String, action: SavedItemAction) {
|
||||
// when (action) {
|
||||
// SavedItemAction.Delete -> {
|
||||
// viewModelScope.launch {
|
||||
// dataService.deleteSavedItem(itemID)
|
||||
// }
|
||||
// }
|
||||
// SavedItemAction.Archive -> {
|
||||
// viewModelScope.launch {
|
||||
// dataService.archiveSavedItem(itemID)
|
||||
// }
|
||||
// }
|
||||
// SavedItemAction.Unarchive -> {
|
||||
// viewModelScope.launch {
|
||||
// dataService.unarchiveSavedItem(itemID)
|
||||
// }
|
||||
// }
|
||||
// SavedItemAction.EditLabels -> {
|
||||
// labelsSelectionCurrentItemLiveData.value = itemID
|
||||
// showLabelsSelectionSheetLiveData.value = true
|
||||
// }
|
||||
// }
|
||||
override fun handleSavedItemAction(itemID: String, action: SavedItemAction) {
|
||||
when (action) {
|
||||
SavedItemAction.Delete -> {
|
||||
viewModelScope.launch {
|
||||
dataService.deleteSavedItem(itemID)
|
||||
}
|
||||
}
|
||||
SavedItemAction.Archive -> {
|
||||
viewModelScope.launch {
|
||||
dataService.archiveSavedItem(itemID)
|
||||
}
|
||||
}
|
||||
SavedItemAction.Unarchive -> {
|
||||
viewModelScope.launch {
|
||||
dataService.unarchiveSavedItem(itemID)
|
||||
}
|
||||
}
|
||||
SavedItemAction.EditLabels -> {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
actionsMenuItemLiveData.postValue(null)
|
||||
}
|
||||
|
||||
fun updateSavedItemLabels(savedItemID: String, labels: List<SavedItemLabel>) {
|
||||
|
||||
@ -41,13 +41,14 @@ fun SavedItemCard(savedItemViewModel: SavedItemViewModel, cardData: SavedItemCar
|
||||
onClick = onClickHandler,
|
||||
onLongClick = { savedItemViewModel.actionsMenuItemLiveData.postValue(cardData) }
|
||||
)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.Top,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(15.dp)
|
||||
.padding(20.dp)
|
||||
.background(if (isMenuExpanded) Color.LightGray else Color.Transparent)
|
||||
) {
|
||||
Column(
|
||||
|
||||
9
android/Omnivore/app/src/main/res/drawable/unarchive.xml
Normal file
9
android/Omnivore/app/src/main/res/drawable/unarchive.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:pathData="M208,32L48,32A16,16 0,0 0,32 48L32,208a16,16 0,0 0,16 16L208,224a16,16 0,0 0,16 -16L224,48A16,16 0,0 0,208 32ZM208,48L208,152h-28.7A15.86,15.86 0,0 0,168 156.69L148.69,176L107.31,176L88,156.69A15.86,15.86 0,0 0,76.69 152L48,152L48,48ZM208,208L48,208L48,168L76.69,168L96,187.31A15.86,15.86 0,0 0,107.31 192h41.38A15.86,15.86 0,0 0,160 187.31L179.31,168L208,168v40ZM90.34,125.66a8,8 0,0 1,11.32 -11.32L120,132.69L120,72a8,8 0,0 1,16 0v60.69l18.34,-18.35a8,8 0,0 1,11.32 11.32l-32,32a8,8 0,0 1,-11.32 0Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
Reference in New Issue
Block a user