Rename remaining session id refs

This commit is contained in:
bemusementpark
2024-07-17 12:32:15 +09:30
parent ce1790a895
commit 8245e4ffe5
37 changed files with 187 additions and 202 deletions

View File

@@ -136,29 +136,29 @@ class SodiumUtilitiesTest {
}
@Test
fun sessionIdSuccess() {
val result = SodiumUtilities.sessionId("05$publicKey", "15$blindedPublicKey", serverPublicKey)
fun accountIdSuccess() {
val result = SodiumUtilities.accountId("05$publicKey", "15$blindedPublicKey", serverPublicKey)
assertTrue(result)
}
@Test
fun sessionIdFailureInvalidAccountId() {
val result = SodiumUtilities.sessionId("AB$publicKey", "15$blindedPublicKey", serverPublicKey)
fun accountIdFailureInvalidAccountId() {
val result = SodiumUtilities.accountId("AB$publicKey", "15$blindedPublicKey", serverPublicKey)
assertFalse(result)
}
@Test
fun sessionIdFailureInvalidBlindedId() {
val result = SodiumUtilities.sessionId("05$publicKey", "AB$blindedPublicKey", serverPublicKey)
fun accountIdFailureInvalidBlindedId() {
val result = SodiumUtilities.accountId("05$publicKey", "AB$blindedPublicKey", serverPublicKey)
assertFalse(result)
}
@Test
fun sessionIdFailureBlindingFactor() {
val result = SodiumUtilities.sessionId("05$publicKey", "15$blindedPublicKey", "Test")
fun accountIdFailureBlindingFactor() {
val result = SodiumUtilities.accountId("05$publicKey", "15$blindedPublicKey", "Test")
assertFalse(result)
}

View File

@@ -45,7 +45,7 @@ class NewMessageFragment : Fragment() {
viewModel,
onClose = { delegate.onDialogClosePressed() },
onBack = { delegate.onDialogBackPressed() },
onHelp = { requireContext().openUrl("https://sessionapp.zendesk.com/hc/en-us/articles/4439132747033-How-do-Session-ID-usernames-work") }
onHelp = { requireContext().openUrl("https://sessionapp.zendesk.com/hc/en-us/articles/4439132747033-How-do-Account-ID-usernames-work") }
)
}

View File

@@ -239,12 +239,12 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
intent.getParcelableExtra<Address>(ADDRESS)?.let { it ->
threadId = threadDb.getThreadIdIfExistsFor(it.serialize())
if (threadId == -1L) {
val sessionId = AccountId(it.serialize())
val accountId = AccountId(it.serialize())
val openGroup = lokiThreadDb.getOpenGroupChat(intent.getLongExtra(FROM_GROUP_THREAD_ID, -1))
val address = if (sessionId.prefix == IdPrefix.BLINDED && openGroup != null) {
storage.getOrCreateBlindedIdMapping(sessionId.hexString, openGroup.server, openGroup.publicKey).sessionId?.let {
val address = if (accountId.prefix == IdPrefix.BLINDED && openGroup != null) {
storage.getOrCreateBlindedIdMapping(accountId.hexString, openGroup.server, openGroup.publicKey).accountId?.let {
fromSerialized(it)
} ?: GroupUtil.getEncodedOpenGroupInboxID(openGroup, sessionId)
} ?: GroupUtil.getEncodedOpenGroupInboxID(openGroup, accountId)
} else {
it
}
@@ -1131,8 +1131,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
}
override fun copyAccountID(sessionId: String) {
val clip = ClipData.newPlainText("Account ID", sessionId)
override fun copyAccountID(accountId: String) {
val clip = ClipData.newPlainText("Account ID", accountId)
val manager = getSystemService(PassphraseRequiredActionBarActivity.CLIPBOARD_SERVICE) as ClipboardManager
manager.setPrimaryClip(clip)
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()

View File

@@ -57,7 +57,7 @@ object ConversationMenuHelper {
if (!isOpenGroup && (thread.hasApprovedMe() || thread.isClosedGroupRecipient || thread.isLocalNumber)) {
inflater.inflate(R.menu.menu_conversation_expiration, menu)
}
// One-on-one chat menu allows copying the session id
// One-on-one chat menu allows copying the account id
if (thread.isContactRecipient) {
inflater.inflate(R.menu.menu_conversation_copy_account_id, menu)
}
@@ -325,7 +325,7 @@ object ConversationMenuHelper {
interface ConversationMenuListener {
fun block(deleteThread: Boolean = false)
fun unblock()
fun copyAccountID(sessionId: String)
fun copyAccountID(accountId: String)
fun copyOpenGroupUrl(thread: Recipient)
fun showDisappearingMessages(thread: Recipient)
}

View File

@@ -157,7 +157,7 @@ object MentionUtilities {
}
private fun isYou(mentionedPublicKey: String, userPublicKey: String, openGroup: OpenGroup?): Boolean {
val isUserBlindedPublicKey = openGroup?.let { SodiumUtilities.sessionId(userPublicKey, mentionedPublicKey, it.publicKey) } ?: false
val isUserBlindedPublicKey = openGroup?.let { SodiumUtilities.accountId(userPublicKey, mentionedPublicKey, it.publicKey) } ?: false
return mentionedPublicKey.equals(userPublicKey, ignoreCase = true) || isUserBlindedPublicKey
}
}

View File

@@ -31,7 +31,7 @@ class BlindedIdMappingDatabase(context: Context, helper: SQLCipherOpenHelper) :
private fun readBlindedIdMapping(cursor: Cursor): BlindedIdMapping {
return BlindedIdMapping(
blindedId = cursor.getString(cursor.getColumnIndexOrThrow(BLINDED_PK)),
sessionId = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(SESSION_PK)),
accountId = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(SESSION_PK)),
serverUrl = cursor.getString(cursor.getColumnIndexOrThrow(SERVER_URL)),
serverId = cursor.getString(cursor.getColumnIndexOrThrow(SERVER_PK)),
)
@@ -58,7 +58,7 @@ class BlindedIdMappingDatabase(context: Context, helper: SQLCipherOpenHelper) :
try {
val values = ContentValues().apply {
put(BLINDED_PK, blindedIdMapping.blindedId)
put(SERVER_PK, blindedIdMapping.sessionId)
put(SERVER_PK, blindedIdMapping.accountId)
put(SERVER_URL, blindedIdMapping.serverUrl)
put(SERVER_PK, blindedIdMapping.serverId)
}

View File

@@ -42,12 +42,12 @@ class SessionContactDatabase(context: Context, helper: SQLCipherOpenHelper) : Da
}
}
fun getContacts(sessionIDs: Collection<String>): List<Contact> {
fun getContacts(accountIDs: Collection<String>): List<Contact> {
val database = databaseHelper.readableDatabase
return database.getAll(
sessionContactTable,
"$accountID IN (SELECT value FROM json_each(?))",
arrayOf(JSONArray(sessionIDs).toString())
arrayOf(JSONArray(accountIDs).toString())
) { cursor -> contactFromCursor(cursor) }
}
@@ -56,8 +56,7 @@ class SessionContactDatabase(context: Context, helper: SQLCipherOpenHelper) : Da
return database.getAll(sessionContactTable, null, null) { cursor ->
contactFromCursor(cursor)
}.filter { contact ->
val sessionId = AccountId(contact.accountID)
sessionId.prefix == IdPrefix.STANDARD
contact.accountID.let(::AccountId).prefix == IdPrefix.STANDARD
}.toSet()
}

View File

@@ -6,6 +6,7 @@ import java.security.MessageDigest
import network.loki.messenger.libsession_util.ConfigBase
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_HIDDEN
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_PINNED
import network.loki.messenger.libsession_util.ConfigBase.Companion.PRIORITY_VISIBLE
import network.loki.messenger.libsession_util.Contacts
import network.loki.messenger.libsession_util.ConversationVolatileConfig
import network.loki.messenger.libsession_util.UserGroupsConfig
@@ -111,12 +112,12 @@ open class Storage(
if (address.isGroup) {
val groups = configFactory.userGroups ?: return
if (address.isClosedGroup) {
val sessionId = GroupUtil.doubleDecodeGroupId(address.serialize())
val accountId = GroupUtil.doubleDecodeGroupId(address.serialize())
val closedGroup = getGroup(address.toGroupString())
if (closedGroup != null && closedGroup.isActive) {
val legacyGroup = groups.getOrConstructLegacyGroupInfo(sessionId)
val legacyGroup = groups.getOrConstructLegacyGroupInfo(accountId)
groups.set(legacyGroup)
val newVolatileParams = volatile.getOrConstructLegacyGroup(sessionId).copy(
val newVolatileParams = volatile.getOrConstructLegacyGroup(accountId).copy(
lastRead = SnodeAPI.nowWithOffset,
)
volatile.set(newVolatileParams)
@@ -132,11 +133,11 @@ open class Storage(
if (getUserPublicKey() != address.serialize()) {
val contacts = configFactory.contacts ?: return
contacts.upsertContact(address.serialize()) {
priority = ConfigBase.PRIORITY_VISIBLE
priority = PRIORITY_VISIBLE
}
} else {
val userProfile = configFactory.user ?: return
userProfile.setNtsPriority(ConfigBase.PRIORITY_VISIBLE)
userProfile.setNtsPriority(PRIORITY_VISIBLE)
DatabaseComponent.get(context).threadDatabase().setHasSent(threadId, true)
}
val newVolatileParams = volatile.getOrConstructOneToOne(address.serialize())
@@ -149,9 +150,9 @@ open class Storage(
if (address.isGroup) {
val groups = configFactory.userGroups ?: return
if (address.isClosedGroup) {
val sessionId = GroupUtil.doubleDecodeGroupId(address.serialize())
volatile.eraseLegacyClosedGroup(sessionId)
groups.eraseLegacyGroup(sessionId)
val accountId = GroupUtil.doubleDecodeGroupId(address.serialize())
volatile.eraseLegacyClosedGroup(accountId)
groups.eraseLegacyGroup(accountId)
} else if (address.isCommunity) {
// these should be removed in the group leave / handling new configs
Log.w("Loki", "Thread delete called for open group address, expecting to be handled elsewhere")
@@ -265,10 +266,8 @@ open class Storage(
}
// otherwise recipient is one to one
recipient.isContactRecipient -> {
// don't process non-standard session IDs though
val sessionId = AccountId(recipient.address.serialize())
if (sessionId.prefix != IdPrefix.STANDARD) return
// don't process non-standard account IDs though
if (AccountId(recipient.address.serialize()).prefix != IdPrefix.STANDARD) return
config.getOrConstructOneToOne(recipient.address.serialize())
}
else -> throw NullPointerException("Weren't expecting to have a convo with address ${recipient.address.serialize()}")
@@ -299,8 +298,8 @@ open class Storage(
var messageID: Long? = null
val senderAddress = fromSerialized(message.sender!!)
val isUserSender = (message.sender!! == getUserPublicKey())
val isUserBlindedSender = message.threadID?.takeIf { it >= 0 }?.let { getOpenGroup(it)?.publicKey }
?.let { SodiumUtilities.sessionId(getUserPublicKey()!!, message.sender!!, it) } ?: false
val isUserBlindedSender = message.threadID?.takeIf { it >= 0 }?.let(::getOpenGroup)?.publicKey
?.let { SodiumUtilities.accountId(getUserPublicKey()!!, message.sender!!, it) } ?: false
val group: Optional<SignalServiceGroup> = when {
openGroupID != null -> Optional.of(SignalServiceGroup(openGroupID.toByteArray(), SignalServiceGroup.GroupType.PUBLIC_CHAT))
groupPublicKey != null -> {
@@ -540,7 +539,7 @@ open class Storage(
val extracted = convos.all()
for (conversation in extracted) {
val threadId = when (conversation) {
is Conversation.OneToOne -> getThreadIdFor(conversation.sessionId, null, null, createThread = false)
is Conversation.OneToOne -> getThreadIdFor(conversation.accountId, null, null, createThread = false)
is Conversation.LegacyGroup -> getThreadIdFor("", conversation.groupId,null, createThread = false)
is Conversation.Community -> getThreadIdFor("",null, "${conversation.baseCommunityInfo.baseUrl.removeSuffix("/")}.${conversation.baseCommunityInfo.room}", createThread = false)
}
@@ -571,7 +570,7 @@ open class Storage(
val existingJoinUrls = existingCommunities.values.map { it.joinURL }
val existingClosedGroups = getAllGroups(includeInactive = true).filter { it.isClosedGroup }
val lgcIds = lgc.map { it.sessionId }
val lgcIds = lgc.map { it.accountId }
val toDeleteClosedGroups = existingClosedGroups.filter { group ->
GroupUtil.doubleDecodeGroupId(group.encodedId) !in lgcIds
}
@@ -605,8 +604,8 @@ open class Storage(
}
for (group in lgc) {
val groupId = GroupUtil.doubleEncodeGroupID(group.sessionId)
val existingGroup = existingClosedGroups.firstOrNull { GroupUtil.doubleDecodeGroupId(it.encodedId) == group.sessionId }
val groupId = GroupUtil.doubleEncodeGroupID(group.accountId)
val existingGroup = existingClosedGroups.firstOrNull { GroupUtil.doubleDecodeGroupId(it.encodedId) == group.accountId }
val existingThread = existingGroup?.let { getThreadId(existingGroup.encodedId) }
if (existingGroup != null) {
if (group.priority == PRIORITY_HIDDEN && existingThread != null) {
@@ -625,19 +624,19 @@ open class Storage(
createGroup(groupId, title, admins + members, null, null, admins, formationTimestamp)
setProfileSharing(Address.fromSerialized(groupId), true)
// Add the group to the user's set of public keys to poll for
addClosedGroupPublicKey(group.sessionId)
addClosedGroupPublicKey(group.accountId)
// Store the encryption key pair
val keyPair = ECKeyPair(DjbECPublicKey(group.encPubKey), DjbECPrivateKey(group.encSecKey))
addClosedGroupEncryptionKeyPair(keyPair, group.sessionId, SnodeAPI.nowWithOffset)
addClosedGroupEncryptionKeyPair(keyPair, group.accountId, SnodeAPI.nowWithOffset)
// Notify the PN server
PushRegistryV1.subscribeGroup(group.sessionId, publicKey = localUserPublicKey)
PushRegistryV1.subscribeGroup(group.accountId, publicKey = localUserPublicKey)
// Notify the user
val threadID = getOrCreateThreadIdFor(Address.fromSerialized(groupId))
threadDb.setDate(threadID, formationTimestamp)
insertOutgoingInfoMessage(context, groupId, SignalServiceGroup.Type.CREATION, title, members.map { it.serialize() }, admins.map { it.serialize() }, threadID, formationTimestamp)
// Don't create config group here, it's from a config update
// Start polling
ClosedGroupPollerV2.shared.startPolling(group.sessionId)
ClosedGroupPollerV2.shared.startPolling(group.accountId)
}
getThreadId(Address.fromSerialized(groupId))?.let {
setExpirationConfiguration(
@@ -938,10 +937,10 @@ open class Storage(
groupVolatileConfig.lastRead = formationTimestamp
volatiles.set(groupVolatileConfig)
val groupInfo = GroupInfo.LegacyGroupInfo(
sessionId = groupPublicKey,
accountId = groupPublicKey,
name = name,
members = members,
priority = ConfigBase.PRIORITY_VISIBLE,
priority = PRIORITY_VISIBLE,
encPubKey = (encryptionKeyPair.publicKey as DjbECPublicKey).publicKey, // 'serialize()' inserts an extra byte
encSecKey = encryptionKeyPair.privateKey.serialize(),
disappearingTimer = expirationTimer.toLong(),
@@ -975,7 +974,7 @@ open class Storage(
members = membersMap,
encPubKey = (latestKeyPair.publicKey as DjbECPublicKey).publicKey, // 'serialize()' inserts an extra byte
encSecKey = latestKeyPair.privateKey.serialize(),
priority = if (isPinned(threadID)) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE,
priority = if (isPinned(threadID)) PRIORITY_PINNED else PRIORITY_VISIBLE,
disappearingTimer = getExpirationConfiguration(threadID)?.expiryMode?.expirySeconds ?: 0L,
joinedAt = (existingGroup.formationTimestamp / 1000L)
)
@@ -1209,7 +1208,7 @@ open class Storage(
val mappingDb = DatabaseComponent.get(context).blindedIdMappingDatabase()
val moreContacts = contacts.filter { contact ->
val id = AccountId(contact.id)
id.prefix?.isBlinded() == false || mappingDb.getBlindedIdMapping(contact.id).none { it.sessionId != null }
id.prefix?.isBlinded() == false || mappingDb.getBlindedIdMapping(contact.id).none { it.accountId != null }
}
val profileManager = SSKEnvironment.shared.profileManager
moreContacts.forEach { contact ->
@@ -1262,7 +1261,7 @@ open class Storage(
val mappingDb = DatabaseComponent.get(context).blindedIdMappingDatabase()
val moreContacts = contacts.filter { contact ->
val id = AccountId(contact.publicKey)
id.prefix != IdPrefix.BLINDED || mappingDb.getBlindedIdMapping(contact.publicKey).none { it.sessionId != null }
id.prefix != IdPrefix.BLINDED || mappingDb.getBlindedIdMapping(contact.publicKey).none { it.accountId != null }
}
for (contact in moreContacts) {
val address = fromSerialized(contact.publicKey)
@@ -1329,25 +1328,25 @@ open class Storage(
val threadRecipient = getRecipientForThread(threadID) ?: return
if (threadRecipient.isLocalNumber) {
val user = configFactory.user ?: return
user.setNtsPriority(if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE)
user.setNtsPriority(if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE)
} else if (threadRecipient.isContactRecipient) {
val contacts = configFactory.contacts ?: return
contacts.upsertContact(threadRecipient.address.serialize()) {
priority = if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
}
} else if (threadRecipient.isGroupRecipient) {
val groups = configFactory.userGroups ?: return
if (threadRecipient.isClosedGroupRecipient) {
val sessionId = GroupUtil.doubleDecodeGroupId(threadRecipient.address.serialize())
val newGroupInfo = groups.getOrConstructLegacyGroupInfo(sessionId).copy (
priority = if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE
)
groups.set(newGroupInfo)
threadRecipient.address.serialize()
.let(GroupUtil::doubleDecodeGroupId)
.let(groups::getOrConstructLegacyGroupInfo)
.copy (priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE)
.let(groups::set)
} else if (threadRecipient.isCommunityRecipient) {
val openGroup = getOpenGroup(threadID) ?: return
val (baseUrl, room, pubKeyHex) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: return
val newGroupInfo = groups.getOrConstructCommunityInfo(baseUrl, room, Hex.toStringCondensed(pubKeyHex)).copy (
priority = if (isPinned) PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
)
groups.set(newGroupInfo)
}
@@ -1505,10 +1504,10 @@ open class Storage(
}
}
for (mapping in mappings) {
if (!SodiumUtilities.sessionId(senderPublicKey, mapping.value.blindedId, mapping.value.serverId)) {
if (!SodiumUtilities.accountId(senderPublicKey, mapping.value.blindedId, mapping.value.serverId)) {
continue
}
mappingDb.addBlindedIdMapping(mapping.value.copy(sessionId = senderPublicKey))
mappingDb.addBlindedIdMapping(mapping.value.copy(accountId = senderPublicKey))
val blindedThreadId = threadDB.getOrCreateThreadIdFor(Recipient.from(context, fromSerialized(mapping.key), false))
mmsDb.updateThreadId(blindedThreadId, threadId)
@@ -1614,20 +1613,20 @@ open class Storage(
): BlindedIdMapping {
val db = DatabaseComponent.get(context).blindedIdMappingDatabase()
val mapping = db.getBlindedIdMapping(blindedId).firstOrNull() ?: BlindedIdMapping(blindedId, null, server, serverPublicKey)
if (mapping.sessionId != null) {
if (mapping.accountId != null) {
return mapping
}
getAllContacts().forEach { contact ->
val sessionId = AccountId(contact.accountID)
if (sessionId.prefix == IdPrefix.STANDARD && SodiumUtilities.sessionId(sessionId.hexString, blindedId, serverPublicKey)) {
val contactMapping = mapping.copy(sessionId = sessionId.hexString)
val accountId = AccountId(contact.accountID)
if (accountId.prefix == IdPrefix.STANDARD && SodiumUtilities.accountId(accountId.hexString, blindedId, serverPublicKey)) {
val contactMapping = mapping.copy(accountId = accountId.hexString)
db.addBlindedIdMapping(contactMapping)
return contactMapping
}
}
db.getBlindedIdMappingsExceptFor(server).forEach {
if (SodiumUtilities.sessionId(it.sessionId!!, blindedId, serverPublicKey)) {
val otherMapping = mapping.copy(sessionId = it.sessionId)
if (SodiumUtilities.accountId(it.accountId!!, blindedId, serverPublicKey)) {
val otherMapping = mapping.copy(accountId = it.accountId)
db.addBlindedIdMapping(otherMapping)
return otherMapping
}

View File

@@ -72,7 +72,7 @@ class QRCodeActivity : PassphraseRequiredActionBarActivity() {
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun Tabs(sessionId: String, errors: Flow<String>, onScan: (String) -> Unit) {
private fun Tabs(accountId: String, errors: Flow<String>, onScan: (String) -> Unit) {
val pagerState = rememberPagerState { TITLES.size }
Column {
@@ -82,7 +82,7 @@ private fun Tabs(sessionId: String, errors: Flow<String>, onScan: (String) -> Un
modifier = Modifier.weight(1f)
) { page ->
when (TITLES[page]) {
R.string.view -> QrPage(sessionId)
R.string.view -> QrPage(accountId)
R.string.scan -> MaybeScanQrCode(errors, onScan = onScan)
}
}

View File

@@ -293,7 +293,7 @@ class DefaultConversationRepository @Inject constructor(
override suspend fun banAndDeleteAll(threadId: Long, recipient: Recipient): ResultOf<Unit> =
suspendCoroutine { continuation ->
// Note: This sessionId could be the blinded Id
// Note: This accountId could be the blinded Id
val accountID = recipient.address.toString()
val openGroup = lokiThreadDb.getOpenGroupChat(threadId)!!

View File

@@ -92,8 +92,8 @@ class ProfileManager(private val context: Context, private val configFactory: Co
override fun contactUpdatedInternal(contact: Contact): String? {
val contactConfig = configFactory.contacts ?: return null
if (contact.accountID == TextSecurePreferences.getLocalNumber(context)) return null
val sessionId = AccountId(contact.accountID)
if (sessionId.prefix != IdPrefix.STANDARD) return null // only internally store standard session IDs
val accountId = AccountId(contact.accountID)
if (accountId.prefix != IdPrefix.STANDARD) return null // only internally store standard account IDs
contactConfig.upsertContact(contact.accountID) {
this.name = contact.name.orEmpty()
this.nickname = contact.nickname.orEmpty()

View File

@@ -205,7 +205,7 @@ object ConfigurationMessageUtilities {
val admins = group.admins.map { it.serialize() to true }.toMap()
val members = group.members.filterNot { it.serialize() !in admins.keys }.map { it.serialize() to false }.toMap()
GroupInfo.LegacyGroupInfo(
sessionId = groupPublicKey,
accountId = groupPublicKey,
name = group.title,
members = admins + members,
priority = if (isPinned) ConfigBase.PRIORITY_PINNED else ConfigBase.PRIORITY_VISIBLE,

View File

@@ -566,7 +566,7 @@
<string name="activity_create_private_chat_scan_qr_code_explanation">Scannen Sie den QR-Code eines Benutzers, um eine Session zu starten. QR-Codes finden Sie, indem Sie in den Einstellungen auf das QR-Code-Symbol tippen.</string>
<string name="fragment_enter_public_key_edit_text_hint">Sitzungs-ID oder ONS-Name eingeben</string>
<string name="fragment_enter_public_key_explanation">Benutzer können ihre Account ID freigeben, indem sie in ihren Einstellungen auf \"Account ID freigeben\" tippen oder ihren QR-Code freigeben.</string>
<string name="fragment_enter_public_key_error_message">Bitte überprüfe die Session-ID oder den ONS-Namen und versuche es erneut.</string>
<string name="fragment_enter_public_key_error_message">Bitte überprüfe die Account-ID oder den ONS-Namen und versuche es erneut.</string>
<string name="fragment_scan_qr_code_camera_access_explanation">Session benötigt Kamerazugriff, um die QR-Codes scannen zu können.</string>
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Kamerazugriff gewähren</string>
<string name="activity_create_closed_group_title">Neue geschlossene Gruppe</string>
@@ -638,7 +638,7 @@
<string name="dialog_ui_mode_option_day">Tag</string>
<string name="dialog_ui_mode_option_night">Nacht</string>
<string name="dialog_ui_mode_option_system_default">Systemstandard</string>
<string name="activity_conversation_menu_copy_account_id">Session-ID kopieren</string>
<string name="activity_conversation_menu_copy_account_id">Account-ID kopieren</string>
<string name="attachment">Anhang</string>
<string name="attachment_type_voice_message">Sprachnachricht</string>
<string name="details">Details</string>

View File

@@ -566,7 +566,7 @@
<string name="activity_create_private_chat_scan_qr_code_explanation">Scannen Sie den QR-Code eines Benutzers, um eine Session zu starten. QR-Codes finden Sie, indem Sie in den Einstellungen auf das QR-Code-Symbol tippen.</string>
<string name="fragment_enter_public_key_edit_text_hint">Sitzungs-ID oder ONS-Name eingeben</string>
<string name="fragment_enter_public_key_explanation">Benutzer können ihre Account ID freigeben, indem sie in ihren Einstellungen auf \"Account ID freigeben\" tippen oder ihren QR-Code freigeben.</string>
<string name="fragment_enter_public_key_error_message">Bitte überprüfe die Session-ID oder den ONS-Namen und versuche es erneut.</string>
<string name="fragment_enter_public_key_error_message">Bitte überprüfe die Account-ID oder den ONS-Namen und versuche es erneut.</string>
<string name="fragment_scan_qr_code_camera_access_explanation">Session benötigt Kamerazugriff, um die QR-Codes scannen zu können.</string>
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Kamerazugriff gewähren</string>
<string name="activity_create_closed_group_title">Neue geschlossene Gruppe</string>
@@ -638,7 +638,7 @@
<string name="dialog_ui_mode_option_day">Tag</string>
<string name="dialog_ui_mode_option_night">Nacht</string>
<string name="dialog_ui_mode_option_system_default">Systemstandard</string>
<string name="activity_conversation_menu_copy_account_id">Session-ID kopieren</string>
<string name="activity_conversation_menu_copy_account_id">Account-ID kopieren</string>
<string name="attachment">Anhang</string>
<string name="attachment_type_voice_message">Sprachnachricht</string>
<string name="details">Details</string>

View File

@@ -551,7 +551,7 @@ nøkkelutvekslingsmelding.</string>
<string name="activity_home_delete_conversation_dialog_message">Er du sikker på at du vil slette denne samtalen?</string>
<string name="activity_home_conversation_deleted_message">Samtalen slettet</string>
<string name="view_seed_reminder_subtitle_1">Sikre kontoen din ved å lagre din gjenopprettingsfrase</string>
<string name="view_seed_reminder_subtitle_2">Trykk og hold inne de overflødige ordene for å hente gjenopprettingsfrasen din, og lagre den trygt å sikre din Session-ID.</string>
<string name="view_seed_reminder_subtitle_2">Trykk og hold inne de overflødige ordene for å hente gjenopprettingsfrasen din, og lagre den trygt å sikre din Account-ID.</string>
<string name="view_seed_reminder_subtitle_3">Pass på å lagre gjenopprettingsfrasen på et sikkert sted</string>
<string name="activity_path_title">Bane</string>
<string name="activity_path_explanation">Session skjuler din IP ved å laste ned meldingene dine gjennom flere Service Noder i Sessions desentraliserte nettverk. Disse er landene som koblingen din for øyeblikket blir kontaktet gjennom:</string>
@@ -565,9 +565,9 @@ nøkkelutvekslingsmelding.</string>
<string name="activity_create_private_chat_enter_account_id_tab_title">Skriv inn Account ID</string>
<string name="activity_create_private_chat_scan_qr_code_tab_title">Skann QR-kode</string>
<string name="activity_create_private_chat_scan_qr_code_explanation">Skann en brukers QR-kode for å starte en økt. QR-koder finnes ved å trykke på QR-koden i kontoinnstillingene.</string>
<string name="fragment_enter_public_key_edit_text_hint">Angi Session-ID eller ONS-navn</string>
<string name="fragment_enter_public_key_explanation">Brukere kan dele sin Session-ID ved å gå inn i sine kontoinnstillinger og trykke på \"Del Session-ID\", eller ved å dele sin QR-kode.</string>
<string name="fragment_enter_public_key_error_message">Vennligst sjekk Session-ID\'en eller ONS-navnet og prøv igjen.</string>
<string name="fragment_enter_public_key_edit_text_hint">Angi Account-ID eller ONS-navn</string>
<string name="fragment_enter_public_key_explanation">Brukere kan dele sin Account-ID ved å gå inn i sine kontoinnstillinger og trykke på \"Del Account-ID\", eller ved å dele sin QR-kode.</string>
<string name="fragment_enter_public_key_error_message">Vennligst sjekk Account-ID\'en eller ONS-navnet og prøv igjen.</string>
<string name="fragment_scan_qr_code_camera_access_explanation">Session trenger kameratilgang for å skanne QR-koder</string>
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Gi kameratilgang</string>
<string name="activity_create_closed_group_title">Ny lukket gruppe</string>
@@ -639,7 +639,7 @@ nøkkelutvekslingsmelding.</string>
<string name="dialog_ui_mode_option_day">Dag</string>
<string name="dialog_ui_mode_option_night">Natt</string>
<string name="dialog_ui_mode_option_system_default">Systemstandard</string>
<string name="activity_conversation_menu_copy_account_id">Kopier Session-ID</string>
<string name="activity_conversation_menu_copy_account_id">Kopier Account-ID</string>
<string name="attachment">Vedlegg</string>
<string name="attachment_type_voice_message">Talemelding</string>
<string name="details">Detaljer</string>

View File

@@ -551,7 +551,7 @@ nøkkelutvekslingsmelding.</string>
<string name="activity_home_delete_conversation_dialog_message">Er du sikker på at du vil slette denne samtalen?</string>
<string name="activity_home_conversation_deleted_message">Samtalen slettet</string>
<string name="view_seed_reminder_subtitle_1">Sikre kontoen din ved å lagre din gjenopprettingsfrase</string>
<string name="view_seed_reminder_subtitle_2">Trykk og hold inne de overflødige ordene for å hente gjenopprettingsfrasen din, og lagre den trygt å sikre din Session-ID.</string>
<string name="view_seed_reminder_subtitle_2">Trykk og hold inne de overflødige ordene for å hente gjenopprettingsfrasen din, og lagre den trygt å sikre din Account-ID.</string>
<string name="view_seed_reminder_subtitle_3">Pass på å lagre gjenopprettingsfrasen på et sikkert sted</string>
<string name="activity_path_title">Bane</string>
<string name="activity_path_explanation">Session skjuler din IP ved å laste ned meldingene dine gjennom flere Service Noder i Sessions desentraliserte nettverk. Disse er landene som koblingen din for øyeblikket blir kontaktet gjennom:</string>
@@ -565,9 +565,9 @@ nøkkelutvekslingsmelding.</string>
<string name="activity_create_private_chat_enter_account_id_tab_title">Skriv inn Account ID</string>
<string name="activity_create_private_chat_scan_qr_code_tab_title">Skann QR-kode</string>
<string name="activity_create_private_chat_scan_qr_code_explanation">Skann en brukers QR-kode for å starte en økt. QR-koder finnes ved å trykke på QR-koden i kontoinnstillingene.</string>
<string name="fragment_enter_public_key_edit_text_hint">Angi Session-ID eller ONS-navn</string>
<string name="fragment_enter_public_key_explanation">Brukere kan dele sin Session-ID ved å gå inn i sine kontoinnstillinger og trykke på \"Del Session-ID\", eller ved å dele sin QR-kode.</string>
<string name="fragment_enter_public_key_error_message">Vennligst sjekk Session-ID\'en eller ONS-navnet og prøv igjen.</string>
<string name="fragment_enter_public_key_edit_text_hint">Angi Account-ID eller ONS-navn</string>
<string name="fragment_enter_public_key_explanation">Brukere kan dele sin Account-ID ved å gå inn i sine kontoinnstillinger og trykke på \"Del Account-ID\", eller ved å dele sin QR-kode.</string>
<string name="fragment_enter_public_key_error_message">Vennligst sjekk Account-ID\'en eller ONS-navnet og prøv igjen.</string>
<string name="fragment_scan_qr_code_camera_access_explanation">Session trenger kameratilgang for å skanne QR-koder</string>
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Gi kameratilgang</string>
<string name="activity_create_closed_group_title">Ny lukket gruppe</string>
@@ -639,7 +639,7 @@ nøkkelutvekslingsmelding.</string>
<string name="dialog_ui_mode_option_day">Dag</string>
<string name="dialog_ui_mode_option_night">Natt</string>
<string name="dialog_ui_mode_option_system_default">Systemstandard</string>
<string name="activity_conversation_menu_copy_account_id">Kopier Session-ID</string>
<string name="activity_conversation_menu_copy_account_id">Kopier Account-ID</string>
<string name="attachment">Vedlegg</string>
<string name="attachment_type_voice_message">Talemelding</string>
<string name="details">Detaljer</string>

View File

@@ -567,7 +567,7 @@
<string name="activity_create_private_chat_scan_qr_code_tab_title">Scan QR-code</string>
<string name="activity_create_private_chat_scan_qr_code_explanation">Scan de QR-code van een gebruiker om een sessie te starten. QR-codes kunnen worden gevonden door op het QR-icoon in de accountinstellingen te tikken.</string>
<string name="fragment_enter_public_key_edit_text_hint">Voer uw Account ID of ONS naam in</string>
<string name="fragment_enter_public_key_explanation">Gebruikers kunnen hun Session-ID delen door naar hun accountinstellingen te gaan en op \"Deel Session-ID\" te tikken, of door hun QR-code te delen.</string>
<string name="fragment_enter_public_key_explanation">Gebruikers kunnen hun Account-ID delen door naar hun accountinstellingen te gaan en op \"Deel Account-ID\" te tikken, of door hun QR-code te delen.</string>
<string name="fragment_enter_public_key_error_message">Controleer de sessie-ID of ONS naam en probeer het opnieuw.</string>
<string name="fragment_scan_qr_code_camera_access_explanation">Sessie heeft cameratoegang nodig om QR-codes te scannen</string>
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Toegang tot camera verlenen</string>

View File

@@ -567,7 +567,7 @@
<string name="activity_create_private_chat_scan_qr_code_tab_title">Scan QR-code</string>
<string name="activity_create_private_chat_scan_qr_code_explanation">Scan de QR-code van een gebruiker om een sessie te starten. QR-codes kunnen worden gevonden door op het QR-icoon in de accountinstellingen te tikken.</string>
<string name="fragment_enter_public_key_edit_text_hint">Voer uw Account ID of ONS naam in</string>
<string name="fragment_enter_public_key_explanation">Gebruikers kunnen hun Session-ID delen door naar hun accountinstellingen te gaan en op \"Deel Session-ID\" te tikken, of door hun QR-code te delen.</string>
<string name="fragment_enter_public_key_explanation">Gebruikers kunnen hun Account-ID delen door naar hun accountinstellingen te gaan en op \"Deel Account-ID\" te tikken, of door hun QR-code te delen.</string>
<string name="fragment_enter_public_key_error_message">Controleer de sessie-ID of ONS naam en probeer het opnieuw.</string>
<string name="fragment_scan_qr_code_camera_access_explanation">Sessie heeft cameratoegang nodig om QR-codes te scannen</string>
<string name="fragment_scan_qr_code_grant_camera_access_button_title">Toegang tot camera verlenen</string>

View File

@@ -551,7 +551,7 @@ för nyckelutbyte!</string>
<string name="activity_home_delete_conversation_dialog_message">Är du säker på att du vill ta bort denna konversation?</string>
<string name="activity_home_conversation_deleted_message">Konversationen har raderats</string>
<string name="view_seed_reminder_subtitle_1">Säkra ditt konto genom att spara din återställningsfras</string>
<string name="view_seed_reminder_subtitle_2">Tryck på och håll ned de dolda orden för att avslöja din återställningsfras och lagra dem på ett säkert sätt för att säkra ditt Session-ID.</string>
<string name="view_seed_reminder_subtitle_2">Tryck på och håll ned de dolda orden för att avslöja din återställningsfras och lagra dem på ett säkert sätt för att säkra ditt Account-ID.</string>
<string name="view_seed_reminder_subtitle_3">Se till att spara din återställningsfras på en säker plats</string>
<string name="activity_path_title">Sökväg</string>
<string name="activity_path_explanation">Session döljer din IP-adress genom att dirigera dina meddelanden genom flera Tjänstnoder i Sessions decentraliserade nätverk. Detta är de länder som din anslutning för närvarande går igenom:</string>
@@ -639,7 +639,7 @@ för nyckelutbyte!</string>
<string name="dialog_ui_mode_option_day">Dag</string>
<string name="dialog_ui_mode_option_night">Natt</string>
<string name="dialog_ui_mode_option_system_default">Systemets inställning</string>
<string name="activity_conversation_menu_copy_account_id">Kopiera Session-ID</string>
<string name="activity_conversation_menu_copy_account_id">Kopiera Account-ID</string>
<string name="attachment">Bilaga</string>
<string name="attachment_type_voice_message">Röstmeddelande</string>
<string name="details">Detaljer</string>

View File

@@ -551,7 +551,7 @@ för nyckelutbyte!</string>
<string name="activity_home_delete_conversation_dialog_message">Är du säker på att du vill ta bort denna konversation?</string>
<string name="activity_home_conversation_deleted_message">Konversationen har raderats</string>
<string name="view_seed_reminder_subtitle_1">Säkra ditt konto genom att spara din återställningsfras</string>
<string name="view_seed_reminder_subtitle_2">Tryck på och håll ned de dolda orden för att avslöja din återställningsfras och lagra dem på ett säkert sätt för att säkra ditt Session-ID.</string>
<string name="view_seed_reminder_subtitle_2">Tryck på och håll ned de dolda orden för att avslöja din återställningsfras och lagra dem på ett säkert sätt för att säkra ditt Account-ID.</string>
<string name="view_seed_reminder_subtitle_3">Se till att spara din återställningsfras på en säker plats</string>
<string name="activity_path_title">Sökväg</string>
<string name="activity_path_explanation">Session döljer din IP-adress genom att dirigera dina meddelanden genom flera Tjänstnoder i Sessions decentraliserade nätverk. Detta är de länder som din anslutning för närvarande går igenom:</string>
@@ -639,7 +639,7 @@ för nyckelutbyte!</string>
<string name="dialog_ui_mode_option_day">Dag</string>
<string name="dialog_ui_mode_option_night">Natt</string>
<string name="dialog_ui_mode_option_system_default">Systemets inställning</string>
<string name="activity_conversation_menu_copy_account_id">Kopiera Session-ID</string>
<string name="activity_conversation_menu_copy_account_id">Kopiera Account-ID</string>
<string name="attachment">Bilaga</string>
<string name="attachment_type_voice_message">Röstmeddelande</string>
<string name="details">Detaljer</string>