Compare commits

...

28 Commits

Author SHA1 Message Date
Stanislav Dmitrenko
23ca901f14 ios: mailto url open 2023-05-04 07:03:25 -07:00
Evgeny Poberezkin
af59178318 core: 5.1.0.0 2023-05-04 12:45:57 +01:00
Stanislav Dmitrenko
5149623b57 ios: prevent crash when no email account was setup (#2375) 2023-05-04 11:13:53 +01:00
spaced4ndy
205c74b5d8 core: make use of covering indexes when reading chats (#2372) 2023-05-03 20:26:04 +04:00
Evgeny Poberezkin
5116bfa79c cli: option to disable notifications, closes #2340 (#2373) 2023-05-03 16:40:11 +01:00
Stanislav Dmitrenko
69767126aa mobile: disable ability to write text in text view when sending a message and prevent saving message that is in progress as draft (#2371)
* android: prevent saving message that is in progress as draft

* android: disable ability to write text in text view when sending a message

* ios: prevent saving message that is in progress as draft

* ios: disable ability to write text in text view when sending a message

* do not show welcome button when not needed
2023-05-03 13:57:10 +01:00
spaced4ndy
5af389ae3f mobile: change links from repo to website (#2370) 2023-05-03 15:01:45 +04:00
Stanislav Dmitrenko
f711f4d8a8 android: socks proxy port (#2367)
* android: socks proxy port

* ability to specify socks host and port before enabling it

* comment
2023-05-03 11:23:23 +01:00
Stanislav Dmitrenko
8b80efd537 android: contact address UX (#2363)
* android: contact address UX

* unneeded block

* review changes
2023-05-03 12:42:43 +04:00
spaced4ndy
7b83450a9c ios: AddGroupMembersView fixes (#2369) 2023-05-03 12:17:39 +04:00
spaced4ndy
e3011a1cb0 core: disable creation of decryption errors chat items (#2365) 2023-05-02 19:38:58 +04:00
Stanislav Dmitrenko
7ff8dcfb78 android: floating button background (#2366) 2023-05-02 16:38:20 +01:00
spaced4ndy
551ed202be ios: create address during onboarding (#2362)
* ios: create address during onboarding

* contact picker

* email wip

* send email w/t leaving app

* fomatting

* layout, texts

* remove contact picker, add email button to address page

* refactor

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-05-01 20:36:52 +04:00
Evgeny Poberezkin
6f11913359 core: fix CIStatus parser (#2361) 2023-05-01 11:33:30 +01:00
Stanislav Dmitrenko
d91a78da7d android: fixed background on some screens (#2360)
* android: fixed background on some screens

* background color and alert title color

* Revert "android: export all theme colors (#2348)"

This reverts commit 315d830357.

* small changes in logic

* unused color

* colors of background
2023-05-01 10:38:59 +01:00
M Sarmad Qadeer
02fdd058ec website: add theme switch for code snippets (#2359) 2023-05-01 09:44:15 +01:00
spaced4ndy
08148afac7 Merge pull request #2336 from simplex-chat/contact-address-ux
core, mobile: contact address ux
2023-05-01 11:21:53 +04:00
Evgeny Poberezkin
f037ffe107 core: prevent failure loading chat on invalid item content JSON (#2349)
* core: prevent failure loading chat on invalid item content JSON

* corrections

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* platform independent parsing

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-05-01 08:18:04 +01:00
M Sarmad Qadeer
fa6ba3110b website: fix Chinese in dropdown (#2358) 2023-05-01 07:38:59 +01:00
Evgeny Poberezkin
6f82ddc032 website: fix tailwindcss version 2023-05-01 07:13:29 +01:00
Evgeny Poberezkin
ee3267388f website: fix build 2023-04-30 23:22:35 +01:00
M Sarmad Qadeer
f97a1fcedf website: add docs to website (#2080)
* website: add fontmatter & improve image URLs where necessary

* website: add docs to website

* website: add prismjs for code highlighting

* website: change npm install position in web.sh

* website: fix an image URL in lang/cs/README.md

* website: improve image paths in lang/cs/translations.md

* website: add responsiveness & improve stylings of docs

* website: add dir to navbar in blog & docs

* website: remove scroll in mobile dropdown menu

* website: remove rfcs & add guide docs to website

* website: remove file renaming script from web.sh

* website: add menu to docs in nav

* website: add hash list & add scroll to headers

* website: customize docs frontmatter through JS

* website: remove supported_languages.json

* website: move merge_translations.js to JS folder

* website: add the following changes to docs
- add frontmatter to new doc merged from master
- add ignoreForWeb property to frontmatter of README.md docs

* website: remove package-lock.json from .gitignore

* website: add package-lock.json from .gitignore

* website: add no docs message to docs dropdown

* website: improve the sidebar of docs

* website: add revision date to docs

* website: add script to add version to docs frontmatter

* website: add layout to display message in docs if its version is old

* website: improve nav responsiveness

* website: remove frontmatter form main README & rfcs

* website: remove rfcs from website folder

* website: add ignore condition for rfcs in .eleventy

* website: remove frontmatter from lang README docs

* website: remove README from website's lang docs

* website: add guides menu in nav

* website: following changes
- add docs_dropdown.json
- extend reference menu in nav
- remove docs menu from nav

* website: fix in docs sidebar

* website: revert main docs README.md files

* website: revert main docs README.md files

* website: move scripts out of js that are for build

* website: remove displayAt form guide docs

* website: create a docs_sidebar.json & shift to that approach

* update navigation

* website: set navbar

* website: add icons to external links

* website: change the approach for docs sidebar creation

* website: update docs template

* website: add some strings to en.json and map them accordingly

* remove icon

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-04-30 22:31:23 +01:00
spaced4ndy
199835b671 ios: allow all group members to view welcome message (#2347)
* ios: allow all group members to view welcome message

* remove diff

* layout

* ignore taps on preview

* remove newline

* show/hide keyboard

* fix button flickering

* remove space

* remove unused function

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-04-28 20:34:24 +04:00
spaced4ndy
ce2225d355 ios: align 1-time link design with new address design (#2337)
* ios: align 1-time link design with new address design

* update text

* layout

* bigger font, icon

* padding

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-04-28 14:11:32 +04:00
Evgeny Poberezkin
b4f1f94bcc Merge branch 'master' into contact-address-ux 2023-04-28 10:41:49 +01:00
spaced4ndy
90cee6b802 ios: scroll address view on keyboard, translations (#2344)
* ios: scroll address view on keyboard, translations

* fix typo

* revert text

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-04-28 12:21:23 +04:00
spaced4ndy
2a883bb958 core: add /profile_address command to help (#2345) 2023-04-28 12:14:07 +04:00
spaced4ndy
0b57cc08a7 core, ios: include contact addresses in profiles (#2328)
* core: include contact links in profiles

* add connection request link to contact and group profiles

* set group link on update, view, api

* core: include contact addresses in profiles

* remove id from UserContactLink

* schema, fix test

* remove address from profile when deleting link, tests

* remove diff

* remove diff

* fix

* ios wip

* learn more, confirm save, reset on delete

* re-use in create link view

* remove obsolete files

* color

* revert scheme

* learn more with create

* layout

* layout

* progress indicator

* delete text

* save on change, layout

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-04-27 17:19:21 +04:00
194 changed files with 4989 additions and 1666 deletions

2
.gitignore vendored
View File

@@ -49,8 +49,8 @@ logs/
# for website
website/node_modules/
website/src/blog/
website/src/docs/
website/translations.json
website/src/_data/supported_languages.json
website/src/img/images/
website/src/images/
# Generated files

View File

@@ -83,14 +83,16 @@ class MainActivity: FragmentActivity() {
}
setContent {
SimpleXTheme {
MainPage(
m,
userAuthorized,
laFailed,
::runAuthenticate,
::setPerformLA,
showLANotice = { showLANotice(m.controller.appPrefs.laNoticeShown, this) }
)
Surface(color = MaterialTheme.colors.background) {
MainPage(
m,
userAuthorized,
laFailed,
::runAuthenticate,
::setPerformLA,
showLANotice = { showLANotice(m.controller.appPrefs.laNoticeShown, this) }
)
}
}
}
SimplexApp.context.schedulePeriodicServiceRestartWorker()

View File

@@ -461,6 +461,8 @@ data class User(
val showNotifications: Boolean = activeUser || showNtfs
val addressShared: Boolean = profile.contactLink != null
companion object {
val sampleData = User(
userId = 1,
@@ -734,6 +736,7 @@ data class Contact(
override val displayName get() = localAlias.ifEmpty { profile.displayName }
override val fullName get() = profile.fullName
override val image get() = profile.image
val contactLink: String? = profile.contactLink
override val localAlias get() = profile.localAlias
val verified get() = activeConn.connectionCode != null
@@ -814,6 +817,7 @@ data class Profile(
override val fullName: String,
override val image: String? = null,
override val localAlias : String = "",
val contactLink: String? = null,
val preferences: ChatPreferences? = null
): NamedChat {
val profileViewName: String
@@ -821,7 +825,7 @@ data class Profile(
return if (fullName == "" || displayName == fullName) displayName else "$displayName ($fullName)"
}
fun toLocalProfile(profileId: Long): LocalProfile = LocalProfile(profileId, displayName, fullName, image, localAlias, preferences)
fun toLocalProfile(profileId: Long): LocalProfile = LocalProfile(profileId, displayName, fullName, image, localAlias, contactLink, preferences)
companion object {
val sampleData = Profile(
@@ -832,17 +836,18 @@ data class Profile(
}
@Serializable
class LocalProfile(
data class LocalProfile(
val profileId: Long,
override val displayName: String,
override val fullName: String,
override val image: String? = null,
override val localAlias: String,
val contactLink: String? = null,
val preferences: ChatPreferences? = null
): NamedChat {
val profileViewName: String = localAlias.ifEmpty { if (fullName == "" || displayName == fullName) displayName else "$displayName ($fullName)" }
fun toProfile(): Profile = Profile(displayName, fullName, image, localAlias, preferences)
fun toProfile(): Profile = Profile(displayName, fullName, image, localAlias, contactLink, preferences)
companion object {
val sampleData = LocalProfile(
@@ -952,6 +957,7 @@ data class GroupMember (
val displayName: String get() = memberProfile.localAlias.ifEmpty { memberProfile.displayName }
val fullName: String get() = memberProfile.fullName
val image: String? get() = memberProfile.image
val contactLink: String? = memberProfile.contactLink
val verified get() = activeConn?.connectionCode != null
val chatViewName: String

View File

@@ -855,6 +855,15 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
return null
}
suspend fun apiSetProfileAddress(on: Boolean): User? {
val userId = try { currentUserId("apiSetProfileAddress") } catch (e: Exception) { return null }
return when (val r = sendCmd(CC.ApiSetProfileAddress(userId, on))) {
is CR.UserProfileNoChange -> null
is CR.UserProfileUpdated -> r.user
else -> throw Exception("failed to set profile address: ${r.responseType} ${r.details}")
}
}
suspend fun apiSetContactPrefs(contactId: Long, prefs: ChatPreferences): Contact? {
val r = sendCmd(CC.ApiSetContactPrefs(contactId, prefs))
if (r is CR.ContactPrefsUpdated) return r.toContact
@@ -890,12 +899,12 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
}
}
suspend fun apiDeleteUserAddress(): Boolean {
val userId = kotlin.runCatching { currentUserId("apiDeleteUserAddress") }.getOrElse { return false }
suspend fun apiDeleteUserAddress(): User? {
val userId = try { currentUserId("apiDeleteUserAddress") } catch (e: Exception) { return null }
val r = sendCmd(CC.ApiDeleteMyAddress(userId))
if (r is CR.UserContactLinkDeleted) return true
if (r is CR.UserContactLinkDeleted) return r.user
Log.e(TAG, "apiDeleteUserAddress bad response: ${r.responseType} ${r.details}")
return false
return null
}
private suspend fun apiGetUserAddress(): UserContactLinkRec? {
@@ -1803,6 +1812,9 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
)
}
/**
* [AppPreferences.networkProxyHostPort] is not changed here, use appPrefs to set it
* */
fun setNetCfg(cfg: NetCfg) {
appPrefs.networkUseSocksProxy.set(cfg.useSocksProxy)
appPrefs.networkHostMode.set(cfg.hostMode.name)
@@ -1905,6 +1917,7 @@ sealed class CC {
class ApiCreateMyAddress(val userId: Long): CC()
class ApiDeleteMyAddress(val userId: Long): CC()
class ApiShowMyAddress(val userId: Long): CC()
class ApiSetProfileAddress(val userId: Long, val on: Boolean): CC()
class ApiAddressAutoAccept(val userId: Long, val autoAccept: AutoAccept?): CC()
class ApiSendCallInvitation(val contact: Contact, val callType: CallType): CC()
class ApiRejectCall(val contact: Contact): CC()
@@ -1989,6 +2002,7 @@ sealed class CC {
is ApiCreateMyAddress -> "/_address $userId"
is ApiDeleteMyAddress -> "/_delete_address $userId"
is ApiShowMyAddress -> "/_show_address $userId"
is ApiSetProfileAddress -> "/_profile_address $userId ${onOff(on)}"
is ApiAddressAutoAccept -> "/_auto_accept $userId ${AutoAccept.cmdString(autoAccept)}"
is ApiAcceptContact -> "/_accept $contactReqId"
is ApiRejectContact -> "/_reject $contactReqId"
@@ -2074,6 +2088,7 @@ sealed class CC {
is ApiCreateMyAddress -> "apiCreateMyAddress"
is ApiDeleteMyAddress -> "apiDeleteMyAddress"
is ApiShowMyAddress -> "apiShowMyAddress"
is ApiSetProfileAddress -> "apiSetProfileAddress"
is ApiAddressAutoAccept -> "apiAddressAutoAccept"
is ApiAcceptContact -> "apiAcceptContact"
is ApiRejectContact -> "apiRejectContact"
@@ -2343,6 +2358,15 @@ data class NetCfg(
val useSocksProxy: Boolean get() = socksProxy != null
val enableKeepAlive: Boolean get() = tcpKeepAlive != null
fun withHostPort(hostPort: String?, default: String? = ":9050"): NetCfg {
val socksProxy = if (hostPort?.startsWith("localhost:") == true) {
hostPort.removePrefix("localhost")
} else {
hostPort ?: default
}
return copy(socksProxy = socksProxy)
}
companion object {
val defaults: NetCfg =
NetCfg(

View File

@@ -21,7 +21,6 @@ val ToolbarDark = Color(80, 80, 80, 12)
val SettingsSecondaryLight = Color(200, 196, 195, 90)
val GroupDark = Color(80, 80, 80, 60)
val IncomingCallLight = Color(239, 237, 236, 255)
val IncomingCallDark = Color(34, 30, 29, 255)
val WarningOrange = Color(255, 127, 0, 255)
val WarningYellow = Color(255, 192, 0, 255)
val FileLight = Color(183, 190, 199, 255)

View File

@@ -16,6 +16,7 @@ import chat.simplex.app.views.helpers.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import okhttp3.internal.toHexString
enum class DefaultTheme {
SYSTEM, LIGHT, DARK, SIMPLEX;
@@ -128,11 +129,29 @@ data class ThemeColors(
receivedMessage = receivedMessage?.colorFromReadableHex() ?: baseColors.receivedMessage,
)
}
fun withFilledColors(base: DefaultTheme): ThemeColors {
val c = toColors(base)
val ac = toAppColors(base)
return ThemeColors(
primary = c.primary.toReadableHex(),
primaryVariant = c.primaryVariant.toReadableHex(),
secondary = c.secondary.toReadableHex(),
secondaryVariant = c.secondaryVariant.toReadableHex(),
background = c.background.toReadableHex(),
surface = c.surface.toReadableHex(),
title = ac.title.toReadableHex(),
sentMessage = ac.sentMessage.toReadableHex(),
receivedMessage = ac.receivedMessage.toReadableHex()
)
}
}
private fun String.colorFromReadableHex(): Color =
Color(this.replace("#", "").toLongOrNull(16) ?: Color.White.toArgb().toLong())
private fun Color.toReadableHex(): String = "#" + toArgb().toHexString()
@Serializable
data class ThemeOverrides (
val base: DefaultTheme,
@@ -153,9 +172,6 @@ data class ThemeOverrides (
}
}
@Serializable
data class ThemeData (val colors: ThemeColors)
fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, shape: Shape = RectangleShape): Modifier {
return if (baseTheme == DefaultTheme.SIMPLEX) {
this.background(brush = Brush.linearGradient(

View File

@@ -44,19 +44,16 @@ object ThemeManager {
return ActiveTheme(themeName, baseTheme.first, theme.colors.toColors(theme.base), theme.colors.toAppColors(theme.base))
}
fun currentThemeData(darkForSystemTheme: Boolean): ThemeData {
val t = currentColors(darkForSystemTheme)
return ThemeData(colors = ThemeColors(
primary = t.colors.primary.toReadableHex(),
primaryVariant = t.colors.primaryVariant.toReadableHex(),
secondary = t.colors.secondary.toReadableHex(),
secondaryVariant = t.colors.secondaryVariant.toReadableHex(),
background = t.colors.background.toReadableHex(),
surface = t.colors.surface.toReadableHex(),
title = t.appColors.title.toReadableHex(),
sentMessage = t.appColors.sentMessage.toReadableHex(),
receivedMessage = t.appColors.receivedMessage.toReadableHex()
))
fun currentThemeOverridesForExport(darkForSystemTheme: Boolean): ThemeOverrides {
val themeName = appPrefs.currentTheme.get()!!
val nonSystemThemeName = if (themeName != DefaultTheme.SYSTEM.name) {
themeName
} else {
if (darkForSystemTheme) appPrefs.systemDarkTheme.get()!! else DefaultTheme.LIGHT.name
}
val overrides = appPrefs.themeOverrides.get().toMutableMap()
val nonFilledTheme = overrides[nonSystemThemeName] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors())
return nonFilledTheme.copy(colors = nonFilledTheme.colors.withFilledColors(CurrentColors.value.base))
}
// colors, default theme enum, localized name of theme
@@ -128,11 +125,12 @@ object ThemeManager {
CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight)
}
fun saveAndApplyThemeData(name: String, theme: ThemeData, darkForSystemTheme: Boolean) {
fun saveAndApplyThemeOverrides(theme: ThemeOverrides, darkForSystemTheme: Boolean) {
val overrides = appPrefs.themeOverrides.get().toMutableMap()
val prevValue = overrides[name] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors())
overrides[name] = prevValue.copy(colors = theme.colors)
val prevValue = overrides[theme.base.name] ?: ThemeOverrides(base = CurrentColors.value.base, colors = ThemeColors())
overrides[theme.base.name] = prevValue.copy(colors = theme.colors)
appPrefs.themeOverrides.set(overrides)
appPrefs.currentTheme.set(theme.base.name)
CurrentColors.value = currentColors(!CurrentColors.value.colors.isLight)
}

View File

@@ -99,8 +99,8 @@ fun TerminalLayout(
Surface(
modifier = Modifier
.padding(contentPadding)
.fillMaxWidth()
.themedBackground()
.fillMaxWidth(),
color = MaterialTheme.colors.background
) {
TerminalLog(terminalItems)
}

View File

@@ -44,77 +44,75 @@ fun CreateProfilePanel(chatModel: ChatModel, close: () -> Unit) {
val fullName = rememberSaveable { mutableStateOf("") }
val focusRequester = remember { FocusRequester() }
Surface(Modifier.background(MaterialTheme.colors.onBackground)) {
Column(
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())
) {
/*CloseSheetBar(close = {
if (chatModel.users.isEmpty()) {
chatModel.onboardingStage.value = OnboardingStage.Step1_SimpleXInfo
} else {
close()
}
})*/
Column(Modifier.padding(horizontal = DEFAULT_PADDING * 1f)) {
AppBarTitle(stringResource(R.string.create_profile))
ReadableText(R.string.your_profile_is_stored_on_your_device, TextAlign.Center, padding = PaddingValues())
ReadableText(R.string.profile_is_only_shared_with_your_contacts, TextAlign.Center)
Spacer(Modifier.height(DEFAULT_PADDING * 1.5f))
Row(Modifier.padding(bottom = DEFAULT_PADDING_HALF).fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Text(
stringResource(R.string.display_name),
fontSize = 16.sp
)
if (!isValidDisplayName(displayName.value)) {
Text(
stringResource(R.string.no_spaces),
fontSize = 16.sp,
color = Color.Red
)
}
}
ProfileNameField(displayName, "", ::isValidDisplayName, focusRequester)
Spacer(Modifier.height(DEFAULT_PADDING))
Column(
modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())
) {
/*CloseSheetBar(close = {
if (chatModel.users.isEmpty()) {
chatModel.onboardingStage.value = OnboardingStage.Step1_SimpleXInfo
} else {
close()
}
})*/
Column(Modifier.padding(horizontal = DEFAULT_PADDING * 1f)) {
AppBarTitle(stringResource(R.string.create_profile))
ReadableText(R.string.your_profile_is_stored_on_your_device, TextAlign.Center, padding = PaddingValues())
ReadableText(R.string.profile_is_only_shared_with_your_contacts, TextAlign.Center)
Spacer(Modifier.height(DEFAULT_PADDING * 1.5f))
Row(Modifier.padding(bottom = DEFAULT_PADDING_HALF).fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Text(
stringResource(R.string.full_name_optional__prompt),
fontSize = 16.sp,
modifier = Modifier.padding(bottom = DEFAULT_PADDING_HALF)
stringResource(R.string.display_name),
fontSize = 16.sp
)
ProfileNameField(fullName, "", ::isValidDisplayName)
}
Spacer(Modifier.fillMaxHeight().weight(1f))
Row {
if (chatModel.users.isEmpty()) {
SimpleButtonDecorated(
text = stringResource(R.string.about_simplex),
icon = painterResource(R.drawable.ic_arrow_back_ios_new),
textDecoration = TextDecoration.None,
fontWeight = FontWeight.Medium
) { chatModel.onboardingStage.value = OnboardingStage.Step1_SimpleXInfo }
}
Spacer(Modifier.fillMaxWidth().weight(1f))
val enabled = displayName.value.isNotEmpty() && isValidDisplayName(displayName.value)
val createModifier: Modifier
val createColor: Color
if (enabled) {
createModifier = Modifier.clickable { createProfile(chatModel, displayName.value, fullName.value, close) }.padding(8.dp)
createColor = MaterialTheme.colors.primary
} else {
createModifier = Modifier.padding(8.dp)
createColor = MaterialTheme.colors.secondary
}
Surface(shape = RoundedCornerShape(20.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = createModifier) {
Text(stringResource(R.string.create_profile_button), style = MaterialTheme.typography.caption, color = createColor, fontWeight = FontWeight.Medium)
Icon(painterResource(R.drawable.ic_arrow_forward_ios), stringResource(R.string.create_profile_button), tint = createColor)
}
if (!isValidDisplayName(displayName.value)) {
Text(
stringResource(R.string.no_spaces),
fontSize = 16.sp,
color = Color.Red
)
}
}
ProfileNameField(displayName, "", ::isValidDisplayName, focusRequester)
Spacer(Modifier.height(DEFAULT_PADDING))
Text(
stringResource(R.string.full_name_optional__prompt),
fontSize = 16.sp,
modifier = Modifier.padding(bottom = DEFAULT_PADDING_HALF)
)
ProfileNameField(fullName, "", ::isValidDisplayName)
}
Spacer(Modifier.fillMaxHeight().weight(1f))
Row {
if (chatModel.users.isEmpty()) {
SimpleButtonDecorated(
text = stringResource(R.string.about_simplex),
icon = painterResource(R.drawable.ic_arrow_back_ios_new),
textDecoration = TextDecoration.None,
fontWeight = FontWeight.Medium
) { chatModel.onboardingStage.value = OnboardingStage.Step1_SimpleXInfo }
}
Spacer(Modifier.fillMaxWidth().weight(1f))
val enabled = displayName.value.isNotEmpty() && isValidDisplayName(displayName.value)
val createModifier: Modifier
val createColor: Color
if (enabled) {
createModifier = Modifier.clickable { createProfile(chatModel, displayName.value, fullName.value, close) }.padding(8.dp)
createColor = MaterialTheme.colors.primary
} else {
createModifier = Modifier.padding(8.dp)
createColor = MaterialTheme.colors.secondary
}
Surface(shape = RoundedCornerShape(20.dp), color = Color.Transparent) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = createModifier) {
Text(stringResource(R.string.create_profile_button), style = MaterialTheme.typography.caption, color = createColor, fontWeight = FontWeight.Medium)
Icon(painterResource(R.drawable.ic_arrow_forward_ios), stringResource(R.string.create_profile_button), tint = createColor)
}
}
}
LaunchedEffect(Unit) {
delay(300)
focusRequester.requestFocus()
}
LaunchedEffect(Unit) {
delay(300)
focusRequester.requestFocus()
}
}
}

View File

@@ -97,8 +97,9 @@ fun IncomingCallActivityView(m: ChatModel) {
SimpleXTheme {
Surface(
Modifier
.themedBackground()
.fillMaxSize()) {
.fillMaxSize(),
color = MaterialTheme.colors.background
) {
if (showCallView) {
Box {
ActiveCallView(m)
@@ -226,8 +227,9 @@ fun PreviewIncomingCallLockScreenAlert() {
SimpleXTheme(true) {
Surface(
Modifier
.themedBackground()
.fillMaxSize()) {
.fillMaxSize(),
color = MaterialTheme.colors.background
) {
IncomingCallLockScreenAlertLayout(
invitation = RcvCallInvitation(
user = User.sampleData,

View File

@@ -50,13 +50,13 @@ fun IncomingCallAlertLayout(
ignoreCall: () -> Unit,
acceptCall: () -> Unit
) {
val color = if (isInDarkTheme()) IncomingCallDark else IncomingCallLight
val color = if (isInDarkTheme()) MaterialTheme.colors.surface else IncomingCallLight
Column(Modifier.fillMaxWidth().background(color).padding(top = DEFAULT_PADDING, bottom = DEFAULT_PADDING, start = DEFAULT_PADDING, end = 8.dp)) {
IncomingCallInfo(invitation, chatModel)
Spacer(Modifier.height(8.dp))
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween) {
Row(Modifier.fillMaxWidth().weight(1f), verticalAlignment = Alignment.CenterVertically) {
ProfilePreview(profileOf = invitation.contact, size = 64.dp, color = Color.White)
ProfilePreview(profileOf = invitation.contact, size = 64.dp)
}
Row(verticalAlignment = Alignment.CenterVertically) {
CallButton(stringResource(R.string.reject), painterResource(R.drawable.ic_call_end_filled), Color.Red, rejectCall)
@@ -78,7 +78,7 @@ fun IncomingCallInfo(invitation: RcvCallInvitation, chatModel: ChatModel) {
if (invitation.callType.media == CallMediaType.Video) CallIcon(painterResource(R.drawable.ic_videocam_filled), stringResource(R.string.icon_descr_video_call))
else CallIcon(painterResource(R.drawable.ic_call_filled), stringResource(R.string.icon_descr_audio_call))
Spacer(Modifier.width(4.dp))
Text(invitation.callTypeText)
Text(invitation.callTypeText, color = MaterialTheme.colors.onBackground)
}
}

View File

@@ -5,8 +5,11 @@ import InfoRowEllipsis
import SectionBottomSpacer
import SectionDividerSpaced
import SectionItemView
import SectionItemViewWithIcon
import SectionSpacer
import SectionTextFooter
import SectionView
import TextIconSpaced
import android.widget.Toast
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.*
@@ -18,8 +21,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.*
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
@@ -34,6 +36,7 @@ import chat.simplex.app.SimplexApp
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.newchat.QRCode
import chat.simplex.app.views.usersettings.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
@@ -195,6 +198,15 @@ fun ChatInfoLayout(
}
SectionDividerSpaced()
if (contact.contactLink != null) {
val context = LocalContext.current
SectionView(stringResource(R.string.address_section_title).uppercase()) {
QRCode(contact.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f))
ShareAddressButton { shareText(context, contact.contactLink) }
SectionTextFooter(stringResource(R.string.you_can_share_this_address_with_your_contacts).format(contact.displayName))
}
SectionDividerSpaced()
}
SectionView(title = stringResource(R.string.conn_stats_section_title_servers)) {
SwitchAddressButton(switchContactAddress)
@@ -416,6 +428,17 @@ private fun DeleteContactButton(onClick: () -> Unit) {
)
}
@Composable
fun ShareAddressButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(R.drawable.ic_share_filled),
stringResource(R.string.share_address),
onClick,
iconColor = MaterialTheme.colors.primary,
textColor = MaterialTheme.colors.primary,
)
}
private fun setContactAlias(contactApiId: Long, localAlias: String, chatModel: ChatModel) = withApi {
chatModel.controller.apiSetContactAlias(contactApiId, localAlias)?.let {
chatModel.updateContact(it)

View File

@@ -326,7 +326,6 @@ fun ChatLayout(
Box(
Modifier
.fillMaxWidth()
.themedBackground()
) {
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
ModalBottomSheetLayout(
@@ -855,6 +854,7 @@ private fun TopEndFloatingButton(
FloatingActionButton(
{}, // no action here
modifier.size(48.dp),
backgroundColor = MaterialTheme.colors.secondaryVariant,
elevation = FloatingActionButtonDefaults.elevation(0.dp, 0.dp),
interactionSource = interactionSource,
) {
@@ -881,7 +881,8 @@ private fun bottomEndFloatingButton(
FloatingActionButton(
onClick = onClickCounter,
elevation = FloatingActionButtonDefaults.elevation(0.dp, 0.dp, 0.dp, 0.dp),
modifier = Modifier.size(48.dp)
modifier = Modifier.size(48.dp),
backgroundColor = MaterialTheme.colors.secondaryVariant,
) {
Text(
unreadCountStr(unreadCount),
@@ -896,7 +897,8 @@ private fun bottomEndFloatingButton(
FloatingActionButton(
onClick = onClickArrowDown,
elevation = FloatingActionButtonDefaults.elevation(0.dp, 0.dp, 0.dp, 0.dp),
modifier = Modifier.size(48.dp)
modifier = Modifier.size(48.dp),
backgroundColor = MaterialTheme.colors.secondaryVariant,
) {
Icon(
painter = painterResource(R.drawable.ic_keyboard_arrow_down),

View File

@@ -118,7 +118,7 @@ data class ComposeState(
val attachmentDisabled: Boolean
get() {
if (editing || liveMessage != null) return true
if (editing || liveMessage != null || inProgress) return true
return when (preview) {
ComposePreview.NoPreview -> false
is ComposePreview.CLinkPreview -> false
@@ -623,23 +623,27 @@ fun ComposeView(
fun previewView() {
when (val preview = composeState.value.preview) {
ComposePreview.NoPreview -> {}
is ComposePreview.CLinkPreview -> ComposeLinkView(preview.linkPreview, ::cancelLinkPreview)
is ComposePreview.CLinkPreview -> ComposeLinkView(
preview.linkPreview,
::cancelLinkPreview,
cancelEnabled = !composeState.value.inProgress
)
is ComposePreview.MediaPreview -> ComposeImageView(
preview,
::cancelImages,
cancelEnabled = !composeState.value.editing
cancelEnabled = !composeState.value.editing && !composeState.value.inProgress
)
is ComposePreview.VoicePreview -> ComposeVoiceView(
preview.voice,
preview.durationMs,
preview.finished,
cancelEnabled = !composeState.value.editing,
cancelEnabled = !composeState.value.editing && !composeState.value.inProgress,
::cancelVoice
)
is ComposePreview.FilePreview -> ComposeFileView(
preview.fileName,
::cancelFile,
cancelEnabled = !composeState.value.editing
cancelEnabled = !composeState.value.editing && !composeState.value.inProgress
)
}
}
@@ -657,6 +661,14 @@ fun ComposeView(
}
}
// In case a user sent something, state is in progress, the user rotates a screen to different orientation.
// Without clearing the state the user will be unable to send anything until re-enters ChatView
LaunchedEffect(Unit) {
if (composeState.value.inProgress) {
clearState()
}
}
LaunchedEffect(chatModel.sharedContent.value) {
// Important. If it's null, don't do anything, chat is not closed yet but will be after a moment
if (chatModel.chatId.value == null) return@LaunchedEffect
@@ -744,6 +756,8 @@ fun ComposeView(
resetLinkPreview()
clearCurrentDraft()
deleteUnusedFiles()
} else if (composeState.value.inProgress) {
clearCurrentDraft()
} else if (!composeState.value.empty) {
if (cs.preview is ComposePreview.VoicePreview && !cs.preview.finished) {
composeState.value = cs.copy(preview = cs.preview.copy(finished = true))

View File

@@ -79,7 +79,7 @@ fun SendMsgView(
val showDeleteTextButton = rememberSaveable { mutableStateOf(false) }
NativeKeyboard(composeState, textStyle, showDeleteTextButton, userIsObserver, onMessageChange)
// Disable clicks on text field
if (cs.preview is ComposePreview.VoicePreview || !userCanSend) {
if (cs.preview is ComposePreview.VoicePreview || !userCanSend || cs.inProgress) {
Box(Modifier
.matchParentSize()
.clickable(enabled = !userCanSend, indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = {
@@ -250,14 +250,20 @@ private fun NativeKeyboard(
Log.e(chat.simplex.app.TAG, e.stackTraceToString())
}
}
editText.doOnTextChanged { text, _, _, _ -> onMessageChange(text.toString()) }
editText.doOnTextChanged { text, _, _, _ ->
if (!composeState.value.inProgress) {
onMessageChange(text.toString())
} else if (text.toString() != composeState.value.message) {
editText.setText(composeState.value.message)
}
}
editText.doAfterTextChanged { text -> if (composeState.value.preview is ComposePreview.VoicePreview && text.toString() != "") editText.setText("") }
editText
}) {
it.setTextColor(textColor.toArgb())
it.textSize = textStyle.value.fontSize.value
DrawableCompat.setTint(it.background, tintColor.toArgb())
it.isFocusable = composeState.value.preview !is ComposePreview.VoicePreview
it.isFocusable = composeState.value.preview !is ComposePreview.VoicePreview && !cs.inProgress
it.isFocusableInTouchMode = it.isFocusable
if (cs.message != it.text.toString()) {
it.setText(cs.message)
@@ -270,7 +276,7 @@ private fun NativeKeyboard(
imm.showSoftInput(it, InputMethodManager.SHOW_IMPLICIT)
showKeyboard = false
}
showDeleteTextButton.value = it.lineCount >= 4
showDeleteTextButton.value = it.lineCount >= 4 && !cs.inProgress
}
if (composeState.value.preview is ComposePreview.VoicePreview) {
ComposeOverlay(R.string.voice_message_send_text, textStyle, padding)

View File

@@ -175,6 +175,8 @@ fun GroupChatInfoLayout(
SectionView {
if (groupInfo.canEdit) {
EditGroupProfileButton(editGroupProfile)
}
if (groupInfo.groupProfile.description != null || groupInfo.canEdit) {
AddOrEditWelcomeMessage(groupInfo.groupProfile.description, addOrEditWelcomeMessage)
}
GroupPreferencesButton(openPreferences)

View File

@@ -4,6 +4,7 @@ import InfoRow
import SectionBottomSpacer
import SectionDividerSpaced
import SectionSpacer
import SectionTextFooter
import SectionView
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.*
@@ -13,6 +14,7 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -20,10 +22,12 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import chat.simplex.app.R
import chat.simplex.app.SimplexApp
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.chat.*
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.newchat.QRCode
import chat.simplex.app.views.usersettings.SettingsActionItem
import kotlinx.datetime.Clock
@@ -173,10 +177,20 @@ fun GroupMemberInfoLayout(
VerifyCodeButton(member.verified, verifyClicked)
}
}
SectionSpacer()
SectionDividerSpaced()
}
}
if (member.contactLink != null) {
val context = LocalContext.current
SectionView(stringResource(R.string.address_section_title).uppercase()) {
QRCode(member.contactLink, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f))
ShareAddressButton { shareText(context, member.contactLink) }
SectionTextFooter(stringResource(R.string.you_can_share_this_address_with_your_contacts).format(member.displayName))
}
SectionDividerSpaced()
}
SectionView(title = stringResource(R.string.member_info_section_title_member)) {
InfoRow(stringResource(R.string.info_row_group), groupInfo.displayName)
val roles = remember { member.canChangeRoleTo(groupInfo) }

View File

@@ -1,22 +1,30 @@
package chat.simplex.app.views.chat.group
import SectionBottomSpacer
import SectionDividerSpaced
import SectionItemView
import SectionSpacer
import SectionView
import TextIconSpaced
import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import chat.simplex.app.*
import chat.simplex.app.R
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
import kotlinx.coroutines.delay
import kotlinx.serialization.Serializable
import java.lang.Exception
@Composable
fun GroupWelcomeView(m: ChatModel, groupInfo: GroupInfo, close: () -> Unit) {
@@ -49,6 +57,7 @@ fun GroupWelcomeView(m: ChatModel, groupInfo: GroupInfo, close: () -> Unit) {
GroupWelcomeLayout(
welcomeText,
groupInfo,
m.controller.appPrefs.simplexLinkMode.get(),
save = ::save
)
}
@@ -58,19 +67,43 @@ fun GroupWelcomeView(m: ChatModel, groupInfo: GroupInfo, close: () -> Unit) {
private fun GroupWelcomeLayout(
welcomeText: MutableState<String>,
groupInfo: GroupInfo,
linkMode: SimplexLinkMode,
save: () -> Unit,
) {
Column(
Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
val editMode = remember { mutableStateOf(true) }
AppBarTitle(stringResource(R.string.group_welcome_title))
val welcomeText = remember { welcomeText }
TextEditor(Modifier.padding(horizontal = DEFAULT_PADDING).height(160.dp), text = welcomeText)
SectionSpacer()
SaveButton(
save = save,
disabled = welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null)
)
val welcomeText = rememberSaveable { welcomeText }
if (groupInfo.canEdit) {
if (editMode.value) {
val focusRequester = remember { FocusRequester() }
TextEditor(welcomeText, Modifier.heightIn(min = 100.dp), stringResource(R.string.enter_welcome_message), focusRequester = focusRequester)
LaunchedEffect(Unit) {
delay(300)
focusRequester.requestFocus()
}
} else {
TextEditorPreview(welcomeText.value, linkMode)
}
ChangeModeButton(
editMode.value,
click = {
editMode.value = !editMode.value
},
welcomeText.value.isEmpty()
)
CopyTextButton { copyText(SimplexApp.context, welcomeText.value) }
SectionDividerSpaced(maxBottomPadding = false)
SaveButton(
save = save,
disabled = welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null)
)
} else {
TextEditorPreview(welcomeText.value, linkMode)
CopyTextButton { copyText(SimplexApp.context, welcomeText.value) }
}
SectionBottomSpacer()
}
}
@@ -84,6 +117,35 @@ private fun SaveButton(save: () -> Unit, disabled: Boolean) {
}
}
@Composable
private fun ChangeModeButton(editMode: Boolean, click: () -> Unit, disabled: Boolean) {
SectionItemView(click, disabled = disabled) {
Icon(
painterResource(if (editMode) R.drawable.ic_visibility else R.drawable.ic_edit),
contentDescription = generalGetString(R.string.edit_verb),
tint = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary,
)
TextIconSpaced()
Text(
stringResource(if (editMode) R.string.group_welcome_preview else R.string.edit_verb),
color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary
)
}
}
@Composable
private fun CopyTextButton(click: () -> Unit) {
SectionItemView(click) {
Icon(
painterResource(R.drawable.ic_content_copy),
contentDescription = generalGetString(R.string.copy_verb),
tint = MaterialTheme.colors.primary,
)
TextIconSpaced()
Text(stringResource(R.string.copy_verb), color = MaterialTheme.colors.primary)
}
}
private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) {
AlertManager.shared.showAlertDialogStacked(
title = generalGetString(R.string.save_welcome_message_question),

View File

@@ -8,7 +8,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.font.FontWeight
@@ -18,7 +17,7 @@ import androidx.compose.ui.unit.sp
import chat.simplex.app.R
import chat.simplex.app.ui.theme.SimpleXTheme
import chat.simplex.app.views.helpers.annotatedStringResource
import chat.simplex.app.views.helpers.openUriCatching
import chat.simplex.app.views.onboarding.ReadableTextWithLink
import chat.simplex.app.views.usersettings.MarkdownHelpView
import chat.simplex.app.views.usersettings.simplexTeamUri
@@ -29,17 +28,8 @@ fun ChatHelpView(addContact: (() -> Unit)? = null) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
val uriHandler = LocalUriHandler.current
Text(stringResource(R.string.thank_you_for_installing_simplex), lineHeight = 22.sp)
Text(
annotatedStringResource(R.string.you_can_connect_to_simplex_chat_founder),
modifier = Modifier.clickable(onClick = {
uriHandler.openUriCatching(simplexTeamUri)
}),
lineHeight = 22.sp
)
ReadableTextWithLink(R.string.you_can_connect_to_simplex_chat_founder, simplexTeamUri)
Column(
Modifier.padding(top = 24.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)

View File

@@ -35,7 +35,6 @@ fun ShareListView(chatModel: ChatModel, stopped: Boolean) {
Column(
modifier = Modifier
.fillMaxSize()
.themedBackground()
) {
if (chatModel.chats.isNotEmpty()) {
ShareList(chatModel, search = searchInList)

View File

@@ -77,7 +77,7 @@ suspend fun getLinkPreview(url: String): LinkPreview? {
}
@Composable
fun ComposeLinkView(linkPreview: LinkPreview?, cancelPreview: () -> Unit) {
fun ComposeLinkView(linkPreview: LinkPreview?, cancelPreview: () -> Unit, cancelEnabled: Boolean) {
val sentColor = CurrentColors.collectAsState().value.appColors.sentMessage
Row(
Modifier.fillMaxWidth().padding(top = 8.dp).background(sentColor),
@@ -109,13 +109,15 @@ fun ComposeLinkView(linkPreview: LinkPreview?, cancelPreview: () -> Unit) {
)
}
}
IconButton(onClick = cancelPreview, modifier = Modifier.padding(0.dp)) {
Icon(
painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.icon_descr_cancel_link_preview),
tint = MaterialTheme.colors.primary,
modifier = Modifier.padding(10.dp)
)
if (cancelEnabled) {
IconButton(onClick = cancelPreview, modifier = Modifier.padding(0.dp)) {
Icon(
painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.icon_descr_cancel_link_preview),
tint = MaterialTheme.colors.primary,
modifier = Modifier.padding(10.dp)
)
}
}
}
}
@@ -193,7 +195,7 @@ fun PreviewChatItemLinkView() {
@Composable
fun PreviewComposeLinkView() {
SimpleXTheme {
ComposeLinkView(LinkPreview.sampleData) { -> }
ComposeLinkView(LinkPreview.sampleData, cancelPreview = { -> }, true)
}
}
@@ -201,6 +203,6 @@ fun PreviewComposeLinkView() {
@Composable
fun PreviewComposeLinkViewLoading() {
SimpleXTheme {
ComposeLinkView(null) { -> }
ComposeLinkView(null, cancelPreview = { -> }, true)
}
}

View File

@@ -1,64 +1,130 @@
package chat.simplex.app.views.helpers
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import android.util.Log
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.*
import chat.simplex.app.ui.theme.DEFAULT_PADDING
import chat.simplex.app.TAG
import chat.simplex.app.chatParseMarkdown
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.chat.item.MarkdownText
import com.google.accompanist.insets.navigationBarsWithImePadding
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.serialization.Serializable
import java.lang.Exception
@Composable
fun TextEditor(
value: MutableState<String>,
modifier: Modifier,
text: MutableState<String>,
border: Boolean = true,
fontSize: TextUnit = 14.sp,
background: Color = MaterialTheme.colors.background,
onChange: ((String) -> Unit)? = null
placeholder: String? = null,
contentPadding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING),
isValid: (String) -> Boolean = { true },
focusRequester: FocusRequester? = null
) {
BasicTextField(
value = text.value,
onValueChange = { text.value = it; onChange?.invoke(it) },
textStyle = TextStyle(
fontFamily = FontFamily.Monospace, fontSize = fontSize,
color = MaterialTheme.colors.onBackground
),
keyboardOptions = KeyboardOptions.Default.copy(
capitalization = KeyboardCapitalization.None,
autoCorrect = false
),
modifier = modifier,
cursorBrush = SolidColor(MaterialTheme.colors.secondary),
decorationBox = { innerTextField ->
Surface(
shape = if (border) RoundedCornerShape(10.dp) else RectangleShape,
border = if (border) BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant) else null
) {
Row(
Modifier.background(background),
verticalAlignment = Alignment.Top
) {
Box(
Modifier
.weight(1f)
.padding(vertical = 5.dp, horizontal = if (border) 7.dp else DEFAULT_PADDING)
) {
innerTextField()
}
var valid by rememberSaveable { mutableStateOf(true) }
var focused by rememberSaveable { mutableStateOf(false) }
val strokeColor by remember {
derivedStateOf {
if (valid) {
if (focused) {
CurrentColors.value.colors.secondary.copy(alpha = 0.6f)
} else {
CurrentColors.value.colors.secondary.copy(alpha = 0.3f)
}
}
} else Color.Red
}
)
}
Box(
Modifier
.fillMaxWidth()
.padding(contentPadding)
.heightIn(min = 52.dp),
// .border(border = BorderStroke(1.dp, strokeColor), shape = RoundedCornerShape(26.dp)),
contentAlignment = Alignment.Center,
) {
val modifier = modifier
.fillMaxWidth()
.navigationBarsWithImePadding()
.onFocusChanged { focused = it.isFocused }
BasicTextField(
value = value.value,
onValueChange = { value.value = it },
modifier = if (focusRequester == null) modifier else modifier.focusRequester(focusRequester),
textStyle = TextStyle(fontSize = 18.sp, color = MaterialTheme.colors.onBackground),
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
autoCorrect = false
),
singleLine = false,
maxLines = 5,
cursorBrush = SolidColor(MaterialTheme.colors.secondary),
decorationBox = @Composable { innerTextField ->
TextFieldDefaults.TextFieldDecorationBox(
value = value.value,
innerTextField = innerTextField,
placeholder = if (placeholder != null) {{ Text(placeholder, fontSize = 18.sp, color = MaterialTheme.colors.secondary) }} else null,
contentPadding = PaddingValues(),
label = null,
visualTransformation = VisualTransformation.None,
leadingIcon = null,
trailingIcon = null,
singleLine = false,
enabled = true,
isError = false,
interactionSource = remember { MutableInteractionSource() },
)
}
)
}
LaunchedEffect(Unit) {
snapshotFlow { value.value }
.distinctUntilChanged()
.collect {
valid = isValid(it)
}
}
}
@Composable
fun TextEditorPreview(text: String, linkMode: SimplexLinkMode, markdown: Boolean = true) {
SelectionContainer {
MarkdownText(
text,
formattedText = if (markdown) remember(text) { parseToMarkdown(text) } else null,
modifier = Modifier.heightIn(min = 100.dp).padding(horizontal = DEFAULT_PADDING),
linkMode = linkMode,
style = TextStyle(fontSize = 18.sp, color = MaterialTheme.colors.onBackground)
)
}
}
@Serializable
data class ParsedFormattedText(
val formattedText: List<FormattedText>? = null
)
fun parseToMarkdown(text: String): List<FormattedText>? {
val formatted = chatParseMarkdown(text)
return try {
json.decodeFromString(ParsedFormattedText.serializer(), formatted).formattedText
} catch (e: Exception) {
Log.e(TAG, "Failed to parse into markdown: " + e.stackTraceToString())
null
}
}

View File

@@ -37,7 +37,6 @@ import androidx.core.text.HtmlCompat
import chat.simplex.app.*
import chat.simplex.app.R
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.ThemeData
import chat.simplex.app.ui.theme.ThemeOverrides
import com.charleskorn.kaml.decodeFromStream
import kotlinx.coroutines.*
@@ -391,10 +390,10 @@ fun getDrawableFromUri(uri: Uri, withAlertOnException: Boolean = true): Drawable
}
}
fun getThemeFromUri(uri: Uri, withAlertOnException: Boolean = true): ThemeData? {
fun getThemeFromUri(uri: Uri, withAlertOnException: Boolean = true): ThemeOverrides? {
SimplexApp.context.contentResolver.openInputStream(uri).use {
runCatching {
return yaml.decodeFromStream<ThemeData>(it!!)
return yaml.decodeFromStream<ThemeOverrides>(it!!)
}.onFailure {
if (withAlertOnException) {
AlertManager.shared.showAlertMsg(

View File

@@ -0,0 +1,23 @@
package chat.simplex.app.views.newchat
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import chat.simplex.app.R
import chat.simplex.app.views.helpers.AppBarTitle
import chat.simplex.app.views.onboarding.ReadableText
import chat.simplex.app.views.onboarding.ReadableTextWithLink
@Composable
fun AddContactLearnMore() {
Column(
Modifier.verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.one_time_link))
ReadableText(R.string.scan_qr_to_connect_to_contact)
ReadableText(R.string.if_you_cant_meet_in_person)
ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/readme.html#connect-to-friends")
}
}

View File

@@ -1,6 +1,8 @@
package chat.simplex.app.views.newchat
import SectionBottomSpacer
import SectionSpacer
import SectionView
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -15,10 +17,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.app.R
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.usersettings.SettingsActionItem
@Composable
fun AddContactView(connReqInvitation: String, connIncognito: Boolean) {
@@ -26,64 +28,94 @@ fun AddContactView(connReqInvitation: String, connIncognito: Boolean) {
AddContactLayout(
connReq = connReqInvitation,
connIncognito = connIncognito,
share = { shareText(cxt, connReqInvitation) }
share = { shareText(cxt, connReqInvitation) },
learnMore = {
ModalManager.shared.showModal {
Column(
Modifier
.fillMaxHeight()
.padding(horizontal = DEFAULT_PADDING),
verticalArrangement = Arrangement.SpaceBetween
) {
AddContactLearnMore()
}
}
}
)
}
@Composable
fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit) {
BoxWithConstraints {
val screenHeight = maxHeight
Column(
Modifier
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.SpaceBetween,
) {
AppBarTitle(stringResource(R.string.add_contact), false)
Text(
stringResource(R.string.show_QR_code_for_your_contact_to_scan_from_the_app__multiline),
)
Row {
InfoAboutIncognito(
connIncognito,
true,
generalGetString(R.string.incognito_random_profile_description),
generalGetString(R.string.your_profile_will_be_sent)
)
}
if (connReq.isNotEmpty()) {
QRCode(
connReq, Modifier
.aspectRatio(1f)
.padding(vertical = 3.dp)
)
} else {
CircularProgressIndicator(
Modifier
.size(36.dp)
.padding(4.dp)
.align(Alignment.CenterHorizontally),
color = MaterialTheme.colors.secondary,
strokeWidth = 3.dp
)
}
Text(
annotatedStringResource(R.string.if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel),
lineHeight = 22.sp,
modifier = Modifier
.padding(top = DEFAULT_PADDING, bottom = if (screenHeight > 600.dp) DEFAULT_PADDING else 0.dp)
)
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
SimpleButton(stringResource(R.string.share_invitation_link), icon = painterResource(R.drawable.ic_share), click = share)
}
SectionBottomSpacer()
fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit, learnMore: () -> Unit) {
Column(
Modifier
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.SpaceBetween,
) {
AppBarTitle(stringResource(R.string.add_contact))
OneTimeLinkProfileText(connIncognito)
SectionSpacer()
SectionView(stringResource(R.string.one_time_link_short).uppercase()) {
OneTimeLinkSection(connReq, share, learnMore)
}
SectionBottomSpacer()
}
}
@Composable
fun OneTimeLinkProfileText(connIncognito: Boolean) {
Row(Modifier.padding(horizontal = DEFAULT_PADDING)) {
InfoAboutIncognito(
connIncognito,
true,
generalGetString(R.string.incognito_random_profile_description),
generalGetString(R.string.your_profile_will_be_sent)
)
}
}
@Composable
fun ColumnScope.OneTimeLinkSection(connReq: String, share: () -> Unit, learnMore: () -> Unit) {
if (connReq.isNotEmpty()) {
QRCode(
connReq, Modifier
.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF)
.aspectRatio(1f)
)
} else {
CircularProgressIndicator(
Modifier
.size(36.dp)
.padding(4.dp)
.align(Alignment.CenterHorizontally),
color = MaterialTheme.colors.secondary,
strokeWidth = 3.dp
)
}
ShareLinkButton(share)
OneTimeLinkLearnMoreButton(learnMore)
}
@Composable
fun ShareLinkButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(R.drawable.ic_share),
stringResource(R.string.share_invitation_link),
onClick,
iconColor = MaterialTheme.colors.primary,
textColor = MaterialTheme.colors.primary,
)
}
@Composable
fun OneTimeLinkLearnMoreButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(R.drawable.ic_info),
stringResource(R.string.learn_more),
onClick,
)
}
@Composable
fun InfoAboutIncognito(chatModelIncognito: Boolean, supportedIncognito: Boolean = true, onText: String, offText: String, centered: Boolean = false) {
if (chatModelIncognito) {
@@ -133,7 +165,8 @@ fun PreviewAddContactView() {
AddContactLayout(
connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D",
connIncognito = false,
share = {}
share = {},
learnMore = {},
)
}
}

View File

@@ -159,7 +159,7 @@ fun CreateGroupButton(color: Color, modifier: Modifier) {
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
Surface(shape = RoundedCornerShape(20.dp)) {
Surface(shape = RoundedCornerShape(20.dp), color = Color.Transparent) {
Row(modifier, verticalAlignment = Alignment.CenterVertically) {
Text(stringResource(R.string.create_profile_button), style = MaterialTheme.typography.caption, color = color, fontWeight = FontWeight.Bold)
Icon(painterResource(R.drawable.ic_arrow_forward_ios), stringResource(R.string.create_profile_button), tint = color)

View File

@@ -1,6 +1,7 @@
package chat.simplex.app.views.newchat
import SectionBottomSpacer
import SectionDividerSpaced
import SectionView
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
@@ -10,6 +11,7 @@ import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@@ -43,13 +45,16 @@ fun ContactConnectionInfoView(
}
}
}
val context = LocalContext.current
ContactConnectionInfoLayout(
connReq = connReqInvitation,
contactConnection,
connIncognito = contactConnection.incognito,
focusAlias,
deleteConnection = { deleteContactConnectionAlert(contactConnection, chatModel, close) },
onLocalAliasChanged = { setContactAlias(contactConnection, it, chatModel) },
showQr = {
share = { if (connReqInvitation != null) shareText(context, connReqInvitation) },
learnMore = {
ModalManager.shared.showModal {
Column(
Modifier
@@ -57,7 +62,7 @@ fun ContactConnectionInfoView(
.padding(horizontal = DEFAULT_PADDING),
verticalArrangement = Arrangement.SpaceBetween
) {
AddContactView(connReqInvitation ?: return@showModal, contactConnection.incognito)
AddContactLearnMore()
}
}
}
@@ -68,10 +73,12 @@ fun ContactConnectionInfoView(
private fun ContactConnectionInfoLayout(
connReq: String?,
contactConnection: PendingContactConnection,
connIncognito: Boolean,
focusAlias: Boolean,
deleteConnection: () -> Unit,
onLocalAliasChanged: (String) -> Unit,
showQr: () -> Unit,
share: () -> Unit,
learnMore: () -> Unit,
) {
Column(
Modifier
@@ -83,11 +90,6 @@ private fun ContactConnectionInfoLayout(
else R.string.you_accepted_connection
)
)
if (contactConnection.groupLinkId == null) {
Row(Modifier.padding(bottom = DEFAULT_PADDING)) {
LocalAliasEditor(contactConnection.localAlias, center = false, leadingIcon = true, focus = focusAlias, updateValue = onLocalAliasChanged)
}
}
Text(
stringResource(
if (contactConnection.viaContactUri)
@@ -97,27 +99,28 @@ private fun ContactConnectionInfoLayout(
),
Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = DEFAULT_PADDING)
)
OneTimeLinkProfileText(connIncognito)
if (contactConnection.groupLinkId == null) {
LocalAliasEditor(contactConnection.localAlias, center = false, leadingIcon = true, focus = focusAlias, updateValue = onLocalAliasChanged)
}
SectionView {
if (!connReq.isNullOrEmpty() && contactConnection.initiated) {
ShowQrButton(contactConnection.incognito, showQr)
OneTimeLinkSection(connReq, share, learnMore)
} else {
OneTimeLinkLearnMoreButton(learnMore)
}
DeleteButton(deleteConnection)
}
SectionDividerSpaced(maxBottomPadding = false)
DeleteButton(deleteConnection)
SectionBottomSpacer()
}
}
@Composable
fun ShowQrButton(incognito: Boolean, onClick: () -> Unit) {
SettingsActionItem(
painterResource(R.drawable.ic_qr_code),
stringResource(R.string.show_QR_code),
click = onClick,
textColor = if (incognito) Indigo else MaterialTheme.colors.primary,
iconColor = if (incognito) Indigo else MaterialTheme.colors.primary,
)
}
@Composable
fun DeleteButton(onClick: () -> Unit) {
SettingsActionItem(
@@ -147,10 +150,12 @@ private fun PreviewContactConnectionInfoView() {
ContactConnectionInfoLayout(
connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D",
PendingContactConnection.getSampleData(),
connIncognito = false,
focusAlias = false,
deleteConnection = {},
onLocalAliasChanged = {},
showQr = {},
share = {},
learnMore = {}
)
}
}

View File

@@ -45,14 +45,13 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) {
when {
it == CreateLinkTab.ONE_TIME && connReqInvitation.value.isNullOrEmpty() -> stringResource(R.string.create_one_time_link)
it == CreateLinkTab.ONE_TIME -> stringResource(R.string.one_time_link)
it == CreateLinkTab.LONG_TERM -> stringResource(R.string.your_contact_address)
it == CreateLinkTab.LONG_TERM -> stringResource(R.string.your_simplex_contact_address)
else -> ""
}
}
Column(
Modifier
.fillMaxHeight()
.padding(horizontal = DEFAULT_PADDING),
.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceBetween
) {
Column(Modifier.weight(1f)) {
@@ -61,7 +60,7 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) {
AddContactView(connReqInvitation.value ?: "", m.incognito.value)
}
CreateLinkTab.LONG_TERM -> {
UserAddressView(m)
UserAddressView(m, viaCreateLinkView = true, close = {})
}
}
}

View File

@@ -173,7 +173,7 @@ fun ActionButton(
disabled: Boolean = false,
click: () -> Unit = {}
) {
Surface(shape = RoundedCornerShape(18.dp)) {
Surface(shape = RoundedCornerShape(18.dp), color = Color.Transparent) {
Column(
Modifier
.clickable(onClick = click)

View File

@@ -85,7 +85,7 @@ fun PasteToConnectLayout(
)
Box(Modifier.padding(top = DEFAULT_PADDING, bottom = 6.dp)) {
TextEditor(Modifier.height(180.dp), text = connectionLink)
TextEditor(connectionLink, Modifier.height(180.dp), contentPadding = PaddingValues())
}
Row(

View File

@@ -4,21 +4,23 @@ import android.content.res.Configuration
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.app.R
import chat.simplex.app.SimplexApp
import chat.simplex.app.model.User
import chat.simplex.app.ui.theme.DEFAULT_PADDING
import chat.simplex.app.ui.theme.SimpleXTheme
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.chat.item.MarkdownText
import chat.simplex.app.views.helpers.*
@Composable
@@ -33,12 +35,7 @@ fun HowItWorks(user: User?, onboardingStage: MutableState<OnboardingStage?>? = n
ReadableText(R.string.you_control_servers_to_receive_your_contacts_to_send)
ReadableText(R.string.only_client_devices_store_contacts_groups_e2e_encrypted_messages)
if (onboardingStage == null) {
val uriHandler = LocalUriHandler.current
Text(
annotatedStringResource(R.string.read_more_in_github_with_link),
modifier = Modifier.padding(bottom = 12.dp).clickable { uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat#readme") },
lineHeight = 22.sp
)
ReadableTextWithLink(R.string.read_more_in_github_with_link, "https://github.com/simplex-chat/simplex-chat#readme")
} else {
ReadableText(R.string.read_more_in_github)
}
@@ -59,11 +56,42 @@ fun ReadableText(@StringRes stringResId: Int, textAlign: TextAlign = TextAlign.S
Text(annotatedStringResource(stringResId), modifier = Modifier.padding(padding), textAlign = textAlign, lineHeight = 22.sp)
}
@Composable
fun ReadableTextWithLink(@StringRes stringResId: Int, link: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) {
val annotated = annotatedStringResource(stringResId)
val primary = MaterialTheme.colors.primary
// This replaces links in text highlighted with specific color, e.g. SimplexBlue
val newStyles = remember(stringResId) {
val newStyles = ArrayList<AnnotatedString.Range<SpanStyle>>()
annotated.spanStyles.forEach {
if (it.item.color == SimplexBlue) {
newStyles.add(it.copy(item = it.item.copy(primary)))
} else {
newStyles.add(it)
}
}
newStyles
}
val uriHandler = LocalUriHandler.current
Text(AnnotatedString(annotated.text, newStyles), modifier = Modifier.padding(padding).clickable { uriHandler.openUriCatching(link) }, textAlign = textAlign, lineHeight = 22.sp)
}
@Composable
fun ReadableText(text: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) {
Text(text, modifier = Modifier.padding(padding), textAlign = textAlign, lineHeight = 22.sp)
}
@Composable
fun ReadableMarkdownText(text: String, textAlign: TextAlign = TextAlign.Start, padding: PaddingValues = PaddingValues(bottom = 12.dp)) {
MarkdownText(
text,
formattedText = remember(text) { parseToMarkdown(text) },
modifier = Modifier.padding(padding),
style = TextStyle(textAlign = textAlign, lineHeight = 22.sp, fontSize = 16.sp),
linkMode = SimplexApp.context.chatModel.controller.appPrefs.simplexLinkMode.get(),
)
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,

View File

@@ -31,7 +31,6 @@ fun CreateProfile(chatModel: ChatModel, close: () -> Unit) {
Box(
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colors.background)
.padding(20.dp)
) {
CreateProfilePanel(chatModel, close)

View File

@@ -261,7 +261,7 @@ private val versionDescriptions: List<VersionDescription> = listOf(
icon = R.drawable.ic_translate,
titleId = R.string.v4_5_italian_interface,
descrId = R.string.v4_5_italian_interface_descr,
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps"
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat"
)
)
),
@@ -297,7 +297,7 @@ private val versionDescriptions: List<VersionDescription> = listOf(
icon = R.drawable.ic_translate,
titleId = R.string.v4_6_chinese_spanish_interface,
descrId = R.string.v4_6_chinese_spanish_interface_descr,
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps"
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat"
)
)
),
@@ -318,7 +318,7 @@ private val versionDescriptions: List<VersionDescription> = listOf(
icon = R.drawable.ic_translate,
titleId = R.string.v5_0_polish_interface,
descrId = R.string.v5_0_polish_interface_descr,
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps"
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat"
)
)
)

View File

@@ -1,160 +0,0 @@
package chat.simplex.app.views.usersettings
import SectionBottomSpacer
import SectionCustomFooter
import SectionView
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.app.R
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
@Composable
fun AcceptRequestsView(m: ChatModel, contactLink: UserContactLinkRec) {
var contactLink by remember { mutableStateOf(contactLink) }
AcceptRequestsLayout(
contactLink,
saveState = { new: MutableState<AutoAcceptState>, old: MutableState<AutoAcceptState> ->
withApi {
val link = m.controller.userAddressAutoAccept(new.value.autoAccept)
if (link != null) {
contactLink = link
m.userAddress.value = link
old.value = new.value
}
}
}
)
}
@Composable
private fun AcceptRequestsLayout(
contactLink: UserContactLinkRec,
saveState: (new: MutableState<AutoAcceptState>, old: MutableState<AutoAcceptState>) -> Unit,
) {
Column(
Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.contact_requests))
val autoAcceptState = remember { mutableStateOf(AutoAcceptState(contactLink)) }
val autoAcceptStateSaved = remember { mutableStateOf(autoAcceptState.value) }
SectionView(stringResource(R.string.accept_requests).uppercase()) {
PreferenceToggleWithIcon(stringResource(R.string.accept_automatically), painterResource(R.drawable.ic_check), checked = autoAcceptState.value.enable) {
autoAcceptState.value = if (!it)
AutoAcceptState()
else
AutoAcceptState(it, autoAcceptState.value.incognito, autoAcceptState.value.welcomeText)
}
if (autoAcceptState.value.enable) {
PreferenceToggleWithIcon(
stringResource(R.string.incognito),
if (autoAcceptState.value.incognito) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy),
if (autoAcceptState.value.incognito) Indigo else MaterialTheme.colors.secondary,
autoAcceptState.value.incognito,
) {
autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText)
}
}
}
val welcomeText = remember { mutableStateOf(autoAcceptState.value.welcomeText) }
SectionCustomFooter(PaddingValues(horizontal = DEFAULT_PADDING)) {
ButtonsFooter(
cancel = {
autoAcceptState.value = autoAcceptStateSaved.value
welcomeText.value = autoAcceptStateSaved.value.welcomeText
},
save = { saveState(autoAcceptState, autoAcceptStateSaved) },
disabled = autoAcceptState.value == autoAcceptStateSaved.value
)
}
Spacer(Modifier.height(DEFAULT_PADDING))
if (autoAcceptState.value.enable) {
Text(
stringResource(R.string.section_title_welcome_message), color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2,
modifier = Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), fontSize = 12.sp
)
TextEditor(Modifier.padding(horizontal = DEFAULT_PADDING).height(160.dp), text = welcomeText)
LaunchedEffect(welcomeText.value) {
if (welcomeText.value != autoAcceptState.value.welcomeText) {
autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, autoAcceptState.value.incognito, welcomeText.value)
}
}
}
SectionBottomSpacer()
}
}
@Composable
private fun ButtonsFooter(cancel: () -> Unit, save: () -> Unit, disabled: Boolean) {
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
FooterButton(painterResource(R.drawable.ic_replay), stringResource(R.string.cancel_verb), cancel, disabled)
FooterButton(painterResource(R.drawable.ic_check), stringResource(R.string.save_verb), save, disabled)
}
}
private class AutoAcceptState {
var enable: Boolean = false
private set
var incognito: Boolean = false
private set
var welcomeText: String = ""
private set
constructor(enable: Boolean = false, incognito: Boolean = false, welcomeText: String = "") {
this.enable = enable
this.incognito = incognito
this.welcomeText = welcomeText
}
constructor(contactLink: UserContactLinkRec) {
contactLink.autoAccept?.let { aa ->
enable = true
incognito = aa.acceptIncognito
aa.autoReply?.let { msg ->
welcomeText = msg.text
} ?: run {
welcomeText = ""
}
}
}
val autoAccept: AutoAccept?
get() {
if (enable) {
var autoReply: MsgContent? = null
val s = welcomeText.trim()
if (s != "") {
autoReply = MsgContent.MCText(s)
}
return AutoAccept(incognito, autoReply)
}
return null
}
override fun equals(other: Any?): Boolean {
if (other !is AutoAcceptState) return false
return this.enable == other.enable && this.incognito == other.incognito && this.welcomeText == other.welcomeText
}
override fun hashCode(): Int {
var result = enable.hashCode()
result = 31 * result + incognito.hashCode()
result = 31 * result + welcomeText.hashCode()
return result
}
}

View File

@@ -240,8 +240,8 @@ fun CustomizeThemeView(editColor: (ThemeColor, Color) -> Unit) {
val theme = remember { mutableStateOf(null as String?) }
val exportThemeLauncher = rememberSaveThemeLauncher(context, theme)
SectionItemView({
val themeData = ThemeManager.currentThemeData(isInDarkTheme)
theme.value = yaml.encodeToString<ThemeData>(themeData)
val overrides = ThemeManager.currentThemeOverridesForExport(isInDarkTheme)
theme.value = yaml.encodeToString<ThemeOverrides>(overrides)
exportThemeLauncher.launch("simplex.theme")
}) {
Text(generalGetString(R.string.export_theme), color = colors.primary)
@@ -251,7 +251,7 @@ fun CustomizeThemeView(editColor: (ThemeColor, Color) -> Unit) {
if (uri != null) {
val theme = getThemeFromUri(uri)
if (theme != null) {
ThemeManager.saveAndApplyThemeData(currentTheme.name, theme, isInDarkTheme)
ThemeManager.saveAndApplyThemeOverrides(theme, isInDarkTheme)
}
}
}

View File

@@ -48,12 +48,13 @@ fun NetworkAndServersView(
chatModel.userSMPServersUnsaved.value = null
}
val proxyPort = remember { derivedStateOf { chatModel.controller.appPrefs.networkProxyHostPort.state.value?.split(":")?.lastOrNull()?.toIntOrNull() ?: 9050 } }
NetworkAndServersLayout(
developerTools = developerTools,
networkUseSocksProxy = networkUseSocksProxy,
onionHosts = onionHosts,
sessionMode = sessionMode,
proxyPort = remember { derivedStateOf { chatModel.controller.appPrefs.networkProxyHostPort.state.value?.split(":")?.lastOrNull()?.toIntOrNull() ?: 9050 } },
proxyPort = proxyPort,
showModal = showModal,
showSettingsModal = showSettingsModal,
showCustomModal = showCustomModal,
@@ -61,14 +62,15 @@ fun NetworkAndServersView(
if (enable) {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.network_enable_socks),
text = generalGetString(R.string.network_enable_socks_info),
text = generalGetString(R.string.network_enable_socks_info).format(proxyPort.value),
confirmText = generalGetString(R.string.confirm_verb),
onConfirm = {
withApi {
chatModel.controller.apiSetNetworkConfig(NetCfg.proxyDefaults)
chatModel.controller.setNetCfg(NetCfg.proxyDefaults)
val conf = NetCfg.proxyDefaults.withHostPort(chatModel.controller.appPrefs.networkProxyHostPort.get())
chatModel.controller.apiSetNetworkConfig(conf)
chatModel.controller.setNetCfg(conf)
networkUseSocksProxy.value = true
onionHosts.value = NetCfg.proxyDefaults.onionHosts
onionHosts.value = conf.onionHosts
}
}
)
@@ -79,10 +81,11 @@ fun NetworkAndServersView(
confirmText = generalGetString(R.string.confirm_verb),
onConfirm = {
withApi {
chatModel.controller.apiSetNetworkConfig(NetCfg.defaults)
chatModel.controller.setNetCfg(NetCfg.defaults)
val conf = NetCfg.defaults
chatModel.controller.apiSetNetworkConfig(conf)
chatModel.controller.setNetCfg(conf)
networkUseSocksProxy.value = false
onionHosts.value = NetCfg.defaults.onionHosts
onionHosts.value = conf.onionHosts
}
}
)
@@ -206,35 +209,31 @@ fun UseSocksProxySwitch(
) {
Icon(
painterResource(R.drawable.ic_settings_ethernet),
stringResource(R.string.network_socks_toggle),
stringResource(R.string.network_socks_toggle_use_socks_proxy),
tint = MaterialTheme.colors.secondary
)
TextIconSpaced(false)
if (networkUseSocksProxy.value) {
val text = buildAnnotatedString {
append(generalGetString(R.string.network_socks_toggle_use_socks_proxy) + " (")
val style = SpanStyle(color = MaterialTheme.colors.primary)
withAnnotation(tag = "PORT", annotation = generalGetString(R.string.network_proxy_port).format(proxyPort.value)) {
withStyle(style) { append(generalGetString(R.string.network_proxy_port).format(proxyPort.value)) }
}
append(")")
}
ClickableText(
text,
style = TextStyle(color = MaterialTheme.colors.onBackground, fontSize = 16.sp, fontFamily = FontFamily(Font(R.font.inter_regular))),
onClick = { offset ->
text.getStringAnnotations(tag = "PORT", start = offset, end = offset)
.firstOrNull()?.let { _ ->
showSettingsModal { SockProxySettings(it) }()
}
},
shouldConsumeEvent = { offset ->
text.getStringAnnotations(tag = "PORT", start = offset, end = offset).any()
}
)
} else {
Text(stringResource(R.string.network_socks_toggle))
val text = buildAnnotatedString {
append(generalGetString(R.string.network_socks_toggle_use_socks_proxy) + " (")
val style = SpanStyle(color = MaterialTheme.colors.primary)
withAnnotation(tag = "PORT", annotation = generalGetString(R.string.network_proxy_port).format(proxyPort.value)) {
withStyle(style) { append(generalGetString(R.string.network_proxy_port).format(proxyPort.value)) }
}
append(")")
}
ClickableText(
text,
style = TextStyle(color = MaterialTheme.colors.onBackground, fontSize = 16.sp, fontFamily = FontFamily(Font(R.font.inter_regular))),
onClick = { offset ->
text.getStringAnnotations(tag = "PORT", start = offset, end = offset)
.firstOrNull()?.let { _ ->
showSettingsModal { SockProxySettings(it) }()
}
},
shouldConsumeEvent = { offset ->
text.getStringAnnotations(tag = "PORT", start = offset, end = offset).any()
}
)
}
DefaultSwitch(
checked = networkUseSocksProxy.value,
@@ -262,13 +261,15 @@ fun SockProxySettings(m: ChatModel) {
val save = {
withBGApi {
m.controller.appPrefs.networkProxyHostPort.set(hostUnsaved.value.text + ":" + portUnsaved.value.text)
m.controller.apiSetNetworkConfig(m.controller.getNetCfg())
if (m.controller.appPrefs.networkUseSocksProxy.get()) {
m.controller.apiSetNetworkConfig(m.controller.getNetCfg())
}
}
}
SectionView {
SectionItemView {
ResetToDefaultsButton({
showUpdateNetworkSettingsDialog {
val reset = {
m.controller.appPrefs.networkProxyHostPort.set(defaultHostPort)
val newHost = defaultHostPort.split(":").first()
val newPort = defaultHostPort.split(":").last()
@@ -276,6 +277,13 @@ fun SockProxySettings(m: ChatModel) {
portUnsaved.value = portUnsaved.value.copy(newPort, TextRange(newPort.length))
save()
}
if (m.controller.appPrefs.networkUseSocksProxy.get()) {
showUpdateNetworkSettingsDialog {
reset()
}
} else {
reset()
}
}, disabled = hostPort == defaultHostPort)
}
SectionItemView {
@@ -307,7 +315,7 @@ fun SockProxySettings(m: ChatModel) {
hostUnsaved.value = hostUnsaved.value.copy(prevHost, TextRange(prevHost.length))
portUnsaved.value = portUnsaved.value.copy(prevPort, TextRange(prevPort.length))
},
save = { showUpdateNetworkSettingsDialog { save() } },
save = { if (m.controller.appPrefs.networkUseSocksProxy.get()) showUpdateNetworkSettingsDialog { save() } else save() },
revertDisabled = hostPort == (hostUnsaved.value.text + ":" + portUnsaved.value.text),
saveDisabled = hostPort == (hostUnsaved.value.text + ":" + portUnsaved.value.text) ||
remember { derivedStateOf { !validHost(hostUnsaved.value.text) } }.value ||

View File

@@ -27,6 +27,8 @@ import chat.simplex.app.model.ServerAddress.Companion.parseServerAddress
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.newchat.QRCode
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
@@ -140,14 +142,16 @@ private fun CustomServer(
) {
val testedPreviously = remember { mutableMapOf<String, Boolean?>() }
TextEditor(
Modifier.height(144.dp),
text = serverAddress,
border = false,
fontSize = 16.sp,
background = if (isInDarkTheme()) GroupDark else MaterialTheme.colors.background
) {
testedPreviously[server.server] = server.tested
onUpdate(server.copy(server = it, tested = testedPreviously[serverAddress.value]))
serverAddress,
Modifier.height(144.dp)
)
LaunchedEffect(Unit) {
snapshotFlow { serverAddress.value }
.distinctUntilChanged()
.collect {
testedPreviously[server.server] = server.tested
onUpdate(server.copy(server = it, tested = testedPreviously[serverAddress.value]))
}
}
}
SectionDividerSpaced()

View File

@@ -266,7 +266,7 @@ private fun HowToButton() {
SettingsActionItem(
painterResource(R.drawable.ic_open_in_new),
stringResource(R.string.how_to_use_your_servers),
{ uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat/blob/stable/docs/SERVER.md") },
{ uriHandler.openUriCatching("https://simplex.chat/docs/server.html") },
textColor = MaterialTheme.colors.primary,
iconColor = MaterialTheme.colors.primary
)

View File

@@ -120,7 +120,7 @@ fun RTCServersLayout(
} else {
Text(stringResource(R.string.enter_one_ICE_server_per_line))
if (editRTCServers) {
TextEditor(Modifier.height(160.dp), text = userRTCServersStr)
TextEditor(userRTCServersStr, Modifier.height(160.dp), contentPadding = PaddingValues())
Row(
Modifier.fillMaxWidth(),
@@ -197,7 +197,7 @@ private fun howToButton() {
val uriHandler = LocalUriHandler.current
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable { uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat/blob/stable/docs/WEBRTC.md#configure-mobile-apps") }
modifier = Modifier.clickable { uriHandler.openUriCatching("https://simplex.chat/docs/webrtc.html#configure-mobile-apps") }
) {
Text(stringResource(R.string.how_to), color = MaterialTheme.colors.primary)
Icon(

View File

@@ -8,7 +8,6 @@ import SectionView
import TextIconSpaced
import android.content.Context
import android.content.res.Configuration
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
@@ -151,7 +150,7 @@ fun SettingsLayout(
val profileHidden = rememberSaveable { mutableStateOf(false) }
SettingsActionItem(painterResource(R.drawable.ic_manage_accounts), stringResource(R.string.your_chat_profiles), { withAuth(generalGetString(R.string.auth_open_chat_profiles), generalGetString(R.string.auth_log_in_using_credential)) { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden) } } }, disabled = stopped, extraPadding = true)
SettingsIncognitoActionItem(incognitoPref, incognito, stopped) { showModal { IncognitoView() }() }
SettingsActionItem(painterResource(R.drawable.ic_qr_code), stringResource(R.string.your_simplex_contact_address), showModal { CreateLinkView(it, CreateLinkTab.LONG_TERM) }, disabled = stopped, extraPadding = true)
SettingsActionItem(painterResource(R.drawable.ic_qr_code), stringResource(R.string.your_simplex_contact_address), showCustomModal { it, close -> UserAddressView(it, shareViaProfile = it.currentUser.value!!.addressShared, close = close) }, disabled = stopped, extraPadding = true)
ChatPreferencesItem(showCustomModal, stopped = stopped)
}
SectionDividerSpaced()
@@ -362,15 +361,15 @@ fun ChatLockItem(
Text("v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
}
@Composable fun ProfilePreview(profileOf: NamedChat, size: Dp = 60.dp, color: Color = MaterialTheme.colors.secondaryVariant, stopped: Boolean = false) {
ProfileImage(size = size, image = profileOf.image, color = color)
@Composable fun ProfilePreview(profileOf: NamedChat, size: Dp = 60.dp, iconColor: Color = MaterialTheme.colors.secondaryVariant, textColor: Color = MaterialTheme.colors.onBackground, stopped: Boolean = false) {
ProfileImage(size = size, image = profileOf.image, color = iconColor)
Spacer(Modifier.padding(horizontal = 8.dp))
Column(Modifier.height(size), verticalArrangement = Arrangement.Center) {
Text(
profileOf.displayName,
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Bold,
color = if (stopped) MaterialTheme.colors.secondary else Color.Unspecified,
color = if (stopped) MaterialTheme.colors.secondary else textColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
@@ -378,7 +377,7 @@ fun ChatLockItem(
Text(
profileOf.fullName,
Modifier.padding(vertical = 5.dp),
color = if (stopped) MaterialTheme.colors.secondary else Color.Unspecified,
color = if (stopped) MaterialTheme.colors.secondary else textColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)

View File

@@ -0,0 +1,24 @@
package chat.simplex.app.views.usersettings
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import chat.simplex.app.R
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.onboarding.ReadableText
import chat.simplex.app.views.onboarding.ReadableTextWithLink
@Composable
fun UserAddressLearnMore() {
Column(
Modifier.verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.simplex_address))
ReadableText(R.string.you_can_share_your_address)
ReadableText(R.string.you_wont_lose_your_contacts_if_delete_address)
ReadableText(R.string.you_can_accept_or_reject_connection)
ReadableTextWithLink(R.string.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address")
}
}

View File

@@ -1,13 +1,19 @@
package chat.simplex.app.views.usersettings
import SectionBottomSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
import android.content.res.Configuration
import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -16,103 +22,382 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.app.R
import chat.simplex.app.model.ChatModel
import chat.simplex.app.model.UserContactLinkRec
import chat.simplex.app.TAG
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.chat.ShareAddressButton
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.newchat.QRCode
@Composable
fun UserAddressView(chatModel: ChatModel) {
fun UserAddressView(
chatModel: ChatModel,
viaCreateLinkView: Boolean = false,
shareViaProfile: Boolean = false,
close: () -> Unit
) {
val cxt = LocalContext.current
UserAddressLayout(
userAddress = remember { chatModel.userAddress }.value,
createAddress = {
withApi {
val connReqContact = chatModel.controller.apiCreateUserAddress()
if (connReqContact != null) {
chatModel.userAddress.value = UserContactLinkRec(connReqContact)
val shareViaProfile = remember { mutableStateOf(shareViaProfile) }
var progressIndicator by remember { mutableStateOf(false) }
val onCloseHandler: MutableState<(close: () -> Unit) -> Unit> = remember { mutableStateOf({ _ -> }) }
fun setProfileAddress(on: Boolean) {
progressIndicator = true
withBGApi {
try {
val u = chatModel.controller.apiSetProfileAddress(on)
if (u != null) {
chatModel.updateUser(u)
}
} catch (e: Exception) {
Log.e(TAG, "UserAddressView apiSetProfileAddress: ${e.stackTraceToString()}")
} finally {
progressIndicator = false
}
},
share = { userAddress: String -> shareText(cxt, userAddress) },
acceptRequests = {
chatModel.userAddress.value?.let { address ->
ModalManager.shared.showModal(settings = true) { AcceptRequestsView(chatModel, address) }
}
},
deleteAddress = {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.delete_address__question),
text = generalGetString(R.string.all_your_contacts_will_remain_connected),
confirmText = generalGetString(R.string.delete_verb),
onConfirm = {
withApi {
chatModel.controller.apiDeleteUserAddress()
chatModel.userAddress.value = null
}
}
val userAddress = remember { chatModel.userAddress }
val showLayout = @Composable {
UserAddressLayout(
userAddress = userAddress.value,
shareViaProfile,
onCloseHandler,
createAddress = {
withApi {
progressIndicator = true
val connReqContact = chatModel.controller.apiCreateUserAddress()
if (connReqContact != null) {
chatModel.userAddress.value = UserContactLinkRec(connReqContact)
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.delete_address_with_contacts_question),
text = generalGetString(R.string.add_address_to_your_profile),
confirmText = generalGetString(R.string.share_verb),
onConfirm = {
setProfileAddress(true)
shareViaProfile.value = true
}
)
}
},
destructive = true,
progressIndicator = false
}
},
learnMore = {
ModalManager.shared.showModal {
Column(
Modifier
.fillMaxHeight()
.padding(horizontal = DEFAULT_PADDING),
verticalArrangement = Arrangement.SpaceBetween
) {
UserAddressLearnMore()
}
}
},
share = { userAddress: String -> shareText(cxt, userAddress) },
setProfileAddress = ::setProfileAddress,
deleteAddress = {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.delete_address__question),
text = if (shareViaProfile.value) generalGetString(R.string.all_your_contacts_will_remain_connected_update_sent) else generalGetString(R.string.all_your_contacts_will_remain_connected),
confirmText = generalGetString(R.string.delete_verb),
onConfirm = {
progressIndicator = true
withApi {
val u = chatModel.controller.apiDeleteUserAddress()
if (u != null) {
chatModel.userAddress.value = null
chatModel.updateUser(u)
shareViaProfile.value = false
progressIndicator = false
}
}
},
destructive = true,
)
},
saveAas = { aas: AutoAcceptState, savedAAS: MutableState<AutoAcceptState> ->
withBGApi {
val address = chatModel.controller.userAddressAutoAccept(aas.autoAccept)
if (address != null) {
chatModel.userAddress.value = address
savedAAS.value = aas
}
}
})
}
if (viaCreateLinkView) {
showLayout()
} else {
ModalView(close = { onCloseHandler.value(close) }) {
showLayout()
}
}
if (progressIndicator) {
Box(
Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
if (userAddress.value != null) {
Surface(Modifier.size(50.dp), color = MaterialTheme.colors.background.copy(0.9f), shape = RoundedCornerShape(50)){}
}
CircularProgressIndicator(
Modifier
.padding(horizontal = 2.dp)
.size(30.dp),
color = MaterialTheme.colors.secondary,
strokeWidth = 3.dp
)
}
)
}
}
@Composable
fun UserAddressLayout(
private fun UserAddressLayout(
userAddress: UserContactLinkRec?,
shareViaProfile: MutableState<Boolean>,
onCloseHandler: MutableState<(close: () -> Unit) -> Unit>,
createAddress: () -> Unit,
learnMore: () -> Unit,
share: (String) -> Unit,
acceptRequests: () -> Unit,
deleteAddress: () -> Unit
setProfileAddress: (Boolean) -> Unit,
deleteAddress: () -> Unit,
saveAas: (AutoAcceptState, MutableState<AutoAcceptState>) -> Unit,
) {
Column(
Modifier.verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.your_contact_address), false)
Text(
stringResource(R.string.you_can_share_your_address_anybody_will_be_able_to_connect),
Modifier.padding(bottom = 12.dp),
lineHeight = 22.sp
)
AppBarTitle(stringResource(R.string.simplex_address), false)
Column(
Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceEvenly
) {
if (userAddress == null) {
SimpleButton(stringResource(R.string.create_address), icon = painterResource(R.drawable.ic_qr_code), click = createAddress)
} else {
QRCode(userAddress.connReqContact, Modifier.aspectRatio(1f))
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(vertical = DEFAULT_PADDING)
) {
SimpleButton(
stringResource(R.string.share_link),
icon = painterResource(R.drawable.ic_share),
click = { share(userAddress.connReqContact) })
SimpleButtonIconEnded(
stringResource(R.string.contact_requests),
icon = painterResource(R.drawable.ic_chevron_right),
click = acceptRequests
)
SectionView {
CreateAddressButton(createAddress)
SectionTextFooter(stringResource(R.string.create_address_and_let_people_connect))
}
SectionDividerSpaced(maxBottomPadding = false)
SectionView {
LearnMoreButton(learnMore)
}
LaunchedEffect(Unit) {
onCloseHandler.value = { close -> close() }
}
} else {
val autoAcceptState = remember { mutableStateOf(AutoAcceptState(userAddress)) }
val autoAcceptStateSaved = remember { mutableStateOf(autoAcceptState.value) }
SectionView(stringResource(R.string.address_section_title).uppercase()) {
QRCode(userAddress.connReqContact, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f))
ShareAddressButton { share(userAddress.connReqContact) }
ShareWithContactsButton(shareViaProfile, setProfileAddress)
AutoAcceptToggle(autoAcceptState) { saveAas(autoAcceptState.value, autoAcceptStateSaved) }
LearnMoreButton(learnMore)
}
if (autoAcceptState.value.enable) {
SectionDividerSpaced()
AutoAcceptSection(autoAcceptState, autoAcceptStateSaved, saveAas)
}
SectionDividerSpaced(maxBottomPadding = false)
SectionView {
DeleteAddressButton(deleteAddress)
SectionTextFooter(stringResource(R.string.your_contacts_will_remain_connected))
}
LaunchedEffect(Unit) {
onCloseHandler.value = { close ->
if (autoAcceptState.value == autoAcceptStateSaved.value) close()
else showUnsavedChangesAlert({ saveAas(autoAcceptState.value, autoAcceptStateSaved); close() }, close)
}
}
SimpleButton(
stringResource(R.string.delete_address),
icon = painterResource(R.drawable.ic_delete),
color = Color.Red,
click = deleteAddress
)
}
}
SectionBottomSpacer()
}
}
@Composable
private fun CreateAddressButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(R.drawable.ic_qr_code),
stringResource(R.string.create_simplex_address),
onClick,
iconColor = MaterialTheme.colors.primary,
textColor = MaterialTheme.colors.primary,
)
}
@Composable
private fun LearnMoreButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(R.drawable.ic_info),
stringResource(R.string.learn_more_about_address),
onClick,
)
}
@Composable
fun ShareWithContactsButton(shareViaProfile: MutableState<Boolean>, setProfileAddress: (Boolean) -> Unit) {
PreferenceToggleWithIcon(
stringResource(R.string.share_with_contacts),
painterResource(R.drawable.ic_person),
checked = shareViaProfile.value,
) { on ->
shareViaProfile.value = on
if (on) {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.share_address_with_contacts_question),
text = generalGetString(R.string.profile_update_will_be_sent_to_contacts),
confirmText = generalGetString(R.string.share_verb),
onConfirm = {
setProfileAddress(on)
},
onDismiss = {
shareViaProfile.value = !on
},
onDismissRequest = {
shareViaProfile.value = !on
})
} else {
AlertManager.shared.showAlertDialog(
title = generalGetString(R.string.stop_sharing_address),
text = generalGetString(R.string.profile_update_will_be_sent_to_contacts),
confirmText = generalGetString(R.string.stop_sharing),
onConfirm = {
setProfileAddress(on)
},
onDismiss = {
shareViaProfile.value = !on
},
onDismissRequest = {
shareViaProfile.value = !on
})
}
}
}
@Composable
private fun AutoAcceptToggle(autoAcceptState: MutableState<AutoAcceptState>, saveAas: (AutoAcceptState) -> Unit) {
PreferenceToggleWithIcon(stringResource(R.string.auto_accept_contact), painterResource(R.drawable.ic_check), checked = autoAcceptState.value.enable) {
autoAcceptState.value = if (!it)
AutoAcceptState()
else
AutoAcceptState(it, autoAcceptState.value.incognito, autoAcceptState.value.welcomeText)
saveAas(autoAcceptState.value)
}
}
@Composable
private fun DeleteAddressButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(R.drawable.ic_delete),
stringResource(R.string.delete_address),
onClick,
iconColor = MaterialTheme.colors.error,
textColor = MaterialTheme.colors.error,
)
}
private class AutoAcceptState {
var enable: Boolean = false
private set
var incognito: Boolean = false
private set
var welcomeText: String = ""
private set
constructor(enable: Boolean = false, incognito: Boolean = false, welcomeText: String = "") {
this.enable = enable
this.incognito = incognito
this.welcomeText = welcomeText
}
constructor(contactLink: UserContactLinkRec) {
contactLink.autoAccept?.let { aa ->
enable = true
incognito = aa.acceptIncognito
aa.autoReply?.let { msg ->
welcomeText = msg.text
} ?: run {
welcomeText = ""
}
}
}
val autoAccept: AutoAccept?
get() {
if (enable) {
var autoReply: MsgContent? = null
val s = welcomeText.trim()
if (s != "") {
autoReply = MsgContent.MCText(s)
}
return AutoAccept(incognito, autoReply)
}
return null
}
override fun equals(other: Any?): Boolean {
if (other !is AutoAcceptState) return false
return this.enable == other.enable && this.incognito == other.incognito && this.welcomeText == other.welcomeText
}
override fun hashCode(): Int {
var result = enable.hashCode()
result = 31 * result + incognito.hashCode()
result = 31 * result + welcomeText.hashCode()
return result
}
}
@Composable
private fun AutoAcceptSection(
autoAcceptState: MutableState<AutoAcceptState>,
savedAutoAcceptState: MutableState<AutoAcceptState>,
saveAas: (AutoAcceptState, MutableState<AutoAcceptState>) -> Unit
) {
SectionView(stringResource(R.string.auto_accept_contact).uppercase()) {
AcceptIncognitoToggle(autoAcceptState)
WelcomeMessageEditor(autoAcceptState)
SaveAASButton(autoAcceptState.value == savedAutoAcceptState.value) { saveAas(autoAcceptState.value, savedAutoAcceptState) }
}
}
@Composable
private fun AcceptIncognitoToggle(autoAcceptState: MutableState<AutoAcceptState>) {
PreferenceToggleWithIcon(
stringResource(R.string.accept_contact_incognito_button),
if (autoAcceptState.value.incognito) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy),
if (autoAcceptState.value.incognito) Indigo else MaterialTheme.colors.secondary,
autoAcceptState.value.incognito,
) {
autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText)
}
}
@Composable
private fun WelcomeMessageEditor(autoAcceptState: MutableState<AutoAcceptState>) {
val welcomeText = rememberSaveable { mutableStateOf(autoAcceptState.value.welcomeText) }
TextEditor(welcomeText, Modifier.height(100.dp), placeholder = stringResource(R.string.enter_welcome_message_optional))
LaunchedEffect(welcomeText.value) {
if (welcomeText.value != autoAcceptState.value.welcomeText) {
autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, autoAcceptState.value.incognito, welcomeText.value)
}
}
}
@Composable
private fun SaveAASButton(disabled: Boolean, onClick: () -> Unit) {
SectionItemView(onClick, disabled = disabled) {
Text(stringResource(R.string.save_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary)
}
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
@@ -126,12 +411,26 @@ fun PreviewUserAddressLayoutNoAddress() {
userAddress = null,
createAddress = {},
share = { _ -> },
acceptRequests = {},
deleteAddress = {},
saveAas = { _, _ -> },
setProfileAddress = { _ -> },
learnMore = {},
shareViaProfile = remember { mutableStateOf(false) },
onCloseHandler = remember { mutableStateOf({}) }
)
}
}
private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) {
AlertManager.shared.showAlertDialogStacked(
title = generalGetString(R.string.save_settings_question),
confirmText = generalGetString(R.string.save_auto_accept_settings),
dismissText = generalGetString(R.string.exit_without_saving),
onConfirm = save,
onDismiss = revert,
)
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
@@ -145,8 +444,12 @@ fun PreviewUserAddressLayoutAddressCreated() {
userAddress = UserContactLinkRec("https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D"),
createAddress = {},
share = { _ -> },
acceptRequests = {},
deleteAddress = {},
saveAas = { _, _ -> },
setProfileAddress = { _ -> },
learnMore = {},
shareViaProfile = remember { mutableStateOf(false) },
onCloseHandler = remember { mutableStateOf({}) }
)
}
}

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#FF000000"
android:pathData="M480.02,479.5q-65.52,0 -106.52,-40.98t-41,-106.5q0,-65.52 40.98,-106.52t106.5,-41q65.52,0 106.52,40.98t41,106.5q0,65.52 -40.98,106.52t-106.5,41ZM738,793.5L222,793.5q-23.72,0 -40.61,-16.89Q164.5,759.72 164.5,736v-33.51q0,-37.49 18.75,-63.99t48.43,-40.17Q298,569 358.5,554T480,539q61,0 121,15.25t126.4,44.43q30.82,13.64 49.46,39.85Q795.5,664.75 795.5,702.47v33.77q0,23.45 -16.89,40.36Q761.72,793.5 738,793.5ZM222,736h516v-33.37q0,-16.32 -9.75,-30.97Q718.5,657 705,650q-64,-30.5 -116.29,-42t-108.57,-11.5Q423.5,596.5 370.5,608t-116,42q-14,7 -23.25,21.73T222,702.74L222,736ZM480,422q39,0 64.5,-25.5T570,332q0,-39 -25.5,-64.5T480,242q-39,0 -64.5,25.5T390,332q0,39 25.5,64.5T480,422ZM480,332ZM480,736Z"/>
</vector>

View File

@@ -30,8 +30,7 @@
<string name="smp_servers_preset_add">أضف خوادم محددة مسبقًا</string>
<string name="smp_servers_add_to_another_device">أضف إلى جهاز آخر</string>
<string name="users_delete_all_chats_deleted">سيتم حذف جميع الدردشات والرسائل - لا يمكن التراجع عن هذا!</string>
<string name="network_enable_socks_info">الوصول إلى الخوادم عبر بروكسي SOCKS على المنفذ 9050؟ يجب بدء تشغيل الوكيل قبل تمكين هذا الخيار.</string>
<string name="accept_requests">قبول طلبات</string>
<string name="network_enable_socks_info">الوصول إلى الخوادم عبر بروكسي SOCKS على المنفذ %d؟ يجب بدء تشغيل الوكيل قبل تمكين هذا الخيار.</string>
<string name="smp_servers_add">إضافة خادم …</string>
<string name="network_settings">إعدادات الشبكة المتقدمة</string>
<string name="all_group_members_will_remain_connected">سيبقى جميع أعضاء المجموعة على اتصال.</string>

View File

@@ -9,12 +9,11 @@
<string name="network_settings">Pokročilá nastavení sítě</string>
<string name="accept">Přijmout</string>
<string name="smp_servers_add">Přidat server…</string>
<string name="network_enable_socks_info">Přistupovat k serverům přes SOCKS proxy na portu 9050\? Před povolením této možnosti musí být spuštěna proxy.</string>
<string name="network_enable_socks_info">Přistupovat k serverům přes SOCKS proxy na portu %d\? Před povolením této možnosti musí být spuštěna proxy.</string>
<string name="accept_feature">Přijmout</string>
<string name="allow_your_contacts_to_send_disappearing_messages">Povolte svým kontaktům odesílat mizící zprávy.</string>
<string name="about_simplex_chat">O <xliff:g id="appNameFull">SimpleX Chat</xliff:g></string>
<string name="smp_servers_add_to_another_device">Přidat do jiného zařízení</string>
<string name="accept_requests">Přijímat žádosti</string>
<string name="allow_verb">Povolit</string>
<string name="allow_voice_messages_question">Povolit hlasové zprávy\?</string>
<string name="about_simplex">O SimpleX</string>
@@ -241,8 +240,6 @@
<string name="network_session_mode_entity">Připojení</string>
<string name="core_simplexmq_version">simplexmq: v%s (%2s)</string>
<string name="create_address">Vytvořit adresu</string>
<string name="accept_automatically">Automaticky</string>
<string name="section_title_welcome_message">UVÍTACÍ ZPRÁVA</string>
<string name="save_and_notify_group_members">Uložit a upozornit členy skupiny</string>
<string name="exit_without_saving">Ukončit bez uložení</string>
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">Platforma pro zasílání zpráv a aplikace chránící vaše soukromí a bezpečnost.</string>
@@ -378,7 +375,6 @@
<string name="delete_pending_connection__question">Smazat čekající připojení\?</string>
<string name="icon_descr_settings">Nastavení</string>
<string name="image_descr_qr_code">QR kód</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Váš kontakt může z aplikace naskenovat QR kód.</string>
<string name="if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel">Pokud se nemůžete setkat osobně, ukažte ve <b>videohovoru QR kód</b> nebo sdílejte odkaz.</string>
<string name="scan_code">Skenovat kód</string>
<string name="incorrect_code">Nesprávný bezpečnostní kód!</string>
@@ -396,7 +392,6 @@
<string name="network_use_onion_hosts_required_desc">Pro připojení budou vyžadováni Onion hostitelé.</string>
<string name="update_network_session_mode_question">Aktualizovat režim dopravní izolace\?</string>
<string name="app_version_code">Sestavení aplikace: %s</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Můžete sdílet svou adresu jako odkaz nebo jako QR kód - kdokoli se k vám bude moci připojit. O své kontakty nepřijdete, pokud ji později smažete.</string>
<string name="share_link">Sdílet odkaz</string>
<string name="delete_address">Smazat adresu</string>
<string name="full_name__field">Celé jméno:</string>
@@ -640,7 +635,6 @@
<string name="ensure_ICE_server_address_are_correct_format_and_unique">Ujistěte se, že adresy serverů WebRTC ICE jsou ve správném formátu, oddělené na řádcích a nejsou duplicitní.</string>
<string name="save_servers_button">Uložit</string>
<string name="network_and_servers">Síť a servery</string>
<string name="network_socks_toggle">Použít proxy server SOCKS (port 9050)</string>
<string name="update_onion_hosts_settings_question">Aktualizovat nastavení hostitelů .onion\?</string>
<string name="network_use_onion_hosts">Použít hostitele .onion</string>
<string name="network_use_onion_hosts_prefer">Když bude dostupný</string>
@@ -659,7 +653,6 @@
<string name="core_version">Verze jádra: v%s</string>
<string name="delete_address__question">Smazat adresu\?</string>
<string name="all_your_contacts_will_remain_connected">Všechny vaše kontakty zůstanou připojeny.</string>
<string name="contact_requests">Žádosti o kontakt</string>
<string name="display_name__field">Zobrazované jméno:</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Váš profil je uložen v zařízení a je sdílen pouze s vašimi kontakty. <xliff:g id="appName">SimpleX</xliff:g> servery váš profil vidět nemohou.</string>
<string name="save_preferences_question">Uložit předvolby\?</string>
@@ -957,7 +950,6 @@
<string name="v4_5_italian_interface">Italské rozhraní</string>
<string name="v4_5_italian_interface_descr">Díky uživatelům - překládejte prostřednictvím Weblate!</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">Budete připojeni, jakmile bude zařízení vašeho kontaktu online, vyčkejte prosím nebo se podívejte později!</string>
<string name="your_contact_address">Vaše adresa</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Váš chat profil bude odeslán
\nvašemu kontaktu</string>
<string name="your_chats">Vaše konverzace</string>

View File

@@ -328,7 +328,6 @@
<string name="you_will_be_connected_when_group_host_device_is_online">Sie werden mit der Gruppe verbunden, sobald das Endgerät des Gruppen-Hosts online ist. Bitte warten oder schauen Sie später nochmal nach!</string>
<string name="you_will_be_connected_when_your_connection_request_is_accepted">Sie werden verbunden, sobald Ihre Verbindungsanfrage akzeptiert wird. Bitte warten oder schauen Sie später nochmal nach!</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">Sie werden verbunden, sobald das Endgerät Ihres Kontakts online ist. Bitte warten oder schauen Sie später nochmal nach!</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Zeigen Sie Ihrem Kontakt den QR-Code aus der App zum Scannen.</string>
<string name="if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel">Wenn Sie sich nicht persönlich treffen können, können Sie <b>den QR-Code während eines Videoanrufs anzeigen</b> oder einen Einladungslink über einen anderen Kanal mit Ihrem Kontakt teilen.</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Ihr Chat-Profil wird
\nan Ihren Kontakt gesendet</string>
@@ -345,7 +344,6 @@
<!-- CreateLinkView.kt -->
<string name="create_one_time_link">Link / QR-Code erstellen</string>
<string name="one_time_link">Einmaliger Einladungs-Link</string>
<string name="your_contact_address">Meine Kontaktadresse</string>
<!-- settings - SettingsView.kt -->
<string name="your_settings">Meine Einstellungen</string>
<string name="your_simplex_contact_address">Meine <xliff:g id="appName">SimpleX</xliff:g> Kontaktadresse</string>
@@ -397,9 +395,8 @@
<string name="network_and_servers">Netzwerk &amp; Server</string>
<string name="network_settings">Erweiterte Netzwerkeinstellungen</string>
<string name="network_settings_title">Netzwerkeinstellungen</string>
<string name="network_socks_toggle">SOCKS-Proxy verwenden (Port 9050)</string>
<string name="network_enable_socks">SOCKS-Proxy verwenden?</string>
<string name="network_enable_socks_info">Zugriff auf die Server über SOCKS-Proxy auf Port 9050? Der Proxy muss gestartet werden, bevor diese Option aktiviert wird.</string>
<string name="network_enable_socks_info">Zugriff auf die Server über SOCKS-Proxy auf Port %d? Der Proxy muss gestartet werden, bevor diese Option aktiviert wird.</string>
<string name="network_disable_socks">Direkte Internetverbindung verwenden?</string>
<string name="network_disable_socks_info">Wenn Sie dies bestätigen, können die Messaging-Server Ihre IP-Adresse und Ihren Provider sehen und mit welchen Servern Sie sich verbinden.</string>
<string name="update_onion_hosts_settings_question">Einstellung für .onion-Hosts aktualisieren?</string>
@@ -418,14 +415,8 @@
<string name="create_address">Adresse erstellen</string>
<string name="delete_address__question">Adresse löschen?</string>
<string name="all_your_contacts_will_remain_connected">Alle Ihre Kontakte bleiben verbunden.</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Sie können Ihre Adresse als Link oder als QR-Code teilen Jede Person kann sich darüber mit Ihnen verbinden. Sie werden Ihre mit dieser Adresse verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen.</string>
<string name="share_link">Link teilen</string>
<string name="delete_address">Adresse löschen</string>
<!-- AcceptRequestsView.kt -->
<string name="contact_requests">Kontaktanfragen</string>
<string name="accept_requests">Anfragen annehmen</string>
<string name="accept_automatically">Automatisch</string>
<string name="section_title_welcome_message">Begrüßungsmeldung</string>
<!-- User profile details - UserProfileView.kt -->
<string name="display_name__field">Angezeigter Name:</string>
<string name="full_name__field">"Vollständiger Name:</string>

View File

@@ -33,7 +33,7 @@
<string name="accept_contact_incognito_button">Aceptar incógnito</string>
<string name="clear_chat_warning">Se eliminarán todos los mensajes SOLO para tí. ¡No puede deshacerse!</string>
<string name="smp_servers_add">Añadir servidor…</string>
<string name="network_enable_socks_info">¿Acceder a los servidores a través del proxy SOCKS en el puerto 9050\? El proxy debe iniciarse antes de activar esta opción.</string>
<string name="network_enable_socks_info">¿Acceder a los servidores a través del proxy SOCKS en el puerto %d\? El proxy debe iniciarse antes de activar esta opción.</string>
<string name="all_your_contacts_will_remain_connected">Todos tus contactos permanecerán conectados.</string>
<string name="appearance_settings">Apariencia</string>
<string name="app_version_title">Versión</string>
@@ -75,8 +75,6 @@
<string name="about_simplex_chat">Sobre <xliff:g id="appNameFull">SimpleX Chat</xliff:g></string>
<string name="smp_servers_add_to_another_device">Añadir a otro dispositivo</string>
<string name="app_version_name">Versión de la aplicación: v%s</string>
<string name="accept_requests">Aceptar solicitudes</string>
<string name="accept_automatically">Automáticamente</string>
<string name="icon_descr_asked_to_receive">Solicita recibir la imagen</string>
<string name="impossible_to_recover_passphrase"><b>Ten en cuenta</b>: NO podrás recuperar o cambiar la contraseña si la pierdes.</string>
<string name="both_you_and_your_contact_can_send_voice">Tanto tú como tu contacto podéis enviar mensajes de voz.</string>
@@ -254,7 +252,6 @@
\nContraseña</string>
<string name="contribute">Contribuye</string>
<string name="core_version">Core versión: v%s</string>
<string name="contact_requests">Solicitud del contacto</string>
<string name="delete_image">Eliminar imagen</string>
<string name="edit_image">Editar imagen</string>
<string name="settings_section_title_chats">CHATS</string>
@@ -741,7 +738,6 @@
<string name="share_verb">Compartir</string>
<string name="icon_descr_sent_msg_status_unauthorized_send">envío no autorizado</string>
<string name="set_contact_name">Escribe un nombre para el contacto</string>
<string name="network_socks_toggle">Usar proxy SOCKS (puerto 9050)</string>
<string name="unknown_error">Error desconocido</string>
<string name="member_role_will_be_changed_with_notification">El rol cambiará a \"%s\". Se notificará a todos los miembros del grupo.</string>
<string name="v4_2_security_assessment_desc">La seguridad de SimpleX Chat fue auditada por Trail of Bits.</string>
@@ -858,7 +854,6 @@
<string name="description_via_one_time_link">mediante enlace de un uso</string>
<string name="your_chats">Tus chats</string>
<string name="voice_message_send_text">Mensaje de voz…</string>
<string name="your_contact_address">Mi dirección de contacto</string>
<string name="icon_descr_video_off">Desactivar vídeo</string>
<string name="icon_descr_video_on">Activar vídeo</string>
<string name="wrong_passphrase">Contraseña de base de datos incorrecta</string>
@@ -888,7 +883,6 @@
<string name="failed_to_create_user_duplicate_desc">Tienes un perfil de chat con el mismo nombre mostrado. Debes elegir otro nombre.</string>
<string name="you_can_also_connect_by_clicking_the_link">También puedes conectarte haciendo clic en el enlace. Si se abre en el navegador, haz clic en <b>Abrir en aplicación móvil</b>.</string>
<string name="you_can_connect_to_simplex_chat_founder">Puedes <font color="#0088ff">ponerte en contacto con los desarrolladores de <xliff:g id="appNameFull">SimpleX Chat</xliff:g> para consultas y para recibir actualizaciones</font>.</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo. Si lo eliminas más tarde tus contactos no se perderán.</string>
<string name="observer_cant_send_message_title">¡No puedes enviar mensajes!</string>
<string name="you_can_use_markdown_to_format_messages__prompt">Puedes usar la sintaxis markdown para dar formato a los mensajes:</string>
<string name="you_must_use_the_most_recent_version_of_database">Debes usar la versión más reciente de tu base de datos ÚNICAMENTE en un dispositivo, de lo contrario podrías dejar de recibir mensajes de algunos contactos.</string>
@@ -923,7 +917,6 @@
<string name="you_accepted_connection">Has aceptado la conexión</string>
<string name="you_invited_your_contact">Has invitado a tu contacto</string>
<string name="you_will_be_connected_when_group_host_device_is_online">Te conectarás al grupo cuando el dispositivo del anfitrión esté en línea, por favor espera o compruébalo más tarde.</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Tu contacto puede escanear el código QR desde la aplicación.</string>
<string name="your_settings">Mi configuración</string>
<string name="your_SMP_servers">Tus servidores SMP</string>
<string name="you_control_your_chat">¡Tú controlas tu chat!</string>
@@ -972,7 +965,6 @@
<string name="your_simplex_contact_address">Mi dirección de contacto <xliff:g id="appName">SimpleX</xliff:g></string>
<string name="smp_servers_your_server">Tu servidor</string>
<string name="smp_servers_your_server_address">Dirección de tu servidor</string>
<string name="section_title_welcome_message">MENSAJE DE BIENVENIDA</string>
<string name="your_current_profile">Tu perfil actual</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Tu perfil se almacena en tu dispositivo y sólo se comparte con tus contactos. Los servidores <xliff:g id="appName">SimpleX</xliff:g> no pueden ver tu perfil.</string>
<string name="language_system">Sistema</string>

View File

@@ -240,7 +240,6 @@
<string name="this_QR_code_is_not_a_link">Ce code QR n\'est pas un lien !</string>
<string name="you_will_be_connected_when_your_connection_request_is_accepted">Vous serez connecté·e lorsque votre demande de connexion sera acceptée, veuillez attendre ou vérifier plus tard !</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">Vous serez connecté·e lorsque l\'appareil de votre contact sera en ligne, veuillez attendre ou vérifier plus tard !</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Votre contact peut scanner le code QR depuis l\'app.</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Votre profil de chat sera envoyé
\nà votre contact</string>
<string name="share_invitation_link">Partager le lien d\'invitation</string>
@@ -260,7 +259,6 @@
<string name="connect_via_link">Se connecter via un lien</string>
<string name="clear_verification">Retirer la vérification</string>
<string name="one_time_link">Lien d\'invitation unique</string>
<string name="your_contact_address">Votre adresse de contact</string>
<string name="scan_code">Scanner le code</string>
<string name="incorrect_code">Code de sécurité incorrect !</string>
<string name="security_code">Code de sécurité</string>
@@ -326,7 +324,7 @@
<string name="use_simplex_chat_servers__question">Utiliser les serveurs <xliff:g id="appNameFull">SimpleX Chat</xliff:g> \?</string>
<string name="smp_servers_delete_server">Supprimer le serveur</string>
<string name="ensure_ICE_server_address_are_correct_format_and_unique">Assurez-vous que les adresses des serveurs WebRTC ICE sont au bon format et ne sont pas dupliquées, un par ligne.</string>
<string name="network_enable_socks_info">Accéder aux serveurs via un proxy SOCKS sur le port 9050 \? Le proxy doit être démarré avant d\'activer cette option.</string>
<string name="network_enable_socks_info">Accéder aux serveurs via un proxy SOCKS sur le port %d \? Le proxy doit être démarré avant d\'activer cette option.</string>
<string name="network_use_onion_hosts">Utiliser les hôtes .onions</string>
<string name="network_use_onion_hosts_prefer_desc_in_alert">Les hôtes .onion seront utilisés lorsqu\'ils sont disponibles.</string>
<string name="network_use_onion_hosts_required_desc_in_alert">Les hôtes .onion seront nécessaires pour la connexion.</string>
@@ -352,7 +350,6 @@
<string name="configure_ICE_servers">Configurer les serveurs ICE</string>
<string name="network_settings">Paramètres réseau avancés</string>
<string name="network_settings_title">Paramètres réseau</string>
<string name="network_socks_toggle">Utiliser un proxy SOCKS (port 9050)</string>
<string name="network_enable_socks">Utiliser un proxy SOCKS \?</string>
<string name="network_disable_socks">Utiliser une connexion Internet directe \?</string>
<string name="network_disable_socks_info">Si vous confirmez, les serveurs de messagerie seront en mesure de voir votre adresse IP, votre fournisseur ainsi que les serveurs auxquels vous vous connectez.</string>
@@ -361,7 +358,6 @@
<string name="network_use_onion_hosts_prefer_desc">Les hôtes .onion seront utilisés lorsqu\'ils sont disponibles.</string>
<string name="appearance_settings">Apparence</string>
<string name="create_address">Créer une adresse</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Vous pouvez partager votre adresse sous forme de lien ou de code QR - n\'importe qui pourra se connecter à vous. Vous ne perdrez pas vos contacts si vous la supprimez par la suite.</string>
<string name="your_current_profile">Votre profil de chat</string>
<string name="edit_image">Modifier l\'image</string>
<string name="save_and_notify_contacts">Sauvegarder et notifier les contacts</string>
@@ -433,10 +429,6 @@
<string name="all_your_contacts_will_remain_connected">Tous vos contacts resteront connectés.</string>
<string name="share_link">Partager le lien</string>
<string name="delete_address">Supprimer l\'adresse</string>
<string name="contact_requests">Demandes de contact</string>
<string name="accept_requests">Accepter les demandes</string>
<string name="accept_automatically">Automatiquement</string>
<string name="section_title_welcome_message">MESSAGE DE BIENVENUE</string>
<string name="display_name__field">Nom affiché :</string>
<string name="full_name__field">Nom complet :</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Votre profil est stocké sur votre appareil et partagé uniquement avec vos contacts. Les serveurs <xliff:g id="appName">SimpleX</xliff:g> ne peuvent pas voir votre profil.</string>

View File

@@ -10,7 +10,6 @@
<string name="above_then_preposition_continuation">ऊपर,तब:</string>
<string name="accept_contact_button">स्वीकार करना</string>
<string name="connect_button">जुडिये</string>
<string name="your_contact_address">आपका संपर्क पता</string>
<string name="smp_servers_add_to_another_device">दूसरे उपकरण में जोड़ें</string>
<string name="bold">निडर</string>
<string name="answer_call">कॉल का उत्तर दें</string>
@@ -35,7 +34,6 @@
<string name="accept_connection_request__question">संबंध अनुरोध स्वीकार करें\?</string>
<string name="callstatus_accepted">स्वीकृत कॉल</string>
<string name="accept_contact_incognito_button">गुप्त स्वीकार करें</string>
<string name="accept_requests">निवेदन स्वीकार करो</string>
<string name="smp_servers_preset_add">पूर्वनिर्धारित सर्वर जोड़ें</string>
<string name="users_add">प्रोफ़ाइल जोड़ें</string>
<string name="smp_servers_add">सर्वर जोड़े…</string>
@@ -67,7 +65,6 @@
<string name="chat_preferences_you_allow">आप आज्ञा दें</string>
<string name="welcome">स्वागत!</string>
<string name="la_notice_turn_on">चालू करो</string>
<string name="section_title_welcome_message">स्वागत संदेश</string>
<string name="unknown_message_format">अज्ञात संदेश प्रारूप</string>
<string name="personal_welcome">स्वागत <xliff:g>%1$s</xliff:g>!</string>
<string name="callstate_starting">शुरुआत</string>
@@ -235,7 +232,6 @@
<string name="chat_console">चैट कंसोल</string>
<string name="all_your_contacts_will_remain_connected">आपके सभी संपर्क जुड़े रहेंगे।</string>
<string name="network_session_mode_user">चैट प्रोफ़ाइल</string>
<string name="contact_requests">संपर्क अनुरोध</string>
<string name="create_profile_button">बनाएं</string>
<string name="callstatus_error">कॉल त्रुटि</string>
<string name="callstatus_in_progress">कॉल चल रहा है</string>

View File

@@ -239,8 +239,7 @@
<string name="allow_disappearing_messages_only_if">Consenti i messaggi a tempo solo se il tuo contatto li consente.</string>
<string name="allow_to_delete_messages">Permetti di eliminare irreversibilmente i messaggi inviati.</string>
<string name="allow_your_contacts_to_send_disappearing_messages">Permetti ai tuoi contatti di inviare messaggi a tempo.</string>
<string name="accept_requests">Accetta le richieste</string>
<string name="network_enable_socks_info">Accedere ai server via proxy SOCKS sulla porta 9050\? Il proxy deve essere avviato prima di attivare questa opzione.</string>
<string name="network_enable_socks_info">Accedere ai server via proxy SOCKS sulla porta %d\? Il proxy deve essere avviato prima di attivare questa opzione.</string>
<string name="v4_3_improved_server_configuration_desc">Aggiungi server scansionando codici QR.</string>
<string name="all_group_members_will_remain_connected">Tutti i membri del gruppo resteranno connessi.</string>
<string name="allow_irreversible_message_deletion_only_if">Consenti l\'eliminazione irreversibile dei messaggi solo se il contatto la consente a te.</string>
@@ -284,7 +283,6 @@
<string name="snd_conn_event_switch_queue_phase_changing">cambio indirizzo…</string>
<string name="chat_is_stopped">Chat fermata</string>
<string name="group_member_status_introduced">connessione (presentato)</string>
<string name="contact_requests">Richieste del contatto</string>
<string name="connection_request_sent">Richiesta di connessione inviata!</string>
<string name="delete_link_question">Eliminare il link\?</string>
<string name="delete_link">Elimina link</string>
@@ -339,7 +337,6 @@
<string name="how_to">Come si fa</string>
<string name="how_to_use_your_servers">Come usare i tuoi server</string>
<string name="enter_one_ICE_server_per_line">Server ICE (uno per riga)</string>
<string name="accept_automatically">Automaticamente</string>
<string name="bold">grassetto</string>
<string name="callstatus_ended">chiamata terminata <xliff:g id="duration" example="01:15">%1$s</xliff:g></string>
<string name="callstatus_error">errore di chiamata</string>
@@ -575,7 +572,6 @@
<string name="you_invited_your_contact">Hai invitato il contatto</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Il tuo profilo di chat verrà inviato
\nal tuo contatto</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Il tuo contatto può scansionare il codice QR dall\'app.</string>
<string name="alert_text_connection_pending_they_need_to_be_online_can_delete_and_retry">Il tuo contatto deve essere in linea per completare la connessione.
\nPuoi annullare questa connessione e rimuovere il contatto (e riprovare più tardi con un link nuovo).</string>
<string name="you_will_be_connected_when_your_connection_request_is_accepted">Verrai connesso/a quando la tua richiesta di connessione verrà accettata, attendi o controlla più tardi!</string>
@@ -612,7 +608,6 @@
<string name="smp_servers_use_server">Usa il server</string>
<string name="you_can_also_connect_by_clicking_the_link">Puoi anche connetterti cliccando il link. Se si apre nel browser, clicca il pulsante <b>Apri nell\'app mobile</b>.</string>
<string name="your_profile_will_be_sent">Il tuo profilo di chat verrà inviato al tuo contatto</string>
<string name="your_contact_address">Il tuo indirizzo di contatto</string>
<string name="smp_servers_your_server">Il tuo server</string>
<string name="smp_servers_your_server_address">L\'indirizzo del tuo server</string>
<string name="your_simplex_contact_address">Il tuo indirizzo di contatto di <xliff:g id="appName">SimpleX</xliff:g></string>
@@ -638,11 +633,9 @@
<string name="network_disable_socks">Usare una connessione internet diretta\?</string>
<string name="network_use_onion_hosts">Usa gli host .onion</string>
<string name="network_enable_socks">Usare il proxy SOCKS\?</string>
<string name="network_socks_toggle">Usa il proxy SOCKS (porta 9050)</string>
<string name="use_simplex_chat_servers__question">Usare i server di <xliff:g id="appNameFull">SimpleX Chat</xliff:g>\?</string>
<string name="using_simplex_chat_servers">Stai usando i server di <xliff:g id="appNameFull">SimpleX Chat</xliff:g>.</string>
<string name="network_use_onion_hosts_prefer">Quando disponibili</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Puoi condividere il tuo indirizzo come link o come codice QR: chiunque potrà connettersi a te. Non perderai i tuoi contatti se in seguito lo elimini.</string>
<string name="your_ICE_servers">I tuoi server ICE</string>
<string name="your_SMP_servers">I tuoi server SMP</string>
<string name="italic">corsivo</string>
@@ -662,7 +655,6 @@
<string name="callstate_waiting_for_answer">in attesa di risposta…</string>
<string name="callstate_waiting_for_confirmation">in attesa di conferma…</string>
<string name="we_do_not_store_contacts_or_messages_on_servers">Non memorizziamo nessuno dei tuoi contatti o messaggi (una volta recapitati) sui server.</string>
<string name="section_title_welcome_message">MESSAGGIO DI BENVENUTO</string>
<string name="you_can_use_markdown_to_format_messages__prompt">Puoi usare il markdown per formattare i messaggi:</string>
<string name="you_control_your_chat">Sei tu a controllare la tua chat!</string>
<string name="your_current_profile">Il tuo profilo attuale</string>

View File

@@ -22,7 +22,7 @@
<string name="smp_servers_add_to_another_device">別の端末に追加</string>
<string name="users_add">プロフィールを追加</string>
<string name="smp_servers_add">サーバを追加…</string>
<string name="network_enable_socks_info">SOCKSプロキシ(ポート9050)経由で接続しますか?(※設定する前にプロキシ起動が必要※)</string>
<string name="network_enable_socks_info">SOCKSプロキシ(ポート%d)経由で接続しますか?(※設定する前にプロキシ起動が必要※)</string>
<string name="users_delete_all_chats_deleted">全チャットとメッセージが削除されます(※元に戻せません※)</string>
<string name="allow_your_contacts_to_send_voice_messages">送信相手からの音声メッセージを許可する。</string>
<string name="both_you_and_your_contact_can_send_voice">あなたと連絡相手が音声メッセージを送信できます。</string>
@@ -31,8 +31,6 @@
<string name="attach">添付する</string>
<string name="app_version_code">アプリ・ビルド番号: %s</string>
<string name="all_your_contacts_will_remain_connected">あなたの連絡先が繋がったまま継続します。</string>
<string name="accept_requests">リクエストを承諾</string>
<string name="accept_automatically">自動的に</string>
<string name="icon_descr_audio_on">音声オン</string>
<string name="integrity_msg_bad_hash">メッセージのハッシュ値問題</string>
<string name="integrity_msg_bad_id">メッセージIDの問題</string>
@@ -227,7 +225,6 @@
<string name="contact_preferences">連絡先の設定</string>
<string name="status_contact_has_no_e2e_encryption">連絡先はエンドツーエンド暗号化がありません。</string>
<string name="alert_title_contact_connection_pending">連絡先がまだ繋がってません!</string>
<string name="contact_requests">連絡先のリクエスト</string>
<string name="icon_descr_context">追加情報アイコン</string>
<string name="network_use_onion_hosts_prefer_desc">オニオンのホストが利用可能時に使われます。</string>
<string name="network_use_onion_hosts_no_desc">オニオンのホストが使われません。</string>
@@ -729,7 +726,6 @@
<string name="this_link_is_not_a_valid_connection_link">このリンクは有効な接続リンクではありません!</string>
<string name="this_QR_code_is_not_a_link">このQRコードはリンクではありません</string>
<string name="you_will_be_connected_when_group_host_device_is_online">グループのホスト端末がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">連絡相手がアプリからQRコードを読み込めます。</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">連絡先がオンラインになったら、接続されます。後でチェックするか、しばらくお待ちください。</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">あなたのチャットプロフィールが
\n連絡相手に送られます。</string>
@@ -739,7 +735,6 @@
<string name="scan_code_from_contacts_app">連絡相手のアプリからセキュリティコードを読み込む</string>
<string name="chat_lock">SimpleXロック</string>
<string name="is_not_verified">%s は未認証</string>
<string name="your_contact_address">あなたのチャットアドレス</string>
<string name="your_settings">あなたの設定</string>
<string name="smp_servers_test_server">テストサーバ</string>
<string name="smp_servers_save">サーバを保存</string>
@@ -753,7 +748,6 @@
<string name="your_ICE_servers">あなたのICEサーバ</string>
<string name="network_disable_socks">直接にインタネットに繋がりますか?</string>
<string name="network_enable_socks">SOCKSプロキシを使いますか</string>
<string name="network_socks_toggle">SOCKSプロキシ (ポート9050) を使う</string>
<string name="update_onion_hosts_settings_question">.onionのホスト設定を更新しますか</string>
<string name="network_use_onion_hosts">.onionホストを使う</string>
<string name="network_use_onion_hosts_prefer">利用可能時に</string>
@@ -890,8 +884,6 @@
<string name="using_simplex_chat_servers"><xliff:g id="appNameFull">SimpleX Chat</xliff:g>を使っています。</string>
<string name="share_link">リンクを送る</string>
<string name="core_simplexmq_version">simplexmq: バージョン%s (%2s)</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">あなたと繋がるリンク、またはQRコードを共有できます。誰でも接続できます。後で削除しても、連絡先がそのままのこります。</string>
<string name="section_title_welcome_message">歓迎メッセージ</string>
<string name="callstate_waiting_for_answer">応答待ち…</string>
<string name="callstate_waiting_for_confirmation">確認待ち…</string>
<string name="first_platform_without_user_ids">世界初のユーザーIDのないプラットフォーム設計も元からプライベート</string>

View File

@@ -52,13 +52,10 @@
<string name="network_settings">고급 네트워크 설정</string>
<string name="network_session_mode_user">채팅 프로필</string>
<string name="network_session_mode_entity">연결</string>
<string name="accept_requests">요청 수락</string>
<string name="app_version_code">앱 빌드 : %s</string>
<string name="appearance_settings">외관</string>
<string name="app_version_title">앱 버전</string>
<string name="app_version_name">앱 버전 : v%s</string>
<string name="accept_automatically">자동</string>
<string name="contact_requests">대화 상대의 요청</string>
<string name="core_version">코어 버전 : v%s</string>
<string name="callstatus_accepted">전화 받음</string>
<string name="bold">굵게</string>
@@ -143,7 +140,7 @@
<string name="accept_call_on_lock_screen">응답</string>
<string name="accept_connection_request__question">연결 요청을 수락할까요\?</string>
<string name="accept_feature">수락</string>
<string name="network_enable_socks_info">SOCKS 프록시(포트 9050)를 통해 서버에 액세스할까요\? 이 설정을 활성화하기 전에 프록시를 시작해야 해요.</string>
<string name="network_enable_socks_info">SOCKS 프록시(포트 %d)를 통해 서버에 액세스할까요\? 이 설정을 활성화하기 전에 프록시를 시작해야 해요.</string>
<string name="smp_servers_add_to_another_device">다른 기기에 추가</string>
<string name="v4_3_improved_server_configuration_desc">QR 코드 스캔으로 서버 추가</string>
<string name="button_add_welcome_message">환영 메시지 추가</string>
@@ -670,7 +667,6 @@
<string name="mark_unread">읽지 않음으로 표시</string>
<string name="mute_chat">음소거</string>
<string name="markdown_in_messages">메시지에 사용된 마크다운</string>
<string name="network_socks_toggle">SOCKS 프록시 사용 (포트 9050)</string>
<string name="network_disable_socks">직접적인 인터넷 연결을 사용할까요\?</string>
<string name="network_enable_socks">SOCKS 프록시를 사용할까요\?</string>
<string name="network_disable_socks_info">설정하면 메시징 서버에서 내 IP 주소와 내가 연결하려는 서버를 볼 수 있어요.</string>
@@ -828,12 +824,10 @@
<string name="send_live_message_desc">라이브 메시지 보내기 - 입력 과정을 실시간으로 상대에게 보여줘요.</string>
<string name="send_verb">보내기</string>
<string name="share_invitation_link">초대 링크 공유</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">연락하고자 하는 사람이 앱에서 QR 코드를 스캔할 수 있어요.</string>
<string name="security_code">보안 코드</string>
<string name="smp_servers_scan_qr">서버 QR코드 스캔</string>
<string name="smp_servers_test_some_failed">일부 서버가 테스트에 통과하지 못했습니다 :</string>
<string name="smp_servers_test_failed">서버 테스트 실패!</string>
<string name="section_title_welcome_message">환영 메시지</string>
<string name="share_link">링크 공유</string>
<string name="show_call_on_lock_screen">표시하기</string>
<string name="select_contacts">연락처 선택</string>

View File

@@ -12,7 +12,6 @@
<string name="app_version_title">Programėlės versija</string>
<string name="app_version_name">Programėlės versija: v%s</string>
<string name="app_version_code">Programėlės darinys: %s</string>
<string name="accept_automatically">Automatiškai</string>
<string name="callstatus_calling">skambinama…</string>
<string name="callstatus_error">skambučio klaida</string>
<string name="call_already_ended">Skambutis jau baigtas!</string>
@@ -279,7 +278,6 @@
<string name="use_camera_button">Naudoti kamerą</string>
<string name="thank_you_for_installing_simplex">Dėkojame, kad įdiegėte <xliff:g id="appNameFull">SimpleX Chat</xliff:g>!</string>
<string name="smp_servers_use_server">Naudoti serverį</string>
<string name="network_socks_toggle">Naudoti SOCKS įgaliotąjį serverį (prievadas 9050)</string>
<string name="network_enable_socks">Naudoti SOCKS įgaliotąjį serverį\?</string>
<string name="core_simplexmq_version">simplexmq: v%s (%2s)</string>
<string name="share_link">Bendrinti nuorodą</string>

View File

@@ -16,7 +16,7 @@
<string name="icon_descr_asked_to_receive">Gevraagd om de afbeelding te ontvangen</string>
<string name="change_verb">Wijziging</string>
<string name="network_settings">Geavanceerde netwerk instellingen</string>
<string name="network_enable_socks_info">Toegang tot de servers via SOCKS proxy op poort 9050\? De proxy moet worden gestart voordat u deze optie inschakelt.</string>
<string name="network_enable_socks_info">Toegang tot de servers via SOCKS proxy op poort %d\? De proxy moet worden gestart voordat u deze optie inschakelt.</string>
<string name="alert_title_cant_invite_contacts">Kan geen contacten uitnodigen!</string>
<string name="allow_direct_messages">Sta het verzenden van directe berichten naar leden toe.</string>
<string name="allow_to_delete_messages">Sta toe om verzonden berichten onomkeerbaar te verwijderen.</string>
@@ -75,7 +75,6 @@
<string name="about_simplex">Over SimpleX</string>
<string name="about_simplex_chat">Over <xliff:g id="appNameFull">SimpleX Chat</xliff:g></string>
<string name="above_then_preposition_continuation">hier boven, dan:</string>
<string name="accept_requests">Verzoeken accepteren</string>
<string name="users_delete_all_chats_deleted">Alle gesprekken en berichten worden verwijderd, dit kan niet ongedaan worden gemaakt!</string>
<string name="clear_chat_warning">Alle berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! De berichten worden ALLEEN voor jou verwijderd.</string>
<string name="allow_disappearing_messages_only_if">Sta verdwijnende berichten alleen toe als uw contactpersoon dit toestaat.</string>
@@ -96,7 +95,6 @@
<string name="app_version_name">App versie: v%s</string>
<string name="network_session_mode_user_description">Er wordt een aparte TCP-verbinding (en SOCKS-referentie) gebruikt <b> voor elk chat profiel dat je in de app hebt </b>.</string>
<string name="audio_call_no_encryption">audio oproep (niet e2e versleuteld)</string>
<string name="accept_automatically">Automatisch</string>
<string name="notifications_mode_service_desc">Achtergrondservice is altijd actief, meldingen worden weergegeven zodra de berichten beschikbaar zijn.</string>
<string name="add_new_contact_to_create_one_time_QR_code"><b>Nieuw contact toevoegen</b>: om uw eenmalige QR-code voor uw contact te maken.</string>
<string name="icon_descr_call_ended">Oproep beëindigd</string>
@@ -210,7 +208,6 @@
<string name="create_one_time_link">Maak een eenmalige uitnodiging link</string>
<string name="colored">gekleurd</string>
<string name="callstatus_connecting">Oproep verbinden…</string>
<string name="contact_requests">Contact verzoeken</string>
<string name="create_profile_button">Maak</string>
<string name="create_profile">Maak een profiel aan</string>
<string name="delete_address">Adres verwijderen</string>
@@ -625,10 +622,8 @@
<string name="icon_descr_simplex_team"><xliff:g id="appName">SimpleX</xliff:g>-Team</string>
<string name="this_QR_code_is_not_a_link">Deze QR-code is geen link!</string>
<string name="this_link_is_not_a_valid_connection_link">Deze link is geen geldige link!</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Uw contactpersoon kan de QR-code vanuit de app scannen.</string>
<string name="share_invitation_link">Uitnodiging link delen</string>
<string name="scan_code">Code scannen</string>
<string name="your_contact_address">Uw contact adres</string>
<string name="your_settings">Uw instellingen</string>
<string name="share_link">Deel link</string>
<string name="you_control_your_chat">Jij beheert je gesprek!</string>
@@ -725,10 +720,8 @@
<string name="smp_servers_your_server_address">Uw server adres</string>
<string name="smp_servers_your_server">Uw server</string>
<string name="network_session_mode_transport_isolation">Transport isolation</string>
<string name="network_socks_toggle">SOCKS-proxy gebruiken (poort 9050)</string>
<string name="save_preferences_question">Voorkeuren opslaan\?</string>
<string name="save_and_notify_contact">Opslaan en Contact melden</string>
<string name="section_title_welcome_message">WELKOMST BERICHT</string>
<string name="your_current_profile">Je huidige profiel</string>
<string name="save_and_notify_contacts">Opslaan en Contacten melden</string>
<string name="save_and_notify_group_members">Opslaan en Groepsleden melden</string>
@@ -927,7 +920,6 @@
<string name="use_simplex_chat_servers__question"><xliff:g id="appNameFull">SimpleX Chat</xliff:g> servers gebruiken\?</string>
<string name="voice_messages_are_prohibited">Spraak berichten zijn verboden in deze groep.</string>
<string name="personal_welcome">Welkom <xliff:g>%1$s</xliff:g>!</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">U kunt uw adres delen als een link of als een QR-code. Iedereen kan verbinding met u maken. U verliest uw contacten niet als u deze later verwijdert.</string>
<string name="you_can_start_chat_via_setting_or_by_restarting_the_app">U kunt de chat starten via app Instellingen / Database of door de app opnieuw op te starten.</string>
<string name="snd_conn_event_switch_queue_phase_completed_for_member">je hebt het adres gewijzigd voor %s</string>
<string name="snd_group_event_member_deleted">je hebt <xliff:g id="member profile" example="alice (Alice)">%1$s</xliff:g> verwijderd</string>

View File

@@ -290,7 +290,6 @@
<string name="your_chat_profile_will_be_sent_to_your_contact">Twój profil czatu zostanie wysłany
\ndo Twojego kontaktu</string>
<string name="your_profile_will_be_sent">Twój profil czatu zostanie wysłany do Twojego kontaktu</string>
<string name="your_contact_address">Twój adres kontaktowy</string>
<string name="you_will_be_connected_when_group_host_device_is_online">Zostaniesz połączony do grupy, gdy urządzenie gospodarza grupy będzie online, proszę czekać lub sprawdzić później!</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">Zostaniesz połączony, gdy urządzenie Twojego kontaktu będzie online, proszę czekać lub sprawdzić później!</string>
<string name="smp_servers_preset_add">Dodaj gotowe serwery</string>
@@ -332,7 +331,7 @@
<string name="smp_servers_your_server_address">Twój adres serwera</string>
<string name="your_simplex_contact_address">Twój adres kontaktowy <xliff:g id="appName">SimpleX</xliff:g></string>
<string name="contribute">Przyczyń się</string>
<string name="network_enable_socks_info">Uzyskiwać dostęp do serwerów przez SOCKS proxy na porcie 9050\? Proxy musi zostać uruchomione przed włączeniem tej opcji.</string>
<string name="network_enable_socks_info">Uzyskiwać dostęp do serwerów przez SOCKS proxy na porcie %d\? Proxy musi zostać uruchomione przed włączeniem tej opcji.</string>
<string name="network_settings">Zaawansowane ustawienia sieci</string>
<string name="app_version_code">Kompilacja aplikacji: %s</string>
<string name="appearance_settings">Wygląd</string>
@@ -363,11 +362,7 @@
<string name="network_disable_socks">Użyć bezpośredniego połączenia z Internetem\?</string>
<string name="network_use_onion_hosts">Użyj hostów .onion</string>
<string name="network_enable_socks">Użyć proxy SOCKS\?</string>
<string name="network_socks_toggle">Użyj proxy SOCKS (port 9050)</string>
<string name="accept_requests">Akceptuj prośby</string>
<string name="all_your_contacts_will_remain_connected">Wszystkie Twoje kontakty pozostaną połączone.</string>
<string name="accept_automatically">Automatycznie</string>
<string name="contact_requests">Prośby kontaktu</string>
<string name="create_address">Utwórz adres</string>
<string name="developer_options">ID bazy danych i opcja izolacji transportu.</string>
<string name="delete_address">Usuń adres</string>
@@ -387,8 +382,6 @@
<string name="show_dev_options">Pokaż:</string>
<string name="show_developer_options">Pokaż opcje dewelopera</string>
<string name="core_simplexmq_version">simplexmq: v%s (%2s)</string>
<string name="section_title_welcome_message">WIADOMOŚĆ POWITALNA</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Możesz udostępnić swój adres jako link lub jako kod QR - każdy będzie mógł się z Tobą połączyć. Nie stracisz swoich kontaktów, jeśli później go usuniesz.</string>
<string name="your_current_profile">Twój obecny profil</string>
<string name="confirm_password">Potwierdź hasło</string>
<string name="create_profile">Utwórz profil</string>
@@ -1041,7 +1034,6 @@
<string name="you_must_use_the_most_recent_version_of_database">Musisz używać najnowszej wersji bazy danych czatu TYLKO na jednym urządzeniu, w przeciwnym razie możesz przestać otrzymywać wiadomości od niektórych kontaktów.</string>
<string name="you_can_start_chat_via_setting_or_by_restarting_the_app">Możesz rozpocząć czat poprzez Ustawienia aplikacji / Bazę danych lub poprzez ponowne uruchomienie aplikacji.</string>
<string name="your_settings">Twoje ustawienia</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Twój kontakt może zeskanować kod QR z aplikacji.</string>
<string name="your_current_chat_database_will_be_deleted_and_replaced_with_the_imported_one">Twoja obecna baza danych czatu zostanie USUNIĘTA i ZASTĄPIONA zaimportowaną.
\nTej czynności nie można cofnąć - Twój profil, kontakty, wiadomości i pliki zostaną nieodwracalnie utracone.</string>
<string name="contact_sent_large_file">Twój kontakt wysłał plik, który jest większy niż obecnie obsługiwany maksymalny rozmiar (<xliff:g id="maxFileSize">%1$s</xliff:g>).</string>

View File

@@ -50,7 +50,6 @@
<string name="icon_descr_close_button">Botão Fechar</string>
<string name="clear_verification">Limpar verificação</string>
<string name="app_version_title">Versão do App</string>
<string name="accept_automatically">Automaticamente</string>
<string name="bold">negrito</string>
<string name="callstatus_error">erro de chamada</string>
<string name="settings_audio_video_calls">Chamadas de áudio e vídeo</string>
@@ -67,7 +66,6 @@
<string name="incognito_random_profile_description">Um perfil aleatório será enviado para o seu contato</string>
<string name="chat_preferences">Preferências de chat</string>
<string name="network_session_mode_user">perfil de chat</string>
<string name="accept_requests">Aceitar solicitações</string>
<string name="icon_descr_audio_off">Áudio desligado</string>
<string name="auto_accept_images">Aceitar imagens automaticamente</string>
<string name="chat_database_deleted">Banco de dados de chat excluído</string>
@@ -123,7 +121,6 @@
<string name="copied">Copiado para a área de transferência</string>
<string name="accept_connection_request__question">Aceitar solicitação de conexão\?</string>
<string name="network_settings">Configurações de rede avançadas</string>
<string name="contact_requests">Solicitações de contato</string>
<string name="create_address">Criar endereço</string>
<string name="all_your_contacts_will_remain_connected">Todos os seus contatos permanecerão conectados.</string>
<string name="callstatus_accepted">chamada aceita</string>
@@ -157,7 +154,7 @@
<string name="alert_title_contact_connection_pending">Contato ainda não está conectado!</string>
<string name="contribute">Contribuir</string>
<string name="create_profile_button">Criar</string>
<string name="network_enable_socks_info">Acessar os servidores via proxy SOCKS na porta 9050\? O proxy deve ser iniciado antes de habilitar esta opção.</string>
<string name="network_enable_socks_info">Acessar os servidores via proxy SOCKS na porta %d\? O proxy deve ser iniciado antes de habilitar esta opção.</string>
<string name="allow_your_contacts_irreversibly_delete">Permitir que seus contatos excluam de forma irreversível as mensagens enviadas.</string>
<string name="smp_servers_add_to_another_device">Adicionar a outro dispositivo</string>
<string name="v4_2_group_links_desc">Os administradores podem criar os links para ingressar em grupos.</string>
@@ -462,7 +459,6 @@
<string name="reject_contact_button">Rejeitar</string>
<string name="feature_offered_item">ofereceu %s</string>
<string name="icon_descr_address"><xliff:g id="appName">Endereço</xliff:g> SimpleX</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Seu contato pode escanear o código QR do aplicativo.</string>
<string name="feature_offered_item_with_param">ofereceu %s: %2s</string>
<string name="paste_connection_link_below_to_connect">Cole o link que você recebeu na caixa abaixo para conectar com o seu contato.</string>
<string name="new_in_version">Novo em %s</string>
@@ -657,7 +653,6 @@
<string name="this_QR_code_is_not_a_link">Esse código QR não é um link!</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Seu perfil de chat será enviado para seu
\ncontato</string>
<string name="your_contact_address">Seu endereço de contato</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">Você será conectado quando o dispositivo do seu contato estiver online, aguarde ou verifique mais tarde!</string>
<string name="how_to">Como</string>
<string name="smp_servers_test_failed">Teste do servidor falhou!</string>
@@ -784,7 +779,6 @@
<string name="network_use_onion_hosts_no_desc_in_alert">Hosts Onion não serão usados.</string>
<string name="network_use_onion_hosts_prefer_desc">Os hosts Onion serão usados quando disponíveis.</string>
<string name="network_use_onion_hosts_prefer_desc_in_alert">Os hosts Onion serão usados quando disponíveis.</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Você pode compartilhar seu endereço como um link ou como um código QR - qualquer pessoa poderá se conectar a você. Você não perderá seus contatos se excluí-los posteriormente.</string>
<string name="your_current_profile">Seu perfil atual</string>
<string name="privacy_redefined">Privacidade redefinida</string>
<string name="onboarding_notifications_mode_title">Notificações privadas</string>
@@ -815,7 +809,6 @@
<string name="network_settings_title">Configurações de conexão</string>
<string name="no_details">sem detalhes</string>
<string name="add_contact">Link de convite de uso único</string>
<string name="network_socks_toggle">Usar proxy SOCKS (porta 9050)</string>
<string name="smp_servers_your_server_address">Seu endereço de servidor</string>
<string name="your_settings">Suas configurações</string>
<string name="is_verified">%s é verificado</string>
@@ -921,7 +914,6 @@
<string name="you_are_observer">você é um observador</string>
<string name="voice_message_with_duration">Mensagem de voz (<xliff:g id="duration">%1$s</xliff:g>)</string>
<string name="share_link">Compartilhar link</string>
<string name="section_title_welcome_message">MENSAGEM DE BOAS-VINDAS</string>
<string name="to_protect_privacy_simplex_has_ids_for_queues">Para proteger a privacidade, em vez dos IDs de usuário usados por todas as outras plataformas, <xliff:g id="appName">SimpleX</xliff:g> tem identificadores para filas de mensagens, separados para cada um de seus contatos.</string>
<string name="icon_descr_video_call">chamada de vídeo</string>
<string name="show_call_on_lock_screen">Mostrar</string>

View File

@@ -330,7 +330,6 @@
<string name="you_will_be_connected_when_group_host_device_is_online">Соединение с группой будет установлено, когда хост группы будет онлайн. Пожалуйста, подождите или проверьте позже!</string>
<string name="you_will_be_connected_when_your_connection_request_is_accepted">Соединение будет установлено, когда Ваш запрос будет принят. Пожалуйста, подождите или проверьте позже!</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">Соединение будет установлено, когда Ваш контакт будет онлайн. Пожалуйста, подождите или проверьте позже!</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Ваш контакт может сосканировать QR код в приложении.</string>
<string name="if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel">Если Вы не можете встретиться лично, Вы можете <b>показать QR код во время видеозвонка</b> или поделиться ссылкой.</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Ваш профиль будет отправлен
\nВашему контакту</string>
@@ -344,7 +343,6 @@
<!-- CreateLinkView.kt -->
<string name="create_one_time_link">Создать одноразовую ссылку</string>
<string name="one_time_link">Одноразовая ссылка</string>
<string name="your_contact_address">Ваш SimpleX адрес</string>
<!-- settings - SettingsView.kt -->
<string name="your_settings">Настройки</string>
<string name="your_simplex_contact_address">Ваш <xliff:g id="appName">SimpleX</xliff:g> адрес</string>
@@ -396,9 +394,8 @@
<string name="network_and_servers">Сеть и серверы</string>
<string name="network_settings">Настройки сети</string>
<string name="network_settings_title">Настройки сети</string>
<string name="network_socks_toggle">Использовать SOCKS прокси (порт 9050)</string>
<string name="network_enable_socks">Использовать SOCKS прокси?</string>
<string name="network_enable_socks_info">Соединяться с серверами через SOCKS прокси через порт 9050? Прокси должен быть запущен до включения этой опции.</string>
<string name="network_enable_socks_info">Соединяться с серверами через SOCKS прокси через порт %d? Прокси должен быть запущен до включения этой опции.</string>
<string name="network_disable_socks">Использовать прямое соединение с Интернет?</string>
<string name="network_disable_socks_info">Если Вы подтвердите, серверы смогут видеть Ваш IP адрес, а провайдер - с какими серверами Вы соединяетесь.</string>
<string name="update_onion_hosts_settings_question">Обновить настройки .onion хостов?</string>
@@ -417,14 +414,8 @@
<string name="create_address">Создать адрес</string>
<string name="delete_address__question">Удалить адрес?</string>
<string name="all_your_contacts_will_remain_connected">Все контакты, которые соединились через этот адрес, сохранятся.</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">Вы можете использовать Ваш адрес как ссылку или как QR код - кто угодно сможет соединиться с Вами. Вы сможете удалить адрес, сохранив контакты, которые через него соединились.</string>
<string name="share_link">Поделиться\nссылкой</string>
<string name="delete_address">Удалить\nадрес</string>
<!-- AcceptRequestsView.kt -->
<string name="contact_requests">Запросы контактов</string>
<string name="accept_requests">Принимать запросы</string>
<string name="accept_automatically">Автоматически</string>
<string name="section_title_welcome_message">ПРИВЕТСТВЕННОЕ СООБЩЕНИЕ</string>
<string name="delete_address">Удалить адрес</string>
<!-- User profile details - UserProfileView.kt -->
<string name="display_name__field">Имя профиля:</string>
<string name="full_name__field">"Полное имя:</string>

View File

@@ -14,7 +14,7 @@
<string name="color_primary">色调</string>
<string name="callstatus_accepted">已接受通话</string>
<string name="accept">接受</string>
<string name="network_enable_socks_info">通过 SOCKS 代理访问服务器在端口9050?允许该选项前必须开始代理。</string>
<string name="network_enable_socks_info">通过 SOCKS 代理访问服务器在端口%d?允许该选项前必须开始代理。</string>
<string name="smp_servers_add">添加服务器……</string>
<string name="smp_servers_add_to_another_device">添加另一设备</string>
<string name="group_member_role_admin">管理员</string>
@@ -23,7 +23,6 @@
<string name="accept_connection_request__question">接受连接请求?</string>
<string name="accept_contact_incognito_button">接受隐身聊天</string>
<string name="v4_2_group_links_desc">管理员可以创建链接以加入群组。</string>
<string name="accept_requests">接受请求</string>
<string name="smp_servers_preset_add">添加预设服务器</string>
<string name="connect_via_link">通过链接连接</string>
<string name="display_name_connection_established">已建立连接</string>
@@ -112,7 +111,6 @@
<string name="integrity_msg_bad_hash">错误消息散列</string>
<string name="integrity_msg_bad_id">错误消息 ID</string>
<string name="settings_audio_video_calls">语音和视频通话</string>
<string name="accept_automatically">自动</string>
<string name="turning_off_service_and_periodic">激活电池优化,关闭了后台服务和新消息的定期请求。您可以通过设置重新启用它们。</string>
<string name="notifications_mode_service_desc">后台服务一直在运行——一旦有消息,就会显示通知。</string>
<string name="icon_descr_audio_off">关闭音频</string>
@@ -328,7 +326,6 @@
<string name="delete_contact_all_messages_deleted_cannot_undo_warning">联系人和所有的消息都将被删除——这是不可逆回的!</string>
<string name="notification_preview_mode_contact">联系人姓名</string>
<string name="group_member_status_intro_invitation">连接(介绍邀请)</string>
<string name="contact_requests">联系人请求</string>
<string name="callstate_connecting">连接中……</string>
<string name="contacts_can_mark_messages_for_deletion">联系人可以将信息标记为删除;您将可以查看这些信息。</string>
<string name="contribute">贡献</string>
@@ -516,7 +513,6 @@
<string name="you_must_use_the_most_recent_version_of_database">您只能在一台设备上使用最新版本的聊天数据库,否则您可能会停止接收来自某些联系人的消息。</string>
<string name="new_passphrase">新密码……</string>
<string name="member_role_will_be_changed_with_notification">该角色将更改为“%s”。群组中每个人都会收到通知。</string>
<string name="your_contact_address">您的联系人地址</string>
<string name="chat_lock">SimpleX 锁定</string>
<string name="periodic_notifications">定期通知</string>
<string name="notifications_mode_periodic">定期启动</string>
@@ -876,7 +872,6 @@
<string name="you_will_be_connected_when_your_contacts_device_is_online">当您的联系人设备在线时,您将可以连接,请稍等或稍后查看!</string>
<string name="rate_the_app">评价此应用程序</string>
<string name="network_enable_socks">使用 SOCKS 代理?</string>
<string name="network_socks_toggle">使用 SOCKS 代理(端口 9050</string>
<string name="total_files_count_and_size">%d 个文件,总大小为 %s</string>
<string name="you_joined_this_group">您已加入此群组</string>
<string name="you_are_invited_to_group">您被邀请加入群组</string>
@@ -891,9 +886,7 @@
<string name="icon_descr_simplex_team"><xliff:g id="appName">SimpleX</xliff:g> 团队</string>
<string name="group_info_section_title_num_members"><xliff:g id="num_members">%1$s</xliff:g> 成员</string>
<string name="chat_preferences_yes"></string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">您可以将您的地址作为链接或二维码共享——任何人都可以连接到您。 如果您以后删除它,您不会丢失您的联系人。</string>
<string name="you_control_servers_to_receive_your_contacts_to_send">您可以控制通过哪些服务器<b>接收</b>消息,您的联系人 - 您用来向他们发送消息的服务器。</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">您的联系人可以从应用程序中扫描二维码。</string>
<string name="you_will_be_connected_when_group_host_device_is_online">您将在组主设备上线时连接到该群组,请稍等或稍后再检查!</string>
<string name="auth_you_will_be_required_to_authenticate_when_you_start_or_resume">当您启动应用或在应用程序驻留后台超过30 秒后,您将需要进行身份验证。</string>
<string name="archive_created_on_ts">创建于 <xliff:g id="archive_ts">%1$s</xliff:g></string>
@@ -942,7 +935,6 @@
<string name="network_use_onion_hosts">使用 .onion 主机</string>
<string name="your_ICE_servers">您的 ICE 服务器</string>
<string name="core_simplexmq_version">simplexmq: v%s (%2s)</string>
<string name="section_title_welcome_message">欢迎消息</string>
<string name="you_control_your_chat">您的聊天由您掌控!</string>
<string name="you_can_use_markdown_to_format_messages__prompt">您可以使用 markdown 来编排消息格式:</string>
<string name="ttl_h">%dh</string>

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="chat_item_ttl_week">1 個星期</string>
<string name="accept_requests">接受請求</string>
<string name="a_plus_b">a + b</string>
<string name="about_simplex">關於 SimpleX</string>
<string name="accept_call_on_lock_screen">接受</string>
@@ -70,7 +69,6 @@
<string name="app_version_code">程式建構:%s</string>
<string name="app_version_name">應用程式版本v%s</string>
<string name="share_link">分享連結</string>
<string name="accept_automatically">自動接受所有請求</string>
<string name="your_current_profile">你目前的個人檔案</string>
<string name="display_name_cannot_contain_whitespace">顯示的名稱字與字中間不能有空白。</string>
<string name="save_preferences_question">儲存設定?</string>
@@ -434,8 +432,6 @@
<string name="core_version">核心版本v%s</string>
<string name="core_simplexmq_version">simplexmq: v%s (%2s)</string>
<string name="create_address">建立地址</string>
<string name="contact_requests">聯絡人請求</string>
<string name="section_title_welcome_message">歡迎訊息</string>
<string name="edit_image">編輯圖片</string>
<string name="italic">斜體</string>
<string name="callstatus_rejected">已拒絕通話</string>
@@ -487,7 +483,6 @@
<string name="this_string_is_not_a_connection_link">這些字串不是連接連結!</string>
<string name="you_can_also_connect_by_clicking_the_link">你也可以點擊連結連接。如果在瀏覧器中開啟,點擊 <b>程式內的開啟</b> 按扭。</string>
<string name="one_time_link">一次性邀請連結</string>
<string name="your_contact_address">你的聯絡人地址</string>
<string name="scan_code">掃描二碼碼</string>
<string name="incorrect_code">錯誤的安全碼!</string>
<string name="scan_code_from_contacts_app">在你聯絡人的程式內掃描安全碼</string>
@@ -511,7 +506,6 @@
<string name="network_use_onion_hosts_prefer_desc">Onion 主機會當有的時侯啟用</string>
<string name="network_use_onion_hosts_required_desc_in_alert">連接時將需要 Onion 主機</string>
<string name="delete_address__question">刪除地址?</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">你可以使用連結或二維碼分享你的地址 - 任何人也可以和你連線。如果你不主動刪除你的聯絡人,你並不會遺失你的聯絡人</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">你的個人檔案只會儲存於你的裝置和只會分享給你的聯絡人。 <xliff:g id="appName">SimpleX</xliff:g> 伺服器並不會看到你的個人檔案。</string>
<string name="save_and_notify_contact">儲存並通知你的聯絡人</string>
<string name="save_and_notify_contacts">儲存並通知你的多個聯絡人</string>
@@ -525,11 +519,9 @@
<string name="callstate_received_answer">收到回應 …</string>
<string name="callstate_connecting">連接中 …</string>
<string name="callstate_ended">通話完結</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">你的聯絡人可以在程式內使用二維碼</string>
<string name="connect_button">連接</string>
<string name="network_and_servers">網路 &amp; 伺服器</string>
<string name="network_settings_title">網路設定</string>
<string name="network_socks_toggle">使用 SOCKS 代理伺服器 (端口 9050)</string>
<string name="network_enable_socks">使用 SOCKS 代理伺服器</string>
<string name="save_and_notify_group_members">儲存並通知群組內的聯絡人</string>
<string name="exit_without_saving">退出並且不儲存記錄</string>

View File

@@ -103,6 +103,7 @@
<string name="error_smp_test_server_auth">Server requires authorization to create queues, check password</string>
<string name="error_xftp_test_server_auth">Server requires authorization to upload, check password</string>
<string name="error_smp_test_certificate">Possibly, certificate fingerprint in server address is incorrect</string>
<string name="error_setting_address">Error setting address</string>
<string name="smp_server_test_connect">Connect</string>
<string name="smp_server_test_disconnect">Disconnect</string>
<string name="smp_server_test_create_queue">Create queue</string>
@@ -446,13 +447,24 @@
<string name="you_will_be_connected_when_group_host_device_is_online">You will be connected to group when the group host\'s device is online, please wait or check later!</string>
<string name="you_will_be_connected_when_your_connection_request_is_accepted">You will be connected when your connection request is accepted, please wait or check later!</string>
<string name="you_will_be_connected_when_your_contacts_device_is_online">You will be connected when your contact\'s device is online, please wait or check later!</string>
<string name="show_QR_code_for_your_contact_to_scan_from_the_app__multiline">Your contact can scan QR code from the app.</string>
<string name="if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel">If you can\'t meet in person, <b>show QR code in the video call</b>, or share the link.</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Your chat profile will be sent\nto your contact</string>
<string name="if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link">If you cannot meet in person, you can <b>scan QR code in the video call</b>, or your contact can share an invitation link.</string>
<string name="share_invitation_link">Share invitation link</string>
<string name="share_invitation_link">Share 1-time link</string>
<string name="paste_connection_link_below_to_connect">Paste the link you received into the box below to connect with your contact.</string>
<string name="your_profile_will_be_sent">Your chat profile will be sent to your contact</string>
<string name="learn_more">Learn more</string>
<string name="learn_more_about_address">About SimpleX address</string>
<!-- Add Contact Learn More - AddContactLearnMore.kt -->
<string name="scan_qr_to_connect_to_contact">To connect, your contact can scan QR code or use the link in the app.</string>
<string name="if_you_cant_meet_in_person">If you can\'t meet in person, show QR code in a video call, or share the link.</string>
<!-- User Address Learn More - UserAddressLearnMore.kt -->
<string name="you_can_share_your_address">You can share your address as a link or QR code - anybody can connect to you.</string>
<string name="you_wont_lose_your_contacts_if_delete_address">You won\'t lose your contacts if you later delete your address.</string>
<string name="you_can_accept_or_reject_connection">When people request to connect, you can accept or reject it.</string>
<string name="read_more_in_user_guide_with_link">Read more in <font color="#0088ff">User Guide</font>.</string>
<!-- PasteToConnect.kt -->
<string name="connect_via_link">Connect via link</string>
@@ -464,7 +476,8 @@
<!-- CreateLinkView.kt -->
<string name="create_one_time_link">Create one-time invitation link</string>
<string name="one_time_link">One-time invitation link</string>
<string name="your_contact_address">Your contact address</string>
<string name="one_time_link_short">1-time link</string>
<string name="simplex_address">SimpleX address</string>
<!-- ScanCodeView.kt -->
<string name="scan_code">Scan code</string>
@@ -481,7 +494,7 @@
<!-- settings - SettingsView.kt -->
<string name="your_settings">Your settings</string>
<string name="your_simplex_contact_address">Your <xliff:g id="appName">SimpleX</xliff:g> contact address</string>
<string name="your_simplex_contact_address">Your SimpleX address</string>
<string name="your_chat_profiles">Your chat profiles</string>
<string name="database_passphrase_and_export">Database passphrase &amp; export</string>
<string name="about_simplex_chat">About <xliff:g id="appNameFull">SimpleX Chat</xliff:g></string>
@@ -535,14 +548,13 @@
<string name="network_and_servers">Network &amp; servers</string>
<string name="network_settings">Advanced network settings</string>
<string name="network_settings_title">Network settings</string>
<string name="network_socks_toggle">Use SOCKS proxy (port 9050)</string>
<string name="network_socks_proxy_settings">SOCKS proxy settings</string>
<string name="network_socks_toggle_use_socks_proxy">Use SOCKS proxy</string>
<string name="network_proxy_port">port %d</string>
<string name="host_verb">Host</string>
<string name="port_verb">Port</string>
<string name="network_enable_socks">Use SOCKS proxy?</string>
<string name="network_enable_socks_info">Access the servers via SOCKS proxy on port 9050? Proxy must be started before enabling this option.</string>
<string name="network_enable_socks_info">Access the servers via SOCKS proxy on port %d? Proxy must be started before enabling this option.</string>
<string name="network_disable_socks">Use direct Internet connection?</string>
<string name="network_disable_socks_info">If you confirm, the messaging servers will be able to see your IP address, and your provider - which servers you are connecting to.</string>
<string name="update_onion_hosts_settings_question">Update .onion hosts setting?</string>
@@ -579,17 +591,25 @@
<!-- Address Items - UserAddressView.kt -->
<string name="create_address">Create address</string>
<string name="delete_address__question">Delete address?</string>
<string name="your_contacts_will_remain_connected">Your contacts will remain connected.</string>
<string name="all_your_contacts_will_remain_connected">All your contacts will remain connected.</string>
<string name="you_can_share_your_address_anybody_will_be_able_to_connect">You can share your address as a link or as a QR code - anybody will be able to connect to you. You won\'t lose your contacts if you later delete it.</string>
<string name="all_your_contacts_will_remain_connected_update_sent">All your contacts will remain connected. Profile update will be sent to your contacts.</string>
<string name="share_link">Share link</string>
<string name="delete_address_with_contacts_question">Share address with contacts?</string>
<string name="add_address_to_your_profile">Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</string>
<string name="create_address_and_let_people_connect">Create an address to let people connect with you.</string>
<string name="create_simplex_address">Create SimpleX address</string>
<string name="share_with_contacts">Share with contacts</string>
<string name="share_address_with_contacts_question">Share address with contacts?</string>
<string name="profile_update_will_be_sent_to_contacts">Profile update will be sent to your contacts.</string>
<string name="stop_sharing_address">Stop sharing address?</string>
<string name="stop_sharing">Stop sharing</string>
<string name="auto_accept_contact">Auto-accept</string>
<string name="enter_welcome_message_optional">Enter welcome message… (optional)</string>
<string name="save_settings_question">Save settings?</string>
<string name="save_auto_accept_settings">Save auto-accept settings</string>
<string name="delete_address">Delete address</string>
<!-- AcceptRequestsView.kt -->
<string name="contact_requests">Contact requests</string>
<string name="accept_requests">Accept requests</string>
<string name="accept_automatically">Automatically</string>
<string name="section_title_welcome_message">WELCOME MESSAGE</string>
<!-- User profile details - UserProfileView.kt -->
<string name="display_name__field">Display name:</string>
<string name="full_name__field">"Full name:</string>
@@ -1050,6 +1070,9 @@
<string name="error_updating_link_for_group">Error updating group link</string>
<string name="error_deleting_link_for_group">Error deleting group link</string>
<string name="only_group_owners_can_change_prefs">Only group owners can change group preferences.</string>
<string name="address_section_title">Address</string>
<string name="share_address">Share address</string>
<string name="you_can_share_this_address_with_your_contacts">You can share this address with your contacts to let them connect with %s.</string>
<!-- For Console chat info section -->
<string name="section_title_for_console">FOR CONSOLE</string>
@@ -1080,6 +1103,8 @@
<string name="group_welcome_title">Welcome message</string>
<string name="save_welcome_message_question">Save welcome message?</string>
<string name="save_and_update_group_profile">Save and update group profile</string>
<string name="group_welcome_preview">Preview</string>
<string name="enter_welcome_message">Enter welcome message…</string>
<!-- ConnectionStats -->
<string name="conn_stats_section_title_servers">SERVERS</string>

View File

@@ -618,6 +618,16 @@ func apiUpdateProfile(profile: Profile) async throws -> Profile? {
}
}
func apiSetProfileAddress(on: Bool) async throws -> User? {
let userId = try currentUserId("apiSetProfileAddress")
let r = await chatSendCmd(.apiSetProfileAddress(userId: userId, on: on))
switch r {
case .userProfileNoChange: return nil
case let .userProfileUpdated(user, _, _): return user
default: throw r
}
}
func apiSetContactPrefs(contactId: Int64, preferences: Preferences) async throws -> Contact? {
let r = await chatSendCmd(.apiSetContactPrefs(contactId: contactId, preferences: preferences))
if case let .contactPrefsUpdated(_, _, toContact) = r { return toContact }
@@ -643,10 +653,10 @@ func apiCreateUserAddress() async throws -> String {
throw r
}
func apiDeleteUserAddress() async throws {
func apiDeleteUserAddress() async throws -> User? {
let userId = try currentUserId("apiDeleteUserAddress")
let r = await chatSendCmd(.apiDeleteMyAddress(userId: userId))
if case .userContactLinkDeleted = r { return }
if case let .userContactLinkDeleted(user) = r { return user }
throw r
}
@@ -943,12 +953,6 @@ func apiListMembers(_ groupId: Int64) async -> [GroupMember] {
return []
}
func apiListMembersSync(_ groupId: Int64) -> [GroupMember] {
let r = chatSendCmdSync(.apiListMembers(groupId: groupId))
if case let .groupMembers(_, group) = r { return group.members }
return []
}
func filterMembersToAdd(_ ms: [GroupMember]) -> [Contact] {
let memberContactIds = ms.compactMap{ m in m.memberCurrent ? m.memberContactId : nil }
return ChatModel.shared.chats
@@ -1047,7 +1051,7 @@ func startChat(refreshInvitations: Bool = true) throws {
}
withAnimation {
m.onboardingStage = m.onboardingStage == .step2_CreateProfile && m.users.count == 1
? .step3_SetNotificationsMode
? .step3_CreateSimpleXAddress
: .onboardingComplete
}
}

View File

@@ -116,6 +116,21 @@ struct ChatInfoView: View {
contactPreferencesButton()
}
if let contactLink = contact.contactLink {
Section {
QRCode(uri: contactLink)
Button {
showShareSheet(items: [contactLink])
} label: {
Label("Share address", systemImage: "square.and.arrow.up")
}
} header: {
Text("Address")
} footer: {
Text("You can share this address with your contacts to let them connect with **\(contact.displayName)**.")
}
}
Section("Servers") {
networkStatusRow()
.onTapGesture {

File diff suppressed because one or more lines are too long

View File

@@ -154,7 +154,7 @@ struct ComposeState {
}
var attachmentDisabled: Bool {
if editing || liveMessage != nil { return true }
if editing || liveMessage != nil || inProgress { return true }
switch preview {
case .noPreview: return false
case .linkPreview: return false
@@ -427,6 +427,8 @@ struct ComposeView: View {
clearCurrentDraft()
sendMessage()
resetLinkPreview()
} else if (composeState.inProgress) {
clearCurrentDraft()
} else if !composeState.empty {
saveCurrentDraft()
} else {
@@ -522,7 +524,11 @@ struct ComposeView: View {
case .noPreview:
EmptyView()
case let .linkPreview(linkPreview: preview):
ComposeLinkView(linkPreview: preview, cancelPreview: cancelLinkPreview)
ComposeLinkView(
linkPreview: preview,
cancelPreview: cancelLinkPreview,
cancelEnabled: !composeState.inProgress
)
case let .mediaPreviews(mediaPreviews: media):
ComposeImageView(
images: media.map { (img, _) in img },
@@ -530,7 +536,7 @@ struct ComposeView: View {
composeState = composeState.copy(preview: .noPreview)
chosenMedia = []
},
cancelEnabled: !composeState.editing)
cancelEnabled: !composeState.editing && !composeState.inProgress)
case let .voicePreview(recordingFileName, _):
ComposeVoiceView(
recordingFileName: recordingFileName,
@@ -540,7 +546,7 @@ struct ComposeView: View {
cancelVoiceMessageRecording($0)
clearState()
},
cancelEnabled: !composeState.editing,
cancelEnabled: !composeState.editing && !composeState.inProgress,
stopPlayback: $stopPlayback
)
case let .filePreview(fileName, _):
@@ -549,7 +555,7 @@ struct ComposeView: View {
cancelFile: {
composeState = composeState.copy(preview: .noPreview)
},
cancelEnabled: !composeState.editing)
cancelEnabled: !composeState.editing && !composeState.inProgress)
}
}

View File

@@ -13,6 +13,7 @@ import PhotosUI
struct NativeTextEditor: UIViewRepresentable {
@Binding var text: String
@Binding var disableEditing: Bool
let height: CGFloat
let font: UIFont
@FocusState.Binding var focused: Bool
@@ -26,7 +27,11 @@ struct NativeTextEditor: UIViewRepresentable {
field.textAlignment = alignment == .leading ? .left : .right
field.autocapitalizationType = .sentences
field.setOnTextChangedListener { newText, images in
text = newText
if !disableEditing {
text = newText
} else {
field.text = text
}
if !images.isEmpty {
onImagesAdded(images)
}
@@ -140,6 +145,7 @@ struct NativeTextEditor_Previews: PreviewProvider{
@FocusState var keyboardVisible: Bool
return NativeTextEditor(
text: Binding.constant("Hello, world!"),
disableEditing: Binding.constant(false),
height: 100,
font: UIFont.preferredFont(forTextStyle: .body),
focused: $keyboardVisible,

View File

@@ -65,6 +65,7 @@ struct SendMessageView: View {
NativeTextEditor(
text: $composeState.message,
disableEditing: $composeState.inProgress,
height: teHeight,
font: teUiFont,
focused: $keyboardVisible,
@@ -83,7 +84,7 @@ struct SendMessageView: View {
.padding([.bottom, .trailing], 3)
} else {
VStack(alignment: .trailing) {
if teHeight > 100 {
if teHeight > 100 && !composeState.inProgress {
deleteTextButton()
Spacer()
}

View File

@@ -10,13 +10,22 @@ import SwiftUI
import SimpleXChat
struct AddGroupMembersView: View {
@EnvironmentObject var chatModel: ChatModel
@Environment(\.dismiss) var dismiss: DismissAction
var chat: Chat
var groupInfo: GroupInfo
var body: some View {
AddGroupMembersViewCommon(chat: chat, groupInfo: groupInfo, addedMembersCb: { _ in dismiss() })
}
}
struct AddGroupMembersViewCommon: View {
@EnvironmentObject var chatModel: ChatModel
var chat: Chat
@State var groupInfo: GroupInfo
var creatingGroup: Bool = false
var showFooterCounter: Bool = true
var addedMembersCb: ((Set<Int64>) -> Void)? = nil
var addedMembersCb: ((Set<Int64>) -> Void)
@State private var selectedContacts = Set<Int64>()
@State private var selectedRole: GroupMemberRole = .member
@State private var alert: AddGroupMembersAlert?
@@ -39,7 +48,7 @@ struct AddGroupMembersView: View {
addGroupMembersView()
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button ("Skip") { addedMembersCb?(selectedContacts) }
Button ("Skip") { addedMembersCb(selectedContacts) }
}
}
}
@@ -128,8 +137,7 @@ struct AddGroupMembersView: View {
let member = try await apiAddMember(groupInfo.groupId, contactId, selectedRole)
await MainActor.run { _ = ChatModel.shared.upsertGroupMember(groupInfo, member) }
}
await MainActor.run { dismiss() }
if let cb = addedMembersCb { cb(selectedContacts) }
addedMembersCb(selectedContacts)
} catch {
let a = getErrorAlert(error, "Error adding member(s)")
alert = .error(title: a.title, error: a.message)

View File

@@ -45,6 +45,8 @@ struct GroupChatInfoView: View {
Section {
if groupInfo.canEdit {
editGroupButton()
}
if groupInfo.groupProfile.description != nil || groupInfo.canEdit {
addOrEditWelcomeMessage()
}
groupPreferencesButton($groupInfo)
@@ -142,7 +144,12 @@ struct GroupChatInfoView: View {
NavigationLink {
AddGroupMembersView(chat: chat, groupInfo: groupInfo)
.onAppear {
ChatModel.shared.groupMembers = apiListMembersSync(groupInfo.groupId)
Task {
let groupMembers = await apiListMembers(groupInfo.groupId)
await MainActor.run {
ChatModel.shared.groupMembers = groupMembers
}
}
}
} label: {
Label("Invite members", systemImage: "plus")

View File

@@ -65,6 +65,21 @@ struct GroupMemberInfoView: View {
}
}
if let contactLink = member.contactLink {
Section {
QRCode(uri: contactLink)
Button {
showShareSheet(items: [contactLink])
} label: {
Label("Share address", systemImage: "square.and.arrow.up")
}
} header: {
Text("Address")
} footer: {
Text("You can share this address with your contacts to let them connect with **\(member.displayName)**.")
}
}
Section("Member") {
infoRow("Group", groupInfo.displayName)

View File

@@ -15,43 +15,101 @@ struct GroupWelcomeView: View {
var groupId: Int64
@Binding var groupInfo: GroupInfo
@State private var welcomeText: String = ""
@State private var editMode = true
@FocusState private var keyboardVisible: Bool
@State private var showSaveDialog = false
var body: some View {
List {
Section {
TextEditor(text: $welcomeText)
.focused($keyboardVisible)
.padding(.horizontal, -5)
.padding(.top, -8)
.frame(height: 90, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
Section {
saveButton()
VStack {
if groupInfo.canEdit {
editorView()
.modifier(BackButton {
if welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil) {
dismiss()
} else {
showSaveDialog = true
}
})
.confirmationDialog("Save welcome message?", isPresented: $showSaveDialog) {
Button("Save and update group profile") {
save()
dismiss()
}
Button("Exit without saving") { dismiss() }
}
} else {
List {
Section {
textPreview()
copyButton()
}
}
}
}
.onAppear {
welcomeText = groupInfo.groupProfile.description ?? ""
}
.modifier(BackButton {
if welcomeText == groupInfo.groupProfile.description || (welcomeText == "" && groupInfo.groupProfile.description == nil) {
dismiss()
} else {
showSaveDialog = true
}
})
.confirmationDialog("Save welcome message?", isPresented: $showSaveDialog) {
Button("Save and update group profile") {
save()
dismiss()
}
Button("Exit without saving") { dismiss() }
keyboardVisible = true
}
}
@ViewBuilder private func saveButton() -> some View {
private func textPreview() -> some View {
messageText(welcomeText, parseSimpleXMarkdown(welcomeText), nil)
.allowsHitTesting(false)
}
private func editorView() -> some View {
List {
Section {
if editMode {
ZStack {
Group {
if welcomeText.isEmpty {
TextEditor(text: Binding.constant(NSLocalizedString("Enter welcome message…", comment: "placeholder")))
.foregroundColor(.secondary)
.disabled(true)
}
TextEditor(text: $welcomeText)
.focused($keyboardVisible)
}
.padding(.horizontal, -5)
.padding(.top, -8)
.frame(height: 90, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
} else {
textPreview()
.frame(height: 90, alignment: .topLeading)
}
Button {
editMode = !editMode
keyboardVisible = editMode
} label: {
if editMode {
Label ("Preview", systemImage: "character")
} else {
Label ("Edit", systemImage: "pencil")
}
}
.disabled(welcomeText.isEmpty)
copyButton()
}
Section {
saveButton()
}
}
}
private func copyButton() -> some View {
Button {
UIPasteboard.general.string = welcomeText
} label: {
Label ("Copy", systemImage: "doc.on.doc")
}
}
private func saveButton() -> some View {
Button("Save and update group profile") {
save()
}

View File

@@ -39,6 +39,11 @@ struct ContactConnectionInfo: View {
.padding(.bottom, 16)
Text(contactConnectionText(contactConnection))
.padding(.bottom, 16)
if let connReqInv = contactConnection.connReqInv {
OneTimeLinkProfileText(contactConnection: contactConnection, connReqInvitation: connReqInv)
}
}
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
@@ -47,11 +52,7 @@ struct ContactConnectionInfo: View {
Section {
if contactConnection.groupLinkId == nil {
HStack(spacing: 20) {
Image(systemName: "pencil")
.foregroundColor(.secondary)
.padding(.leading, 6)
.onTapGesture { aliasTextFieldFocused = true }
settingsRow("pencil") {
TextField("Set contact name…", text: $localAlias)
.autocapitalization(.none)
.autocorrectionDisabled(true)
@@ -59,20 +60,18 @@ struct ContactConnectionInfo: View {
.submitLabel(.done)
.onSubmit(setConnectionAlias)
}
.onTapGesture { aliasTextFieldFocused = true }
}
if contactConnection.initiated,
let connReqInv = contactConnection.connReqInv {
NavigationLink {
AddContactView(contactConnection: contactConnection, connReqInvitation: connReqInv)
.navigationTitle(CreateLinkTab.oneTime.title)
.navigationBarTitleDisplayMode(.large)
} label: {
Label("Show QR code", systemImage: "qrcode")
.foregroundColor(contactConnection.incognito ? .indigo : .accentColor)
}
oneTimeLinkSection(contactConnection: contactConnection, connReqInvitation: connReqInv)
} else {
oneTimeLinkLearnMoreButton()
}
}
Section {
Button(role: .destructive) {
alert = .deleteInvitationAlert
} label: {
@@ -81,7 +80,6 @@ struct ContactConnectionInfo: View {
}
}
}
.listStyle(.insetGrouped)
}
.alert(item: $alert) { _alert in
switch _alert {
@@ -96,7 +94,6 @@ struct ContactConnectionInfo: View {
}
.onAppear {
localAlias = contactConnection.localAlias
aliasTextFieldFocused = true
}
}

View File

@@ -109,7 +109,7 @@ struct MigrateToAppGroupView: View {
do {
resetChatCtrl()
try initializeChat(start: true)
chatModel.onboardingStage = .step3_SetNotificationsMode
chatModel.onboardingStage = .step4_SetNotificationsMode
setV3DBMigration(.ready)
} catch let error {
dbContainerGroupDefault.set(.documents)

View File

@@ -0,0 +1,61 @@
//
// MailView.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 01.05.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
import UIKit
import MessageUI
struct MailView: UIViewControllerRepresentable {
@Binding var isShowing: Bool
@Binding var result: Result<MFMailComposeResult, Error>?
var subject = ""
var messageBody = ""
class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
@Binding var isShowing: Bool
@Binding var result: Result<MFMailComposeResult, Error>?
init(isShowing: Binding<Bool>,
result: Binding<Result<MFMailComposeResult, Error>?>) {
_isShowing = isShowing
_result = result
}
func mailComposeController(
_ controller: MFMailComposeViewController,
didFinishWith result: MFMailComposeResult,
error: Error?
) {
defer {
isShowing = false
}
if let error = error {
self.result = .failure(error)
return
}
self.result = .success(result)
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(isShowing: $isShowing, result: $result)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<MailView>) -> MFMailComposeViewController {
let vc = MFMailComposeViewController()
vc.setSubject(subject)
vc.setMessageBody(messageBody, isHTML: true)
vc.mailComposeDelegate = context.coordinator
return vc
}
func updateUIViewController(_ uiViewController: MFMailComposeViewController,
context: UIViewControllerRepresentableContext<MailView>) {
}
}

View File

@@ -0,0 +1,28 @@
//
// AddContactLearnMore.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 27.04.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
struct AddContactLearnMore: View {
var body: some View {
List {
VStack(alignment: .leading, spacing: 18) {
Text("To connect, your contact can scan QR code or use the link in the app.")
Text("If you can't meet in person, show QR code in a video call, or share the link.")
Text("Read more in [User Guide](https://simplex.chat/docs/guide/readme.html#connect-to-friends).")
}
.listRowBackground(Color.clear)
}
}
}
struct AddContactLearnMore_Previews: PreviewProvider {
static var previews: some View {
AddContactLearnMore()
}
}

View File

@@ -16,50 +16,73 @@ struct AddContactView: View {
var connReqInvitation: String
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Your contact can scan it from the app.")
.padding(.bottom, 4)
if (contactConnection?.incognito ?? chatModel.incognito) {
HStack {
Image(systemName: "theatermasks").foregroundColor(.indigo).font(.footnote)
Spacer().frame(width: 8)
Text("A random profile will be sent to your contact").font(.footnote)
}
.padding(.bottom)
} else {
HStack {
Image(systemName: "info.circle").foregroundColor(.secondary).font(.footnote)
Spacer().frame(width: 8)
Text("Your chat profile will be sent to your contact").font(.footnote)
}
.padding(.bottom)
}
if connReqInvitation != "" {
QRCode(uri: connReqInvitation).padding(.bottom)
} else {
ProgressView()
.progressViewStyle(.circular)
.scaleEffect(2)
.frame(maxWidth: .infinity)
.padding(.vertical)
}
Text("If you can't meet in person, **show QR code in the video call**, or share the link.")
.padding(.bottom)
Button {
showShareSheet(items: [connReqInvitation])
} label: {
Label("Share invitation link", systemImage: "square.and.arrow.up")
}
.frame(maxWidth: .infinity, alignment: .center)
List {
OneTimeLinkProfileText(contactConnection: contactConnection, connReqInvitation: connReqInvitation)
.listRowBackground(Color.clear)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
Section("1-time link") {
oneTimeLinkSection(contactConnection: contactConnection, connReqInvitation: connReqInvitation)
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
}
.onAppear { chatModel.connReqInv = connReqInvitation }
}
}
@ViewBuilder func oneTimeLinkSection(contactConnection: PendingContactConnection? = nil, connReqInvitation: String) -> some View {
if connReqInvitation != "" {
QRCode(uri: connReqInvitation)
} else {
ProgressView()
.progressViewStyle(.circular)
.scaleEffect(2)
.frame(maxWidth: .infinity)
.padding(.vertical)
}
shareLinkButton(connReqInvitation)
oneTimeLinkLearnMoreButton()
}
private func shareLinkButton(_ connReqInvitation: String) -> some View {
Button {
showShareSheet(items: [connReqInvitation])
} label: {
settingsRow("square.and.arrow.up") {
Text("Share 1-time link")
}
}
}
func oneTimeLinkLearnMoreButton() -> some View {
NavigationLink {
AddContactLearnMore()
.navigationTitle("One-time invitation link")
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("info.circle") {
Text("Learn more")
}
}
}
struct OneTimeLinkProfileText: View {
@EnvironmentObject private var chatModel: ChatModel
var contactConnection: PendingContactConnection? = nil
var connReqInvitation: String
var body: some View {
HStack {
if (contactConnection?.incognito ?? chatModel.incognito) {
Image(systemName: "theatermasks").foregroundColor(.indigo)
Text("A random profile will be sent to your contact")
} else {
Image(systemName: "info.circle").foregroundColor(.secondary)
Text("Your chat profile will be sent to your contact")
}
}
}
}
struct AddContactView_Previews: PreviewProvider {
static var previews: some View {
AddContactView(connReqInvitation: "https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FFe5ICmvrm4wkrr6X1LTMii-lhBqLeB76%23MCowBQYDK2VuAyEAdhZZsHpuaAk3Hh1q0uNb_6hGTpuwBIrsp2z9U2T0oC0%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAcz6jJk71InuxA0bOX7OUhddfB8Ov7xwQIlIDeXBRZaOntUU4brU5Y3rBzroZBdQJi0FKdtt_D7I%3D%2CMEIwBQYDK2VvAzkA-hDvk1duBi1hlOr08VWSI-Ou4JNNSQjseY69QyKm7Kgg1zZjbpGfyBqSZ2eqys6xtoV4ZtoQUXQ%3D")

View File

@@ -24,14 +24,14 @@ struct AddGroupView: View {
var body: some View {
if let chat = chat, let groupInfo = groupInfo {
AddGroupMembersView(
AddGroupMembersViewCommon(
chat: chat,
groupInfo: groupInfo,
creatingGroup: true,
showFooterCounter: false
) { _ in
dismiss()
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
m.chatId = groupInfo.id
}
}

View File

@@ -15,7 +15,7 @@ enum CreateLinkTab {
var title: LocalizedStringKey {
switch self {
case .oneTime: return "One-time invitation link"
case .longTerm: return "Your contact address"
case .longTerm: return "Your SimpleX address"
}
}
}
@@ -49,9 +49,9 @@ struct CreateLinkView: View {
)
}
.tag(CreateLinkTab.oneTime)
UserAddress()
UserAddressView(viaCreateLinkView: true)
.tabItem {
Label("Your contact address", systemImage: "infinity.circle")
Label("Your SimpleX address", systemImage: "infinity.circle")
}
.tag(CreateLinkTab.longTerm)
}

View File

@@ -34,7 +34,9 @@ struct CreateProfile: View {
VStack(alignment: .leading) {
Text("Create your profile")
.font(.largeTitle)
.bold()
.padding(.bottom, 4)
.frame(maxWidth: .infinity)
Text("Your profile, contacts and delivered messages are stored on your device.")
.padding(.bottom, 4)
Text("The profile is only shared with your contacts.")
@@ -122,7 +124,7 @@ struct CreateProfile: View {
m.currentUser = try apiCreateActiveUser(profile)
if m.users.isEmpty {
try startChat()
withAnimation { m.onboardingStage = .step3_SetNotificationsMode }
withAnimation { m.onboardingStage = .step3_CreateSimpleXAddress }
} else {
dismiss()
m.users = try listUsers()

View File

@@ -0,0 +1,222 @@
//
// CreateSimpleXAddress.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 28.04.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
import Contacts
import ContactsUI
import MessageUI
import SimpleXChat
struct CreateSimpleXAddress: View {
@EnvironmentObject var m: ChatModel
@State private var progressIndicator = false
@State private var showMailView = false
@State private var mailViewResult: Result<MFMailComposeResult, Error>? = nil
var body: some View {
GeometryReader { g in
ScrollView {
ZStack {
VStack(alignment: .leading) {
Text("SimpleX Address")
.font(.largeTitle)
.bold()
.frame(maxWidth: .infinity)
Spacer()
if let userAddress = m.userAddress {
QRCode(uri: userAddress.connReqContact)
.frame(maxHeight: g.size.width)
shareQRCodeButton(userAddress)
.frame(maxWidth: .infinity)
Spacer()
if MFMailComposeViewController.canSendMail() {
shareViaEmailButton(userAddress)
.frame(maxWidth: .infinity)
} else {
shareViaEmailToButton(userAddress)
.frame(maxWidth: .infinity)
}
Spacer()
continueButton()
.padding(.bottom, 8)
.frame(maxWidth: .infinity)
} else {
createAddressButton()
.frame(maxWidth: .infinity)
Spacer()
skipButton()
.padding(.bottom, 56)
.frame(maxWidth: .infinity)
}
}
.frame(minHeight: g.size.height)
if progressIndicator {
ProgressView().scaleEffect(2)
}
}
}
}
.frame(maxHeight: .infinity)
.padding()
}
private func createAddressButton() -> some View {
VStack(spacing: 8) {
Button {
progressIndicator = true
Task {
do {
let connReqContact = try await apiCreateUserAddress()
DispatchQueue.main.async {
m.userAddress = UserContactLink(connReqContact: connReqContact)
}
if let u = try await apiSetProfileAddress(on: true) {
DispatchQueue.main.async {
m.updateUser(u)
}
}
await MainActor.run { progressIndicator = false }
} catch let error {
logger.error("CreateSimpleXAddress create address: \(responseError(error))")
await MainActor.run { progressIndicator = false }
let a = getErrorAlert(error, "Error creating address")
AlertManager.shared.showAlertMsg(
title: a.title,
message: a.message
)
}
}
} label: {
Text("Create SimpleX address").font(.title)
}
Group {
Text("Your contacts in SimpleX will see it.\nYou can change it in Settings.")
}
.multilineTextAlignment(.center)
.font(.footnote)
.padding(.horizontal, 32)
}
}
private func skipButton() -> some View {
VStack(spacing: 8) {
Button {
withAnimation {
m.onboardingStage = .step4_SetNotificationsMode
}
} label: {
HStack {
Text("Don't create address")
Image(systemName: "chevron.right")
}
}
Text("You can create it later").font(.footnote)
}
}
private func shareQRCodeButton(_ userAddress: UserContactLink) -> some View {
Button {
showShareSheet(items: [userAddress.connReqContact])
} label: {
Label("Share", systemImage: "square.and.arrow.up")
}
}
private func shareViaEmailButton(_ userAddress: UserContactLink) -> some View {
Button {
showMailView = true
} label: {
Label("Invite friends", systemImage: "envelope")
.font(.title2)
}
.sheet(isPresented: $showMailView) {
SendAddressMailView(
showMailView: $showMailView,
mailViewResult: $mailViewResult,
userAddress: userAddress
)
.edgesIgnoringSafeArea(.bottom)
}
.onChange(of: mailViewResult == nil) { _ in
if let r = mailViewResult {
switch r {
case let .success(composeResult):
switch composeResult {
case .sent:
m.onboardingStage = .step4_SetNotificationsMode
default: ()
}
case let .failure(error):
logger.error("CreateSimpleXAddress share via email: \(responseError(error))")
let a = getErrorAlert(error, "Error sending email")
AlertManager.shared.showAlertMsg(
title: a.title,
message: a.message
)
}
mailViewResult = nil
}
}
}
private func shareViaEmailToButton(_ userAddress: UserContactLink) -> some View {
Button {
UserAddressView.shareUserAddressViaMailTo(userAddress)
} label: {
Label("Invite friends", systemImage: "envelope")
.font(.title2)
}
}
private func continueButton() -> some View {
Button {
withAnimation {
m.onboardingStage = .step4_SetNotificationsMode
}
} label: {
HStack {
Text("Continue")
Image(systemName: "greaterthan")
}
}
}
}
struct SendAddressMailView: View {
@Binding var showMailView: Bool
@Binding var mailViewResult: Result<MFMailComposeResult, Error>?
var userAddress: UserContactLink
var body: some View {
let messageBody = NSLocalizedString("""
<p>Hi!</p>
<p><a href="\(userAddress.connReqContact)">Connect to me via SimpleX Chat</a></p>
""", comment: "")
MailView(
isShowing: self.$showMailView,
result: $mailViewResult,
subject: NSLocalizedString("Let's talk in SimpleX Chat", comment: ""),
messageBody: messageBody
)
}
}
struct CreateSimpleXAddress_Previews: PreviewProvider {
static var previews: some View {
CreateSimpleXAddress()
}
}

View File

@@ -15,7 +15,8 @@ struct OnboardingView: View {
switch onboarding {
case .step1_SimpleXInfo: SimpleXInfo(onboarding: true)
case .step2_CreateProfile: CreateProfile()
case .step3_SetNotificationsMode: SetNotificationsMode()
case .step3_CreateSimpleXAddress: CreateSimpleXAddress()
case .step4_SetNotificationsMode: SetNotificationsMode()
case .onboardingComplete: EmptyView()
}
}
@@ -24,7 +25,8 @@ struct OnboardingView: View {
enum OnboardingStage {
case step1_SimpleXInfo
case step2_CreateProfile
case step3_SetNotificationsMode
case step3_CreateSimpleXAddress
case step4_SetNotificationsMode
case onboardingComplete
}

View File

@@ -17,7 +17,10 @@ struct SetNotificationsMode: View {
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 16) {
Text("Push notifications").font(.largeTitle)
Text("Push notifications")
.font(.largeTitle)
.bold()
.frame(maxWidth: .infinity)
Text("Send notifications:")
ForEach(NotificationsMode.values) { mode in
@@ -62,9 +65,10 @@ struct SetNotificationsMode: View {
m.notificationMode = mode
}
} catch let error {
let a = getErrorAlert(error, "Error enabling notifications")
AlertManager.shared.showAlertMsg(
title: "Error enabling notifications",
message: "\(responseError(error))"
title: a.title,
message: a.message
)
}
}

View File

@@ -126,7 +126,7 @@ private let versionDescriptions: [VersionDescription] = [
FeatureDescription(
icon: "character",
title: "Italian interface",
description: "Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"
description: "Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"
)
]
),
@@ -161,7 +161,7 @@ private let versionDescriptions: [VersionDescription] = [
FeatureDescription(
icon: "character",
title: "Chinese and Spanish interface",
description: "Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"
description: "Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"
),
]
),
@@ -181,7 +181,7 @@ private let versionDescriptions: [VersionDescription] = [
FeatureDescription(
icon: "character",
title: "Polish interface",
description: "Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!"
description: "Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!"
),
]
)

View File

@@ -1,131 +0,0 @@
//
// AcceptRequestsView.swift
// SimpleX (iOS)
//
// Created by Evgeny on 23/10/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct AcceptRequestsView: View {
@EnvironmentObject private var m: ChatModel
@State var contactLink: UserContactLink
@State private var a = AutoAcceptState()
@State private var saved = AutoAcceptState()
@FocusState private var keyboardVisible: Bool
var body: some View {
List {
Section {
settingsRow("checkmark") {
Toggle("Automatically", isOn: $a.enable)
}
if a.enable {
settingsRow(
a.incognito ? "theatermasks.fill" : "theatermasks",
color: a.incognito ? .indigo : .secondary
) {
Toggle("Incognito", isOn: $a.incognito)
}
}
} header: {
Text("Accept requests")
} footer: {
saveButtons()
}
if a.enable {
Section {
TextEditor(text: $a.welcomeText)
.focused($keyboardVisible)
.padding(.horizontal, -5)
.padding(.top, -8)
.frame(height: 90, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
} header: {
Text("Welcome message")
}
}
}
.onAppear {
a = AutoAcceptState(contactLink: contactLink)
saved = a
}
.onChange(of: a.enable) { _ in
if !a.enable { a = AutoAcceptState() }
}
}
@ViewBuilder private func saveButtons() -> some View {
HStack {
Button {
a = saved
} label: {
Label("Cancel", systemImage: "arrow.counterclockwise")
}
Spacer()
Button {
Task {
do {
if let link = try await userAddressAutoAccept(a.autoAccept) {
contactLink = link
m.userAddress = link
saved = a
}
} catch let error {
logger.error("userAddressAutoAccept error: \(responseError(error))")
}
}
} label: {
Label("Save", systemImage: "checkmark")
}
}
.font(.body)
.disabled(a == saved)
}
private struct AutoAcceptState: Equatable {
var enable = false
var incognito = false
var welcomeText = ""
init(enable: Bool = false, incognito: Bool = false, welcomeText: String = "") {
self.enable = enable
self.incognito = incognito
self.welcomeText = welcomeText
}
init(contactLink: UserContactLink) {
if let aa = contactLink.autoAccept {
enable = true
incognito = aa.acceptIncognito
if let msg = aa.autoReply {
welcomeText = msg.text
} else {
welcomeText = ""
}
} else {
enable = false
incognito = false
welcomeText = ""
}
}
var autoAccept: AutoAccept? {
if enable {
var autoReply: MsgContent? = nil
let s = welcomeText.trimmingCharacters(in: .whitespacesAndNewlines)
if s != "" { autoReply = .text(s) }
return AutoAccept(acceptIncognito: incognito, autoReply: autoReply)
}
return nil
}
}
}
struct AcceptRequestsView_Previews: PreviewProvider {
static var previews: some View {
AcceptRequestsView(contactLink: UserContactLink(connReqContact: ""))
}
}

View File

@@ -9,7 +9,7 @@
import SwiftUI
import SimpleXChat
private let howToUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/SERVER.md")!
private let howToUrl = URL(string: "https://simplex.chat/docs/server.html")!
struct ProtocolServersView: View {
@Environment(\.dismiss) var dismiss: DismissAction

View File

@@ -8,7 +8,7 @@
import SwiftUI
private let howToUrl = URL(string: "https://github.com/simplex-chat/simplex-chat/blob/stable/docs/WEBRTC.md#configure-mobile-apps")!
private let howToUrl = URL(string: "https://simplex.chat/docs/webrtc.html#configure-mobile-apps")!
let serversFont = Font.custom("Menlo", size: 14)

View File

@@ -147,10 +147,11 @@ struct SettingsView: View {
incognitoRow()
NavigationLink {
CreateLinkView(selection: .longTerm, viaNavLink: true)
.navigationBarTitleDisplayMode(.inline)
UserAddressView(shareViaProfile: chatModel.currentUser!.addressShared)
.navigationTitle("SimpleX address")
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("qrcode") { Text("Your SimpleX contact address") }
settingsRow("qrcode") { Text("Your SimpleX address") }
}
NavigationLink {

View File

@@ -1,128 +0,0 @@
//
// UserAddress.swift
// SimpleX
//
// Created by Evgeny Poberezkin on 31/01/2022.
// Copyright © 2022 SimpleX Chat. All rights reserved.
//
import SwiftUI
import SimpleXChat
struct UserAddress: View {
@EnvironmentObject private var chatModel: ChatModel
@State private var alert: UserAddressAlert?
@State private var showAcceptRequests = false
private enum UserAddressAlert: Identifiable {
case deleteAddress
case error(title: LocalizedStringKey, error: LocalizedStringKey = "")
var id: String {
switch self {
case .deleteAddress: return "deleteAddress"
case let .error(title, _): return "error \(title)"
}
}
}
var body: some View {
ScrollView {
VStack (alignment: .leading) {
Text("You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.")
.padding(.bottom)
if let userAdress = chatModel.userAddress {
QRCode(uri: userAdress.connReqContact)
HStack {
Button {
showShareSheet(items: [userAdress.connReqContact])
} label: {
HStack {
Image(systemName: "square.and.arrow.up")
Text("Share link")
}
}
.padding()
NavigationLink {
if let contactLink = chatModel.userAddress {
AcceptRequestsView(contactLink: contactLink)
.navigationTitle("Contact requests")
.navigationBarTitleDisplayMode(.large)
}
} label: {
HStack {
Text("Contact requests")
Image(systemName: "chevron.right")
}
}
.padding()
}
.frame(maxWidth: .infinity)
Button(role: .destructive) { alert = .deleteAddress } label: {
Label("Delete address", systemImage: "trash")
}
.frame(maxWidth: .infinity)
} else {
Button {
Task {
do {
let connReqContact = try await apiCreateUserAddress()
DispatchQueue.main.async {
chatModel.userAddress = UserContactLink(connReqContact: connReqContact)
}
} catch let error {
logger.error("UserAddress apiCreateUserAddress: \(responseError(error))")
let a = getErrorAlert(error, "Error creating address")
alert = .error(title: a.title, error: a.message)
}
}
} label: { Label("Create address", systemImage: "qrcode") }
.frame(maxWidth: .infinity)
}
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.sheet(isPresented: $showAcceptRequests) {
if let contactLink = chatModel.userAddress {
AcceptRequestsView(contactLink: contactLink)
}
}
.alert(item: $alert) { alert in
switch alert {
case .deleteAddress:
return Alert(
title: Text("Delete address?"),
message: Text("All your contacts will remain connected"),
primaryButton: .destructive(Text("Delete")) {
Task {
do {
try await apiDeleteUserAddress()
DispatchQueue.main.async {
chatModel.userAddress = nil
}
} catch let error {
logger.error("UserAddress apiDeleteUserAddress: \(responseError(error))")
}
}
}, secondaryButton: .cancel()
)
case let .error(title, error):
return Alert(title: Text(title), message: Text(error))
}
}
}
}
}
struct UserAddress_Previews: PreviewProvider {
static var previews: some View {
let chatModel = ChatModel()
chatModel.userAddress = UserContactLink(connReqContact: "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D")
return Group {
UserAddress()
.environmentObject(chatModel)
UserAddress()
.environmentObject(ChatModel())
}
}
}

View File

@@ -0,0 +1,29 @@
//
// UserAddressLearnMore.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 27.04.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
struct UserAddressLearnMore: View {
var body: some View {
List {
VStack(alignment: .leading, spacing: 18) {
Text("You can share your address as a link or QR code - anybody can connect to you.")
Text("You won't lose your contacts if you later delete your address.")
Text("When people request to connect, you can accept or reject it.")
Text("Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).")
}
.listRowBackground(Color.clear)
}
}
}
struct UserAddressLearnMore_Previews: PreviewProvider {
static var previews: some View {
UserAddressLearnMore()
}
}

View File

@@ -0,0 +1,494 @@
//
// UserAddressView.swift
// SimpleX (iOS)
//
// Created by spaced4ndy on 26.04.2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import SwiftUI
import MessageUI
import SimpleXChat
struct UserAddressView: View {
@Environment(\.dismiss) var dismiss: DismissAction
@EnvironmentObject private var chatModel: ChatModel
@State var viaCreateLinkView = false
@State var shareViaProfile = false
@State private var aas = AutoAcceptState()
@State private var savedAAS = AutoAcceptState()
@State private var ignoreShareViaProfileChange = false
@State private var showMailView = false
@State private var mailViewResult: Result<MFMailComposeResult, Error>? = nil
@State private var alert: UserAddressAlert?
@State private var showSaveDialogue = false
@State private var progressIndicator = false
@FocusState private var keyboardVisible: Bool
private enum UserAddressAlert: Identifiable {
case deleteAddress
case profileAddress(on: Bool)
case shareOnCreate
case error(title: LocalizedStringKey, error: LocalizedStringKey = "")
var id: String {
switch self {
case .deleteAddress: return "deleteAddress"
case let .profileAddress(on): return "profileAddress \(on)"
case .shareOnCreate: return "shareOnCreate"
case let .error(title, _): return "error \(title)"
}
}
}
var body: some View {
ZStack {
if viaCreateLinkView {
userAddressScrollView()
} else {
userAddressScrollView()
.modifier(BackButton {
if savedAAS == aas {
dismiss()
} else {
keyboardVisible = false
showSaveDialogue = true
}
})
.confirmationDialog("Save settings?", isPresented: $showSaveDialogue) {
Button("Save auto-accept settings") {
saveAAS()
dismiss()
}
Button("Exit without saving") { dismiss() }
}
}
if progressIndicator {
ZStack {
if chatModel.userAddress != nil {
Circle()
.fill(.white)
.opacity(0.7)
.frame(width: 56, height: 56)
}
ProgressView().scaleEffect(2)
}
}
}
}
@Namespace private var bottomID
private func userAddressScrollView() -> some View {
ScrollViewReader { proxy in
userAddressView()
.onChange(of: keyboardVisible) { _ in
if keyboardVisible {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
withAnimation {
proxy.scrollTo(bottomID, anchor: .top)
}
}
}
}
}
}
private func userAddressView() -> some View {
List {
if let userAddress = chatModel.userAddress {
existingAddressView(userAddress)
.onAppear {
aas = AutoAcceptState(userAddress: userAddress)
savedAAS = aas
}
.onChange(of: aas.enable) { _ in
if !aas.enable { aas = AutoAcceptState() }
}
} else {
Section {
createAddressButton()
} footer: {
Text("Create an address to let people connect with you.")
}
Section {
learnMoreButton()
}
}
}
.alert(item: $alert) { alert in
switch alert {
case .deleteAddress:
return Alert(
title: Text("Delete address?"),
message:
shareViaProfile
? Text("All your contacts will remain connected. Profile update will be sent to your contacts.")
: Text("All your contacts will remain connected."),
primaryButton: .destructive(Text("Delete")) {
progressIndicator = true
Task {
do {
if let u = try await apiDeleteUserAddress() {
DispatchQueue.main.async {
chatModel.userAddress = nil
chatModel.updateUser(u)
if shareViaProfile {
ignoreShareViaProfileChange = true
shareViaProfile = false
}
}
}
await MainActor.run { progressIndicator = false }
} catch let error {
logger.error("UserAddressView apiDeleteUserAddress: \(responseError(error))")
await MainActor.run { progressIndicator = false }
}
}
}, secondaryButton: .cancel()
)
case let .profileAddress(on):
if on {
return Alert(
title: Text("Share address with contacts?"),
message: Text("Profile update will be sent to your contacts."),
primaryButton: .default(Text("Share")) {
setProfileAddress(on)
}, secondaryButton: .cancel() {
ignoreShareViaProfileChange = true
shareViaProfile = !on
}
)
} else {
return Alert(
title: Text("Stop sharing address?"),
message: Text("Profile update will be sent to your contacts."),
primaryButton: .default(Text("Stop sharing")) {
setProfileAddress(on)
}, secondaryButton: .cancel() {
ignoreShareViaProfileChange = true
shareViaProfile = !on
}
)
}
case .shareOnCreate:
return Alert(
title: Text("Share address with contacts?"),
message: Text("Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts."),
primaryButton: .default(Text("Share")) {
setProfileAddress(true)
ignoreShareViaProfileChange = true
shareViaProfile = true
}, secondaryButton: .cancel()
)
case let .error(title, error):
return Alert(title: Text(title), message: Text(error))
}
}
}
@ViewBuilder private func existingAddressView(_ userAddress: UserContactLink) -> some View {
Section {
QRCode(uri: userAddress.connReqContact)
shareQRCodeButton(userAddress)
if MFMailComposeViewController.canSendMail() {
shareViaEmailButton(userAddress)
} else {
shareViaEmailToButton(userAddress)
}
shareWithContactsButton()
autoAcceptToggle()
learnMoreButton()
} header: {
Text("Address")
}
if aas.enable {
autoAcceptSection()
}
Section {
deleteAddressButton()
} footer: {
Text("Your contacts will remain connected.")
}
.id(bottomID)
}
private func createAddressButton() -> some View {
Button {
progressIndicator = true
Task {
do {
let connReqContact = try await apiCreateUserAddress()
DispatchQueue.main.async {
chatModel.userAddress = UserContactLink(connReqContact: connReqContact)
alert = .shareOnCreate
progressIndicator = false
}
} catch let error {
logger.error("UserAddressView apiCreateUserAddress: \(responseError(error))")
let a = getErrorAlert(error, "Error creating address")
alert = .error(title: a.title, error: a.message)
await MainActor.run { progressIndicator = false }
}
}
} label: {
Label("Create SimpleX address", systemImage: "qrcode")
}
}
private func deleteAddressButton() -> some View {
Button(role: .destructive) {
alert = .deleteAddress
} label: {
Label("Delete address", systemImage: "trash")
.foregroundColor(Color.red)
}
}
private func shareQRCodeButton(_ userAddress: UserContactLink) -> some View {
Button {
showShareSheet(items: [userAddress.connReqContact])
} label: {
settingsRow("square.and.arrow.up") {
Text("Share address")
}
}
}
private func shareViaEmailButton(_ userAddress: UserContactLink) -> some View {
Button {
showMailView = true
} label: {
settingsRow("envelope") {
Text("Invite friends")
}
}
.sheet(isPresented: $showMailView) {
SendAddressMailView(
showMailView: $showMailView,
mailViewResult: $mailViewResult,
userAddress: userAddress
)
.edgesIgnoringSafeArea(.bottom)
}
.onChange(of: mailViewResult == nil) { _ in
if let r = mailViewResult {
switch r {
case .success: ()
case let .failure(error):
logger.error("UserAddressView share via email: \(responseError(error))")
let a = getErrorAlert(error, "Error sending email")
alert = .error(title: a.title, error: a.message)
}
mailViewResult = nil
}
}
}
private func shareViaEmailToButton(_ userAddress: UserContactLink) -> some View {
Button {
UserAddressView.shareUserAddressViaMailTo(userAddress)
} label: {
settingsRow("envelope") {
Text("Invite friends")
}
}
}
private func autoAcceptToggle() -> some View {
settingsRow("checkmark") {
Toggle("Auto-accept", isOn: $aas.enable)
.onChange(of: aas.enable) { _ in
saveAAS()
}
}
}
private func learnMoreButton() -> some View {
NavigationLink {
UserAddressLearnMore()
.navigationTitle("SimpleX address")
.navigationBarTitleDisplayMode(.large)
} label: {
settingsRow("info.circle") {
Text("About SimpleX address")
}
}
}
private func shareWithContactsButton() -> some View {
settingsRow("person") {
Toggle("Share with contacts", isOn: $shareViaProfile)
.onChange(of: shareViaProfile) { on in
if ignoreShareViaProfileChange {
ignoreShareViaProfileChange = false
} else {
alert = .profileAddress(on: on)
}
}
}
}
private func setProfileAddress(_ on: Bool) {
progressIndicator = true
Task {
do {
if let u = try await apiSetProfileAddress(on: on) {
DispatchQueue.main.async {
chatModel.updateUser(u)
}
}
await MainActor.run { progressIndicator = false }
} catch let error {
logger.error("UserAddressView apiSetProfileAddress: \(responseError(error))")
await MainActor.run { progressIndicator = false }
}
}
}
private struct AutoAcceptState: Equatable {
var enable = false
var incognito = false
var welcomeText = ""
init(enable: Bool = false, incognito: Bool = false, welcomeText: String = "") {
self.enable = enable
self.incognito = incognito
self.welcomeText = welcomeText
}
init(userAddress: UserContactLink) {
if let aa = userAddress.autoAccept {
enable = true
incognito = aa.acceptIncognito
if let msg = aa.autoReply {
welcomeText = msg.text
} else {
welcomeText = ""
}
} else {
enable = false
incognito = false
welcomeText = ""
}
}
var autoAccept: AutoAccept? {
if enable {
var autoReply: MsgContent? = nil
let s = welcomeText.trimmingCharacters(in: .whitespacesAndNewlines)
if s != "" { autoReply = .text(s) }
return AutoAccept(acceptIncognito: incognito, autoReply: autoReply)
}
return nil
}
}
@ViewBuilder private func autoAcceptSection() -> some View {
Section {
acceptIncognitoToggle()
welcomeMessageEditor()
saveAASButton()
.disabled(aas == savedAAS)
} header: {
Text("Auto-accept")
}
}
private func acceptIncognitoToggle() -> some View {
settingsRow(
aas.incognito ? "theatermasks.fill" : "theatermasks",
color: aas.incognito ? .indigo : .secondary
) {
Toggle("Accept incognito", isOn: $aas.incognito)
}
}
private func welcomeMessageEditor() -> some View {
ZStack {
Group {
if aas.welcomeText.isEmpty {
TextEditor(text: Binding.constant(NSLocalizedString("Enter welcome message… (optional)", comment: "placeholder")))
.foregroundColor(.secondary)
.disabled(true)
}
TextEditor(text: $aas.welcomeText)
.focused($keyboardVisible)
}
.padding(.horizontal, -5)
.padding(.top, -8)
.frame(height: 90, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
private func saveAASButton() -> some View {
Button {
keyboardVisible = false
saveAAS()
} label: {
Text("Save")
}
}
private func saveAAS() {
Task {
do {
if let address = try await userAddressAutoAccept(aas.autoAccept) {
chatModel.userAddress = address
savedAAS = aas
}
} catch let error {
logger.error("userAddressAutoAccept error: \(responseError(error))")
}
}
}
static func shareUserAddressViaMailTo(_ userAddress: UserContactLink) {
guard
let subject = String(format: NSLocalizedString("Let's talk in SimpleX Chat", comment: "")).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let addressStr = userAddress.connReqContact.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&"))),
let bodyWithoutAddress = (String(format: NSLocalizedString("Hi!\nConnect to me via SimpleX Chat:", comment: "")) + " ").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
else { return }
let body = bodyWithoutAddress + addressStr
let gmailUrl = URL(string: "googlegmail://co?subject=\(subject)&body=\(body)")
let outlookUrl = URL(string: "ms-outlook://compose?subject=\(subject)&body=\(body)")
let yahooUrl = URL(string: "ymail://mail/compose?subject=\(subject)&body=\(body)")
let sparkUrl = URL(string: "readdle-spark://compose?subject=\(subject)&body=\(body)")
var selectedUrl: URL
if let gmailUrl = gmailUrl, UIApplication.shared.canOpenURL(gmailUrl) {
selectedUrl = gmailUrl
} else if let outlookUrl = outlookUrl, UIApplication.shared.canOpenURL(outlookUrl) {
selectedUrl = outlookUrl
} else if let yahooUrl = yahooUrl, UIApplication.shared.canOpenURL(yahooUrl) {
selectedUrl = yahooUrl
} else if let sparkUrl = sparkUrl, UIApplication.shared.canOpenURL(sparkUrl) {
selectedUrl = sparkUrl
} else {
return
}
UIApplication.shared.open(selectedUrl, options: [:])
}
}
struct UserAddressView_Previews: PreviewProvider {
static var previews: some View {
let chatModel = ChatModel()
chatModel.userAddress = UserContactLink(connReqContact: "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D")
return Group {
UserAddressView()
.environmentObject(chatModel)
UserAddressView()
.environmentObject(ChatModel())
}
}
}

View File

@@ -2573,8 +2573,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>Thank you for installing SimpleX Chat!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">

View File

@@ -361,6 +361,10 @@ Dostupné ve verzi 5.1</target>
<target>O SimpleX chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="About SimpleX address" xml:space="preserve">
<source>About SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accent color" xml:space="preserve">
<source>Accent color</source>
<target>Zbarvení</target>
@@ -387,9 +391,8 @@ Dostupné ve verzi 5.1</target>
<target>Přijmout inkognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept requests" xml:space="preserve">
<source>Accept requests</source>
<target>Přijímat žádosti</target>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve">
@@ -422,6 +425,10 @@ Dostupné ve verzi 5.1</target>
<target>Přidat uvítací zprávu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Address" xml:space="preserve">
<source>Address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Admins can create the links to join groups." xml:space="preserve">
<source>Admins can create the links to join groups.</source>
<target>Správci mohou vytvářet odkazy pro připojení ke skupinám.</target>
@@ -447,9 +454,12 @@ Dostupné ve verzi 5.1</target>
<target>Všechny zprávy budou smazány tuto akci nelze vrátit zpět! Zprávy budou smazány POUZE pro vás.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected" xml:space="preserve">
<source>All your contacts will remain connected</source>
<target>Všechny vaše kontakty zůstanou připojeny</target>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve">
<source>All your contacts will remain connected. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow" xml:space="preserve">
@@ -612,6 +622,10 @@ Dostupné ve verzi 5.1</target>
<target>Ověřování není k dispozici</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept" xml:space="preserve">
<source>Auto-accept</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept contact requests" xml:space="preserve">
<source>Auto-accept contact requests</source>
<target>Automatické přijímání žádostí o kontakt</target>
@@ -622,11 +636,6 @@ Dostupné ve verzi 5.1</target>
<target>Automaticky přijímat obrázky</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Automatically" xml:space="preserve">
<source>Automatically</source>
<target>Automaticky</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Zpět</target>
@@ -992,11 +1001,6 @@ Dostupné ve verzi 5.1</target>
<target>Předvolby kontaktů</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests" xml:space="preserve">
<source>Contact requests</source>
<target>Žádosti o kontakt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve">
<source>Contacts can mark messages for deletion; you will be able to view them.</source>
<target>Kontakty mohou označit zprávy ke smazání; vy je budete moci zobrazit.</target>
@@ -1017,9 +1021,12 @@ Dostupné ve verzi 5.1</target>
<target>Vytvořit</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create address" xml:space="preserve">
<source>Create address</source>
<target>Vytvořit adresu</target>
<trans-unit id="Create SimpleX address" xml:space="preserve">
<source>Create SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create file" xml:space="preserve">
@@ -1590,6 +1597,10 @@ Dostupné ve verzi 5.1</target>
<target>Zadejte server ručně</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message… (optional)" xml:space="preserve">
<source>Enter welcome message… (optional)</source>
<note>placeholder</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
<source>Error</source>
<target>Chyba</target>
@@ -2343,6 +2354,10 @@ Dostupné ve verzi 5.1</target>
<target>Velký soubor!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave" xml:space="preserve">
<source>Leave</source>
<target>Opustit</target>
@@ -2987,6 +3002,10 @@ Dostupné ve verzi 5.1</target>
<target>Heslo profilu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile update will be sent to your contacts." xml:space="preserve">
<source>Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit audio/video calls." xml:space="preserve">
<source>Prohibit audio/video calls.</source>
<target>Zákaz audio/video hovorů.</target>
@@ -3247,6 +3266,10 @@ Dostupné ve verzi 5.1</target>
<target>Uložit archiv</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Uložení profilu skupiny</target>
@@ -3282,6 +3305,10 @@ Dostupné ve verzi 5.1</target>
<target>Uložit servery?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Uložit uvítací zprávu?</target>
@@ -3472,6 +3499,14 @@ Dostupné ve verzi 5.1</target>
<target>Sdílet</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Share address" xml:space="preserve">
<source>Share address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share address with contacts?" xml:space="preserve">
<source>Share address with contacts?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share invitation link" xml:space="preserve">
<source>Share invitation link</source>
<target>Sdílet odkaz na pozvánku</target>
@@ -3487,6 +3522,10 @@ Dostupné ve verzi 5.1</target>
<target>Jednorázový zvací odkaz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve">
<source>Share with contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
<source>Show QR code</source>
<target>Zobrazit QR kód</target>
@@ -3537,6 +3576,10 @@ Dostupné ve verzi 5.1</target>
<target>Zapnutý zámek SimpleX Lock</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX address" xml:space="preserve">
<source>SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
<source>SimpleX contact address</source>
<target>SimpleX kontaktní adresa</target>
@@ -3632,6 +3675,14 @@ Dostupné ve verzi 5.1</target>
<target>Zastavit odesílání souboru?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing" xml:space="preserve">
<source>Stop sharing</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing address?" xml:space="preserve">
<source>Stop sharing address?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Submit" xml:space="preserve">
<source>Submit</source>
<target>Odeslat</target>
@@ -3727,9 +3778,9 @@ Dostupné ve verzi 5.1</target>
<target>Děkujeme, že jste si nainstalovali SimpleX Chat!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<target>Díky uživatelům - [přispějte přes Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</target>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target>Díky uživatelům - [přispějte přes Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">
@@ -4228,6 +4279,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Když je k dispozici</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When people request to connect, you can accept or reject it." xml:space="preserve">
<source>When people request to connect, you can accept or reject it.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." xml:space="preserve">
<source>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</source>
<target>Pokud s někým sdílíte inkognito profil, bude tento profil použit pro skupiny, do kterých vás pozve.</target>
@@ -4320,9 +4375,13 @@ SimpleX zámek musí být povolen.</target>
<target>Můžete sdílet odkaz nebo QR kód - ke skupině se bude moci připojit kdokoli. O členy skupiny nepřijdete, pokud ji později odstraníte.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it." xml:space="preserve">
<source>You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.</source>
<target>Můžete sdílet svou adresu jako odkaz nebo jako QR kód - kdokoli se k vám bude moci připojit. O své kontakty nepřijdete, pokud ji později smažete.</target>
<trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve">
<source>You can share this address with your contacts to let them connect with **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve">
<source>You can share your address as a link or QR code - anybody can connect to you.</source>
<target>Můžete sdílet svou adresu jako odkaz nebo jako QR kód - kdokoli se k vám bude moci připojit.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve">
@@ -4435,6 +4494,11 @@ SimpleX zámek musí být povolen.</target>
<target>Přestanete dostávat zprávy z této skupiny. Historie chatu bude zachována.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve">
<source>You won't lose your contacts if you later delete your address.</source>
<target>O své kontakty nepřijdete, pokud ji později smažete.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve">
<source>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</source>
<target>Snažíte se pozvat kontakt, se kterým jste sdíleli inkognito profil, do skupiny, ve které používáte svůj hlavní profil</target>
@@ -4462,7 +4526,7 @@ SimpleX zámek musí být povolen.</target>
</trans-unit>
<trans-unit id="Your SimpleX contact address" xml:space="preserve">
<source>Your SimpleX contact address</source>
<target>Vaše kontaktní adresa SimpleX</target>
<target>Vaše adresa SimpleX</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your XFTP servers" xml:space="preserve">
@@ -4532,6 +4596,10 @@ Toto připojení můžete zrušit a kontakt odebrat (a zkusit to později s nov
<target>Vaše kontakty mohou povolit úplné mazání zpráv.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
<source>Your current chat database will be DELETED and REPLACED with the imported one.</source>
<target>Vaše aktuální chat databáze bude ODSTRANĚNA a NAHRAZENA importovanou.</target>

View File

@@ -361,6 +361,10 @@ Verfügbar ab v5.1</target>
<target>Über SimpleX Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="About SimpleX address" xml:space="preserve">
<source>About SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accent color" xml:space="preserve">
<source>Accent color</source>
<target>Akzentfarbe</target>
@@ -387,9 +391,8 @@ Verfügbar ab v5.1</target>
<target>Inkognito akzeptieren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept requests" xml:space="preserve">
<source>Accept requests</source>
<target>Anfragen annehmen</target>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve">
@@ -422,6 +425,10 @@ Verfügbar ab v5.1</target>
<target>Begrüßungsmeldung hinzufügen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Address" xml:space="preserve">
<source>Address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Admins can create the links to join groups." xml:space="preserve">
<source>Admins can create the links to join groups.</source>
<target>Administratoren können Links für den Beitritt zu Gruppen erzeugen.</target>
@@ -447,9 +454,12 @@ Verfügbar ab v5.1</target>
<target>Alle Nachrichten werden gelöscht - dies kann nicht rückgängig gemacht werden! Die Nachrichten werden NUR bei Ihnen gelöscht.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected" xml:space="preserve">
<source>All your contacts will remain connected</source>
<target>Alle Ihre Kontakte bleiben verbunden</target>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve">
<source>All your contacts will remain connected. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow" xml:space="preserve">
@@ -612,6 +622,10 @@ Verfügbar ab v5.1</target>
<target>Authentifizierung nicht verfügbar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept" xml:space="preserve">
<source>Auto-accept</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept contact requests" xml:space="preserve">
<source>Auto-accept contact requests</source>
<target>Kontaktanfragen automatisch annehmen</target>
@@ -622,11 +636,6 @@ Verfügbar ab v5.1</target>
<target>Bilder automatisch akzeptieren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Automatically" xml:space="preserve">
<source>Automatically</source>
<target>Automatisch</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Zurück</target>
@@ -992,11 +1001,6 @@ Verfügbar ab v5.1</target>
<target>Kontakt Präferenzen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests" xml:space="preserve">
<source>Contact requests</source>
<target>Kontaktanfragen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve">
<source>Contacts can mark messages for deletion; you will be able to view them.</source>
<target>Ihre Kontakte können Nachrichten zum Löschen markieren. Sie können diese Nachrichten trotzdem anschauen.</target>
@@ -1017,9 +1021,12 @@ Verfügbar ab v5.1</target>
<target>Erstellen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create address" xml:space="preserve">
<source>Create address</source>
<target>Adresse erstellen</target>
<trans-unit id="Create SimpleX address" xml:space="preserve">
<source>Create SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create file" xml:space="preserve">
@@ -1590,6 +1597,10 @@ Verfügbar ab v5.1</target>
<target>Geben Sie den Server manuell ein</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message… (optional)" xml:space="preserve">
<source>Enter welcome message… (optional)</source>
<note>placeholder</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
<source>Error</source>
<target>Fehler</target>
@@ -2343,6 +2354,10 @@ Verfügbar ab v5.1</target>
<target>Große Datei!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave" xml:space="preserve">
<source>Leave</source>
<target>Verlassen</target>
@@ -2987,6 +3002,10 @@ Verfügbar ab v5.1</target>
<target>Passwort für Profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile update will be sent to your contacts." xml:space="preserve">
<source>Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit audio/video calls." xml:space="preserve">
<source>Prohibit audio/video calls.</source>
<target>Audio/Video Anrufe nicht erlauben.</target>
@@ -3247,6 +3266,10 @@ Verfügbar ab v5.1</target>
<target>Archiv speichern</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Gruppenprofil speichern</target>
@@ -3282,6 +3305,10 @@ Verfügbar ab v5.1</target>
<target>Alle Server speichern?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Begrüßungsmeldung speichern?</target>
@@ -3472,6 +3499,14 @@ Verfügbar ab v5.1</target>
<target>Teilen</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Share address" xml:space="preserve">
<source>Share address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share address with contacts?" xml:space="preserve">
<source>Share address with contacts?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share invitation link" xml:space="preserve">
<source>Share invitation link</source>
<target>Einladungslink teilen</target>
@@ -3487,6 +3522,10 @@ Verfügbar ab v5.1</target>
<target>Einmal-Einladungslink teilen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve">
<source>Share with contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
<source>Show QR code</source>
<target>QR-Code anzeigen</target>
@@ -3537,6 +3576,10 @@ Verfügbar ab v5.1</target>
<target>SimpleX Sperre aktiviert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX address" xml:space="preserve">
<source>SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
<source>SimpleX contact address</source>
<target>SimpleX Kontaktadressen-Link</target>
@@ -3632,6 +3675,14 @@ Verfügbar ab v5.1</target>
<target>Das Senden der Datei beenden?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing" xml:space="preserve">
<source>Stop sharing</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing address?" xml:space="preserve">
<source>Stop sharing address?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Submit" xml:space="preserve">
<source>Submit</source>
<target>Übermitteln</target>
@@ -3727,9 +3778,9 @@ Verfügbar ab v5.1</target>
<target>Vielen Dank, dass Sie SimpleX Chat installiert haben!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<target>Dank der Nutzer - [Tragen Sie per Weblate bei](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</target>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target>Dank der Nutzer - [Tragen Sie per Weblate bei](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">
@@ -4228,6 +4279,10 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Wenn verfügbar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When people request to connect, you can accept or reject it." xml:space="preserve">
<source>When people request to connect, you can accept or reject it.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." xml:space="preserve">
<source>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</source>
<target>Wenn Sie ein Inkognito-Profil mit Jemandem teilen, wird dieses Profil auch für die Gruppen verwendet, für die Sie von diesem Kontakt eingeladen werden.</target>
@@ -4320,9 +4375,13 @@ Dafür muss die SimpleX Sperre aktiviert sein.</target>
<target>Sie können diesen Link oder QR-Code teilen - Damit kann jede Person der Gruppe beitreten. Wenn Sie den Link später löschen, werden Sie keine Gruppenmitglieder verlieren, die der Gruppe darüber beigetreten sind.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it." xml:space="preserve">
<source>You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.</source>
<target>Sie können Ihre Adresse als Link oder als QR-Code teilen Jede Person kann sich darüber mit Ihnen verbinden. Sie werden Ihre mit dieser Adresse verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen.</target>
<trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve">
<source>You can share this address with your contacts to let them connect with **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve">
<source>You can share your address as a link or QR code - anybody can connect to you.</source>
<target>Sie können Ihre Adresse als Link oder als QR-Code teilen Jede Person kann sich darüber mit Ihnen verbinden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve">
@@ -4435,6 +4494,11 @@ Dafür muss die SimpleX Sperre aktiviert sein.</target>
<target>Sie werden von dieser Gruppe keine Nachrichten mehr erhalten. Der Chatverlauf wird beibehalten.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve">
<source>You won't lose your contacts if you later delete your address.</source>
<target>Sie werden Ihre mit dieser Adresse verbundenen Kontakte nicht verlieren, wenn Sie diese Adresse später löschen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve">
<source>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</source>
<target>Sie versuchen, einen Kontakt, mit dem Sie ein Inkognito-Profil geteilt haben, in die Gruppe einzuladen, in der Sie Ihr Hauptprofil verwenden</target>
@@ -4532,6 +4596,10 @@ Sie können diese Verbindung abbrechen und den Kontakt entfernen (und es später
<target>Ihre Kontakte können die unwiederbringliche Löschung von Nachrichten erlauben.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
<source>Your current chat database will be DELETED and REPLACED with the imported one.</source>
<target>Ihre aktuelle Chat-Datenbank wird GELÖSCHT und durch die Importierte ERSETZT.</target>

View File

@@ -361,6 +361,11 @@ Available in v5.1</target>
<target>About SimpleX Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="About SimpleX address" xml:space="preserve">
<source>About SimpleX address</source>
<target>About SimpleX address</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accent color" xml:space="preserve">
<source>Accent color</source>
<target>Accent color</target>
@@ -387,9 +392,9 @@ Available in v5.1</target>
<target>Accept incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept requests" xml:space="preserve">
<source>Accept requests</source>
<target>Accept requests</target>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
<target>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve">
@@ -422,6 +427,11 @@ Available in v5.1</target>
<target>Add welcome message</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Address" xml:space="preserve">
<source>Address</source>
<target>Address</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Admins can create the links to join groups." xml:space="preserve">
<source>Admins can create the links to join groups.</source>
<target>Admins can create the links to join groups.</target>
@@ -447,9 +457,14 @@ Available in v5.1</target>
<target>All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected" xml:space="preserve">
<source>All your contacts will remain connected</source>
<target>All your contacts will remain connected</target>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<target>All your contacts will remain connected.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve">
<source>All your contacts will remain connected. Profile update will be sent to your contacts.</source>
<target>All your contacts will remain connected. Profile update will be sent to your contacts.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow" xml:space="preserve">
@@ -612,6 +627,11 @@ Available in v5.1</target>
<target>Authentication unavailable</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept" xml:space="preserve">
<source>Auto-accept</source>
<target>Auto-accept</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept contact requests" xml:space="preserve">
<source>Auto-accept contact requests</source>
<target>Auto-accept contact requests</target>
@@ -622,11 +642,6 @@ Available in v5.1</target>
<target>Auto-accept images</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Automatically" xml:space="preserve">
<source>Automatically</source>
<target>Automatically</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Back</target>
@@ -992,11 +1007,6 @@ Available in v5.1</target>
<target>Contact preferences</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests" xml:space="preserve">
<source>Contact requests</source>
<target>Contact requests</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve">
<source>Contacts can mark messages for deletion; you will be able to view them.</source>
<target>Contacts can mark messages for deletion; you will be able to view them.</target>
@@ -1017,9 +1027,14 @@ Available in v5.1</target>
<target>Create</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create address" xml:space="preserve">
<source>Create address</source>
<target>Create address</target>
<trans-unit id="Create SimpleX address" xml:space="preserve">
<source>Create SimpleX address</source>
<target>Create SimpleX address</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source>
<target>Create an address to let people connect with you.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create file" xml:space="preserve">
@@ -1590,6 +1605,11 @@ Available in v5.1</target>
<target>Enter server manually</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message… (optional)" xml:space="preserve">
<source>Enter welcome message… (optional)</source>
<target>Enter welcome message… (optional)</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
<source>Error</source>
<target>Error</target>
@@ -2343,6 +2363,11 @@ Available in v5.1</target>
<target>Large file!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source>
<target>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave" xml:space="preserve">
<source>Leave</source>
<target>Leave</target>
@@ -2987,6 +3012,11 @@ Available in v5.1</target>
<target>Profile password</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile update will be sent to your contacts." xml:space="preserve">
<source>Profile update will be sent to your contacts.</source>
<target>Profile update will be sent to your contacts.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit audio/video calls." xml:space="preserve">
<source>Prohibit audio/video calls.</source>
<target>Prohibit audio/video calls.</target>
@@ -3247,6 +3277,11 @@ Available in v5.1</target>
<target>Save archive</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Save auto-accept settings</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Save group profile</target>
@@ -3282,6 +3317,11 @@ Available in v5.1</target>
<target>Save servers?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<target>Save settings?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Save welcome message?</target>
@@ -3472,6 +3512,16 @@ Available in v5.1</target>
<target>Share</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Share address" xml:space="preserve">
<source>Share address</source>
<target>Share address</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share address with contacts?" xml:space="preserve">
<source>Share address with contacts?</source>
<target>Share address with contacts?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share invitation link" xml:space="preserve">
<source>Share invitation link</source>
<target>Share invitation link</target>
@@ -3487,6 +3537,11 @@ Available in v5.1</target>
<target>Share one-time invitation link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve">
<source>Share with contacts</source>
<target>Share with contacts</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
<source>Show QR code</source>
<target>Show QR code</target>
@@ -3537,6 +3592,11 @@ Available in v5.1</target>
<target>SimpleX Lock turned on</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX address" xml:space="preserve">
<source>SimpleX address</source>
<target>SimpleX address</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
<source>SimpleX contact address</source>
<target>SimpleX contact address</target>
@@ -3632,6 +3692,16 @@ Available in v5.1</target>
<target>Stop sending file?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing" xml:space="preserve">
<source>Stop sharing</source>
<target>Stop sharing</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing address?" xml:space="preserve">
<source>Stop sharing address?</source>
<target>Stop sharing address?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Submit" xml:space="preserve">
<source>Submit</source>
<target>Submit</target>
@@ -3727,9 +3797,9 @@ Available in v5.1</target>
<target>Thank you for installing SimpleX Chat!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<target>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</target>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">
@@ -4228,6 +4298,11 @@ To connect, please ask your contact to create another connection link and check
<target>When available</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When people request to connect, you can accept or reject it." xml:space="preserve">
<source>When people request to connect, you can accept or reject it.</source>
<target>When people request to connect, you can accept or reject it.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." xml:space="preserve">
<source>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</source>
<target>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</target>
@@ -4320,9 +4395,14 @@ SimpleX Lock must be enabled.</target>
<target>You can share a link or a QR code - anybody will be able to join the group. You won't lose members of the group if you later delete it.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it." xml:space="preserve">
<source>You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.</source>
<target>You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.</target>
<trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve">
<source>You can share this address with your contacts to let them connect with **%@**.</source>
<target>You can share this address with your contacts to let them connect with **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve">
<source>You can share your address as a link or QR code - anybody can connect to you.</source>
<target>You can share your address as a link or QR code - anybody can connect to you.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve">
@@ -4435,6 +4515,11 @@ SimpleX Lock must be enabled.</target>
<target>You will stop receiving messages from this group. Chat history will be preserved.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve">
<source>You won't lose your contacts if you later delete your address.</source>
<target>You won't lose your contacts if you later delete your address.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve">
<source>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</source>
<target>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</target>
@@ -4460,9 +4545,9 @@ SimpleX Lock must be enabled.</target>
<target>Your SMP servers</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your SimpleX contact address" xml:space="preserve">
<source>Your SimpleX contact address</source>
<target>Your SimpleX contact address</target>
<trans-unit id="Your SimpleX address" xml:space="preserve">
<source>Your SimpleX address</source>
<target>Your SimpleX address</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your XFTP servers" xml:space="preserve">
@@ -4532,6 +4617,11 @@ You can cancel this connection and remove the contact (and try later with a new
<target>Your contacts can allow full message deletion.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source>
<target>Your contacts will remain connected.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
<source>Your current chat database will be DELETED and REPLACED with the imported one.</source>
<target>Your current chat database will be DELETED and REPLACED with the imported one.</target>

View File

@@ -361,6 +361,10 @@ Disponible en v5.1</target>
<target>Acerca de SimpleX Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="About SimpleX address" xml:space="preserve">
<source>About SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accent color" xml:space="preserve">
<source>Accent color</source>
<target>Color</target>
@@ -387,9 +391,8 @@ Disponible en v5.1</target>
<target>Aceptar incógnito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept requests" xml:space="preserve">
<source>Accept requests</source>
<target>Aceptar solicitudes</target>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve">
@@ -422,6 +425,10 @@ Disponible en v5.1</target>
<target>Agregar mensaje de bienvenida</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Address" xml:space="preserve">
<source>Address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Admins can create the links to join groups." xml:space="preserve">
<source>Admins can create the links to join groups.</source>
<target>Los administradores pueden crear los enlaces para unirse a los grupos.</target>
@@ -447,9 +454,12 @@ Disponible en v5.1</target>
<target>Se eliminarán todos los mensajes SOLO para tí. ¡No puede deshacerse!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected" xml:space="preserve">
<source>All your contacts will remain connected</source>
<target>Todos tus contactos permanecerán conectados</target>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve">
<source>All your contacts will remain connected. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow" xml:space="preserve">
@@ -612,6 +622,10 @@ Disponible en v5.1</target>
<target>Autenticación no disponible</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept" xml:space="preserve">
<source>Auto-accept</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept contact requests" xml:space="preserve">
<source>Auto-accept contact requests</source>
<target>Aceptar automáticamente solicitudes del contacto</target>
@@ -622,11 +636,6 @@ Disponible en v5.1</target>
<target>Aceptar automáticamente imágenes</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Automatically" xml:space="preserve">
<source>Automatically</source>
<target>Automáticamente</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Volver</target>
@@ -992,11 +1001,6 @@ Disponible en v5.1</target>
<target>Preferencias de contacto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests" xml:space="preserve">
<source>Contact requests</source>
<target>Solicitud del contacto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve">
<source>Contacts can mark messages for deletion; you will be able to view them.</source>
<target>El contacto solo puede marcar los mensajes para eliminar. Tu podrás verlos.</target>
@@ -1017,9 +1021,12 @@ Disponible en v5.1</target>
<target>Crear</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create address" xml:space="preserve">
<source>Create address</source>
<target>Crear dirección</target>
<trans-unit id="Create SimpleX address" xml:space="preserve">
<source>Create SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create file" xml:space="preserve">
@@ -1590,6 +1597,10 @@ Disponible en v5.1</target>
<target>Introduce el servidor manualmente</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message… (optional)" xml:space="preserve">
<source>Enter welcome message… (optional)</source>
<note>placeholder</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
<source>Error</source>
<target>Error</target>
@@ -2343,6 +2354,10 @@ Disponible en v5.1</target>
<target>¡Archivo grande!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave" xml:space="preserve">
<source>Leave</source>
<target>Salir</target>
@@ -2987,6 +3002,10 @@ Disponible en v5.1</target>
<target>Contraseña del perfil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile update will be sent to your contacts." xml:space="preserve">
<source>Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit audio/video calls." xml:space="preserve">
<source>Prohibit audio/video calls.</source>
<target>Prohibir las llamadas/videollamadas.</target>
@@ -3247,6 +3266,10 @@ Disponible en v5.1</target>
<target>Guardar archivo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Guardar perfil de grupo</target>
@@ -3282,6 +3305,10 @@ Disponible en v5.1</target>
<target>¿Guardar servidores?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>¿Guardar mensaje de bienvenida?</target>
@@ -3472,6 +3499,14 @@ Disponible en v5.1</target>
<target>Compartir</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Share address" xml:space="preserve">
<source>Share address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share address with contacts?" xml:space="preserve">
<source>Share address with contacts?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share invitation link" xml:space="preserve">
<source>Share invitation link</source>
<target>Compartir enlace de invitación</target>
@@ -3487,6 +3522,10 @@ Disponible en v5.1</target>
<target>Compartir enlace de invitación de un uso</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve">
<source>Share with contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
<source>Show QR code</source>
<target>Mostrar código QR</target>
@@ -3537,6 +3576,10 @@ Disponible en v5.1</target>
<target>Bloqueo SimpleX activado</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX address" xml:space="preserve">
<source>SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
<source>SimpleX contact address</source>
<target>Dirección de contacto SimpleX</target>
@@ -3632,6 +3675,14 @@ Disponible en v5.1</target>
<target>¿Dejar de enviar el archivo?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing" xml:space="preserve">
<source>Stop sharing</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing address?" xml:space="preserve">
<source>Stop sharing address?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Submit" xml:space="preserve">
<source>Submit</source>
<target>Enviar</target>
@@ -3727,8 +3778,8 @@ Disponible en v5.1</target>
<target>¡Gracias por instalar SimpleX Chat!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target>Gracias a los usuarios: [contribuye vía Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#traducir-el-aplicaciones)!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4229,6 +4280,10 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb
<target>Cuando esté disponible</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When people request to connect, you can accept or reject it." xml:space="preserve">
<source>When people request to connect, you can accept or reject it.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." xml:space="preserve">
<source>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</source>
<target>Cuando compartes un perfil incógnito con alguien, este perfil también se usará para los grupos a los que te inviten.</target>
@@ -4321,9 +4376,13 @@ Bloqueo SimpleX debe estar activado.</target>
<target>Puedes compartir un enlace o un código QR: cualquiera podrá unirse al grupo. Si lo eliminas más tarde los miembros del grupo no se perderán.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it." xml:space="preserve">
<source>You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.</source>
<target>Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo. Si lo eliminas más tarde tus contactos no se perderán.</target>
<trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve">
<source>You can share this address with your contacts to let them connect with **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve">
<source>You can share your address as a link or QR code - anybody can connect to you.</source>
<target>Puedes compartir tu dirección como enlace o como código QR: cualquiera podrá conectarse contigo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve">
@@ -4436,6 +4495,11 @@ Bloqueo SimpleX debe estar activado.</target>
<target>Dejarás de recibir mensajes de este grupo. El historial del chat se conservará.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve">
<source>You won't lose your contacts if you later delete your address.</source>
<target>Si lo eliminas más tarde tus contactos no se perderán.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve">
<source>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</source>
<target>Estás intentando invitar a un contacto con el que compartes un perfil incógnito a un grupo en el que usas tu perfil principal</target>
@@ -4463,7 +4527,7 @@ Bloqueo SimpleX debe estar activado.</target>
</trans-unit>
<trans-unit id="Your SimpleX contact address" xml:space="preserve">
<source>Your SimpleX contact address</source>
<target>Mi dirección de contacto SimpleX</target>
<target>Mi dirección SimpleX</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your XFTP servers" xml:space="preserve">
@@ -4533,6 +4597,10 @@ Puedes cancelar esta conexión y eliminar el contacto (e intentarlo más tarde c
<target>Tus contactos pueden permitir la eliminación completa de mensajes.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
<source>Your current chat database will be DELETED and REPLACED with the imported one.</source>
<target>La base de datos actual será ELIMINADA y SUSTITUIDA por la importada.</target>

View File

@@ -2640,8 +2640,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>Thank you for installing SimpleX Chat!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">

View File

@@ -361,6 +361,10 @@ Disponible dans la v5.1</target>
<target>À propos de SimpleX Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="About SimpleX address" xml:space="preserve">
<source>About SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accent color" xml:space="preserve">
<source>Accent color</source>
<target>Couleur principale</target>
@@ -387,9 +391,8 @@ Disponible dans la v5.1</target>
<target>Accepter en incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept requests" xml:space="preserve">
<source>Accept requests</source>
<target>Accepter les demandes</target>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve">
@@ -422,6 +425,10 @@ Disponible dans la v5.1</target>
<target>Ajouter un message d'accueil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Address" xml:space="preserve">
<source>Address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Admins can create the links to join groups." xml:space="preserve">
<source>Admins can create the links to join groups.</source>
<target>Les admins peuvent créer les liens qui permettent de rejoindre les groupes.</target>
@@ -447,9 +454,12 @@ Disponible dans la v5.1</target>
<target>Tous les messages seront supprimés - impossible de revenir en arrière ! Les messages seront supprimés UNIQUEMENT pour vous.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected" xml:space="preserve">
<source>All your contacts will remain connected</source>
<target>Tous vos contacts resteront connectés</target>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve">
<source>All your contacts will remain connected. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow" xml:space="preserve">
@@ -612,6 +622,10 @@ Disponible dans la v5.1</target>
<target>Authentification indisponible</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept" xml:space="preserve">
<source>Auto-accept</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept contact requests" xml:space="preserve">
<source>Auto-accept contact requests</source>
<target>Demandes de contact auto-acceptées</target>
@@ -622,11 +636,6 @@ Disponible dans la v5.1</target>
<target>Images auto-acceptées</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Automatically" xml:space="preserve">
<source>Automatically</source>
<target>Automatiquement</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Retour</target>
@@ -992,11 +1001,6 @@ Disponible dans la v5.1</target>
<target>Préférences de contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests" xml:space="preserve">
<source>Contact requests</source>
<target>Demandes de contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve">
<source>Contacts can mark messages for deletion; you will be able to view them.</source>
<target>Vos contacts peuvent marquer les messages pour les supprimer ; vous pourrez les consulter.</target>
@@ -1017,9 +1021,12 @@ Disponible dans la v5.1</target>
<target>Créer</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create address" xml:space="preserve">
<source>Create address</source>
<target>Créer une adresse</target>
<trans-unit id="Create SimpleX address" xml:space="preserve">
<source>Create SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create file" xml:space="preserve">
@@ -1590,6 +1597,10 @@ Disponible dans la v5.1</target>
<target>Entrer un serveur manuellement</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message… (optional)" xml:space="preserve">
<source>Enter welcome message… (optional)</source>
<note>placeholder</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
<source>Error</source>
<target>Erreur</target>
@@ -2343,6 +2354,10 @@ Disponible dans la v5.1</target>
<target>Fichier trop lourd !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave" xml:space="preserve">
<source>Leave</source>
<target>Quitter</target>
@@ -2987,6 +3002,10 @@ Disponible dans la v5.1</target>
<target>Mot de passe de profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile update will be sent to your contacts." xml:space="preserve">
<source>Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit audio/video calls." xml:space="preserve">
<source>Prohibit audio/video calls.</source>
<target>Interdire les appels audio/vidéo.</target>
@@ -3247,6 +3266,10 @@ Disponible dans la v5.1</target>
<target>Sauvegarder l'archive</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Sauvegarder le profil du groupe</target>
@@ -3282,6 +3305,10 @@ Disponible dans la v5.1</target>
<target>Sauvegarder les serveurs ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Sauvegarder le message d'accueil ?</target>
@@ -3472,6 +3499,14 @@ Disponible dans la v5.1</target>
<target>Partager</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Share address" xml:space="preserve">
<source>Share address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share address with contacts?" xml:space="preserve">
<source>Share address with contacts?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share invitation link" xml:space="preserve">
<source>Share invitation link</source>
<target>Partager le lien d'invitation</target>
@@ -3487,6 +3522,10 @@ Disponible dans la v5.1</target>
<target>Partager un lien d'invitation unique</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve">
<source>Share with contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
<source>Show QR code</source>
<target>Afficher le code QR</target>
@@ -3537,6 +3576,10 @@ Disponible dans la v5.1</target>
<target>SimpleX Lock activé</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX address" xml:space="preserve">
<source>SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
<source>SimpleX contact address</source>
<target>Adresse de contact SimpleX</target>
@@ -3632,6 +3675,14 @@ Disponible dans la v5.1</target>
<target>Arrêter l'envoi du fichier ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing" xml:space="preserve">
<source>Stop sharing</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing address?" xml:space="preserve">
<source>Stop sharing address?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Submit" xml:space="preserve">
<source>Submit</source>
<target>Soumettre</target>
@@ -3727,9 +3778,9 @@ Disponible dans la v5.1</target>
<target>Merci d'avoir installé SimpleX Chat!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<target>Merci aux utilisateurs - [contribuer via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps) !</target>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target>Merci aux utilisateurs - [contribuer via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat) !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">
@@ -4228,6 +4279,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Quand disponible</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When people request to connect, you can accept or reject it." xml:space="preserve">
<source>When people request to connect, you can accept or reject it.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." xml:space="preserve">
<source>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</source>
<target>Lorsque vous partagez un profil incognito avec quelqu'un, ce profil sera utilisé pour les groupes auxquels il vous invite.</target>
@@ -4320,9 +4375,13 @@ SimpleX Lock doit être activé.</target>
<target>Vous pouvez partager un lien ou un code QR - n'importe qui pourra rejoindre le groupe. Vous ne perdrez pas les membres du groupe si vous le supprimez par la suite.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it." xml:space="preserve">
<source>You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.</source>
<target>Vous pouvez partager votre adresse sous forme de lien ou de code QR - n'importe qui pourra se connecter à vous. Vous ne perdrez pas vos contacts si vous la supprimez par la suite.</target>
<trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve">
<source>You can share this address with your contacts to let them connect with **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve">
<source>You can share your address as a link or QR code - anybody can connect to you.</source>
<target>Vous pouvez partager votre adresse sous forme de lien ou de code QR - n'importe qui pourra se connecter à vous.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve">
@@ -4435,6 +4494,11 @@ SimpleX Lock doit être activé.</target>
<target>Vous ne recevrez plus de messages de ce groupe. L'historique du chat sera conservé.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve">
<source>You won't lose your contacts if you later delete your address.</source>
<target>Vous ne perdrez pas vos contacts si vous la supprimez par la suite.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve">
<source>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</source>
<target>Vous essayez d'inviter un contact avec lequel vous avez partagé un profil incognito à rejoindre le groupe dans lequel vous utilisez votre profil principal</target>
@@ -4462,7 +4526,7 @@ SimpleX Lock doit être activé.</target>
</trans-unit>
<trans-unit id="Your SimpleX contact address" xml:space="preserve">
<source>Your SimpleX contact address</source>
<target>Votre adresse de contact SimpleX</target>
<target>Votre adresse SimpleX</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your XFTP servers" xml:space="preserve">
@@ -4532,6 +4596,10 @@ Vous pouvez annuler la connexion et supprimer le contact (et réessayer plus tar
<target>Vos contacts peuvent autoriser la suppression complète des messages.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
<source>Your current chat database will be DELETED and REPLACED with the imported one.</source>
<target>Votre base de données de chat actuelle va être SUPPRIMEE et REMPLACEE par celle importée.</target>

View File

@@ -2569,8 +2569,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>Thank you for installing SimpleX Chat!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">

View File

@@ -361,6 +361,10 @@ Disponibile nella v5.1</target>
<target>Riguardo SimpleX Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="About SimpleX address" xml:space="preserve">
<source>About SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accent color" xml:space="preserve">
<source>Accent color</source>
<target>Colore principale</target>
@@ -387,9 +391,8 @@ Disponibile nella v5.1</target>
<target>Accetta in incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept requests" xml:space="preserve">
<source>Accept requests</source>
<target>Accetta le richieste</target>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Add preset servers" xml:space="preserve">
@@ -422,6 +425,10 @@ Disponibile nella v5.1</target>
<target>Aggiungi messaggio di benvenuto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Address" xml:space="preserve">
<source>Address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Admins can create the links to join groups." xml:space="preserve">
<source>Admins can create the links to join groups.</source>
<target>Gli amministratori possono creare i link per entrare nei gruppi.</target>
@@ -447,9 +454,12 @@ Disponibile nella v5.1</target>
<target>Tutti i messaggi verranno eliminati, non è reversibile! I messaggi verranno eliminati SOLO per te.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected" xml:space="preserve">
<source>All your contacts will remain connected</source>
<target>Tutti i tuoi contatti resteranno connessi</target>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
<source>All your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected. Profile update will be sent to your contacts." xml:space="preserve">
<source>All your contacts will remain connected. Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow" xml:space="preserve">
@@ -612,6 +622,10 @@ Disponibile nella v5.1</target>
<target>Autenticazione non disponibile</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept" xml:space="preserve">
<source>Auto-accept</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept contact requests" xml:space="preserve">
<source>Auto-accept contact requests</source>
<target>Auto-accetta richieste di contatto</target>
@@ -622,11 +636,6 @@ Disponibile nella v5.1</target>
<target>Auto-accetta immagini</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Automatically" xml:space="preserve">
<source>Automatically</source>
<target>Automaticamente</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Back" xml:space="preserve">
<source>Back</source>
<target>Indietro</target>
@@ -992,11 +1001,6 @@ Disponibile nella v5.1</target>
<target>Preferenze del contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contact requests" xml:space="preserve">
<source>Contact requests</source>
<target>Richieste del contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve">
<source>Contacts can mark messages for deletion; you will be able to view them.</source>
<target>I contatti possono contrassegnare i messaggi per l'eliminazione; potrai vederli.</target>
@@ -1017,9 +1021,12 @@ Disponibile nella v5.1</target>
<target>Crea</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create address" xml:space="preserve">
<source>Create address</source>
<target>Crea indirizzo</target>
<trans-unit id="Create SimpleX address" xml:space="preserve">
<source>Create SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve">
<source>Create an address to let people connect with you.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create file" xml:space="preserve">
@@ -1590,6 +1597,10 @@ Disponibile nella v5.1</target>
<target>Inserisci il server a mano</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter welcome message… (optional)" xml:space="preserve">
<source>Enter welcome message… (optional)</source>
<note>placeholder</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
<source>Error</source>
<target>Errore</target>
@@ -2343,6 +2354,10 @@ Disponibile nella v5.1</target>
<target>File grande!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)." xml:space="preserve">
<source>Read more in [User Guide](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address).</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave" xml:space="preserve">
<source>Leave</source>
<target>Esci</target>
@@ -2987,6 +3002,10 @@ Disponibile nella v5.1</target>
<target>Password del profilo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile update will be sent to your contacts." xml:space="preserve">
<source>Profile update will be sent to your contacts.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit audio/video calls." xml:space="preserve">
<source>Prohibit audio/video calls.</source>
<target>Proibisci le chiamate audio/video.</target>
@@ -3247,6 +3266,10 @@ Disponibile nella v5.1</target>
<target>Salva archivio</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
<source>Save group profile</source>
<target>Salva il profilo del gruppo</target>
@@ -3282,6 +3305,10 @@ Disponibile nella v5.1</target>
<target>Salvare i server?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save settings?" xml:space="preserve">
<source>Save settings?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save welcome message?" xml:space="preserve">
<source>Save welcome message?</source>
<target>Salvare il messaggio di benvenuto?</target>
@@ -3472,6 +3499,14 @@ Disponibile nella v5.1</target>
<target>Condividi</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Share address" xml:space="preserve">
<source>Share address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share address with contacts?" xml:space="preserve">
<source>Share address with contacts?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share invitation link" xml:space="preserve">
<source>Share invitation link</source>
<target>Condividi link di invito</target>
@@ -3487,6 +3522,10 @@ Disponibile nella v5.1</target>
<target>Condividi link di invito una tantum</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Share with contacts" xml:space="preserve">
<source>Share with contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Show QR code" xml:space="preserve">
<source>Show QR code</source>
<target>Mostra codice QR</target>
@@ -3537,6 +3576,10 @@ Disponibile nella v5.1</target>
<target>SimpleX Lock attivato</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX address" xml:space="preserve">
<source>SimpleX address</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="SimpleX contact address" xml:space="preserve">
<source>SimpleX contact address</source>
<target>Indirizzo del contatto SimpleX</target>
@@ -3632,6 +3675,14 @@ Disponibile nella v5.1</target>
<target>Fermare l'invio del file?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing" xml:space="preserve">
<source>Stop sharing</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Stop sharing address?" xml:space="preserve">
<source>Stop sharing address?</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Submit" xml:space="preserve">
<source>Submit</source>
<target>Invia</target>
@@ -3727,9 +3778,9 @@ Disponibile nella v5.1</target>
<target>Grazie per aver installato SimpleX Chat!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<target>Grazie agli utenti [contribuite via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</target>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<target>Grazie agli utenti [contribuite via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">
@@ -4228,6 +4279,10 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Quando disponibili</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When people request to connect, you can accept or reject it." xml:space="preserve">
<source>When people request to connect, you can accept or reject it.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="When you share an incognito profile with somebody, this profile will be used for the groups they invite you to." xml:space="preserve">
<source>When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.</source>
<target>Quando condividi un profilo in incognito con qualcuno, questo profilo verrà utilizzato per i gruppi a cui ti invitano.</target>
@@ -4320,9 +4375,13 @@ SimpleX Lock deve essere attivato.</target>
<target>Puoi condividere un link o un codice QR: chiunque potrà unirsi al gruppo. Non perderai i membri del gruppo se in seguito lo elimini.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it." xml:space="preserve">
<source>You can share your address as a link or as a QR code - anybody will be able to connect to you. You won't lose your contacts if you later delete it.</source>
<target>Puoi condividere il tuo indirizzo come link o come codice QR: chiunque potrà connettersi a te. Non perderai i tuoi contatti se in seguito lo elimini.</target>
<trans-unit id="You can share this address with your contacts to let them connect with **%@**." xml:space="preserve">
<source>You can share this address with your contacts to let them connect with **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can share your address as a link or QR code - anybody can connect to you." xml:space="preserve">
<source>You can share your address as a link or QR code - anybody can connect to you.</source>
<target>Puoi condividere il tuo indirizzo come link o come codice QR: chiunque potrà connettersi a te.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can start chat via app Settings / Database or by restarting the app" xml:space="preserve">
@@ -4435,6 +4494,11 @@ SimpleX Lock deve essere attivato.</target>
<target>Non riceverai più messaggi da questo gruppo. La cronologia della chat verrà conservata.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You won't lose your contacts if you later delete your address." xml:space="preserve">
<source>You won't lose your contacts if you later delete your address.</source>
<target>Non perderai i tuoi contatti se in seguito lo elimini.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile" xml:space="preserve">
<source>You're trying to invite contact with whom you've shared an incognito profile to the group in which you're using your main profile</source>
<target>Stai tentando di invitare un contatto con cui hai condiviso un profilo in incognito nel gruppo in cui stai usando il tuo profilo principale</target>
@@ -4462,7 +4526,7 @@ SimpleX Lock deve essere attivato.</target>
</trans-unit>
<trans-unit id="Your SimpleX contact address" xml:space="preserve">
<source>Your SimpleX contact address</source>
<target>Il tuo indirizzo di contatto SimpleX</target>
<target>Il tuo indirizzo SimpleX</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your XFTP servers" xml:space="preserve">
@@ -4532,6 +4596,10 @@ Puoi annullare questa connessione e rimuovere il contatto (e riprovare più tard
<target>I tuoi contatti possono consentire l'eliminazione completa dei messaggi.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contacts will remain connected." xml:space="preserve">
<source>Your contacts will remain connected.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your current chat database will be DELETED and REPLACED with the imported one." xml:space="preserve">
<source>Your current chat database will be DELETED and REPLACED with the imported one.</source>
<target>Il tuo attuale database della chat verrà ELIMINATO e SOSTITUITO con quello importato.</target>

View File

@@ -2645,8 +2645,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>Thank you for installing SimpleX Chat!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">

View File

@@ -2583,8 +2583,8 @@ We will be adding server redundancy to prevent lost messages.</source>
<source>Thank you for installing SimpleX Chat!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps)!</source>
<trans-unit id="Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!" xml:space="preserve">
<source>Thanks to the users [contribute via Weblate](https://github.com/simplex-chat/simplex-chat/tree/stable#help-translating-simplex-chat)!</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Thanks to the users contribute via Weblate!" xml:space="preserve">

Some files were not shown because too many files have changed in this diff Show More