add settings to load profile pictures

This commit is contained in:
greenart7c3
2023-09-27 10:48:26 -03:00
parent ed70585e90
commit e762ad5e18
23 changed files with 302 additions and 41 deletions
@@ -80,6 +80,7 @@ private object PrefKeys {
const val AUTOMATICALLY_LOAD_URL_PREVIEW = "automatically_load_url_preview" const val AUTOMATICALLY_LOAD_URL_PREVIEW = "automatically_load_url_preview"
const val AUTOMATICALLY_HIDE_NAV_BARS = "automatically_hide_nav_bars" const val AUTOMATICALLY_HIDE_NAV_BARS = "automatically_hide_nav_bars"
const val LOGIN_WITH_EXTERNAL_SIGNER = "login_with_external_signer" const val LOGIN_WITH_EXTERNAL_SIGNER = "login_with_external_signer"
const val AUTOMATICALLY_SHOW_PROFILE_PICTURE = "automatically_show_profile_picture"
} }
object LocalPreferences { object LocalPreferences {
@@ -280,6 +281,12 @@ object LocalPreferences {
} else { } else {
putBoolean(PrefKeys.AUTOMATICALLY_HIDE_NAV_BARS, account.settings.automaticallyHideNavigationBars.prefCode!!) putBoolean(PrefKeys.AUTOMATICALLY_HIDE_NAV_BARS, account.settings.automaticallyHideNavigationBars.prefCode!!)
} }
if (account.settings.automaticallyShowProfilePictures.prefCode == null) {
remove(PrefKeys.AUTOMATICALLY_SHOW_PROFILE_PICTURE)
} else {
putBoolean(PrefKeys.AUTOMATICALLY_SHOW_PROFILE_PICTURE, account.settings.automaticallyShowProfilePictures.prefCode!!)
}
putString(PrefKeys.PREFERRED_LANGUAGE, account.settings.preferredLanguage ?: "") putString(PrefKeys.PREFERRED_LANGUAGE, account.settings.preferredLanguage ?: "")
}.apply() }.apply()
} }
@@ -431,6 +438,12 @@ object LocalPreferences {
BooleanType.ALWAYS BooleanType.ALWAYS
} }
settings.automaticallyShowProfilePictures = if (contains(PrefKeys.AUTOMATICALLY_SHOW_PROFILE_PICTURE)) {
parseConnectivityType(getBoolean(PrefKeys.AUTOMATICALLY_SHOW_PROFILE_PICTURE, false))
} else {
ConnectivityType.ALWAYS
}
settings.preferredLanguage = getString(PrefKeys.PREFERRED_LANGUAGE, "") settings.preferredLanguage = getString(PrefKeys.PREFERRED_LANGUAGE, "")
} }
@@ -185,6 +185,14 @@ class Account(
saveable.invalidateData() saveable.invalidateData()
} }
fun updateAutomaticallyShowProfilePicture(
automaticallyShowProfilePicture: ConnectivityType
) {
settings.automaticallyShowProfilePictures = automaticallyShowProfilePicture
live.invalidateData()
saveable.invalidateData()
}
fun updateAutomaticallyHideHavBars( fun updateAutomaticallyHideHavBars(
automaticallyHideHavBars: BooleanType automaticallyHideHavBars: BooleanType
) { ) {
@@ -9,7 +9,8 @@ class Settings(
var automaticallyShowImages: ConnectivityType = ConnectivityType.ALWAYS, var automaticallyShowImages: ConnectivityType = ConnectivityType.ALWAYS,
var automaticallyStartPlayback: ConnectivityType = ConnectivityType.ALWAYS, var automaticallyStartPlayback: ConnectivityType = ConnectivityType.ALWAYS,
var automaticallyShowUrlPreview: ConnectivityType = ConnectivityType.ALWAYS, var automaticallyShowUrlPreview: ConnectivityType = ConnectivityType.ALWAYS,
var automaticallyHideNavigationBars: BooleanType = BooleanType.ALWAYS var automaticallyHideNavigationBars: BooleanType = BooleanType.ALWAYS,
var automaticallyShowProfilePictures: ConnectivityType = ConnectivityType.ALWAYS
) )
enum class ConnectivityType(val prefCode: Boolean?, val screenCode: Int, val reourceId: Int) { enum class ConnectivityType(val prefCode: Boolean?, val screenCode: Int, val reourceId: Int) {
@@ -54,10 +54,12 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.note.ChannelName import com.vitorpamplona.amethyst.ui.note.ChannelName
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
import com.vitorpamplona.amethyst.ui.note.SearchIcon import com.vitorpamplona.amethyst.ui.note.SearchIcon
@@ -303,6 +305,13 @@ private fun RenderSearchResults(
val users by searchBarViewModel.searchResultsUsers.collectAsState() val users by searchBarViewModel.searchResultsUsers.collectAsState()
val channels by searchBarViewModel.searchResultsChannels.collectAsState() val channels by searchBarViewModel.searchResultsChannels.collectAsState()
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
Row( Row(
modifier = Modifier modifier = Modifier
@@ -337,7 +346,7 @@ private fun RenderSearchResults(
channels, channels,
key = { _, item -> "c" + item.idHex } key = { _, item -> "c" + item.idHex }
) { _, item -> ) { _, item ->
RenderChannel(item) { RenderChannel(item, automaticallyShowProfilePicture) {
nav("Channel/${item.idHex}") nav("Channel/${item.idHex}")
searchBarViewModel.clear() searchBarViewModel.clear()
} }
@@ -350,6 +359,7 @@ private fun RenderSearchResults(
@Composable @Composable
private fun RenderChannel( private fun RenderChannel(
item: com.vitorpamplona.amethyst.model.Channel, item: com.vitorpamplona.amethyst.model.Channel,
loadProfilePicture: Boolean,
onClick: () -> Unit onClick: () -> Unit
) { ) {
val hasNewMessages = remember { val hasNewMessages = remember {
@@ -368,7 +378,8 @@ private fun RenderChannel(
channelLastTime = null, channelLastTime = null,
channelLastContent = item.summary(), channelLastContent = item.summary(),
hasNewMessages, hasNewMessages,
onClick = onClick onClick = onClick,
loadProfilePicture = loadProfilePicture
) )
} }
@@ -56,9 +56,11 @@ import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.RelayBriefInfo import com.vitorpamplona.amethyst.model.RelayBriefInfo
import com.vitorpamplona.amethyst.model.RelaySetupInfo import com.vitorpamplona.amethyst.model.RelaySetupInfo
import com.vitorpamplona.amethyst.service.Nip11Retriever import com.vitorpamplona.amethyst.service.Nip11Retriever
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.service.relays.Constants import com.vitorpamplona.amethyst.service.relays.Constants
import com.vitorpamplona.amethyst.service.relays.Constants.defaultRelays import com.vitorpamplona.amethyst.service.relays.Constants.defaultRelays
import com.vitorpamplona.amethyst.service.relays.FeedType import com.vitorpamplona.amethyst.service.relays.FeedType
@@ -258,6 +260,7 @@ fun ServerConfigHeader() {
@Composable @Composable
fun ServerConfigPreview() { fun ServerConfigPreview() {
ServerConfigClickableLine( ServerConfigClickableLine(
loadProfilePicture = true,
item = RelaySetupInfo( item = RelaySetupInfo(
url = "nostr.mom", url = "nostr.mom",
read = true, read = true,
@@ -310,7 +313,16 @@ fun ServerConfig(
) )
} }
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
ServerConfigClickableLine( ServerConfigClickableLine(
loadProfilePicture = automaticallyShowProfilePicture,
item = item, item = item,
onToggleDownload = onToggleDownload, onToggleDownload = onToggleDownload,
onToggleUpload = onToggleUpload, onToggleUpload = onToggleUpload,
@@ -351,6 +363,7 @@ fun ServerConfig(
@Composable @Composable
fun ServerConfigClickableLine( fun ServerConfigClickableLine(
loadProfilePicture: Boolean,
item: RelaySetupInfo, item: RelaySetupInfo,
onToggleDownload: (RelaySetupInfo) -> Unit, onToggleDownload: (RelaySetupInfo) -> Unit,
onToggleUpload: (RelaySetupInfo) -> Unit, onToggleUpload: (RelaySetupInfo) -> Unit,
@@ -368,7 +381,7 @@ fun ServerConfigClickableLine(
modifier = Modifier.padding(vertical = 5.dp) modifier = Modifier.padding(vertical = 5.dp)
) { ) {
Column(Modifier.clickable(onClick = onClick)) { Column(Modifier.clickable(onClick = onClick)) {
RenderRelayIcon(iconUrl = item.briefInfo.favIcon, Size55dp) RenderRelayIcon(iconUrl = item.briefInfo.favIcon, loadProfilePicture, Size55dp)
} }
Spacer(modifier = HalfHorzPadding) Spacer(modifier = HalfHorzPadding)
@@ -16,6 +16,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@@ -25,8 +26,10 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.RelayBriefInfo import com.vitorpamplona.amethyst.model.RelayBriefInfo
import com.vitorpamplona.amethyst.model.RelayInformation import com.vitorpamplona.amethyst.model.RelayInformation
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.components.ClickableEmail import com.vitorpamplona.amethyst.ui.components.ClickableEmail
import com.vitorpamplona.amethyst.ui.components.ClickableUrl import com.vitorpamplona.amethyst.ui.components.ClickableUrl
import com.vitorpamplona.amethyst.ui.note.LoadUser import com.vitorpamplona.amethyst.ui.note.LoadUser
@@ -47,6 +50,14 @@ fun RelayInformationDialog(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
Dialog( Dialog(
onDismissRequest = { onClose() }, onDismissRequest = { onClose() },
properties = DialogProperties( properties = DialogProperties(
@@ -77,6 +88,7 @@ fun RelayInformationDialog(
Column() { Column() {
RenderRelayIcon( RenderRelayIcon(
relayBriefInfo.favIcon, relayBriefInfo.favIcon,
automaticallyShowProfilePicture,
Size55dp Size55dp
) )
} }
@@ -58,14 +58,15 @@ fun RobohashFallbackAsyncImage(
contentScale: ContentScale = ContentScale.Fit, contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha, alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null, colorFilter: ColorFilter? = null,
filterQuality: FilterQuality = DrawScope.DefaultFilterQuality filterQuality: FilterQuality = DrawScope.DefaultFilterQuality,
loadProfilePicture: Boolean
) { ) {
val context = LocalContext.current val context = LocalContext.current
val painter = rememberAsyncImagePainter( val painter = rememberAsyncImagePainter(
model = Robohash.imageRequest(context, robot) model = Robohash.imageRequest(context, robot)
) )
if (model != null) { if (model != null && loadProfilePicture) {
AsyncImage( AsyncImage(
model = model, model = model,
contentDescription = contentDescription, contentDescription = contentDescription,
@@ -101,7 +102,8 @@ fun RobohashAsyncImageProxy(
contentScale: ContentScale = ContentScale.Fit, contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha, alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null, colorFilter: ColorFilter? = null,
filterQuality: FilterQuality = DrawScope.DefaultFilterQuality filterQuality: FilterQuality = DrawScope.DefaultFilterQuality,
loadProfilePicture: Boolean
) { ) {
RobohashFallbackAsyncImage( RobohashFallbackAsyncImage(
robot = robot, robot = robot,
@@ -112,6 +114,7 @@ fun RobohashAsyncImageProxy(
contentScale = contentScale, contentScale = contentScale,
alpha = alpha, alpha = alpha,
colorFilter = colorFilter, colorFilter = colorFilter,
filterQuality = filterQuality filterQuality = filterQuality,
loadProfilePicture = loadProfilePicture
) )
} }
@@ -44,8 +44,10 @@ import androidx.lifecycle.map
import com.vitorpamplona.amethyst.AccountInfo import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.LocalPreferences import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon import com.vitorpamplona.amethyst.ui.note.ArrowBackIcon
@@ -136,6 +138,14 @@ fun DisplayAccount(
) )
} }
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
if (baseUser == null) { if (baseUser == null) {
LaunchedEffect(key1 = acc.npub) { LaunchedEffect(key1 = acc.npub) {
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
@@ -173,7 +183,7 @@ fun DisplayAccount(
.width(55.dp) .width(55.dp)
.padding(0.dp) .padding(0.dp)
) { ) {
AccountPicture(it) AccountPicture(it, automaticallyShowProfilePicture)
} }
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
@@ -208,7 +218,7 @@ private fun ActiveMarker(acc: AccountInfo, accountViewModel: AccountViewModel) {
} }
@Composable @Composable
private fun AccountPicture(user: User) { private fun AccountPicture(user: User, loadProfilePicture: Boolean) {
val profilePicture by user.live().metadata.map { val profilePicture by user.live().metadata.map {
it.user.profilePicture() it.user.profilePicture()
}.observeAsState() }.observeAsState()
@@ -217,7 +227,8 @@ private fun AccountPicture(user: User) {
robot = remember(user) { user.pubkeyHex }, robot = remember(user) { user.pubkeyHex },
model = profilePicture, model = profilePicture,
contentDescription = stringResource(R.string.profile_image), contentDescription = stringResource(R.string.profile_image),
modifier = AccountPictureModifier modifier = AccountPictureModifier,
loadProfilePicture = loadProfilePicture
) )
} }
@@ -62,6 +62,7 @@ import coil.Coil
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS
import com.vitorpamplona.amethyst.model.KIND3_FOLLOWS import com.vitorpamplona.amethyst.model.KIND3_FOLLOWS
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
@@ -82,6 +83,7 @@ import com.vitorpamplona.amethyst.service.NostrThreadDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
import com.vitorpamplona.amethyst.service.NostrVideoDataSource import com.vitorpamplona.amethyst.service.NostrVideoDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.service.relays.RelayPool import com.vitorpamplona.amethyst.service.relays.RelayPool
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
@@ -515,6 +517,14 @@ private fun LoggedInUserPictureDrawer(
val pubkeyHex = remember { accountViewModel.userProfile().pubkeyHex } val pubkeyHex = remember { accountViewModel.userProfile().pubkeyHex }
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
IconButton( IconButton(
onClick = onClick onClick = onClick
) { ) {
@@ -523,7 +533,8 @@ private fun LoggedInUserPictureDrawer(
model = profilePicture, model = profilePicture,
contentDescription = stringResource(id = R.string.profile_image), contentDescription = stringResource(id = R.string.profile_image),
modifier = HeaderPictureModifier, modifier = HeaderPictureModifier,
contentScale = ContentScale.Crop contentScale = ContentScale.Crop,
loadProfilePicture = automaticallyShowProfilePicture
) )
} }
} }
@@ -70,8 +70,10 @@ import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.ServiceManager
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.HttpClient import com.vitorpamplona.amethyst.service.HttpClient
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.service.relays.RelayPool import com.vitorpamplona.amethyst.service.relays.RelayPool
import com.vitorpamplona.amethyst.service.relays.RelayPoolStatus import com.vitorpamplona.amethyst.service.relays.RelayPoolStatus
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
@@ -100,6 +102,14 @@ fun DrawerContent(
sheetState: ModalBottomSheetState, sheetState: ModalBottomSheetState,
accountViewModel: AccountViewModel accountViewModel: AccountViewModel
) { ) {
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
Surface( Surface(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
color = MaterialTheme.colors.background color = MaterialTheme.colors.background
@@ -129,7 +139,7 @@ fun DrawerContent(
accountViewModel accountViewModel
) )
BottomContent(accountViewModel.account.userProfile(), scaffoldState, nav) BottomContent(accountViewModel.account.userProfile(), scaffoldState, automaticallyShowProfilePicture, nav)
} }
} }
} }
@@ -155,6 +165,14 @@ fun ProfileContent(
val tags = remember(accountUserState) { accountUserState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists() } val tags = remember(accountUserState) { accountUserState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists() }
val route = remember(accountUserState) { "User/${accountUserState?.user?.pubkeyHex}" } val route = remember(accountUserState) { "User/${accountUserState?.user?.pubkeyHex}" }
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
Box { Box {
if (profileBanner != null) { if (profileBanner != null) {
AsyncImage( AsyncImage(
@@ -192,7 +210,8 @@ fun ProfileContent(
coroutineScope.launch { coroutineScope.launch {
scaffoldState.drawerState.close() scaffoldState.drawerState.close()
} }
}) }),
loadProfilePicture = automaticallyShowProfilePicture
) )
if (bestDisplayName != null) { if (bestDisplayName != null) {
@@ -754,7 +773,7 @@ fun IconRowRelays(accountViewModel: AccountViewModel, onClick: () -> Unit) {
} }
@Composable @Composable
fun BottomContent(user: User, scaffoldState: ScaffoldState, nav: (String) -> Unit) { fun BottomContent(user: User, scaffoldState: ScaffoldState, loadProfilePicture: Boolean, nav: (String) -> Unit) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
// store the dialog open or close state // store the dialog open or close state
@@ -816,6 +835,7 @@ fun BottomContent(user: User, scaffoldState: ScaffoldState, nav: (String) -> Uni
if (dialogOpen) { if (dialogOpen) {
ShowQRDialog( ShowQRDialog(
user, user,
loadProfilePicture = loadProfilePicture,
onScan = { onScan = {
dialogOpen = false dialogOpen = false
coroutineScope.launch { coroutineScope.launch {
@@ -47,8 +47,10 @@ import androidx.lifecycle.map
import com.patrykandpatrick.vico.core.extension.forEachIndexedExtended import com.patrykandpatrick.vico.core.extension.forEachIndexedExtended
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Channel import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.ConnectivityType
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.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -185,6 +187,14 @@ private fun ChannelRoomCompose(
val hasNewMessages = remember { mutableStateOf<Boolean>(false) } val hasNewMessages = remember { mutableStateOf<Boolean>(false) }
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
WatchNotificationChanges(note, route, accountViewModel) { newHasNewMessages -> WatchNotificationChanges(note, route, accountViewModel) { newHasNewMessages ->
if (hasNewMessages.value != newHasNewMessages) { if (hasNewMessages.value != newHasNewMessages) {
hasNewMessages.value = newHasNewMessages hasNewMessages.value = newHasNewMessages
@@ -200,6 +210,7 @@ private fun ChannelRoomCompose(
channelLastTime = remember(note) { note.createdAt() }, channelLastTime = remember(note) { note.createdAt() },
channelLastContent = remember(note) { "$authorName: $description" }, channelLastContent = remember(note) { "$authorName: $description" },
hasNewMessages = hasNewMessages, hasNewMessages = hasNewMessages,
loadProfilePicture = automaticallyShowProfilePicture,
onClick = { nav(route) } onClick = { nav(route) }
) )
} }
@@ -443,6 +454,7 @@ fun ChannelName(
channelLastTime: Long?, channelLastTime: Long?,
channelLastContent: String?, channelLastContent: String?,
hasNewMessages: MutableState<Boolean>, hasNewMessages: MutableState<Boolean>,
loadProfilePicture: Boolean,
onClick: () -> Unit onClick: () -> Unit
) { ) {
ChannelName( ChannelName(
@@ -456,7 +468,8 @@ fun ChannelName(
.width(Size55dp) .width(Size55dp)
.height(Size55dp) .height(Size55dp)
.clip(shape = CircleShape) .clip(shape = CircleShape)
} },
loadProfilePicture = loadProfilePicture
) )
}, },
channelTitle, channelTitle,
@@ -43,8 +43,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.map import androidx.lifecycle.map
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
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.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
@@ -400,10 +402,19 @@ private fun MessageBubbleLines(
bubbleSize: MutableState<Int>, bubbleSize: MutableState<Int>,
availableBubbleSize: MutableState<Int> availableBubbleSize: MutableState<Int>
) { ) {
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
if (drawAuthorInfo) { if (drawAuthorInfo) {
DrawAuthorInfo( DrawAuthorInfo(
baseNote, baseNote,
alignment, alignment,
automaticallyShowProfilePicture,
nav nav
) )
} else { } else {
@@ -712,6 +723,7 @@ private fun RenderCreateChannelNote(note: Note) {
private fun DrawAuthorInfo( private fun DrawAuthorInfo(
baseNote: Note, baseNote: Note,
alignment: Arrangement.Horizontal, alignment: Arrangement.Horizontal,
loadProfilePicture: Boolean,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
Row( Row(
@@ -719,26 +731,28 @@ private fun DrawAuthorInfo(
horizontalArrangement = alignment, horizontalArrangement = alignment,
modifier = Modifier.padding(top = 5.dp) modifier = Modifier.padding(top = 5.dp)
) { ) {
DisplayAndWatchNoteAuthor(baseNote, nav) DisplayAndWatchNoteAuthor(baseNote, loadProfilePicture, nav)
} }
} }
@Composable @Composable
private fun DisplayAndWatchNoteAuthor( private fun DisplayAndWatchNoteAuthor(
baseNote: Note, baseNote: Note,
loadProfilePicture: Boolean,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
val author = remember { val author = remember {
baseNote.author baseNote.author
} }
author?.let { author?.let {
WatchAndDisplayUser(it, nav) WatchAndDisplayUser(it, loadProfilePicture, nav)
} }
} }
@Composable @Composable
private fun WatchAndDisplayUser( private fun WatchAndDisplayUser(
author: User, author: User,
loadProfilePicture: Boolean,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
val pubkeyHex = remember { author.pubkeyHex } val pubkeyHex = remember { author.pubkeyHex }
@@ -764,7 +778,7 @@ private fun WatchAndDisplayUser(
} }
} }
UserIcon(pubkeyHex, userProfilePicture, nav, route) UserIcon(pubkeyHex, userProfilePicture, loadProfilePicture, nav, route)
userDisplayName?.let { userDisplayName?.let {
DisplayMessageUsername(it, userTags, route, nav) DisplayMessageUsername(it, userTags, route, nav)
@@ -775,6 +789,7 @@ private fun WatchAndDisplayUser(
private fun UserIcon( private fun UserIcon(
pubkeyHex: String, pubkeyHex: String,
userProfilePicture: String?, userProfilePicture: String?,
loadProfilePicture: Boolean,
nav: (String) -> Unit, nav: (String) -> Unit,
route: String route: String
) { ) {
@@ -782,6 +797,7 @@ private fun UserIcon(
robot = pubkeyHex, robot = pubkeyHex,
model = userProfilePicture, model = userProfilePicture,
contentDescription = stringResource(id = R.string.profile_image), contentDescription = stringResource(id = R.string.profile_image),
loadProfilePicture = loadProfilePicture,
modifier = remember { modifier = remember {
Modifier Modifier
.width(Size25dp) .width(Size25dp)
@@ -43,8 +43,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
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.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.components.ImageUrlType import com.vitorpamplona.amethyst.ui.components.ImageUrlType
import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
@@ -525,6 +527,14 @@ fun WatchUserMetadataAndFollowsAndRenderUserProfilePicture(
author: User, author: User,
accountViewModel: AccountViewModel accountViewModel: AccountViewModel
) { ) {
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
WatchUserMetadata(author) { baseUserPicture -> WatchUserMetadata(author) { baseUserPicture ->
// Crossfade(targetState = baseUserPicture) { userPicture -> // Crossfade(targetState = baseUserPicture) { userPicture ->
RobohashAsyncImageProxy( RobohashAsyncImageProxy(
@@ -532,7 +542,8 @@ fun WatchUserMetadataAndFollowsAndRenderUserProfilePicture(
model = baseUserPicture, model = baseUserPicture,
contentDescription = stringResource(id = R.string.profile_image), contentDescription = stringResource(id = R.string.profile_image),
modifier = MaterialTheme.colors.profile35dpModifier, modifier = MaterialTheme.colors.profile35dpModifier,
contentScale = ContentScale.Crop contentScale = ContentScale.Crop,
loadProfilePicture = automaticallyShowProfilePicture
) )
// } // }
} }
@@ -728,6 +728,14 @@ fun ShortCommunityHeader(baseNote: AddressableNote, fontWeight: FontWeight = Fon
val noteState by baseNote.live().metadata.observeAsState() val noteState by baseNote.live().metadata.observeAsState()
val noteEvent = remember(noteState) { noteState?.note?.event as? CommunityDefinitionEvent } ?: return val noteEvent = remember(noteState) { noteState?.note?.event as? CommunityDefinitionEvent } ?: return
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
noteEvent.image()?.let { noteEvent.image()?.let {
RobohashAsyncImageProxy( RobohashAsyncImageProxy(
@@ -735,7 +743,8 @@ fun ShortCommunityHeader(baseNote: AddressableNote, fontWeight: FontWeight = Fon
model = it, model = it,
contentDescription = stringResource(R.string.profile_image), contentDescription = stringResource(R.string.profile_image),
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = HeaderPictureModifier modifier = HeaderPictureModifier,
loadProfilePicture = automaticallyShowProfilePicture
) )
} }
@@ -2779,11 +2788,19 @@ private fun RenderAuthorImages(
val isChannel = baseNote.event is ChannelMessageEvent && baseNote.channelHex() != null val isChannel = baseNote.event is ChannelMessageEvent && baseNote.channelHex() != null
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
if (isChannel) { if (isChannel) {
val baseChannelHex = remember { baseNote.channelHex() } val baseChannelHex = remember { baseNote.channelHex() }
if (baseChannelHex != null) { if (baseChannelHex != null) {
LoadChannel(baseChannelHex, accountViewModel) { channel -> LoadChannel(baseChannelHex, accountViewModel) { channel ->
ChannelNotePicture(channel) ChannelNotePicture(channel, loadProfilePicture = automaticallyShowProfilePicture)
} }
} }
} }
@@ -2811,7 +2828,7 @@ fun LoadChannel(baseChannelHex: String, accountViewModel: AccountViewModel, cont
} }
@Composable @Composable
private fun ChannelNotePicture(baseChannel: Channel) { private fun ChannelNotePicture(baseChannel: Channel, loadProfilePicture: Boolean) {
val model by baseChannel.live.map { val model by baseChannel.live.map {
it.channel.profilePicture() it.channel.profilePicture()
}.distinctUntilChanged().observeAsState() }.distinctUntilChanged().observeAsState()
@@ -2836,7 +2853,8 @@ private fun ChannelNotePicture(baseChannel: Channel) {
robot = baseChannel.idHex, robot = baseChannel.idHex,
model = model, model = model,
contentDescription = stringResource(R.string.group_picture), contentDescription = stringResource(R.string.group_picture),
modifier = modifier modifier = modifier,
loadProfilePicture = loadProfilePicture
) )
} }
} }
@@ -33,10 +33,12 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.map import androidx.lifecycle.map
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.RelayBriefInfo import com.vitorpamplona.amethyst.model.RelayBriefInfo
import com.vitorpamplona.amethyst.model.RelayInformation import com.vitorpamplona.amethyst.model.RelayInformation
import com.vitorpamplona.amethyst.service.Nip11Retriever import com.vitorpamplona.amethyst.service.Nip11Retriever
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -126,6 +128,14 @@ fun RenderRelay(relay: RelayBriefInfo, accountViewModel: AccountViewModel, nav:
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
val ripple = rememberRipple(bounded = false, radius = Size15dp) val ripple = rememberRipple(bounded = false, radius = Size15dp)
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
val clickableModifier = remember(relay) { val clickableModifier = remember(relay) {
Modifier Modifier
.padding(1.dp) .padding(1.dp)
@@ -166,12 +176,12 @@ fun RenderRelay(relay: RelayBriefInfo, accountViewModel: AccountViewModel, nav:
Box( Box(
modifier = clickableModifier modifier = clickableModifier
) { ) {
RenderRelayIcon(relay.favIcon) RenderRelayIcon(relay.favIcon, automaticallyShowProfilePicture)
} }
} }
@Composable @Composable
fun RenderRelayIcon(iconUrl: String, size: Dp = Size13dp) { fun RenderRelayIcon(iconUrl: String, loadProfilePicture: Boolean, size: Dp = Size13dp) {
val backgroundColor = MaterialTheme.colors.background val backgroundColor = MaterialTheme.colors.background
val iconModifier = remember { val iconModifier = remember {
@@ -186,6 +196,7 @@ fun RenderRelayIcon(iconUrl: String, size: Dp = Size13dp) {
model = iconUrl, model = iconUrl,
contentDescription = stringResource(id = R.string.relay_icon), contentDescription = stringResource(id = R.string.relay_icon),
colorFilter = RelayIconFilter, colorFilter = RelayIconFilter,
modifier = iconModifier modifier = iconModifier,
loadProfilePicture = loadProfilePicture
) )
} }
@@ -41,9 +41,11 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.distinctUntilChanged import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.map import androidx.lifecycle.map
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.ConnectivityType
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.ExternalSignerUtils import com.vitorpamplona.amethyst.service.ExternalSignerUtils
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -76,6 +78,13 @@ fun NoteAuthorPicture(
onClick: ((User) -> Unit)? = null onClick: ((User) -> Unit)? = null
) { ) {
val author by baseNote.live().authorChanges.observeAsState(baseNote.author) val author by baseNote.live().authorChanges.observeAsState(baseNote.author)
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
Crossfade(targetState = author) { Crossfade(targetState = author) {
if (it == null) { if (it == null) {
@@ -323,12 +332,21 @@ fun PictureAndFollowingMark(
.background(backgroundColor) .background(backgroundColor)
} }
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
RobohashAsyncImageProxy( RobohashAsyncImageProxy(
robot = userHex, robot = userHex,
model = userPicture, model = userPicture,
contentDescription = stringResource(id = R.string.profile_image), contentDescription = stringResource(id = R.string.profile_image),
modifier = myImageModifier, modifier = myImageModifier,
contentScale = ContentScale.Crop contentScale = ContentScale.Crop,
loadProfilePicture = automaticallyShowProfilePicture
) )
val myIconSize by remember(size) { val myIconSize by remember(size) {
@@ -41,7 +41,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size35dp
import com.vitorpamplona.quartz.events.toImmutableListOfLists import com.vitorpamplona.quartz.events.toImmutableListOfLists
@Composable @Composable
fun ShowQRDialog(user: User, onScan: (String) -> Unit, onClose: () -> Unit) { fun ShowQRDialog(user: User, loadProfilePicture: Boolean, onScan: (String) -> Unit, onClose: () -> Unit) {
var presenting by remember { mutableStateOf(true) } var presenting by remember { mutableStateOf(true) }
Dialog( Dialog(
@@ -82,7 +82,8 @@ fun ShowQRDialog(user: User, onScan: (String) -> Unit, onClose: () -> Unit) {
.height(100.dp) .height(100.dp)
.clip(shape = CircleShape) .clip(shape = CircleShape)
.border(3.dp, MaterialTheme.colors.background, CircleShape) .border(3.dp, MaterialTheme.colors.background, CircleShape)
.background(MaterialTheme.colors.background) .background(MaterialTheme.colors.background),
loadProfilePicture = loadProfilePicture
) )
} }
Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth().padding(top = 5.dp)) { Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth().padding(top = 5.dp)) {
@@ -98,6 +98,12 @@ class AccountViewModel(val account: Account) : ViewModel(), Dao {
account.updateAutomaticallyShowUrlPreview(automaticallyShowUrlPreview) account.updateAutomaticallyShowUrlPreview(automaticallyShowUrlPreview)
} }
fun updateAutomaticallyShowProfilePicture(
automaticallyShowProfilePicture: ConnectivityType
) {
account.updateAutomaticallyShowProfilePicture(automaticallyShowProfilePicture)
}
fun updateAutomaticallyHideNavBars( fun updateAutomaticallyHideNavBars(
automaticallyHideHavBars: BooleanType automaticallyHideHavBars: BooleanType
) { ) {
@@ -79,6 +79,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.Channel import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.LiveActivitiesChannel import com.vitorpamplona.amethyst.model.LiveActivitiesChannel
import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
@@ -86,6 +87,7 @@ import com.vitorpamplona.amethyst.model.PublicChatChannel
import com.vitorpamplona.amethyst.model.ServersAvailable import com.vitorpamplona.amethyst.model.ServersAvailable
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.NostrChannelDataSource import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.actions.NewChannelView import com.vitorpamplona.amethyst.ui.actions.NewChannelView
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel
@@ -677,6 +679,14 @@ fun ShortChannelHeader(
channelState.value?.channel channelState.value?.channel
} ?: return } ?: return
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
if (channel is LiveActivitiesChannel) { if (channel is LiveActivitiesChannel) {
channel.creator?.let { channel.creator?.let {
@@ -694,7 +704,8 @@ fun ShortChannelHeader(
model = it, model = it,
contentDescription = stringResource(R.string.profile_image), contentDescription = stringResource(R.string.profile_image),
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = HeaderPictureModifier modifier = HeaderPictureModifier,
loadProfilePicture = automaticallyShowProfilePicture
) )
} }
} }
@@ -55,10 +55,12 @@ import coil.compose.AsyncImage
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.LocalCache 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.ui.actions.NewUserMetadataView import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView
import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji
import com.vitorpamplona.amethyst.ui.components.DisplayNip05ProfileStatus import com.vitorpamplona.amethyst.ui.components.DisplayNip05ProfileStatus
@@ -864,6 +866,14 @@ private fun DrawAdditionalInfo(
val uri = LocalUriHandler.current val uri = LocalUriHandler.current
val clipboardManager = LocalClipboardManager.current val clipboardManager = LocalClipboardManager.current
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
(user.bestDisplayName() ?: user.bestUsername())?.let { (user.bestDisplayName() ?: user.bestUsername())?.let {
Row(verticalAlignment = Alignment.Bottom, modifier = Modifier.padding(top = 7.dp)) { Row(verticalAlignment = Alignment.Bottom, modifier = Modifier.padding(top = 7.dp)) {
CreateTextWithEmoji( CreateTextWithEmoji(
@@ -918,6 +928,7 @@ private fun DrawAdditionalInfo(
if (dialogOpen) { if (dialogOpen) {
ShowQRDialog( ShowQRDialog(
user, user,
automaticallyShowProfilePicture,
onScan = { onScan = {
dialogOpen = false dialogOpen = false
nav(it) nav(it)
@@ -1186,6 +1197,14 @@ private fun DisplayBadges(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
LoadAddressableNote( LoadAddressableNote(
aTag = ATag( aTag = ATag(
BadgeProfilesEvent.kind, BadgeProfilesEvent.kind,
@@ -1196,7 +1215,7 @@ private fun DisplayBadges(
accountViewModel accountViewModel
) { note -> ) { note ->
if (note != null) { if (note != null) {
WatchAndRenderBadgeList(note, nav) WatchAndRenderBadgeList(note, automaticallyShowProfilePicture, nav)
} }
} }
} }
@@ -1204,6 +1223,7 @@ private fun DisplayBadges(
@Composable @Composable
private fun WatchAndRenderBadgeList( private fun WatchAndRenderBadgeList(
note: AddressableNote, note: AddressableNote,
loadProfilePicture: Boolean,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
val badgeList by note.live().metadata.map { val badgeList by note.live().metadata.map {
@@ -1211,7 +1231,7 @@ private fun WatchAndRenderBadgeList(
}.distinctUntilChanged().observeAsState() }.distinctUntilChanged().observeAsState()
badgeList?.let { list -> badgeList?.let { list ->
RenderBadgeList(list, nav) RenderBadgeList(list, loadProfilePicture, nav)
} }
} }
@@ -1219,6 +1239,7 @@ private fun WatchAndRenderBadgeList(
@OptIn(ExperimentalLayoutApi::class) @OptIn(ExperimentalLayoutApi::class)
private fun RenderBadgeList( private fun RenderBadgeList(
list: ImmutableList<String>, list: ImmutableList<String>,
loadProfilePicture: Boolean,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
FlowRow( FlowRow(
@@ -1226,13 +1247,13 @@ private fun RenderBadgeList(
modifier = Modifier.padding(vertical = 5.dp) modifier = Modifier.padding(vertical = 5.dp)
) { ) {
list.forEach { badgeAwardEvent -> list.forEach { badgeAwardEvent ->
LoadAndRenderBadge(badgeAwardEvent, nav) LoadAndRenderBadge(badgeAwardEvent, loadProfilePicture, nav)
} }
} }
} }
@Composable @Composable
private fun LoadAndRenderBadge(badgeAwardEventHex: String, nav: (String) -> Unit) { private fun LoadAndRenderBadge(badgeAwardEventHex: String, loadProfilePicture: Boolean, nav: (String) -> Unit) {
var baseNote by remember { var baseNote by remember {
mutableStateOf(LocalCache.getNoteIfExists(badgeAwardEventHex)) mutableStateOf(LocalCache.getNoteIfExists(badgeAwardEventHex))
} }
@@ -1246,13 +1267,14 @@ private fun LoadAndRenderBadge(badgeAwardEventHex: String, nav: (String) -> Unit
} }
baseNote?.let { baseNote?.let {
ObserveAndRenderBadge(it, nav) ObserveAndRenderBadge(it, loadProfilePicture, nav)
} }
} }
@Composable @Composable
private fun ObserveAndRenderBadge( private fun ObserveAndRenderBadge(
it: Note, it: Note,
loadProfilePicture: Boolean,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
val badgeAwardState by it.live().metadata.observeAsState() val badgeAwardState by it.live().metadata.observeAsState()
@@ -1263,18 +1285,19 @@ private fun ObserveAndRenderBadge(
} }
baseBadgeDefinition?.let { baseBadgeDefinition?.let {
BadgeThumb(it, nav, Size35dp) BadgeThumb(it, loadProfilePicture, nav, Size35dp)
} }
} }
@Composable @Composable
fun BadgeThumb( fun BadgeThumb(
note: Note, note: Note,
loadProfilePicture: Boolean,
nav: (String) -> Unit, nav: (String) -> Unit,
size: Dp, size: Dp,
pictureModifier: Modifier = Modifier pictureModifier: Modifier = Modifier
) { ) {
BadgeThumb(note, size, pictureModifier) { BadgeThumb(note, loadProfilePicture, size, pictureModifier) {
nav("Note/${note.idHex}") nav("Note/${note.idHex}")
} }
} }
@@ -1282,6 +1305,7 @@ fun BadgeThumb(
@Composable @Composable
fun BadgeThumb( fun BadgeThumb(
baseNote: Note, baseNote: Note,
loadProfilePicture: Boolean,
size: Dp, size: Dp,
pictureModifier: Modifier = Modifier, pictureModifier: Modifier = Modifier,
onClick: ((String) -> Unit)? = null onClick: ((String) -> Unit)? = null
@@ -1293,13 +1317,14 @@ fun BadgeThumb(
.height(size) .height(size)
} }
) { ) {
WatchAndRenderBadgeImage(baseNote, size, pictureModifier, onClick) WatchAndRenderBadgeImage(baseNote, loadProfilePicture, size, pictureModifier, onClick)
} }
} }
@Composable @Composable
private fun WatchAndRenderBadgeImage( private fun WatchAndRenderBadgeImage(
baseNote: Note, baseNote: Note,
loadProfilePicture: Boolean,
size: Dp, size: Dp,
pictureModifier: Modifier, pictureModifier: Modifier,
onClick: ((String) -> Unit)? onClick: ((String) -> Unit)?
@@ -1344,8 +1369,8 @@ private fun WatchAndRenderBadgeImage(
this this
} }
} }
} },
loadProfilePicture = loadProfilePicture
) )
} }
} }
@@ -49,11 +49,13 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.Channel import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.ConnectivityType
import com.vitorpamplona.amethyst.model.LocalCache 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.NostrSearchEventOrUserDataSource import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.service.connectivitystatus.ConnectivityStatus
import com.vitorpamplona.amethyst.ui.components.BundledUpdate import com.vitorpamplona.amethyst.ui.components.BundledUpdate
import com.vitorpamplona.amethyst.ui.note.AboutDisplay import com.vitorpamplona.amethyst.ui.note.AboutDisplay
import com.vitorpamplona.amethyst.ui.note.ChannelName import com.vitorpamplona.amethyst.ui.note.ChannelName
@@ -343,6 +345,14 @@ private fun DisplaySearchResults(
mutableStateOf(false) mutableStateOf(false)
} }
val automaticallyShowProfilePicture = remember {
when (accountViewModel.account.settings.automaticallyShowProfilePictures) {
ConnectivityType.WIFI_ONLY -> !ConnectivityStatus.isOnMobileData.value
ConnectivityType.NEVER -> false
ConnectivityType.ALWAYS -> true
}
}
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxHeight(), modifier = Modifier.fillMaxHeight(),
contentPadding = PaddingValues( contentPadding = PaddingValues(
@@ -383,6 +393,7 @@ private fun DisplaySearchResults(
channelLastTime = null, channelLastTime = null,
channelLastContent = item.summary(), channelLastContent = item.summary(),
hasNewMessages = hasNewMessages, hasNewMessages = hasNewMessages,
loadProfilePicture = automaticallyShowProfilePicture,
onClick = { nav("Channel/${item.idHex}") } onClick = { nav("Channel/${item.idHex}") }
) )
} }
@@ -133,6 +133,7 @@ fun SettingsScreen(
val videoIndex = settings.automaticallyStartPlayback.screenCode val videoIndex = settings.automaticallyStartPlayback.screenCode
val linkIndex = settings.automaticallyShowUrlPreview.screenCode val linkIndex = settings.automaticallyShowUrlPreview.screenCode
val hideNavBarsIndex = settings.automaticallyHideNavigationBars.screenCode val hideNavBarsIndex = settings.automaticallyHideNavigationBars.screenCode
val profilePictureIndex = settings.automaticallyShowProfilePictures.screenCode
val themeIndex = themeViewModel.theme.value ?: 0 val themeIndex = themeViewModel.theme.value ?: 0
@@ -228,6 +229,20 @@ fun SettingsScreen(
} }
} }
SettingsRow(
R.string.automatically_show_profile_picture,
R.string.automatically_show_profile_picture_description,
selectedItens,
profilePictureIndex
) {
val automaticallyShowProfilePicture = parseConnectivityType(it)
scope.launch(Dispatchers.IO) {
accountViewModel.updateAutomaticallyShowProfilePicture(automaticallyShowProfilePicture)
LocalPreferences.saveToEncryptedStorage(accountViewModel.account)
}
}
Spacer(modifier = HalfVertSpacer) Spacer(modifier = HalfVertSpacer)
SettingsRow( SettingsRow(
+2
View File
@@ -598,4 +598,6 @@
<string name="hidden_words">Hidden Words</string> <string name="hidden_words">Hidden Words</string>
<string name="hide_new_word_label">Hide new word or sentence</string> <string name="hide_new_word_label">Hide new word or sentence</string>
<string name="automatically_show_profile_picture">Profile Picture</string>
<string name="automatically_show_profile_picture_description">Show Profile pictures</string>
</resources> </resources>