Compare commits

...

19 Commits

Author SHA1 Message Date
Vitor Pamplona
dab02f2cbd v0.77.4 2023-09-20 19:05:00 -04:00
Vitor Pamplona
978f13fbf3 Activates sliding effect for all screens 2023-09-20 18:59:49 -04:00
Vitor Pamplona
831386a656 Using Slide in and out instead of crossfade for the top and bottom bars. 2023-09-20 18:57:11 -04:00
Vitor Pamplona
8b7406e25a Merge pull request #607 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-20 18:41:11 -04:00
Crowdin Bot
9e7fed6646 New Crowdin translations by GitHub Action 2023-09-20 22:19:01 +00:00
Vitor Pamplona
89d88326e8 Merge pull request #606 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-20 18:18:08 -04:00
Vitor Pamplona
f18dd02161 Merge pull request #605 from greenart7c3/main
immersive scrolling on home feed
2023-09-20 18:17:56 -04:00
Crowdin Bot
e00db19485 New Crowdin translations by GitHub Action 2023-09-20 22:14:39 +00:00
Vitor Pamplona
a706b71d7c Moves reaction calls to the viewModelScope 2023-09-20 18:12:41 -04:00
greenart7c3
a83b26cc6f immersive scrolling on home feed 2023-09-20 18:18:56 -03:00
Vitor Pamplona
dc73843447 Fixes OK string 2023-09-20 16:43:57 -04:00
Vitor Pamplona
3e6aa2b943 Protects against null contact lists 2023-09-20 16:32:38 -04:00
Vitor Pamplona
909d3f4fbe Migrates alt descriptions from .content to alt tag. 2023-09-20 16:18:21 -04:00
Vitor Pamplona
fb0748f4a7 v0.77.3 2023-09-20 15:12:23 -04:00
Vitor Pamplona
1ec4823122 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-20 15:11:56 -04:00
Vitor Pamplona
cce5e0bf21 v0.77.2 2023-09-20 15:11:51 -04:00
Vitor Pamplona
0006595786 Quick fix on zap notifications 2023-09-20 15:11:35 -04:00
Vitor Pamplona
6b884f645e Merge pull request #604 from greenart7c3/main
Change nav bar color according to the theme
2023-09-20 14:58:18 -04:00
greenart7c3
946723a80e change nav bar color 2023-09-20 15:42:21 -03:00
18 changed files with 154 additions and 69 deletions

View File

@@ -13,8 +13,8 @@ android {
applicationId "com.vitorpamplona.amethyst"
minSdk 26
targetSdk 34
versionCode 298
versionName "0.77.1"
versionCode 301
versionName "0.77.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@@ -352,7 +352,11 @@ object LocalPreferences {
val latestContactList = try {
getString(PrefKeys.LATEST_CONTACT_LIST, null)?.let {
println("Decoding Contact List: " + it)
Event.fromJson(it) as ContactListEvent?
if (it != null) {
Event.fromJson(it) as ContactListEvent?
} else {
null
}
}
} catch (e: Throwable) {
Log.w("LocalPreferences", "Error Decoding Contact List ${getString(PrefKeys.LATEST_CONTACT_LIST, null)}", e)

View File

@@ -1202,7 +1202,7 @@ class Account(
size = headerInfo.size.toString(),
dimensions = headerInfo.dim,
blurhash = headerInfo.blurHash,
description = headerInfo.description,
alt = headerInfo.alt,
sensitiveContent = headerInfo.sensitiveContent,
pubKey = keyPair.pubKey.toHexKey()
)
@@ -1234,7 +1234,7 @@ class Account(
size = headerInfo.size.toString(),
dimensions = headerInfo.dim,
blurhash = headerInfo.blurHash,
description = headerInfo.description,
alt = headerInfo.alt,
sensitiveContent = headerInfo.sensitiveContent,
privateKey = keyPair.privKey!!
)
@@ -1273,7 +1273,7 @@ class Account(
size = headerInfo.size.toString(),
dimensions = headerInfo.dim,
blurhash = headerInfo.blurHash,
description = headerInfo.description,
alt = headerInfo.alt,
sensitiveContent = headerInfo.sensitiveContent,
keyPair = keyPair
)
@@ -1298,7 +1298,7 @@ class Account(
size = headerInfo.size.toString(),
dimensions = headerInfo.dim,
blurhash = headerInfo.blurHash,
description = headerInfo.description,
alt = headerInfo.alt,
sensitiveContent = headerInfo.sensitiveContent,
keyPair = keyPair
)

View File

@@ -16,16 +16,16 @@ class FileHeader(
val size: Int,
val dim: String?,
val blurHash: String?,
val description: String? = null,
val alt: String? = null,
val sensitiveContent: Boolean = false
) {
companion object {
suspend fun prepare(fileUrl: String, mimeType: String?, description: String?, sensitiveContent: Boolean, onReady: (FileHeader) -> Unit, onError: () -> Unit) {
suspend fun prepare(fileUrl: String, mimeType: String?, alt: String?, sensitiveContent: Boolean, onReady: (FileHeader) -> Unit, onError: () -> Unit) {
try {
val imageData: ByteArray? = ImageDownloader().waitAndGetImage(fileUrl)
if (imageData != null) {
prepare(imageData, fileUrl, mimeType, description, sensitiveContent, onReady, onError)
prepare(imageData, fileUrl, mimeType, alt, sensitiveContent, onReady, onError)
} else {
onError()
}
@@ -39,7 +39,7 @@ class FileHeader(
data: ByteArray,
fileUrl: String,
mimeType: String?,
description: String?,
alt: String?,
sensitiveContent: Boolean,
onReady: (FileHeader) -> Unit,
onError: () -> Unit
@@ -79,7 +79,7 @@ class FileHeader(
Pair(null, null)
}
onReady(FileHeader(fileUrl, mimeType, hash, size, dim, blurHash, description, sensitiveContent))
onReady(FileHeader(fileUrl, mimeType, hash, size, dim, blurHash, alt, sensitiveContent))
} catch (e: Exception) {
Log.e("ImageDownload", "Couldn't convert image in to File Header: ${e.message}")
onError()

View File

@@ -26,7 +26,7 @@ open class NewMediaModel : ViewModel() {
var mediaType by mutableStateOf<String?>(null)
var selectedServer by mutableStateOf<ServersAvailable?>(null)
var description by mutableStateOf("")
var alt by mutableStateOf("")
var sensitiveContent by mutableStateOf(false)
// Images and Videos
@@ -79,7 +79,7 @@ open class NewMediaModel : ViewModel() {
uploadingPercentage.value = 0.2f
uploadingDescription.value = "Loading"
contentResolver.openInputStream(fileUri)?.use {
createNIP95Record(it.readBytes(), contentType, description, sensitiveContent, relayList = relayList)
createNIP95Record(it.readBytes(), contentType, alt, sensitiveContent, relayList = relayList)
}
?: run {
viewModelScope.launch {
@@ -103,7 +103,7 @@ open class NewMediaModel : ViewModel() {
createNIP94Record(
imageUrl,
mimeType,
description,
alt,
sensitiveContent,
relayList = relayList
)
@@ -139,7 +139,7 @@ open class NewMediaModel : ViewModel() {
uploadingDescription.value = null
uploadingPercentage.value = 0.0f
description = ""
alt = ""
selectedServer = account?.defaultFileServer
}
@@ -147,7 +147,7 @@ open class NewMediaModel : ViewModel() {
return !isUploadingImage && galleryUri != null && selectedServer != null
}
fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
fun createNIP94Record(imageUrl: String, mimeType: String?, alt: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
uploadingPercentage.value = 0.40f
viewModelScope.launch(Dispatchers.IO) {
uploadingDescription.value = "Server Processing"
@@ -166,7 +166,7 @@ open class NewMediaModel : ViewModel() {
imageData,
imageUrl,
mimeType,
description,
alt,
sensitiveContent,
onReady = {
uploadingPercentage.value = 0.90f
@@ -200,7 +200,7 @@ open class NewMediaModel : ViewModel() {
}
}
fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
fun createNIP95Record(bytes: ByteArray, mimeType: String?, alt: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
uploadingPercentage.value = 0.30f
uploadingDescription.value = "Hashing"
@@ -209,7 +209,7 @@ open class NewMediaModel : ViewModel() {
bytes,
"",
mimeType,
description,
alt,
sensitiveContent,
onReady = {
uploadingDescription.value = "Signing"

View File

@@ -287,8 +287,8 @@ fun ImageVideoPost(postViewModel: NewMediaModel, accountViewModel: AccountViewMo
modifier = Modifier
.fillMaxWidth()
.windowInsetsPadding(WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)),
value = postViewModel.description,
onValueChange = { postViewModel.description = it },
value = postViewModel.alt,
onValueChange = { postViewModel.alt = it },
placeholder = {
Text(
text = stringResource(R.string.content_description_example),

View File

@@ -338,8 +338,8 @@ fun NewPostView(
ImageVideoDescription(
url,
account.defaultFileServer,
onAdd = { description, server, sensitiveContent ->
postViewModel.upload(url, description, sensitiveContent, server, context, relayList)
onAdd = { alt, server, sensitiveContent ->
postViewModel.upload(url, alt, sensitiveContent, server, context, relayList)
account.changeDefaultFileServer(server)
},
onCancel = {

View File

@@ -299,7 +299,7 @@ open class NewPostViewModel() : ViewModel() {
cancel()
}
fun upload(galleryUri: Uri, description: String, sensitiveContent: Boolean, server: ServersAvailable, context: Context, relayList: List<Relay>? = null) {
fun upload(galleryUri: Uri, alt: String, sensitiveContent: Boolean, server: ServersAvailable, context: Context, relayList: List<Relay>? = null) {
isUploadingImage = true
contentToAddUrl = null
@@ -314,7 +314,7 @@ open class NewPostViewModel() : ViewModel() {
onReady = { fileUri, contentType, size ->
if (server == ServersAvailable.NIP95) {
contentResolver.openInputStream(fileUri)?.use {
createNIP95Record(it.readBytes(), contentType, description, sensitiveContent, relayList = relayList)
createNIP95Record(it.readBytes(), contentType, alt, sensitiveContent, relayList = relayList)
}
} else {
ImageUploader.uploadImage(
@@ -325,7 +325,7 @@ open class NewPostViewModel() : ViewModel() {
contentResolver = contentResolver,
onSuccess = { imageUrl, mimeType ->
if (isNIP94Server(server)) {
createNIP94Record(imageUrl, mimeType, description, sensitiveContent)
createNIP94Record(imageUrl, mimeType, alt, sensitiveContent)
} else {
isUploadingImage = false
message = TextFieldValue(message.text + "\n\n" + imageUrl)
@@ -537,13 +537,13 @@ open class NewPostViewModel() : ViewModel() {
}
}
fun createNIP94Record(imageUrl: String, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
fun createNIP94Record(imageUrl: String, mimeType: String?, alt: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
viewModelScope.launch(Dispatchers.IO) {
// Images don't seem to be ready immediately after upload
FileHeader.prepare(
imageUrl,
mimeType,
description,
alt,
sensitiveContent,
onReady = {
val note = account?.sendHeader(it, relayList = relayList)
@@ -568,13 +568,13 @@ open class NewPostViewModel() : ViewModel() {
}
}
fun createNIP95Record(bytes: ByteArray, mimeType: String?, description: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
fun createNIP95Record(bytes: ByteArray, mimeType: String?, alt: String, sensitiveContent: Boolean, relayList: List<Relay>? = null) {
viewModelScope.launch(Dispatchers.IO) {
FileHeader.prepare(
bytes,
"",
mimeType,
description,
alt,
sensitiveContent,
onReady = {
val nip95 = account?.createNip95(bytes, headerInfo = it)

View File

@@ -179,7 +179,7 @@ private fun Galeries(
val hasLikeEvents by remember { derivedStateOf { multiSetCard.likeEvents.isNotEmpty() } }
if (hasZapEvents) {
var zapEvents by remember(multiSetCard) {
var zapEvents by remember(multiSetCard.zapEvents) {
mutableStateOf<ImmutableList<ZapAmountCommentNotification>>(persistentListOf())
}

View File

@@ -3343,7 +3343,7 @@ fun FileHeaderDisplay(note: Note, roundedCorner: Boolean, accountViewModel: Acco
val blurHash = event.blurhash()
val hash = event.hash()
val dimensions = event.dimensions()
val description = event.content
val description = event.alt() ?: event.content
val isImage = imageExtensions.any { fullUrl.split("?")[0].lowercase().endsWith(it) }
val uri = note.toNostrUri()
@@ -3407,7 +3407,7 @@ private fun ObserverAndRenderNIP95(
val localDir = note?.idHex?.let { File(File(appContext.cacheDir, "NIP95"), it) }
val blurHash = eventHeader.blurhash()
val dimensions = eventHeader.dimensions()
val description = eventHeader.content
val description = eventHeader.alt() ?: eventHeader.content
val mimeType = eventHeader.mimeType()
val newContent = if (mimeType?.startsWith("image") == true) {

View File

@@ -1366,18 +1366,14 @@ private fun ActionableReactionButton(
onChangeAmount: () -> Unit,
toRemove: Set<String>
) {
val scope = rememberCoroutineScope()
Button(
modifier = Modifier.padding(horizontal = 3.dp),
onClick = {
scope.launch(Dispatchers.IO) {
accountViewModel.reactToOrDelete(
baseNote,
reactionType
)
onDismiss()
}
accountViewModel.reactToOrDelete(
baseNote,
reactionType
)
onDismiss()
},
shape = ButtonBorder,
colors = ButtonDefaults
@@ -1388,13 +1384,11 @@ private fun ActionableReactionButton(
val thisModifier = remember(reactionType) {
Modifier.combinedClickable(
onClick = {
scope.launch(Dispatchers.IO) {
accountViewModel.reactToOrDelete(
baseNote,
reactionType
)
onDismiss()
}
accountViewModel.reactToOrDelete(
baseNote,
reactionType
)
onDismiss()
},
onLongClick = {
onChangeAmount()

View File

@@ -117,11 +117,13 @@ class AccountViewModel(val account: Account) : ViewModel(), Dao {
}
fun reactToOrDelete(note: Note, reaction: String) {
val currentReactions = account.reactionTo(note, reaction)
if (currentReactions.isNotEmpty()) {
account.delete(currentReactions)
} else {
account.reactTo(note, reaction)
viewModelScope.launch(Dispatchers.IO) {
val currentReactions = account.reactionTo(note, reaction)
if (currentReactions.isNotEmpty()) {
account.delete(currentReactions)
} else {
account.reactTo(note, reaction)
}
}
}

View File

@@ -2,8 +2,14 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn
import android.content.res.Configuration
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.Crossfade
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
import androidx.compose.animation.with
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
@@ -15,11 +21,18 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavBackStackEntry
import androidx.navigation.compose.currentBackStackEntryAsState
@@ -44,7 +57,7 @@ import com.vitorpamplona.amethyst.ui.screen.NotificationViewModel
import com.vitorpamplona.amethyst.ui.screen.ThemeViewModel
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@OptIn(ExperimentalMaterialApi::class, ExperimentalAnimationApi::class)
@Composable
fun MainScreen(
accountViewModel: AccountViewModel,
@@ -180,6 +193,23 @@ fun MainScreen(
}
}
val bottomBarHeight = 50.dp
val bottomBarHeightPx = with(LocalDensity.current) { bottomBarHeight.roundToPx().toFloat() }
val bottomBarOffsetHeightPx = remember { mutableStateOf(0f) }
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y
val newOffset = bottomBarOffsetHeightPx.value + delta
bottomBarOffsetHeightPx.value = newOffset.coerceIn(-bottomBarHeightPx, 0f)
return Offset.Zero
}
}
}
val shouldShow = bottomBarOffsetHeightPx.value == 0f
ModalBottomSheetLayout(
sheetState = sheetState,
sheetContent = {
@@ -189,12 +219,40 @@ fun MainScreen(
Scaffold(
modifier = Modifier
.background(MaterialTheme.colors.primaryVariant)
.statusBarsPadding(),
.statusBarsPadding()
.nestedScroll(nestedScrollConnection),
bottomBar = {
AppBottomBar(accountViewModel, navState, navBottomRow)
AnimatedContent(
targetState = shouldShow,
transitionSpec = {
slideInVertically { height -> height } togetherWith
slideOutVertically { height -> height }
}
) { isVisible ->
if (isVisible) {
AppBottomBar(accountViewModel, navState, navBottomRow)
}
}
},
topBar = {
AppTopBar(followLists, navState, scaffoldState, accountViewModel, nav = nav, navPopBack)
AnimatedContent(
targetState = shouldShow,
transitionSpec = {
slideInVertically { height -> 0 } togetherWith
slideOutVertically { height -> 0 }
}
) { isVisible ->
if (isVisible) {
AppTopBar(
followLists,
navState,
scaffoldState,
accountViewModel,
nav = nav,
navPopBack
)
}
}
},
drawerContent = {
DrawerContent(nav, scaffoldState, sheetState, accountViewModel)
@@ -203,11 +261,27 @@ fun MainScreen(
}
},
floatingActionButton = {
FloatingButtons(navState, accountViewModel, accountStateViewModel, nav, navBottomRow)
Crossfade(
targetState = shouldShow,
animationSpec = tween(durationMillis = 100)
) { state ->
if (state) {
FloatingButtons(
navState,
accountViewModel,
accountStateViewModel,
nav,
navBottomRow
)
}
}
},
scaffoldState = scaffoldState
) {
Column(modifier = Modifier.padding(bottom = it.calculateBottomPadding())) {
Column(
modifier = Modifier
.padding(bottom = if (bottomBarOffsetHeightPx.value == 0f || navState.value?.destination?.route != Route.Home.base) it.calculateBottomPadding() else 0.dp)
) {
AppNavigation(
homeFeedViewModel = homeFeedViewModel,
repliesFeedViewModel = repliesFeedViewModel,

View File

@@ -26,6 +26,7 @@ import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.core.view.WindowCompat
import com.halilibo.richtext.ui.RichTextStyle
import com.halilibo.richtext.ui.resolveDefaults
import com.patrykandpatrick.vico.compose.style.ChartStyle
@@ -347,11 +348,14 @@ fun AmethystTheme(themeViewModel: ThemeViewModel, content: @Composable () -> Uni
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
val insetsController = WindowCompat.getInsetsController(window, view)
if (darkTheme) {
window.statusBarColor = colors.background.toArgb()
} else {
window.statusBarColor = colors.primary.toArgb()
}
window.navigationBarColor = colors.background.toArgb()
insetsController.isAppearanceLightNavigationBars = !darkTheme
}
}
}

View File

@@ -473,7 +473,6 @@
<string name="poll_zap_value_min_max_explainer">I voti sono ponderati con l\'importo dello zap. È possibile impostare una quantità minima per evitare gli spammer e una quantità massima per evitare che un grande zapper predomini il sondaggio. Usa lo stesso importo in entrambi i campi per assicurarti che ogni voto valga lo stesso importo. Lascialo vuoto per accettare qualsiasi importo.</string>
<string name="error_dialog_zap_error">Impossibile inviare lo zap</string>
<string name="error_dialog_talk_to_user">Invia un messaggio all\'utente</string>
<string name="error_dialog_button_ok">OK</string>
<string name="relay_information_document_error_assemble_url">Impossibile raggiungere %1$s: %2$s</string>
<string name="relay_information_document_error_reach_server">Impossibile raggiungere %1$s: %2$s</string>
<string name="relay_information_document_error_parse_result">Impossibile analizzare il risultato da %1$s: %2$s</string>

View File

@@ -561,7 +561,7 @@
<string name="error_dialog_zap_error">Unable to send zap</string>
<string name="error_dialog_talk_to_user">Message the User</string>
<string name="error_dialog_button_ok">Ok</string>
<string name="error_dialog_button_ok">OK</string>
<string name="relay_information_document_error_assemble_url">Failed to reach %1$s: %2$s</string>
<string name="relay_information_document_error_reach_server">Failed to reach %1$s: %2$s</string>

View File

@@ -22,6 +22,7 @@ class FileHeaderEvent(
fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == MIME_TYPE }?.get(1)
fun hash() = tags.firstOrNull { it.size > 1 && it[0] == HASH }?.get(1)
fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1)
fun alt() = tags.firstOrNull { it.size > 1 && it[0] == ALT }?.get(1)
fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1)
fun magnetURI() = tags.firstOrNull { it.size > 1 && it[0] == MAGNET_URI }?.get(1)
fun torrentInfoHash() = tags.firstOrNull { it.size > 1 && it[0] == TORRENT_INFOHASH }?.get(1)
@@ -41,11 +42,12 @@ class FileHeaderEvent(
private const val MAGNET_URI = "magnet"
private const val TORRENT_INFOHASH = "i"
private const val BLUR_HASH = "blurhash"
private const val ALT = "alt"
fun create(
url: String,
mimeType: String? = null,
description: String? = null,
alt: String? = null,
hash: String? = null,
size: String? = null,
dimensions: String? = null,
@@ -60,11 +62,13 @@ class FileHeaderEvent(
val tags = listOfNotNull(
listOf(URL, url),
mimeType?.let { listOf(MIME_TYPE, mimeType) },
alt?.let { listOf(ALT, it) },
hash?.let { listOf(HASH, it) },
size?.let { listOf(FILE_SIZE, it) },
dimensions?.let { listOf(DIMENSION, it) },
blurhash?.let { listOf(BLUR_HASH, it) },
magnetURI?.let { listOf(MAGNET_URI, it) },
torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) },
encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) },
sensitiveContent?.let {
@@ -76,7 +80,7 @@ class FileHeaderEvent(
}
)
val content = description ?: ""
val content = alt ?: ""
val pubKey = keyPair.pubKey.toHexKey()
val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = if (keyPair.privKey == null) null else CryptoUtils.sign(id, keyPair.privKey)

View File

@@ -22,6 +22,7 @@ class FileStorageHeaderEvent(
fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == MIME_TYPE }?.get(1)
fun hash() = tags.firstOrNull { it.size > 1 && it[0] == HASH }?.get(1)
fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1)
fun alt() = tags.firstOrNull { it.size > 1 && it[0] == ALT }?.get(1)
fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1)
fun magnetURI() = tags.firstOrNull { it.size > 1 && it[0] == MAGNET_URI }?.get(1)
fun torrentInfoHash() = tags.firstOrNull { it.size > 1 && it[0] == TORRENT_INFOHASH }?.get(1)
@@ -38,11 +39,12 @@ class FileStorageHeaderEvent(
private const val MAGNET_URI = "magnet"
private const val TORRENT_INFOHASH = "i"
private const val BLUR_HASH = "blurhash"
private const val ALT = "alt"
fun create(
storageEvent: FileStorageEvent,
mimeType: String? = null,
description: String? = null,
alt: String? = null,
hash: String? = null,
size: String? = null,
dimensions: String? = null,
@@ -57,6 +59,7 @@ class FileStorageHeaderEvent(
val tags = listOfNotNull(
listOf("e", storageEvent.id),
mimeType?.let { listOf(MIME_TYPE, mimeType) },
alt?.let { listOf(ALT, it) },
hash?.let { listOf(HASH, it) },
size?.let { listOf(FILE_SIZE, it) },
dimensions?.let { listOf(DIMENSION, it) },
@@ -73,7 +76,7 @@ class FileStorageHeaderEvent(
}
)
val content = description ?: ""
val content = alt ?: ""
val id = generateId(pubKey, createdAt, kind, tags, content)
return FileStorageHeaderEvent(id.toHexKey(), pubKey, createdAt, tags, content, "")
}
@@ -81,7 +84,7 @@ class FileStorageHeaderEvent(
fun create(
storageEvent: FileStorageEvent,
mimeType: String? = null,
description: String? = null,
alt: String? = null,
hash: String? = null,
size: String? = null,
dimensions: String? = null,
@@ -97,6 +100,7 @@ class FileStorageHeaderEvent(
listOf("e", storageEvent.id),
mimeType?.let { listOf(MIME_TYPE, mimeType) },
hash?.let { listOf(HASH, it) },
alt?.let { listOf(ALT, it) },
size?.let { listOf(FILE_SIZE, it) },
dimensions?.let { listOf(DIMENSION, it) },
blurhash?.let { listOf(BLUR_HASH, it) },
@@ -112,7 +116,7 @@ class FileStorageHeaderEvent(
}
)
val content = description ?: ""
val content = alt ?: ""
val pubKey = CryptoUtils.pubkeyCreate(privateKey).toHexKey()
val id = generateId(pubKey, createdAt, kind, tags, content)
val sig = CryptoUtils.sign(id, privateKey)