add url preview settings
This commit is contained in:
@@ -72,6 +72,7 @@ private object PrefKeys {
|
|||||||
const val AUTOMATICALLY_START_PLAYBACK = "automatically_start_playback"
|
const val AUTOMATICALLY_START_PLAYBACK = "automatically_start_playback"
|
||||||
const val THEME = "theme"
|
const val THEME = "theme"
|
||||||
const val PREFERRED_LANGUAGE = "preferred_Language"
|
const val PREFERRED_LANGUAGE = "preferred_Language"
|
||||||
|
const val AUTOMATICALLY_LOAD_URL_PREVIEW = "automatically_load_url_preview"
|
||||||
val LAST_READ: (String) -> String = { route -> "last_read_route_$route" }
|
val LAST_READ: (String) -> String = { route -> "last_read_route_$route" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,6 +256,11 @@ object LocalPreferences {
|
|||||||
} else {
|
} else {
|
||||||
putBoolean(PrefKeys.AUTOMATICALLY_START_PLAYBACK, account.settings.automaticallyStartPlayback!!)
|
putBoolean(PrefKeys.AUTOMATICALLY_START_PLAYBACK, account.settings.automaticallyStartPlayback!!)
|
||||||
}
|
}
|
||||||
|
if (account.settings.automaticallyShowUrlPreview == null) {
|
||||||
|
remove(PrefKeys.AUTOMATICALLY_LOAD_URL_PREVIEW)
|
||||||
|
} else {
|
||||||
|
putBoolean(PrefKeys.AUTOMATICALLY_LOAD_URL_PREVIEW, account.settings.automaticallyShowUrlPreview!!)
|
||||||
|
}
|
||||||
putString(PrefKeys.PREFERRED_LANGUAGE, account.settings.preferredLanguage ?: "")
|
putString(PrefKeys.PREFERRED_LANGUAGE, account.settings.preferredLanguage ?: "")
|
||||||
}.apply()
|
}.apply()
|
||||||
}
|
}
|
||||||
@@ -396,6 +402,11 @@ object LocalPreferences {
|
|||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
settings.automaticallyShowUrlPreview = if (contains(PrefKeys.AUTOMATICALLY_LOAD_URL_PREVIEW)) {
|
||||||
|
getBoolean(PrefKeys.AUTOMATICALLY_LOAD_URL_PREVIEW, false)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
settings.preferredLanguage = getString(PrefKeys.PREFERRED_LANGUAGE, "")
|
settings.preferredLanguage = getString(PrefKeys.PREFERRED_LANGUAGE, "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,9 +86,14 @@ class Account(
|
|||||||
|
|
||||||
var userProfileCache: User? = null
|
var userProfileCache: User? = null
|
||||||
|
|
||||||
fun updateGlobalSettings(automaticallyShowImages: Boolean?, automaticallyStartPlayback: Boolean?) {
|
fun updateGlobalSettings(
|
||||||
|
automaticallyShowImages: Boolean?,
|
||||||
|
automaticallyStartPlayback: Boolean?,
|
||||||
|
automaticallyShowUrlPreview: Boolean?
|
||||||
|
) {
|
||||||
settings.automaticallyStartPlayback = automaticallyStartPlayback
|
settings.automaticallyStartPlayback = automaticallyStartPlayback
|
||||||
settings.automaticallyShowImages = automaticallyShowImages
|
settings.automaticallyShowImages = automaticallyShowImages
|
||||||
|
settings.automaticallyShowUrlPreview = automaticallyShowUrlPreview
|
||||||
live.invalidateData()
|
live.invalidateData()
|
||||||
saveable.invalidateData()
|
saveable.invalidateData()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ import androidx.compose.runtime.Stable
|
|||||||
class Settings(
|
class Settings(
|
||||||
var automaticallyShowImages: Boolean? = null,
|
var automaticallyShowImages: Boolean? = null,
|
||||||
var automaticallyStartPlayback: Boolean? = null,
|
var automaticallyStartPlayback: Boolean? = null,
|
||||||
var preferredLanguage: String? = null
|
var preferredLanguage: String? = null,
|
||||||
|
var automaticallyShowUrlPreview: Boolean? = null
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ fun NewPostView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
|
|||||||
} else if (videoExtensions.any { removedParamsFromUrl.endsWith(it) }) {
|
} else if (videoExtensions.any { removedParamsFromUrl.endsWith(it) }) {
|
||||||
VideoView(myUrlPreview, automaticallyStartPlayback = remember { mutableStateOf(true) })
|
VideoView(myUrlPreview, automaticallyStartPlayback = remember { mutableStateOf(true) })
|
||||||
} else {
|
} else {
|
||||||
UrlPreview(myUrlPreview, myUrlPreview)
|
UrlPreview(myUrlPreview, myUrlPreview, remember { mutableStateOf(true) })
|
||||||
}
|
}
|
||||||
} else if (startsWithNIP19Scheme(myUrlPreview)) {
|
} else if (startsWithNIP19Scheme(myUrlPreview)) {
|
||||||
val bgColor = MaterialTheme.colors.background
|
val bgColor = MaterialTheme.colors.background
|
||||||
@@ -348,7 +348,7 @@ fun NewPostView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
|
|||||||
nav
|
nav
|
||||||
)
|
)
|
||||||
} else if (noProtocolUrlValidator.matcher(myUrlPreview).matches()) {
|
} else if (noProtocolUrlValidator.matcher(myUrlPreview).matches()) {
|
||||||
UrlPreview("https://$myUrlPreview", myUrlPreview)
|
UrlPreview("https://$myUrlPreview", myUrlPreview, remember { mutableStateOf(true) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -68,6 +68,16 @@ fun ExpandableRichTextViewer(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val automaticallyShowUrlPreview = remember {
|
||||||
|
mutableStateOf(
|
||||||
|
when (settings?.automaticallyShowUrlPreview) {
|
||||||
|
true -> !isMobile
|
||||||
|
false -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
var showFullText by remember { mutableStateOf(false) }
|
var showFullText by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
val whereToCut = remember(content) {
|
val whereToCut = remember(content) {
|
||||||
@@ -98,6 +108,7 @@ fun ExpandableRichTextViewer(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
showImage,
|
showImage,
|
||||||
automaticallyStartPlayback,
|
automaticallyStartPlayback,
|
||||||
|
automaticallyShowUrlPreview,
|
||||||
nav
|
nav
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -110,13 +110,14 @@ fun RichTextViewer(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
showImage: MutableState<Boolean>,
|
showImage: MutableState<Boolean>,
|
||||||
automaticallyStartPlayback: MutableState<Boolean>,
|
automaticallyStartPlayback: MutableState<Boolean>,
|
||||||
|
automaticallyShowUrlPreview: MutableState<Boolean>,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
if (remember(content) { isMarkdown(content) }) {
|
if (remember(content) { isMarkdown(content) }) {
|
||||||
RenderContentAsMarkdown(content, tags, nav)
|
RenderContentAsMarkdown(content, tags, nav)
|
||||||
} else {
|
} else {
|
||||||
RenderRegular(content, tags, canPreview, backgroundColor, accountViewModel, showImage, automaticallyStartPlayback, nav)
|
RenderRegular(content, tags, canPreview, backgroundColor, accountViewModel, showImage, automaticallyStartPlayback, automaticallyShowUrlPreview, nav)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,6 +132,7 @@ private fun RenderRegular(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
showImage: MutableState<Boolean>,
|
showImage: MutableState<Boolean>,
|
||||||
automaticallyStartPlayback: MutableState<Boolean>,
|
automaticallyStartPlayback: MutableState<Boolean>,
|
||||||
|
automaticallyShowUrlPreview: MutableState<Boolean>,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val state by remember(content) {
|
val state by remember(content) {
|
||||||
@@ -162,6 +164,7 @@ private fun RenderRegular(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
showImage,
|
showImage,
|
||||||
automaticallyStartPlayback,
|
automaticallyStartPlayback,
|
||||||
|
automaticallyShowUrlPreview,
|
||||||
nav
|
nav
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -243,11 +246,12 @@ private fun RenderWordWithPreview(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
showImage: MutableState<Boolean>,
|
showImage: MutableState<Boolean>,
|
||||||
automaticallyStartPlayback: MutableState<Boolean>,
|
automaticallyStartPlayback: MutableState<Boolean>,
|
||||||
|
automaticallyShowUrlPreview: MutableState<Boolean>,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
when (word) {
|
when (word) {
|
||||||
is ImageSegment -> ZoomableContentView(word.segmentText, state, showImage, automaticallyStartPlayback)
|
is ImageSegment -> ZoomableContentView(word.segmentText, state, showImage, automaticallyStartPlayback)
|
||||||
is LinkSegment -> UrlPreview(word.segmentText, word.segmentText)
|
is LinkSegment -> UrlPreview(word.segmentText, word.segmentText, automaticallyShowUrlPreview)
|
||||||
is EmojiSegment -> RenderCustomEmoji(word.segmentText, state)
|
is EmojiSegment -> RenderCustomEmoji(word.segmentText, state)
|
||||||
is InvoiceSegment -> MayBeInvoicePreview(word.segmentText)
|
is InvoiceSegment -> MayBeInvoicePreview(word.segmentText)
|
||||||
is WithdrawSegment -> MayBeWithdrawal(word.segmentText)
|
is WithdrawSegment -> MayBeWithdrawal(word.segmentText)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import androidx.compose.animation.Crossfade
|
|||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
@@ -13,33 +14,41 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UrlPreview(url: String, urlText: String) {
|
fun UrlPreview(url: String, urlText: String, automaticallyShowUrlPreview: MutableState<Boolean>) {
|
||||||
var urlPreviewState by remember(url) {
|
if (!automaticallyShowUrlPreview.value) {
|
||||||
mutableStateOf(
|
ClickableUrl(urlText, url)
|
||||||
UrlCachedPreviewer.cache.get(url)?.let { it } ?: UrlPreviewState.Loading
|
} else {
|
||||||
)
|
var urlPreviewState by remember(url) {
|
||||||
}
|
mutableStateOf(
|
||||||
|
UrlCachedPreviewer.cache.get(url)?.let { it } ?: UrlPreviewState.Loading
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Doesn't use a viewModel because of viewModel reusing issues (too many UrlPreview are created).
|
// Doesn't use a viewModel because of viewModel reusing issues (too many UrlPreview are created).
|
||||||
if (urlPreviewState == UrlPreviewState.Loading) {
|
if (urlPreviewState == UrlPreviewState.Loading) {
|
||||||
LaunchedEffect(url) {
|
LaunchedEffect(url) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
UrlCachedPreviewer.previewInfo(url) {
|
UrlCachedPreviewer.previewInfo(url) {
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
urlPreviewState = it
|
urlPreviewState = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Crossfade(targetState = urlPreviewState, animationSpec = tween(durationMillis = 100)) { state ->
|
Crossfade(
|
||||||
when (state) {
|
targetState = urlPreviewState,
|
||||||
is UrlPreviewState.Loaded -> {
|
animationSpec = tween(durationMillis = 100)
|
||||||
UrlPreviewCard(url, state.previewInfo)
|
) { state ->
|
||||||
}
|
when (state) {
|
||||||
else -> {
|
is UrlPreviewState.Loaded -> {
|
||||||
ClickableUrl(urlText, url)
|
UrlPreviewCard(url, state.previewInfo, automaticallyShowUrlPreview)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
ClickableUrl(urlText, url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -26,8 +27,12 @@ import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
|||||||
@Composable
|
@Composable
|
||||||
fun UrlPreviewCard(
|
fun UrlPreviewCard(
|
||||||
url: String,
|
url: String,
|
||||||
previewInfo: UrlInfoItem
|
previewInfo: UrlInfoItem,
|
||||||
|
automaticallyShowUrlPreview: MutableState<Boolean>
|
||||||
) {
|
) {
|
||||||
|
if (!automaticallyShowUrlPreview.value) {
|
||||||
|
return ClickableUrl(url, url)
|
||||||
|
}
|
||||||
val uri = LocalUriHandler.current
|
val uri = LocalUriHandler.current
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@@ -49,8 +49,12 @@ class AccountViewModel(val account: Account, private val themeViewModel: ThemeVi
|
|||||||
return themeViewModel.theme.value ?: "System"
|
return themeViewModel.theme.value ?: "System"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateGlobalSettings(automaticallyShowImages: Boolean?, automaticallyStartPlayback: Boolean?) {
|
fun updateGlobalSettings(
|
||||||
account.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback)
|
automaticallyShowImages: Boolean?,
|
||||||
|
automaticallyStartPlayback: Boolean?,
|
||||||
|
automaticallyShowUrlPreview: Boolean?
|
||||||
|
) {
|
||||||
|
account.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback, automaticallyShowUrlPreview)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isWriteable(): Boolean {
|
fun isWriteable(): Boolean {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
|||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
||||||
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
|
|
||||||
import com.vitorpamplona.amethyst.service.model.AppDefinitionEvent
|
import com.vitorpamplona.amethyst.service.model.AppDefinitionEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.BadgeDefinitionEvent
|
import com.vitorpamplona.amethyst.service.model.BadgeDefinitionEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.BadgeProfilesEvent
|
import com.vitorpamplona.amethyst.service.model.BadgeProfilesEvent
|
||||||
@@ -599,20 +598,6 @@ private fun ProfileHeader(
|
|||||||
var popupExpanded by remember { mutableStateOf(false) }
|
var popupExpanded by remember { mutableStateOf(false) }
|
||||||
var zoomImageDialogOpen by remember { mutableStateOf(false) }
|
var zoomImageDialogOpen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
|
||||||
val settings = accountState?.account?.settings
|
|
||||||
val isMobile = ConnectivityStatus.isOnMobileData.value
|
|
||||||
|
|
||||||
val showImage = remember {
|
|
||||||
mutableStateOf(
|
|
||||||
when (settings?.automaticallyShowImages) {
|
|
||||||
true -> !isMobile
|
|
||||||
false -> false
|
|
||||||
else -> true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Box {
|
Box {
|
||||||
DrawBanner(baseUser)
|
DrawBanner(baseUser)
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,12 @@ fun SettingsScreen(
|
|||||||
val selectedVideoItem = remember {
|
val selectedVideoItem = remember {
|
||||||
mutableStateOf(selectedItens[videoIndex])
|
mutableStateOf(selectedItens[videoIndex])
|
||||||
}
|
}
|
||||||
|
val linkIndex = if (settings.automaticallyShowUrlPreview == null) { 0 } else {
|
||||||
|
if (settings.automaticallyShowUrlPreview == true) 1 else 2
|
||||||
|
}
|
||||||
|
val selectedLinkItem = remember {
|
||||||
|
mutableStateOf(selectedItens[linkIndex])
|
||||||
|
}
|
||||||
|
|
||||||
val themeItens = arrayOf("System", "Light", "Dark")
|
val themeItens = arrayOf("System", "Light", "Dark")
|
||||||
val themeIndex = themeItens.indexOf(accountViewModel.currentTheme())
|
val themeIndex = themeItens.indexOf(accountViewModel.currentTheme())
|
||||||
@@ -216,6 +222,12 @@ fun SettingsScreen(
|
|||||||
title = "Automatically play videos"
|
title = "Automatically play videos"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
DropDownSettings(
|
||||||
|
selectedItem = selectedLinkItem,
|
||||||
|
listItems = selectedItens,
|
||||||
|
title = "Automatically show url preview"
|
||||||
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
Modifier.fillMaxWidth(),
|
Modifier.fillMaxWidth(),
|
||||||
Arrangement.Center
|
Arrangement.Center
|
||||||
@@ -232,10 +244,15 @@ fun SettingsScreen(
|
|||||||
2 -> false
|
2 -> false
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
val automaticallyShowUrlPreview = when (selectedItens.indexOf(selectedLinkItem.value)) {
|
||||||
|
1 -> true
|
||||||
|
2 -> false
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
accountViewModel.changeTheme(selectedTheme.value)
|
accountViewModel.changeTheme(selectedTheme.value)
|
||||||
|
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
accountViewModel.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback)
|
accountViewModel.updateGlobalSettings(automaticallyShowImages, automaticallyStartPlayback, automaticallyShowUrlPreview)
|
||||||
LocalPreferences.saveToEncryptedStorage(accountViewModel.account)
|
LocalPreferences.saveToEncryptedStorage(accountViewModel.account)
|
||||||
LocalPreferences.updateTheme(selectedTheme.value)
|
LocalPreferences.updateTheme(selectedTheme.value)
|
||||||
ServiceManager.pause()
|
ServiceManager.pause()
|
||||||
|
|||||||
Reference in New Issue
Block a user