Merge remote-tracking branch 'origin/HEAD' into less_memory_test_branch
This commit is contained in:
+26
@@ -0,0 +1,26 @@
|
||||
package com.vitorpamplona.amethyst.ui.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.navigation.NavController
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
|
||||
@Composable
|
||||
fun TranslateableRichTextViewer(
|
||||
content: String,
|
||||
canPreview: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
tags: List<List<String>>?,
|
||||
backgroundColor: Color,
|
||||
accountViewModel: AccountViewModel,
|
||||
navController: NavController
|
||||
) = ExpandableRichTextViewer(
|
||||
content,
|
||||
canPreview,
|
||||
modifier,
|
||||
tags,
|
||||
backgroundColor,
|
||||
accountViewModel,
|
||||
navController
|
||||
)
|
||||
@@ -79,7 +79,7 @@ object LocalPreferences {
|
||||
}
|
||||
val prefs = encryptedPreferences()
|
||||
prefs.edit().apply {
|
||||
putString(PrefKeys.SAVED_ACCOUNTS, accounts.joinToString(comma))
|
||||
putString(PrefKeys.SAVED_ACCOUNTS, accounts.joinToString(comma).ifBlank { null })
|
||||
}.apply()
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ object LocalPreferences {
|
||||
if (accounts.remove(npub)) {
|
||||
val prefs = encryptedPreferences()
|
||||
prefs.edit().apply {
|
||||
putString(PrefKeys.SAVED_ACCOUNTS, accounts.joinToString(comma))
|
||||
putString(PrefKeys.SAVED_ACCOUNTS, accounts.joinToString(comma).ifBlank { null })
|
||||
}.apply()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ class Account(
|
||||
LocalCache.consume(signedEvent, null)
|
||||
}
|
||||
|
||||
fun sendPrivateMeesage(message: String, toUser: String, replyingTo: Note? = null) {
|
||||
fun sendPrivateMessage(message: String, toUser: String, replyingTo: Note? = null) {
|
||||
if (!isWriteable()) return
|
||||
val user = LocalCache.users[toUser] ?: return
|
||||
|
||||
|
||||
@@ -218,7 +218,9 @@ fun NewPostView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
|
||||
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
UploadFromGallery(
|
||||
isUploading = postViewModel.isUploadingImage
|
||||
isUploading = postViewModel.isUploadingImage,
|
||||
tint = MaterialTheme.colors.primary,
|
||||
modifier = Modifier.padding(bottom = 10.dp)
|
||||
) {
|
||||
postViewModel.upload(it, context)
|
||||
}
|
||||
|
||||
@@ -4,23 +4,38 @@ import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AddPhotoAlternate
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun UploadFromGallery(
|
||||
isUploading: Boolean,
|
||||
tint: Color,
|
||||
modifier: Modifier,
|
||||
onImageChosen: (Uri) -> Unit
|
||||
) {
|
||||
val cameraPermissionState =
|
||||
@@ -43,64 +58,111 @@ fun UploadFromGallery(
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
Box() {
|
||||
TextButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopCenter),
|
||||
enabled = !isUploading,
|
||||
onClick = {
|
||||
showGallerySelect = true
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_add_photo),
|
||||
contentDescription = stringResource(id = R.string.upload_image),
|
||||
modifier = Modifier
|
||||
.height(20.dp)
|
||||
.padding(end = 8.dp),
|
||||
tint = MaterialTheme.colors.primary
|
||||
)
|
||||
}
|
||||
|
||||
if (!isUploading) {
|
||||
Text(stringResource(R.string.upload_image))
|
||||
} else {
|
||||
Text(stringResource(R.string.uploading))
|
||||
}
|
||||
}
|
||||
}
|
||||
UploadBoxButton(isUploading, tint, modifier) {
|
||||
showGallerySelect = true
|
||||
}
|
||||
} else {
|
||||
Column {
|
||||
Button(
|
||||
onClick = { cameraPermissionState.launchPermissionRequest() },
|
||||
enabled = !isUploading
|
||||
) {
|
||||
if (!isUploading) {
|
||||
Text(stringResource(R.string.upload_image))
|
||||
} else {
|
||||
Text(stringResource(R.string.uploading))
|
||||
}
|
||||
UploadBoxButton(isUploading, tint, modifier) {
|
||||
cameraPermissionState.launchPermissionRequest()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UploadBoxButton(
|
||||
isUploading: Boolean,
|
||||
tint: Color,
|
||||
modifier: Modifier,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
Box() {
|
||||
IconButton(
|
||||
modifier = modifier.align(Alignment.Center),
|
||||
enabled = !isUploading,
|
||||
onClick = {
|
||||
onClick()
|
||||
}
|
||||
) {
|
||||
if (!isUploading) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AddPhotoAlternate,
|
||||
contentDescription = stringResource(id = R.string.upload_image),
|
||||
modifier = Modifier.height(25.dp),
|
||||
tint = tint
|
||||
)
|
||||
} else {
|
||||
LoadingAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoadingAnimation(
|
||||
indicatorSize: Dp = 20.dp,
|
||||
circleColors: List<Color> = listOf(
|
||||
Color(0xFF5851D8),
|
||||
Color(0xFF833AB4),
|
||||
Color(0xFFC13584),
|
||||
Color(0xFFE1306C),
|
||||
Color(0xFFFD1D1D),
|
||||
Color(0xFFF56040),
|
||||
Color(0xFFF77737),
|
||||
Color(0xFFFCAF45),
|
||||
Color(0xFFFFDC80),
|
||||
Color(0xFF5851D8)
|
||||
),
|
||||
animationDuration: Int = 1000
|
||||
) {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
|
||||
val rotateAnimation by infiniteTransition.animateFloat(
|
||||
initialValue = 0f,
|
||||
targetValue = 360f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(
|
||||
durationMillis = animationDuration,
|
||||
easing = LinearEasing
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.size(size = indicatorSize)
|
||||
.rotate(degrees = rotateAnimation)
|
||||
.border(
|
||||
width = 4.dp,
|
||||
brush = Brush.sweepGradient(circleColors),
|
||||
shape = CircleShape
|
||||
),
|
||||
progress = 1f,
|
||||
strokeWidth = 1.dp,
|
||||
color = MaterialTheme.colors.background // Set background color
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun GallerySelect(
|
||||
onImageUri: (Uri?) -> Unit = { }
|
||||
) {
|
||||
var hasLaunched by remember { mutableStateOf(AtomicBoolean(false)) }
|
||||
val launcher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.GetContent(),
|
||||
onResult = { uri: Uri? ->
|
||||
onImageUri(uri)
|
||||
hasLaunched.set(false)
|
||||
}
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun LaunchGallery() {
|
||||
SideEffect {
|
||||
launcher.launch("image/*")
|
||||
if (!hasLaunched.getAndSet(true)) {
|
||||
launcher.launch("image/*")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
package com.vitorpamplona.amethyst.ui.components
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import coil.ImageLoader
|
||||
import coil.decode.DataSource
|
||||
import coil.decode.ImageSource
|
||||
import coil.fetch.Fetcher
|
||||
import coil.fetch.SourceResult
|
||||
import coil.request.ImageRequest
|
||||
import java.nio.ByteBuffer
|
||||
import coil.request.Options
|
||||
import okio.Buffer
|
||||
import java.security.MessageDigest
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.measureTimedValue
|
||||
|
||||
private fun toHex(color: Color): String {
|
||||
val argb = color.toArgb()
|
||||
@@ -40,29 +49,54 @@ private fun svgString(msg: String): String {
|
||||
val mouth = mouths[mouthIndex]
|
||||
val accessory = accessories[accIndex]
|
||||
|
||||
return """
|
||||
<svg id="$hashHex" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-bg{fill:${toHex(bgColor)}}.cls-fill-1{fill:${toHex(fgColor)};}.cls-fill-2{fill:${toHex(fgColor)};}
|
||||
${body.style}${face.style}${eye.style}${mouth.style}${accessory.style}
|
||||
</style>
|
||||
</defs>
|
||||
<title>Robohash $hashHex</title>
|
||||
${background}${body.paths}${face.paths}${eye.paths}${mouth.paths}${accessory.paths}
|
||||
</svg>
|
||||
""".trimIndent()
|
||||
return """<svg id="$hashHex" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-bg{fill:${toHex(bgColor)}}.cls-fill-1{fill:${toHex(fgColor)};}.cls-fill-2{fill:${toHex(fgColor)};}
|
||||
${body.style}${face.style}${eye.style}${mouth.style}${accessory.style}
|
||||
</style>
|
||||
</defs>
|
||||
<title>Robohash $hashHex</title>
|
||||
${background}${body.paths}${face.paths}${eye.paths}${mouth.paths}${accessory.paths}
|
||||
</svg>"""
|
||||
}
|
||||
|
||||
class HashImageFetcher(
|
||||
private val context: Context,
|
||||
private val data: Uri
|
||||
) : Fetcher {
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
override suspend fun fetch(): SourceResult {
|
||||
val (value, elapsed) = measureTimedValue {
|
||||
val source = try {
|
||||
Buffer().apply { write(svgString(data.toString()).toByteArray()) }
|
||||
} finally {
|
||||
}
|
||||
|
||||
SourceResult(
|
||||
source = ImageSource(source, context),
|
||||
mimeType = null,
|
||||
dataSource = DataSource.MEMORY
|
||||
)
|
||||
}
|
||||
println("Elapsed: $elapsed")
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
class Factory : Fetcher.Factory<Uri> {
|
||||
override fun create(data: Uri, options: Options, imageLoader: ImageLoader): Fetcher {
|
||||
return HashImageFetcher(options.context, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
object Robohash {
|
||||
fun imageRequest(context: Context, message: String): ImageRequest {
|
||||
return ImageRequest
|
||||
.Builder(context)
|
||||
.data(
|
||||
ByteBuffer.wrap(
|
||||
svgString(message).toByteArray()
|
||||
)
|
||||
)
|
||||
.data("robohash:$message")
|
||||
.fetcherFactory(HashImageFetcher.Factory())
|
||||
.crossfade(100)
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ fun MainTopBar(scaffoldState: ScaffoldState, accountViewModel: AccountViewModel)
|
||||
Column() {
|
||||
TopAppBar(
|
||||
elevation = 0.dp,
|
||||
backgroundColor = MaterialTheme.colors.surface,
|
||||
title = {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
|
||||
@@ -344,7 +344,7 @@ fun ChatroomMessageCompose(
|
||||
}
|
||||
}
|
||||
|
||||
NoteQuickActionMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel)
|
||||
NoteDropDownMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ class AccountStateViewModel() : ViewModel() {
|
||||
Account(Persona(Hex.decode(key)))
|
||||
}
|
||||
|
||||
LocalPreferences.updatePrefsForLogin(account)
|
||||
login(account)
|
||||
}
|
||||
|
||||
@@ -64,7 +63,6 @@ class AccountStateViewModel() : ViewModel() {
|
||||
|
||||
fun newKey() {
|
||||
val account = Account(Persona())
|
||||
LocalPreferences.updatePrefsForLogin(account)
|
||||
login(account)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -65,7 +66,9 @@ import com.vitorpamplona.amethyst.model.Channel
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewChannelView
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.actions.PostButton
|
||||
import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery
|
||||
import com.vitorpamplona.amethyst.ui.components.ResizeImage
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
|
||||
import com.vitorpamplona.amethyst.ui.dal.ChannelFeedFilter
|
||||
@@ -82,9 +85,10 @@ fun ChannelScreen(
|
||||
) {
|
||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||
val account = accountState?.account
|
||||
val context = LocalContext.current
|
||||
val channelScreenModel: NewPostViewModel = viewModel()
|
||||
|
||||
if (account != null && channelId != null) {
|
||||
val newPost = remember { mutableStateOf(TextFieldValue("")) }
|
||||
val replyTo = remember { mutableStateOf<Note?>(null) }
|
||||
|
||||
ChannelFeedFilter.loadMessagesBetween(account, channelId)
|
||||
@@ -98,6 +102,9 @@ fun ChannelScreen(
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
feedViewModel.invalidateData()
|
||||
channelScreenModel.imageUploadingError.collect { error ->
|
||||
Toast.makeText(context, error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(channelId) {
|
||||
@@ -178,8 +185,10 @@ fun ChannelScreen(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
TextField(
|
||||
value = newPost.value,
|
||||
onValueChange = { newPost.value = it },
|
||||
value = channelScreenModel.message,
|
||||
onValueChange = {
|
||||
channelScreenModel.updateMessage(it)
|
||||
},
|
||||
keyboardOptions = KeyboardOptions.Default.copy(
|
||||
capitalization = KeyboardCapitalization.Sentences
|
||||
),
|
||||
@@ -195,15 +204,24 @@ fun ChannelScreen(
|
||||
trailingIcon = {
|
||||
PostButton(
|
||||
onPost = {
|
||||
account.sendChannelMessage(newPost.value.text, channel.idHex, replyTo.value, null)
|
||||
newPost.value = TextFieldValue("")
|
||||
account.sendChannelMessage(channelScreenModel.message.text, channel.idHex, replyTo.value, null)
|
||||
channelScreenModel.message = TextFieldValue("")
|
||||
replyTo.value = null
|
||||
feedViewModel.refresh() // Don't wait a full second before updating
|
||||
},
|
||||
newPost.value.text.isNotBlank(),
|
||||
isActive = channelScreenModel.message.text.isNotBlank() && !channelScreenModel.isUploadingImage,
|
||||
modifier = Modifier.padding(end = 10.dp)
|
||||
)
|
||||
},
|
||||
leadingIcon = {
|
||||
UploadFromGallery(
|
||||
isUploading = channelScreenModel.isUploadingImage,
|
||||
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||
modifier = Modifier.padding(start = 5.dp)
|
||||
) {
|
||||
channelScreenModel.upload(it, context)
|
||||
}
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
focusedIndicatorColor = Color.Transparent,
|
||||
unfocusedIndicatorColor = Color.Transparent
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -36,6 +37,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
@@ -50,7 +52,9 @@ import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.NostrChatroomDataSource
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel
|
||||
import com.vitorpamplona.amethyst.ui.actions.PostButton
|
||||
import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery
|
||||
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
|
||||
import com.vitorpamplona.amethyst.ui.components.ResizeImage
|
||||
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
|
||||
@@ -64,9 +68,10 @@ import com.vitorpamplona.amethyst.ui.screen.NostrChatRoomFeedViewModel
|
||||
fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navController: NavController) {
|
||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||
val account = accountState?.account
|
||||
val context = LocalContext.current
|
||||
val chatRoomScreenModel: NewPostViewModel = viewModel()
|
||||
|
||||
if (account != null && userId != null) {
|
||||
val newPost = remember { mutableStateOf(TextFieldValue("")) }
|
||||
val replyTo = remember { mutableStateOf<Note?>(null) }
|
||||
|
||||
ChatroomFeedFilter.loadMessagesBetween(account, userId)
|
||||
@@ -77,6 +82,9 @@ fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navContr
|
||||
|
||||
LaunchedEffect(userId) {
|
||||
feedViewModel.refresh()
|
||||
chatRoomScreenModel.imageUploadingError.collect { error ->
|
||||
Toast.makeText(context, error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
DisposableEffect(userId) {
|
||||
@@ -156,8 +164,8 @@ fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navContr
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
TextField(
|
||||
value = newPost.value,
|
||||
onValueChange = { newPost.value = it },
|
||||
value = chatRoomScreenModel.message,
|
||||
onValueChange = { chatRoomScreenModel.updateMessage(it) },
|
||||
keyboardOptions = KeyboardOptions.Default.copy(
|
||||
capitalization = KeyboardCapitalization.Sentences
|
||||
),
|
||||
@@ -173,15 +181,24 @@ fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navContr
|
||||
trailingIcon = {
|
||||
PostButton(
|
||||
onPost = {
|
||||
account.sendPrivateMeesage(newPost.value.text, userId, replyTo.value)
|
||||
newPost.value = TextFieldValue("")
|
||||
account.sendPrivateMessage(chatRoomScreenModel.message.text, userId, replyTo.value)
|
||||
chatRoomScreenModel.message = TextFieldValue("")
|
||||
replyTo.value = null
|
||||
feedViewModel.refresh() // Don't wait a full second before updating
|
||||
},
|
||||
newPost.value.text.isNotBlank(),
|
||||
isActive = chatRoomScreenModel.message.text.isNotBlank() && !chatRoomScreenModel.isUploadingImage,
|
||||
modifier = Modifier.padding(end = 10.dp)
|
||||
)
|
||||
},
|
||||
leadingIcon = {
|
||||
UploadFromGallery(
|
||||
isUploading = chatRoomScreenModel.isUploadingImage,
|
||||
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||
modifier = Modifier.padding(start = 5.dp)
|
||||
) {
|
||||
chatRoomScreenModel.upload(it, context)
|
||||
}
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
focusedIndicatorColor = Color.Transparent,
|
||||
unfocusedIndicatorColor = Color.Transparent
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.google.accompanist.pager.PagerState
|
||||
import com.google.accompanist.pager.pagerTabIndicatorOffset
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.service.NostrHomeDataSource
|
||||
import com.vitorpamplona.amethyst.ui.dal.HomeConversationsFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.navigation.Route
|
||||
import com.vitorpamplona.amethyst.ui.screen.FeedView
|
||||
import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel
|
||||
@@ -43,10 +45,12 @@ fun HomeScreen(
|
||||
scrollToTop: Boolean = false
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val account = accountViewModel.accountLiveData.value?.account ?: return
|
||||
|
||||
LaunchedEffect(accountViewModel) {
|
||||
HomeNewThreadFeedFilter.account = account
|
||||
HomeConversationsFeedFilter.account = account
|
||||
NostrHomeDataSource.resetFilters()
|
||||
|
||||
homeFeedViewModel.refresh()
|
||||
repliesFeedViewModel.refresh()
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.NostrGlobalDataSource
|
||||
import com.vitorpamplona.amethyst.service.NostrSearchEventOrUserDataSource
|
||||
import com.vitorpamplona.amethyst.ui.dal.GlobalFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.note.ChannelName
|
||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||
import com.vitorpamplona.amethyst.ui.note.UserCompose
|
||||
@@ -81,8 +82,11 @@ fun SearchScreen(
|
||||
scrollToTop: Boolean = false
|
||||
) {
|
||||
val lifeCycleOwner = LocalLifecycleOwner.current
|
||||
val account = accountViewModel.accountLiveData.value?.account ?: return
|
||||
|
||||
LaunchedEffect(accountViewModel) {
|
||||
GlobalFeedFilter.account = account
|
||||
NostrGlobalDataSource.resetFilters()
|
||||
feedViewModel.refresh()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<string name="show_anyway">Laat toch zien</string>
|
||||
<string name="post_was_flagged_as_inappropriate_by">Bericht gemarkeerd als ongepast door</string>
|
||||
<string name="post_not_found">Bericht niet gevonden</string>
|
||||
<string name="channel_image">Groepsafbeelding</string>
|
||||
<string name="channel_image">Kanaalafbeelding</string>
|
||||
<string name="referenced_event_not_found">Verwezen event niet gevonden</string>
|
||||
<string name="could_not_decrypt_the_message">Note versleuteld met encryptie</string>
|
||||
<string name="group_picture">Kanaal-afbeelding</string>
|
||||
<string name="group_picture">Groepafbeelding</string>
|
||||
<string name="explicit_content">Expliciete inhoud</string>
|
||||
<string name="spam">Spam</string>
|
||||
<string name="impersonation">Imitatie</string>
|
||||
@@ -53,7 +53,7 @@
|
||||
<string name="lightning_invoice">Lightning invoice</string>
|
||||
<string name="pay">Betalen</string>
|
||||
<string name="lightning_tips">Lightning Tips</string>
|
||||
<string name="note_to_receiver">Notitie aan ontvanger</string>
|
||||
<string name="note_to_receiver">Note aan ontvanger</string>
|
||||
<string name="thank_you_so_much">Hartelijk bedankt!</string>
|
||||
<string name="amount_in_sats">Bedrag in sats</string>
|
||||
<string name="send_sats">Verstuur sats</string>
|
||||
@@ -97,16 +97,16 @@
|
||||
<string name="uploading">Uploaden…</string>
|
||||
<string name="user_does_not_have_a_lightning_address_setup_to_receive_sats">Gebruiker heeft geen Lightning Adress ingesteld om sats te ontvangen</string>
|
||||
<string name="reply_here">"hier reageren.. "</string>
|
||||
<string name="copies_the_note_id_to_the_clipboard_for_sharing">Kopieert Notitie ID naar klembord om te delen</string>
|
||||
<string name="copy_channel_id_note_to_the_clipboard">Kopieer kanaal ID (Notitie) naar klembord</string>
|
||||
<string name="copies_the_note_id_to_the_clipboard_for_sharing">Kopieert note ID naar klembord om te delen</string>
|
||||
<string name="copy_channel_id_note_to_the_clipboard">Kopieer kanaal ID (note) naar klembord</string>
|
||||
<string name="edits_the_channel_metadata">Past de kanaal-metadata aan</string>
|
||||
<string name="join">Lid worden</string>
|
||||
<string name="known">Bekend</string>
|
||||
<string name="new_requests">Nieuw verzoek</string>
|
||||
<string name="blocked_users">Geblokeerde gebruikers</string>
|
||||
<string name="new_threads">Nieuwe notities</string>
|
||||
<string name="new_threads">Nieuwe notes</string>
|
||||
<string name="conversations">Gesprekken</string>
|
||||
<string name="notes">Notities</string>
|
||||
<string name="notes">Notes</string>
|
||||
<string name="replies">Reacties</string>
|
||||
<string name="follows">"Volgend"</string>
|
||||
<string name="reports">"Rapporten"</string>
|
||||
@@ -174,9 +174,9 @@
|
||||
<string name="report_hateful_speech">Haatdragende taal rapporteren</string>
|
||||
<string name="report_nudity_porn">Naaktheid / porno rapporteren</string>
|
||||
<string name="others">anderen</string>
|
||||
<string name="mark_all_known_as_read">Alle bekende als gelezen markeren</string>
|
||||
<string name="mark_all_new_as_read">Alle nieuwe als gelezen markeren</string>
|
||||
<string name="mark_all_as_read">Alles als gelezen markeren</string>
|
||||
<string name="mark_all_known_as_read">Bekende markeren als gelezen</string>
|
||||
<string name="mark_all_new_as_read">Nieuwe markeren als gelezen</string>
|
||||
<string name="mark_all_as_read">Alles markeren als gelezen</string>
|
||||
<string name="backup_keys">Back-up sleutels</string>
|
||||
<string name="account_backup_tips_md" tools:ignore="Typos">
|
||||
## Sleutel back-up en veiligheidstips
|
||||
@@ -193,19 +193,38 @@
|
||||
<string name="badge_award_image_for">"Badge award afbeelding voor %1$s"</string>
|
||||
<string name="new_badge_award_notif">Je hebt een nieuwe Badge award ontvangen</string>
|
||||
<string name="award_granted_to">Badge award gegeven aan</string>
|
||||
<string name="copied_note_text_to_clipboard">Notitie tekst gekopieerd naar klembord</string>
|
||||
<string name="copied_note_text_to_clipboard">Note tekst gekopieerd naar klembord</string>
|
||||
<string name="copied_user_id_to_clipboard" tools:ignore="Typos">@npub auteur gekopieerd naar klembord</string>
|
||||
<string name="copied_note_id_to_clipboard" tools:ignore="Typos">Notitie ID (@note1) gekopieerd naar klembord</string>
|
||||
<string name="copied_note_id_to_clipboard" tools:ignore="Typos">Note ID (@note1) gekopieerd naar klembord</string>
|
||||
<string name="select_text_dialog_top">Selecteer tekst</string>
|
||||
<string name="quick_action_select">Selecteer</string>
|
||||
<string name="quick_action_share_browser_link">Deel browserlink</string>
|
||||
<string name="quick_action_share">Delen</string>
|
||||
<string name="quick_action_copy_user_id">Auteur ID</string>
|
||||
<string name="quick_action_copy_note_id">Notitie ID</string>
|
||||
<string name="quick_action_copy_note_id">Note ID</string>
|
||||
<string name="quick_action_copy_text">Kopieer tekst</string>
|
||||
<string name="quick_action_delete">Verwijderen</string>
|
||||
<string name="quick_action_unfollow">Ontvolgen</string>
|
||||
<string name="quick_action_follow">Volgen</string>
|
||||
<string name="quick_action_request_deletion_alert_title">Verzoek om te verwijderen</string>
|
||||
<string name="quick_action_request_deletion_alert_body">Amethyst zal vragen om uw notitie te verwijderen van de relays waarmee u momenteel verbonden bent. Er is geen garantie dat uw notitie permanent wordt verwijderd van deze relays, of van andere relays waar het kan worden opgeslagen.</string>
|
||||
<string name="quick_action_request_deletion_alert_body">Amethyst zal vragen om uw note te verwijderen van de relays waarmee u momenteel verbonden bent. Er is geen garantie dat uw note permanent wordt verwijderd van deze relays, of van andere relays waar het kan worden opgeslagen.</string>
|
||||
<string name="github" translatable="false">Github Gist w/ Proof</string>
|
||||
<string name="telegram" translatable="false">Telegram</string>
|
||||
<string name="mastodon" translatable="false">Mastodon Post ID w/ Proof</string>
|
||||
<string name="twitter" translatable="false">Twitter Status w/ Proof</string>
|
||||
<string name="github_proof_url_template" translatable="false">https://gist.github.com/<user>/<gist></string>
|
||||
<string name="telegram_proof_url_template" translatable="false">https://t.me/<proof post></string>
|
||||
<string name="mastodon_proof_url_template" translatable="false">https://<server>/<user>/<proof post></string>
|
||||
<string name="twitter_proof_url_template" translatable="false">https://twitter.com/<user>/status/<proof post></string>
|
||||
<string name="private_conversation_notification">"<Kan privébericht niet ontsleutelen>\n\nJe werd genoemd in een privégesprek tussen %1$s en %2$s."</string>
|
||||
<string name="quick_action_delete_button">Verwijderen</string>
|
||||
<string name="quick_action_dont_show_again_button">Niet meer laten zien</string>
|
||||
<string name="account_switch_add_account_dialog_title">Nieuw account toevoegen</string>
|
||||
<string name="drawer_accounts">Accounts</string>
|
||||
<string name="account_switch_select_account">Account selecteren</string>
|
||||
<string name="account_switch_add_account_btn">Nieuw account toevoegen</string>
|
||||
<string name="account_switch_active_account">Account activeren</string>
|
||||
<string name="account_switch_has_private_key">Heeft privésleutel</string>
|
||||
<string name="account_switch_pubkey_only">Alleen lezen, geen privésleutel</string>
|
||||
<string name="back">Terug</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user