diff --git a/android/Omnivore/app/build.gradle b/android/Omnivore/app/build.gradle index dda1a8cc8..2decf0cf9 100644 --- a/android/Omnivore/app/build.gradle +++ b/android/Omnivore/app/build.gradle @@ -17,8 +17,8 @@ android { applicationId "app.omnivore.omnivore" minSdk 26 targetSdk 33 - versionCode 47 - versionName "0.0.47" + versionCode 50 + versionName "0.0.50" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt index 5476df750..fe5d75097 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Constants.kt @@ -15,6 +15,7 @@ object DatastoreKeys { const val preferredWebMaxWidthPercentage = "preferredWebMaxWidthPercentage" const val preferredWebFontFamily = "preferredWebFontFamily" const val prefersWebHighContrastText = "prefersWebHighContrastText" + const val prefersJustifyText = "prefersJustifyText" const val lastUsedSavedItemFilter = "lastUsedSavedItemFilter" const val lastUsedSavedItemSortFilter = "lastUsedSavedItemSortFilter" const val preferredTheme = "preferredTheme" diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/components/LabelChip.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/components/LabelChip.kt new file mode 100644 index 000000000..5f56c3c23 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/components/LabelChip.kt @@ -0,0 +1,33 @@ +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.selection.toggleable +import androidx.compose.material.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import app.omnivore.omnivore.ui.components.LabelChipColors + +@Composable +fun LabelChip( + name: String, + colors: LabelChipColors, + onSelectionChanged: (String) -> Unit = {}, +) { + Surface( + modifier = Modifier.padding(4.dp), + shape = MaterialTheme.shapes.medium, + color = colors.containerColor + ) { + Row(modifier = Modifier + ) { + Text( + text = name, + color = colors.textColor, + style = MaterialTheme.typography.subtitle2, + modifier = Modifier.padding(vertical = 3.dp, horizontal = 5.dp) + ) + } + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/components/LabelsSelectionSheet.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/components/LabelsSelectionSheet.kt index f441e0172..0824d11dc 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/components/LabelsSelectionSheet.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/components/LabelsSelectionSheet.kt @@ -1,20 +1,31 @@ +@file:OptIn(ExperimentalMaterialApi::class) + package app.omnivore.omnivore.ui.components +import LabelChip import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +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.AddCircle import androidx.compose.material.icons.filled.Check +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.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog @@ -29,28 +40,37 @@ fun WebReaderLabelsSelectionSheet(viewModel: WebReaderViewModel) { val labels: List by viewModel.savedItemLabelsLiveData.observeAsState(listOf()) val webReaderParams: WebReaderParams? by viewModel.webReaderParamsLiveData.observeAsState(null) + val modalBottomSheetState = rememberModalBottomSheetState( + ModalBottomSheetValue.HalfExpanded, + confirmStateChange = { it != ModalBottomSheetValue.Hidden } + ) + if (isActive) { - Dialog(onDismissRequest = { - viewModel.showLabelsSelectionSheetLiveData.value = false - } ) { - LabelsSelectionSheetContent( - labels = labels, - initialSelectedLabels = webReaderParams?.labels ?: listOf(), - onCancel = { - viewModel.showLabelsSelectionSheetLiveData.value = false - }, - isLibraryMode = false, - onSave = { - if (it != labels) { - viewModel.updateSavedItemLabels(savedItemID = webReaderParams?.item?.savedItemId ?: "", labels = it) - } - viewModel.showLabelsSelectionSheetLiveData.value = false - }, - onCreateLabel = { newLabelName, labelHexValue -> - viewModel.createNewSavedItemLabel(newLabelName, labelHexValue) + ModalBottomSheetLayout( + sheetBackgroundColor = Color.Transparent, + sheetState = modalBottomSheetState, + sheetContent = { + BottomSheetUI { + LabelsSelectionSheetContent( + labels = labels, + initialSelectedLabels = webReaderParams?.labels ?: listOf(), + onCancel = { + viewModel.showLabelsSelectionSheetLiveData.value = false + }, + isLibraryMode = false, + onSave = { + if (it != labels) { + viewModel.updateSavedItemLabels(savedItemID = webReaderParams?.item?.savedItemId ?: "", labels = it) + } + viewModel.showLabelsSelectionSheetLiveData.value = false + }, + onCreateLabel = { newLabelName, labelHexValue -> + viewModel.createNewSavedItemLabel(newLabelName, labelHexValue) + } + ) } - ) - } + } + ) {} } } @@ -60,48 +80,59 @@ fun LabelsSelectionSheet(viewModel: LibraryViewModel) { val labels: List by viewModel.savedItemLabelsLiveData.observeAsState(listOf()) val currentSavedItemData = viewModel.currentSavedItemUnderEdit() + val modalBottomSheetState = rememberModalBottomSheetState( + ModalBottomSheetValue.HalfExpanded, + confirmStateChange = { it != ModalBottomSheetValue.Hidden } + ) + if (isActive) { - Dialog(onDismissRequest = { - viewModel.labelsSelectionCurrentItemLiveData.value = null - viewModel.showLabelsSelectionSheetLiveData.value = false - } ) { - if (currentSavedItemData != null) { - LabelsSelectionSheetContent( - labels = labels, - initialSelectedLabels = currentSavedItemData.labels, - onCancel = { - viewModel.showLabelsSelectionSheetLiveData.value = false - viewModel.labelsSelectionCurrentItemLiveData.value = null - }, - isLibraryMode = false, - onSave = { - if (it != labels) { - viewModel.updateSavedItemLabels(savedItemID = currentSavedItemData.savedItem.savedItemId, labels = it) - } - viewModel.labelsSelectionCurrentItemLiveData.value = null - viewModel.showLabelsSelectionSheetLiveData.value = false - }, - onCreateLabel = { newLabelName, labelHexValue -> - viewModel.createNewSavedItemLabel(newLabelName, labelHexValue) + ModalBottomSheetLayout( + sheetBackgroundColor = Color.Transparent, + sheetState = modalBottomSheetState, + sheetContent = { + BottomSheetUI { + if (currentSavedItemData != null) { + LabelsSelectionSheetContent( + labels = labels, + initialSelectedLabels = currentSavedItemData.labels, + onCancel = { + viewModel.showLabelsSelectionSheetLiveData.value = false + viewModel.labelsSelectionCurrentItemLiveData.value = null + }, + isLibraryMode = false, + onSave = { + if (it != labels) { + viewModel.updateSavedItemLabels( + savedItemID = currentSavedItemData.savedItem.savedItemId, + labels = it + ) + } + viewModel.labelsSelectionCurrentItemLiveData.value = null + viewModel.showLabelsSelectionSheetLiveData.value = false + }, + onCreateLabel = { newLabelName, labelHexValue -> + viewModel.createNewSavedItemLabel(newLabelName, labelHexValue) + } + ) + } else { // Is used in library mode + LabelsSelectionSheetContent( + labels = labels, + initialSelectedLabels = viewModel.activeLabelsLiveData.value ?: listOf(), + onCancel = { viewModel.showLabelsSelectionSheetLiveData.value = false }, + isLibraryMode = true, + onSave = { + viewModel.updateAppliedLabels(it) + viewModel.labelsSelectionCurrentItemLiveData.value = null + viewModel.showLabelsSelectionSheetLiveData.value = false + }, + onCreateLabel = { newLabelName, labelHexValue -> + viewModel.createNewSavedItemLabel(newLabelName, labelHexValue) + } + ) } - ) - } else { // Is used in library mode - LabelsSelectionSheetContent( - labels = labels, - initialSelectedLabels = viewModel.activeLabelsLiveData.value ?: listOf(), - onCancel = { viewModel.showLabelsSelectionSheetLiveData.value = false }, - isLibraryMode = true, - onSave = { - viewModel.updateAppliedLabels(it) - viewModel.labelsSelectionCurrentItemLiveData.value = null - viewModel.showLabelsSelectionSheetLiveData.value = false - }, - onCreateLabel = { newLabelName, labelHexValue -> - viewModel.createNewSavedItemLabel(newLabelName, labelHexValue) - } - ) + } } - } + ) {} } } @@ -125,7 +156,6 @@ fun LabelsSelectionSheetContent( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background), - shape = RoundedCornerShape(16.dp) ) { if (showCreateLabelDialog) { @@ -142,8 +172,9 @@ fun LabelsSelectionSheetContent( verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier + // .verticalScroll(rememberScrollState()) .fillMaxSize() - .padding(horizontal = 6.dp) + .padding(horizontal = 0.dp) ) { Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -158,7 +189,7 @@ fun LabelsSelectionSheetContent( Text(titleText, fontWeight = FontWeight.ExtraBold) TextButton(onClick = { onSave(selectedLabels.value) }) { - Text(text = "Done") + Text(text = "Save") } } LazyColumn( @@ -184,19 +215,13 @@ fun LabelsSelectionSheetContent( selectedLabels.value = selectedLabels.value + listOf(label) } } - .padding(horizontal = 6.dp) + .padding(horizontal = 10.dp, vertical = 6.dp) ) { val chipColors = LabelChipColors.fromHex(label.color) - SuggestionChip( - onClick = {}, - label = { Text(label.name) }, - border = null, - colors = SuggestionChipDefaults.elevatedSuggestionChipColors( - containerColor = chipColors.containerColor, - labelColor = chipColors.textColor, - iconContentColor = chipColors.textColor - ) + LabelChip( + name = label.name, + colors = chipColors ) if (isLabelSelected) { Icon( @@ -233,3 +258,17 @@ fun LabelsSelectionSheetContent( } } } + +@Composable +private fun BottomSheetUI(content: @Composable () -> Unit) { + Box( + modifier = Modifier + .wrapContentHeight() + .fillMaxWidth() + .clip(RoundedCornerShape(topEnd = 20.dp, topStart = 20.dp)) + .background(Color.White) + .statusBarsPadding() + ) { + content() + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebPreferencesDialog.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebPreferencesDialog.kt index 769c8a6a0..3a967f554 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebPreferencesDialog.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebPreferencesDialog.kt @@ -49,6 +49,9 @@ fun WebPreferencesView(webReaderViewModel: WebReaderViewModel) { val currentWebPreferences = webReaderViewModel.storedWebPreferences(isDark) val isFontListExpanded = remember { mutableStateOf(false) } val highContrastTextSwitchState = remember { mutableStateOf(currentWebPreferences.prefersHighContrastText) } + + val justifyTextSwitchState = remember { mutableStateOf(currentWebPreferences.prefersJustifyText) } + val selectedWebFontRawValue = remember { mutableStateOf(currentWebPreferences.fontFamily.rawValue) } Column( @@ -98,6 +101,18 @@ fun WebPreferencesView(webReaderViewModel: WebReaderViewModel) { ) } + Row(verticalAlignment = Alignment.CenterVertically) { + Text("Justify Text") + Spacer(modifier = Modifier.weight(1.0F)) + Switch( + checked = justifyTextSwitchState.value, + onCheckedChange = { + justifyTextSwitchState.value = it + webReaderViewModel.updateJustifyText(it) + } + ) + } + Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier @@ -200,5 +215,6 @@ data class WebPreferences( val themeKey: String, val storedThemePreference: String, val fontFamily: WebFont, - val prefersHighContrastText: Boolean + val prefersHighContrastText: Boolean, + val prefersJustifyText: Boolean ) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt index c2e827b9b..c4576e921 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReader.kt @@ -30,8 +30,8 @@ import java.util.* @SuppressLint("SetJavaScriptEnabled") @Composable fun WebReader( - params: WebReaderParams, preferences: WebPreferences, + styledContent: String, webReaderViewModel: WebReaderViewModel ) { val javascriptActionLoopUUID: UUID by webReaderViewModel @@ -40,23 +40,9 @@ fun WebReader( WebView.setWebContentsDebuggingEnabled(true) - val webReaderContent = WebReaderContent( - preferences = preferences, - item = params.item, - articleContent = params.articleContent, - ) - - val styledContent = webReaderContent.styledContent() - val isInDarkMode = preferences.themeKey == "Dark" - Box { AndroidView(factory = { OmnivoreWebView(it).apply { - if (isInDarkMode) { - setBackgroundColor(Color.Transparent.hashCode()) - } else { - setBackgroundColor(Color.White.hashCode()) - } viewModel = webReaderViewModel layoutParams = ViewGroup.LayoutParams( diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderContent.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderContent.kt index e5b2fb966..aaf518016 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderContent.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderContent.kt @@ -43,11 +43,11 @@ data class WebReaderContent( val articleContent: ArticleContent, ) { fun styledContent(): String { - // TODO: Kotlinize these three values (pasted from Swift) - val savedAt = "new Date(1662571290735.0).toISOString()" - val createdAt = "new Date().toISOString()" - val publishedAt = - "new Date().toISOString()" //if (item.publishDate != null) "new Date((item.publishDate!.timeIntervalSince1970 * 1000)).toISOString()" else "undefined" + val savedAt = "\"${item.savedAt}\"" + val createdAt = "\"${item.createdAt}\"" + val publishedAt = if (item.publishDate != null) "\"${item.publishDate}\"" else "undefined" + + val textFontSize = preferences.textFontSize val highlightCssFilePath = "highlight${if (preferences.themeKey == "Dark") "-dark" else ""}.css" @@ -80,9 +80,9 @@ data class WebReaderContent( id: "${item.savedItemId}", linkId: "${item.savedItemId}", slug: "${item.slug}", - createdAt: new Date(1662571290735.0).toISOString(), - savedAt: new Date(1662571290981.0).toISOString(), - publishedAt: new Date(1662454816000.0).toISOString(), + createdAt: ${createdAt}, + savedAt: ${savedAt}, + publishedAt: ${publishedAt}, url: `${item.pageURLString}`, title: `${articleContent.title.replace("`", "\\`")}`, content: document.getElementById('_omnivore-htmlContent').innerHTML, @@ -100,6 +100,7 @@ data class WebReaderContent( window.maxWidthPercentage = ${preferences.maxWidthPercentage} window.lineHeight = ${preferences.lineHeight} window.prefersHighContrastFont = ${preferences.prefersHighContrastText} + window.justifyText = ${preferences.prefersJustifyText} window.enableHighlightBar = false diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderLoadingContainer.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderLoadingContainer.kt index 53fa6c433..5230b381e 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderLoadingContainer.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderLoadingContainer.kt @@ -122,17 +122,26 @@ fun WebReaderLoadingContainer(slug: String? = null, requestID: String? = null, o webReaderViewModel.maxToolbarHeightPx = with(LocalDensity.current) { maxToolbarHeight.roundToPx().toFloat() } webReaderViewModel.loadItem(slug = slug, requestID = requestID) + val styledContent = webReaderParams?.let { + val webReaderContent = WebReaderContent( + preferences = webReaderViewModel.storedWebPreferences(isSystemInDarkTheme()), + item = it.item, + articleContent = it.articleContent, + ) + webReaderContent.styledContent() + } ?: null + Box( modifier = Modifier .fillMaxSize() .systemBarsPadding() .background(color = backgroundColor) ) { - if (webReaderParams != null) { + if (styledContent != null) { WebReader( - webReaderParams!!, - webReaderViewModel.storedWebPreferences(isSystemInDarkTheme()), - webReaderViewModel + preferences = webReaderViewModel.storedWebPreferences(isSystemInDarkTheme()), + styledContent = styledContent, + webReaderViewModel = webReaderViewModel ) TopAppBar( diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt index 38d037106..adfe7f46b 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/reader/WebReaderViewModel.kt @@ -56,7 +56,8 @@ class WebReaderViewModel @Inject constructor( val showLabelsSelectionSheetLiveData = MutableLiveData(false) val savedItemLabelsLiveData = dataService.db.savedItemLabelDao().getSavedItemLabelsLiveData() - val systemThemeKeys = listOf("Light", "Dark", "System") + // "Sepia", "Apollo", + val systemThemeKeys = listOf("Light", "Black", "System") var hasTappedExistingHighlight = false var lastTapCoordinates: TapCoordinates? = null @@ -265,6 +266,7 @@ class WebReaderViewModel @Inject constructor( val storedWebFont = WebFont.values().first { it.rawValue == storedFontFamily } val prefersHighContrastFont = datastoreRepo.getString(DatastoreKeys.prefersWebHighContrastText) == "true" + val prefersJustifyText = datastoreRepo.getString(DatastoreKeys.prefersJustifyText) == "true" WebPreferences( textFontSize = storedFontSize ?: 12, @@ -273,13 +275,14 @@ class WebReaderViewModel @Inject constructor( themeKey = themeKey(isDarkMode, storedThemePreference), storedThemePreference = storedThemePreference, fontFamily = storedWebFont, - prefersHighContrastText = prefersHighContrastFont + prefersHighContrastText = prefersHighContrastFont, + prefersJustifyText = prefersJustifyText ) } fun themeKey(isDarkMode: Boolean, storedThemePreference: String): String { if (storedThemePreference == "System") { - return if (isDarkMode) "Dark" else "Light" + return if (isDarkMode) "Black" else "Light" } return storedThemePreference @@ -292,7 +295,7 @@ class WebReaderViewModel @Inject constructor( datastoreRepo.putString(DatastoreKeys.preferredTheme, systemThemeKeys[index]) } - val isDark = newThemeKey == "Dark" + val isDark = newThemeKey == "Dark" || newThemeKey == "Black" val script = "var event = new Event('updateColorMode');event.isDark = '$isDark';document.dispatchEvent(event);" enqueueScript(script) } @@ -351,6 +354,14 @@ class WebReaderViewModel @Inject constructor( enqueueScript(script) } + fun updateJustifyText(justifyText: Boolean) { + runBlocking { + datastoreRepo.putString(DatastoreKeys.prefersJustifyText, justifyText.toString()) + } + val script = "var event = new Event('updateJustifyText');event.justifyText = $justifyText;document.dispatchEvent(event);" + enqueueScript(script) + } + fun applyWebFont(font: WebFont) { runBlocking { datastoreRepo.putString(DatastoreKeys.preferredWebFontFamily, font.rawValue) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveSheetActivity.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveSheetActivity.kt index 5786f261e..9648fdd25 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveSheetActivity.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveSheetActivity.kt @@ -39,12 +39,11 @@ abstract class SaveSheetActivityBase: AppCompatActivity() { Intent.ACTION_SEND -> { if (intent.type?.startsWith("text/plain") == true) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { - Log.d(ContentValues.TAG, "Extracted text: $extractedText") extractedText = it viewModel.saveURL(it) + Log.d(ContentValues.TAG, "Extracted text: $extractedText") } } - if (intent.type?.startsWith("text/html") == true) { intent.getStringExtra(Intent.EXTRA_HTML_TEXT)?.let { extractedText = it @@ -155,7 +154,9 @@ abstract class SaveSheetActivityBase: AppCompatActivity() { viewModel: SaveViewModel, modalBottomSheetState: ModalBottomSheetState ) { - Box(modifier = Modifier.height(300.dp).background(Color.White)) { + Box(modifier = Modifier + .height(300.dp) + .background(Color.White)) { SaveContent(viewModel, modalBottomSheetState, modifier = Modifier.fillMaxSize()) } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt index b02e92f59..05ad7b3d6 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/save/SaveViewModel.kt @@ -17,6 +17,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import java.util.* +import java.util.regex.Pattern import javax.inject.Inject @HiltViewModel @@ -36,6 +37,11 @@ class SaveViewModel @Inject constructor( datastoreRepo.getString(DatastoreKeys.omnivoreAuthToken) } + fun cleanUrl(url: String): String? { + return Regex("https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)") + .findAll(url).map { it.value }.first() + } + fun saveURL(url: String) { viewModelScope.launch { isLoading = true @@ -54,6 +60,9 @@ class SaveViewModel @Inject constructor( .addHttpHeader("Authorization", value = authToken) .build() + // Attempt to parse the URL out of the text, if that fails send the text + val cleanedUrl = cleanUrl(url) ?: url + try { clientRequestID = UUID.randomUUID().toString() @@ -62,7 +71,7 @@ class SaveViewModel @Inject constructor( SaveUrlInput( clientRequestId = clientRequestID!!, source = "android", - url = url + url = cleanedUrl ) ) ).execute() diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/savedItemViews/SavedItemCard.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/savedItemViews/SavedItemCard.kt index 2cfc42db2..1144ced03 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/savedItemViews/SavedItemCard.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/savedItemViews/SavedItemCard.kt @@ -1,5 +1,6 @@ package app.omnivore.omnivore.ui.savedItemViews +import LabelChip import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow @@ -102,21 +103,16 @@ fun SavedItemCard(savedItemViewModel: SavedItemViewModel, savedItem: SavedItemWi horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically, modifier = Modifier - .padding(start = 10.dp, bottom = 5.dp, end = 10.dp) + .padding(start = 5.dp, bottom = 5.dp, end = 10.dp) ) { items(savedItem.labels.sortedBy { it.name }) { label -> val chipColors = LabelChipColors.fromHex(label.color) - SuggestionChip( - onClick = onClickHandler, - label = { Text(label.name) }, - border = null, - colors = elevatedSuggestionChipColors( - containerColor = chipColors.containerColor, - labelColor = chipColors.textColor, - iconContentColor = chipColors.textColor - ), - modifier = Modifier.padding(end = 5.dp) + LabelChip( + // onClick = onClickHandler, + name = label.name, + colors = chipColors, + // modifier = Modifier.padding(end = 5.dp) ) }