More work on notebook using bottom sheet

This commit is contained in:
Jackson Harper
2023-05-08 17:06:27 +08:00
parent e4e153e01f
commit dc7c992ed2
3 changed files with 117 additions and 45 deletions

View File

@ -156,8 +156,6 @@ interface SavedItemDao {
"LEFT OUTER JOIN Highlight on highlight.highlightId = SavedItemAndHighlightCrossRef.highlightId " +
"WHERE SavedItem.savedItemId = :savedItemId " +
"AND SavedItem.serverSyncStatus != 2 " +
"AND Highlight.serverSyncStatus != 2 " +
"GROUP BY SavedItem.savedItemId "
)

View File

@ -46,7 +46,10 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController
import dagger.hilt.android.AndroidEntryPoint
import dev.jeziellago.compose.markdowntext.MarkdownText
import kotlinx.coroutines.launch
import android.util.Log
import androidx.compose.ui.platform.LocalDensity
import app.omnivore.omnivore.persistence.entities.Highlight
import kotlin.math.roundToInt
@AndroidEntryPoint
class NotebookActivity: ComponentActivity() {
@ -102,61 +105,105 @@ class NotebookActivity: ComponentActivity() {
}
}
fun notebookMD(notes: List<Highlight>, highlights: List<Highlight>): String {
var result = ""
if (notes.isNotEmpty()) {
result += "## Notes\n"
notes.forEach {
result += it.annotation + "\n"
}
result += "\n"
}
if (highlights.isNotEmpty()) {
result += "## Highlights\n"
highlights.forEach {
result += "> ${it.quote}\n"
if ((it.annotation?: "").isNotEmpty()) {
result += it.annotation + "\n"
}
}
result += "\n"
}
return result
}
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
@Composable
fun NotebookView(savedItemId: String, viewModel: NotebookViewModel) {
val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
var isMenuOpen by remember {
mutableStateOf(false)
}
val savedItem = viewModel.getLibraryItemById(savedItemId).observeAsState()
val scrollState = rememberScrollState()
val modalBottomSheetState = rememberModalBottomSheetState(
ModalBottomSheetValue.Hidden,
)
val coroutineScope = rememberCoroutineScope()
val snackBarHostState = remember { SnackbarHostState() }
val clipboard: ClipboardManager? =
LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
val notes = savedItem.value?.highlights?.filter { it.type == "NOTE" } ?: listOf()
val highlights = savedItem.value?.highlights?.filter { it.type == "HIGHLIGHT" } ?: listOf()
ModalBottomSheetLayout(
modifier = Modifier.statusBarsPadding(),
sheetBackgroundColor = Color.Transparent,
sheetState = modalBottomSheetState,
sheetContent = {
EditNoteModal()
// EditNoteModal()
Spacer(modifier = Modifier.weight(1.0F))
}
) {
Scaffold(
topBar = {
TopAppBar(
title = { Text("Notebook") },
modifier = Modifier.statusBarsPadding(),
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.background
),
navigationIcon = {
IconButton(onClick = {
onBackPressedDispatcher?.onBackPressed()
}) {
Icon(
imageVector = androidx.compose.material.icons.Icons.Filled.ArrowBack,
modifier = Modifier,
contentDescription = "Back"
)
actions = {
Box {
IconButton(onClick = {
isMenuOpen = true
}) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = null
)
}
if (isMenuOpen) {
DropdownMenu(
expanded = isMenuOpen,
onDismissRequest = { isMenuOpen = false }
) {
DropdownMenuItem(
text = { Text("Copy") },
onClick = {
val clip = ClipData.newPlainText("notebook", notebookMD(notes, highlights))
clipboard?.let {
it
clipboard?.setPrimaryClip(clip)
} ?: run {
coroutineScope.launch {
snackBarHostState
.showSnackbar("Notebook copied")
}
}
isMenuOpen = false
}
)
}
}
}
},
// actions = {
// IconButton(onClick = {
//
// }) {
// Icon(
// imageVector = Icons.Default.MoreVert,
// contentDescription = null
// )
// }
// }
}
)
}
) { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.verticalScroll(scrollState)
.fillMaxSize()
) {
@ -166,7 +213,6 @@ fun NotebookView(savedItemId: String, viewModel: NotebookViewModel) {
}
HighlightsList(it)
}
Spacer(Modifier.weight(100f))
}
}
}

View File

@ -24,7 +24,6 @@ import androidx.compose.runtime.livedata.observeAsState
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.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
@ -34,7 +33,8 @@ import androidx.core.view.WindowInsetsCompat
import app.omnivore.omnivore.MainActivity
import app.omnivore.omnivore.R
import app.omnivore.omnivore.ui.components.WebReaderLabelsSelectionSheet
import app.omnivore.omnivore.ui.notebook.NotebookActivity
import app.omnivore.omnivore.ui.notebook.NotebookView
import app.omnivore.omnivore.ui.notebook.NotebookViewModel
import app.omnivore.omnivore.ui.savedItemViews.SavedItemContextMenu
import app.omnivore.omnivore.ui.theme.OmnivoreTheme
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@ -46,6 +46,7 @@ import kotlin.math.roundToInt
@AndroidEntryPoint
class WebReaderLoadingContainerActivity: ComponentActivity() {
val viewModel: WebReaderViewModel by viewModels()
val notebookViewModel: NotebookViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -79,6 +80,7 @@ class WebReaderLoadingContainerActivity: ComponentActivity() {
slug = slug,
onLibraryIconTap = if (requestID != null) { { startMainActivity() } } else null,
webReaderViewModel = viewModel,
notebookViewModel = notebookViewModel,
)
}
}
@ -101,13 +103,25 @@ class WebReaderLoadingContainerActivity: ComponentActivity() {
}
}
enum class BottomSheetState(
) {
NONE(),
PREFERENCES(),
NOTEBOOK(),
HIGHLIGHTNOTE()
}
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
@Composable
fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, onLibraryIconTap: (() -> Unit)? = null, webReaderViewModel: WebReaderViewModel) {
fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null,
onLibraryIconTap: (() -> Unit)? = null,
webReaderViewModel: WebReaderViewModel,
notebookViewModel: NotebookViewModel) {
val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
var isMenuExpanded by remember { mutableStateOf(false) }
var showWebPreferencesDialog by remember { mutableStateOf(false ) }
var bottomSheetState by remember { mutableStateOf(app.omnivore.omnivore.ui.reader.BottomSheetState.NONE)}
val currentThemeKey = webReaderViewModel.currentThemeKey.observeAsState()
val currentTheme = Themes.values().find { it.themeKey == currentThemeKey.value }
@ -121,7 +135,6 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, o
webReaderViewModel.maxToolbarHeightPx = with(LocalDensity.current) { maxToolbarHeight.roundToPx().toFloat() }
webReaderViewModel.loadItem(slug = slug, requestID = requestID)
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val styledContent = webReaderParams?.let {
@ -140,13 +153,29 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, o
val themeTintColor = Color(currentTheme?.foregroundColor ?: 0xFFFFFFFF)
ModalBottomSheetLayout(
modifier = Modifier.statusBarsPadding(),
modifier = Modifier
.statusBarsPadding(),
sheetBackgroundColor = Color.Transparent,
sheetState = modalBottomSheetState,
sheetContent = {
if (showWebPreferencesDialog) {
BottomSheetUI("Reader Preferences") {
ReaderPreferencesView(webReaderViewModel)
when (bottomSheetState) {
BottomSheetState.PREFERENCES -> {
BottomSheetUI("Reader Preferences") {
ReaderPreferencesView(webReaderViewModel)
}
}
BottomSheetState.NOTEBOOK -> {
webReaderParams?.let { params ->
BottomSheetUI(title = "Notebook") {
NotebookView(savedItemId = params.item.savedItemId, viewModel = notebookViewModel)
}
}
}
BottomSheetState.HIGHLIGHTNOTE -> {
}
BottomSheetState.NONE -> {
}
}
Spacer(modifier = Modifier.weight(1.0F))
@ -186,9 +215,10 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, o
}
webReaderParams?.let {
IconButton(onClick = {
val intent = Intent(context, NotebookActivity::class.java)
intent.putExtra("SAVED_ITEM_ID", it.item.savedItemId)
context.startActivity(intent)
bottomSheetState = BottomSheetState.NOTEBOOK
coroutineScope.launch {
modalBottomSheetState.show()
}
}) {
Icon(
painter = painterResource(id = R.drawable.notebook),
@ -198,7 +228,7 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, o
}
}
IconButton(onClick = {
showWebPreferencesDialog = true
bottomSheetState = BottomSheetState.PREFERENCES
coroutineScope.launch {
modalBottomSheetState.show()
}
@ -219,7 +249,7 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, o
webReaderParams?.let { params ->
SavedItemContextMenu(
isExpanded = isMenuExpanded,
isArchived = webReaderParams!!.item.isArchived,
isArchived = params.item.isArchived,
onDismiss = { isMenuExpanded = false },
actionHandler = {
webReaderViewModel.handleSavedItemAction(
@ -269,8 +299,6 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, o
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
@Composable
fun BottomSheetUI(title: String?, content: @Composable () -> Unit) {
val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
Box(
modifier = Modifier
.wrapContentHeight()