Compare commits

...

406 Commits

Author SHA1 Message Date
Morgan Pretty 041038476a
Merge pull request #731 from RyanRory/disappearing-message-redesign
Disappearing message rebuild
4 months ago
Morgan Pretty f528742752 Bumped build number and re-enabled feature flag 4 months ago
Ryan ZHAO 6e8e72c573 fix an issue when disappearing messages jobs weren't be created for messages received by PNs. 4 months ago
Ryan ZHAO bd0a25bbe9 fix an issue that a disappearing messages control message will be removed by a race condition 4 months ago
Ryan ZHAO b4f01db37e extend expire timer update message TTL to be default 14 days 4 months ago
Ryan ZHAO 4cf739eeef clean 4 months ago
Ryan ZHAO ce1eee2018 fix an issue where disappearing messages settings in groups won't be synced on new linked devices 4 months ago
Ryan ZHAO da0a459e89 Merge branch 'disappearing-message-redesign' of https://github.com/RyanRory/loki-messenger-ios into disappearing-message-redesign 4 months ago
Ryan ZHAO d63f3a8bee fix disappearing message settings subtitle copy 4 months ago
Morgan Pretty 92299e92a9 Updated build number 4 months ago
Morgan Pretty a76c220709 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	.drone.jsonnet
4 months ago
Ryan ZHAO 3899cdd389 enable the feature again 4 months ago
Ryan ZHAO afe08faa4a move disappearing message jobs to its concurrent queue. 4 months ago
Ryan ZHAO 262dfdebaa update timestamp for enabling disappearing messages V2 4 months ago
Ryan ZHAO 2eac3d79f2 fix an issue where after creating a group, the group will have a DaS-1D default setting 4 months ago
Morgan Pretty 5ff9ae96c7 Updated build number 4 months ago
Ryan ZHAO 145495da6d add accessibility id for follow setting button 4 months ago
Ryan ZHAO 6d2e07dea6 fix an issue for local generated expiration update messages being removed immediately. 4 months ago
Ryan ZHAO 73651773b7 Merge branch 'dev' into disappearing-message-redesign 4 months ago
Morgan Pretty 8777d1b2d0 Updated build number 4 months ago
Ryan ZHAO 91760c00bb minor fix 4 months ago
Ryan ZHAO d9c2471b4d clean 4 months ago
Ryan ZHAO 31b0d008e6 clean 4 months ago
Ryan ZHAO fdae955288 fix data extraction message DaR 4 months ago
Ryan ZHAO b2360d8e1a fix an issue where DaR messages are read on linked devices won't have correct expiration start time 4 months ago
Ryan ZHAO 9a528f8c71 fix disappearing message control message already read on linked devices 4 months ago
Ryan ZHAO 93e139cfa6 minor fix on minimum width for context menu action 4 months ago
Ryan ZHAO 3fcd85aee3 update translation 4 months ago
Ryan ZHAO 68a8311166 add auto deletes subtitle on delete action in long press menu screen 4 months ago
Morgan Pretty e9dd86bfc2 Tweak to CI script 5 months ago
Morgan Pretty 259167dbd5 Fix CI config error 5 months ago
Morgan Pretty a27bf7a210 Added a step to the CI to output build tool versions 5 months ago
Morgan Pretty 9951d5c75d Increased build & version number, removed ATS hack 5 months ago
Morgan Pretty 84492be016 Fixed build issues, removed invalid unit tests and missing copy 5 months ago
Morgan Pretty 661720a988 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Meta/Translations/ar.lproj/Localizable.strings
#	Session/Meta/Translations/be.lproj/Localizable.strings
#	Session/Meta/Translations/bg.lproj/Localizable.strings
#	Session/Meta/Translations/bn.lproj/Localizable.strings
#	Session/Meta/Translations/cs.lproj/Localizable.strings
#	Session/Meta/Translations/da.lproj/Localizable.strings
#	Session/Meta/Translations/de.lproj/Localizable.strings
#	Session/Meta/Translations/el.lproj/Localizable.strings
#	Session/Meta/Translations/en.lproj/Localizable.strings
#	Session/Meta/Translations/eo.lproj/Localizable.strings
#	Session/Meta/Translations/es-ES.lproj/Localizable.strings
#	Session/Meta/Translations/fa.lproj/Localizable.strings
#	Session/Meta/Translations/fi.lproj/Localizable.strings
#	Session/Meta/Translations/fil.lproj/Localizable.strings
#	Session/Meta/Translations/fr.lproj/Localizable.strings
#	Session/Meta/Translations/hi.lproj/Localizable.strings
#	Session/Meta/Translations/hr.lproj/Localizable.strings
#	Session/Meta/Translations/hu.lproj/Localizable.strings
#	Session/Meta/Translations/id.lproj/Localizable.strings
#	Session/Meta/Translations/it.lproj/Localizable.strings
#	Session/Meta/Translations/ja.lproj/Localizable.strings
#	Session/Meta/Translations/ko.lproj/Localizable.strings
#	Session/Meta/Translations/ku.lproj/Localizable.strings
#	Session/Meta/Translations/lt.lproj/Localizable.strings
#	Session/Meta/Translations/lv.lproj/Localizable.strings
#	Session/Meta/Translations/ne-NP.lproj/Localizable.strings
#	Session/Meta/Translations/nl.lproj/Localizable.strings
#	Session/Meta/Translations/no.lproj/Localizable.strings
#	Session/Meta/Translations/pl.lproj/Localizable.strings
#	Session/Meta/Translations/pt-BR.lproj/Localizable.strings
#	Session/Meta/Translations/pt-PT.lproj/Localizable.strings
#	Session/Meta/Translations/ro.lproj/Localizable.strings
#	Session/Meta/Translations/ru.lproj/Localizable.strings
#	Session/Meta/Translations/si-LK.lproj/Localizable.strings
#	Session/Meta/Translations/sk.lproj/Localizable.strings
#	Session/Meta/Translations/sl.lproj/Localizable.strings
#	Session/Meta/Translations/sv-SE.lproj/Localizable.strings
#	Session/Meta/Translations/th.lproj/Localizable.strings
#	Session/Meta/Translations/tr.lproj/Localizable.strings
#	Session/Meta/Translations/uk.lproj/Localizable.strings
#	Session/Meta/Translations/vi.lproj/Localizable.strings
#	Session/Meta/Translations/zh-CN.lproj/Localizable.strings
#	Session/Meta/Translations/zh-TW.lproj/Localizable.strings
#	SessionMessagingKit/Configuration.swift
#	SessionUtilitiesKit/Database/Storage.swift
5 months ago
Ryan ZHAO 4c340188c2 fix ttl for legacy mode 5 months ago
Ryan ZHAO 6eae9c4ba6 add accessibility ids for follow settings modal 5 months ago
Ryan ZHAO 43e2983f49 fix call messages and data extraction messages with their expiration info and refactor 5 months ago
Ryan ZHAO e85ec08b36 remove test settings 5 months ago
Ryan ZHAO 1c6232e4d7 minor refactor 5 months ago
Ryan ZHAO 4c0c1cda1a Do not process outdated expiration update messages 5 months ago
Ryan ZHAO c02c3abd73 fix an issue where deleted messages won't show profile picture in groups 5 months ago
Ryan ZHAO c473c6cb23 fix an issue where disappearing messages config in legacy group was not updated 5 months ago
Ryan ZHAO 68ce009d1c fix an issue when following settings linked devices won't sync the updated config 5 months ago
Ryan ZHAO e81923cdef fix an issue when updating expiry unchanged messages won't start disappear 5 months ago
Ryan ZHAO 87309ccba1 fix an issue where note to self may show expiration update control messages which should be removed already. 5 months ago
Ryan ZHAO 084586e6ba change call messages and data extraction notification to be DaR if needed 6 months ago
Ryan ZHAO 9231f57636 minor fix 6 months ago
Ryan ZHAO 04d734ef87 use local disappearing messages setting for call messages and data extraction notifications 6 months ago
Ryan ZHAO 39341742ea Don't show following settings for closed groups 6 months ago
Ryan ZHAO 10d1c64c29 remove outdated client banner when receiving a message from new version 6 months ago
Ryan ZHAO 787f2835a9 fix outdated client banner for showing current user 6 months ago
Ryan ZHAO ac30b3c797 fix unsend requests 6 months ago
Ryan ZHAO 810a990735 fix disappearing messages for call message 6 months ago
Ryan ZHAO 2cc51aec28 add workaround for a SS bug when getting and updating expiries 6 months ago
Ryan ZHAO ff691529c4 Do NOT expire control messages in groups 6 months ago
Ryan ZHAO e38fb400ea refactor on the way that attaching disappearing messages config to messages 6 months ago
Ryan ZHAO 9fc5f8fa68 WIP: refactoring the way of applying disappearing messages settings 6 months ago
Ryan ZHAO 7d0e0d5164 remove attached disappearing messages settings for some control messages 6 months ago
Ryan ZHAO c9df2a73e7 bring back false deleted logic 6 months ago
Ryan ZHAO 79eafa7df8 fix logic error for message ttl 6 months ago
Ryan ZHAO 3667d304f2 Merge branch 'dev' into disappearing-message-redesign 6 months ago
Ryan ZHAO 2fc021c48c fix an edge case where there is no expiration info for messages already expired 6 months ago
Ryan ZHAO 0aa32bcab3 fix an issue where expiration update control messages won't be marked as read on linked devices 6 months ago
Ryan ZHAO b22fe40d6e fix an issue where received expiration update control message should already be read 6 months ago
Ryan ZHAO 7693e53183 minor refactor and fix expiration update message for control messages 6 months ago
Ryan ZHAO 42f2440067 fix disappearing messages update control messages for legacy groups and linked devices 6 months ago
Ryan ZHAO 74efe8cc72 fix an issue for legacy groups disappearing message update control message 6 months ago
Ryan ZHAO 8c2491712e fix an issue where non-admin can change disappearing messages settings in legacy group 6 months ago
Ryan ZHAO 490cde57ce fix disappearing messages update control messages for legacy groups 6 months ago
Ryan ZHAO 4ec1d730cd remove previous logic for expiring control messages indicating disappearing messages turned off 6 months ago
Ryan ZHAO 362dcd3528 remove last change timestamp in local database 6 months ago
Ryan ZHAO 978ec30074 hide and display the following setting action accordingly 6 months ago
Ryan ZHAO 5d2a307d5e WIP: update copies and implement following setting 7 months ago
Ryan ZHAO 0038a78df3 fix outdated client banner 7 months ago
Ryan ZHAO c561a05273 WIP: fix outdated client banner 7 months ago
Ryan ZHAO e8ec91ba8b keep disappearing message update control message for legacy mode 7 months ago
Ryan ZHAO 9af95a672e only show outdated client banner when disappearing message is enabled 7 months ago
Ryan ZHAO 96d1f9deb2 fix outdated banner 7 months ago
Ryan ZHAO bf3fdad856 fix outdated banner for 1-1s 7 months ago
Ryan ZHAO d492290303 WIP: fix outdated client banner with sql query 7 months ago
Ryan ZHAO adf1a76acc fix outdated client version check 7 months ago
Ryan ZHAO 666061fec9 fix outdated client banner in conversation screen 7 months ago
Ryan ZHAO 21c4a17a85 minor fix: only show banner when V2 is enabled 7 months ago
Ryan ZHAO 5f0835c41b feat : display outdated client banner for linked devices 7 months ago
Ryan ZHAO 39c9ec7357 clean 7 months ago
Ryan ZHAO 3d566c1923 minor fix on close button accessibility id 7 months ago
Ryan ZHAO 6d92f31f6d update accessibility of empty state label 7 months ago
Ryan Zhao 18852b8a52 fix an issue where closed group disappearing messages type can be set to unknown by shared config 8 months ago
Ryan Zhao 70326b5c74 fix disappearing messages for closed group control messages 8 months ago
Ryan Zhao f2629f193b add disappearing timer to call info messages 8 months ago
Ryan Zhao 8c6c6705a5 update control message text colour 8 months ago
Ryan Zhao d27475d0be feat: add timer for disappearing info messages 8 months ago
Ryan Zhao 83a64c5ca1 clean 8 months ago
Ryan Zhao 3d1b930ede feat: update disappearing messages ui for visible messages 8 months ago
Ryan Zhao 61df9e2cf1 refactor disappearing timer view from objc to swift 8 months ago
ryanzhao 5569da0874 add accessibility id for radio button in cells 8 months ago
ryanzhao 2d6db6a768 feat(disabled): remove message requests from community when leaving this community 8 months ago
Ryan Zhao 5e0a29f5af WIP: clear message requests from community when leaving this community chat 8 months ago
Ryan Zhao c933ea1734 add comments 8 months ago
Ryan Zhao b605193e61 fix an issue by the refactor 8 months ago
Ryan Zhao 99d5620536 minor refactor and clean up 8 months ago
Ryan Zhao 928d7f2b1e add comments and minor refactor 8 months ago
ryanzhao a64d054537 only start disappearing messages after a message successfully sent 8 months ago
Ryan Zhao 71fa811064 WIP: handle disappearing message failed to send 8 months ago
Morgan Pretty c74d9a89f5 Fixed broken tests 8 months ago
Morgan Pretty 12347c9f2f Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	Session/Media Viewing & Editing/MediaDetailViewController.swift
8 months ago
Morgan Pretty f809a71c8b Updated the config merge process to only consider timestamps from merged messages 8 months ago
Morgan Pretty a6931bb922 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift
#	Session/Conversations/Settings/ThreadSettingsViewModel.swift
#	Session/Shared/SessionTableViewController.swift
#	Session/Shared/SessionTableViewModel.swift
#	Session/Shared/Types/SessionTableSection.swift
#	SessionTests/Conversations/Settings/ThreadDisappearingMessagesViewModelSpec.swift
#	SessionUIKit/Components/SessionButton.swift
8 months ago
Morgan Pretty b97c0955be Copy tweak to better support localization 8 months ago
Morgan Pretty d1d2531ced Fixed a minor layout issue and string linter tweaks 8 months ago
Morgan Pretty b20e533929 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign 9 months ago
Morgan Pretty c6455ceb3a Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign 9 months ago
Morgan Pretty 992cc233c5 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign 9 months ago
Morgan Pretty 90cd3fb5e0 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	_SharedTestUtilities/MockJobRunner.swift
9 months ago
Morgan Pretty e4357f153e Removed an unneeded import breaking the CI tests 9 months ago
Morgan Pretty 5b7c9d866c Updated the 'MessageReceiverDisappearingMessagesSpec' to the updated pattern 9 months ago
Morgan Pretty bf58831313 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	Scripts/LintLocalizableStrings.swift
9 months ago
Ryan Zhao 6e9cbe402f add accessibility id for radio buttons 9 months ago
Ryan Zhao 8721d8c5f3 update accessibility ids 9 months ago
Ryan Zhao 01671438d5 fix issues that the expiresStartAtMs not being set correctly 9 months ago
Ryan Zhao 33ef2b0920 refactor and fix issues that some control messages were not following disappearing messages settings 9 months ago
Ryan Zhao 946acf3089 fix an issue where clicking on user count didn't navigate to the correct screen 9 months ago
Morgan Pretty 00008787cc Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	Session/Meta/Translations/ar.lproj/Localizable.strings
#	Session/Meta/Translations/be.lproj/Localizable.strings
#	Session/Meta/Translations/bg.lproj/Localizable.strings
#	Session/Meta/Translations/bn.lproj/Localizable.strings
#	Session/Meta/Translations/cs.lproj/Localizable.strings
#	Session/Meta/Translations/da.lproj/Localizable.strings
#	Session/Meta/Translations/de.lproj/Localizable.strings
#	Session/Meta/Translations/el.lproj/Localizable.strings
#	Session/Meta/Translations/en.lproj/Localizable.strings
#	Session/Meta/Translations/eo.lproj/Localizable.strings
#	Session/Meta/Translations/es-ES.lproj/Localizable.strings
#	Session/Meta/Translations/fa.lproj/Localizable.strings
#	Session/Meta/Translations/fi.lproj/Localizable.strings
#	Session/Meta/Translations/fil.lproj/Localizable.strings
#	Session/Meta/Translations/fr.lproj/Localizable.strings
#	Session/Meta/Translations/hi.lproj/Localizable.strings
#	Session/Meta/Translations/hr.lproj/Localizable.strings
#	Session/Meta/Translations/hu.lproj/Localizable.strings
#	Session/Meta/Translations/id.lproj/Localizable.strings
#	Session/Meta/Translations/it.lproj/Localizable.strings
#	Session/Meta/Translations/ja.lproj/Localizable.strings
#	Session/Meta/Translations/ko.lproj/Localizable.strings
#	Session/Meta/Translations/ku.lproj/Localizable.strings
#	Session/Meta/Translations/lt.lproj/Localizable.strings
#	Session/Meta/Translations/lv.lproj/Localizable.strings
#	Session/Meta/Translations/ne-NP.lproj/Localizable.strings
#	Session/Meta/Translations/nl.lproj/Localizable.strings
#	Session/Meta/Translations/no.lproj/Localizable.strings
#	Session/Meta/Translations/pl.lproj/Localizable.strings
#	Session/Meta/Translations/pt-BR.lproj/Localizable.strings
#	Session/Meta/Translations/pt-PT.lproj/Localizable.strings
#	Session/Meta/Translations/ro.lproj/Localizable.strings
#	Session/Meta/Translations/ru.lproj/Localizable.strings
#	Session/Meta/Translations/si-LK.lproj/Localizable.strings
#	Session/Meta/Translations/sk.lproj/Localizable.strings
#	Session/Meta/Translations/sl.lproj/Localizable.strings
#	Session/Meta/Translations/sv-SE.lproj/Localizable.strings
#	Session/Meta/Translations/th.lproj/Localizable.strings
#	Session/Meta/Translations/tr.lproj/Localizable.strings
#	Session/Meta/Translations/uk.lproj/Localizable.strings
#	Session/Meta/Translations/vi.lproj/Localizable.strings
#	Session/Meta/Translations/zh-CN.lproj/Localizable.strings
#	Session/Meta/Translations/zh-TW.lproj/Localizable.strings
9 months ago
ryanzhao 99b76df32a update translation 9 months ago
ryanzhao dc02e588eb merge translation files 9 months ago
ryanzhao 22c7559e63 Merge branch 'dev' into disappearing-message-redesign 9 months ago
ryanzhao 2d0bbe4455 Merge branch 'dev' into disappearing-message-redesign
#	Session/Meta/Translations/de.lproj/Localizable.strings
#	Session/Meta/Translations/en.lproj/Localizable.strings
#	Session/Meta/Translations/es-ES.lproj/Localizable.strings
#	Session/Meta/Translations/fa.lproj/Localizable.strings
#	Session/Meta/Translations/fi.lproj/Localizable.strings
#	Session/Meta/Translations/fil.lproj/Localizable.strings
#	Session/Meta/Translations/fr.lproj/Localizable.strings
#	Session/Meta/Translations/hi.lproj/Localizable.strings
#	Session/Meta/Translations/hr.lproj/Localizable.strings
#	Session/Meta/Translations/it.lproj/Localizable.strings
#	Session/Meta/Translations/ja.lproj/Localizable.strings
#	Session/Meta/Translations/nl.lproj/Localizable.strings
#	Session/Meta/Translations/pl.lproj/Localizable.strings
#	Session/Meta/Translations/pt-BR.lproj/Localizable.strings
#	Session/Meta/Translations/ru.lproj/Localizable.strings
#	Session/Meta/Translations/sk.lproj/Localizable.strings
#	Session/Meta/Translations/sl.lproj/Localizable.strings
#	Session/Meta/Translations/sv-SE.lproj/Localizable.strings
#	Session/Meta/Translations/th.lproj/Localizable.strings
#	Session/Meta/Translations/vi.lproj/Localizable.strings
#	Session/Meta/Translations/zh-CN.lproj/Localizable.strings
#	Session/Meta/Translations/zh-TW.lproj/Localizable.strings
9 months ago
ryanzhao 38c34f2977 trigger disappear after read for community invitaion 9 months ago
ryanzhao ba1d468e9b fix an issue where call messages were not attached with disappearing messages setting 9 months ago
ryanzhao d415ea5781 Merge branch 'dev' into disappearing-message-redesign 9 months ago
Ryan Zhao 07348f2079 Merge branch 'dev' into disappearing-message-redesign 9 months ago
Ryan Zhao 77ceac54e0 fix closed group default disappearing messages settings 9 months ago
Ryan Zhao 66e37cef07 Merge branch 'dev' into disappearing-message-redesign 9 months ago
Ryan Zhao 2411e6a6a1 Merge branch 'dev' into disappearing-message-redesign 10 months ago
Ryan Zhao 6c75007c0b Merge branch 'dev' into disappearing-message-redesign 10 months ago
ryanzhao 8b529676a4 Merge branch 'dev' into disappearing-message-redesign 10 months ago
Ryan Zhao 19787f9028 clean 10 months ago
Ryan Zhao e1f5f86743 try to fix unit test 10 months ago
Ryan Zhao 0df7baa2ee WIP: try to fix unit test 10 months ago
Ryan Zhao 432f32b0a8 WIP: try to fix unit test 10 months ago
Ryan Zhao c4afcb3c3e WIP: try to fix unit test 10 months ago
Ryan Zhao c2d4bbe9d8 WIP: try to fix unit test 10 months ago
Ryan Zhao a7a19abccf update unit test 10 months ago
Ryan Zhao cc9504bf40 reenable the failed unit test 10 months ago
Ryan Zhao 356e9775e7 WIP: fix unit test on CI pipeline 10 months ago
Ryan Zhao 89f87d173a update LibSession Util 10 months ago
Ryan Zhao 9e1f68380a Merge branch 'dev' into disappearing-message-redesign 10 months ago
Ryan Zhao fda9a60a2e remove the logic that is not as expected 10 months ago
Ryan Zhao e4beb5c794 update expiresInSeconds filter to be safe for negative value 10 months ago
Ryan Zhao 0eeb4fcd1a fix an UI issue when there is no message in an outdated conversation, the banner and empty state string will be overlapped 10 months ago
Ryan Zhao acbf6fb126 clean 10 months ago
Morgan Pretty c293bbca3a Fixed a couple of migration issues and minor tweaks
Added the ability to define requirements for migrations (in case some data or state needs to be loaded for a migration to be able to be performed correctly)
Fixed a bug where the migration would throw because the user config might not have loaded it's state yet
Fixed a bug where the migration would throw if the user didn't exist yet
Commented out some logic in the ConfigSyncJob that could be problemmatic
11 months ago
Morgan Pretty 63be502434 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift
#	SessionMessagingKit/Configuration.swift
#	SessionMessagingKit/Sending & Receiving/MessageSender.swift
#	SessionSnodeKit/Networking/SnodeAPI.swift
#	SessionTests/Conversations/Settings/ThreadDisappearingMessagesViewModelSpec.swift
#	SessionUtilitiesKit/General/Dictionary+Utilities.swift
#	SessionUtilitiesKit/JobRunner/JobRunner.swift
11 months ago
ryanzhao 43247b6ffa Merge branch 'dev' into disappearing-message-redesign 11 months ago
ryanzhao 2b2d67a444 Merge branch 'dev' into disappearing-message-redesign 11 months ago
Ryan Zhao cbc8a7806d Merge branch 'dev' into disappearing-message-redesign 11 months ago
ryanzhao 18d3ab0e0e Merge branch 'dev' into disappearing-message-redesign 11 months ago
ryanzhao d4aaca9291 fix build issues after merge 11 months ago
ryanzhao 31976048bd Merge branch 'feature/updated-user-config-handling' of https://github.com/mpretty-cyro/session-ios into disappearing-message-redesign 11 months ago
Ryan Zhao 0fc00ab527 Merge branch 'updated-user-config-handling' into disappearing-message-redesign 11 months ago
ryanzhao dba114e813 add workaround for an issue on storage sever when getting single message's expiration 11 months ago
ryanzhao 929e42d832 minor fix 12 months ago
Ryan Zhao b9b70b1e7f Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
Ryan Zhao c0073ea7de WIP: update expiration of sync messages 12 months ago
Ryan Zhao 0150816aaa clean 12 months ago
Ryan Zhao 8e5e5ac7fb fix on get expiration job to resolve the race condition 12 months ago
Ryan Zhao f0d48670be fix a bunch of crash 12 months ago
Ryan Zhao 0b0371e769 Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
ryanzhao df7b47da64 make get expiration a job to fix race condtion 12 months ago
ryanzhao 6738af200f update expiration of sync visible messages 12 months ago
Ryan Zhao 66e45199d5 handle already read disappearing messages 12 months ago
Ryan Zhao defd7e3cfe Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
Ryan Zhao 1f20403a26 WIP: race condition handling 12 months ago
Ryan Zhao ce02aa3f5a Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
Ryan Zhao bc6099036b Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
Ryan Zhao e78015faa1 Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
ryanzhao aace269359 WIP: make job chain of disappearing messages job, expiration update job, and config sync job 12 months ago
Ryan Zhao d81a8743ac Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
Ryan Zhao 754279e6ab make update message expiration a seperate job from disappearing messages job 12 months ago
ryanzhao 5063feeb6a fix an issue where message is not received & minor refactor on disappearing message job 12 months ago
ryanzhao ee5de25d4a Merge branch 'feature/updated-user-config-handling' of https://github.com/mpretty-cyro/session-ios into disappearing-message-redesign 12 months ago
Ryan Zhao c932b7bd94 add user config migration with disappearing messages config update 12 months ago
Ryan Zhao 2d3b42a53a minor refactor 12 months ago
Ryan Zhao 9ae6d2f506 Merge branch 'updated-user-config-handling' into disappearing-message-redesign 12 months ago
Ryan Zhao f4c25fa697 fix disappearing message control messages won't start disappearing 1 year ago
Ryan Zhao f8d0ac2075 fix an issue where disappearing messages config messages could not be marked as read when opening a conversation 1 year ago
Ryan Zhao f7c7c75527 Merge branch 'updated-user-config-handling' into disappearing-message-redesign 1 year ago
Ryan Zhao 345f9ec47c update legacy closed group + new disappearing message handling in user config 1 year ago
ryanzhao 419cd7dff7 delete outdated control messages for disappearing messages 1 year ago
ryanzhao eeb110b0bd minor refactor 1 year ago
ryanzhao 96804e73e6 WIP: fix first handling user config messages makes expire timer update message not handled 1 year ago
Ryan Zhao 4ac8aa2aea fix an issue where visible message received after expire timer update message could be dropped 1 year ago
Ryan Zhao e3537e55ca Merge branch 'updated-user-config-handling' into disappearing-message-redesign 1 year ago
Ryan Zhao e946fd81d2 minor refactor for automation test 1 year ago
Ryan Zhao 74844cc6b3 add 10s expiration settings for testing 1 year ago
Ryan Zhao a7db4485df resolve a race condition of expireTimerUpdate and configUpdate 1 year ago
ryanzhao d80ac97217 WIP: refactor BezierPathView with swiftUI 1 year ago
ryanzhao d717828af5 remove unused objc AVAudioSession+OWS 1 year ago
ryanzhao 40f1d6491d Merge branch 'feature/updated-user-config-handling' of https://github.com/mpretty-cyro/session-ios into disappearing-message-redesign 1 year ago
ryanzhao 2df820339c refactor on adding expiration on interactions before inserted into database 1 year ago
ryanzhao ae78abc5a4 fix an issue where expire timer update message being invalid 1 year ago
ryanzhao eb8f50c29f minor fix 1 year ago
ryanzhao 5b9944d668 Merge branch 'feature/updated-user-config-handling' of https://github.com/mpretty-cyro/session-ios into disappearing-message-redesign 1 year ago
ryanzhao e9c924b83b fix message receiver disappearing messages config unit test 1 year ago
ryanzhao 2e56a11003 WIP: add logic unit test for disappearing messages 1 year ago
ryanzhao bf20de187d WIP: unit test of message receiver for disappearing messages 1 year ago
ryanzhao 32d7dd2ea6 refactor on accessibility of SessionButton.Info, and fix some unit tests on disappearing messages config 1 year ago
ryanzhao 71f96058f1 fix broken unit test 1 year ago
ryanzhao 289d345874 add unit test for changing back to previous setting before confirming new settings 1 year ago
ryanzhao 6658c5edd5 fix issue of syncing disappearing messages 1 year ago
Ryan Zhao dca70058e3 fix disappearing messages config not sync when linking a new device 1 year ago
Ryan Zhao 9dfaa09a95 fix a bug on getting expirations from snode 1 year ago
Ryan Zhao 43e38c5644 Merge branch 'updated-user-config-handling' into disappearing-message-redesign 1 year ago
Ryan Zhao e171edfb18 update libsession 1 year ago
ryanzhao cd95212918 minor fix 1 year ago
ryanzhao 30e4ad691b further fix 1 year ago
ryanzhao 84452750fe fix disappear after read not synced properly 1 year ago
ryanzhao 284bdab9f8 WIP: refactor on fixing disappear after read 1 year ago
ryanzhao 963b3f6029 WIP: fix disappear after read for message sender 1 year ago
ryanzhao ee490bfa99 minor fix 1 year ago
ryanzhao 71862a52b8 use exported C function in libSession to sync disappearing messages configuration 1 year ago
ryanzhao c969a8e012 fix disappear after read not working for message sender 1 year ago
ryanzhao b78c13eafd fix UI issue of incoming visible messages in 1-1 convos 1 year ago
Ryan Zhao afb456b710 Merge branch 'updated-user-config-handling' into disappearing-message-redesign 1 year ago
Ryan Zhao 58740d9639 sync disappearing messages config through libSession 1 year ago
ryanzhao e711c978c9 WIP: sync disappearing messages config through user config 1 year ago
Ryan Zhao ef1db5a1e2 WIP: Update expiration timer to be based on user config 1 year ago
Ryan Zhao 6ea61f770c clean 1 year ago
ryanzhao 89324f01bf update disappearing messages unit test 1 year ago
ryanzhao 00e468fcce implement the new approach to sync disappearing after read status across devices 1 year ago
ryanzhao 2b85c0fde0 WIP: implement new approach to sync disappearing after read across devices 1 year ago
Ryan Zhao b05bb7f9bd fix a crash when the network clock offset is negative 1 year ago
Ryan Zhao e78b41164c add missing translation in French 1 year ago
Ryan Zhao edfe8a61b0 Merge branch 'feature/updated-user-config-handling' of https://github.com/mpretty-cyro/session-ios into disappearing-message-redesign 1 year ago
ryanzhao 05eb059caf modify & add accessibility ids and labels 1 year ago
ryanzhao 31af9c2ab9 refactor & fix default duration of legacy disappearing message, and fix typo 1 year ago
ryanzhao eae5d463e6 add existing scripts to project 1 year ago
ryanzhao 86705d88e3 Merge branch 'feature/updated-user-config-handling' into disappearing-message-redesign 1 year ago
Ryan Zhao 7770d566df clean up & implement same delete type selection 1 year ago
Ryan Zhao 9a66046e77 clean 1 year ago
Ryan Zhao 75df800c65 WIP: clean up 1 year ago
Ryan Zhao 09e1c02e1d update legacy to be unknown 1 year ago
ryanzhao a966fca55e add disappearing messages type legacy 1 year ago
ryanzhao fa02b76d77 update protobuf 1 year ago
ryanzhao e5f57a6e94 update submodule 1 year ago
Morgan Pretty be7881ad2e Merge remote-tracking branch 'origin/feature/updated-user-config-handling' into disappearing-message-redesign
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Conversations/ConversationVC.swift
#	Session/Conversations/ConversationViewModel.swift
#	Session/Conversations/Settings/ThreadDisappearingMessagesSettingsViewModel.swift
#	Session/Conversations/Settings/ThreadSettingsViewModel.swift
#	Session/Conversations/Views & Modals/ConversationTitleView.swift
#	Session/Notifications/AppNotifications.swift
#	Session/Settings/NukeDataModal.swift
#	Session/Shared/SessionTableViewModel.swift
#	Session/Shared/Views/SessionCell.swift
#	SessionMessagingKit/Configuration.swift
#	SessionMessagingKit/Database/Models/Contact.swift
#	SessionMessagingKit/Database/Models/DisappearingMessageConfiguration.swift
#	SessionMessagingKit/Messages/Control Messages/ClosedGroupControlMessage.swift
#	SessionMessagingKit/Messages/Message.swift
#	SessionMessagingKit/Messages/Visible Messages/VisibleMessage.swift
#	SessionMessagingKit/Protos/Generated/SNProto.swift
#	SessionMessagingKit/Protos/Generated/SessionProtos.pb.swift
#	SessionMessagingKit/Protos/SessionProtos.proto
#	SessionMessagingKit/Sending & Receiving/Message Handling/MessageReceiver+ExpirationTimers.swift
#	SessionMessagingKit/Sending & Receiving/MessageReceiver.swift
#	SessionMessagingKit/Shared Models/SessionThreadViewModel.swift
#	SessionMessagingKitTests/Open Groups/OpenGroupManagerSpec.swift
#	SessionMessagingKitTests/_TestUtilities/TestOnionRequestAPI.swift
#	SessionSnodeKit/Models/SnodeAPIEndpoint.swift
#	SessionSnodeKit/SnodeAPI.swift
#	SessionTests/Conversations/Settings/ThreadDisappearingMessagesViewModelSpec.swift
#	SessionUtilitiesKit/General/Features.swift
1 year ago
Morgan Pretty 593acd8e37 Fixed some broken tests and removed remaining remnants of the 'syncExpiries' job 1 year ago
Morgan Pretty 5e3dd3c731 Merge remote-tracking branch 'upstream/dev' into disappearing-message-redesign
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Conversations/Settings/ThreadDisappearingMessagesViewModel.swift
#	Session/Shared/Views/SessionCell+AccessoryView.swift
#	SessionMessagingKit/Configuration.swift
#	SessionMessagingKit/Database/Models/Interaction.swift
#	SessionMessagingKit/Shared Models/SessionThreadViewModel.swift
#	SessionUtilitiesKit/Database/Models/Job.swift
1 year ago
Ryan Zhao 600637ec78 Merge branch 'dev' into disappearing-message-redesign 1 year ago
Ryan Zhao 2ebc0a6789 Merge branch 'dev' into disappearing-message-redesign 1 year ago
Ryan Zhao b4f44d43e8 Merge branch 'dev' into disappearing-message-redesign 1 year ago
ryanzhao 300eac51c0 Merge branch 'dev' into disappearing-message-redesign 1 year ago
Ryan Zhao 494e12adb6 Merge branch 'dev' into disappearing-message-redesign 1 year ago
ryanzhao b1d78b91d2 improve logs for unhandled response code 1 year ago
ryanzhao a279b53064 change `pubKey` to `pubkey` 1 year ago
Ryan Zhao d5343ac236 fix get_expiries endpoints & clean up 1 year ago
ryanzhao 33c239eae2 WIP: debug new endpoints 1 year ago
Ryan Zhao ef662b2152 fix a threading issue 1 year ago
Ryan Zhao 1fc8261944 fix update expiries testing on testnet 1 year ago
Ryan Zhao 73e05ec19e use new endpoint to shorten messages' TTL 1 year ago
Ryan Zhao 99610cf374 add snode api endpoint get expiries 1 year ago
Ryan Zhao 66b33b6623 update `expire` endpoint 1 year ago
ryanzhao 1f3bfde5b2 WIP: make new property lastChangeTimestampsMs optional 1 year ago
ryanzhao 4b852987cf clean 1 year ago
ryanzhao 4c366dedc2 clean up SyncedExpiries 1 year ago
ryanzhao 0bfc337bcc add index & clean 1 year ago
ryanzhao 071d23c0df update comments 1 year ago
ryanzhao a50af6702e make expiresInSeconds & expiresStartedAtMs private(set) 1 year ago
ryanzhao 23459fee2d minor refactor on threadIsNoteToSelf 1 year ago
ryanzhao 6694414f55 minor fix 1 year ago
ryanzhao 87dda2aa20 clean 1 year ago
ryanzhao 9954cddc2a Merge branch 'dev' into disappearing-message-redesign 1 year ago
Ryan Zhao f105c1d7bc clean 1 year ago
Ryan Zhao 3712893bdc clean 1 year ago
Ryan Zhao 9c39945c89 clean 1 year ago
Ryan Zhao 3a3be0ca7b resolve a TODO 1 year ago
Ryan Zhao a3f8d9e81a clean 1 year ago
Ryan Zhao bae9c3cbc3 UI: update standard font size 1 year ago
Ryan Zhao 71449c22b1 feat: remove previous disappearing messages change info message when adding a new one 1 year ago
Ryan Zhao c9d7565ebe update unit test for disappearing messages 2 years ago
ryanzhao c4e6f3fe47 clear open group inbox when clear account data 2 years ago
ryanzhao 123c458c32 update disappearing messages off config info message's expiration 2 years ago
Ryan Zhao e93c83b9f2 wip: update disappearing messages config off info message's expiration 2 years ago
Ryan Zhao 16cac78880 fix app badge number 2 years ago
Ryan Zhao 28ee331421 reduce mark as read on initial scroll in conversation screen 2 years ago
Ryan Zhao 4cc6d24404 fix sync expiries jobs 2 years ago
Ryan Zhao 3368f184de fix sync expiries job 2 years ago
Ryan Zhao f736e4709b refactor: make sync expiries to a job & only save sync message server hash for outgoing messages 2 years ago
Ryan Zhao 4c5bfe258d fix an issue where sync expiry will falsely start disappearing messages according to current config 2 years ago
Ryan Zhao a33958ae7b add server hash to disappearing messages info message 2 years ago
Ryan Zhao 3b1bc3615e clean 2 years ago
Ryan Zhao 5542f0e389 fix an issue where linked device will remove current username 2 years ago
Ryan Zhao 309ad326d3 add accessibility id to timer & off options 2 years ago
Ryan Zhao 952751603b add accessibility id for footer button in session table view controller 2 years ago
Ryan Zhao 269423a9d8 refactor to add accessibility id for carousel labels 2 years ago
ryanzhao cdc369444d WIP: update unit test 2 years ago
ryanzhao ea44a16f9d fix expire timer update message 2 years ago
ryanzhao f345578d76 Merge branch 'dev' into disappearing-message-redesign 2 years ago
ryanzhao 8caed9dc9c fix open group trimming & removing unread disappearing messages after 14 days 2 years ago
ryanzhao 491ca58e9d fix an issue where the info message won't disappearing if it is from expiration timer update message 2 years ago
Ryan Zhao c4fa91d907 feat: not show disappearing messages type in conversation subtitle carousel until new design is enabled 2 years ago
Ryan Zhao bdea161aba feat: bring back legacy disappearing messages info message 2 years ago
Ryan Zhao 49b22ab98e fix an issue where in some cases the new client will be marked as old ones 2 years ago
Ryan Zhao c2f6c3c8ea ui: finish backwards compatibility for note to self and closed groups 2 years ago
Ryan Zhao 3643a96918 clean 2 years ago
Ryan Zhao c247064fa8 feat: check contacts client version based on protobuf 2 years ago
Ryan Zhao 245682b40d feat: add database column for version detecting 2 years ago
ryanzhao 3b08339e0b feat: add column for contact using outdated client in database 2 years ago
ryanzhao 99ef46f457 WIP: add banner in conversation screen for outdated client 2 years ago
Ryan Zhao b27b62fba5 WIP: outdated client banner 2 years ago
Ryan Zhao 0e78b3953b refactor info banner 2 years ago
Ryan Zhao 70e4a51780 do not show disappearing messages configuration in carousel until the new design is enabled 2 years ago
Ryan Zhao 8e64cda138 re-enable the handling for expiration timer update messages until the new design is enabled 2 years ago
Ryan Zhao f4a2d41d34 do not add disappearing messages configuration to content message proto until the new design is enabled 2 years ago
Ryan Zhao 4225ba6a04 feat: do not update messages' ttl until the new design is enabled 2 years ago
Ryan Zhao a33df00363 update localized string for disappearing messages outdated client banner 2 years ago
Ryan Zhao 3fccbf4d99 update localized strings for legacy disappearing messages option subtitle 2 years ago
Ryan Zhao f0b3044e89 ui: add legacy option for 1-1 disappearing messages and clean 2 years ago
Ryan Zhao 984aee4aa9 WIP: add legacy disappearing messages 2 years ago
ryanzhao 9e88405c44 fix the area for subtitle carousel to scroll 2 years ago
ryanzhao 4da429a08e feat: mark visible messages as read when entering conversation screen 2 years ago
ryanzhao eeb0f4e47c Merge branch 'dev' into disappearing-message-redesign 2 years ago
ryanzhao d3dccae0f1 feat: make the whole conversation title view scrollable 2 years ago
ryanzhao a198145fb2 remove padding for sync expiry messages 2 years ago
ryanzhao 6ac7f786f7 fix subtitle for disappearing messages configuration of note to self 2 years ago
ryanzhao 5c6ab4d0af minor ui adjustment 2 years ago
ryanzhao 6bd7476c29 ui: subtitle for session table view 2 years ago
ryanzhao a50de813ce ui: make session tableview's title view centered 2 years ago
ryanzhao 137b6c3a05 WIP: subtitle for session tableview vc 2 years ago
ryanzhao 68c762781b fix default timer selection when changing disappearing messages type 2 years ago
ryanzhao afbb60b66d fix: disappear after read for control messages 2 years ago
ryanzhao 14a853ab07 feat: send expire timer update message 2 years ago
ryanzhao 49c019a9d4 make control message disappears as the settings 2 years ago
ryanzhao 1a4343e6df update protobuf 2 years ago
ryanzhao d1f075b865 minor ui adjust for carousel width 2 years ago
ryanzhao 9e80187214 refactor to make disappearing message after send work for control messages 2 years ago
ryanzhao f3fcdad553 fix control message sending job will be run twice 2 years ago
ryanzhao 1c4981cb5d WIP: disappearing messages for control messages 2 years ago
ryanzhao dd13125a90 feat: tapping conversation title will lead to the settings of what the carousel is showing 2 years ago
Ryan Zhao b4772e862f WIP 2 years ago
Ryan Zhao 3b17863d85 WIP: tapping convo title goes to the correct settings 2 years ago
Ryan Zhao 37db596f1a feat: add current showing carousel label type for tapping to go to the related settings 2 years ago
Ryan Zhao bfd0fc3c0c fix closed group member & admin sql statement in convo settings 2 years ago
Ryan Zhao 8164d4400d feat: make the carousel looping infinitely 2 years ago
Ryan Zhao b11ac1f6f8 ui: add arrows in subtitle carousel 2 years ago
ryanzhao 4e93ede602 add comment 2 years ago
ryanzhao 210cd29b72 feat: note to self disappearing message settings 2 years ago
ryanzhao 776b4c3234 fix note to self title 2 years ago
Ryan Zhao 879c55906e fix disappear after send 2 years ago
Ryan Zhao 9866e26d03 update disappear after send message receiving 2 years ago
Ryan Zhao 715b4f6d4d add footer title for group disappearing messages setting 2 years ago
Ryan Zhao 2ad8041b59 feat: allow group admin to set disappearing message config 2 years ago
Ryan Zhao 3041f61e31 ui: group disappearing message config disabled for non-admin 2 years ago
Ryan Zhao bd23e7ec4a add min width for footer button in session tableview vc 2 years ago
Ryan Zhao e49b4ccaa1 fix missing localised string 2 years ago
Ryan Zhao 4169ee5c4f adjust the disappearing message subtitle UI 2 years ago
ryanzhao 5c345174c1 update protobuf 2 years ago
ryanzhao 3da092019b Merge branch 'dev' into disappearing-message-redesign 2 years ago
ryanzhao 723d676d81 sync expiries message handling 2 years ago
ryanzhao 89a5739883 send sync expiries 2 years ago
ryanzhao fd14c50f61 add sync expires message and update protobuf 2 years ago
ryanzhao d4d7f6c72c clean 2 years ago
ryanzhao 387b5f953b apply disappearing message config to sync messages 2 years ago
ryanzhao f855e71d61 Merge branch 'dev' into disappearing-message-redesign 2 years ago
Ryan Zhao 03ed90c31d reverse & clean 2 years ago
Ryan Zhao 31c90162d3 fix sending messages with disappearing messages ttl 2 years ago
Ryan Zhao 3efba397ab add YOU for disappearing messages info message 2 years ago
Ryan Zhao e54a37ead0 update ttl after read when disappear after read is set 2 years ago
Ryan Zhao 02240e5940 minor adjustment on info message UI 2 years ago
Ryan Zhao aa81a907a5 update disappearing messages info message 2 years ago
Ryan Zhao 03946aa110 update translation & disappearing messages icon 2 years ago
Ryan Zhao e4bf474fea fix disappearing messages configuration sending & receiving 2 years ago
Ryan Zhao 0567a4eb6a update protobuf 2 years ago
Ryan Zhao 9db547242c insert config message for setting disappearing messages 2 years ago
Ryan Zhao d5c7e3178f minor fix 2 years ago
Ryan Zhao 6e58a0d967 insert info message for updating disappearing message config 2 years ago
ryanzhao 601cc7b92a set disappearing messages config info to all kinds of messages 2 years ago
ryanzhao 38594f8dc1 minor refactor 2 years ago
ryanzhao aaa25c3004 add function to handle disappearing messages configuration 2 years ago
ryanzhao 61647e1c72 fix the migration 2 years ago
ryanzhao 8377da0876 lastChangeTimestamp migration 2 years ago
Ryan Zhao 03b3136316 disappearing message config to proto 2 years ago
Ryan Zhao 95d065f775 update protobuf 1 2 years ago
Ryan Zhao 70ba0bdc13 set ttl as disappearing message config 2 years ago
Ryan Zhao f9ebef9ba6 update disappearing message timer icon 2 years ago
Ryan Zhao a9065b90af minor fix on subtitle view 2 years ago
Ryan Zhao 0e242e57ef save the updated disappearing messages config into database 2 years ago
Ryan Zhao 0f3dc7348a minor fix on scrollable subtitle 2 years ago
Ryan Zhao f5e41907d4 fix retrieve disappearing message config from database with session thread data model 2 years ago
ryanzhao 54914d69c6 WIP: fetch disappearing message config from database 2 years ago
ryanzhao 6c4adc08e1 add footer button 2 years ago
ryanzhao c758ef4d27 Merge branch 'feature/add-footer-button-to-table-controller' of https://github.com/mpretty-cyro/session-ios into disappearing-message-redesign 2 years ago
ryanzhao 6708104efa update database migration 2 years ago
ryanzhao 9e08ab308b correct closed group disappearing message type 2 years ago
ryanzhao 75856ff5c0 minor fix on choosing between DAR and DAS 2 years ago
ryanzhao fee64b6bf0 update disappearing message settings timer section 2 years ago
ryanzhao d01cda454c disappearing message settings UI for closed groups 2 years ago
ryanzhao 9c165000c2 wrap up the disappearing message settings screen 2 years ago
ryanzhao 1a98b0be62 Merge branch 'dev' into disappearing-message-redesign 2 years ago
Ryan Zhao d0f790421a WIP: disappearing message settings ui 2 years ago
Ryan Zhao d803ba20e7 themed scrollable subtitle 2 years ago
Ryan Zhao 12cd02fa0e minor UI fix for scrollable subtitle 2 years ago
Ryan Zhao ee3a03f7cb scrollable subtitle for conversation screen 2 years ago
Ryan Zhao 56e377824a WIP: disappearing message settings ui 2 years ago
Ryan Zhao 4e2eab9975 add localised string and paged scrollview 2 years ago

@ -20,6 +20,15 @@ local clone_submodules = {
// cmake options for static deps mirror
local ci_dep_mirror(want_mirror) = (if want_mirror then ' -DLOCAL_MIRROR=https://oxen.rocks/deps ' else '');
// Output some information about the built tools in case specific combinations break the build
local machine_info = {
name: 'Machine info',
commands: [
'xcodebuild -version',
'LANG=en_US.UTF-8 pod --version'
]
};
// Cocoapods
//
// Unfortunately Cocoapods has a dumb restriction which requires you to use UTF-8 for the
@ -223,4 +232,4 @@ local update_cocoapods_cache(depends_on) = {
},
],
},
]
]

@ -1 +1 @@
Subproject commit e3ccf29db08aaf0b9bb6bbe72ae5967cd183a78d
Subproject commit 4a84257d590d963f38e10dd527476b4eb168b031

@ -131,22 +131,21 @@ DEPENDENCIES:
- YYImage/libwebp (from `https://github.com/signalapp/YYImage`)
SPEC REPOS:
https://github.com/CocoaPods/Specs.git:
trunk:
- CocoaLumberjack
- DifferenceKit
- GRDB.swift
- libwebp
- Nimble
- NVActivityIndicatorView
- OpenSSL-Universal
- PureLayout
- Quick
- Reachability
- SAMKeychain
- SQLCipher
- SwiftProtobuf
- WebRTC-lib
trunk:
- libwebp
- Nimble
- Quick
EXTERNAL SOURCES:
Curve25519Kit:

@ -29,38 +29,50 @@ extension ProjectState {
]
static let excludedPhrases: Set<String> = [ "", " ", ",", ", ", "null" ]
static let excludedUnlocalisedStringLineMatching: Set<MatchType> = [
.contains(ProjectState.lintSuppression),
.prefix("#import"),
.prefix("@available("),
.contains("fatalError("),
.contains("precondition("),
.contains("preconditionFailure("),
.contains("print("),
.contains("NSLog("),
.contains("SNLog("),
.contains("SNLogNotTests("),
.contains("owsFailDebug("),
.contains("#imageLiteral(resourceName:"),
.contains("UIImage(named:"),
.contains("UIImage(systemName:"),
.contains("[UIImage imageNamed:"),
.contains("UIFont(name:"),
.contains(".dateFormat ="),
.contains(".accessibilityLabel ="),
.contains(".accessibilityValue ="),
.contains(".accessibilityIdentifier ="),
.contains("accessibilityIdentifier:"),
.contains("accessibilityLabel:"),
.contains("Accessibility(identifier:"),
.contains("Accessibility(label:"),
.contains("NSAttributedString.Key("),
.contains("Notification.Name("),
.contains("Notification.Key("),
.contains("DispatchQueue("),
.containsAnd("identifier:", .previousLine(numEarlier: 1, .contains("Accessibility("))),
.containsAnd("label:", .previousLine(numEarlier: 1, .contains("Accessibility("))),
.containsAnd("label:", .previousLine(numEarlier: 2, .contains("Accessibility("))),
.contains("SQL("),
.contains(ProjectState.lintSuppression, caseSensitive: false),
.prefix("#import", caseSensitive: false),
.prefix("@available(", caseSensitive: false),
.contains("fatalError(", caseSensitive: false),
.contains("precondition(", caseSensitive: false),
.contains("preconditionFailure(", caseSensitive: false),
.contains("print(", caseSensitive: false),
.contains("NSLog(", caseSensitive: false),
.contains("SNLog(", caseSensitive: false),
.contains("SNLogNotTests(", caseSensitive: false),
.contains("owsFailDebug(", caseSensitive: false),
.contains("#imageLiteral(resourceName:", caseSensitive: false),
.contains("UIImage(named:", caseSensitive: false),
.contains("UIImage(systemName:", caseSensitive: false),
.contains("[UIImage imageNamed:", caseSensitive: false),
.contains("UIFont(name:", caseSensitive: false),
.contains(".dateFormat =", caseSensitive: false),
.contains(".accessibilityLabel =", caseSensitive: false),
.contains(".accessibilityValue =", caseSensitive: false),
.contains(".accessibilityIdentifier =", caseSensitive: false),
.contains("accessibilityIdentifier:", caseSensitive: false),
.contains("accessibilityLabel:", caseSensitive: false),
.contains("Accessibility(identifier:", caseSensitive: false),
.contains("Accessibility(label:", caseSensitive: false),
.contains("NSAttributedString.Key(", caseSensitive: false),
.contains("Notification.Name(", caseSensitive: false),
.contains("Notification.Key(", caseSensitive: false),
.contains("DispatchQueue(", caseSensitive: false),
.containsAnd(
"identifier:",
caseSensitive: false,
.previousLine(numEarlier: 1, .contains("Accessibility(", caseSensitive: false))
),
.containsAnd(
"label:",
caseSensitive: false,
.previousLine(numEarlier: 1, .contains("Accessibility(", caseSensitive: false))
),
.containsAnd(
"label:",
caseSensitive: false,
.previousLine(numEarlier: 2, .contains("Accessibility(", caseSensitive: false))
),
.contains("SQL(", caseSensitive: false),
.regex(".*static var databaseTableName: String"),
.regex("Logger\\..*\\("),
.regex("OWSLogger\\..*\\("),
@ -528,21 +540,33 @@ extension ProjectState {
}
indirect enum MatchType: Hashable {
case prefix(String)
case contains(String)
case containsAnd(String, MatchType)
case prefix(String, caseSensitive: Bool)
case contains(String, caseSensitive: Bool)
case containsAnd(String, caseSensitive: Bool, MatchType)
case regex(String)
case previousLine(numEarlier: Int, MatchType)
func matches(_ value: String, _ index: Int, _ lines: [String]) -> Bool {
switch self {
case .prefix(let prefix):
case .prefix(let prefix, false):
return value
.lowercased()
.trimmingCharacters(in: .whitespacesAndNewlines)
.hasPrefix(prefix.lowercased())
case .prefix(let prefix, true):
return value
.trimmingCharacters(in: .whitespacesAndNewlines)
.hasPrefix(prefix)
case .contains(let other): return value.contains(other)
case .containsAnd(let other, let otherMatch):
case .contains(let other, false): return value.lowercased().contains(other.lowercased())
case .contains(let other, true): return value.contains(other)
case .containsAnd(let other, false, let otherMatch):
guard value.lowercased().contains(other.lowercased()) else { return false }
return otherMatch.matches(value, index, lines)
case .containsAnd(let other, true, let otherMatch):
guard value.contains(other) else { return false }
return otherMatch.matches(value, index, lines)

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */; };
3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3430FE171F7751D4000EC51B /* GiphyAPI.swift */; };
34661FB820C1C0D60056EDD6 /* message_sent.aiff in Resources */ = {isa = PBXBuildFile; fileRef = 34661FB720C1C0D60056EDD6 /* message_sent.aiff */; };
346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */; };
@ -30,7 +29,6 @@
34D1F0521F7E8EA30066283D /* GiphyDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D1F0511F7E8EA30066283D /* GiphyDownloader.swift */; };
34D99CE4217509C2000AFB39 /* AppEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D99CE3217509C1000AFB39 /* AppEnvironment.swift */; };
34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34F308A11ECB469700BB7697 /* OWSBezierPathView.m */; };
3B59D92C6C15D82844A6BF16 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76B2DECEBFEEEFA2221BA817 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework */; };
4503F1BE20470A5B00CEE724 /* classic-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 4503F1BB20470A5B00CEE724 /* classic-quiet.aifc */; };
4503F1BF20470A5B00CEE724 /* classic.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 4503F1BC20470A5B00CEE724 /* classic.aifc */; };
450DF2091E0DD2C6003D14BE /* UserNotificationsAdaptee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450DF2081E0DD2C6003D14BE /* UserNotificationsAdaptee.swift */; };
@ -81,14 +79,11 @@
4C1885D2218F8E1C00B67051 /* PhotoGridViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1885D1218F8E1C00B67051 /* PhotoGridViewCell.swift */; };
4C21D5D8223AC60F00EF8A77 /* PhotoCapture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C21D5D7223AC60F00EF8A77 /* PhotoCapture.swift */; };
4C4AE6A1224AF35700D4AF6F /* SendMediaNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4AE69F224AF21900D4AF6F /* SendMediaNavigationController.swift */; };
4C586926224FAB83003FD070 /* AVAudioSession+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C586925224FAB83003FD070 /* AVAudioSession+OWS.m */; };
4C63CC00210A620B003AE45C /* SignalTSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C63CBFF210A620B003AE45C /* SignalTSan.supp */; };
4C6F527C20FFE8400097DEEE /* SignalUBSan.supp in Resources */ = {isa = PBXBuildFile; fileRef = 4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */; };
4CA46F4C219CCC630038ABDE /* CaptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA46F4B219CCC630038ABDE /* CaptionView.swift */; };
4CA485BB2232339F004B9E7D /* PhotoCaptureViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA485BA2232339F004B9E7D /* PhotoCaptureViewController.swift */; };
4CC613362227A00400E21A3A /* ConversationSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC613352227A00400E21A3A /* ConversationSearch.swift */; };
58860CDCE675B63CBDB1EEED /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E36D73700ED95C005B6BA026 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework */; };
6D6C9F16F244E7FADB1ACBE9 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionSnodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8B0BA5257C58DC6FF797278 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionSnodeKit.framework */; };
70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70377AAA1918450100CAF501 /* MobileCoreServices.framework */; };
76C87F19181EFCE600C4ACAB /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */; };
7B0EFDEE274F598600FFAAE7 /* TimestampUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0EFDED274F598600FFAAE7 /* TimestampUtils.swift */; };
@ -112,13 +107,19 @@
7B46AAAF28766DF4001AF2DC /* AllMediaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B46AAAE28766DF4001AF2DC /* AllMediaViewController.swift */; };
7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */; };
7B4C75CD26BB92060000AC89 /* DeletedMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */; };
7B4EF25A2934743000CB351D /* SessionTableViewTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4EF2592934743000CB351D /* SessionTableViewTitleView.swift */; };
7B50D64D28AC7CF80086CCEC /* silence.aiff in Resources */ = {isa = PBXBuildFile; fileRef = 7B50D64C28AC7CF80086CCEC /* silence.aiff */; };
7B521E0A29BFF84400C3C36A /* GroupLeavingJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B521E0929BFF84400C3C36A /* GroupLeavingJob.swift */; };
7B5233C42900E90F00F8F375 /* SessionLabelCarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5233C32900E90F00F8F375 /* SessionLabelCarouselView.swift */; };
7B5233C6290636D700F8F375 /* _018_DisappearingMessagesConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5233C5290636D700F8F375 /* _018_DisappearingMessagesConfiguration.swift */; };
7B7037432834B81F000DCF35 /* ReactionContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7037422834B81F000DCF35 /* ReactionContainerView.swift */; };
7B7037452834BCC0000DCF35 /* ReactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7037442834BCC0000DCF35 /* ReactionView.swift */; };
7B71A98F2925E2A600E54854 /* SessionFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B71A98E2925E2A600E54854 /* SessionFooterView.swift */; };
7B7AD41F2A5512CA00469FB1 /* GetExpirationJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7AD41E2A5512CA00469FB1 /* GetExpirationJob.swift */; };
7B7CB18E270D066F0079FF93 /* IncomingCallBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */; };
7B7CB190270FB2150079FF93 /* MiniCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18F270FB2150079FF93 /* MiniCallView.swift */; };
7B7CB192271508AD0079FF93 /* CallRingTonePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */; };
7B7E5B522A4D024C00A8208E /* ExpirationUpdateJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7E5B512A4D024C00A8208E /* ExpirationUpdateJob.swift */; };
7B81682328A4C1210069F315 /* UpdateTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682228A4C1210069F315 /* UpdateTypes.swift */; };
7B81682828B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682728B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift */; };
7B81682A28B6F1420069F315 /* ReactionResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682928B6F1420069F315 /* ReactionResponse.swift */; };
@ -135,6 +136,7 @@
7B9F71D42852EEE2006DFE7B /* Emoji+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9F71CF2852EEE2006DFE7B /* Emoji+Name.swift */; };
7B9F71D72853100A006DFE7B /* Emoji+Available.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9F71D528531009006DFE7B /* Emoji+Available.swift */; };
7B9F71D82853100A006DFE7B /* EmojiWithSkinTones.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9F71D628531009006DFE7B /* EmojiWithSkinTones.swift */; };
7BA37AFB2AEB64CA002438F8 /* DisappearingMessageTimerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA37AFA2AEB64CA002438F8 /* DisappearingMessageTimerView.swift */; };
7BA68909272A27BE00EFC32F /* SessionCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA68908272A27BE00EFC32F /* SessionCall.swift */; };
7BA6890D27325CCC00EFC32F /* SessionCallManager+CXCallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA6890C27325CCC00EFC32F /* SessionCallManager+CXCallController.swift */; };
7BA6890F27325CE300EFC32F /* SessionCallManager+CXProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA6890E27325CE300EFC32F /* SessionCallManager+CXProvider.swift */; };
@ -145,6 +147,7 @@
7BAF54D027ACCEEC003D12F8 /* EmptySearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF54CD27ACCEEC003D12F8 /* EmptySearchResultCell.swift */; };
7BAF54D327ACCF01003D12F8 /* ShareAppExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF54D127ACCF01003D12F8 /* ShareAppExtensionContext.swift */; };
7BAF54D427ACCF01003D12F8 /* SAEScreenLockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF54D227ACCF01003D12F8 /* SAEScreenLockViewController.swift */; };
7BAFA1192A39669400B76CB9 /* BezierPathView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAFA1182A39669400B76CB9 /* BezierPathView.swift */; };
7BB92B3F28C825FD0082762F /* NewConversationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB92B3E28C825FD0082762F /* NewConversationViewModel.swift */; };
7BBBDC44286EAD2D00747E59 /* TappableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBDC43286EAD2D00747E59 /* TappableLabel.swift */; };
7BBBDC462875600700747E59 /* DocumentTitleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBDC452875600700747E59 /* DocumentTitleViewController.swift */; };
@ -158,6 +161,9 @@
7BFD1A8A2745C4F000FB91B9 /* Permissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFD1A892745C4F000FB91B9 /* Permissions.swift */; };
7BFD1A8C2747150E00FB91B9 /* TurnServerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFD1A8B2747150E00FB91B9 /* TurnServerInfo.swift */; };
7BFD1A972747689000FB91B9 /* Session-Turn-Server in Resources */ = {isa = PBXBuildFile; fileRef = 7BFD1A962747689000FB91B9 /* Session-Turn-Server */; };
9422EE2B2B8C3A97004C740D /* String+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9422EE2A2B8C3A97004C740D /* String+Utilities.swift */; };
943C6D822B75E061004ACE64 /* Message+DisappearingMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943C6D812B75E061004ACE64 /* Message+DisappearingMessages.swift */; };
9593A1E796C9E6BE2352EA6F /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionSnodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8B0BA5257C58DC6FF797278 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionSnodeKit.framework */; };
99978E3F7A80275823CA9014 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionNotificationServiceExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29E827FDF6C1032BB985740C /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionNotificationServiceExtension.framework */; };
A11CD70D17FA230600A2D1B1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */; };
A163E8AB16F3F6AA0094D68B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A163E8AA16F3F6A90094D68B /* Security.framework */; };
@ -429,6 +435,7 @@
C3DB66C3260ACCE6001EFC55 /* OpenGroupPoller.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DB66C2260ACCE6001EFC55 /* OpenGroupPoller.swift */; };
C3E5C2FA251DBABB0040DFFC /* EditClosedGroupVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E5C2F9251DBABB0040DFFC /* EditClosedGroupVC.swift */; };
C3F0A530255C80BC007BE2A3 /* NoopNotificationsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F0A52F255C80BC007BE2A3 /* NoopNotificationsManager.swift */; };
C93FE8F2981231B9D7A0D96D /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA2B4D0F28E3FD1F3D18E2C4 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework */; };
D2179CFC16BB0B3A0006F3AB /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2179CFB16BB0B3A0006F3AB /* CoreTelephony.framework */; };
D2179CFE16BB0B480006F3AB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */; };
D221A08E169C9E5E00537ABF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A08D169C9E5E00537ABF /* UIKit.framework */; };
@ -437,6 +444,7 @@
D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D24B5BD4169F568C00681372 /* AudioToolbox.framework */; };
D2AEACDC16C426DA00C364C0 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; };
D53824DFCED7AE6BB61E7640 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SignalUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92E8569C96285EE3CDB5960D /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SignalUtilitiesKit.framework */; };
D843F0BF3CCF3D61C3316F32 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA1B4423336A8A5EA0A894FA /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework */; };
DE53B40717A9417578FB40DE /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE35EBADE13F7B7D979B71D5 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit.framework */; };
E984778319BDF24A7ADF100A /* Pods_GlobalDependencies_SessionUIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E517F8611575B37B76BCC54 /* Pods_GlobalDependencies_SessionUIKit.framework */; };
FC3BD9881A30A790005B96BB /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC3BD9871A30A790005B96BB /* Social.framework */; };
@ -757,6 +765,7 @@
FDA8EAFE280E8B78002B68E5 /* FailedMessageSendsJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFD280E8B78002B68E5 /* FailedMessageSendsJob.swift */; };
FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */; };
FDA8EB10280F8238002B68E5 /* Codable+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EB0F280F8238002B68E5 /* Codable+Utilities.swift */; };
FDAED05C2A7C6CE600091B25 /* MigrationRequirement.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDAED05B2A7C6CE600091B25 /* MigrationRequirement.swift */; };
FDB4BBC72838B91E00B7C95D /* LinkPreviewError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB4BBC62838B91E00B7C95D /* LinkPreviewError.swift */; };
FDB4BBC92839BEF000B7C95D /* ProfileManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDB4BBC82839BEF000B7C95D /* ProfileManagerError.swift */; };
FDB6A87C2AD75B7F002D4F96 /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FDB6A87B2AD75B7F002D4F96 /* PhotosUI.framework */; };
@ -821,6 +830,9 @@
FDCD2E032A41294E00964D6A /* LegacyGroupOnlyRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCD2E022A41294E00964D6A /* LegacyGroupOnlyRequest.swift */; };
FDCDB8DE2810F73B00352A0C /* Differentiable+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DD2810F73B00352A0C /* Differentiable+Utilities.swift */; };
FDCDB8E02811007F00352A0C /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DF2811007F00352A0C /* HomeViewModel.swift */; };
FDD20C162A09E64A003898FB /* GetExpiriesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD20C152A09E64A003898FB /* GetExpiriesRequest.swift */; };
FDD20C182A09E7D3003898FB /* GetExpiriesResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD20C172A09E7D3003898FB /* GetExpiriesResponse.swift */; };
FDD20C1A2A0A03AC003898FB /* DeleteInboxResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD20C192A0A03AC003898FB /* DeleteInboxResponse.swift */; };
FDD2506E283711D600198BDA /* DifferenceKit+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD2506D283711D600198BDA /* DifferenceKit+Utilities.swift */; };
FDD250702837199200198BDA /* GarbageCollectionJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */; };
FDD250722837234B00198BDA /* MediaGalleryNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */; };
@ -936,7 +948,7 @@
FDFE75B52ABD46B700655640 /* MockUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD83B9D127D59495005E1583 /* MockUserDefaults.swift */; };
FDFF61D729F2600300F95FB0 /* Identity+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDFF61D629F2600300F95FB0 /* Identity+Utilities.swift */; };
FDFF9FDF2A787F57005E0628 /* JSONEncoder+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDFF9FDE2A787F57005E0628 /* JSONEncoder+Utilities.swift */; };
FE5FDED6D91BB4B3FA5C104D /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A9C113D2086D3C8A68A371C /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework */; };
FE2FFEF6F615EE65BA087187 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E36D73700ED95C005B6BA026 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -1120,8 +1132,6 @@
285705D20F792E174C8A9BBA /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; sourceTree = "<group>"; };
29E827FDF6C1032BB985740C /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionNotificationServiceExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionNotificationServiceExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
34040971CC7AF9C8A6C1E838 /* Pods-GlobalDependencies-Session.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-Session.debug.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-Session/Pods-GlobalDependencies-Session.debug.xcconfig"; sourceTree = "<group>"; };
3427C64120F500DE00EEC730 /* OWSMessageTimerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageTimerView.h; sourceTree = "<group>"; };
3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageTimerView.m; sourceTree = "<group>"; };
3430FE171F7751D4000EC51B /* GiphyAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GiphyAPI.swift; sourceTree = "<group>"; };
34480B371FD092A900BC14EF /* SignalShareExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SignalShareExtension-Bridging-Header.h"; sourceTree = "<group>"; };
34661FB720C1C0D60056EDD6 /* message_sent.aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; name = message_sent.aiff; path = Session/Meta/AudioFiles/message_sent.aiff; sourceTree = SOURCE_ROOT; };
@ -1199,8 +1209,6 @@
4C1885D1218F8E1C00B67051 /* PhotoGridViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoGridViewCell.swift; sourceTree = "<group>"; };
4C21D5D7223AC60F00EF8A77 /* PhotoCapture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoCapture.swift; sourceTree = "<group>"; };
4C4AE69F224AF21900D4AF6F /* SendMediaNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMediaNavigationController.swift; sourceTree = "<group>"; };
4C586924224FAB83003FD070 /* AVAudioSession+OWS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AVAudioSession+OWS.h"; sourceTree = "<group>"; };
4C586925224FAB83003FD070 /* AVAudioSession+OWS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "AVAudioSession+OWS.m"; sourceTree = "<group>"; };
4C63CBFF210A620B003AE45C /* SignalTSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalTSan.supp; sourceTree = "<group>"; };
4C6F527B20FFE8400097DEEE /* SignalUBSan.supp */ = {isa = PBXFileReference; lastKnownFileType = text; path = SignalUBSan.supp; sourceTree = "<group>"; };
4CA46F4B219CCC630038ABDE /* CaptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaptionView.swift; sourceTree = "<group>"; };
@ -1213,9 +1221,9 @@
6A71AD9BEAFF0C9E8016BC23 /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionShareExtension.app store release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionShareExtension.app store release.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionShareExtension/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionShareExtension.app store release.xcconfig"; sourceTree = "<group>"; };
6DA09080DD9779C860023A60 /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionMessagingKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionMessagingKit.debug.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionMessagingKit/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionMessagingKit.debug.xcconfig"; sourceTree = "<group>"; };
70377AAA1918450100CAF501 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
76B2DECEBFEEEFA2221BA817 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
7A9C113D2086D3C8A68A371C /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7B02DF432A16F47B00ADCFD2 /* EmojiGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiGenerator.swift; sourceTree = "<group>"; };
7B02DF442A16F47B00ADCFD2 /* build_libSession_util.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build_libSession_util.sh; sourceTree = "<group>"; };
7B0EFDED274F598600FFAAE7 /* TimestampUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimestampUtils.swift; sourceTree = "<group>"; };
7B0EFDEF275084AA00FFAAE7 /* CallMessageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMessageCell.swift; sourceTree = "<group>"; };
7B0EFDF3275490EA00FFAAE7 /* ringing.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringing.mp3; sourceTree = "<group>"; };
@ -1237,13 +1245,19 @@
7B46AAAE28766DF4001AF2DC /* AllMediaViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllMediaViewController.swift; sourceTree = "<group>"; };
7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsendRequest.swift; sourceTree = "<group>"; };
7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletedMessageView.swift; sourceTree = "<group>"; };
7B4EF2592934743000CB351D /* SessionTableViewTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionTableViewTitleView.swift; sourceTree = "<group>"; };
7B50D64C28AC7CF80086CCEC /* silence.aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; path = silence.aiff; sourceTree = "<group>"; };
7B521E0929BFF84400C3C36A /* GroupLeavingJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupLeavingJob.swift; sourceTree = "<group>"; };
7B5233C32900E90F00F8F375 /* SessionLabelCarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionLabelCarouselView.swift; sourceTree = "<group>"; };
7B5233C5290636D700F8F375 /* _018_DisappearingMessagesConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _018_DisappearingMessagesConfiguration.swift; sourceTree = "<group>"; };
7B7037422834B81F000DCF35 /* ReactionContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionContainerView.swift; sourceTree = "<group>"; };
7B7037442834BCC0000DCF35 /* ReactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionView.swift; sourceTree = "<group>"; };
7B71A98E2925E2A600E54854 /* SessionFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionFooterView.swift; sourceTree = "<group>"; };
7B7AD41E2A5512CA00469FB1 /* GetExpirationJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetExpirationJob.swift; sourceTree = "<group>"; };
7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallBanner.swift; sourceTree = "<group>"; };
7B7CB18F270FB2150079FF93 /* MiniCallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniCallView.swift; sourceTree = "<group>"; };
7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallRingTonePlayer.swift; sourceTree = "<group>"; };
7B7E5B512A4D024C00A8208E /* ExpirationUpdateJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpirationUpdateJob.swift; sourceTree = "<group>"; };
7B81682228A4C1210069F315 /* UpdateTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateTypes.swift; sourceTree = "<group>"; };
7B81682728B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _007_HomeQueryOptimisationIndexes.swift; sourceTree = "<group>"; };
7B81682928B6F1420069F315 /* ReactionResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionResponse.swift; sourceTree = "<group>"; };
@ -1260,6 +1274,7 @@
7B9F71CF2852EEE2006DFE7B /* Emoji+Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Emoji+Name.swift"; sourceTree = "<group>"; };
7B9F71D528531009006DFE7B /* Emoji+Available.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Emoji+Available.swift"; sourceTree = "<group>"; };
7B9F71D628531009006DFE7B /* EmojiWithSkinTones.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmojiWithSkinTones.swift; sourceTree = "<group>"; };
7BA37AFA2AEB64CA002438F8 /* DisappearingMessageTimerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisappearingMessageTimerView.swift; sourceTree = "<group>"; };
7BA68908272A27BE00EFC32F /* SessionCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionCall.swift; sourceTree = "<group>"; };
7BA6890C27325CCC00EFC32F /* SessionCallManager+CXCallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionCallManager+CXCallController.swift"; sourceTree = "<group>"; };
7BA6890E27325CE300EFC32F /* SessionCallManager+CXProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionCallManager+CXProvider.swift"; sourceTree = "<group>"; };
@ -1271,6 +1286,7 @@
7BAF54D127ACCF01003D12F8 /* ShareAppExtensionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareAppExtensionContext.swift; sourceTree = "<group>"; };
7BAF54D227ACCF01003D12F8 /* SAEScreenLockViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SAEScreenLockViewController.swift; sourceTree = "<group>"; };
7BAF54D527ACD0E2003D12F8 /* ReusableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReusableView.swift; sourceTree = "<group>"; };
7BAFA1182A39669400B76CB9 /* BezierPathView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BezierPathView.swift; sourceTree = "<group>"; };
7BB92B3E28C825FD0082762F /* NewConversationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewConversationViewModel.swift; sourceTree = "<group>"; };
7BBBDC43286EAD2D00747E59 /* TappableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TappableLabel.swift; sourceTree = "<group>"; };
7BBBDC452875600700747E59 /* DocumentTitleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentTitleViewController.swift; sourceTree = "<group>"; };
@ -1293,6 +1309,8 @@
8E946CB54A221018E23599DE /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.debug.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-ExtendedDependencies-SessionUtilitiesKit.debug.xcconfig"; sourceTree = "<group>"; };
92E8569C96285EE3CDB5960D /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SignalUtilitiesKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SignalUtilitiesKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
93359C81CF2660040B7CD106 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit_SessionUtilitiesKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit_SessionUtilitiesKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9422EE2A2B8C3A97004C740D /* String+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Utilities.swift"; sourceTree = "<group>"; };
943C6D812B75E061004ACE64 /* Message+DisappearingMessages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Message+DisappearingMessages.swift"; sourceTree = "<group>"; };
A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
A163E8AA16F3F6A90094D68B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
@ -1387,6 +1405,7 @@
B8FF8E7325C10FC3004D1F22 /* GeoLite2-Country-Locations-English */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "GeoLite2-Country-Locations-English"; path = "Countries/GeoLite2-Country-Locations-English"; sourceTree = "<group>"; };
B8FF8EA525C11FEF004D1F22 /* IPv4.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPv4.swift; sourceTree = "<group>"; };
B9EB5ABC1884C002007CBB57 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
BA1B4423336A8A5EA0A894FA /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BE35EBADE13F7B7D979B71D5 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C300A5B12554AF9800555489 /* VisibleMessage+Profile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisibleMessage+Profile.swift"; sourceTree = "<group>"; };
C300A5BC2554B00D00555489 /* ReadReceipt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadReceipt.swift; sourceTree = "<group>"; };
@ -1593,6 +1612,7 @@
D221A0E7169DFFC500537ABF /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = ../../../../../../System/Library/Frameworks/AVFoundation.framework; sourceTree = "<group>"; };
D24B5BD4169F568C00681372 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = ../../../../../../System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<group>"; };
D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
DA2B4D0F28E3FD1F3D18E2C4 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E1A0AD8B16E13FDD0071E604 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
E36D73700ED95C005B6BA026 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EB5B8ACA4C6F512FA3E21859 /* Pods-GlobalDependencies-SessionUIKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-SessionUIKit.debug.xcconfig"; path = "Target Support Files/Pods-GlobalDependencies-SessionUIKit/Pods-GlobalDependencies-SessionUIKit.debug.xcconfig"; sourceTree = "<group>"; };
@ -1908,6 +1928,7 @@
FDA8EAFD280E8B78002B68E5 /* FailedMessageSendsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedMessageSendsJob.swift; sourceTree = "<group>"; };
FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedAttachmentDownloadsJob.swift; sourceTree = "<group>"; };
FDA8EB0F280F8238002B68E5 /* Codable+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Codable+Utilities.swift"; sourceTree = "<group>"; };
FDAED05B2A7C6CE600091B25 /* MigrationRequirement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationRequirement.swift; sourceTree = "<group>"; };
FDB4BBC62838B91E00B7C95D /* LinkPreviewError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewError.swift; sourceTree = "<group>"; };
FDB4BBC82839BEF000B7C95D /* ProfileManagerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileManagerError.swift; sourceTree = "<group>"; };
FDB6A87B2AD75B7F002D4F96 /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = System/Library/Frameworks/PhotosUI.framework; sourceTree = SDKROOT; };
@ -1971,6 +1992,9 @@
FDCD2E022A41294E00964D6A /* LegacyGroupOnlyRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyGroupOnlyRequest.swift; sourceTree = "<group>"; };
FDCDB8DD2810F73B00352A0C /* Differentiable+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Differentiable+Utilities.swift"; sourceTree = "<group>"; };
FDCDB8DF2811007F00352A0C /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
FDD20C152A09E64A003898FB /* GetExpiriesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetExpiriesRequest.swift; sourceTree = "<group>"; };
FDD20C172A09E7D3003898FB /* GetExpiriesResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetExpiriesResponse.swift; sourceTree = "<group>"; };
FDD20C192A0A03AC003898FB /* DeleteInboxResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteInboxResponse.swift; sourceTree = "<group>"; };
FDD2506D283711D600198BDA /* DifferenceKit+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DifferenceKit+Utilities.swift"; sourceTree = "<group>"; };
FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GarbageCollectionJob.swift; sourceTree = "<group>"; };
FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaGalleryNavigationController.swift; sourceTree = "<group>"; };
@ -2096,7 +2120,7 @@
C3D90A5C25773A25002C9DF5 /* SessionUtilitiesKit.framework in Frameworks */,
C3402FE52559036600EA6424 /* SessionUIKit.framework in Frameworks */,
B8D64FCB25BA78A90029CFC0 /* SignalUtilitiesKit.framework in Frameworks */,
FE5FDED6D91BB4B3FA5C104D /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework in Frameworks */,
D843F0BF3CCF3D61C3316F32 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2138,7 +2162,7 @@
buildActionMask = 2147483647;
files = (
C3C2A6C62553896A00C340D1 /* SessionUtilitiesKit.framework in Frameworks */,
6D6C9F16F244E7FADB1ACBE9 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionSnodeKit.framework in Frameworks */,
9593A1E796C9E6BE2352EA6F /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_SessionSnodeKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2146,7 +2170,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
58860CDCE675B63CBDB1EEED /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework in Frameworks */,
FE2FFEF6F615EE65BA087187 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2162,6 +2186,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C8BB5A4618641C387640AE22 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D221A086169C9E5E00537ABF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -2222,7 +2253,7 @@
buildActionMask = 2147483647;
files = (
FDC4389227B9FFC700C60D73 /* SessionMessagingKit.framework in Frameworks */,
3B59D92C6C15D82844A6BF16 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework in Frameworks */,
C93FE8F2981231B9D7A0D96D /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2354,8 +2385,6 @@
45C0DC1A1E68FE9000E04C47 /* UIApplication+OWS.swift */,
45C0DC1D1E69011F00E04C47 /* UIStoryboard+OWS.swift */,
45B5360D206DD8BB00D61655 /* UIResponder+OWS.swift */,
4C586924224FAB83003FD070 /* AVAudioSession+OWS.h */,
4C586925224FAB83003FD070 /* AVAudioSession+OWS.m */,
4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */,
FD37E9D828A230F2003AE748 /* TraitObservingWindow.swift */,
C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */,
@ -2488,6 +2517,7 @@
7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */,
7B7037422834B81F000DCF35 /* ReactionContainerView.swift */,
7B7037442834BCC0000DCF35 /* ReactionView.swift */,
7BA37AFA2AEB64CA002438F8 /* DisappearingMessageTimerView.swift */,
);
path = "Content Views";
sourceTree = "<group>";
@ -2513,6 +2543,7 @@
C374EEEA25DA3CA70073A857 /* ConversationTitleView.swift */,
FD4B200D283492210034334B /* InsetLockableTableView.swift */,
7B9F71C828470667006DFE7B /* ReactionListSheet.swift */,
7B5233C32900E90F00F8F375 /* SessionLabelCarouselView.swift */,
);
path = "Views & Modals";
sourceTree = "<group>";
@ -2702,6 +2733,7 @@
4CA46F4B219CCC630038ABDE /* CaptionView.swift */,
34F308A01ECB469700BB7697 /* OWSBezierPathView.h */,
34F308A11ECB469700BB7697 /* OWSBezierPathView.m */,
7BAFA1182A39669400B76CB9 /* BezierPathView.swift */,
C354E75923FE2A7600CE22E3 /* BaseVC.swift */,
B8BB82AA238F669C00BA5194 /* FullConversationCell.swift */,
4542DF53208D40AC007B4E76 /* LoadingViewController.swift */,
@ -2711,6 +2743,7 @@
FD52090828B59411006098F6 /* ScreenLockUI.swift */,
FD37EA0828AA2D27003AE748 /* SessionTableViewModel.swift */,
FD37EA0628AA2CCA003AE748 /* SessionTableViewController.swift */,
7B4EF2592934743000CB351D /* SessionTableViewTitleView.swift */,
7B3A39312980D02B002FE4AC /* SessionCarouselView.swift */,
7B2561C329874851005C086C /* SessionCarouselView+Info.swift */,
7B3A3933298882D6002FE4AC /* SessionCarouselViewDelegate.swift */,
@ -2749,6 +2782,7 @@
children = (
C3C2A74325539EB700C340D1 /* Message.swift */,
C352A30825574D8400338F3E /* Message+Destination.swift */,
943C6D812B75E061004ACE64 /* Message+DisappearingMessages.swift */,
C300A5C62554B02D00555489 /* Visible Messages */,
C300A5C72554B03900555489 /* Control Messages */,
);
@ -2812,8 +2846,6 @@
isa = PBXGroup;
children = (
B84A89BB25DE328A0040017D /* ProfilePictureVC.swift */,
3427C64120F500DE00EEC730 /* OWSMessageTimerView.h */,
3427C64220F500DF00EEC730 /* OWSMessageTimerView.m */,
FD7115EA28C5D78E00B47552 /* ThreadSettingsViewModel.swift */,
FD7115F328C71EB200B47552 /* ThreadDisappearingMessagesSettingsViewModel.swift */,
);
@ -2950,6 +2982,7 @@
C33100272559000A00070591 /* UIView+Utilities.swift */,
FD71161F28D97ABC00B47552 /* UIImage+Tinting.swift */,
FDBB25E62988BBBD00F1508E /* UIContextualAction+Theming.swift */,
9422EE2A2B8C3A97004C740D /* String+Utilities.swift */,
);
path = Utilities;
sourceTree = "<group>";
@ -3545,8 +3578,6 @@
D221A08F169C9E5E00537ABF /* Foundation.framework */,
D221A091169C9E5E00537ABF /* CoreGraphics.framework */,
BE35EBADE13F7B7D979B71D5 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit.framework */,
76B2DECEBFEEEFA2221BA817 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework */,
7A9C113D2086D3C8A68A371C /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework */,
E36D73700ED95C005B6BA026 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit.framework */,
93359C81CF2660040B7CD106 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionUtilitiesKit_SessionUtilitiesKitTests.framework */,
92E8569C96285EE3CDB5960D /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SignalUtilitiesKit.framework */,
@ -3555,6 +3586,8 @@
1677131E9189A0043FF97ACB /* Pods_GlobalDependencies_Session.framework */,
164F5FAD2DCE932054F61E78 /* Pods_GlobalDependencies_Session_SessionTests.framework */,
3E517F8611575B37B76BCC54 /* Pods_GlobalDependencies_SessionUIKit.framework */,
DA2B4D0F28E3FD1F3D18E2C4 /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionMessagingKit_SessionMessagingKitTests.framework */,
BA1B4423336A8A5EA0A894FA /* Pods_GlobalDependencies_FrameworkAndExtensionDependencies_ExtendedDependencies_SessionShareExtension.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -3656,6 +3689,7 @@
FD1D732D2A86114600E3F410 /* _015_BlockCommunityMessageRequests.swift */,
FDFE75B02ABD2D2400655640 /* _016_MakeBrokenProfileTimestampsNullable.swift */,
FD428B222B4B9969006D0888 /* _017_RebuildFTSIfNeeded_2_4_5.swift */,
7B5233C5290636D700F8F375 /* _018_DisappearingMessagesConfiguration.swift */,
);
path = Migrations;
sourceTree = "<group>";
@ -3724,6 +3758,7 @@
FD17D7B727F51ECA00122BE0 /* Migration.swift */,
FD1F9C9E2A862BE60050F671 /* MigrationRequirement.swift */,
FD17D7B927F51F2100122BE0 /* TargetMigrations.swift */,
FDAED05B2A7C6CE600091B25 /* MigrationRequirement.swift */,
FD17D7C027F5200100122BE0 /* TypedTableDefinition.swift */,
FD37EA1028AB34B3003AE748 /* TypedTableAlteration.swift */,
FD7162DA281B6C440060647B /* TypedTableAlias.swift */,
@ -4011,6 +4046,7 @@
FD37EA0A28AB12E2003AE748 /* SessionCell.swift */,
FD71164728E2CE8700B47552 /* SessionCell+AccessoryView.swift */,
FD71164528E2CC1300B47552 /* SessionHighlightingBackgroundLabel.swift */,
7B71A98E2925E2A600E54854 /* SessionFooterView.swift */,
);
path = Views;
sourceTree = "<group>";
@ -4260,6 +4296,7 @@
FDC438C627BB6DF000C60D73 /* DirectMessage.swift */,
FDC438C827BB706500C60D73 /* SendDirectMessageRequest.swift */,
FD83B9C827D0487A005E1583 /* SendDirectMessageResponse.swift */,
FDD20C192A0A03AC003898FB /* DeleteInboxResponse.swift */,
FDC438A327BB107F00C60D73 /* UserBanRequest.swift */,
FDC438A527BB113A00C60D73 /* UserUnbanRequest.swift */,
FDC438A927BB12BB00C60D73 /* UserModeratorRequest.swift */,
@ -4377,6 +4414,8 @@
FDE7214E287E50D50093DF33 /* Scripts */ = {
isa = PBXGroup;
children = (
7B02DF442A16F47B00ADCFD2 /* build_libSession_util.sh */,
7B02DF432A16F47B00ADCFD2 /* EmojiGenerator.swift */,
FDE7214F287E50D50093DF33 /* ProtoWrappers.py */,
FDCCC6E82ABA7402002BBEF5 /* EmojiGenerator.swift */,
FDE72150287E50D50093DF33 /* LintLocalizableStrings.swift */,
@ -4403,6 +4442,8 @@
C352A35A2557824E00338F3E /* AttachmentUploadJob.swift */,
7B521E0929BFF84400C3C36A /* GroupLeavingJob.swift */,
FD2B4AFE2946C93200AB4848 /* ConfigurationSyncJob.swift */,
7B7E5B512A4D024C00A8208E /* ExpirationUpdateJob.swift */,
7B7AD41E2A5512CA00469FB1 /* GetExpirationJob.swift */,
);
path = Types;
sourceTree = "<group>";
@ -4475,6 +4516,8 @@
FDF848AE29405C5A007DCAE5 /* UpdateExpiryResponse.swift */,
FDF848AC29405C5A007DCAE5 /* UpdateExpiryAllRequest.swift */,
FDF848B129405C5A007DCAE5 /* UpdateExpiryAllResponse.swift */,
FDD20C152A09E64A003898FB /* GetExpiriesRequest.swift */,
FDD20C172A09E7D3003898FB /* GetExpiriesResponse.swift */,
FDF848BA29405C5A007DCAE5 /* RevokeSubkeyRequest.swift */,
FDF848A229405C5A007DCAE5 /* RevokeSubkeyResponse.swift */,
FDF848B629405C5A007DCAE5 /* SwarmSnode.swift */,
@ -4791,6 +4834,7 @@
buildConfigurationList = FD9BDDFC2A5D2294005F1EBC /* Build configuration list for PBXNativeTarget "SessionUtil" */;
buildPhases = (
FD9BDDFF2A5D229B005F1EBC /* Build libSessionUtil if Needed */,
C8BB5A4618641C387640AE22 /* Frameworks */,
);
buildRules = (
);
@ -5633,6 +5677,7 @@
FD37E9D528A1FCE8003AE748 /* Theme+OceanLight.swift in Sources */,
FDF848F129406A30007DCAE5 /* Format.swift in Sources */,
FD37E9C828A1D73F003AE748 /* Theme+Colors.swift in Sources */,
9422EE2B2B8C3A97004C740D /* String+Utilities.swift in Sources */,
FD37EA0128A60473003AE748 /* UIKit+Theme.swift in Sources */,
FD37E9CF28A1EB1B003AE748 /* Theme.swift in Sources */,
C331FFB92558FA8D00070591 /* UIView+Constraints.swift in Sources */,
@ -5750,6 +5795,7 @@
FD17D7AA27F41BF500122BE0 /* SnodeSet.swift in Sources */,
FDF848D029405C5B007DCAE5 /* UpdateExpiryResponse.swift in Sources */,
FDF848D329405C5B007DCAE5 /* UpdateExpiryAllResponse.swift in Sources */,
FDD20C162A09E64A003898FB /* GetExpiriesRequest.swift in Sources */,
FDF848BC29405C5A007DCAE5 /* SnodeRecursiveResponse.swift in Sources */,
FDF848C029405C5A007DCAE5 /* ONSResolveResponse.swift in Sources */,
FD17D7A427F40F8100122BE0 /* _003_YDBToGRDBMigration.swift in Sources */,
@ -5774,6 +5820,7 @@
FDF848D529405C5B007DCAE5 /* DeleteAllMessagesResponse.swift in Sources */,
FDF848E329405D6E007DCAE5 /* OnionRequestAPIVersion.swift in Sources */,
FDF848BF29405C5A007DCAE5 /* SnodeResponse.swift in Sources */,
FDD20C182A09E7D3003898FB /* GetExpiriesResponse.swift in Sources */,
C3C2A5E42553860B00C340D1 /* Data+Utilities.swift in Sources */,
FDF848D929405C5B007DCAE5 /* SnodeAuthenticatedRequestBody.swift in Sources */,
FDF848ED29405E4F007DCAE5 /* Notification+OnionRequestAPI.swift in Sources */,
@ -5871,6 +5918,7 @@
FD7728982849E8110018502F /* UITableView+ReusableView.swift in Sources */,
FD428B1B2B4B6098006D0888 /* Notifications+Lifecycle.swift in Sources */,
7B0EFDEE274F598600FFAAE7 /* TimestampUtils.swift in Sources */,
FDAED05C2A7C6CE600091B25 /* MigrationRequirement.swift in Sources */,
FD52090028AF6153006098F6 /* OWSBackgroundTask.m in Sources */,
C32C5DDB256DD9FF003C73A2 /* ContentProxy.swift in Sources */,
C3A71F892558BA9F0043A11F /* Mnemonic.swift in Sources */,
@ -5961,6 +6009,7 @@
FD716E6A2850327900C96BF4 /* EndCallMode.swift in Sources */,
FDF0B75C2807F41D004C14C5 /* MessageSender+Convenience.swift in Sources */,
7B81682A28B6F1420069F315 /* ReactionResponse.swift in Sources */,
7B7E5B522A4D024C00A8208E /* ExpirationUpdateJob.swift in Sources */,
FD09799727FFA84A00936362 /* RecipientState.swift in Sources */,
FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */,
FD09798927FD1C5A00936362 /* OpenGroup.swift in Sources */,
@ -5970,6 +6019,7 @@
FD428B232B4B9969006D0888 /* _017_RebuildFTSIfNeeded_2_4_5.swift in Sources */,
FD09797527FAB64300936362 /* ProfileManager.swift in Sources */,
FD245C57285065F100B966DD /* Poller.swift in Sources */,
7B7AD41F2A5512CA00469FB1 /* GetExpirationJob.swift in Sources */,
FDA8EAFE280E8B78002B68E5 /* FailedMessageSendsJob.swift in Sources */,
FD245C6A2850666F00B966DD /* FileServerAPI.swift in Sources */,
FDFBB74D2A1F3C4E00CA7350 /* NotificationMetadata.swift in Sources */,
@ -5981,6 +6031,7 @@
FDC4385F27B4C4A200C60D73 /* PinnedMessage.swift in Sources */,
7BFD1A8C2747150E00FB91B9 /* TurnServerInfo.swift in Sources */,
B8BF43BA26CC95FB007828D1 /* WebRTC+Utilities.swift in Sources */,
FDD20C1A2A0A03AC003898FB /* DeleteInboxResponse.swift in Sources */,
7B8D5FC428332600008324D9 /* VisibleMessage+Reaction.swift in Sources */,
FDC4386527B4DE7600C60D73 /* RoomPollInfo.swift in Sources */,
FD245C6B2850667400B966DD /* VisibleMessage+Profile.swift in Sources */,
@ -6048,6 +6099,7 @@
FDC13D4B2A16ECBA007267C7 /* SubscribeResponse.swift in Sources */,
FD7115F228C6CB3900B47552 /* _010_AddThreadIdToFTS.swift in Sources */,
FD716E6428502DDD00C96BF4 /* CallManagerProtocol.swift in Sources */,
943C6D822B75E061004ACE64 /* Message+DisappearingMessages.swift in Sources */,
FDC438C727BB6DF000C60D73 /* DirectMessage.swift in Sources */,
FDC13D502A16EE50007267C7 /* PushNotificationAPIEndpoint.swift in Sources */,
FD432434299C6985008A0213 /* PendingReadReceipt.swift in Sources */,
@ -6056,6 +6108,7 @@
FD23CE222A661D000000B97C /* OpenGroupAPI+Crypto.swift in Sources */,
FD245C652850665400B966DD /* ClosedGroupControlMessage.swift in Sources */,
FDC4387827B5C35400C60D73 /* SendMessageRequest.swift in Sources */,
7B5233C6290636D700F8F375 /* _018_DisappearingMessagesConfiguration.swift in Sources */,
FD5C72FD284F0EC90029977D /* MessageReceiver+ExpirationTimers.swift in Sources */,
C32C5A88256DBCF9003C73A2 /* MessageReceiver+ClosedGroups.swift in Sources */,
B8D0A25925E367AC00C1835E /* Notification+MessageReceiver.swift in Sources */,
@ -6142,6 +6195,7 @@
FDF2220B2818F38D000A4995 /* SessionApp.swift in Sources */,
FD7115EB28C5D78E00B47552 /* ThreadSettingsViewModel.swift in Sources */,
B8041AA725C90927003C2166 /* TypingIndicatorCell.swift in Sources */,
7B4EF25A2934743000CB351D /* SessionTableViewTitleView.swift in Sources */,
B8CCF63723961D6D0091D419 /* NewDMVC.swift in Sources */,
FDFDE12A282D056B0098B17F /* MediaZoomAnimationController.swift in Sources */,
4C1885D2218F8E1C00B67051 /* PhotoGridViewCell.swift in Sources */,
@ -6160,6 +6214,7 @@
B877E24626CA13BA0007970A /* CallVC+Camera.swift in Sources */,
454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */,
451A13B11E13DED2000A50FD /* AppNotifications.swift in Sources */,
7BA37AFB2AEB64CA002438F8 /* DisappearingMessageTimerView.swift in Sources */,
FD12A8492AD63C4700EEBA0D /* SessionNavItem.swift in Sources */,
FD12A83D2AD63BCC00EEBA0D /* EditableState.swift in Sources */,
34D99CE4217509C2000AFB39 /* AppEnvironment.swift in Sources */,
@ -6230,6 +6285,7 @@
B877E24226CA12910007970A /* CallVC.swift in Sources */,
FDC498B92AC15FE300EDD897 /* AppNotificationAction.swift in Sources */,
7BA6890D27325CCC00EFC32F /* SessionCallManager+CXCallController.swift in Sources */,
7B71A98F2925E2A600E54854 /* SessionFooterView.swift in Sources */,
C374EEEB25DA3CA70073A857 /* ConversationTitleView.swift in Sources */,
FD716E7128505E5200C96BF4 /* MessageRequestsCell.swift in Sources */,
FDF848F329413DB0007DCAE5 /* ImagePickerHandler.swift in Sources */,
@ -6249,7 +6305,6 @@
7BAF54CF27ACCEEC003D12F8 /* GlobalSearchViewController.swift in Sources */,
FD37EA1728AC5605003AE748 /* NotificationContentViewModel.swift in Sources */,
B886B4A72398B23E00211ABE /* QRCodeVC.swift in Sources */,
4C586926224FAB83003FD070 /* AVAudioSession+OWS.m in Sources */,
C331FFF42558FF0300070591 /* PNOptionView.swift in Sources */,
7BB92B3F28C825FD0082762F /* NewConversationViewModel.swift in Sources */,
4C4AE6A1224AF35700D4AF6F /* SendMediaNavigationController.swift in Sources */,
@ -6322,9 +6377,11 @@
B835249B25C3AB650089A44F /* VisibleMessageCell.swift in Sources */,
B8D0A25025E3678700C1835E /* LinkDeviceVC.swift in Sources */,
B894D0752339EDCF00B4D94D /* NukeDataModal.swift in Sources */,
7B5233C42900E90F00F8F375 /* SessionLabelCarouselView.swift in Sources */,
7B93D07727CF1A8A00811CB6 /* MockDataGenerator.swift in Sources */,
7B1B52D828580C6D006069F2 /* EmojiPickerSheet.swift in Sources */,
FD368A6A29DE9E30000DBF1E /* UIContextualAction+Utilities.swift in Sources */,
7BAFA1192A39669400B76CB9 /* BezierPathView.swift in Sources */,
7B4C75CD26BB92060000AC89 /* DeletedMessageView.swift in Sources */,
FDD250722837234B00198BDA /* MediaGalleryNavigationController.swift in Sources */,
FDD2506E283711D600198BDA /* DifferenceKit+Utilities.swift in Sources */,
@ -6339,7 +6396,6 @@
FD37E9CC28A1E578003AE748 /* AppearanceViewController.swift in Sources */,
B8EB20F02640F7F000773E52 /* OpenGroupInvitationView.swift in Sources */,
C328254025CA55880062D0A7 /* ContextMenuVC.swift in Sources */,
3427C64320F500E000EEC730 /* OWSMessageTimerView.m in Sources */,
B8269D2925C7A4B400488AB4 /* InputView.swift in Sources */,
FD71162E28E168C700B47552 /* SettingsViewModel.swift in Sources */,
);
@ -6638,7 +6694,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 429;
CURRENT_PROJECT_VERSION = 435;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -6662,7 +6718,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.4.5;
MARKETING_VERSION = 2.5.0;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -6710,7 +6766,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 429;
CURRENT_PROJECT_VERSION = 435;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO;
@ -6739,7 +6795,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.4.5;
MARKETING_VERSION = 2.5.0;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -6775,7 +6831,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 429;
CURRENT_PROJECT_VERSION = 435;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -6798,7 +6854,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.4.5;
MARKETING_VERSION = 2.5.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@ -6849,7 +6905,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 429;
CURRENT_PROJECT_VERSION = 435;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = SUQ8J2PCT7;
ENABLE_NS_ASSERTIONS = NO;
@ -6877,7 +6933,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.4.5;
MARKETING_VERSION = 2.5.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@ -7809,7 +7865,7 @@
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 429;
CURRENT_PROJECT_VERSION = 435;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -7847,7 +7903,7 @@
"$(SRCROOT)",
);
LLVM_LTO = NO;
MARKETING_VERSION = 2.4.5;
MARKETING_VERSION = 2.5.0;
OTHER_LDFLAGS = "$(inherited)";
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
@ -7880,7 +7936,7 @@
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 429;
CURRENT_PROJECT_VERSION = 435;
DEVELOPMENT_TEAM = SUQ8J2PCT7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@ -7918,7 +7974,7 @@
"$(SRCROOT)",
);
LLVM_LTO = NO;
MARKETING_VERSION = 2.4.5;
MARKETING_VERSION = 2.5.0;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
PRODUCT_NAME = Session;

@ -221,19 +221,24 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
let webRTCSession: WebRTCSession = self.webRTCSession
let timestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs()
let disappearingMessagesConfiguration = try? thread.disappearingMessagesConfiguration.fetchOne(db)?.forcedWithDisappearAfterReadIfNeeded()
let message: CallMessage = CallMessage(
uuid: self.uuid,
kind: .preOffer,
sdps: [],
sentTimestampMs: UInt64(timestampMs)
)
.with(disappearingMessagesConfiguration)
let interaction: Interaction? = try? Interaction(
messageUuid: self.uuid,
threadId: sessionId,
authorId: getUserHexEncodedPublicKey(db),
variant: .infoCall,
body: String(data: messageInfoData, encoding: .utf8),
timestampMs: timestampMs
timestampMs: timestampMs,
expiresInSeconds: message.expiresInSeconds,
expiresStartedAtMs: message.expiresStartedAtMs
)
.inserted(db)

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import AVFAudio
import CallKit
import SessionUtilitiesKit
import SignalCoreKit

@ -2,6 +2,7 @@
import UIKit
import SessionUIKit
import CoreMedia
public protocol VideoPreviewDelegate: AnyObject {
func cameraDidConfirmTurningOn()

@ -3,11 +3,19 @@
import UIKit
import SessionMessagingKit
import SessionUtilitiesKit
import SessionUIKit
extension ContextMenuVC {
struct ExpirationInfo {
let expiresStartedAtMs: Double?
let expiresInSeconds: TimeInterval?
}
struct Action {
let icon: UIImage?
let title: String
let expirationInfo: ExpirationInfo?
let themeColor: ThemeValue
let isEmojiAction: Bool
let isEmojiPlus: Bool
let isDismissAction: Bool
@ -19,6 +27,8 @@ extension ContextMenuVC {
init(
icon: UIImage? = nil,
title: String = "",
expirationInfo: ExpirationInfo? = nil,
themeColor: ThemeValue = .textPrimary,
isEmojiAction: Bool = false,
isEmojiPlus: Bool = false,
isDismissAction: Bool = false,
@ -27,6 +37,8 @@ extension ContextMenuVC {
) {
self.icon = icon
self.title = title
self.expirationInfo = expirationInfo
self.themeColor = themeColor
self.isEmojiAction = isEmojiAction
self.isEmojiPlus = isEmojiPlus
self.isDismissAction = isDismissAction
@ -84,6 +96,11 @@ extension ContextMenuVC {
return Action(
icon: UIImage(named: "ic_trash"),
title: "TXT_DELETE_TITLE".localized(),
expirationInfo: ExpirationInfo(
expiresStartedAtMs: cellViewModel.expiresStartedAtMs,
expiresInSeconds: cellViewModel.expiresInSeconds
),
themeColor: .danger,
accessibilityLabel: "Delete message"
) { delegate?.delete(cellViewModel, using: dependencies) }
}
@ -100,6 +117,7 @@ extension ContextMenuVC {
return Action(
icon: UIImage(named: "ic_block"),
title: "context_menu_ban_user".localized(),
themeColor: .danger,
accessibilityLabel: "Ban user"
) { delegate?.ban(cellViewModel, using: dependencies) }
}
@ -108,6 +126,7 @@ extension ContextMenuVC {
return Action(
icon: UIImage(named: "ic_block"),
title: "context_menu_ban_and_delete_all".localized(),
themeColor: .danger,
accessibilityLabel: "Ban user and delete"
) { delegate?.banAndDeleteAllMessages(cellViewModel, using: dependencies) }
}

@ -3,6 +3,7 @@
import UIKit
import SessionUIKit
import SessionUtilitiesKit
import SessionSnodeKit
extension ContextMenuVC {
final class ActionView: UIView {
@ -12,26 +13,48 @@ extension ContextMenuVC {
private let action: Action
private let dismiss: () -> Void
private var didTouchDownInside: Bool = false
private var timer: Timer?
// MARK: - UI
private let iconImageView: UIImageView = {
private lazy var iconImageView: UIImageView = {
let result: UIImageView = UIImageView()
result.contentMode = .center
result.themeTintColor = .textPrimary
result.themeTintColor = action.themeColor
result.set(.width, to: ActionView.iconImageViewSize)
result.set(.height, to: ActionView.iconImageViewSize)
return result
}()
private let titleLabel: UILabel = {
private lazy var titleLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .systemFont(ofSize: Values.mediumFontSize)
result.themeTextColor = .textPrimary
result.themeTextColor = action.themeColor
return result
}()
private lazy var subtitleLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .systemFont(ofSize: Values.miniFontSize)
result.themeTextColor = action.themeColor
return result
}()
private lazy var labelContainer: UIView = {
let result: UIView = UIView()
result.addSubview(titleLabel)
result.addSubview(subtitleLabel)
titleLabel.pin([ UIView.HorizontalEdge.leading, UIView.HorizontalEdge.trailing, UIView.VerticalEdge.top ], to: result)
subtitleLabel.pin([ UIView.HorizontalEdge.leading, UIView.HorizontalEdge.trailing, UIView.VerticalEdge.bottom ], to: result)
titleLabel.pin(.bottom, to: .top, of: subtitleLabel)
return result
}()
private lazy var subtitleWidthConstraint = labelContainer.set(.width, greaterThanOrEqualTo: 115)
// MARK: - Lifecycle
@ -59,9 +82,10 @@ extension ContextMenuVC {
.resizedImage(to: CGSize(width: ActionView.iconSize, height: ActionView.iconSize))?
.withRenderingMode(.alwaysTemplate)
titleLabel.text = action.title
setUpSubtitle()
// Stack view
let stackView: UIStackView = UIStackView(arrangedSubviews: [ iconImageView, titleLabel ])
let stackView: UIStackView = UIStackView(arrangedSubviews: [ iconImageView, labelContainer ])
stackView.axis = .horizontal
stackView.spacing = Values.smallSpacing
stackView.alignment = .center
@ -82,11 +106,47 @@ extension ContextMenuVC {
addGestureRecognizer(tapGestureRecognizer)
}
private func setUpSubtitle() {
guard
let expiresInSeconds = self.action.expirationInfo?.expiresInSeconds,
let expiresStartedAtMs = self.action.expirationInfo?.expiresStartedAtMs
else {
subtitleLabel.isHidden = true
subtitleWidthConstraint.isActive = false
return
}
subtitleLabel.isHidden = false
subtitleWidthConstraint.isActive = true
// To prevent a negative timer
let timeToExpireInSeconds: TimeInterval = max(0, (expiresStartedAtMs + expiresInSeconds * 1000 - Double(SnodeAPI.currentOffsetTimestampMs())) / 1000)
subtitleLabel.text = String(format: "DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN".localized(), timeToExpireInSeconds.formatted(format: .twoUnits))
timer = Timer.scheduledTimerOnMainThread(withTimeInterval: 1, repeats: true, block: { [weak self] _ in
let timeToExpireInSeconds: TimeInterval = (expiresStartedAtMs + expiresInSeconds * 1000 - Double(SnodeAPI.currentOffsetTimestampMs())) / 1000
if timeToExpireInSeconds <= 0 {
self?.dismissWithTimerInvalidationIfNeeded()
} else {
self?.subtitleLabel.text = String(format: "DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN".localized(), timeToExpireInSeconds.formatted(format: .twoUnits))
}
})
}
override func removeFromSuperview() {
self.timer?.invalidate()
super.removeFromSuperview()
}
// MARK: - Interaction
private func dismissWithTimerInvalidationIfNeeded() {
self.timer?.invalidate()
dismiss()
}
@objc private func handleTap() {
action.work()
dismiss()
dismissWithTimerInvalidationIfNeeded()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

@ -24,16 +24,49 @@ extension ConversationVC:
AttachmentApprovalViewControllerDelegate,
GifPickerViewControllerDelegate
{
// MARK: - Open Settings
@objc func handleTitleViewTapped() {
// Don't take the user to settings for unapproved threads
guard viewModel.threadData.threadRequiresApproval == false else { return }
openSettings()
openSettingsFromTitleView()
}
@objc func openSettingsFromTitleView() {
switch self.titleView.currentLabelType {
case .userCount:
if self.viewModel.threadData.threadVariant == .group || self.viewModel.threadData.threadVariant == .legacyGroup {
let viewController = EditClosedGroupVC(
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant
)
navigationController?.pushViewController(viewController, animated: true)
} else {
openSettings()
}
break
case .none, .notificationSettings:
openSettings()
break
case .disappearingMessageSetting:
let viewController = SessionTableViewController(
viewModel: ThreadDisappearingMessagesSettingsViewModel(
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant,
currentUserIsClosedGroupMember: self.viewModel.threadData.currentUserIsClosedGroupMember,
currentUserIsClosedGroupAdmin: self.viewModel.threadData.currentUserIsClosedGroupAdmin,
config: self.viewModel.threadData.disappearingMessagesConfiguration!
)
)
navigationController?.pushViewController(viewController, animated: true)
break
}
}
@objc func openSettings() {
let viewController: SessionTableViewController = SessionTableViewController(
viewModel: ThreadSettingsViewModel(
let viewController = SessionTableViewController(viewModel: ThreadSettingsViewModel(
threadId: self.viewModel.threadData.threadId,
threadVariant: self.viewModel.threadData.threadVariant,
didTriggerSearch: { [weak self] in
@ -49,7 +82,6 @@ extension ConversationVC:
}
)
)
navigationController?.pushViewController(viewController, animated: true)
}
@ -864,6 +896,63 @@ extension ConversationVC:
return
}
// For disappearing messages config update, show the following settings modal
guard cellViewModel.variant != .infoDisappearingMessagesUpdate else {
let messageDisappearingConfig = cellViewModel.messageDisappearingConfiguration()
let expirationTimerString: String = floor(messageDisappearingConfig.durationSeconds).formatted(format: .long)
let expirationTypeString: String = (messageDisappearingConfig.type == .disappearAfterRead ? "DISAPPEARING_MESSAGE_STATE_READ".localized() : "DISAPPEARING_MESSAGE_STATE_SENT".localized())
let modalBodyString: String = (
messageDisappearingConfig.isEnabled ?
String(
format: "FOLLOW_SETTING_EXPLAINATION_TURNING_ON".localized(),
expirationTimerString,
expirationTypeString
) :
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF".localized()
)
let modalConfirmTitle: String = messageDisappearingConfig.isEnabled ? "DISAPPERING_MESSAGES_SAVE_TITLE".localized() : "CONFIRM_BUTTON_TITLE".localized()
let confirmationModal: ConfirmationModal = ConfirmationModal(
info: ConfirmationModal.Info(
title: "FOLLOW_SETTING_TITLE".localized(),
body: .attributedText(
NSAttributedString(string: modalBodyString)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.smallFontSize) ],
range: (modalBodyString as NSString).range(of: expirationTypeString)
)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.smallFontSize) ],
range: (modalBodyString as NSString).range(of: expirationTimerString)
)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.smallFontSize) ],
range: (modalBodyString as NSString).range(of: "DISAPPEARING_MESSAGES_OFF".localized().lowercased())
)
),
accessibility: Accessibility(identifier: "Follow setting dialog"),
confirmTitle: modalConfirmTitle,
confirmAccessibility: Accessibility(identifier: "Set button"),
confirmStyle: .danger,
cancelStyle: .textPrimary,
dismissOnConfirm: false // Custom dismissal logic
) { [weak self] _ in
dependencies.storage.writeAsync { db in
try messageDisappearingConfig.save(db)
try SessionUtil
.update(
db,
sessionId: cellViewModel.threadId,
disappearingMessagesConfig: messageDisappearingConfig
)
}
self?.dismiss(animated: true, completion: nil)
}
)
present(confirmationModal, animated: true, completion: nil)
return
}
// If it's an incoming media message and the thread isn't trusted then show the placeholder view
if cellViewModel.cellType != .textOnlyMessage && cellViewModel.variant == .standardIncoming && !cellViewModel.threadIsTrusted {
let message: String = String(
@ -2047,6 +2136,10 @@ extension ConversationVC:
cellViewModel.authorId
)
)
.with(
expiresInSeconds: cellViewModel.expiresInSeconds,
expiresStartedAtMs: cellViewModel.expiresStartedAtMs
)
// For incoming interactions or interactions with no serverHash just delete them locally
guard cellViewModel.variant == .standardOutgoing, let serverHash: String = serverHash else {
@ -2476,6 +2569,10 @@ extension ConversationVC:
message: DataExtractionNotification(
kind: kind,
sentTimestamp: UInt64(SnodeAPI.currentOffsetTimestampMs())
)
.with(DisappearingMessagesConfiguration
.fetchOne(db, id: threadId)?
.forcedWithDisappearAfterReadIfNeeded()
),
interactionId: nil,
threadId: threadId,

@ -122,6 +122,7 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
var scrollButtonMessageRequestsBottomConstraint: NSLayoutConstraint?
var messageRequestsViewBotomConstraint: NSLayoutConstraint?
var messageRequestDescriptionLabelBottomConstraint: NSLayoutConstraint?
var emptyStateLabelTopConstraint: NSLayoutConstraint?
lazy var titleView: ConversationTitleView = {
let result: ConversationTitleView = ConversationTitleView()
@ -191,13 +192,42 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
return result
}()
lazy var stateStackView: UIStackView = {
let result: UIStackView = UIStackView(arrangedSubviews: [ outdatedClientBanner, emptyStateLabelContainer ])
result.axis = .vertical
result.spacing = Values.smallSpacing
result.alignment = .fill
return result
}()
lazy var outdatedClientBanner: InfoBanner = {
let info: InfoBanner.Info = InfoBanner.Info(
message: String(format: "DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER".localized(), self.viewModel.threadData.displayName),
backgroundColor: .primary,
messageFont: .systemFont(ofSize: Values.verySmallFontSize),
messageTintColor: .messageBubble_outgoingText,
messageLabelAccessibilityLabel: "Outdated client banner text",
height: 40
)
let result: InfoBanner = InfoBanner(info: info, dismiss: self.removeOutdatedClientBanner)
result.accessibilityLabel = "Outdated client banner"
result.isAccessibilityElement = true
return result
}()
lazy var blockedBanner: InfoBanner = {
let result: InfoBanner = InfoBanner(
let info: InfoBanner.Info = InfoBanner.Info(
message: self.viewModel.blockedBannerMessage,
backgroundColor: .danger,
messageLabelAccessibilityLabel: "Blocked banner text"
messageFont: .boldSystemFont(ofSize: Values.smallFontSize),
messageTintColor: .textPrimary,
messageLabelAccessibilityLabel: "Blocked banner text",
height: 54
)
let result: InfoBanner = InfoBanner(info: info)
result.accessibilityLabel = "Blocked banner"
result.isAccessibilityElement = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(unblock))
@ -206,9 +236,20 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
return result
}()
private lazy var emptyStateLabelContainer: UIView = {
let result: UIView = UIView()
result.addSubview(emptyStateLabel)
emptyStateLabel.pin(.leading, to: .leading, of: result, withInset: Values.largeSpacing)
emptyStateLabel.pin(.trailing, to: .trailing, of: result, withInset: -Values.largeSpacing)
return result
}()
private lazy var emptyStateLabel: UILabel = {
let text: String = emptyStateText(for: viewModel.threadData)
let result: UILabel = UILabel()
result.isAccessibilityElement = true
result.accessibilityIdentifier = "Empty state label"
result.accessibilityLabel = "Empty state label"
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .systemFont(ofSize: Values.verySmallFontSize)
@ -408,13 +449,14 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
// Message requests view & scroll to bottom
view.addSubview(scrollButton)
view.addSubview(emptyStateLabel)
view.addSubview(stateStackView)
view.addSubview(messageRequestBackgroundView)
view.addSubview(messageRequestStackView)
emptyStateLabel.pin(.top, to: .top, of: view, withInset: Values.largeSpacing)
emptyStateLabel.pin(.leading, to: .leading, of: view, withInset: Values.veryLargeSpacing)
emptyStateLabel.pin(.trailing, to: .trailing, of: view, withInset: -Values.veryLargeSpacing)
stateStackView.pin(.top, to: .top, of: view, withInset: 0)
stateStackView.pin(.leading, to: .leading, of: view, withInset: 0)
stateStackView.pin(.trailing, to: .trailing, of: view, withInset: 0)
self.emptyStateLabelTopConstraint = emptyStateLabel.pin(.top, to: .top, of: emptyStateLabelContainer, withInset: Values.largeSpacing)
messageRequestStackView.addArrangedSubview(messageRequestBlockButton)
messageRequestStackView.addArrangedSubview(messageRequestDescriptionContainerView)
@ -741,7 +783,8 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
viewModel.threadData.threadIsNoteToSelf != updatedThreadData.threadIsNoteToSelf ||
viewModel.threadData.threadMutedUntilTimestamp != updatedThreadData.threadMutedUntilTimestamp ||
viewModel.threadData.threadOnlyNotifyForMentions != updatedThreadData.threadOnlyNotifyForMentions ||
viewModel.threadData.userCount != updatedThreadData.userCount
viewModel.threadData.userCount != updatedThreadData.userCount ||
viewModel.threadData.disappearingMessagesConfiguration != updatedThreadData.disappearingMessagesConfiguration
{
titleView.update(
with: updatedThreadData.displayName,
@ -749,7 +792,8 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
threadVariant: updatedThreadData.threadVariant,
mutedUntilTimestamp: updatedThreadData.threadMutedUntilTimestamp,
onlyNotifyForMentions: (updatedThreadData.threadOnlyNotifyForMentions == true),
userCount: updatedThreadData.userCount
userCount: updatedThreadData.userCount,
disappearingMessagesConfig: updatedThreadData.disappearingMessagesConfiguration
)
// Update the empty state
@ -826,6 +870,17 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
}
}
if
initialLoad ||
viewModel.threadData.outdatedMemberId != updatedThreadData.outdatedMemberId ||
viewModel.threadData.disappearingMessagesConfiguration != updatedThreadData.disappearingMessagesConfiguration
{
addOrRemoveOutdatedClientBanner(
outdatedMemberId: updatedThreadData.outdatedMemberId,
disappearingMessagesConfiguration: updatedThreadData.disappearingMessagesConfiguration
)
}
if initialLoad || viewModel.threadData.threadIsBlocked != updatedThreadData.threadIsBlocked {
addOrRemoveBlockedBanner(threadIsBlocked: (updatedThreadData.threadIsBlocked == true))
}
@ -1227,7 +1282,6 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
else {
self.scrollToBottom(isAnimated: false)
}
self.updateScrollToBottom()
self.hasPerformedInitialScroll = true
@ -1472,6 +1526,57 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
}
// MARK: - General
func addOrRemoveOutdatedClientBanner(
outdatedMemberId: String?,
disappearingMessagesConfiguration: DisappearingMessagesConfiguration?
) {
let currentDisappearingMessagesConfiguration: DisappearingMessagesConfiguration? = disappearingMessagesConfiguration ?? self.viewModel.threadData.disappearingMessagesConfiguration
// Do not show the banner until the new disappearing messages is enabled
guard
Features.useNewDisappearingMessagesConfig &&
currentDisappearingMessagesConfiguration?.isEnabled == true
else {
self.outdatedClientBanner.isHidden = true
self.emptyStateLabelTopConstraint?.constant = Values.largeSpacing
return
}
guard let outdatedMemberId: String = outdatedMemberId else {
UIView.animate(
withDuration: 0.25,
animations: { [weak self] in
self?.outdatedClientBanner.alpha = 0
},
completion: { [weak self] _ in
self?.outdatedClientBanner.isHidden = true
self?.outdatedClientBanner.alpha = 1
self?.emptyStateLabelTopConstraint?.constant = Values.largeSpacing
}
)
return
}
self.outdatedClientBanner.update(
message: String(
format: "DISAPPEARING_MESSAGES_OUTDATED_CLIENT_BANNER".localized(),
Profile.displayName(id: outdatedMemberId, threadVariant: self.viewModel.threadData.threadVariant)
),
dismiss: self.removeOutdatedClientBanner
)
self.outdatedClientBanner.isHidden = false
self.emptyStateLabelTopConstraint?.constant = 0
}
private func removeOutdatedClientBanner() {
guard let outdatedMemberId: String = self.viewModel.threadData.outdatedMemberId else { return }
Storage.shared.writeAsync { db in
try Contact
.filter(id: outdatedMemberId)
.updateAll(db, Contact.Columns.lastKnownClientVersion.set(to: nil))
}
}
func addOrRemoveBlockedBanner(threadIsBlocked: Bool) {
guard threadIsBlocked else {

@ -326,6 +326,16 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
return SQL("LEFT JOIN \(RecipientState.self) ON \(recipientState[.interactionId]) = \(interaction[.id])")
}()
),
PagedData.ObservedChanges(
table: DisappearingMessagesConfiguration.self,
columns: [ .isEnabled, .type, .durationSeconds ],
joinToPagedType: {
let interaction: TypedTableAlias<Interaction> = TypedTableAlias()
let disappearingMessagesConfiguration: TypedTableAlias<DisappearingMessagesConfiguration> = TypedTableAlias()
return SQL("LEFT JOIN \(DisappearingMessagesConfiguration.self) ON \(disappearingMessagesConfiguration[.threadId]) = \(interaction[.threadId])")
}()
),
],
filterSQL: MessageViewModel.filterSQL(threadId: threadId),
groupSQL: MessageViewModel.groupSQL,
@ -528,12 +538,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
].compactMap { $0 },
body: text
),
expiresInSeconds: threadData.disappearingMessagesConfiguration
.map { disappearingConfig in
guard disappearingConfig.isEnabled else { return nil }
return disappearingConfig.durationSeconds
},
expiresInSeconds: threadData.disappearingMessagesConfiguration?.durationSeconds,
expiresStartedAtMs: (threadData.disappearingMessagesConfiguration?.type == .disappearAfterSend ? Double(sentTimestampMs) : nil),
linkPreviewUrl: linkPreviewDraft?.urlString
)
let optimisticAttachments: Attachment.PreparedData? = attachments
@ -550,7 +556,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
optimisticMessageId: optimisticMessageId,
threadId: threadData.threadId,
threadVariant: threadData.threadVariant,
threadHasDisappearingMessagesEnabled: (threadData.disappearingMessagesConfiguration?.isEnabled ?? false),
threadExpirationType: threadData.disappearingMessagesConfiguration?.type,
threadExpirationTimer: threadData.disappearingMessagesConfiguration?.durationSeconds,
threadOpenGroupServer: threadData.openGroupServer,
threadOpenGroupPublicKey: threadData.openGroupPublicKey,
threadContactNameInternal: threadData.threadContactName(),

@ -7,6 +7,7 @@ import SessionUtilitiesKit
final class CallMessageCell: MessageCell {
private static let iconSize: CGFloat = 16
private static let timerViewSize: CGFloat = 12
private static let inset = Values.mediumSpacing
private static let margin = UIScreen.main.bounds.width * 0.1
@ -16,7 +17,7 @@ final class CallMessageCell: MessageCell {
// MARK: - UI
private lazy var topConstraint: NSLayoutConstraint = container.pin(.top, to: .top, of: self, withInset: CallMessageCell.inset)
private lazy var topConstraint: NSLayoutConstraint = mainStackView.pin(.top, to: .top, of: self, withInset: CallMessageCell.inset)
private lazy var iconImageViewWidthConstraint: NSLayoutConstraint = iconImageView.set(.width, to: 0)
private lazy var iconImageViewHeightConstraint: NSLayoutConstraint = iconImageView.set(.height, to: 0)
private lazy var infoImageViewWidthConstraint: NSLayoutConstraint = infoImageView.set(.width, to: 0)
@ -33,6 +34,16 @@ final class CallMessageCell: MessageCell {
return result
}()
private lazy var timerView: DisappearingMessageTimerView = DisappearingMessageTimerView()
private lazy var timerViewContainer: UIView = {
let result: UIView = UIView()
result.addSubview(timerView)
result.set(.height, to: Self.timerViewSize)
timerView.center(in: result)
return result
}()
private lazy var label: UILabel = {
let result: UILabel = UILabel()
result.font = .boldSystemFont(ofSize: Values.smallFontSize)
@ -76,6 +87,15 @@ final class CallMessageCell: MessageCell {
return result
}()
private lazy var mainStackView: UIStackView = {
let result: UIStackView = UIStackView(arrangedSubviews: [ timerViewContainer, container ])
result.axis = .vertical
result.spacing = Values.smallSpacing
result.alignment = .fill
return result
}()
// MARK: - Lifecycle
override func setUpViewHierarchy() {
@ -83,12 +103,12 @@ final class CallMessageCell: MessageCell {
iconImageViewWidthConstraint.isActive = true
iconImageViewHeightConstraint.isActive = true
addSubview(container)
addSubview(mainStackView)
topConstraint.isActive = true
container.pin(.left, to: .left, of: self, withInset: CallMessageCell.margin)
container.pin(.right, to: .right, of: self, withInset: -CallMessageCell.margin)
container.pin(.bottom, to: .bottom, of: self, withInset: -CallMessageCell.inset)
mainStackView.pin(.left, to: .left, of: self, withInset: CallMessageCell.margin)
mainStackView.pin(.right, to: .right, of: self, withInset: -CallMessageCell.margin)
mainStackView.pin(.bottom, to: .bottom, of: self, withInset: -CallMessageCell.inset)
}
override func setUpGestureRecognizers() {
@ -147,6 +167,24 @@ final class CallMessageCell: MessageCell {
infoImageViewHeightConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0)
label.text = cellViewModel.body
// Timer
if
let expiresStartedAtMs: Double = cellViewModel.expiresStartedAtMs,
let expiresInSeconds: TimeInterval = cellViewModel.expiresInSeconds
{
let expirationTimestampMs: Double = (expiresStartedAtMs + (expiresInSeconds * 1000))
timerView.configure(
expirationTimestampMs: expirationTimestampMs,
initialDurationSeconds: expiresInSeconds
)
timerView.themeTintColor = .textSecondary
timerViewContainer.isHidden = false
}
else {
timerViewContainer.isHidden = true
}
}
override func dynamicUpdate(with cellViewModel: MessageViewModel, playbackInfo: ConversationViewModel.PlaybackInfo?) {

@ -0,0 +1,80 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SessionSnodeKit
class DisappearingMessageTimerView: UIView {
private var initialDurationSeconds: Double = 0
private var expirationTimestampMs: Double = 0
// MARK: - Animation
private var animationTimer: Timer?
private var progress: Int = 12 // 0 == about to expire, 12 == just started countdown.
// MARK: - UI
private var iconImageView = UIImageView()
// MARK: - Lifecycle
init() {
super.init(frame: CGRect.zero)
self.addSubview(iconImageView)
iconImageView.pin(to: self, withInset: 1)
}
override init(frame: CGRect) {
preconditionFailure("Use init(viewItem:textColor:) instead.")
}
required init?(coder: NSCoder) {
preconditionFailure("Use init(viewItem:textColor:) instead.")
}
public func configure(expirationTimestampMs: Double, initialDurationSeconds: Double) {
self.expirationTimestampMs = expirationTimestampMs
self.initialDurationSeconds = initialDurationSeconds
self.updateProgress()
self.startAnimation()
}
@objc private func updateProgress() {
guard self.expirationTimestampMs > 0 else {
self.progress = 12
return
}
let timestampMs: Double = Double(SnodeAPI.currentOffsetTimestampMs())
let secondsLeft: Double = max((self.expirationTimestampMs - timestampMs) / 1000, 0)
let progressRatio: Double = self.initialDurationSeconds > 0 ? secondsLeft / self.initialDurationSeconds : 0
self.progress = Int(round(min(progressRatio, 1) * 12))
self.updateIcon()
}
private func updateIcon() {
let imageName: String = "disappearing_message_\(String(format: "%02d", 5 * self.progress))"
self.iconImageView.image = UIImage(named: imageName)?.withRenderingMode(.alwaysTemplate)
}
private func startAnimation() {
self.clearAnimation()
self.animationTimer = Timer.weakScheduledTimer(
withTimeInterval: 0.1,
target: self,
selector: #selector(updateProgress),
userInfo: nil,
repeats: true
)
}
private func clearAnimation() {
self.animationTimer?.invalidate()
self.animationTimer = nil
}
public func prepareForReuse() {
self.clearAnimation()
}
}

@ -5,7 +5,7 @@ import SessionUIKit
import SessionMessagingKit
final class InfoMessageCell: MessageCell {
private static let iconSize: CGFloat = 16
private static let iconSize: CGFloat = 12
public static let inset = Values.mediumSpacing
private var isHandlingLongPress: Bool = false
@ -14,24 +14,47 @@ final class InfoMessageCell: MessageCell {
// MARK: - UI
private lazy var iconImageViewWidthConstraint = iconImageView.set(.width, to: InfoMessageCell.iconSize)
private lazy var iconImageViewHeightConstraint = iconImageView.set(.height, to: InfoMessageCell.iconSize)
private lazy var iconContainerViewWidthConstraint = iconContainerView.set(.width, to: InfoMessageCell.iconSize)
private lazy var iconContainerViewHeightConstraint = iconContainerView.set(.height, to: InfoMessageCell.iconSize)
private lazy var iconImageView: UIImageView = UIImageView()
private lazy var timerView: DisappearingMessageTimerView = DisappearingMessageTimerView()
private lazy var iconContainerView: UIView = {
let result: UIView = UIView()
result.addSubview(iconImageView)
result.addSubview(timerView)
iconImageView.pin(to: result)
timerView.pin(to: result)
return result
}()
private lazy var label: UILabel = {
let result: UILabel = UILabel()
result.font = .boldSystemFont(ofSize: Values.verySmallFontSize)
result.themeTextColor = .textPrimary
result.font = .systemFont(ofSize: Values.verySmallFontSize)
result.themeTextColor = .textSecondary
result.textAlignment = .center
result.lineBreakMode = .byWordWrapping
result.numberOfLines = 0
return result
}()
private lazy var actionLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .systemFont(ofSize: Values.verySmallFontSize)
result.themeTextColor = .primary
result.textAlignment = .center
result.numberOfLines = 1
result.isAccessibilityElement = true
result.accessibilityIdentifier = "Follow setting"
return result
}()
private lazy var stackView: UIStackView = {
let result: UIStackView = UIStackView(arrangedSubviews: [ iconImageView, label ])
let result: UIStackView = UIStackView(arrangedSubviews: [ iconContainerView, label, actionLabel ])
result.axis = .vertical
result.alignment = .center
result.spacing = Values.smallSpacing
@ -44,19 +67,23 @@ final class InfoMessageCell: MessageCell {
override func setUpViewHierarchy() {
super.setUpViewHierarchy()
iconImageViewWidthConstraint.isActive = true
iconImageViewHeightConstraint.isActive = true
iconContainerViewWidthConstraint.isActive = true
iconContainerViewHeightConstraint.isActive = true
addSubview(stackView)
stackView.pin(.left, to: .left, of: self, withInset: InfoMessageCell.inset)
stackView.pin(.left, to: .left, of: self, withInset: Values.massiveSpacing)
stackView.pin(.top, to: .top, of: self, withInset: InfoMessageCell.inset)
stackView.pin(.right, to: .right, of: self, withInset: -InfoMessageCell.inset)
stackView.pin(.right, to: .right, of: self, withInset: -Values.massiveSpacing)
stackView.pin(.bottom, to: .bottom, of: self, withInset: -InfoMessageCell.inset)
}
override func setUpGestureRecognizers() {
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
addGestureRecognizer(longPressRecognizer)
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapGestureRecognizer.numberOfTapsRequired = 1
addGestureRecognizer(tapGestureRecognizer)
}
// MARK: - Updating
@ -74,13 +101,13 @@ final class InfoMessageCell: MessageCell {
self.isAccessibilityElement = true
self.viewModel = cellViewModel
self.actionLabel.isHidden = true
self.actionLabel.text = nil
let icon: UIImage? = {
switch cellViewModel.variant {
case .infoDisappearingMessagesUpdate:
return (cellViewModel.threadHasDisappearingMessagesEnabled ?
UIImage(named: "ic_timer") :
UIImage(named: "ic_timer_disabled")
)
return UIImage(systemName: "timer")
case .infoMediaSavedNotification: return UIImage(named: "ic_download")
@ -90,14 +117,67 @@ final class InfoMessageCell: MessageCell {
if let icon = icon {
iconImageView.image = icon.withRenderingMode(.alwaysTemplate)
iconImageView.themeTintColor = .textPrimary
iconImageView.themeTintColor = .textSecondary
}
iconImageViewWidthConstraint.constant = (icon != nil) ? InfoMessageCell.iconSize : 0
iconImageViewHeightConstraint.constant = (icon != nil) ? InfoMessageCell.iconSize : 0
if cellViewModel.variant == .infoDisappearingMessagesUpdate, let body: String = cellViewModel.body {
self.label.attributedText = NSAttributedString(string: body)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize) ],
range: (body as NSString).range(of: cellViewModel.authorName)
)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize) ],
range: (body as NSString).range(of: "vc_path_device_row_title".localized())
)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize) ],
range: (body as NSString).range(of: floor(cellViewModel.threadExpirationTimer ?? 0).formatted(format: .long))
)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize) ],
range: (body as NSString).range(of: (cellViewModel.threadExpirationType == .disappearAfterRead ? "DISAPPEARING_MESSAGE_STATE_READ".localized() : "DISAPPEARING_MESSAGE_STATE_SENT".localized()))
)
.adding(
attributes: [ .font: UIFont.boldSystemFont(ofSize: Values.verySmallFontSize) ],
range: (body as NSString).range(of: "DISAPPEARING_MESSAGES_OFF".localized().lowercased())
)
if cellViewModel.canDoFollowingSetting() {
self.actionLabel.isHidden = false
self.actionLabel.text = "FOLLOW_SETTING_TITLE".localized()
}
} else {
self.label.text = cellViewModel.body
}
self.label.themeTextColor = (cellViewModel.variant == .infoClosedGroupCurrentUserErrorLeaving) ? .danger : .textSecondary
let shouldShowIcon: Bool = (icon != nil) || ((cellViewModel.expiresInSeconds ?? 0) > 0)
iconContainerViewWidthConstraint.constant = shouldShowIcon ? InfoMessageCell.iconSize : 0
iconContainerViewHeightConstraint.constant = shouldShowIcon ? InfoMessageCell.iconSize : 0
self.label.text = cellViewModel.body
self.label.themeTextColor = (cellViewModel.variant == .infoClosedGroupCurrentUserErrorLeaving) ? .danger : .textPrimary
guard shouldShowIcon else { return }
// Timer
if
let expiresStartedAtMs: Double = cellViewModel.expiresStartedAtMs,
let expiresInSeconds: TimeInterval = cellViewModel.expiresInSeconds
{
let expirationTimestampMs: Double = (expiresStartedAtMs + (expiresInSeconds * 1000))
timerView.configure(
expirationTimestampMs: expirationTimestampMs,
initialDurationSeconds: expiresInSeconds
)
timerView.themeTintColor = .textSecondary
timerView.isHidden = false
iconImageView.isHidden = true
}
else {
timerView.isHidden = true
iconImageView.isHidden = false
}
}
override func dynamicUpdate(with cellViewModel: MessageViewModel, playbackInfo: ConversationViewModel.PlaybackInfo?) {
@ -105,7 +185,7 @@ final class InfoMessageCell: MessageCell {
// MARK: - Interaction
@objc func handleLongPress(_ gestureRecognizer: UITapGestureRecognizer) {
@objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
if [ .ended, .cancelled, .failed ].contains(gestureRecognizer.state) {
isHandlingLongPress = false
return
@ -115,4 +195,12 @@ final class InfoMessageCell: MessageCell {
delegate?.handleItemLongPressed(cellViewModel)
isHandlingLongPress = true
}
@objc func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
guard let cellViewModel: MessageViewModel = self.viewModel else { return }
if cellViewModel.variant == .infoDisappearingMessagesUpdate && cellViewModel.canDoFollowingSetting() {
delegate?.handleItemTapped(cellViewModel, cell: self, cellLocation: gestureRecognizer.location(in: self))
}
}
}

@ -21,7 +21,7 @@ final class UnreadMarkerCell: MessageCell {
private lazy var titleLabel: UILabel = {
let result = UILabel()
result.font = .boldSystemFont(ofSize: Values.smallFontSize)
result.font = .boldSystemFont(ofSize: Values.verySmallFontSize)
result.text = "UNREAD_MESSAGES".localized()
result.themeTextColor = .unreadMarker
result.textAlignment = .center

@ -39,8 +39,10 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
private lazy var underBubbleStackViewOutgoingTrailingConstraint: NSLayoutConstraint = underBubbleStackView.pin(.trailing, to: .trailing, of: snContentView)
private lazy var underBubbleStackViewNoHeightConstraint: NSLayoutConstraint = underBubbleStackView.set(.height, to: 0)
private lazy var timerViewOutgoingMessageConstraint = timerView.pin(.leading, to: .leading, of: self, withInset: VisibleMessageCell.contactThreadHSpacing)
private lazy var timerViewIncomingMessageConstraint = timerView.pin(.trailing, to: .trailing, of: self, withInset: -VisibleMessageCell.contactThreadHSpacing)
private lazy var timerViewOutgoingMessageConstraint = timerView.pin(.trailing, to: .trailing, of: messageStatusContainerView)
private lazy var timerViewIncomingMessageConstraint = timerView.pin(.leading, to: .leading, of: messageStatusContainerView)
private lazy var messageStatusLabelOutgoingMessageConstraint = messageStatusLabel.pin(.trailing, to: .leading, of: timerView, withInset: -2)
private lazy var messageStatusLabelIncomingMessageConstraint = messageStatusLabel.pin(.leading, to: .trailing, of: timerView, withInset: 2)
private lazy var panGestureRecognizer: UIPanGestureRecognizer = {
let result = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
@ -121,7 +123,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
return result
}()
private lazy var timerView: OWSMessageTimerView = OWSMessageTimerView()
private lazy var timerView: DisappearingMessageTimerView = DisappearingMessageTimerView()
lazy var underBubbleStackView: UIStackView = {
let result = UIStackView(arrangedSubviews: [])
@ -218,11 +220,6 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
bubbleBackgroundView.addSubview(bubbleView)
bubbleView.pin(to: bubbleBackgroundView)
// Timer view
addSubview(timerView)
timerView.center(.vertical, in: snContentView)
timerViewOutgoingMessageConstraint.isActive = true
// Reply button
addSubview(replyButton)
replyButton.addSubview(replyIconImageView)
@ -245,6 +242,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
messageStatusContainerView.addSubview(messageStatusLabel)
messageStatusContainerView.addSubview(messageStatusImageView)
messageStatusContainerView.addSubview(timerView)
reactionContainerView.widthAnchor
.constraint(lessThanOrEqualTo: underBubbleStackView.widthAnchor)
@ -254,9 +252,11 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
messageStatusImageView.pin(.trailing, to: .trailing, of: messageStatusContainerView)
messageStatusImageView.set(.width, to: VisibleMessageCell.messageStatusImageViewSize)
messageStatusImageView.set(.height, to: VisibleMessageCell.messageStatusImageViewSize)
timerView.pin(.top, to: .top, of: messageStatusContainerView)
timerView.pin(.bottom, to: .bottom, of: messageStatusContainerView)
timerView.set(.width, to: VisibleMessageCell.messageStatusImageViewSize)
timerView.set(.height, to: VisibleMessageCell.messageStatusImageViewSize)
messageStatusLabel.center(.vertical, in: messageStatusContainerView)
messageStatusLabel.pin(.leading, to: .leading, of: messageStatusContainerView)
messageStatusLabel.pin(.trailing, to: .leading, of: messageStatusImageView, withInset: -2)
messageStatusLabelPaddingView.pin(.leading, to: .leading, of: messageStatusContainerView)
messageStatusLabelPaddingView.pin(.trailing, to: .trailing, of: messageStatusContainerView)
}
@ -362,31 +362,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
let authorLabelAvailableSpace = CGSize(width: authorLabelAvailableWidth, height: .greatestFiniteMagnitude)
let authorLabelSize = authorLabel.sizeThatFits(authorLabelAvailableSpace)
authorLabelHeightConstraint.constant = (cellViewModel.senderName != nil ? authorLabelSize.height : 0)
// Timer
if
let expiresStartedAtMs: Double = cellViewModel.expiresStartedAtMs,
let expiresInSeconds: TimeInterval = cellViewModel.expiresInSeconds
{
let expirationTimestampMs: Double = (expiresStartedAtMs + (expiresInSeconds * 1000))
timerView.configure(
withExpirationTimestamp: UInt64(floor(expirationTimestampMs)),
initialDurationSeconds: UInt32(floor(expiresInSeconds))
)
timerView.themeTintColor = .textPrimary
timerView.isHidden = false
}
else {
timerView.isHidden = true
}
timerViewOutgoingMessageConstraint.isActive = (cellViewModel.variant == .standardOutgoing)
timerViewIncomingMessageConstraint.isActive = (
cellViewModel.variant == .standardIncoming ||
cellViewModel.variant == .standardIncomingDeleted
)
// Swipe to reply
if ContextMenuVC.viewModelCanReply(cellViewModel) {
addGestureRecognizer(panGestureRecognizer)
@ -427,11 +403,13 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
messageStatusLabel.accessibilityIdentifier = "Message sent status: \(statusText ?? "invalid")"
messageStatusImageView.themeTintColor = tintColor
messageStatusContainerView.isHidden = (
cellViewModel.variant != .standardOutgoing ||
cellViewModel.variant == .infoCall ||
(
cellViewModel.state == .sent &&
!cellViewModel.isLastOutgoing
(cellViewModel.expiresInSeconds ?? 0) == 0 && (
cellViewModel.variant != .standardOutgoing ||
cellViewModel.variant == .infoCall ||
(
cellViewModel.state == .sent &&
!cellViewModel.isLastOutgoing
)
)
)
messageStatusLabelPaddingView.isHidden = (
@ -439,6 +417,37 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
cellViewModel.isLast
)
// Timer
if
let expiresStartedAtMs: Double = cellViewModel.expiresStartedAtMs,
let expiresInSeconds: TimeInterval = cellViewModel.expiresInSeconds
{
let expirationTimestampMs: Double = (expiresStartedAtMs + (expiresInSeconds * 1000))
timerView.configure(
expirationTimestampMs: expirationTimestampMs,
initialDurationSeconds: expiresInSeconds
)
timerView.themeTintColor = tintColor
timerView.isHidden = false
messageStatusImageView.isHidden = true
}
else {
timerView.isHidden = true
messageStatusImageView.isHidden = false
}
timerViewOutgoingMessageConstraint.isActive = (cellViewModel.variant == .standardOutgoing)
timerViewIncomingMessageConstraint.isActive = (
cellViewModel.variant == .standardIncoming ||
cellViewModel.variant == .standardIncomingDeleted
)
messageStatusLabelOutgoingMessageConstraint.isActive = (cellViewModel.variant == .standardOutgoing)
messageStatusLabelIncomingMessageConstraint.isActive = (
cellViewModel.variant == .standardIncoming ||
cellViewModel.variant == .standardIncomingDeleted
)
// Set the height of the underBubbleStackView to 0 if it has no content (need to do this
// otherwise it can randomly stretch)
underBubbleStackViewNoHeightConstraint.isActive = underBubbleStackView.arrangedSubviews
@ -528,6 +537,9 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
textColor: bodyLabelTextColor,
isOutgoing: (cellViewModel.variant == .standardOutgoing)
)
openGroupInvitationView.isAccessibilityElement = true
openGroupInvitationView.accessibilityIdentifier = "Community invitation"
openGroupInvitationView.accessibilityLabel = cellViewModel.linkPreview?.title
bubbleView.addSubview(openGroupInvitationView)
bubbleView.pin(to: openGroupInvitationView)
snContentView.addArrangedSubview(bubbleBackgroundView)

@ -1,26 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface OWSMessageTimerView : UIView
@property (nonatomic) UIImageView *imageView;
- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
- (void)configureWithExpirationTimestamp:(uint64_t)expirationTimestamp
initialDurationSeconds:(uint32_t)initialDurationSeconds;
- (void)prepareForReuse;
+ (CGSize)measureSize;
@end
NS_ASSUME_NONNULL_END

@ -1,192 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSMessageTimerView.h"
#import "OWSMath.h"
#import "UIView+OWS.h"
#import <QuartzCore/QuartzCore.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <PureLayout/PureLayout.h>
#import <SignalCoreKit/NSDate+OWS.h>
#import <SessionUtilitiesKit/NSTimer+Proxying.h>
#import <SessionSnodeKit/SessionSnodeKit.h>
NS_ASSUME_NONNULL_BEGIN
const CGFloat kDisappearingMessageIconSize = 12.f;
@interface OWSMessageTimerView ()
@property (nonatomic) uint32_t initialDurationSeconds;
@property (nonatomic) uint64_t expirationTimestamp;
@property (nonatomic, nullable) NSTimer *animationTimer;
// 0 == about to expire, 12 == just started countdown.
@property (nonatomic) NSInteger progress12;
@end
#pragma mark -
@implementation OWSMessageTimerView
- (void)dealloc
{
[self clearAnimation];
}
- (instancetype)init
{
self = [super initWithFrame:CGRectZero];
if (!self) {
return self;
}
[self commonInit];
return self;
}
- (void)commonInit
{
self.imageView = [UIImageView new];
[self addSubview:self.imageView];
[self.imageView ows_autoPinToSuperviewEdges];
[self.imageView autoSetDimension:ALDimensionWidth toSize:kDisappearingMessageIconSize];
[self.imageView autoSetDimension:ALDimensionHeight toSize:kDisappearingMessageIconSize];
}
- (void)configureWithExpirationTimestamp:(uint64_t)expirationTimestamp
initialDurationSeconds:(uint32_t)initialDurationSeconds
{
self.expirationTimestamp = expirationTimestamp;
self.initialDurationSeconds = initialDurationSeconds;
[self updateProgress12];
[self updateIcon];
[self startAnimation];
}
- (void)updateProgress12
{
BOOL hasStartedCountdown = self.expirationTimestamp > 0;
if (!hasStartedCountdown) {
self.progress12 = 12;
return;
}
uint64_t nowTimestamp = [SNSnodeAPI currentOffsetTimestampMs];
CGFloat secondsLeft
= (self.expirationTimestamp > nowTimestamp ? (self.expirationTimestamp - nowTimestamp) / 1000.f : 0.f);
CGFloat progress = 0.f;
if (self.initialDurationSeconds > 0) {
progress = CGFloatClamp(secondsLeft / self.initialDurationSeconds, 0.f, 1.f);
}
OWSAssertDebug(progress >= 0.f);
OWSAssertDebug(progress <= 1.f);
self.progress12 = (NSInteger)round(CGFloatClamp(progress, 0.f, 1.f) * 12);
}
- (void)setProgress12:(NSInteger)progress12
{
if (_progress12 == progress12) {
return;
}
_progress12 = progress12;
[self updateIcon];
}
- (void)updateIcon
{
self.imageView.image = [[self progressIcon] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
}
- (UIImage *)progressIcon
{
OWSAssertDebug(self.progress12 >= 0);
OWSAssertDebug(self.progress12 <= 12);
UIImage *_Nullable image;
switch (self.progress12) {
default:
case 0:
image = [UIImage imageNamed:@"disappearing_message_00"];
break;
case 1:
image = [UIImage imageNamed:@"disappearing_message_05"];
break;
case 2:
image = [UIImage imageNamed:@"disappearing_message_10"];
break;
case 3:
image = [UIImage imageNamed:@"disappearing_message_15"];
break;
case 4:
image = [UIImage imageNamed:@"disappearing_message_20"];
break;
case 5:
image = [UIImage imageNamed:@"disappearing_message_25"];
break;
case 6:
image = [UIImage imageNamed:@"disappearing_message_30"];
break;
case 7:
image = [UIImage imageNamed:@"disappearing_message_35"];
break;
case 8:
image = [UIImage imageNamed:@"disappearing_message_40"];
break;
case 9:
image = [UIImage imageNamed:@"disappearing_message_45"];
break;
case 10:
image = [UIImage imageNamed:@"disappearing_message_50"];
break;
case 11:
image = [UIImage imageNamed:@"disappearing_message_55"];
break;
case 12:
image = [UIImage imageNamed:@"disappearing_message_60"];
break;
}
OWSAssertDebug(image);
OWSAssertDebug(image.size.width == kDisappearingMessageIconSize);
OWSAssertDebug(image.size.height == kDisappearingMessageIconSize);
return image;
}
- (void)startAnimation
{
[self clearAnimation];
self.animationTimer = [NSTimer weakScheduledTimerWithTimeInterval:0.1f
target:self
selector:@selector(updateProgress12)
userInfo:nil
repeats:YES];
}
- (void)clearAnimation
{
[self.animationTimer invalidate];
self.animationTimer = nil;
}
- (void)prepareForReuse
{
[self clearAnimation];
}
+ (CGSize)measureSize
{
return CGSizeMake(kDisappearingMessageIconSize, kDisappearingMessageIconSize);
}
@end
NS_ASSUME_NONNULL_END

@ -19,171 +19,508 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga
private let threadId: String
private let threadVariant: SessionThread.Variant
private var isNoteToSelf: Bool
private let currentUserIsClosedGroupMember: Bool?
private let currentUserIsClosedGroupAdmin: Bool?
private let config: DisappearingMessagesConfiguration
private var storedSelection: TimeInterval
private var currentSelection: CurrentValueSubject<TimeInterval, Never>
private var currentSelection: CurrentValueSubject<DisappearingMessagesConfiguration, Error>
private var shouldShowConfirmButton: CurrentValueSubject<Bool, Never>
// MARK: - Initialization
init(
threadId: String,
threadVariant: SessionThread.Variant,
currentUserIsClosedGroupMember: Bool?,
currentUserIsClosedGroupAdmin: Bool?,
config: DisappearingMessagesConfiguration,
using dependencies: Dependencies = Dependencies()
) {
self.dependencies = dependencies
self.threadId = threadId
self.threadVariant = threadVariant
self.isNoteToSelf = (threadId == getUserHexEncodedPublicKey(using: dependencies))
self.currentUserIsClosedGroupMember = currentUserIsClosedGroupMember
self.currentUserIsClosedGroupAdmin = currentUserIsClosedGroupAdmin
self.config = config
self.storedSelection = (config.isEnabled ? config.durationSeconds : 0)
self.currentSelection = CurrentValueSubject(self.storedSelection)
self.currentSelection = CurrentValueSubject(config)
self.shouldShowConfirmButton = CurrentValueSubject(false)
}
// MARK: - Config
enum NavItem: Equatable {
case cancel
case save
}
public enum Section: SessionTableSection {
case content
case type
case timerLegacy
case timerDisappearAfterSend
case timerDisappearAfterRead
case noteToSelf
case group
var title: String? {
switch self {
case .type: return "DISAPPERING_MESSAGES_TYPE_TITLE".localized()
// We need to keep these although the titles of them are the same
// because we need them to trigger timer section to refresh when
// the user selects different disappearing messages type
case .timerLegacy, .timerDisappearAfterSend, .timerDisappearAfterRead: return "DISAPPERING_MESSAGES_TIMER_TITLE".localized()
case .noteToSelf: return nil
case .group: return nil
}
}
var style: SessionTableSectionStyle { return .titleRoundedContent }
var footer: String? {
switch self {
case .group: return "DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY".localized()
default: return nil
}
}
}
// MARK: - Navigation
// MARK: - Content
lazy var leftNavItems: AnyPublisher<[SessionNavItem<NavItem>], Never> = [
SessionNavItem(
id: .cancel,
systemItem: .cancel,
accessibilityIdentifier: "Cancel button"
) { [weak self] in self?.dismissScreen() }
]
lazy var rightNavItems: AnyPublisher<[SessionNavItem<NavItem>], Never> = currentSelection
let title: String = "DISAPPEARING_MESSAGES".localized()
lazy var subtitle: String? = {
guard Features.useNewDisappearingMessagesConfig else {
return (isNoteToSelf ? nil : "DISAPPERING_MESSAGES_SUBTITLE_LEGACY".localized())
}
if threadVariant == .contact && !isNoteToSelf {
return "DISAPPERING_MESSAGES_SUBTITLE_CONTACTS".localized()
}
return "DISAPPERING_MESSAGES_SUBTITLE_GROUPS".localized()
}()
lazy var footerButtonInfo: AnyPublisher<SessionButton.Info?, Never> = shouldShowConfirmButton
.removeDuplicates()
.map { [weak self] currentSelection in (self?.storedSelection != currentSelection) }
.map { [weak self, dependencies] isChanged in
guard isChanged else { return [] }
.map { [weak self] shouldShowConfirmButton in
guard shouldShowConfirmButton else { return nil }
return [
SessionNavItem(
id: .save,
systemItem: .save,
accessibilityIdentifier: "Save button"
) {
self?.saveChanges(using: dependencies)
return SessionButton.Info(
style: .bordered,
title: "DISAPPERING_MESSAGES_SAVE_TITLE".localized(),
isEnabled: true,
accessibility: Accessibility(
identifier: "Set button",
label: "Set button"
),
minWidth: 110,
onTap: {
self?.saveChanges()
self?.dismissScreen()
}
]
)
}
.eraseToAnyPublisher()
// MARK: - Content
let title: String = "DISAPPEARING_MESSAGES".localized()
.eraseToAnyPublisher()
lazy var observation: TargetObservation = ObservationBuilder
.databaseObservation(self) { [dependencies, threadId = self.threadId] db -> SessionThreadViewModel? in
let userPublicKey: String = getUserHexEncodedPublicKey(db, using: dependencies)
return try SessionThreadViewModel
.conversationSettingsQuery(threadId: threadId, userPublicKey: userPublicKey)
.fetchOne(db)
}
.map { [weak self, config, dependencies, threadId = self.threadId] maybeThreadViewModel -> [SectionModel] in
return [
SectionModel(
model: .content,
elements: [
SessionCell.Info(
id: "DISAPPEARING_MESSAGES_OFF".localized(),
title: "DISAPPEARING_MESSAGES_OFF".localized(),
rightAccessory: .radio(
isSelected: { (self?.currentSelection.value == 0) }
),
isEnabled: (
(
maybeThreadViewModel?.threadVariant != .legacyGroup &&
maybeThreadViewModel?.threadVariant != .group
) ||
maybeThreadViewModel?.currentUserIsClosedGroupMember == true
),
onTap: { self?.currentSelection.send(0) }
)
].appending(
contentsOf: DisappearingMessagesConfiguration.validDurationsSeconds
.map { duration in
let title: String = duration.formatted(format: .long)
return SessionCell.Info(
id: title,
title: title,
.subject(currentSelection)
.map { [weak self, threadVariant, isNoteToSelf, config, currentUserIsClosedGroupMember, currentUserIsClosedGroupAdmin] currentSelection -> [SectionModel] in
switch (threadVariant, isNoteToSelf) {
case (.contact, false):
return [
SectionModel(
model: .type,
elements: [
SessionCell.Info(
id: "DISAPPEARING_MESSAGES_OFF".localized(),
title: "DISAPPEARING_MESSAGES_OFF".localized(),
rightAccessory: .radio(
isSelected: { (self?.currentSelection.value == duration) }
isSelected: { (self?.currentSelection.value.isEnabled == false) }
),
accessibility: Accessibility(
identifier: "Disable disappearing messages (Off option)",
label: "Disable disappearing messages (Off option)"
),
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = currentSelection
.with(
isEnabled: false,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.off.seconds
)
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
),
(Features.useNewDisappearingMessagesConfig ? nil :
SessionCell.Info(
id: "DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE".localized(),
title: "DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE".localized(),
subtitle: "DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION".localized(),
rightAccessory: .radio(
isSelected: {
(self?.currentSelection.value.isEnabled == true) &&
!Features.useNewDisappearingMessagesConfig
}
),
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = {
if (config.isEnabled == true && config.type == .disappearAfterRead) {
return config
}
return currentSelection
.with(
isEnabled: true,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.legacy.seconds,
type: .disappearAfterRead // Default for 1-1
)
}()
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
)
),
SessionCell.Info(
id: "DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE".localized(),
title: "DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE".localized(),
subtitle: "DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION".localized(),
rightAccessory: .radio(
isSelected: {
(self?.currentSelection.value.isEnabled == true) &&
(self?.currentSelection.value.type == .disappearAfterRead) &&
Features.useNewDisappearingMessagesConfig
}
),
styling: SessionCell.StyleInfo(
tintColor: (Features.useNewDisappearingMessagesConfig ?
.textPrimary :
.disabled
)
),
isEnabled: Features.useNewDisappearingMessagesConfig,
accessibility: Accessibility(
identifier: "Disappear after read option",
label: "Disappear after read option"
),
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = {
if (config.isEnabled == true && config.type == .disappearAfterRead) {
return config
}
return currentSelection
.with(
isEnabled: true,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.disappearAfterRead.seconds,
type: .disappearAfterRead
)
}()
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
),
SessionCell.Info(
id: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
title: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
subtitle: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION".localized(),
rightAccessory: .radio(
isSelected: {
(self?.currentSelection.value.isEnabled == true) &&
(self?.currentSelection.value.type == .disappearAfterSend) &&
Features.useNewDisappearingMessagesConfig
}
),
styling: SessionCell.StyleInfo(
tintColor: (Features.useNewDisappearingMessagesConfig ?
.textPrimary :
.disabled
)
),
isEnabled: (
(
maybeThreadViewModel?.threadVariant != .legacyGroup &&
maybeThreadViewModel?.threadVariant != .group
) ||
maybeThreadViewModel?.currentUserIsClosedGroupMember == true
isEnabled: Features.useNewDisappearingMessagesConfig,
accessibility: Accessibility(
identifier: "Disappear after send option",
label: "Disappear after send option"
),
onTap: { self?.currentSelection.send(duration) }
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = {
if (config.isEnabled == true && config.type == .disappearAfterSend) {
return config
}
return currentSelection
.with(
isEnabled: true,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.disappearAfterSend.seconds,
type: .disappearAfterSend
)
}()
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
)
}
)
)
]
].compactMap { $0 }
),
(currentSelection.isEnabled == false ? nil :
SectionModel(
model: {
guard Features.useNewDisappearingMessagesConfig else { return .timerLegacy }
return currentSelection.type == .disappearAfterSend ?
.timerDisappearAfterSend :
.timerDisappearAfterRead
}(),
elements: DisappearingMessagesConfiguration
.validDurationsSeconds({
guard Features.useNewDisappearingMessagesConfig else { return .disappearAfterSend }
return currentSelection.type ?? .disappearAfterSend
}())
.map { duration in
let title: String = duration.formatted(format: .long)
return SessionCell.Info(
id: title,
title: title,
rightAccessory: .radio(
isSelected: {
(self?.currentSelection.value.isEnabled == true) &&
(self?.currentSelection.value.durationSeconds == duration)
}
),
accessibility: Accessibility(
identifier: "Time option",
label: "Time option"
),
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = currentSelection
.with(
durationSeconds: duration
)
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
)
}
)
)
].compactMap { $0 }
case (.legacyGroup, _), (.group, _), (_, true):
return [
(Features.useNewDisappearingMessagesConfig ? nil :
SectionModel(
model: .type,
elements: [
SessionCell.Info(
id: "DISAPPEARING_MESSAGES_OFF".localized(),
title: "DISAPPEARING_MESSAGES_OFF".localized(),
rightAccessory: .radio(
isSelected: { (self?.currentSelection.value.isEnabled == false) }
),
isEnabled: (
isNoteToSelf ||
currentUserIsClosedGroupMember == true
),
accessibility: Accessibility(
identifier: "Disable disappearing messages (Off option)",
label: "Disable disappearing messages (Off option)"
),
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = currentSelection
.with(
isEnabled: false,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.off.seconds
)
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
),
SessionCell.Info(
id: "DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE".localized(),
title: "DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE".localized(),
subtitle: "DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION".localized(),
rightAccessory: .radio(
isSelected: {
(self?.currentSelection.value.isEnabled == true) &&
!Features.useNewDisappearingMessagesConfig
}
),
isEnabled: (
isNoteToSelf ||
currentUserIsClosedGroupMember == true
),
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = {
if (config.isEnabled == true && config.type == .disappearAfterSend) {
return config
}
return currentSelection
.with(
isEnabled: true,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.legacy.seconds,
type: .disappearAfterSend // Default for closed group & note to self
)
}()
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
),
SessionCell.Info(
id: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
title: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE".localized(),
subtitle: "DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION".localized(),
rightAccessory: .radio(isSelected: { false }),
styling: SessionCell.StyleInfo(tintColor: .disabled),
isEnabled: false
)
]
)
),
(!Features.useNewDisappearingMessagesConfig && currentSelection.isEnabled == false ? nil :
SectionModel(
model: {
guard Features.useNewDisappearingMessagesConfig else {
return (currentSelection.type == .disappearAfterSend ?
.timerDisappearAfterSend :
.timerDisappearAfterRead
)
}
return (isNoteToSelf ? .noteToSelf : .group)
}(),
elements: [
(!Features.useNewDisappearingMessagesConfig ? nil :
SessionCell.Info(
id: "DISAPPEARING_MESSAGES_OFF".localized(),
title: "DISAPPEARING_MESSAGES_OFF".localized(),
rightAccessory: .radio(
isSelected: { (self?.currentSelection.value.isEnabled == false) }
),
isEnabled: (
isNoteToSelf ||
currentUserIsClosedGroupAdmin == true
),
accessibility: Accessibility(
identifier: "Disable disappearing messages (Off option)",
label: "Disable disappearing messages (Off option)"
),
onTap: {
let updatedConfig: DisappearingMessagesConfiguration = currentSelection
.with(
isEnabled: false,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.off.seconds
)
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
)
)
]
.compactMap { $0 }
.appending(
contentsOf: DisappearingMessagesConfiguration
.validDurationsSeconds(.disappearAfterSend)
.map { duration in
let title: String = duration.formatted(format: .long)
return SessionCell.Info(
id: title,
title: title,
rightAccessory: .radio(
isSelected: {
(self?.currentSelection.value.isEnabled == true) &&
(self?.currentSelection.value.durationSeconds == duration)
}
),
isEnabled: (
isNoteToSelf ||
(currentUserIsClosedGroupMember == true && !Features.useNewDisappearingMessagesConfig) ||
currentUserIsClosedGroupAdmin == true
),
accessibility: Accessibility(
identifier: "Time option",
label: "Time option"
),
onTap: {
// If the new disappearing messages config feature flag isn't
// enabled then the 'isEnabled' and 'type' values are set via
// the first section so pass `nil` values to keep the existing
// setting
let updatedConfig: DisappearingMessagesConfiguration = currentSelection
.with(
isEnabled: (Features.useNewDisappearingMessagesConfig ?
true :
nil
),
durationSeconds: duration,
type: (Features.useNewDisappearingMessagesConfig ?
.disappearAfterSend :
nil
)
)
self?.shouldShowConfirmButton.send(updatedConfig != config)
self?.currentSelection.send(updatedConfig)
}
)
}
)
)
)
].compactMap { $0 }
case (.community, _):
return [] // Should not happen
}
}
// MARK: - Functions
private func saveChanges(using dependencies: Dependencies = Dependencies()) {
let threadId: String = self.threadId
let threadVariant: SessionThread.Variant = self.threadVariant
let currentSelection: TimeInterval = self.currentSelection.value
let updatedConfig: DisappearingMessagesConfiguration = self.config
.with(
isEnabled: (currentSelection != 0),
durationSeconds: currentSelection
)
private func saveChanges() {
let updatedConfig: DisappearingMessagesConfiguration = self.currentSelection.value
guard self.config != updatedConfig else { return }
dependencies.storage.writeAsync { db in
let config: DisappearingMessagesConfiguration = try DisappearingMessagesConfiguration
.fetchOne(db, id: threadId)
.defaulting(to: DisappearingMessagesConfiguration.defaultWith(threadId))
.with(
isEnabled: (currentSelection != 0),
durationSeconds: currentSelection
)
dependencies.storage.writeAsync(using: dependencies) { [threadId, threadVariant, dependencies] db in
let userPublicKey: String = getUserHexEncodedPublicKey(db, using: dependencies)
let currentTimestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs()
let interactionId = try updatedConfig
.saved(db)
.insertControlMessage(
db,
threadVariant: threadVariant,
authorId: userPublicKey,
timestampMs: currentTimestampMs,
serverHash: nil,
serverExpirationTimestamp: nil
)
let duration: UInt32? = {
guard !Features.useNewDisappearingMessagesConfig else { return nil }
return UInt32(floor(updatedConfig.isEnabled ? updatedConfig.durationSeconds : 0))
}()
let interaction: Interaction = try Interaction(
threadId: threadId,
authorId: getUserHexEncodedPublicKey(db),
variant: .infoDisappearingMessagesUpdate,
body: config.messageInfoString(with: nil),
timestampMs: SnodeAPI.currentOffsetTimestampMs()
let expirationTimerUpdateMessage: ExpirationTimerUpdate = ExpirationTimerUpdate(
syncTarget: nil,
duration: duration
)
.inserted(db)
.with(sentTimestamp: UInt64(currentTimestampMs))
.with(updatedConfig)
try MessageSender.send(
db,
message: ExpirationTimerUpdate(
syncTarget: nil,
duration: UInt32(floor(updatedConfig.isEnabled ? updatedConfig.durationSeconds : 0))
),
interactionId: interaction.id,
message: expirationTimerUpdateMessage,
interactionId: interactionId,
threadId: threadId,
threadVariant: threadVariant,
using: dependencies
)
// Legacy closed groups
}
// Contacts & legacy closed groups need to update the SessionUtil
dependencies.storage.writeAsync(using: dependencies) { [threadId, threadVariant] db in
switch threadVariant {
case .contact:
try SessionUtil
.update(
db,
sessionId: threadId,
disappearingMessagesConfig: updatedConfig
)
case .legacyGroup:
try SessionUtil
.update(

@ -444,27 +444,32 @@ class ThreadSettingsViewModel: SessionTableViewModel, NavigationItemSource, Navi
SessionCell.Info(
id: .disappearingMessages,
leftAccessory: .icon(
UIImage(
named: (current.disappearingMessagesConfig.isEnabled ?
"ic_timer" :
"ic_timer_disabled"
)
)?.withRenderingMode(.alwaysTemplate),
accessibility: Accessibility(
label: "Timer icon"
)
UIImage(systemName: "timer")?
.withRenderingMode(.alwaysTemplate)
),
title: "DISAPPEARING_MESSAGES".localized(),
subtitle: (current.disappearingMessagesConfig.isEnabled ?
String(
format: "DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER".localized(),
arguments: [current.disappearingMessagesConfig.durationString]
) :
"DISAPPEARING_MESSAGES_SUBTITLE_OFF".localized()
),
subtitle: {
guard current.disappearingMessagesConfig.isEnabled else {
return "DISAPPEARING_MESSAGES_SUBTITLE_OFF".localized()
}
guard Features.useNewDisappearingMessagesConfig else {
return String(
format: "DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_LEGACY".localized(),
current.disappearingMessagesConfig.durationString
)
}
return String(
format: (current.disappearingMessagesConfig.type == .disappearAfterRead ?
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_READ".localized() :
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_SEND".localized()
),
current.disappearingMessagesConfig.durationString
)
}(),
accessibility: Accessibility(
identifier: "\(ThreadSettingsViewModel.self).disappearing_messages",
label: "Disappearing messages"
identifier: "Disappearing messages",
label: "\(ThreadSettingsViewModel.self).disappearing_messages"
),
onTap: { [weak self] in
self?.transitionToScreen(
@ -472,6 +477,8 @@ class ThreadSettingsViewModel: SessionTableViewModel, NavigationItemSource, Navi
viewModel: ThreadDisappearingMessagesSettingsViewModel(
threadId: threadViewModel.threadId,
threadVariant: threadViewModel.threadVariant,
currentUserIsClosedGroupMember: threadViewModel.currentUserIsClosedGroupMember,
currentUserIsClosedGroupAdmin: threadViewModel.currentUserIsClosedGroupAdmin,
config: current.disappearingMessagesConfig
)
)
@ -801,6 +808,18 @@ class ThreadSettingsViewModel: SessionTableViewModel, NavigationItemSource, Navi
threadVariant: thread.variant,
using: dependencies
)
// Trigger disappear after read
dependencies.jobRunner.upsert(
db,
job: DisappearingMessagesJob.updateNextRunIfNeeded(
db,
interaction: interaction,
startedAtMs: TimeInterval(SnodeAPI.currentOffsetTimestampMs())
),
canStartJob: true,
using: dependencies
)
}
}
}

@ -14,6 +14,12 @@ final class ConversationTitleView: UIView {
override var intrinsicContentSize: CGSize {
return UIView.layoutFittingExpandedSize
}
private lazy var labelCarouselViewWidth = labelCarouselView.set(.width, to: 185)
public var currentLabelType: SessionLabelCarouselView.LabelType? {
return self.labelCarouselView.currentLabelType
}
// MARK: - UI Components
@ -22,7 +28,8 @@ final class ConversationTitleView: UIView {
private lazy var titleLabel: UILabel = {
let result: UILabel = UILabel()
result.accessibilityIdentifier = "Username"
result.accessibilityIdentifier = "Conversation header name"
result.accessibilityLabel = "Conversation header name"
result.isAccessibilityElement = true
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
result.themeTextColor = .textPrimary
@ -30,18 +37,14 @@ final class ConversationTitleView: UIView {
return result
}()
private lazy var subtitleLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .systemFont(ofSize: 13)
result.themeTextColor = .textPrimary
result.lineBreakMode = .byTruncatingTail
private lazy var labelCarouselView: SessionLabelCarouselView = {
let result = SessionLabelCarouselView()
return result
}()
private lazy var stackView: UIStackView = {
let result = UIStackView(arrangedSubviews: [ titleLabel, subtitleLabel ])
let result = UIStackView(arrangedSubviews: [ titleLabel, labelCarouselView ])
result.axis = .vertical
result.alignment = .center
@ -81,7 +84,8 @@ final class ConversationTitleView: UIView {
threadVariant: threadVariant,
mutedUntilTimestamp: nil,
onlyNotifyForMentions: false,
userCount: (threadVariant != .contact ? 0 : nil)
userCount: (threadVariant != .contact ? 0 : nil),
disappearingMessagesConfig: nil
)
}
@ -106,7 +110,8 @@ final class ConversationTitleView: UIView {
threadVariant: SessionThread.Variant,
mutedUntilTimestamp: TimeInterval?,
onlyNotifyForMentions: Bool,
userCount: Int?
userCount: Int?,
disappearingMessagesConfig: DisappearingMessagesConfiguration?
) {
guard Thread.isMainThread else {
DispatchQueue.main.async { [weak self] in
@ -116,7 +121,8 @@ final class ConversationTitleView: UIView {
threadVariant: threadVariant,
mutedUntilTimestamp: mutedUntilTimestamp,
onlyNotifyForMentions: onlyNotifyForMentions,
userCount: userCount
userCount: userCount,
disappearingMessagesConfig: disappearingMessagesConfig
)
}
return
@ -125,62 +131,146 @@ final class ConversationTitleView: UIView {
let shouldHaveSubtitle: Bool = (
Date().timeIntervalSince1970 <= (mutedUntilTimestamp ?? 0) ||
onlyNotifyForMentions ||
userCount != nil
userCount != nil ||
disappearingMessagesConfig?.isEnabled == true
)
self.titleLabel.text = name
self.titleLabel.accessibilityLabel = name
self.titleLabel.font = .boldSystemFont(
ofSize: (shouldHaveSubtitle ?
Values.mediumFontSize :
Values.largeFontSize :
Values.veryLargeFontSize
)
)
ThemeManager.onThemeChange(observer: self.subtitleLabel) { [weak subtitleLabel] theme, _ in
ThemeManager.onThemeChange(observer: self.labelCarouselView) { [weak self] theme, _ in
guard let textPrimary: UIColor = theme.color(for: .textPrimary) else { return }
guard Date().timeIntervalSince1970 > (mutedUntilTimestamp ?? 0) else {
subtitleLabel?.attributedText = NSAttributedString(
var labelInfos: [SessionLabelCarouselView.LabelInfo] = []
if Date().timeIntervalSince1970 <= (mutedUntilTimestamp ?? 0) {
let notificationSettingsLabelString = NSAttributedString(
string: FullConversationCell.mutePrefix,
attributes: [
.font: UIFont(name: "ElegantIcons", size: 10) as Any,
.font: UIFont(name: "ElegantIcons", size: 8) as Any,
.foregroundColor: textPrimary
]
)
.appending(string: "Muted")
return
labelInfos.append(
SessionLabelCarouselView.LabelInfo(
attributedText: notificationSettingsLabelString,
accessibility: nil, // TODO: Add accessibility
type: .notificationSettings
)
)
}
guard !onlyNotifyForMentions else {
else if onlyNotifyForMentions {
let imageAttachment = NSTextAttachment()
imageAttachment.image = UIImage(named: "NotifyMentions.png")?.withTint(textPrimary)
imageAttachment.bounds = CGRect(
x: 0,
y: -2,
width: Values.smallFontSize,
height: Values.smallFontSize
width: Values.miniFontSize,
height: Values.miniFontSize
)
subtitleLabel?.attributedText = NSAttributedString(attachment: imageAttachment)
let notificationSettingsLabelString = NSAttributedString(attachment: imageAttachment)
.appending(string: " ")
.appending(string: "view_conversation_title_notify_for_mentions_only".localized())
return
labelInfos.append(
SessionLabelCarouselView.LabelInfo(
attributedText: notificationSettingsLabelString,
accessibility: nil, // TODO: Add accessibility
type: .notificationSettings
)
)
}
guard let userCount: Int = userCount else { return }
switch threadVariant {
case .contact: break
case .legacyGroup, .group:
subtitleLabel?.attributedText = NSAttributedString(
string: "\(userCount) member\(userCount == 1 ? "" : "s")"
)
if let userCount: Int = userCount {
switch threadVariant {
case .contact: break
case .legacyGroup, .group:
labelInfos.append(
SessionLabelCarouselView.LabelInfo(
attributedText: NSAttributedString(
string: "\(userCount) member\(userCount == 1 ? "" : "s")"
),
accessibility: nil, // TODO: Add accessibility
type: .userCount
)
)
case .community:
labelInfos.append(
SessionLabelCarouselView.LabelInfo(
attributedText: NSAttributedString(
string: "\(userCount) active member\(userCount == 1 ? "" : "s")"
),
accessibility: nil, // TODO: Add accessibility
type: .userCount
)
)
}
}
if let config = disappearingMessagesConfig, config.isEnabled == true {
let imageAttachment = NSTextAttachment()
imageAttachment.image = UIImage(systemName: "timer")?.withTint(textPrimary)
imageAttachment.bounds = CGRect(
x: 0,
y: -2,
width: Values.miniFontSize,
height: Values.miniFontSize
)
let disappearingMessageSettingLabelString: NSAttributedString = {
guard Features.useNewDisappearingMessagesConfig else {
return NSAttributedString(attachment: imageAttachment)
.appending(string: " ")
.appending(string: String(
format: "DISAPPERING_MESSAGES_SUMMARY_LEGACY".localized(),
floor(config.durationSeconds).formatted(format: .short)
))
}
case .community:
subtitleLabel?.attributedText = NSAttributedString(
string: "\(userCount) active member\(userCount == 1 ? "" : "s")"
return NSAttributedString(attachment: imageAttachment)
.appending(string: " ")
.appending(string: String(
format: (config.type == .disappearAfterRead ?
"DISAPPERING_MESSAGES_SUMMARY_READ".localized() :
"DISAPPERING_MESSAGES_SUMMARY_SEND".localized()
),
floor(config.durationSeconds).formatted(format: .short)
))
}()
labelInfos.append(
SessionLabelCarouselView.LabelInfo(
attributedText: disappearingMessageSettingLabelString,
accessibility: Accessibility(
identifier: "Disappearing messages type and time",
label: "Disappearing messages type and time"
),
type: .disappearingMessageSetting
)
)
}
self?.labelCarouselView.update(
with: labelInfos,
labelSize: CGSize(
width: self?.labelCarouselViewWidth.constant ?? 0,
height: 12
),
shouldAutoScroll: false
)
self?.labelCarouselView.isHidden = (labelInfos.count == 0)
}
// Contact threads also have the call button to compensate for
@ -195,4 +285,13 @@ final class ConversationTitleView: UIView {
)
self.stackViewTrailingConstraint.constant = 0
}
// MARK: - Interaction
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.stackView.frame.contains(point) {
return self.labelCarouselView.scrollView
}
return super.hitTest(point, with: event)
}
}

@ -4,10 +4,82 @@ import UIKit
import SessionUIKit
final class InfoBanner: UIView {
init(message: String, backgroundColor: ThemeValue, messageLabelAccessibilityLabel: String? = nil) {
public struct Info: Equatable, Hashable {
let message: String
let backgroundColor: ThemeValue
let messageFont: UIFont
let messageTintColor: ThemeValue
let messageLabelAccessibilityLabel: String?
let height: CGFloat
func with(
message: String? = nil,
backgroundColor: ThemeValue? = nil,
messageFont: UIFont? = nil,
messageTintColor: ThemeValue? = nil,
messageLabelAccessibilityLabel: String? = nil,
height: CGFloat? = nil
) -> Info {
return Info(
message: message ?? self.message,
backgroundColor: backgroundColor ?? self.backgroundColor,
messageFont: messageFont ?? self.messageFont,
messageTintColor: messageTintColor ?? self.messageTintColor,
messageLabelAccessibilityLabel: messageLabelAccessibilityLabel ?? self.messageLabelAccessibilityLabel,
height: height ?? self.height
)
}
}
private lazy var label: UILabel = {
let result: UILabel = UILabel()
result.textAlignment = .center
result.lineBreakMode = .byWordWrapping
result.numberOfLines = 0
result.isAccessibilityElement = true
return result
}()
private lazy var closeButton: UIButton = {
let result: UIButton = UIButton()
result.translatesAutoresizingMaskIntoConstraints = false
result.setImage(
UIImage(systemName: "xmark", withConfiguration: UIImage.SymbolConfiguration(pointSize: 12, weight: .bold))?
.withRenderingMode(.alwaysTemplate),
for: .normal
)
result.contentMode = .center
result.addTarget(self, action: #selector(dismissBanner), for: .touchUpInside)
return result
}()
public var info: Info?
public var dismiss: (() -> Void)?
// MARK: - Initialization
init(info: Info, dismiss: (() -> Void)? = nil) {
super.init(frame: CGRect.zero)
setUpViewHierarchy(message: message, backgroundColor: backgroundColor, messageLabelAccessibilityLabel: messageLabelAccessibilityLabel)
addSubview(label)
label.pin(.top, to: .top, of: self)
label.pin(.bottom, to: .bottom, of: self)
label.pin(.leading, to: .leading, of: self, withInset: Values.veryLargeSpacing)
label.pin(.trailing, to: .trailing, of: self, withInset: -Values.veryLargeSpacing)
addSubview(closeButton)
let buttonSize: CGFloat = (12 + (Values.smallSpacing * 2))
closeButton.center(.vertical, in: self)
closeButton.pin(.trailing, to: .trailing, of: self, withInset: -Values.smallSpacing)
closeButton.set(.width, to: buttonSize)
closeButton.set(.height, to: buttonSize)
self.set(.height, to: info.height)
self.update(info, dismiss: dismiss)
}
override init(frame: CGRect) {
@ -18,19 +90,47 @@ final class InfoBanner: UIView {
preconditionFailure("Use init(coder:) instead.")
}
private func setUpViewHierarchy(message: String, backgroundColor: ThemeValue, messageLabelAccessibilityLabel: String?) {
themeBackgroundColor = backgroundColor
let label: UILabel = UILabel()
label.accessibilityLabel = messageLabelAccessibilityLabel
label.font = .boldSystemFont(ofSize: Values.smallFontSize)
label.text = message
label.themeTextColor = .textPrimary
label.textAlignment = .center
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
addSubview(label)
// MARK: Update
private func update(_ info: InfoBanner.Info, dismiss: (() -> Void)?) {
self.info = info
self.dismiss = dismiss
themeBackgroundColor = info.backgroundColor
label.font = info.messageFont
label.text = info.message
label.themeTextColor = info.messageTintColor
label.accessibilityLabel = info.messageLabelAccessibilityLabel
label.pin(to: self, withInset: Values.mediumSpacing)
closeButton.themeTintColor = info.messageTintColor
closeButton.isHidden = (dismiss == nil)
}
public func update(
message: String? = nil,
backgroundColor: ThemeValue? = nil,
messageFont: UIFont? = nil,
messageTintColor: ThemeValue? = nil,
messageLabelAccessibilityLabel: String? = nil,
height: CGFloat? = nil,
dismiss: (() -> Void)? = nil
) {
if let updatedInfo = self.info?.with(
message: message,
backgroundColor: backgroundColor,
messageFont: messageFont,
messageTintColor: messageTintColor,
messageLabelAccessibilityLabel: messageLabelAccessibilityLabel,
height: height
) {
self.update(updatedInfo, dismiss: dismiss)
}
}
// MARK: - Actions
@objc private func dismissBanner() {
self.dismiss?()
}
}

@ -0,0 +1,239 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SessionUIKit
final class SessionLabelCarouselView: UIView, UIScrollViewDelegate {
private static let autoScrollingTimeInterval: TimeInterval = 10
private var labelInfos: [LabelInfo] = []
private var labelSize: CGSize = .zero
private var shouldAutoScroll: Bool = false
private var timer: Timer?
private lazy var contentWidth = stackView.set(.width, to: 0)
private lazy var contentHeight = stackView.set(.height, to: 0)
private var shouldScroll: Bool = false {
didSet {
arrowLeft.isHidden = !shouldScroll
arrowRight.isHidden = !shouldScroll
pageControl.isHidden = !shouldScroll
}
}
public struct LabelInfo {
let attributedText: NSAttributedString
let accessibility: Accessibility?
let type: LabelType
}
// MARK: - Types
public enum LabelType {
case notificationSettings
case userCount
case disappearingMessageSetting
}
public var currentLabelType: LabelType? {
let index = pageControl.currentPage + (shouldScroll ? 1 : 0)
return self.labelInfos[safe: index]?.type
}
// MARK: - UI Components
public lazy var scrollView: UIScrollView = {
let result = UIScrollView(frame: .zero)
result.isPagingEnabled = true
result.showsVerticalScrollIndicator = false
result.showsHorizontalScrollIndicator = false
result.delegate = self
return result
}()
private lazy var stackView: UIStackView = {
let result = UIStackView()
result.axis = .horizontal
return result
}()
private lazy var pageControl: UIPageControl = {
let result = UIPageControl(frame: .zero)
result.themeCurrentPageIndicatorTintColor = .textPrimary
result.themePageIndicatorTintColor = .textSecondary
result.themeTintColor = .textPrimary
result.currentPage = 0
result.set(.height, to: 5)
result.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
return result
}()
private lazy var arrowLeft: UIImageView = {
let result = UIImageView(image: UIImage(systemName: "chevron.left")?.withRenderingMode(.alwaysTemplate))
result.themeTintColor = .textPrimary
result.set(.height, to: 10)
result.set(.width, to: 5)
return result
}()
private lazy var arrowRight: UIImageView = {
let result = UIImageView(image: UIImage(systemName: "chevron.right")?.withRenderingMode(.alwaysTemplate))
result.themeTintColor = .textPrimary
result.set(.height, to: 10)
result.set(.width, to: 5)
return result
}()
// MARK: - Initialization
init(labelInfos: [LabelInfo] = [], labelSize: CGSize = .zero, shouldAutoScroll: Bool = false) {
super.init(frame: .zero)
setUpViewHierarchy()
self.update(with: labelInfos, labelSize: labelSize, shouldAutoScroll: shouldAutoScroll)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Content
public func update(with labelInfos: [LabelInfo], labelSize: CGSize = .zero, shouldAutoScroll: Bool = false) {
self.labelInfos = labelInfos
self.labelSize = labelSize
self.shouldAutoScroll = shouldAutoScroll
self.shouldScroll = labelInfos.count > 1
if self.shouldScroll {
let first: LabelInfo = labelInfos.first!
let last: LabelInfo = labelInfos.last!
self.labelInfos.append(first)
self.labelInfos.insert(last, at: 0)
}
pageControl.numberOfPages = labelInfos.count
pageControl.currentPage = 0
let contentSize = CGSize(width: labelSize.width * CGFloat(self.labelInfos.count), height: labelSize.height)
scrollView.contentSize = contentSize
contentWidth.constant = contentSize.width
contentHeight.constant = contentSize.height
self.scrollView.setContentOffset(
CGPoint(
x: Int(self.labelSize.width) * (self.shouldScroll ? 1 : 0),
y: 0
),
animated: false
)
stackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
self.labelInfos.forEach {
let wrapper: UIView = UIView()
wrapper.set(.width, to: labelSize.width)
wrapper.set(.height, to: labelSize.height)
let label: UILabel = UILabel()
label.font = .systemFont(ofSize: Values.miniFontSize)
label.themeTextColor = .textPrimary
label.lineBreakMode = .byTruncatingTail
label.attributedText = $0.attributedText
label.accessibilityIdentifier = $0.accessibility?.identifier
label.accessibilityLabel = $0.accessibility?.label
label.isAccessibilityElement = true
wrapper.addSubview(label)
label.center(in: wrapper)
stackView.addArrangedSubview(wrapper)
}
if self.shouldAutoScroll {
startScrolling()
}
}
private func setUpViewHierarchy() {
addSubview(scrollView)
scrollView.pin(to: self)
addSubview(arrowLeft)
arrowLeft.pin(.left, to: .left, of: self)
arrowLeft.center(.vertical, in: self, withInset: -4)
addSubview(arrowRight)
arrowRight.pin(.right, to: .right, of: self)
arrowRight.center(.vertical, in: self, withInset: -4)
addSubview(pageControl)
pageControl.center(.horizontal, in: self)
pageControl.pin(.bottom, to: .bottom, of: self)
scrollView.addSubview(stackView)
}
// MARK: - Interaction
private func startScrolling() {
timer?.invalidate()
timer = Timer.scheduledTimerOnMainThread(withTimeInterval: Self.autoScrollingTimeInterval, repeats: true) { _ in
guard self.labelInfos.count != 0 else { return }
let targetPage = (self.pageControl.currentPage + 1) % self.labelInfos.count
self.scrollView.scrollRectToVisible(
CGRect(
origin: CGPoint(
x: Int(self.labelSize.width) * targetPage,
y: 0
),
size: self.labelSize
),
animated: true
)
}
}
private func stopScrolling() {
timer?.invalidate()
timer = nil
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex: Int = {
let maybeCurrentPageIndex: Int = Int(round(scrollView.contentOffset.x/labelSize.width))
if self.shouldScroll {
if maybeCurrentPageIndex == 0 {
return pageControl.numberOfPages - 1
}
if maybeCurrentPageIndex == self.labelInfos.count - 1 {
return 0
}
return maybeCurrentPageIndex - 1
}
return maybeCurrentPageIndex
}()
pageControl.currentPage = pageIndex
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if pageControl.currentPage == 0 {
scrollView.setContentOffset(
CGPoint(
x: Int(self.labelSize.width) * 1,
y: 0
),
animated: false
)
}
if pageControl.currentPage == pageControl.numberOfPages - 1 {
let realLastIndex: Int = self.labelInfos.count - 2
scrollView.setContentOffset(
CGPoint(
x: Int(self.labelSize.width) * realLastIndex,
y: 0
),
animated: false
)
}
}
}

@ -558,6 +558,10 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou
timestamp: UInt64(currentViewController.galleryItem.interactionTimestampMs)
),
sentTimestamp: UInt64(SnodeAPI.currentOffsetTimestampMs())
)
.with(DisappearingMessagesConfiguration
.fetchOne(db, id: threadId)?
.forcedWithDisappearAfterReadIfNeeded()
),
interactionId: nil, // Show no interaction for the current user
threadId: threadId,

@ -61,8 +61,12 @@
<dict>
<key>seed1.getsession.org</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>seed2.getsession.org</key>
<dict>

@ -1,9 +1,7 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "AVAudioSession+OWS.h"
// Separate iOS Frameworks from other imports.
#import "OWSAudioPlayer.h"
#import "OWSBezierPathView.h"
#import "OWSMessageTimerView.h"
#import "OWSWindowManager.h"

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Запыты на паведамленні";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Няма чаканых запытаў паведамленняў";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Ачысціць усё";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Вы ўпэўнены, што хочаце ачысціць усе запыты паведамленняў?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Вы ўпэўнены, што жадаеце выдаліць усе запыты на паведамленні і запрашэнні ў групы?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Ачысьціць";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Вы ўпэўнены, што жадаеце выдаліць гэты запыт на паведамленне?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Вы ўпэўненыя, што жадаеце заблакіраваць гэты кантакт?";
@ -465,8 +465,6 @@
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "І %@ іншых карыстальнікаў адрэагавалі %@ на гэта паведамленне.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Павольней! Вы адправілі занадта шмат рэакцый на эмодзі. Паўтарыце спробу пазней.";
/* New conversation screen*/
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"vc_new_conversation_title" = "Новая гутарка";
"CREATE_GROUP_BUTTON_TITLE" = "Стварыць";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Далучыцца";
@ -575,8 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Задаць";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Гэты параметр прымяняецца да ўсіх у гэтай размове.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Гэты параметр прымяняецца да ўсіх у гэтай размове.\nТолькі адміністратары групы могуць змяніць гэты параметр.";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ усталяваў знікненне паведамленняў %@ пасля таго, як яны былі %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ змяніў паведамленні, каб яны выдаляліся %@ пасля таго, як яны былі %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ адключыў выдаленне паведамленняў";
/* context_menu_info */
@ -842,13 +842,13 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_PICTURE_UPDATED" = "Фота групы абноўлена.";
/* An informational message displayed when a single member joined the group, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ was invited to join the group.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ быў запрошаны ў групу.";
/* An informational message displayed when two members joined the group, the '%@' will be the names of both members. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ and %@ were invited to join the group.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ і %@ былі запрошаны ў групу.";
/* An informational message displayed when multiple members joined the group, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED" = "%@ and %@ others were invited to join the group.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED" = "%@, %@ і іншыя былі запрошаны ў групу.";
/* An informational message displayed when a single member was removed from the group, the '%@' will be the members. */
"GROUP_MESSAGE_INFO_MEMBER_REMOVED" = "%@ выдалены з групы.";
@ -1007,31 +1007,49 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_INVITED_FALLBACK" = "Вы атрымалі запрашэнне далучыцца да %@.";
/* An informational message displayed when the current user joined the group, the '%@' will be replaced with 'You'. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU" = "%@ were invited to join the group.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU" = "%@ былі запрошаны ў групу.";
/* An informational message displayed when a single member joined the group with access to chat history, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_WITH_HISTORY" = "%@ was invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_WITH_HISTORY" = "%@ быў запрошаны ў групу. Быў адкрыты агульны доступ да гісторыі чата.";
/* An informational message displayed when the current user joined the group, the '%@' will be replaced with 'You'. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU_WITH_HISTORY" = "%@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU_WITH_HISTORY" = "%@ былі запрошаны далучыцца да групы. Быў адкрыты агульны доступ да гісторыі чата.";
/* An informational message displayed when two members joined the group with access to chat history, the '%@' will be the names of both members. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_WITH_HISTORY" = "%@ і %@ былі запрошаны далучыцца да групы. Быў адкрыты агульны доступ да гісторыі чата.";
/* An informational message displayed when the current user and one other user joined the group, the first '%@' will be 'You' and the second will be the name of the other member. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU" = "%@ and %@ were invited to join the group.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU" = "%@ і %@ былі запрошаны ў групу.";
/* An informational message displayed when the current user and one other user joined the group with access to chat history, the first '%@' will be 'You' and the second will be the name of the other member. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ і %@ былі запрошаны далучыцца да групы. Быў адкрыты агульны доступ да гісторыі чата.";
/* An informational message displayed when multiple members joined the group with access to chat history, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_WITH_HISTORY" = "%@ і %@ былі запрошаны далучыцца да групы. Быў адкрыты агульны доступ да гісторыі чата.";
/* An informational message displayed when the current user and multiple other users joined the group, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU" = "%@ and %@ others were invited to join the group.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU" = "%@, %@ і іншыя былі запрошаны ў групу.";
/* An informational message displayed when the current user and multiple other users joined the group with access to chat history, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ and %@ others were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ і %@ былі запрошаны далучыцца да групы. Быў адкрыты агульны доступ да гісторыі чата.";
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "Пры спробе пачаць запіс галасавога паведамлення адбылася памылка.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Наладзіць, каб вашы паведамленні знікалі %@ пасля таго, як яны былі %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Паведамленні, якія вы адпраўляеце, больш не знікнуць. Вы ўпэўнены, што хочаце адключыць знікаючыя паведамленні?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Пацвердзіць";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Žádosti o zprávy";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Žádné nevyřízené žádosti o zprávu";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Smazat vše";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Jste si jisti, že chcete vymazat všechny žádosti o zprávy?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Jste si jisti, že chcete vymazat všechny žádosti o zprávy a pozvánky do skupin?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Smazat";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Jste si jisti, že chcete odstranit tuto žádost o zprávu?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Opravdu chcete zablokovat tento kontakt?";
@ -548,7 +548,6 @@
"modal_permission_library" = "knihovna";
"DISAPPEARING_MESSAGES_OFF" = "Vypnuto";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Vypnuto";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Zmizí po: %@";
"COPY_GROUP_URL" = "Kopírovat adresu skupiny";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontakty";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Vyberte prosím alespoň jednoho člena skupiny";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Nastavit";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Toto nastavení se týká všech účastníků této konverzace.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Toto nastavení se týká všech účastníků této konverzace. Toto nastavení mohou změnit pouze správci skupiny.";
"DISAPPERING_MESSAGES_SUMMARY" = "Zmizí po: %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ nastavil/a zprávy tak, aby zmizely %@ poté, co byly %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ změnil/a zprávy tak, aby zmizely %@ poté, co byly %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ vypnul/a mizející zprávy";
/* context_menu_info */
@ -842,13 +842,13 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_PICTURE_UPDATED" = "Obrázek skupiny aktualizován.";
/* An informational message displayed when a single member joined the group, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ was invited to join the group.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ byl(a) pozván(a) k připojení do skupiny.";
/* An informational message displayed when two members joined the group, the '%@' will be the names of both members. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ and %@ were invited to join the group.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ a %@ byli pozváni k připojení do skupiny.";
/* An informational message displayed when multiple members joined the group, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED" = "%@ and %@ others were invited to join the group.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED" = "%@ a %@ další byli pozváni k připojení do skupiny.";
/* An informational message displayed when a single member was removed from the group, the '%@' will be the members. */
"GROUP_MESSAGE_INFO_MEMBER_REMOVED" = "%@ byl/a odebrán/a ze skupiny.";
@ -1007,31 +1007,49 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_INVITED_FALLBACK" = "Byli jsi pozváni k připojení do %@.";
/* An informational message displayed when the current user joined the group, the '%@' will be replaced with 'You'. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU" = "%@ were invited to join the group.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU" = "%@ jste byli pozváni k připojení do skupiny.";
/* An informational message displayed when a single member joined the group with access to chat history, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_WITH_HISTORY" = "%@ was invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_WITH_HISTORY" = "%@ byl(a) pozván(a) k připojení do skupiny. Historie konverzace byla sdílena.";
/* An informational message displayed when the current user joined the group, the '%@' will be replaced with 'You'. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU_WITH_HISTORY" = "%@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU_WITH_HISTORY" = "%@ jste byli pozváni k připojení do skupiny. Historie konverzace byla sdílena.";
/* An informational message displayed when two members joined the group with access to chat history, the '%@' will be the names of both members. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_WITH_HISTORY" = "%@ a %@ byli pozváni k připojení do skupiny. Historie konverzace byla sdílena.";
/* An informational message displayed when the current user and one other user joined the group, the first '%@' will be 'You' and the second will be the name of the other member. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU" = "%@ and %@ were invited to join the group.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU" = "%@ a %@ byli pozváni k připojení do skupiny.";
/* An informational message displayed when the current user and one other user joined the group with access to chat history, the first '%@' will be 'You' and the second will be the name of the other member. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ a %@ jste byli pozváni k připojení do skupiny. Historie konverzace byla sdílena.";
/* An informational message displayed when multiple members joined the group with access to chat history, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_WITH_HISTORY" = "%@ a %@ byli pozváni k připojení do skupiny. Historie konverzace byla sdílena.";
/* An informational message displayed when the current user and multiple other users joined the group, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU" = "%@ and %@ others were invited to join the group.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU" = "%@ a %@ další byli pozváni k připojení do skupiny.";
/* An informational message displayed when the current user and multiple other users joined the group with access to chat history, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ and %@ others were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ a %@ další jste byli pozváni k připojení do skupiny. Historie konverzace byla sdílena.";
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "Při pokusu o spuštění nahrávání hlasové zprávy došlo k chybě.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Nastavení Sledování";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Nastavit zprávy tak, aby zmizely %@ poté, co byly %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Odeslané zprávy již nebudou mizet. Určitě chcete mizení zpráv vypnout?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Potvrdit";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Beskedanmodninger";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Ingen afventende beskedanmodninger";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Ryd Alle";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Er du sikker på du vil rydde alle beskedanmodninger?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Ryd";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Er du sikker på du vil slette denne beskedanmodning?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Nachrichtenanfragen";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Keine ausstehenden Nachrichtenanfragen";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Alles löschen";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Bist Du sicher, dass Du alle Nachrichtenanfragen löschen möchtest?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Sind Sie sich sicher, dass Sie alle Nachrichten und Gruppenanfragen löschen möchten?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Löschen";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Bist du sicher, dass du diese Nachrichtenanfrage löschen willst?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Möchtest du den Kontakt wirklich blockieren?";
@ -548,7 +548,6 @@
"modal_permission_library" = "Bibliothek";
"DISAPPEARING_MESSAGES_OFF" = "Aus";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Aus";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Verschwinden nach: %@";
"COPY_GROUP_URL" = "Gruppen-URL kopieren";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontakte";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Bitte wähle mindestens ein Gruppenmitglied aus";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Speichern";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Diese Einstellung gilt für alle in dieser Unterhaltung.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Diese Einstellung gilt für alle in dieser Unterhaltung. Nur Gruppenadministratoren können diese Einstellung ändern.";
"DISAPPERING_MESSAGES_SUMMARY" = "Verschwinden nach %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ hat eingestellt, dass die Nachrichten %@ verschwinden, nachdem sie %@ sind";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ hat eingestellt, dass die Nachrichten %@ verschwinden, nachdem sie %@ sind";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ hat verschwindende Nachrichten ausgeschaltet";
/* context_menu_info */
@ -782,19 +782,19 @@ Anhänge senden, sobald der Empfänger diese Nachrichtenanfrage angenommen hat";
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1036,3 +1036,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Αιτήματα Μηνύματος";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Δεν υπάρχουν αιτήματα μηνυμάτων σε εκκρεμότητα";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Διαγραφή Όλων";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Σίγουρα θέλετε να διαγράψετε όλα τα αιτήματα μηνύματος;";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Διαγραφή";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Σίγουρα θέλετε να διαγράψετε αυτό το αίτημα μηνύματος;";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Σίγουρα θέλετε να θέσετε σε φραγή αυτή την επαφή;";
@ -548,7 +548,6 @@
"modal_permission_library" = "βιβλιοθήκη";
"DISAPPEARING_MESSAGES_OFF" = "Απενεργοποιημένο";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Απενεργοποιημένη";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Εξαφάνιση Μετά Από: %@";
"COPY_GROUP_URL" = "Αντιγραφή URL Ομάδας";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Επαφές";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Παρακαλώ επιλέξτε τουλάχιστον 1 μέλος από την ομάδα";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Ορισμός";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Αυτή η ρύθμιση ισχύει για όλους σε αυτή τη συνομιλία.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Αυτή η ρύθμιση ισχύει για όλους σε αυτή τη συνομιλία. Μόνο οι διαχειριστές της ομάδας μπορούν να αλλάξουν αυτή τη ρύθμιση.";
"DISAPPERING_MESSAGES_SUMMARY" = "Εξαφάνιση Μετά Από %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ όρισε τα μηνύματα να εξαφανίζονται %@ αφότου έχουν %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ άλλαξε τα μηνύματα να εξαφανίζονται %@ αφότου έχουν %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ απενεργοποίησε τα εξαφανιζόμενα μηνύματα";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Peticiones de mensajes";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No hay solicitudes de mensajes pendientes";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Borrar todo";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "¿Estás seguro/a que quieres borrar todas las solicitudes de mensajes?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Borrar";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "¿Estás seguro de que quieres eliminar esta solicitud de mensaje?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "¿Estás seguro de que quieres bloquear este contacto?";
@ -548,7 +548,6 @@
"modal_permission_library" = "fototeca";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Desaparecer después de %@";
"COPY_GROUP_URL" = "Copiar URL del grupo";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contactos";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Elige al menos 1 miembro del grupo";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Definir";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Esta opción se aplica a todos los usuarios en esta conversación.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Esta opción se aplica a todos los usuarios en esta conversación.\nSolo los administradores del grupo la pueden cambiar.";
"DISAPPERING_MESSAGES_SUMMARY" = "Desaparece tras %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ ha establecido que los mensajes desaparezcan %@ tras haber sido %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ ha cambiado que los mensajes desaparezcan %@ tras haber sido %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ ha desactivado la desaparición de mensajes";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "درخواست های پیام";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "هیچ درخواست پیامی وجود ندارد";
"MESSAGE_REQUESTS_CLEAR_ALL" = "حذف همه";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "آیا مطمئن هستید که می خواهید تمام درخواست های پیام را پاک کنید؟";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "پاک کردن";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "آیا مطمئن هستید که می خواهید این درخواست پیام را رد کنید؟";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "آیا مطمئن هستید که می‌خواهید این مخاطب را مسدود کنید؟";
@ -548,7 +548,6 @@
"modal_permission_library" = "کتابخانه";
"DISAPPEARING_MESSAGES_OFF" = "خاموش";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "خاموش";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "ناپدید شدن پس از: %@";
"COPY_GROUP_URL" = "کپی کردن URL گروه";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "مخاطبین";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "لطفاً حداقل یک عضو گروه را انتخاب کنید";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "تنظیم";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "این تنظیمات بالای هر کسی در این مکالمه عملی می‌شود.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "این تنظیمات بالای هر کسی در این مکالمه عملی می‌شود. فقط ادمین‌های گروه می‌توانند این تنظیمات را تغییر دهند.";
"DISAPPERING_MESSAGES_SUMMARY" = "ناپدیدظشدن پس از %@ - %@ ";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ تنظیم کرده تا پیام‌ها %@ پس از آنکه %@ شدند، ناپدید شوند.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ پیام‌ها را تغییر داده تا %@ پس از آنکه %@ شدند، ناپدید شوند.";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ ناپدید‌شدن پیام ها را خاموش کرده است";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Viestipyynnöt";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Ei odottavia viestipyyntöjä";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Tyhjennä kaikki";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Haluatko varmasti tyhjentää kaikki viestipyynnöt?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Tyhjennä";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Haluatko varmasti poistaa viestipyynnön?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Haluatko varmasti estää tämän yhteystiedon?";
@ -548,7 +548,6 @@
"modal_permission_library" = "kirjasto";
"DISAPPEARING_MESSAGES_OFF" = "Pois käytöstä";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Pois käytöstä";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Katoa, kun on kulunut: %@";
"COPY_GROUP_URL" = "Kopioi ryhmän URL-osoite";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Yhteystiedot";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Valitse ainakin 1 ryhmän jäsen";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Aseta";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Tämä asetus koskee kaikkia tässä keskustelussa.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Tämä asetus koskee kaikkia tässä keskustelussa. Vain ryhmän ylläpitäjät voivat muuttaa asetusta.";
"DISAPPERING_MESSAGES_SUMMARY" = "Katoa, kun %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ on asettanut viestit katoamaan %@, kun ne on %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ on vahtanut viestit katoamaan %@, kun ne on %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ poisti katoavat viestit käytöstä";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Demandes de message";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Aucune demande de message en attente";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Effacer tous";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Êtes-vous sûr de vouloir supprimer toutes les demandes de messages ?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Effacer";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Êtes-vous sûr de vouloir supprimer cette demande de message ?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Êtes-vous sûr de vouloir bloquer ce contact ?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Appliquer";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Ce paramètre s'applique à tout le monde dans cette conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Üzenet kérések";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Nincsenek függőben lévő üzenetkérelmek";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Mindent töröl";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Biztos, hogy törölni akarja az összes üzenetkérést?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Törlés";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Biztosan törölni akarod ezt az üzenetet?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Biztosan le szeretnéd tiltani?";
@ -548,7 +548,6 @@
"modal_permission_library" = "könyvtár";
"DISAPPEARING_MESSAGES_OFF" = "Ki";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Ki";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Eltűnik %@ után";
"COPY_GROUP_URL" = "Csoport URL-jének másolása";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontaktok";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Kérjük, válassz legalább 1 csoporttagot";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Beállít";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Ez a beállítás mindenkire érvényes a beszélgetésben.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Ez a beállítás mindenkire érvényes a beszélgetésben. Csak adminisztrátorok módosíthatjá ezt a beállítást.";
"DISAPPERING_MESSAGES_SUMMARY" = "Eltűnik %@ - %@ után";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ úgy állította be, hogy az üzenetek eltűnjenek %@ miután %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ megváltoztatta az üzeneteket, hogy eltűnjenek %@ miután már %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ kikapcsolta az eltűnő üzeneteket";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Permintaan Pesan";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Tidak ada permintaan pesan tertunda";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Hapus Semua";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Apakah Anda yakin ingin menghapus semua permintaan pesan?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Hapus";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Apakah Anda yakin ingin menolak permintaan pesan ini?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Apakah Anda yakin ingin memblokir kontak ini?";
@ -548,7 +548,6 @@
"modal_permission_library" = "galeri";
"DISAPPEARING_MESSAGES_OFF" = "Mati";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Mati";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Menghilang Setelah: %@";
"COPY_GROUP_URL" = "Salin URL Grup";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontak";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Pilih setidaknya 1 anggota grup";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Atur";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Setelan ini berlaku untuk semua orang dalam percakapan ini.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Setelan ini berlaku untuk semua orang dalam percakapan ini. Hanya admin grup yang dapat mengubah pengaturan ini.";
"DISAPPERING_MESSAGES_SUMMARY" = "Menghilang Setelah %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ telah memasang pesan untuk menghilang %@ setelah %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ telah mengubah pesan untuk menghilang %@ setelah %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ telah menonaktifkan pesan menghilang";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Richieste di messaggi";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Nessuna richiesta in sospeso";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Cancella tutto";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Cancellare tutte le richieste di messaggi?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Confermi di voler eliminare tutte le richieste e gli inviti ai gruppi?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Cancella";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Vuoi eliminare questa richiesta?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Vuoi bloccare questo contatto?";
@ -548,7 +548,6 @@
"modal_permission_library" = "Libreria";
"DISAPPEARING_MESSAGES_OFF" = "No";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "No";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Timer: %@";
"COPY_GROUP_URL" = "Copia l'URL del gruppo";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contatti";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Scegli almeno 1 membro del gruppo";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Imposta";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Questa impostazione si applica a tutti i partecipanti di questa conversazione.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Questa impostazione si applica a tutti i partecipanti di questa conversazione.\nSolo gli amministratori possono modificarla.";
"DISAPPERING_MESSAGES_SUMMARY" = "Scompaiono dopo %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ ha impostato il timer dei messaggi effimeri a %@ che sono stati %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ ha modificato il timer dei messaggi effimeri a %@ che sono stati %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ ha disattivato i messaggi effimeri";
/* context_menu_info */
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "メッセージリクエスト";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "保留しているリクエストはありません";
"MESSAGE_REQUESTS_CLEAR_ALL" = "すべて消去";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "本当に全てのリクエストを消去しますか?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "本当に全てのメッセージリクエストを消去しますか?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "消去";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "本当にこのリクエストを削除しますか?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "この連絡先をブロックしてもよろしいですか?";
@ -548,7 +548,6 @@
"modal_permission_library" = "ライブラリ";
"DISAPPEARING_MESSAGES_OFF" = "オフ";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "オフ";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "- %@ の後に消えます";
"COPY_GROUP_URL" = "グループのURLをコピー";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "連絡先";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "グループメンバーを少なくとも 2 人選択してください";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "セット";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "この設定は、この会話の全員に適用されます。";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "この設定はこの会話の全員に適用されます。グループ管理者のみがこの設定を変更できます。";
"DISAPPERING_MESSAGES_SUMMARY" = "%@ - %@ の後に消えます";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ が %@ になった後、 %@消えるようにメッセージを設定しました";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ が %@ になった後、 %@消えるようにメッセージを設定しました";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ は消えているメッセージをオフにしました";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "모두 지우기";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "지우기";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "정말 이 메시지를 삭제하시겠습니까?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Ziņu pieprasījumi";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Nav gaidošu ziņojumu pieprasījumu";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Notīrīt visu";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Vai esat pārliecināts ka vēlaties dzēst visus ziņojumus?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Vai esat pārliecināts, ka vēlaties dzēst visu ziņu pieprasījumus un grupu uzaicinājumus?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Notīrīt";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Vai jūs esat pārliecināti ka vēlaties nodzēst šo ziņu?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Vai tiešām vēlaties bloķēt šo kontaktu?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Berichtverzoeken";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Geen berichtverzoeken in behandeling";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Alles wissen";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Weet u zeker dat u alle berichten wilt verwijderen?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Wissen";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Weet je zeker dat je dit bericht wilt verwijderen?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Meldingsforespørsler";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Ingen ventende meldingsforespørsler";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Tøm alle";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Er du sikker på at du ønsker å slette alle meldingsforespørsler?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Tøm";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Er du sikker på at du ønsker å slette denne meldingsforespørselen?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Er du sikker på at du ønsker å blokkere denne kontakten?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Żądania wiadomości";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Brak oczekujących żądań wiadomości";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Wyczyść wszystko";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Czy na pewno chcesz wyczyścić wszystkie żądania wiadomości?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Wyczyść";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Czy na pewno chcesz usunąć to żądanie wiadomości?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Czy na pewno chcesz zablokować ten kontakt?";
@ -548,7 +548,6 @@
"modal_permission_library" = "biblioteka";
"DISAPPEARING_MESSAGES_OFF" = "Wyłączone";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Wyłączone";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Zniknij po - %@";
"COPY_GROUP_URL" = "Skopiuj adres URL grupy";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontakty";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Proszę wybrać co najmniej 1 członka grupy";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Zapisz";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "To ustawienie dotyczy wszystkich w tej rozmowie.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "To ustawienie dotyczy wszystkich w tej konwersacji. Tylko administratorzy grupy mogą zmienić to ustawienie.";
"DISAPPERING_MESSAGES_SUMMARY" = "Zniknij po %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ ustawił(a) znikające wiadomości na %@ po tym, jak były %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ ustawił(a) znikające wiadomości na %@ po tym, jak były %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ wyłączył znikające wiadomości";
/* context_menu_info */
@ -1036,3 +1036,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Solicitações de Mensagem";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Nenhuma solicitação de mensagem pendente";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Limpar tudo";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Você tem certeza que deseja excluir todas as solicitações de mensagem?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Tem certeza de que deseja limpar todos os pedidos de mensagens e convites de grupo?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Limpar";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Você tem certeza que deseja excluir esta solicitação de mensagem?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Tem certeza de que deseja bloquear esse contato?";
@ -548,7 +548,6 @@
"modal_permission_library" = "biblioteca";
"DISAPPEARING_MESSAGES_OFF" = "Desligado";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Desligado";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Desaparecer após: %@";
"COPY_GROUP_URL" = "Copiar URL do grupo";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contatos";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Por favor, escolha pelo menos 1 membro para o grupo";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Aplicar";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Essa configuração se aplica a todos nesta conversa.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Esta configuração aplica-se a todos nesta conversa. Apenas os administradores de grupos podem alterar essa configuração.";
"DISAPPERING_MESSAGES_SUMMARY" = "Desaparecer Após %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ definiu mensagens para desaparecer %@ depois de terem sido %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ alterou as mensagens para desaparecer %@ depois de ter sido %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ desativou o desaparecimento de mensagens";
/* context_menu_info */
@ -607,7 +607,7 @@
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Solicitações de mensagem da comunidade";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Permitir pedidos de mensagens de conversas da Comunidade.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "Você poderá enviar mensagens de voz e anexos quando o destinatário aprovar esta solicitação de mensagem";
@ -727,7 +727,7 @@
"hide_note_to_self_confirmation_alert_message" = "Tem certeza de que deseja esconder %@?";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
"update_profile_modal_title" = "Definir imagem de exibição";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Salvar";
@ -842,13 +842,13 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_PICTURE_UPDATED" = "Imagem do grupo atualizada.";
/* An informational message displayed when a single member joined the group, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ was invited to join the group.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ foi convidado(a) a juntar-se ao grupo.";
/* An informational message displayed when two members joined the group, the '%@' will be the names of both members. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ and %@ were invited to join the group.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ e %@ foram convidados a juntarem-se ao grupo.";
/* An informational message displayed when multiple members joined the group, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED" = "%@ and %@ others were invited to join the group.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED" = "%@ e %@ outros foram convidados a juntar-se ao grupo.";
/* An informational message displayed when a single member was removed from the group, the '%@' will be the members. */
"GROUP_MESSAGE_INFO_MEMBER_REMOVED" = "%@ foi removido(a) do grupo.";
@ -1007,10 +1007,10 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_INVITED_FALLBACK" = "Você foi convidado a juntar-se a %@.";
/* An informational message displayed when the current user joined the group, the '%@' will be replaced with 'You'. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU" = "%@ were invited to join the group.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU" = "%@ foi convidado a juntar-se ao grupo.";
/* An informational message displayed when a single member joined the group with access to chat history, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_WITH_HISTORY" = "%@ was invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED_WITH_HISTORY" = "%@ foi convidado a se juntar-se ao grupo. O histórico de conversas será compartilhado.";
/* An informational message displayed when the current user joined the group, the '%@' will be replaced with 'You'. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU_WITH_HISTORY" = "%@ were invited to join the group. Chat history was shared.";
@ -1034,4 +1034,22 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ and %@ others were invited to join the group. Chat history was shared.";
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "Ocorreu um erro ao tentar iniciar a gravação para a mensagem de voz.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Defina suas mensagens para desaparecer %@ depois que forem %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "As mensagens que você enviar não irão mais desaparecer. Tem certeza de que deseja desativar desaparecer mensagens?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirmar";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -263,20 +263,20 @@
"vc_link_device_scan_qr_code_tab_title" = "Ler código QR";
"vc_display_name_title_2" = "Escolha seu nome";
"vc_display_name_explanation" = "Este será o seu nome quando usar o Session. Pode ser seu nome verdadeiro, um apelido ou qualquer outra coisa que você quiser.";
"vc_display_name_text_field_hint" = "Enter a display name";
"vc_display_name_display_name_missing_error" = "Please pick a display name";
"vc_display_name_display_name_too_long_error" = "Please pick a shorter display name";
"vc_display_name_text_field_hint" = "Introduza um nome de utilizador";
"vc_display_name_display_name_missing_error" = "Por favor, escolha um nome a exibir";
"vc_display_name_display_name_too_long_error" = "Por favor, escolha um nome de exibição mais curto";
"vc_pn_mode_recommended_option_tag" = "Recomendado";
"vc_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
"vc_home_empty_state_message" = "You don't have any contacts yet";
"vc_home_empty_state_button_title" = "Start a Session";
"vc_pn_mode_no_option_picked_modal_title" = "Por favor, escolha uma Opção";
"vc_home_empty_state_message" = "Ainda não tem nenhum contacto";
"vc_home_empty_state_button_title" = "Iniciar sessão";
"vc_seed_title" = "Sua frase de recuperação";
"vc_seed_title_2" = "Revele sua frase de recuperação";
"vc_seed_explanation" = "Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and dont give it to anyone.";
"vc_seed_explanation" = "A sua frase de recuperação é a chave principal para o Session ID — pode usá-la para restaurar a sua Session ID caso perda o acesso ao seu dispositivo. Guarde a sua frase de recuperação num local seguro e não a partilhe com ninguém. ";
"vc_seed_reveal_button_title" = "Segure para revelar";
"view_seed_reminder_subtitle_1" = "Secure your account by saving your recovery phrase";
"view_seed_reminder_subtitle_1" = "Proteja a sua conta guardando a sua frase de recuperação ";
"view_seed_reminder_subtitle_2" = "Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.";
"view_seed_reminder_subtitle_3" = "Make sure to store your recovery phrase in a safe place";
"view_seed_reminder_subtitle_3" = "Certifique-se que guarda a sua frase de recuperação num local seguro ";
"vc_path_title" = "Path";
"vc_path_explanation" = "Session hides your IP by routing your messages through multiple Service Nodes in Session's decentralized network. These are the countries your connection is currently being routed through:";
"vc_path_device_row_title" = "Você";
@ -284,54 +284,54 @@
"vc_path_service_node_row_title" = "Service Node";
"vc_path_destination_row_title" = "Destino";
"vc_path_learn_more_button_title" = "Saber mais";
"vc_create_private_chat_title" = "New Message";
"vc_create_private_chat_enter_session_id_tab_title" = "Enter Session ID";
"vc_create_private_chat_title" = "Nova mensagem";
"vc_create_private_chat_enter_session_id_tab_title" = "Inserir ID da sessão";
"vc_create_private_chat_scan_qr_code_tab_title" = "Ler código QR";
"vc_enter_public_key_explanation" = "Start a new conversation by entering someone's Session ID or share your Session ID with them.";
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
"vc_create_closed_group_title" = "Create Group";
"vc_enter_public_key_explanation" = "Iniciar uma nova conversa, introduzindo o Session ID de alguém ou compartilhando o seu Session ID com outros utilizadores. ";
"vc_scan_qr_code_camera_access_explanation" = "O Session necessita de acesso à câmara de modo a ler códigos QR";
"vc_create_closed_group_title" = "Criar grupo";
"vc_create_closed_group_text_field_hint" = "Introduzir o nome do grupo";
"vc_create_closed_group_empty_state_message" = "Você ainda não tem contatos";
"vc_create_closed_group_group_name_missing_error" = "Por favor, insira o nome do grupo";
"vc_create_closed_group_group_name_too_long_error" = "Digite um nome de grupo mais curto";
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 100 members";
"vc_join_public_chat_title" = "Join Community";
"vc_join_public_chat_enter_group_url_tab_title" = "Community URL";
"vc_create_closed_group_too_many_group_members_error" = "Um grupo fechado/privado não pode ter mais de 100 pessoas";
"vc_join_public_chat_title" = "Junte-se à comunidade";
"vc_join_public_chat_enter_group_url_tab_title" = "URL da comunidade";
"vc_join_public_chat_scan_qr_code_tab_title" = "Ler código QR";
"vc_enter_chat_url_text_field_hint" = "Enter Community URL";
"vc_enter_chat_url_text_field_hint" = "Inserir o URL da comunidade";
"vc_settings_title" = "Definições";
"vc_group_settings_title" = "Group Settings";
"vc_group_settings_title" = "Definições do grupo";
"vc_settings_display_name_missing_error" = "Escolha um nome de exibição";
"vc_settings_display_name_too_long_error" = "Escolha um nome de exibição mais curto";
"vc_settings_privacy_button_title" = "Privacidade";
"vc_settings_notifications_button_title" = "Notificações";
"vc_settings_recovery_phrase_button_title" = "Frase de recuperação";
"vc_settings_clear_all_data_button_title" = "Apagar os dados";
"vc_qr_code_title" = "QR Code";
"vc_qr_code_view_my_qr_code_tab_title" = "View My QR Code";
"vc_qr_code_title" = "Código QR";
"vc_qr_code_view_my_qr_code_tab_title" = "Visualizar o meu código QR";
"vc_qr_code_view_scan_qr_code_tab_title" = "Ler código QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Scan someone's QR code to start a conversation with them";
"vc_view_my_qr_code_explanation" = "This is your QR code. Other users can scan it to start a session with you.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Youll be notified of new messages reliably and immediately using Apples notification servers.";
"fast_mode" = "Fast Mode";
"slow_mode_explanation" = "Session will occasionally check for new messages in the background.";
"slow_mode_explanation" = "Ocasionalmente, o Session procurará novas mensagens em segundo plano. ";
"slow_mode" = "Modo lento";
"vc_pn_mode_title" = "Message Notifications";
"vc_pn_mode_title" = "Notificações de mensagem";
"vc_link_device_recovery_phrase_tab_title" = "Frase de recuperação";
"vc_link_device_scan_qr_code_explanation" = "Navegue para Configurações → Frase de recuperação no outro dispositivo para mostrar o código QR.";
"vc_enter_recovery_phrase_title" = "Frase de recuperação";
"vc_enter_recovery_phrase_explanation" = "To link your device, enter the recovery phrase that was given to you when you signed up.";
"vc_enter_public_key_text_field_hint" = "Enter Session ID or ONS name";
"admin_group_leave_warning" = "Because you are the creator of this group it will be deleted for everyone. This cannot be undone.";
"vc_join_open_group_suggestions_title" = "Or join one of these...";
"vc_enter_recovery_phrase_explanation" = "Para se conectar com o seu dispositivo, introduza o código de recuperação que lhe foi fornecido quando realizou a sua inscrição. ";
"vc_enter_public_key_text_field_hint" = "Introduzir Session ID ou nome de ONS";
"admin_group_leave_warning" = "Tendo em conta que é o criador deste grupo, ele será eliminado para todos. Não poderá retroceder com a sua eliminação. ";
"vc_join_open_group_suggestions_title" = "Ou junte-se a um destes...";
"vc_settings_invite_a_friend_button_title" = "Convidar um Amigo";
"copied" = "Copiado";
"vc_conversation_settings_copy_session_id_button_title" = "Copiar ID da sessão";
"vc_conversation_input_prompt" = "Mensagem";
"vc_conversation_voice_message_cancel_message" = "Deslize para cancelar";
"modal_download_attachment_title" = "Confiar em %@?";
"modal_download_attachment_explanation" = "Are you sure you want to download media sent by %@?";
"modal_download_attachment_explanation" = "Tem a certeza que pretende descarregar o conteúdo enviado por %@ ?";
"modal_download_button_title" = "Transferir";
"modal_open_url_title" = "Abrir URL";
"modal_open_url_explanation" = "Tem certeza de que deseja abrir %@?";
@ -343,22 +343,22 @@
"modal_link_previews_title" = "Ativar pré-visualizações do link?";
"modal_link_previews_explanation" = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings.";
"modal_link_previews_button_title" = "Ativar";
"vc_share_title" = "Share to Session";
"vc_share_title" = "Partilhar com o Session";
"vc_share_loading_message" = "A preparar anexos...";
"vc_share_sending_message" = "A enviar...";
"vc_share_link_previews_unsecure" = "Preview not loaded for unsecure link";
"vc_share_link_previews_error" = "Unable to load preview";
"vc_share_link_previews_disabled_title" = "Link Previews Disabled";
"vc_share_link_previews_unsecure" = "Pré-visualização não carregada devido a link inseguro";
"vc_share_link_previews_error" = "Não foi possível carregar a pré-visualização";
"vc_share_link_previews_disabled_title" = "Pré-visualizações dos links estão desativadas.";
"vc_share_link_previews_disabled_explanation" = "Enabling link previews will show previews for URLs you share. This can be useful, but Session will need to contact linked websites to generate previews.\n\nYou can enable link previews in Session's settings.";
"view_open_group_invitation_description" = "Open group invitation";
"vc_conversation_settings_invite_button_title" = "Add Members";
"view_open_group_invitation_description" = "Abrir convite de grupo";
"vc_conversation_settings_invite_button_title" = "Adicionar membros";
"modal_send_seed_title" = "Aviso";
"modal_send_seed_explanation" = "This is your recovery phrase. If you send it to someone they'll have full access to your account.";
"modal_send_seed_explanation" = "Esta é a sua frase de recuperação. Se a enviar a alguém, essa pessoa terá acesso total à sua conta. ";
"modal_send_seed_send_button_title" = "Enviar";
"vc_conversation_settings_notify_for_mentions_only_title" = "Notify for Mentions Only";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "When enabled, you'll only be notified for messages mentioning you.";
"view_conversation_title_notify_for_mentions_only" = "Notifying for Mentions Only";
"message_deleted" = "This message has been deleted";
"vc_conversation_settings_notify_for_mentions_only_title" = "Notificar apenas quando sou mencionado ";
"vc_conversation_settings_notify_for_mentions_only_explanation" = "Após a sua ativação, apenas será notificado quando for mencionado numa mensagem. ";
"view_conversation_title_notify_for_mentions_only" = "Notificar-me apenas quando sou mencionado ";
"message_deleted" = "Esta mensagem foi apagada";
"delete_message_for_me" = "Apagar apenas para mim";
"delete_message_for_everyone" = "Apagar para todos";
"delete_message_for_me_and_recipient" = "Apagar para mim e %@";
@ -366,7 +366,7 @@
"context_menu_save" = "Guardar";
"context_menu_ban_user" = "Banir utilizador";
"context_menu_ban_and_delete_all" = "Banir e Apagar Todos";
"context_menu_ban_user_error_alert_message" = "Unable to ban user";
"context_menu_ban_user_error_alert_message" = "Não foi possível banir o utilizador";
"accessibility_expanding_attachments_button" = "Adicionar anexos";
"accessibility_gif_button" = "Gif";
"accessibility_document_button" = "Documento";
@ -385,226 +385,232 @@
"PIN_BUTTON_TEXT" = "Fixar";
"UNPIN_BUTTON_TEXT" = "Desafixar";
"modal_call_missed_tips_title" = "Chamada perdida";
"modal_call_missed_tips_explanation" = "Call missed from '%@' because you needed to enable the 'Voice and video calls' permission in the Privacy Settings.";
"media_saved" = "Media saved by %@.";
"modal_call_missed_tips_explanation" = "Perdeu uma chamada de '%@' , porque necessita de ativar as chamadas de voz e vídeo nas configurações de privacidade. ";
"media_saved" = "Conteúdo guardado por %@";
"screenshot_taken" = "%@ fez uma captura de ecrã.";
"SEARCH_SECTION_CONTACTS" = "Contacts & Groups";
"SEARCH_SECTION_CONTACTS" = "Contactos e Grupos";
"SEARCH_SECTION_MESSAGES" = "Mensagens";
"MESSAGE_REQUESTS_TITLE" = "Pedidos de Mensagem";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Nenhum pedido de mensagem pendente";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Limpar tudo";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Tem certeza de que deseja apagar todos os pedidos de mensagem?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Tem a certeza que pretende eliminar todos os pedidos de mensagens e grupos? ";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Apagar";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Tem certeza de que deseja apagar este pedido de mensagem?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Tem a certeza que pretende bloquear este contacto?";
"MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request and reveal your Session ID.";
"MESSAGE_REQUESTS_ACCEPTED" = "Seu pedido de mensagem foi aceito.";
"MESSAGE_REQUESTS_NOTIFICATION" = "Você tem um novo pedido de mensagem";
"TXT_HIDE_TITLE" = "Ocultar";
"TXT_DELETE_ACCEPT" = "Aceitar";
"TXT_BLOCK_USER_TITLE" = "Block User";
"ALERT_ERROR_TITLE" = "Error";
"TXT_BLOCK_USER_TITLE" = "Bloquear utilizador";
"ALERT_ERROR_TITLE" = "Erro";
"modal_call_permission_request_title" = "Call Permissions Required";
"modal_call_permission_request_explanation" = "Pode ativar 'Chamadas de voz e vídeo' nas Configurações de Privacidade.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
"LOADING_CONVERSATIONS" = "Loading Conversations...";
"DATABASE_MIGRATION_FAILED" = "An error occurred when optimising the database\n\nYou can export your application logs to be able to share for troubleshooting or you can restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
"RECOVERY_PHASE_ERROR_GENERIC" = "Something went wrong. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Looks like you didn't enter enough words. Please check your recovery phrase and try again.";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "You seem to be missing the last word of your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "There appears to be an invalid word in your recovery phrase. Please check what you entered and try again.";
"RECOVERY_PHASE_ERROR_FAILED" = "Your recovery phrase couldn't be verified. Please check what you entered and try again.";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, ocorreu um erro";
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Tenta novamente mais tarde";
"LOADING_CONVERSATIONS" = "A carregar conversas...";
"DATABASE_MIGRATION_FAILED" = "Ocorreu um erro aquando da otimização da base de dados \n\\
Pode exportar os seus inícios de sessão da aplicação de modo a partilhar uma eventual resolução de erros ou pode restaurar o seu dispositivo.
Alerta: Restaurar o seu dispositivo levará à perda dos dados mais antigos que duas semanas";
"RECOVERY_PHASE_ERROR_GENERIC" = "Aconteceu algo errado. Por favor, verifique a sua frase de recuperação e tente novamente.";
"RECOVERY_PHASE_ERROR_LENGTH" = "Parece que não introduziu palavras suficientes. Por favor, verifique a sua frase de recuperação e tente novamente. ";
"RECOVERY_PHASE_ERROR_LAST_WORD" = "Parece que falta a última palavra da sua frase de recuperação. Por favor, verifique o que introduziu e tente novamente.";
"RECOVERY_PHASE_ERROR_INVALID_WORD" = "Parece haver uma palavra incorreta no seu código de recuperação. Por favor, verifique o que introduziu e tente novamente. ";
"RECOVERY_PHASE_ERROR_FAILED" = "Não foi possível verificar a sua frase de recuperação. Por favor, verifique o que introduziu e tente novamente. ";
/* Indicates that an unknown error occurred while using Touch ID/Face ID/Phone Passcode. */
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Authentication could not be accessed.";
"SCREEN_LOCK_ENABLE_UNKNOWN_ERROR" = "Não foi possível aceder.";
/* Indicates that Touch ID/Face ID/Phone Passcode authentication failed. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Authentication failed.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_FAILED" = "Falha na autenticação. ";
/* Indicates that Touch ID/Face ID/Phone Passcode is 'locked out' on this device due to authentication failures. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Too many failed authentication attempts. Please try again later.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_LOCKOUT" = "Demasiadas tentativas falhadas. Por favor, tente novamente mais tarde.";
/* Indicates that Touch ID/Face ID/Phone Passcode are not available on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_AVAILABLE" = "Deve ativar a sua senha nas definições do seu iOS de modo a usar o Screen Lock. ";
/* Indicates that Touch ID/Face ID/Phone Passcode is not configured on this device. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_NOT_ENROLLED" = "Deve ativar a sua senha nas definições do seu iOS de modo a usar o Screen Lock. ";
/* Indicates that Touch ID/Face ID/Phone Passcode passcode is not set. */
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "You must enable a passcode in your iOS Settings in order to use Screen Lock.";
"SCREEN_LOCK_ERROR_LOCAL_AUTHENTICATION_PASSCODE_NOT_SET" = "Deve ativar a sua senha nas definições do seu iOS de modo a usar o Screen Lock. ";
/* Label for the button to send a message */
"SEND_BUTTON_TITLE" = "Send";
"SEND_BUTTON_TITLE" = "Enviar";
/* Generic text for button that retries whatever the last action was. */
"RETRY_BUTTON_TEXT" = "Retry";
"RETRY_BUTTON_TEXT" = "Tentar novamente";
/* notification action */
"SHOW_THREAD_BUTTON_TITLE" = "Show Chat";
"SHOW_THREAD_BUTTON_TITLE" = "Mostrar conversa";
/* notification body */
"SEND_FAILED_NOTIFICATION_BODY" = "Your message failed to send.";
"INVALID_SESSION_ID_MESSAGE" = "Please check the Session ID and try again.";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Please check the Recovery Phrase and try again.";
"MEDIA_TAB_TITLE" = "Media";
"DOCUMENT_TAB_TITLE" = "Documents";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "You don't have any document in this conversation.";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "Loading Newer Document…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "Loading Older Document…";
"SEND_FAILED_NOTIFICATION_BODY" = "O envio da sua mensagem falhou.";
"INVALID_SESSION_ID_MESSAGE" = "Por favor, verifique o seu Session ID e tente novamente. ";
"INVALID_RECOVERY_PHRASE_MESSAGE" = "Por favor, verifique a sua frase de recuperação e tente novamente.";
"MEDIA_TAB_TITLE" = "Multimédia";
"DOCUMENT_TAB_TITLE" = "Documentos";
"DOCUMENT_TILES_EMPTY_DOCUMENT" = "Não existe nenhum documento neste conversa. ";
"DOCUMENT_TILES_LOADING_MORE_RECENT_LABEL" = "A carregar documento mais recente…";
"DOCUMENT_TILES_LOADING_OLDER_LABEL" = "A carregar documento mais antigo…";
/* The name for the emoji category 'Activities' */
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Activities";
"EMOJI_CATEGORY_ACTIVITIES_NAME" = "Atividades";
/* The name for the emoji category 'Animals & Nature' */
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animals & Nature";
"EMOJI_CATEGORY_ANIMALS_NAME" = "Animais e natureza";
/* The name for the emoji category 'Flags' */
"EMOJI_CATEGORY_FLAGS_NAME" = "Flags";
/* The name for the emoji category 'Food & Drink' */
"EMOJI_CATEGORY_FOOD_NAME" = "Food & Drink";
"EMOJI_CATEGORY_FOOD_NAME" = "Comida e bebidas";
/* The name for the emoji category 'Objects' */
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objects";
"EMOJI_CATEGORY_OBJECTS_NAME" = "Objetos";
/* The name for the emoji category 'Recents' */
"EMOJI_CATEGORY_RECENTS_NAME" = "Recently Used";
"EMOJI_CATEGORY_RECENTS_NAME" = "Recentemente utilizado";
/* The name for the emoji category 'Smileys & People' */
"EMOJI_CATEGORY_SMILEYSANDPEOPLE_NAME" = "Smileys & People";
/* The name for the emoji category 'Symbols' */
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Symbols";
"EMOJI_CATEGORY_SYMBOLS_NAME" = "Símbolos";
/* The name for the emoji category 'Travel & Places' */
"EMOJI_CATEGORY_TRAVEL_NAME" = "Travel & Places";
"EMOJI_REACTS_NOTIFICATION" = "%@ reacts to a message with %@.";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "And 1 other has reacted %@ to this message.";
"EMOJI_CATEGORY_TRAVEL_NAME" = "Viagem e locais";
"EMOJI_REACTS_NOTIFICATION" = "%@ Reagiu à sua mensagem com %@";
"EMOJI_REACTS_MORE_REACTORS_ONE" = "Outra pessoa reagiu %@ a esta mensagem ";
"EMOJI_REACTS_MORE_REACTORS_MUTIPLE" = "And %@ others have reacted %@ to this message.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Slow down! You've sent too many emoji reacts. Try again soon.";
"EMOJI_REACTS_RATE_LIMIT_TOAST" = "Calma! Enviou demasiadas reações de emojis. Tente novamente em breve.";
/* New conversation screen*/
"vc_new_conversation_title" = "New Conversation";
"CREATE_GROUP_BUTTON_TITLE" = "Create";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Join";
"PRIVACY_TITLE" = "Privacy";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Screen Security";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Lock Session";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Require Touch ID, Face ID or your passcode to unlock Session.";
"PRIVACY_SECTION_READ_RECEIPTS" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_TITLE" = "Read Receipts";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Send read receipts in one-to-one chats.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Typing Indicators";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Typing Indicators";
"vc_new_conversation_title" = "Nova conversa";
"CREATE_GROUP_BUTTON_TITLE" = "Criar";
"JOIN_COMMUNITY_BUTTON_TITLE" = "Entrar";
"PRIVACY_TITLE" = "Privacidade";
"PRIVACY_SECTION_SCREEN_SECURITY" = "Segurança de ecrã";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_TITLE" = "Bloquear sessão";
"PRIVACY_SCREEN_SECURITY_LOCK_SESSION_DESCRIPTION" = "Requer Touch ID, Face ID ou password para desbloquear o Session. ";
"PRIVACY_SECTION_READ_RECEIPTS" = "Recibos de Leitura";
"PRIVACY_READ_RECEIPTS_TITLE" = "Recibos de Leitura";
"PRIVACY_READ_RECEIPTS_DESCRIPTION" = "Enviar confirmações de leitura em conversas privadas.";
"PRIVACY_SECTION_TYPING_INDICATORS" = "Indicadores de escrita";
"PRIVACY_TYPING_INDICATORS_TITLE" = "Indicadores de escrita";
"PRIVACY_TYPING_INDICATORS_DESCRIPTION" = "See and share typing indicators in one-to-one conversations.";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Link Previews";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Send Link Previews";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Generate link previews for supported URLs.";
"PRIVACY_SECTION_CALLS" = "Calls (Beta)";
"PRIVACY_CALLS_TITLE" = "Voice and Video Calls";
"PRIVACY_CALLS_DESCRIPTION" = "Enables voice and video calls to and from other users.";
"PRIVACY_CALLS_WARNING_TITLE" = "Voice and Video Calls (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "Your IP address is visible to your call partner and an Oxen Foundation server while using beta calls. Are you sure you want to enable Voice and Video Calls?";
"NOTIFICATIONS_TITLE" = "Notifications";
"NOTIFICATIONS_SECTION_STRATEGY" = "Notification Strategy";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Use Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "You'll be notified of new message reliably and immediately using Apple's notification servers.";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Go to device notification settings";
"NOTIFICATIONS_SECTION_STYLE" = "Notification Style";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Sound";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Sound When App is Open";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Notification Content";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "The information shown in notifications.";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Name & Content";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Name Only";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "No Name or Content";
"CONVERSATION_SETTINGS_TITLE" = "Conversations";
"PRIVACY_SECTION_LINK_PREVIEWS" = "Pré-visualização de links";
"PRIVACY_LINK_PREVIEWS_TITLE" = "Enviar pré-visualizações de links";
"PRIVACY_LINK_PREVIEWS_DESCRIPTION" = "Criar pré-visualização de links para URLs suportados. ";
"PRIVACY_SECTION_CALLS" = "Chamadas (Beta)";
"PRIVACY_CALLS_TITLE" = "Chamadas de vídeo e voz";
"PRIVACY_CALLS_DESCRIPTION" = "Ativar as chamadas de voz e vídeo de e para outros utilizadores. ";
"PRIVACY_CALLS_WARNING_TITLE" = "Chamadas de vídeo e voz (Beta)";
"PRIVACY_CALLS_WARNING_DESCRIPTION" = "O seu adereço de IP estará visível para o seu companheiro de chamada e para o servidor Fundação Oxen enquanto usa as chamadas em versão BETA. Tem a certeza que pretende ativar as chamadas de voz e vídeo? ";
"NOTIFICATIONS_TITLE" = "Notificações";
"NOTIFICATIONS_SECTION_STRATEGY" = "Estratégia da notificação";
"NOTIFICATIONS_STRATEGY_FAST_MODE_TITLE" = "Usar Fast Mode";
"NOTIFICATIONS_STRATEGY_FAST_MODE_DESCRIPTION" = "Ao usar os servidores de notificação da Apple, será notificado de novas mensagens de forma consistente e imediata. ";
"NOTIFICATIONS_STRATEGY_FAST_MODE_ACTION" = "Ir para as definições de notificações";
"NOTIFICATIONS_SECTION_STYLE" = "Estilo de notificação";
"NOTIFICATIONS_STYLE_SOUND_TITLE" = "Som";
"NOTIFICATIONS_STYLE_SOUND_WHEN_OPEN_TITLE" = "Som de quando a aplicação é iniciada ";
"NOTIFICATIONS_STYLE_CONTENT_TITLE" = "Conteúdo da notificação";
"NOTIFICATIONS_STYLE_CONTENT_DESCRIPTION" = "Informação exibida nas notificações";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT" = "Nome e conteúdo";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY" = "Apenas o nome";
"NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT" = "Sem Nome ou Conteúdo";
"CONVERSATION_SETTINGS_TITLE" = "Conversas";
"CONVERSATION_SETTINGS_SECTION_MESSAGE_TRIMMING" = "Message Trimming";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_TITLE" = "Trim Communities";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Delete messages older than 6 months from Communities that have over 2,000 messages.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Autoplay Audio Messages";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Autoplay consecutive audio messages.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Blocked Contacts";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "You have no blocked contacts.";
"CONVERSATION_SETTINGS_MESSAGE_TRIMMING_DESCRIPTION" = "Eliminar mensagens com mais de 6 meses, de comunidades que têm acima de 2.000 mensagens.";
"CONVERSATION_SETTINGS_SECTION_AUDIO_MESSAGES" = "Mensagens de voz";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_TITLE" = "Reproduzir automaticamente mensagens de áudio ";
"CONVERSATION_SETTINGS_AUDIO_MESSAGES_AUTOPLAY_DESCRIPTION" = "Reproduzir automaticamente mensagens de áudio seguidas.";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_TITLE" = "Contactos Bloqueados";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_EMPTY_STATE" = "Não possui nenhum contacto bloqueado. ";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK" = "Unblock";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Are you sure you want to unblock %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "this contact";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Are you sure you want to unblock %@";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "and %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "and %d others?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_SINGLE" = "Tem a certeza que pretende bloquear %@?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_FALLBACK" = "Este contacto";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_1" = "Tem a certeza que quer bloquear %@ ?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_2_SINGLE" = "e %@ ?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_TITLE_MULTIPLE_3" = "e %d outros?";
"CONVERSATION_SETTINGS_BLOCKED_CONTACTS_UNBLOCK_CONFIRMATION_ACTON" = "Unblock";
"APPEARANCE_TITLE" = "Appearance";
"APPEARANCE_THEMES_TITLE" = "Themes";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Primary colour";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "How are you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "I'm good thanks, you?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "I'm doing great, thanks.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Auto night-mode";
"APPEARANCE_TITLE" = "Aparência";
"APPEARANCE_THEMES_TITLE" = "Temas";
"APPEARANCE_PRIMARY_COLOR_TITLE" = "Cor Principal";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_QUOTE" = "Como estás?";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_INC_MESSAGE" = "Estou bem obrigado, e tu? ";
"APPEARANCE_PRIMARY_COLOR_PREVIEW_OUT_MESSAGE" = "Estou bem, obrigado.";
"APPEARANCE_NIGHT_MODE_TITLE" = "Modo noturno automático";
"APPEARANCE_NIGHT_MODE_TOGGLE" = "Match system settings";
"HELP_TITLE" = "Help";
"HELP_REPORT_BUG_TITLE" = "Report a Bug";
"HELP_REPORT_BUG_DESCRIPTION" = "Export your logs, then upload the file though Session's Help Desk.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Export Logs";
"HELP_TRANSLATE_TITLE" = "Translate Session";
"HELP_FEEDBACK_TITLE" = "We'd love your Feedback";
"HELP_FAQ_TITLE" = "FAQ";
"HELP_SUPPORT_TITLE" = "Support";
"HELP_TITLE" = "Ajuda";
"HELP_REPORT_BUG_TITLE" = "Denunciar erro";
"HELP_REPORT_BUG_DESCRIPTION" = "Exportar os seus inícios de sessão e carregar o ficheiro através do Centro de Ajuda do Session.";
"HELP_REPORT_BUG_ACTION_TITLE" = "Exportar inícios de sessão";
"HELP_TRANSLATE_TITLE" = "Traduzir Session";
"HELP_FEEDBACK_TITLE" = "Adorávamos saber a sua opinião";
"HELP_FAQ_TITLE" = "FAQ (Perguntas Mais Frequentes)";
"HELP_SUPPORT_TITLE" = "Suporte";
"modal_clear_all_data_title" = "Limpar todos os dados";
"modal_clear_all_data_explanation" = "This will permanently delete your messages and contacts. Would you like to clear this device only, or delete your data from the network as well?";
"modal_clear_all_data_explanation" = "Apagará permanentemente as suas mensagens e contactos. Gostaria de eliminar isto apenas do seu telemóvel, ou também eliminar a sua base de dados inteira? ";
"modal_clear_all_data_explanation_2" = "Are you sure you want to delete your data from the network? If you continue, you will not be able to restore your messages or contacts.";
"modal_clear_all_data_device_only_button_title" = "Clear Device Only";
"modal_clear_all_data_entire_account_button_title" = "Clear Device and Network";
"modal_clear_all_data_device_only_button_title" = "Limpar apenas o dispositivo";
"modal_clear_all_data_entire_account_button_title" = "Limpar dispositivo e base de dados";
"dialog_clear_all_data_deletion_failed_1" = "Data not deleted by 1 Service Node. Service Node ID: %@.";
"dialog_clear_all_data_deletion_failed_2" = "Data not deleted by %@ Service Nodes. Service Node IDs: %@.";
"modal_clear_all_data_confirm" = "Clear";
"modal_clear_all_data_confirm" = "Apagar";
"modal_seed_title" = "Sua frase de recuperação";
"modal_seed_explanation" = "You can use your recovery phrase to restore your account or link a device.";
"modal_permission_explanation" = "Session needs %@ access to continue. You can enable access in the iOS settings.";
"modal_permission_settings_title" = "Settings";
"modal_permission_camera" = "camera";
"modal_permission_microphone" = "microphone";
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
"GROUP_CREATION_PLEASE_WAIT" = "Please wait while the group is created...";
"GROUP_CREATION_ERROR_TITLE" = "Couldn't Create Group";
"GROUP_CREATION_ERROR_MESSAGE" = "Please check your internet connection and try again.";
"GROUP_UPDATE_ERROR_TITLE" = "Couldn't Update Group";
"GROUP_UPDATE_ERROR_MESSAGE" = "Can't leave while adding or removing other members.";
"GROUP_ACTION_REMOVE" = "Remove";
"GROUP_TITLE_MEMBERS" = "Members";
"GROUP_TITLE_FALLBACK" = "Group";
"modal_permission_settings_title" = "Definições";
"modal_permission_camera" = "Câmara";
"modal_permission_microphone" = "Microfone";
"modal_permission_library" = "Biblioteca";
"DISAPPEARING_MESSAGES_OFF" = "Desligado";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Desligado";
"COPY_GROUP_URL" = "Copiar URL do grupo";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contatos";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Por favor, escolha pelo menos um membro do grupo";
"GROUP_CREATION_PLEASE_WAIT" = "Por favor, aguarde enquanto o grupo é criado...";
"GROUP_CREATION_ERROR_TITLE" = "Não foi possível criar grupo";
"GROUP_CREATION_ERROR_MESSAGE" = "Por favor, verifique a sua ligação à internet e tente novamente.";
"GROUP_UPDATE_ERROR_TITLE" = "Não foi possível atualizar o grupo";
"GROUP_UPDATE_ERROR_MESSAGE" = "Não pode sair enquanto não adicionar ou remover outros membros do grupo.";
"GROUP_ACTION_REMOVE" = "Eliminar ";
"GROUP_TITLE_MEMBERS" = "Membros";
"GROUP_TITLE_FALLBACK" = "Grupo";
"DM_ERROR_DIRECT_BLINDED_ID" = "You can only send messages to Blinded IDs from within a Community";
"DM_ERROR_INVALID" = "Please check the Session ID or ONS name and try again";
"COMMUNITY_ERROR_INVALID_URL" = "Please check the URL you entered and try again.";
"COMMUNITY_ERROR_GENERIC" = "Couldn't Join";
"DISAPPERING_MESSAGES_TITLE" = "Disappearing Messages";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Delete Type";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Disappear After Read";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "Messages delete after they have been read.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Disappear After Send";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "Messages delete after they have been sent.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Timer";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
"DM_ERROR_INVALID" = "Por favor, verifique o Session ID ou o nome OSN e tente novamente.";
"COMMUNITY_ERROR_INVALID_URL" = "Por favor, verifique o URL colocado e tente novamente. ";
"COMMUNITY_ERROR_GENERIC" = "Falha ao entrar";
"DISAPPERING_MESSAGES_TITLE" = "Desaparecimento de mensagens";
"DISAPPERING_MESSAGES_TYPE_TITLE" = "Categorias de eliminação";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_TITLE" = "Desaparecer após leitura";
"DISAPPERING_MESSAGES_TYPE_AFTER_READ_DESCRIPTION" = "As mensagens serão apagadas após serem lidas.";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_TITLE" = "Desaparecer mensagem após o seu envio";
"DISAPPERING_MESSAGES_TYPE_AFTER_SEND_DESCRIPTION" = "As mensagens serão apagadas após o seu envio.";
"DISAPPERING_MESSAGES_TIMER_TITLE" = "Temporizador";
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Configurar ";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Esta configuração aplica-se a todos os membros desta conversa.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Esta configuração aplica-se a todos os membros da conversa. \n Apenas os administradores do grupo podem modificar esta configuração. ";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
"context_menu_info" = "Informações";
/* An error that is displayed when the application fails for create it's initial connection to the database */
"DATABASE_STARTUP_FAILED" = "An error occurred when opening the database\n\nYou can export your application logs to share for troubleshooting or you can try to restore your device\n\nWarning: Restoring your device will result in loss of any data older than two weeks";
/* A warning displayed to the user when the application takes too long to launch */
"APP_STARTUP_TIMEOUT" = "The app is taking a long time to start\n\nYou can continue to wait for the app to start, export your application logs to share for troubleshooting or you can try to open the app again";
"APP_STARTUP_TIMEOUT" = "A aplicação está a demorar imenso tempo para iniciar\n\n
Pode continuar a esperar que a aplicação inicie, exportando os seus inícios de sessão de modo a partilhar eventuais erros, ou pode tentar iniciar a aplicação novamente.";
/* The title of a button on a modal shown when the application fails to start, pressing the button closes the application */
"APP_STARTUP_EXIT" = "Exit";
"APP_STARTUP_EXIT" = "Sair";
/* An error which occurs if the user tries to restore the database after an initial failure and it fails to restore */
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"QUOTED_MESSAGE_NOT_FOUND" = "Não foi encontrada a mensagem original.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_SHOW_LESS" = "Mostrar menos";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Pedidos de Mensagem";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Solicitações de mensagens da comunidade";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
@ -613,157 +619,157 @@
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
"MESSAGE_DELIVERY_STATUS_SENDING" = "A enviar";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
"MESSAGE_DELIVERY_STATUS_SENT" = "Enviada";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
"MESSAGE_DELIVERY_STATUS_READ" = "Lida";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
"MESSAGE_DELIVERY_STATUS_FAILED" = "Erro ao enviar";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
"MESSAGE_INFO_SENT" = "Enviada";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
"MESSAGE_INFO_RECEIVED" = "Recebida";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
"MESSAGE_INFO_FROM" = "De";
/* Title of the message information screen describing the identifier of the attachment */
"ATTACHMENT_INFO_FILE_ID" = "File ID";
"ATTACHMENT_INFO_FILE_ID" = "ID do ficheiro";
/* Title of the message information screen describing the file type of the attachment */
"ATTACHMENT_INFO_FILE_TYPE" = "File Type";
"ATTACHMENT_INFO_FILE_TYPE" = "Tipo de ficheiro";
/* Title of the message information screen describing the size of the attachment */
"ATTACHMENT_INFO_FILE_SIZE" = "File Size";
"ATTACHMENT_INFO_FILE_SIZE" = "Tamanho do ficheiro";
/* Title on the message information screen describing the resolution of a media attachment */
"ATTACHMENT_INFO_RESOLUTION" = "Resolution";
/* Title on the message information screen describing the duration of a media attachment */
"ATTACHMENT_INFO_DURATION" = "Duration";
"ATTACHMENT_INFO_DURATION" = "Duração";
/* State of a message after it failed to sync to the current users other devices */
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Failed to sync";
"MESSAGE_DELIVERY_STATUS_FAILED_SYNC" = "Falha ao sincronizar";
/* State of a message while it's in the process of being synced to the users other devices */
"MESSAGE_DELIVERY_STATUS_SYNCING" = "Syncing";
"MESSAGE_DELIVERY_STATUS_SYNCING" = "A sincronizar";
/* Title of the modal that appears after a user taps on the state of a message which failed to send */
"MESSAGE_DELIVERY_FAILED_TITLE" = "Failed to send message";
"MESSAGE_DELIVERY_FAILED_TITLE" = "Erro ao enviar mensagem";
/* Title of the modal that appears after a user taps on the state of a message which failed to sync to the users other devices */
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Falha ao sincronizar a mensagem com os seus outros dispositivos";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
"delete_message_for_me_and_my_devices" = "Eliminar de todos os meus dispositivos";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
"context_menu_resend" = "Enviar novamente";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
"GIPHY_PERMISSION_TITLE" = "Procurar GIFs?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
"GIPHY_PERMISSION_MESSAGE" = "O Session será conectado com o Giphy de modo a fornecer resultados de pesquisa. Os seus dados não serão protegidos de forma completa ao enviar GIFs. ";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
"message_info_title" = "Informações da mensagem";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
"mute_button_text" = "Silenciar";
/* Action in the swipe menu to unmute a conversation */
"unmute_button_text" = "Unmute";
"unmute_button_text" = "Não silenciar";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
"MARK_AS_READ" = "Marcar como lida";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
"MARK_AS_UNREAD" = "Marcar como não lida";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
"leave_group_confirmation_alert_title" = "Sair do grupo";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
"leave_community_confirmation_alert_title" = "Sair da comunidade";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
"leave_community_confirmation_alert_message" = "Tem a certeza que pretende sair %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
"group_you_leaving" = "A sair...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
"group_leave_error" = "Erro ao sair do grupo!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
"group_unable_to_leave" = "Não foi possível sair do grupo, por favor, tente novamente";
/* Title in the confirmation modal to delete a group */
"delete_group_confirmation_alert_title" = "Delete Group";
"delete_group_confirmation_alert_title" = "Eliminar grupo";
/* Message in the confirmation modal to delete a group */
"delete_group_confirmation_alert_message" = "Are you sure you want to delete %@?";
"delete_group_confirmation_alert_message" = "Tem a certeza que pretende eliminar %@?";
/* Title in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_title" = "Delete Conversation";
"delete_conversation_confirmation_alert_title" = "Eliminar conversa";
/* Message in the confirmation modal when the user tries to delete a one-to-one conversation */
"delete_conversation_confirmation_alert_message" = "Are you sure you want to delete your conversation with %@?";
"delete_conversation_confirmation_alert_message" = "Tem a certeza que pretende eliminar a sua conversa com %@?";
/* Title in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_title" = "Hide Note to Self";
/* Message in the confirmation modal when the user tries to hide the 'Note to Self' conversation */
"hide_note_to_self_confirmation_alert_message" = "Are you sure you want to hide %@?";
"hide_note_to_self_confirmation_alert_message" = "Tem a certeza que pretende ocultar %@? ";
/* Title in the modal for updating the users profile display picture */
"update_profile_modal_title" = "Set Display Picture";
"update_profile_modal_title" = "Definir imagem a exibir";
/* Save action in the modal for updating the users profile display picture */
"update_profile_modal_save" = "Save";
"update_profile_modal_save" = "Guardar";
/* Remove action in the modal for updating the users profile display picture */
"update_profile_modal_remove" = "Remove";
"update_profile_modal_remove" = "Eliminar ";
/* Title for the error when failing to remove the users profile display picture */
"update_profile_modal_remove_error_title" = "Unable to remove avatar image";
"update_profile_modal_remove_error_title" = "Não foi possível remover a imagem do avatar";
/* Title for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_title" = "Maximum File Size Exceeded";
"update_profile_modal_max_size_error_title" = "Tamanho máximo do arquivo excedido";
/* Message for the error when the user selects a profile display picture that is too large */
"update_profile_modal_max_size_error_message" = "Please select a smaller photo and try again";
"update_profile_modal_max_size_error_message" = "Por favor, escolha uma fotografia mais pequena e tente novamente";
/* Title for the error when the user fails to update their profile display picture */
"update_profile_modal_error_title" = "Couldn't Update Profile";
"update_profile_modal_error_title" = "Não foi possível atualizar o perfil";
/* Message for the error when the user fails to update their profile display picture */
"update_profile_modal_error_message" = "Please check your internet connection and try again";
"update_profile_modal_error_message" = "Por favor, verifique a sua conexão à Internet e tente novamente.";
/* Placeholder when entering a nickname for a contact */
"CONTACT_NICKNAME_PLACEHOLDER" = "Enter a name";
"CONTACT_NICKNAME_PLACEHOLDER" = "Introduza um nome";
/* The separator within a conversation indicating that following messages are unread */
"UNREAD_MESSAGES" = "Unread Messages";
"UNREAD_MESSAGES" = "Mensagens não lidas";
/* Empty state for a conversation */
"CONVERSATION_EMPTY_STATE" = "You have no messages from %@. Send a message to start the conversation!";
"CONVERSATION_EMPTY_STATE" = "Não possui mensagens de %@. Envie uma mensagem para iniciar a conversa! ";
/* Empty state for a read-only conversation */
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "There are no messages in %@.";
"CONVERSATION_EMPTY_STATE_READ_ONLY" = "Não existem mensagens em %@. ";
/* Empty state for the 'Note to Self' conversation */
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "You have no messages in %@.";
"CONVERSATION_EMPTY_STATE_NOTE_TO_SELF" = "Não possui mensagens em %@. ";
/* Message to indicate a user has Community Message Requests disabled */
"COMMUNITY_MESSAGE_REQUEST_DISABLED_EMPTY_STATE" = "%@ has message requests from Community conversations turned off, so you cannot send them a message.";
@ -781,22 +787,22 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "Esta configuração aplica-se a todos os membros nesta conversa.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "As mensagens desaparecerão após o seu envio.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legado";
/* The description for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_DESCRIPTION" = "Original version of disappearing messages.";
@ -809,16 +815,16 @@
/* DISAPPEARING_MESSAGE_STATE_READ
The point that a message will disappear in a disappearing message update message for disappear after read */
"DISAPPEARING_MESSAGE_STATE_READ" = "read";
"DISAPPEARING_MESSAGE_STATE_READ" = "lida";
/* The point that a message will disappear in a disappearing message update message for disappear after send */
"DISAPPEARING_MESSAGE_STATE_SENT" = "sent";
"DISAPPEARING_MESSAGE_STATE_SENT" = "enviada";
/* The current state for the legacy disappearing messages setting, the '%@' will be replaced by a short-form duration */
"DISAPPERING_MESSAGES_SUMMARY_LEGACY" = "Disappear After - %@";
"DISAPPERING_MESSAGES_SUMMARY_LEGACY" = "Desaparecer após - %@";
/* The current state for the disappear after read setting, the '%@' will be replaced by a short-form duration */
"DISAPPERING_MESSAGES_SUMMARY_READ" = "Disappear After Read - %@";
"DISAPPERING_MESSAGES_SUMMARY_READ" = "Desaparecer após leitura - %@";
/* The current state for the disappear after send setting, the '%@' will be replaced by a short-form duration */
"DISAPPERING_MESSAGES_SUMMARY_SEND" = "Disappear After Send - %@";
@ -833,25 +839,25 @@ The point that a message will disappear in a disappearing message update message
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER_SEND" = "Disappear After Send: %@";
/* An informational message displayed when the name of a group is changed, the '%@' will be the updated name. */
"GROUP_MESSAGE_INFO_NAME_UPDATED_TO" = "Group name is now %@.";
"GROUP_MESSAGE_INFO_NAME_UPDATED_TO" = "O nome do grupo é agora '%@'";
/* An informational message displayed when the name of a group is changed. */
"GROUP_MESSAGE_INFO_NAME_UPDATED" = "Group name updated.";
"GROUP_MESSAGE_INFO_NAME_UPDATED" = "Nome de grupo atualizado. ";
/* An informational message displayed when the display picture of a group is changed. */
"GROUP_MESSAGE_INFO_PICTURE_UPDATED" = "Group display picture updated.";
/* An informational message displayed when a single member joined the group, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ was invited to join the group.";
"GROUP_MESSAGE_INFO_MEMBER_ADDED" = "%@ foi convidado para se juntar ao grupo.";
/* An informational message displayed when two members joined the group, the '%@' will be the names of both members. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ and %@ were invited to join the group.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED" = "%@ e %@ foram convidados para se juntarem ao grupo.";
/* An informational message displayed when multiple members joined the group, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED" = "%@ and %@ others were invited to join the group.";
/* An informational message displayed when a single member was removed from the group, the '%@' will be the members. */
"GROUP_MESSAGE_INFO_MEMBER_REMOVED" = "%@ was removed from the group.";
"GROUP_MESSAGE_INFO_MEMBER_REMOVED" = "%@ foi removido do grupo.";
/* An informational message displayed when two members were removed from the group, the '%@' will be the members names. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_REMOVED" = "%@ and %@ were removed from the group.";
@ -860,19 +866,19 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_REMOVED" = "%@ and %@ others were removed from the group.";
/* An informational message displayed when a member leaves the group. */
"GROUP_MESSAGE_INFO_MEMBER_LEFT" = "%@ left the group.";
"GROUP_MESSAGE_INFO_MEMBER_LEFT" = "%@ saiu do grupo.";
/* An informational message displayed when a member of the group was promoted to admin, the '%@' will be the members name. */
"GROUP_MESSAGE_INFO_MEMBER_PROMOTED" = "%@ was promoted to Admin.";
"GROUP_MESSAGE_INFO_MEMBER_PROMOTED" = "%@ foi promovido a administrador.";
/* An informational message displayed when two members of the group were promoted to admin, the '%@' will be the members names. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_PROMOTED" = "%@ and %@ were promoted to Admin.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_PROMOTED" = "%@ e %@ foram promovidos a administradores. ";
/* An informational message displayed when multiple members of the group were promoted to admin, the first '%@' will be the first members name and the second '%@' will be the number of additional members promoted. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_PROMOTED" = "%@ and %@ others were promoted to Admin.";
/* An informational message displayed the current user was removed from a group, the '%@' will be the name of the group. */
"GROUP_MESSAGE_INFO_REMOVED" = "You were removed from %@.";
"GROUP_MESSAGE_INFO_REMOVED" = "Foi removido de %@. ";
/* Description of a warning prompt when deleting an invitation to join a group conversation. */
"MESSAGE_REQUESTS_GROUP_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this group invite?";
@ -881,10 +887,10 @@ The point that a message will disappear in a disappearing message update message
"MESSAGE_REQUESTS_GROUP_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block %@? Blocked users cannot send you message requests, group invites or call you.";
/* An informational message displayed when the user has been invited to join a group, the first '%@' will be the name of the user that sent the invitation and the second '%@' will be the name of the group. */
"GROUP_MESSAGE_INFO_INVITED" = "%@ invited you to join %@.";
"GROUP_MESSAGE_INFO_INVITED" = "%@ convidou-o a juntar-se a %@.";
/* Message within a conversation indicating the device was unable to delete a group conversation */
"group_unable_to_delete" = "Unable to delete the Group, please try again.";
"group_unable_to_delete" = "Não foi possível eliminar o grupo, por favor, tente novamente. ";
/* Information displayed above the input when opening an invitation to join a group. */
"GROUP_MESSAGE_REQUEST_INFO" = "Sending a message to this group will automatically accept the group invite.";
@ -893,16 +899,16 @@ The point that a message will disappear in a disappearing message update message
"ERROR_UNABLE_TO_FIND_DATA" = "There is an issue retrieving the required data. Please try again later.";
/* A title for the list of group members. */
"GROUP_MEMBERS" = "Group Members";
"GROUP_MEMBERS" = "Membros do grupo";
/* The status for a group member while their invite is being sent. */
"GROUP_MEMBER_STATUS_SENDING" = "Sending invite";
"GROUP_MEMBER_STATUS_SENDING" = "Enviar convite";
/* The status for a group member while their invite is pending. */
"GROUP_MEMBER_STATUS_SENT" = "Invite sent";
"GROUP_MEMBER_STATUS_SENT" = "Convite enviado";
/* The status for a group member if their invitation failed to send. */
"GROUP_MEMBER_STATUS_FAILED" = "Invite failed";
"GROUP_MEMBER_STATUS_FAILED" = "O convite falhou";
/* The status for a group admin while their invite is being sent. */
"GROUP_ADMIN_STATUS_SENDING" = "Sending admin promotion";
@ -923,52 +929,52 @@ The point that a message will disappear in a disappearing message update message
"EDIT_DISPLAY_PICTURE_ERROR_REMOVE" = "Unable to remove display picture.";
/* Placeholder text for editing the name of a group. */
"EDIT_GROUP_NAME_PLACEHOLDER" = "Enter group name";
"EDIT_GROUP_NAME_PLACEHOLDER" = "Introduzir nome do grupo";
/* Error message when the edited name of a group is empty. */
"EDIT_GROUP_NAME_ERROR_MISSING" = "Please pick a group name.";
"EDIT_GROUP_NAME_ERROR_MISSING" = "Por favor, escolha um nome para o grupo.";
/* Error message when the edited name of a group is too long. */
"EDIT_GROUP_NAME_ERROR_LONG" = "Please pick a shorter group name.";
/* Placeholder text for editing the description of a group. */
"EDIT_GROUP_DESCRIPTION_PLACEHOLDER" = "Enter group description";
"EDIT_GROUP_DESCRIPTION_PLACEHOLDER" = "Inserir descrição do grupo";
/* Error message when the edited description of a group is too long. */
"EDIT_GROUP_DESCRIPTION_ERROR_LONG" = "Please pick a shorter group description.";
/* Error message when the user attempts to remove an admin from a group. */
"EDIT_GROUP_MEMBERS_ERROR_REMOVE_ADMIN" = "Admins cannot be removed";
"EDIT_GROUP_MEMBERS_ERROR_REMOVE_ADMIN" = "Administradores não podem ser removidos.";
/* A title for the button to send invites for members to join groups. */
"GROUP_ACTION_INVITE" = "Invite";
"GROUP_ACTION_INVITE" = "Convidar";
/* A title for the button to send invites to contacts to join groups. */
"GROUP_ACTION_INVITE_CONTACTS" = "Invite Contacts";
"GROUP_ACTION_INVITE_CONTACTS" = "Convidar contactos";
/* Text which appears when all of the users contacts are already part of the group they want to invite contacts to. */
"GROUP_ACTION_INVITE_EMPTY_STATE" = "You don't have any more contacts.";
"GROUP_ACTION_INVITE_EMPTY_STATE" = "Não possui mais contactos. ";
/* A toast which indicates that a single invitation to join the group is being sent. */
"GROUP_ACTION_INVITE_SENDING" = "Sending invite";
"GROUP_ACTION_INVITE_SENDING" = "Enviar convite";
/* A toast which indicates that multiple invitations to join the group are being sent. */
"GROUP_ACTION_INVITE_SENDING_MULTIPLE" = "Sending invites";
"GROUP_ACTION_INVITE_SENDING_MULTIPLE" = "Enviar convites";
/* A toast which indicates that a single invitation to join a group failed to send, the first '%@' will be the name of the member that couldn't be invited and the second '%@' will be the name of the group. */
"GROUP_ACTION_INVITE_FAILED_ONE" = "Failed to invite %@ to %@";
"GROUP_ACTION_INVITE_FAILED_ONE" = "Falha ao convidar %@ para %@";
/* A toast which indicates that two invitation to join a group failed to send, the first '%@' will be the name of the first member that couldn't be invited, the second '%@' will be the name of the second member that couldn't be invited, and the third '%@' will be the name of the group. */
"GROUP_ACTION_INVITE_FAILED_TWO" = "Failed to invite %@ and %@ to %@";
"GROUP_ACTION_INVITE_FAILED_TWO" = "Falha ao convidar %@ e %@ para %@";
/* A toast which indicates multiple invitations to join a group failed to send, the first '%@' will be the name of the first member that couldn't be invited, the second '%@' will be the number of other members that couldn't be invited, and the third '%@' will be the name of the group. */
"GROUP_ACTION_INVITE_FAILED_MULTIPLE" = "Failed to invite %@ and %@ others to %@";
/* A title for the screen to select which group members should receive promotions to admin. */
"GROUP_ACTION_PROMOTE_ADMINS" = "Promote Admins";
"GROUP_ACTION_PROMOTE_ADMINS" = "Promover administradores";
/* A title for the button to send promotions to members of a group. */
"GROUP_ACTION_PROMOTE" = "Promote";
"GROUP_ACTION_PROMOTE" = "Promover";
/* Text which appears when all of the members of a group are already admins. */
"GROUP_ACTION_PROMOTE_EMPTY_STATE" = "There are no more members in this group.";
@ -992,19 +998,19 @@ The point that a message will disappear in a disappearing message update message
"LEGACY_GROUPS_DEPRECATED_BANNER" = "Groups have been upgraded, create a new group to upgrade. Old group functionality will be degraded from %@.";
/* Title for the prompt which appears when editing the group name and description. */
"EDIT_GROUP_INFO_TITLE" = "Update Group Information";
"EDIT_GROUP_INFO_TITLE" = "Atualizar informações do grupo";
/* Message for the prompt which appears when editing the group name and description. */
"EDIT_GROUP_INFO_MESSAGE" = "Group name and description is visible to all group members.";
/* Title for the prompt which appears when editing a legacy group name. */
"EDIT_LEGACY_GROUP_INFO_TITLE" = "Update Group Name";
"EDIT_LEGACY_GROUP_INFO_TITLE" = "Atualizar nome do grupo";
/* Message for the prompt which appears when editing a legacy group name. */
"EDIT_LEGACY_GROUP_INFO_MESSAGE" = "Group name is visible to all group members.";
"EDIT_LEGACY_GROUP_INFO_MESSAGE" = "O nome do grupo está visível para todos os membros.";
/* An informational message displayed when the user has been invited to join a group, the '%@' will be the name of the group. */
"GROUP_MESSAGE_INFO_INVITED_FALLBACK" = "You were invited to join %@.";
"GROUP_MESSAGE_INFO_INVITED_FALLBACK" = "Foi convidado a juntar-se a %@.";
/* An informational message displayed when the current user joined the group, the '%@' will be replaced with 'You'. */
"GROUP_MESSAGE_INFO_MEMBER_ADDED_YOU" = "%@ were invited to join the group.";
@ -1019,19 +1025,37 @@ The point that a message will disappear in a disappearing message update message
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
/* An informational message displayed when the current user and one other user joined the group, the first '%@' will be 'You' and the second will be the name of the other member. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU" = "%@ and %@ were invited to join the group.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU" = "%@ e %@ foram convidados para se juntarem ao grupo.";
/* An informational message displayed when the current user and one other user joined the group with access to chat history, the first '%@' will be 'You' and the second will be the name of the other member. */
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_TWO_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ e %@ foram convidados a participar no grupo. O histórico de conversas foi partilhado.";
/* An informational message displayed when multiple members joined the group with access to chat history, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_WITH_HISTORY" = "%@ and %@ were invited to join the group. Chat history was shared.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_WITH_HISTORY" = "%@ e %@ foram convidados a participar do grupo. O histórico de conversas foi partilhado.";
/* An informational message displayed when the current user and multiple other users joined the group, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU" = "%@ and %@ others were invited to join the group.";
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU" = "%@ e %@ outros foram convidados para se juntarem ao grupo.";
/* An informational message displayed when the current user and multiple other users joined the group with access to chat history, the first '%@' will be the first members name and the second '%@' will be the number of additional members added. */
"GROUP_MESSAGE_INFO_MULTIPLE_MEMBERS_ADDED_YOU_WITH_HISTORY" = "%@ and %@ others were invited to join the group. Chat history was shared.";
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirmar";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -175,9 +175,9 @@
/* alert title */
"PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA" = "Nu am putut configura camera.";
/* label for system photo collections which have no name. */
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Album fara nume";
"PHOTO_PICKER_UNNAMED_COLLECTION" = "Album fără Nume";
/* Notification action button title */
"PUSH_MANAGER_MARKREAD" = "Marchează ca și citit";
"PUSH_MANAGER_MARKREAD" = "Marchează ca Citit";
/* Notification action button title */
"PUSH_MANAGER_REPLY" = "Răspunde";
/* Description of how and why Session iOS uses Touch ID/Face ID/Phone Passcode to unlock 'screen lock'. */
@ -311,7 +311,7 @@
"vc_qr_code_view_my_qr_code_tab_title" = "Vizualizați codul QR";
"vc_qr_code_view_scan_qr_code_tab_title" = "Scanați codul QR";
"vc_qr_code_view_scan_qr_code_explanation" = "Scanează codul QR al cuiva pentru a începe o conversație cu ei";
"vc_view_my_qr_code_explanation" = "Acesta este codul tău QR. Ceilalți utilizatori îl pot scana ca să înceapă o Sessiune cu tine.";
"vc_view_my_qr_code_explanation" = "Acesta este codul tău QR. Ceilalți utilizatori îl pot scana ca să înceapă o sesiune cu tine.";
// MARK: - Not Yet Translated
"fast_mode_explanation" = "Vei fi notificat în legătură cu noile mesaje imediat prin serverele de încredere Apple pentru notificări.";
"fast_mode" = "Modul rapid";
@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Cereri de mesaj";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Nici o cerere de mesaje în așteptare";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Șterge Toate";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Sunteţi sigur că doriţi să ştergeţi toate solicitările de mesaje?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Ești sigur că vrei să ștergi toate cererile de mesaje și invitațiile de grup?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Sterge";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Sunteţi sigur că doriţi să ştergeţi această solicitare de mesaj?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Ești sigur că vrei să blochezi acest contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "bibliotecă";
"DISAPPEARING_MESSAGES_OFF" = "Dezactivat";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Dezactivat";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Dispar după: %@";
"COPY_GROUP_URL" = "Copiază URL-ul grupului";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacte";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Te rugăm să alegi cel puțin un membru al grupului";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Setează";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Această setare se aplică tuturor celor din această conversație.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Această setare se aplică tuturor celor din această conversație. Numai administratorii de grup pot schimba această setare.";
"DISAPPERING_MESSAGES_SUMMARY" = "Dispare după %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ a setat mesaje pentru a dispărea %@ după ce au fost %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ a schimbat mesajele pentru a dispărea %@ după ce au fost %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ a dezactivat mesajele care dispar";
/* context_menu_info */
@ -595,13 +595,13 @@
"DATABASE_RESTORE_FAILED" = "An error occurred when opening the restored database\n\nYou can export your application logs to share for troubleshooting but to continue to use Session you may need to reinstall";
/* Text displayed in place of a quoted message when the original message is not on the device */
"QUOTED_MESSAGE_NOT_FOUND" = "Original message not found.";
"QUOTED_MESSAGE_NOT_FOUND" = "Mesajul original nu a fost găsit.";
/* EMOJI_REACTS_SHOW_LESS */
"EMOJI_REACTS_SHOW_LESS" = "Show less";
"EMOJI_REACTS_SHOW_LESS" = "Arată mai puțin";
/* PRIVACY_SECTION_MESSAGE_REQUESTS */
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Message Requests";
"PRIVACY_SECTION_MESSAGE_REQUESTS" = "Cereri de Mesaje";
/* PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE */
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_TITLE" = "Community Message Requests";
@ -610,25 +610,25 @@
"PRIVACY_SCREEN_MESSAGE_REQUESTS_COMMUNITY_DESCRIPTION" = "Allow message requests from Community conversations.";
/* Information displayed above the input when sending a message to a new user for the first time explaining limitations around the types of messages which can be sent before being approved */
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request";
"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "Veți putea trimite mesaje vocale și atașamente după ce destinatarul a aprobat cererea de mesaj";
/* State of a message while it's still in the process of being sent */
"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending";
"MESSAGE_DELIVERY_STATUS_SENDING" = "Se trimite";
/* State of a message once it has been sent */
"MESSAGE_DELIVERY_STATUS_SENT" = "Sent";
"MESSAGE_DELIVERY_STATUS_SENT" = "Trimis";
/* State of a message after the recipient has read the message */
"MESSAGE_DELIVERY_STATUS_READ" = "Read";
"MESSAGE_DELIVERY_STATUS_READ" = "Citit";
/* State of a message if it failed to be sent */
"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send";
"MESSAGE_DELIVERY_STATUS_FAILED" = "Trimitere eșuată";
/* Title of the message information screen describing the date/time a message was sent */
"MESSAGE_INFO_SENT" = "Sent";
"MESSAGE_INFO_SENT" = "Trimis";
/* Title of the message information screen describing the date/time a message was received on a specific device */
"MESSAGE_INFO_RECEIVED" = "Received";
"MESSAGE_INFO_RECEIVED" = "Primit";
/* Title of the message information screen describing the sender of the message */
"MESSAGE_INFO_FROM" = "From";
@ -661,22 +661,22 @@
"MESSAGE_DELIVERY_FAILED_SYNC_TITLE" = "Failed to sync message to your other devices";
/* Action for the modal shown when asking the user whether they want to delete from all of their devices */
"delete_message_for_me_and_my_devices" = "Delete from all of my devices";
"delete_message_for_me_and_my_devices" = "Șterge de pe toate dispozitivele mele";
/* Action in the long-press menu to trigger a message to be sent again after it has failed */
"context_menu_resend" = "Resend";
"context_menu_resend" = "Retrimite";
/* Action in the long-press menu to trigger a message to be synced again after it has failed */
"context_menu_resync" = "Resync";
"context_menu_resync" = "Resincronizează";
/* Title of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_TITLE" = "Search GIFs?";
"GIPHY_PERMISSION_TITLE" = "Caută GIF-uri?";
/* Message of a modal show the first time a user tries to search for GIFs */
"GIPHY_PERMISSION_MESSAGE" = "Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.";
"GIPHY_PERMISSION_MESSAGE" = "Session se va conecta la Giphy pentru a obține rezultate la căutare. Dvs. nu veți avea acces la protecția completă a metadatelor când trimiteți GIF-uri.";
/* Action in the long-press menu to view more information about a specific message */
"message_info_title" = "Message Info";
"message_info_title" = "Despre Mesaj";
/* Action to mute a conversation in the swipe menu */
"mute_button_text" = "Mute";
@ -685,25 +685,25 @@
"unmute_button_text" = "Unmute";
/* Action in the swipe menu to mark a conversation as read */
"MARK_AS_READ" = "Mark read";
"MARK_AS_READ" = "Marchează ca citit";
/* Action in the swipe menu to mark a conversation as unread */
"MARK_AS_UNREAD" = "Mark unread";
"MARK_AS_UNREAD" = "Marchează ca necitit";
/* Title of the confirmation modal show when attempting to leave a group conversation */
"leave_group_confirmation_alert_title" = "Leave Group";
"leave_group_confirmation_alert_title" = "Părăsește Grupul";
/* Title of the confirmation modal show when attempting to leave a community conversation */
"leave_community_confirmation_alert_title" = "Leave Community";
"leave_community_confirmation_alert_title" = "Părăsește Comunitatea";
/* Message in the confirmation modal when leaving a community conversation */
"leave_community_confirmation_alert_message" = "Are you sure you want to leave %@?";
"leave_community_confirmation_alert_message" = "Ești sigur ca vrei sa părăsești %@?";
/* Conversation subtitle while the user in the process of leaving */
"group_you_leaving" = "Leaving...";
/* Conversation subtitle if the user in the failed to leave */
"group_leave_error" = "Failed to leave Group!";
"group_leave_error" = "Părăsire a Grupului eșuată!";
/* Message within a conversation indicating the device was unable to leave a group conversation */
"group_unable_to_leave" = "Unable to leave the Group, please try again";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Запросы Сообщений";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Нет ожидающих запросов";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Очистить всё";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Вы уверены, что хотите очистить все запросы сообщений?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Очистить";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Вы уверены, что хотите удалить это сообщение?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Вы уверены, что хотите заблокировать контакт?";
@ -548,7 +548,6 @@
"modal_permission_library" = "библиотека";
"DISAPPEARING_MESSAGES_OFF" = "Выключено";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Выключено";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Удалить через: %@";
"COPY_GROUP_URL" = "Скопировать URL-адрес группы";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Контакты";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Пожалуйста, выберите как минимум 1 участника группы";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Задать";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Эта настройка применяется ко всем участникам беседы.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Этот параметр применим ко всем в этой беседе. Только администраторы групп могут изменить этот параметр.";
"DISAPPERING_MESSAGES_SUMMARY" = "Удалить через %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ поставил сообщения на удаление %@ после того, как они были %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ изменил сообщения, чтобы они удалялись %@ после того, как они были %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ отключил удаление сообщений";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "පණිවිඩ ඉල්ලීම්";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "පොරොත්තු පණිවිඩ ඉල්ලීම් නැත";
"MESSAGE_REQUESTS_CLEAR_ALL" = "සියල්ල හිස් කරන්න";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "ඔබට සියලු පණිවිඩ ඉල්ලීම් ඉවත් කිරීමට අවශ්‍ය බව විශ්වාසද?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "පැහැදිලිව";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "ඔබට මෙම පණිවිඩ ඉල්ලීම මැකීමට අවශ්‍ය බව විශ්වාසද?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Žiadosti o správu";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Žiadne prebiehajúce žiadosti o správu";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Vymazať Všetko";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Naozaj chcete vymazať všetky žiadosti o správu?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Vymazať";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Naozaj chcete vymazať túto žiadosť o správu?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Ste si istí, že chcete tento kontakt zablokovať?";
@ -548,7 +548,6 @@
"modal_permission_library" = "knižnica";
"DISAPPEARING_MESSAGES_OFF" = "Vypnuté";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Vypnuté";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Zmiznutie po: %@";
"COPY_GROUP_URL" = "Kopírovať URL skupiny";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontakty";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Prosím vyberte aspoň 1 člena skupiny";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Nastaviť";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Toto nastavenie sa týka všetkých účastníkov v tejto konverzácii.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Toto nastavenie sa týka všetkých účastníkov v tejto konverzácii. Toto nastavenie môžu zmeniť iba správcovia skupiny.";
"DISAPPERING_MESSAGES_SUMMARY" = "Zmiznutie po %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ nastavil/a správy tak, aby zmizli %@ po ich %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ zmenil/a správy tak, aby zmizli %@ po tom, čo boli %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ vypol/a miznúce správy";
/* context_menu_info */
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Meddelandeförfrågningar";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Inga väntande meddelandeförfrågningar";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Rensa alla";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Är du säker på att du vill rensa alla meddelandeförfrågningar?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Rensa";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Är du säker på att du vill radera denna meddelandeförfrågan?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Är du säker på att du vill blockera denna kontakt?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Kopiera gruppens URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Kontakter";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Välj minst 1 gruppmedlem";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Запити на повідомлення";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "Немає незавершених запитів на повідомлення";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Очистити всі";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Ви впевнені, що бажаєте очистити всі запити на повідомлення?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Очистити";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Ви дійсно бажаєте видалити цей запит?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Ви дійсно хочете заблокувати цей контакт?";
@ -548,7 +548,6 @@
"modal_permission_library" = "бібліотеки";
"DISAPPEARING_MESSAGES_OFF" = "Вимк.";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Вимк.";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Зникнення після: %@";
"COPY_GROUP_URL" = "Скопіювати URL групи";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Контакти";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Будь ласка, виберіть принаймні 1 учасника групи";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Встановити";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "Цей параметр застосовується до всіх в цій розмові.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "Це налаштування застосовується до всіх в цій розмові. Тільки адміністратори групи можуть змінити це налаштування.";
"DISAPPERING_MESSAGES_SUMMARY" = "Зникнення після %@ - %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ встановив, що повідомлення зникатимуть через %@ після того, як вони були %@";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ змінив строк зникнення повідомлень, тепер повідомлення зникатимуть через %@ після того, як вони були %@";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ вимкнув зникнення повідомлень";
/* context_menu_info */
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "Message Requests";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "No pending message requests";
"MESSAGE_REQUESTS_CLEAR_ALL" = "Clear All";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "Are you sure you want to block this contact?";
@ -548,7 +548,6 @@
"modal_permission_library" = "library";
"DISAPPEARING_MESSAGES_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "Off";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "Contacts";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "Set";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "消息请求";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "没有待处理的消息请求";
"MESSAGE_REQUESTS_CLEAR_ALL" = "清除所有";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "您确定要清除所有消息请求吗?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "您确定要清除所有消息请求和群组邀请吗?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "清除";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "您确定要删除此消息请求吗?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "您确定要屏蔽该联系人吗?";
@ -548,7 +548,6 @@
"modal_permission_library" = "媒体库";
"DISAPPEARING_MESSAGES_OFF" = "关闭";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "关闭";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "%@后消失";
"COPY_GROUP_URL" = "复制群组链接";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "联系人";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "请至少选择一名群组成员";
@ -574,9 +573,10 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "会话设置";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "此设置适用于此对话中的所有人。";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "此设置适用于此对话中的所有人。只有群组管理员可以更改此设置。";
"DISAPPERING_MESSAGES_SUMMARY" = "在 %@ - %@ 后消失。";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@已设置%@消息在被%@后消失";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@已改变消息%@在被%@后消失";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ 关闭了阅后即焚消息";
/* context_menu_info */
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -393,7 +393,7 @@
"MESSAGE_REQUESTS_TITLE" = "訊息要求";
"MESSAGE_REQUESTS_EMPTY_TEXT" = "沒有擱置中的訊息要求";
"MESSAGE_REQUESTS_CLEAR_ALL" = "全部清除";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "您確定要清除所有訊息要求嗎?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests and group invites?";
"MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "清除";
"MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "您確定要刪除這則訊息要求嗎?";
"MESSAGE_REQUESTS_BLOCK_CONFIRMATION_ACTON" = "您確定要封鎖此聯絡人?";
@ -548,7 +548,6 @@
"modal_permission_library" = "資料庫";
"DISAPPEARING_MESSAGES_OFF" = "關閉";
"DISAPPEARING_MESSAGES_SUBTITLE_OFF" = "關閉";
"DISAPPEARING_MESSAGES_SUBTITLE_DISAPPEAR_AFTER" = "Disappear After: %@";
"COPY_GROUP_URL" = "Copy Group URL";
"NEW_CONVERSATION_CONTACTS_SECTION_TITLE" = "聯絡人";
"GROUP_ERROR_NO_MEMBER_SELECTION" = "Please pick at least 1 group member";
@ -574,10 +573,11 @@
"DISAPPERING_MESSAGES_SAVE_TITLE" = "設定";
"DISAPPERING_MESSAGES_GROUP_WARNING" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_GROUP_WARNING_ADMIN_ONLY" = "This setting applies to everyone in this conversation.\nOnly group admins can change this setting.";
"DISAPPERING_MESSAGES_SUMMARY" = "Disappear After %@ - %@";
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set messages to disappear %@ after they have been %@";
/* Informational message shown when a conversation participant enables disappearing messages. The first '%@' will be the participants name, the second '%@' will be the duration and the third '%@' will indicate whether the countdown should start after the messages are sent or after they are read. */
"DISAPPERING_MESSAGES_INFO_ENABLE" = "%@ has set their messages to disappear %@ after they have been %@.";
"DISAPPERING_MESSAGES_INFO_UPDATE" = "%@ has changed messages to disappear %@ after they have been %@";
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages";
/* Informational message shown when a conversation participant enables disappearing messages. The '%@' will be the participants name. */
"DISAPPERING_MESSAGES_INFO_DISABLE" = "%@ has turned off disappearing messages. Messages they send will no longer disappear.";
/* context_menu_info */
"context_menu_info" = "Info";
@ -781,19 +781,19 @@
"database_inaccessible_error" = "There is an issue opening the database. Please restart the app and try again.";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation */
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to everyone in this conversation.";
"DISAPPERING_MESSAGES_SUBTITLE_CONTACTS" = "This setting applies to messages you send in this conversation.";
/* A message indicating how the disappearing messages setting applies in a group conversation */
"DISAPPERING_MESSAGES_SUBTITLE_GROUPS" = "Messages disappear after they have been sent.";
/* A record that appears within the message history to indicate that the current user turned on disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@";
"YOU_DISAPPEARING_MESSAGES_INFO_ENABLE" = "You set your messages to disappear %@ after they have been %@.";
/* A record that appears within the message history to indicate that the current user update the disappearing messages setting */
"YOU_DISAPPEARING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@";
/* A record that appears within the message history to indicate that the current user has disabled disappearing messages */
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages";
"YOU_DISAPPEARING_MESSAGES_INFO_DISABLE" = "You turned off disappearing messages. Messages you send will no longer disappear.";
/* The title for the legacy type of disappearing messages on the disappearing messages configuration screen */
"DISAPPEARING_MESSAGES_TYPE_LEGACY_TITLE" = "Legacy";
@ -1035,3 +1035,21 @@ The point that a message will disappear in a disappearing message update message
/* Message for the error modal shown when a voice message fails to start recording. */
"VOICE_MESSAGE_FAILED_TO_START_MESSAGE" = "An error occurred when trying to start recording for the voice message.";
/* Shortcut to copy the disappearing messages setting from another conversation participant. */
"FOLLOW_SETTING_TITLE" = "Follow Setting";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages on. The first '%@' will be the duration messages will remain and the second '%@' will be whether the countdown starts after the messages are sent or after they are read. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_ON" = "Set your messages to disappear %@ after they have been %@?";
/* Explanation when following the disappearing messages setting from another conversation participant will turn disappearing messages off. */
"FOLLOW_SETTING_EXPLAINATION_TURNING_OFF" = "Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?";
/* Title for button on a modal which confirms a change. */
"CONFIRM_BUTTON_TITLE" = "Confirm";
/* The subtitle of delete action in long press menu screen indicating the time that a message will disappear */
"DISAPPEARING_MESSAGES_AUTO_DELETES_COUNT_DOWN" = "Auto-deletes in %@";
/* A message indicating how the disappearing messages setting applies in a one-to-one conversation for legacy mode */
"DISAPPERING_MESSAGES_SUBTITLE_LEGACY" = "This setting applies to everyone in this conversation.";

@ -514,13 +514,7 @@ class NotificationActionHandler {
variant: .standardOutgoing,
body: replyText,
timestampMs: SnodeAPI.currentOffsetTimestampMs(),
hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: replyText),
expiresInSeconds: try? DisappearingMessagesConfiguration
.select(.durationSeconds)
.filter(id: threadId)
.filter(DisappearingMessagesConfiguration.Columns.isEnabled == true)
.asRequest(of: TimeInterval.self)
.fetchOne(db)
hasMention: Interaction.isUserMentioned(db, threadId: threadId, body: replyText)
).inserted(db)
try Interaction.markAsRead(

@ -315,7 +315,10 @@ public enum PushRegistrationError: Error {
variant: .infoCall,
body: messageInfoString,
timestampMs: timestampMs
).inserted(db)
)
.withDisappearingMessagesConfiguration(db)
.inserted(db)
call.callInteractionId = interaction.id
return call

@ -30,7 +30,7 @@ enum Onboarding {
_ requestId: UUID,
using dependencies: Dependencies = Dependencies()
) -> AnyPublisher<String?, Error> {
let userPublicKey: String = getUserHexEncodedPublicKey()
let userPublicKey: String = getUserHexEncodedPublicKey(using: dependencies)
return SnodeAPI.getSwarm(for: userPublicKey)
.tryFlatMapWithRandomSnode { snode -> AnyPublisher<Void, Error> in

@ -1,6 +1,8 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import Combine
import GRDB
import SessionUIKit
import SessionSnodeKit
import SessionMessagingKit
@ -165,8 +167,34 @@ final class NukeDataModal: Modal {
private func clearEntireAccount(presentedViewController: UIViewController) {
ModalActivityIndicatorViewController
.present(fromViewController: presentedViewController, canCancel: false) { [weak self] _ in
SnodeAPI.deleteAllMessages(namespace: .all)
Publishers
.MergeMany(
Storage.shared
.read { db -> [(String, OpenGroupAPI.PreparedSendData<OpenGroupAPI.DeleteInboxResponse>)] in
return try OpenGroup
.filter(OpenGroup.Columns.isActive == true)
.select(.server)
.distinct()
.asRequest(of: String.self)
.fetchSet(db)
.map { ($0, try OpenGroupAPI.preparedClearInbox(db, on: $0))}
}
.defaulting(to: [])
.compactMap { server, data in
OpenGroupAPI
.send(data: data)
.map { _ in [server: true] }
.eraseToAnyPublisher()
}
)
.collect()
.subscribe(on: DispatchQueue.global(qos: .userInitiated))
.flatMap { results in
SnodeAPI
.deleteAllMessages(namespace: .all)
.map { results.reduce($0) { result, next in result.updated(with: next) } }
.eraseToAnyPublisher()
}
.receive(on: DispatchQueue.main)
.sinkUntilComplete(
receiveCompletion: { result in
@ -174,7 +202,7 @@ final class NukeDataModal: Modal {
case .finished: break
case .failure(let error):
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
let modal: ConfirmationModal = ConfirmationModal(
targetView: self?.view,
info: ConfirmationModal.Info(
@ -189,33 +217,34 @@ final class NukeDataModal: Modal {
},
receiveValue: { confirmations in
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
let potentiallyMaliciousSnodes = confirmations
.compactMap { ($0.value == false ? $0.key : nil) }
if potentiallyMaliciousSnodes.isEmpty {
guard !potentiallyMaliciousSnodes.isEmpty else {
self?.deleteAllLocalData()
return
}
let message: String
if potentiallyMaliciousSnodes.count == 1 {
message = String(format: "dialog_clear_all_data_deletion_failed_1".localized(), potentiallyMaliciousSnodes[0])
}
else {
let message: String
if potentiallyMaliciousSnodes.count == 1 {
message = String(format: "dialog_clear_all_data_deletion_failed_1".localized(), potentiallyMaliciousSnodes[0])
}
else {
message = String(format: "dialog_clear_all_data_deletion_failed_2".localized(), String(potentiallyMaliciousSnodes.count), potentiallyMaliciousSnodes.joined(separator: ", "))
}
let modal: ConfirmationModal = ConfirmationModal(
targetView: self?.view,
info: ConfirmationModal.Info(
title: "ALERT_ERROR_TITLE".localized(),
body: .text(message),
cancelTitle: "BUTTON_OK".localized(),
cancelStyle: .alert_text
)
)
self?.present(modal, animated: true)
message = String(format: "dialog_clear_all_data_deletion_failed_2".localized(), String(potentiallyMaliciousSnodes.count), potentiallyMaliciousSnodes.joined(separator: ", "))
}
let modal: ConfirmationModal = ConfirmationModal(
targetView: self?.view,
info: ConfirmationModal.Info(
title: "ALERT_ERROR_TITLE".localized(),
body: .text(message),
cancelTitle: "BUTTON_OK".localized(),
cancelStyle: .alert_text
)
)
self?.present(modal, animated: true)
}
)
}

@ -71,7 +71,7 @@ class PrivacySettingsViewModel: SessionTableViewModel, NavigationItemSource, Nav
image: UIImage(named: "X")?
.withRenderingMode(.alwaysTemplate),
style: .plain,
accessibilityIdentifier: "Close Button"
accessibilityIdentifier: "Close button"
) { [weak self] in self?.dismissScreen() }
]
)

@ -0,0 +1,21 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SwiftUI
struct BezierPath: Shape {
let bezierPath: UIBezierPath
func path(in rect: CGRect) -> Path {
let path = Path(bezierPath.cgPath)
// Figure out how much bigger we need to make our path in order for it to fill the available space without clipping.
let multiplier = min(rect.width, rect.height)
// Create an affine transform that uses the multiplier for both dimensions equally.
let transform = CGAffineTransform(scaleX: multiplier, y: multiplier)
// Apply that scale and send back the result.
return path.applying(transform)
}
}

@ -31,6 +31,8 @@ class SessionTableViewController<ViewModel>: BaseVC, UITableViewDataSource, UITa
// MARK: - Components
private lazy var titleView: SessionTableViewTitleView = SessionTableViewTitleView()
private lazy var tableView: UITableView = {
let result: UITableView = UITableView()
result.translatesAutoresizingMaskIntoConstraints = false
@ -41,6 +43,7 @@ class SessionTableViewController<ViewModel>: BaseVC, UITableViewDataSource, UITa
result.register(view: SessionCell.self)
result.register(view: FullConversationCell.self)
result.registerHeaderFooterView(view: SessionHeaderView.self)
result.registerHeaderFooterView(view: SessionFooterView.self)
result.dataSource = self
result.delegate = self
@ -125,11 +128,8 @@ class SessionTableViewController<ViewModel>: BaseVC, UITableViewDataSource, UITa
override func viewDidLoad() {
super.viewDidLoad()
ViewControllerUtilities.setUpDefaultSessionStyle(
for: self,
title: viewModel.title,
hasCustomBackButton: false
)
navigationItem.titleView = titleView
titleView.update(title: self.viewModel.title, subtitle: self.viewModel.subtitle)
view.themeBackgroundColor = .backgroundPrimary
view.addSubview(tableView)
@ -394,6 +394,7 @@ class SessionTableViewController<ViewModel>: BaseVC, UITableViewDataSource, UITa
self?.footerButton.setTitle(buttonInfo.title, for: .normal)
self?.footerButton.setStyle(buttonInfo.style)
self?.footerButton.isEnabled = buttonInfo.isEnabled
self?.footerButton.set(.width, greaterThanOrEqualTo: buttonInfo.minWidth)
self?.footerButton.accessibilityIdentifier = buttonInfo.accessibility?.identifier
self?.footerButton.accessibilityLabel = buttonInfo.accessibility?.label
}
@ -478,12 +479,31 @@ class SessionTableViewController<ViewModel>: BaseVC, UITableViewDataSource, UITa
return result
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let section: SectionModel = viewModel.tableData[section]
if let footerString = section.model.footer {
let result: SessionFooterView = tableView.dequeueHeaderFooterView(type: SessionFooterView.self)
result.update(title: footerString)
return result
}
return UIView()
}
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return viewModel.tableData[section].model.style.height
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
let section: SectionModel = viewModel.tableData[section]
return (section.model.footer == nil ? 0 : UITableView.automaticDimension)
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}

@ -0,0 +1,104 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
final class SessionTableViewTitleView: UIView {
private static let maxWidth: CGFloat = UIScreen.main.bounds.width - 44 * 2 - 16 * 2
private var oldSize: CGSize = .zero
override var frame: CGRect {
set(newValue) {
super.frame = newValue
if let superview = self.superview {
self.center = CGPoint(x: superview.center.x, y: self.center.y)
}
}
get {
return super.frame
}
}
// MARK: - UI Components
private lazy var titleLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
result.themeTextColor = .textPrimary
result.lineBreakMode = .byTruncatingTail
return result
}()
private lazy var subtitleLabel: UILabel = {
let result: UILabel = UILabel()
result.font = .systemFont(ofSize: Values.miniFontSize)
result.themeTextColor = .textPrimary
result.lineBreakMode = .byWordWrapping
result.numberOfLines = 0
result.textAlignment = .center
result.set(.width, lessThanOrEqualTo: Self.maxWidth)
return result
}()
private lazy var stackView: UIStackView = {
let result = UIStackView(arrangedSubviews: [ titleLabel, subtitleLabel ])
result.axis = .vertical
result.alignment = .center
return result
}()
private lazy var subtitleLabelHeightConstraint: NSLayoutConstraint = subtitleLabel.set(.height, to: 0)
// MARK: - Initialization
init() {
super.init(frame: .zero)
addSubview(stackView)
stackView.pin([ UIView.HorizontalEdge.trailing, UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: self)
stackView.pin(.leading, to: .leading, of: self, withInset: 0)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
required init?(coder: NSCoder) {
preconditionFailure("Use init() instead.")
}
// MARK: - Content
public func update(title: String, subtitle: String?) {
guard Thread.isMainThread else {
DispatchQueue.main.async { [weak self] in
self?.update(title: title, subtitle: subtitle)
}
return
}
self.titleLabel.text = title
self.titleLabel.font = .boldSystemFont(
ofSize: (subtitle?.isEmpty == false ?
Values.largeFontSize :
Values.veryLargeFontSize
)
)
if let subtitle: String = subtitle {
subtitleLabelHeightConstraint.constant = subtitle.heightWithConstrainedWidth(width: Self.maxWidth, font: self.subtitleLabel.font)
self.subtitleLabel.text = subtitle
self.subtitleLabel.isHidden = false
} else {
self.subtitleLabel.isHidden = true
}
}
}

@ -379,6 +379,16 @@ extension SessionCell {
case .radio(let size, let isSelectedRetriever, let storedSelection, let accessibility):
let isSelected: Bool = isSelectedRetriever()
let wasOldSelection: Bool = (!isSelected && storedSelection)
radioView.isAccessibilityElement = true
if isSelected || wasOldSelection {
radioView.accessibilityTraits.insert(.selected)
radioView.accessibilityValue = "selected"
} else {
radioView.accessibilityTraits.remove(.selected)
radioView.accessibilityValue = nil
}
radioBorderView.isHidden = false
radioBorderView.themeBorderColor = {

@ -122,6 +122,7 @@ public class SessionCell: UITableViewCell {
let result: SRCopyableLabel = SRCopyableLabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.isUserInteractionEnabled = false
result.font = .systemFont(ofSize: 12)
result.themeTextColor = .textPrimary
result.numberOfLines = 0
result.isHidden = true

@ -0,0 +1,89 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import SessionUIKit
class SessionFooterView: UITableViewHeaderFooterView {
private lazy var emptyHeightConstraint: NSLayoutConstraint = self.heightAnchor
.constraint(equalToConstant: (Values.verySmallSpacing * 2))
private lazy var filledHeightConstraint: NSLayoutConstraint = self.heightAnchor
.constraint(greaterThanOrEqualToConstant: Values.mediumSpacing)
// MARK: - UI
private let stackView: UIStackView = {
let result: UIStackView = UIStackView()
result.translatesAutoresizingMaskIntoConstraints = false
result.axis = .vertical
result.distribution = .fill
result.alignment = .fill
result.isLayoutMarginsRelativeArrangement = true
return result
}()
private let titleLabel: UILabel = {
let result: UILabel = UILabel()
result.translatesAutoresizingMaskIntoConstraints = false
result.font = .systemFont(ofSize: Values.verySmallFontSize)
result.textAlignment = .center
result.numberOfLines = 0
result.themeTextColor = .textSecondary
return result
}()
// MARK: - Initialization
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
self.backgroundView = UIView()
self.backgroundView?.themeBackgroundColor = .backgroundPrimary
addSubview(stackView)
stackView.addArrangedSubview(titleLabel)
setupLayout()
}
required init?(coder: NSCoder) {
fatalError("use init(reuseIdentifier:) instead")
}
private func setupLayout() {
stackView.pin(to: self)
}
// MARK: - Content
public func update(
style: SessionCell.BackgroundStyle = .rounded,
title: String?
) {
let titleIsEmpty: Bool = (title ?? "").isEmpty
let edgePadding: CGFloat = {
switch style {
case .rounded:
// Align to the start of the text in the cell
return (Values.largeSpacing + Values.mediumSpacing)
case .edgeToEdge, .noBackground: return Values.largeSpacing
}
}()
titleLabel.text = title
titleLabel.isHidden = titleIsEmpty
stackView.layoutMargins = UIEdgeInsets(
top: (titleIsEmpty ? Values.verySmallSpacing : Values.mediumSpacing),
left: edgePadding,
bottom: (titleIsEmpty ? Values.verySmallSpacing : Values.mediumSpacing),
right: edgePadding
)
emptyHeightConstraint.isActive = titleIsEmpty
filledHeightConstraint.isActive = !titleIsEmpty
self.layoutIfNeeded()
}
}

@ -1,22 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import <AVFoundation/AVAudioSession.h>
NS_ASSUME_NONNULL_BEGIN
@interface AVAudioSession (OWS)
// #RADAR 45397675 http://www.openradar.me/45397675
//
// A bug in Swift 4.2+ made `AVAudioSession#setCategory:categorywithOptions:error` not accessible
// to Swift.
//
// It's still available via ObjC, so we have an objc-category method which we can call from Swift
// which just calls the original `AVAudioSession#setCategory:categorywithOptions:error` method.
- (BOOL)ows_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
@end
NS_ASSUME_NONNULL_END

@ -1,15 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "AVAudioSession+OWS.h"
@implementation AVAudioSession(OWS)
- (BOOL)ows_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(6.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos)
{
return [self setCategory:category withOptions:options error:outError];
}
@end

@ -73,7 +73,7 @@ public final class BackgroundPoller {
private static func pollForMessages(
using dependencies: Dependencies
) -> AnyPublisher<Void, Error> {
let userPublicKey: String = getUserHexEncodedPublicKey()
let userPublicKey: String = getUserHexEncodedPublicKey(using: dependencies)
return SnodeAPI.getSwarm(for: userPublicKey)
.tryFlatMapWithRandomSnode { snode -> AnyPublisher<[Message], Error> in

@ -184,6 +184,10 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
kind: .offer,
sdps: [ sdp.sdp ],
sentTimestampMs: UInt64(SnodeAPI.currentOffsetTimestampMs())
)
.with(try? thread.disappearingMessagesConfiguration
.fetchOne(db)?
.forcedWithDisappearAfterReadIfNeeded()
),
to: try Message.Destination
.from(db, threadId: thread.id, threadVariant: thread.variant),
@ -254,6 +258,10 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
uuid: uuid,
kind: .answer,
sdps: [ sdp.sdp ]
)
.with(try? thread.disappearingMessagesConfiguration
.fetchOne(db)?
.forcedWithDisappearAfterReadIfNeeded()
),
to: try Message.Destination
.from(db, threadId: thread.id, threadVariant: thread.variant),
@ -316,6 +324,10 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
sdpMids: candidates.map { $0.sdpMid! }
),
sdps: candidates.map { $0.sdp }
)
.with(try? thread.disappearingMessagesConfiguration
.fetchOne(db)?
.forcedWithDisappearAfterReadIfNeeded()
),
to: try Message.Destination
.from(db, threadId: thread.id, threadVariant: thread.variant),
@ -347,6 +359,10 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
uuid: self.uuid,
kind: .endCall,
sdps: []
)
.with(try? thread.disappearingMessagesConfiguration
.fetchOne(db)?
.forcedWithDisappearAfterReadIfNeeded()
),
to: try Message.Destination.from(db, threadId: thread.id, threadVariant: thread.variant),
namespace: try Message.Destination

@ -34,7 +34,8 @@ public enum SNMessagingKit: MigratableTarget { // Just to make the external API
_014_GenerateInitialUserConfigDumps.self,
_015_BlockCommunityMessageRequests.self,
_016_MakeBrokenProfileTimestampsNullable.self,
_017_RebuildFTSIfNeeded_2_4_5.self
_017_RebuildFTSIfNeeded_2_4_5.self,
_018_DisappearingMessagesConfiguration.self
]
]
)
@ -57,5 +58,7 @@ public enum SNMessagingKit: MigratableTarget { // Just to make the external API
JobRunner.setExecutor(AttachmentDownloadJob.self, for: .attachmentDownload)
JobRunner.setExecutor(ConfigurationSyncJob.self, for: .configurationSync)
JobRunner.setExecutor(ConfigMessageReceiveJob.self, for: .configMessageReceive)
JobRunner.setExecutor(ExpirationUpdateJob.self, for: .expirationUpdate)
JobRunner.setExecutor(GetExpirationJob.self, for: .getExpiration)
}
}

@ -824,9 +824,11 @@ enum _003_YDBToGRDBMigration: Migration {
let updateMessage: SMKLegacy._DisappearingConfigurationUpdateInfoMessage = infoMessage as? SMKLegacy._DisappearingConfigurationUpdateInfoMessage,
let infoMessageData: Data = try? JSONEncoder().encode(
DisappearingMessagesConfiguration.MessageInfo(
threadVariant: nil,
senderName: updateMessage.createdByRemoteName,
isEnabled: updateMessage.configurationIsEnabled,
durationSeconds: TimeInterval(updateMessage.configurationDurationSeconds)
durationSeconds: TimeInterval(updateMessage.configurationDurationSeconds),
type: nil
)
),
let infoMessageString: String = String(data: infoMessageData, encoding: .utf8)

@ -0,0 +1,88 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
enum _018_DisappearingMessagesConfiguration: Migration {
static let target: TargetMigrations.Identifier = .messagingKit
static let identifier: String = "DisappearingMessagesWithTypes" // stringlint:disable
static let needsConfigSync: Bool = false
static let minExpectedRunDuration: TimeInterval = 0.1
static var requirements: [MigrationRequirement] = [.sessionUtilStateLoaded]
static let fetchedTables: [(TableRecord & FetchableRecord).Type] = [
Identity.self, DisappearingMessagesConfiguration.self
]
static let createdOrAlteredTables: [(TableRecord & FetchableRecord).Type] = [
DisappearingMessagesConfiguration.self, Contact.self
]
static func migrate(_ db: GRDB.Database) throws {
try db.alter(table: DisappearingMessagesConfiguration.self) { t in
t.add(.type, .integer)
}
try db.alter(table: Contact.self) { t in
t.add(.lastKnownClientVersion, .integer)
}
/// Add index on interaction table for wasRead and variant
///
/// This is due to new disappearing messages will need some info messages to be able to be unread,
/// but we only want to count the unread message number by incoming visible messages and call messages.
try db.createIndex(
on: Interaction.self,
columns: [.wasRead, .variant]
)
// If there isn't already a user account then we can just finish here (there will be no
// threads/configs to update and the configs won't be setup which would cause this to crash
guard Identity.userExists(db) else {
return Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
// Convenience function to set the disappearing messages type per conversation
func updateDisappearingMessageType(_ db: GRDB.Database, id: String, type: DisappearingMessagesConfiguration.DisappearingMessageType) throws {
_ = try DisappearingMessagesConfiguration
.filter(DisappearingMessagesConfiguration.Columns.threadId == id)
.updateAll(
db,
DisappearingMessagesConfiguration.Columns.type.set(to: type)
)
}
// Process any existing disappearing message settings
var contactUpdate: [DisappearingMessagesConfiguration] = []
var legacyGroupUpdate: [DisappearingMessagesConfiguration] = []
try DisappearingMessagesConfiguration
.filter(DisappearingMessagesConfiguration.Columns.isEnabled == true)
.fetchAll(db)
.forEach { config in
guard let thread: SessionThread = try? SessionThread.fetchOne(db, id: config.threadId) else { return }
guard !thread.isNoteToSelf(db) else {
try updateDisappearingMessageType(db, id: config.threadId, type: .disappearAfterSend)
return
}
switch thread.variant {
case .contact:
try updateDisappearingMessageType(db, id: config.threadId, type: .disappearAfterRead)
contactUpdate.append(config.with(type: .disappearAfterRead))
case .legacyGroup, .group:
try updateDisappearingMessageType(db, id: config.threadId, type: .disappearAfterSend)
legacyGroupUpdate.append(config.with(type: .disappearAfterSend))
case .community: return
}
}
// Update the configs so the settings are synced
_ = try SessionUtil.updatingDisappearingConfigs(db, contactUpdate)
_ = try SessionUtil.batchUpdate(db, disappearingConfigs: legacyGroupUpdate)
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

@ -18,6 +18,7 @@ public struct Contact: Codable, Identifiable, Equatable, FetchableRecord, Persis
case isTrusted
case isApproved
case isBlocked
case lastKnownClientVersion
case didApproveMe
case hasBeenBlocked
}
@ -34,6 +35,9 @@ public struct Contact: Codable, Identifiable, Equatable, FetchableRecord, Persis
/// This flag is used to determine whether message requests from this contact are blocked
public let isBlocked: Bool
/// The last known client version represented by pre defined enum values
public let lastKnownClientVersion: FeatureVersion?
/// This flag is used to determine whether this contact has approved the current users message request
public let didApproveMe: Bool
@ -49,10 +53,12 @@ public struct Contact: Codable, Identifiable, Equatable, FetchableRecord, Persis
// MARK: - Initialization
public init(
_ db: Database? = nil,
id: String,
isTrusted: Bool = false,
isApproved: Bool = false,
isBlocked: Bool = false,
lastKnownClientVersion: FeatureVersion? = nil,
didApproveMe: Bool = false,
hasBeenBlocked: Bool = false,
using dependencies: Dependencies = Dependencies()
@ -60,10 +66,11 @@ public struct Contact: Codable, Identifiable, Equatable, FetchableRecord, Persis
self.id = id
self.isTrusted = (
isTrusted ||
id == getUserHexEncodedPublicKey(using: dependencies) // Always trust ourselves
id == getUserHexEncodedPublicKey(db, using: dependencies) // Always trust ourselves
)
self.isApproved = isApproved
self.isBlocked = isBlocked
self.lastKnownClientVersion = lastKnownClientVersion
self.didApproveMe = didApproveMe
self.hasBeenBlocked = (isBlocked || hasBeenBlocked)
}
@ -77,6 +84,6 @@ public extension Contact {
/// **Note:** This method intentionally does **not** save the newly created Contact,
/// it will need to be explicitly saved after calling
static func fetchOrCreate(_ db: Database, id: ID) -> Contact {
return ((try? fetchOne(db, id: id)) ?? Contact(id: id))
return ((try? fetchOne(db, id: id)) ?? Contact(db, id: id))
}
}

@ -2,6 +2,7 @@
import Foundation
import GRDB
import SessionUtil
import SessionUtilitiesKit
import SessionSnodeKit
@ -15,11 +16,62 @@ public struct DisappearingMessagesConfiguration: Codable, Identifiable, Equatabl
case threadId
case isEnabled
case durationSeconds
case type
}
public enum DefaultDuration {
case off
case unknown
case legacy
case disappearAfterRead
case disappearAfterSend
public var seconds: TimeInterval {
switch self {
case .off, .unknown: return 0
case .legacy: return (24 * 60 * 60)
case .disappearAfterRead: return (12 * 60 * 60)
case .disappearAfterSend: return (24 * 60 * 60)
}
}
}
public enum DisappearingMessageType: Int, Codable, Hashable, DatabaseValueConvertible {
case unknown
case disappearAfterRead
case disappearAfterSend
init(protoType: SNProtoContent.SNProtoContentExpirationType) {
switch protoType {
case .unknown: self = .unknown
case .deleteAfterRead: self = .disappearAfterRead
case .deleteAfterSend: self = .disappearAfterSend
}
}
init(sessionUtilType: CONVO_EXPIRATION_MODE) {
switch sessionUtilType {
case CONVO_EXPIRATION_AFTER_READ: self = .disappearAfterRead
case CONVO_EXPIRATION_AFTER_SEND: self = .disappearAfterSend
default: self = .unknown
}
}
func toProto() -> SNProtoContent.SNProtoContentExpirationType {
switch self {
case .unknown: return .unknown
case .disappearAfterRead: return .deleteAfterRead
case .disappearAfterSend: return .deleteAfterSend
}
}
func toLibSession() -> CONVO_EXPIRATION_MODE {
switch self {
case .unknown: return CONVO_EXPIRATION_NONE
case .disappearAfterRead: return CONVO_EXPIRATION_AFTER_READ
case .disappearAfterSend: return CONVO_EXPIRATION_AFTER_SEND
}
}
}
public var id: String { threadId } // Identifiable
@ -27,7 +79,7 @@ public struct DisappearingMessagesConfiguration: Codable, Identifiable, Equatabl
public let threadId: String
public let isEnabled: Bool
public let durationSeconds: TimeInterval
public var type: DisappearingMessageType? { return nil } // TODO: Add as part of Disappearing Message Rebuild
public var type: DisappearingMessageType?
// MARK: - Relationships
@ -39,13 +91,12 @@ public struct DisappearingMessagesConfiguration: Codable, Identifiable, Equatabl
// MARK: - Mutation
public extension DisappearingMessagesConfiguration {
static let defaultDuration: TimeInterval = (24 * 60 * 60)
static func defaultWith(_ threadId: String) -> DisappearingMessagesConfiguration {
return DisappearingMessagesConfiguration(
threadId: threadId,
isEnabled: false,
durationSeconds: defaultDuration
durationSeconds: 0,
type: .unknown
)
}
@ -57,20 +108,58 @@ public extension DisappearingMessagesConfiguration {
return DisappearingMessagesConfiguration(
threadId: threadId,
isEnabled: (isEnabled ?? self.isEnabled),
durationSeconds: (durationSeconds ?? self.durationSeconds)
durationSeconds: (durationSeconds ?? self.durationSeconds),
type: (isEnabled == false) ? .unknown : (type ?? self.type)
)
}
func forcedWithDisappearAfterReadIfNeeded() -> DisappearingMessagesConfiguration {
if self.isEnabled {
return self.with(type: .disappearAfterRead)
}
return self
}
}
// MARK: - Convenience
public extension DisappearingMessagesConfiguration {
struct MessageInfo: Codable {
public let threadVariant: SessionThread.Variant?
public let senderName: String?
public let isEnabled: Bool
public let durationSeconds: TimeInterval
public let type: DisappearingMessageType?
var previewText: String {
guard Features.useNewDisappearingMessagesConfig && self.threadVariant != nil else { return legacyPreviewText }
guard let senderName: String = senderName else {
guard isEnabled, durationSeconds > 0 else {
return "YOU_DISAPPEARING_MESSAGES_INFO_DISABLE".localized()
}
return String(
format: "YOU_DISAPPEARING_MESSAGES_INFO_ENABLE".localized(),
floor(durationSeconds).formatted(format: .long),
(type == .disappearAfterRead ? "DISAPPEARING_MESSAGE_STATE_READ".localized() : "DISAPPEARING_MESSAGE_STATE_SENT".localized())
)
}
guard isEnabled, durationSeconds > 0 else {
return String(format: "DISAPPERING_MESSAGES_INFO_DISABLE".localized(), senderName)
}
return String(
format: "DISAPPERING_MESSAGES_INFO_ENABLE".localized(),
senderName,
floor(durationSeconds).formatted(format: .long),
(type == .disappearAfterRead ? "DISAPPEARING_MESSAGE_STATE_READ".localized() : "DISAPPEARING_MESSAGE_STATE_SENT".localized())
)
}
private var legacyPreviewText: String {
guard let senderName: String = senderName else {
// Changed by this device or via synced transcript
guard isEnabled, durationSeconds > 0 else { return "YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION".localized() }
@ -97,22 +186,155 @@ public extension DisappearingMessagesConfiguration {
floor(durationSeconds).formatted(format: .long)
}
func messageInfoString(with senderName: String?) -> String? {
func messageInfoString(
threadVariant: SessionThread.Variant?,
senderName: String?
) -> String? {
let messageInfo: MessageInfo = DisappearingMessagesConfiguration.MessageInfo(
threadVariant: threadVariant,
senderName: senderName,
isEnabled: isEnabled,
durationSeconds: durationSeconds
durationSeconds: durationSeconds,
type: type
)
guard let messageInfoData: Data = try? JSONEncoder().encode(messageInfo) else { return nil }
return String(data: messageInfoData, encoding: .utf8)
}
func isValidV2Config() -> Bool {
guard self.type != nil else { return (self.durationSeconds == 0) }
return !(self.durationSeconds > 0 && self.type == .unknown)
}
}
// MARK: - Control Message
public extension DisappearingMessagesConfiguration {
func clearUnrelatedControlMessages(
_ db: Database,
threadVariant: SessionThread.Variant,
using dependencies: Dependencies = Dependencies()
) throws {
guard threadVariant == .contact else {
try Interaction
.filter(Interaction.Columns.threadId == self.threadId)
.filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate)
.filter(Interaction.Columns.expiresInSeconds != self.durationSeconds)
.deleteAll(db)
return
}
let userPublicKey: String = getUserHexEncodedPublicKey(db, using: dependencies)
guard self.isEnabled else {
try Interaction
.filter(Interaction.Columns.threadId == self.threadId)
.filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate)
.filter(Interaction.Columns.authorId == userPublicKey)
.filter(Interaction.Columns.expiresInSeconds != 0)
.deleteAll(db)
return
}
switch self.type {
case .disappearAfterRead:
try Interaction
.filter(Interaction.Columns.threadId == self.threadId)
.filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate)
.filter(Interaction.Columns.authorId == userPublicKey)
.filter(!(Interaction.Columns.expiresInSeconds == self.durationSeconds && Interaction.Columns.expiresStartedAtMs != Interaction.Columns.timestampMs))
.deleteAll(db)
case .disappearAfterSend:
try Interaction
.filter(Interaction.Columns.threadId == self.threadId)
.filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate)
.filter(Interaction.Columns.authorId == userPublicKey)
.filter(!(Interaction.Columns.expiresInSeconds == self.durationSeconds && Interaction.Columns.expiresStartedAtMs == Interaction.Columns.timestampMs))
.deleteAll(db)
default:
break
}
}
func insertControlMessage(
_ db: Database,
threadVariant: SessionThread.Variant,
authorId: String,
timestampMs: Int64,
serverHash: String?,
serverExpirationTimestamp: TimeInterval?,
using dependencies: Dependencies = Dependencies()
) throws -> Int64? {
if Features.useNewDisappearingMessagesConfig {
switch threadVariant {
case .contact:
_ = try Interaction
.filter(Interaction.Columns.threadId == threadId)
.filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate)
.filter(Interaction.Columns.authorId == authorId)
.deleteAll(db)
case .legacyGroup:
_ = try Interaction
.filter(Interaction.Columns.threadId == threadId)
.filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate)
.deleteAll(db)
default:
break
}
}
let currentUserPublicKey: String = getUserHexEncodedPublicKey(db, using: dependencies)
let wasRead: Bool = (
authorId == currentUserPublicKey ||
SessionUtil.timestampAlreadyRead(
threadId: threadId,
threadVariant: threadVariant,
timestampMs: timestampMs,
userPublicKey: getUserHexEncodedPublicKey(db),
openGroup: nil
)
)
let messageExpirationInfo: Message.MessageExpirationInfo = Message.getMessageExpirationInfo(
wasRead: wasRead,
serverExpirationTimestamp: serverExpirationTimestamp,
expiresInSeconds: self.durationSeconds,
expiresStartedAtMs: (self.type == .disappearAfterSend) ? Double(timestampMs) : nil
)
let interaction = try Interaction(
serverHash: serverHash,
threadId: threadId,
authorId: authorId,
variant: .infoDisappearingMessagesUpdate,
body: self.messageInfoString(
threadVariant: threadVariant,
senderName: (authorId != getUserHexEncodedPublicKey(db) ? Profile.displayName(db, id: authorId) : nil)
),
timestampMs: timestampMs,
wasRead: wasRead,
expiresInSeconds: (threadVariant == .legacyGroup ? nil : messageExpirationInfo.expiresInSeconds), // Do not expire this control message in legacy groups
expiresStartedAtMs: (threadVariant == .legacyGroup ? nil : messageExpirationInfo.expiresStartedAtMs)
).inserted(db)
if messageExpirationInfo.shouldUpdateExpiry {
Message.updateExpiryForDisappearAfterReadMessages(
db,
threadId: threadId,
serverHash: serverHash,
expiresInSeconds: messageExpirationInfo.expiresInSeconds,
expiresStartedAtMs: messageExpirationInfo.expiresStartedAtMs
)
}
return interaction.id
}
}
// MARK: - UI Constraints
extension DisappearingMessagesConfiguration {
// TODO: Remove this when disappearing messages V2 is up and running
public static var validDurationsSeconds: [TimeInterval] {
return [
5,
@ -132,4 +354,48 @@ extension DisappearingMessagesConfiguration {
public static var maxDurationSeconds: TimeInterval = {
return (validDurationsSeconds.max() ?? 0)
}()
public static func validDurationsSeconds(_ type: DisappearingMessageType) -> [TimeInterval] {
switch type {
case .disappearAfterRead:
var result = [
(5 * 60),
(1 * 60 * 60),
(12 * 60 * 60),
(24 * 60 * 60),
(7 * 24 * 60 * 60),
(2 * 7 * 24 * 60 * 60)
]
.map { TimeInterval($0) }
#if targetEnvironment(simulator)
result.insert(
TimeInterval(60),
at: 0
)
result.insert(
TimeInterval(10),
at: 0
)
#endif
return result
case .disappearAfterSend:
var result = [
(12 * 60 * 60),
(24 * 60 * 60),
(7 * 24 * 60 * 60),
(2 * 7 * 24 * 60 * 60)
]
.map { TimeInterval($0) }
#if targetEnvironment(simulator)
result.insert(
TimeInterval(10),
at: 0
)
#endif
return result
default:
return []
}
}
}

@ -130,12 +130,16 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
switch self {
case .standardIncoming: return true
case .infoCall: return true
case .infoDisappearingMessagesUpdate, .infoScreenshotNotification, .infoMediaSavedNotification:
/// These won't be counted as unread messages but need to be able to be in an unread state so that they can disappear
/// after being read (if we don't do this their expiration timer will start immediately when received)
return true
case .standardOutgoing, .standardIncomingDeleted: return false
case .infoClosedGroupCreated, .infoClosedGroupUpdated,
.infoClosedGroupCurrentUserLeft, .infoClosedGroupCurrentUserLeaving, .infoClosedGroupCurrentUserErrorLeaving,
.infoDisappearingMessagesUpdate, .infoScreenshotNotification, .infoMediaSavedNotification,
.infoMessageRequestAccepted:
return false
}
@ -192,6 +196,10 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
/// A flag indicating whether the interaction has been read (this is a flag rather than a timestamp because
/// we couldnt know if a read timestamp is accurate)
///
/// This flag is used:
/// - In conjunction with `Interaction.variantsToIncrementUnreadCount` to determine the unread count for a thread
/// - In order to determine whether the "Disappear After Read" expiration type should be started
///
/// **Note:** This flag is not applicable to standardOutgoing or standardIncomingDeleted interactions
public private(set) var wasRead: Bool
@ -199,12 +207,12 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
public let hasMention: Bool
/// The number of seconds until this message should expire
public let expiresInSeconds: TimeInterval?
public private(set) var expiresInSeconds: TimeInterval?
/// The timestamp in milliseconds since 1970 at which this messages expiration timer started counting
/// down (this is stored in order to allow the `expiresInSeconds` value to be updated before a
/// message has expired)
public let expiresStartedAtMs: Double?
public private(set) var expiresStartedAtMs: Double?
/// This value is the url for the link preview for this interaction
///
@ -419,6 +427,14 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
default: break
}
// Start the disappearing messages timer if needed
if self.expiresStartedAtMs != nil {
JobRunner.upsert(
db,
job: DisappearingMessagesJob.updateNextRunIfNeeded(db)
)
}
}
public mutating func didInsert(_ inserted: InsertionSuccess) {
@ -460,6 +476,31 @@ public extension Interaction {
openGroupWhisperTo: self.openGroupWhisperTo
)
}
func withDisappearAfterReadIfNeeded(_ db: Database) -> Interaction {
if let config = try? DisappearingMessagesConfiguration.fetchOne(db, id: self.threadId) {
return self.withDisappearingMessagesConfiguration(
config: config.with(type: .disappearAfterRead)
)
}
return self
}
func withDisappearingMessagesConfiguration(_ db: Database) -> Interaction {
if let config = try? DisappearingMessagesConfiguration.fetchOne(db, id: self.threadId) {
return self.withDisappearingMessagesConfiguration(config: config)
}
return self
}
func withDisappearingMessagesConfiguration(config: DisappearingMessagesConfiguration?) -> Interaction {
return self.with(
expiresInSeconds: config?.durationSeconds,
expiresStartedAtMs: (config?.type == .disappearAfterSend ? Double(self.timestampMs) : nil)
)
}
}
// MARK: - GRDB Interactions
@ -690,18 +731,26 @@ public extension Interaction {
threadVariant: threadVariant,
lastReadTimestampMs: lastReadTimestampMs
)
}
// Add the 'DisappearingMessagesJob' if needed - this will update any expiring
// messages `expiresStartedAtMs` values
JobRunner.upsert(
db,
job: DisappearingMessagesJob.updateNextRunIfNeeded(
// Add the 'DisappearingMessagesJob' if needed - this will update any expiring
// messages `expiresStartedAtMs` values
JobRunner.upsert(
db,
interactionIds: interactionInfo.map { $0.id },
startedAtMs: TimeInterval(SnodeAPI.currentOffsetTimestampMs())
job: DisappearingMessagesJob.updateNextRunIfNeeded(
db,
interactionIds: interactionInfo.map { $0.id },
startedAtMs: TimeInterval(SnodeAPI.currentOffsetTimestampMs()),
threadId: threadId
)
)
)
} else {
// Update old disappearing after read messages to start
DisappearingMessagesJob.updateNextRunIfNeeded(
db,
lastReadTimestampMs: lastReadTimestampMs,
threadId: threadId
)
}
// Clear out any notifications for the interactions we mark as read
Environment.shared?.notificationsManager.wrappedValue?.cancelNotifications(
@ -794,8 +843,6 @@ public extension Interaction {
// MARK: - Variables
var isExpiringMessage: Bool {
guard variant == .standardIncoming || variant == .standardOutgoing else { return false }
return (expiresInSeconds ?? 0 > 0)
}

@ -71,7 +71,7 @@ public struct RecipientState: Codable, Equatable, FetchableRecord, PersistableRe
}
public func statusIconInfo(variant: Interaction.Variant, hasAtLeastOneReadReceipt: Bool) -> (image: UIImage?, text: String?, themeTintColor: ThemeValue) {
guard variant == .standardOutgoing else { return (nil, nil, .textPrimary) }
guard variant == .standardOutgoing else { return (nil, "MESSAGE_DELIVERY_STATUS_READ".localized(), .messageBubble_deliveryStatus) }
switch (self, hasAtLeastOneReadReceipt) {
case (.sending, _):

@ -11,6 +11,7 @@ public enum ConfigurationSyncJob: JobExecutor {
public static let requiresThreadId: Bool = true
public static let requiresInteractionId: Bool = false
private static let maxRunFrequency: TimeInterval = 3
private static let waitTimeForExpirationUpdate: TimeInterval = 1
public static func run(
_ job: Job,
@ -53,8 +54,8 @@ public enum ConfigurationSyncJob: JobExecutor {
// fresh install due to the migrations getting run)
guard
let publicKey: String = job.threadId,
let pendingConfigChanges: [SessionUtil.OutgoingConfResult] = Storage.shared
.read({ db in try SessionUtil.pendingChanges(db, publicKey: publicKey) })
let pendingConfigChanges: [SessionUtil.OutgoingConfResult] = dependencies.storage
.read(using: dependencies, { db in try SessionUtil.pendingChanges(db, publicKey: publicKey) })
else {
SNLog("[ConfigurationSyncJob] For \(job.threadId ?? "UnknownId") failed due to invalid data")
return failure(job, StorageError.generic, false, dependencies)

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Combine
import GRDB
import SessionUtilitiesKit
import SessionSnodeKit
@ -49,13 +50,10 @@ public enum DisappearingMessagesJob: JobExecutor {
public extension DisappearingMessagesJob {
@discardableResult static func updateNextRunIfNeeded(_ db: Database) -> Job? {
// Don't run when inactive or not in main app
guard (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else { return nil }
// If there is another expiring message then update the job to run 1 second after it's meant to expire
let nextExpirationTimestampMs: Double? = try? Interaction
.filter(Interaction.Columns.expiresStartedAtMs != nil)
.filter(Interaction.Columns.expiresInSeconds != nil)
.filter(Interaction.Columns.expiresInSeconds != 0)
.select(Interaction.Columns.expiresStartedAtMs + (Interaction.Columns.expiresInSeconds * 1000))
.order((Interaction.Columns.expiresStartedAtMs + (Interaction.Columns.expiresInSeconds * 1000)).asc)
.asRequest(of: Double.self)
@ -78,19 +76,100 @@ public extension DisappearingMessagesJob {
.saved(db)
}
@discardableResult static func updateNextRunIfNeeded(_ db: Database, interactionIds: [Int64], startedAtMs: Double) -> Job? {
static func updateNextRunIfNeeded(_ db: Database, lastReadTimestampMs: Int64, threadId: String) {
struct ExpirationInfo: Codable, Hashable, FetchableRecord {
let expiresInSeconds: TimeInterval
let serverHash: String
}
let expirationInfo: [String: TimeInterval] = (try? Interaction
.filter(
Interaction.Columns.threadId == threadId &&
Interaction.Columns.timestampMs <= lastReadTimestampMs &&
Interaction.Columns.expiresInSeconds != 0 &&
Interaction.Columns.expiresStartedAtMs == nil
)
.select(
Interaction.Columns.expiresInSeconds,
Interaction.Columns.serverHash
)
.asRequest(of: ExpirationInfo.self)
.fetchAll(db))
.defaulting(to: [])
.grouped(by: \.serverHash)
.compactMapValues{ $0.first?.expiresInSeconds }
guard (expirationInfo.count > 0) else { return }
let startedAtTimestampMs: Double = Double(SnodeAPI.currentOffsetTimestampMs())
JobRunner.add(
db,
job: Job(
variant: .getExpiration,
behaviour: .runOnce,
threadId: threadId,
details: GetExpirationJob.Details(
expirationInfo: expirationInfo,
startedAtTimestampMs: startedAtTimestampMs
)
)
)
}
@discardableResult static func updateNextRunIfNeeded(_ db: Database, interactionIds: [Int64], startedAtMs: Double, threadId: String) -> Job? {
struct ExpirationInfo: Codable, Hashable, FetchableRecord {
let id: Int64
let expiresInSeconds: TimeInterval
let serverHash: String
}
let interactionExpirationInfosByExpiresInSeconds: [TimeInterval: [ExpirationInfo]] = (try? Interaction
.filter(interactionIds.contains(Interaction.Columns.id))
.filter(
Interaction.Columns.expiresInSeconds != 0 &&
Interaction.Columns.expiresStartedAtMs == nil
)
.select(
Interaction.Columns.id,
Interaction.Columns.expiresInSeconds,
Interaction.Columns.serverHash
)
.asRequest(of: ExpirationInfo.self)
.fetchAll(db))
.defaulting(to: [])
.grouped(by: \.expiresInSeconds)
// Update the expiring messages expiresStartedAtMs value
let changeCount: Int? = try? Interaction
.filter(interactionIds.contains(Interaction.Columns.id))
.filter(
Interaction.Columns.expiresInSeconds != nil &&
Interaction.Columns.expiresInSeconds != 0 &&
Interaction.Columns.expiresStartedAtMs == nil
)
.updateAll(db, Interaction.Columns.expiresStartedAtMs.set(to: startedAtMs))
.updateAll(
db,
Interaction.Columns.expiresStartedAtMs.set(to: startedAtMs)
)
// If there were no changes then none of the provided `interactionIds` are expiring messages
guard (changeCount ?? 0) > 0 else { return nil }
interactionExpirationInfosByExpiresInSeconds.forEach { expiresInSeconds, expirationInfos in
let expirationTimestampMs: Int64 = Int64(startedAtMs + expiresInSeconds * 1000)
JobRunner.add(
db,
job: Job(
variant: .expirationUpdate,
behaviour: .runOnce,
threadId: threadId,
details: ExpirationUpdateJob.Details(
serverHashes: expirationInfos.map { $0.serverHash },
expirationTimestampMs: expirationTimestampMs
)
)
)
}
return updateNextRunIfNeeded(db)
}
@ -107,7 +186,7 @@ public extension DisappearingMessagesJob {
throw StorageError.objectNotFound
}
return updateNextRunIfNeeded(db, interactionIds: [interactionId], startedAtMs: startedAtMs)
return updateNextRunIfNeeded(db, interactionIds: [interactionId], startedAtMs: startedAtMs, threadId: interaction.threadId)
}
catch {
SNLog("[DisappearingMessagesJob] Failed to update the expiring messages timer on an interaction")

@ -0,0 +1,136 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Combine
import GRDB
import SessionUtilitiesKit
import SessionSnodeKit
public enum ExpirationUpdateJob: JobExecutor {
public static var maxFailureCount: Int = -1
public static var requiresThreadId: Bool = true
public static var requiresInteractionId: Bool = false
public static func run(
_ job: Job,
queue: DispatchQueue,
success: @escaping (Job, Bool, Dependencies) -> (),
failure: @escaping (Job, Error?, Bool, Dependencies) -> (),
deferred: @escaping (Job, Dependencies) -> (),
using dependencies: Dependencies
) {
guard
let detailsData: Data = job.details,
let details: Details = try? JSONDecoder().decode(Details.self, from: detailsData)
else {
SNLog("[ExpirationUpdateJob] Failing due to missing details")
failure(job, JobRunnerError.missingRequiredDetails, true, dependencies)
return
}
let userPublicKey: String = getUserHexEncodedPublicKey(using: dependencies)
SnodeAPI
.updateExpiry(
publicKey: userPublicKey,
serverHashes: details.serverHashes,
updatedExpiryMs: details.expirationTimestampMs,
shortenOnly: true,
using: dependencies
)
.subscribe(on: queue, using: dependencies)
.receive(on: queue, using: dependencies)
.map { response -> [UInt64: [String]] in
guard
let results: [UpdateExpiryResponseResult] = response
.compactMap({ _, value in value.didError ? nil : value })
.nullIfEmpty(),
let unchangedMessages: [UInt64: [String]] = results
.reduce([:], { result, next in result.updated(with: next.unchanged) })
.groupedByValue()
.nullIfEmpty()
else { return [:] }
return unchangedMessages
}
.sinkUntilComplete(
receiveCompletion: { result in
switch result {
case .finished: success(job, false, dependencies)
case .failure(let error): failure(job, error, true, dependencies)
}
},
receiveValue: { unchangedMessages in
guard !unchangedMessages.isEmpty else { return }
dependencies.storage.writeAsync(using: dependencies) { db in
unchangedMessages.forEach { updatedExpiry, hashes in
hashes.forEach { hash in
guard
let interaction: Interaction = try? Interaction
.filter(Interaction.Columns.serverHash == hash)
.fetchOne(db),
let expiresInSeconds: TimeInterval = interaction.expiresInSeconds
else { return }
let expiresStartedAtMs: TimeInterval = TimeInterval(updatedExpiry - UInt64(expiresInSeconds * 1000))
dependencies.jobRunner.upsert(
db,
job: DisappearingMessagesJob.updateNextRunIfNeeded(
db,
interaction: interaction,
startedAtMs: expiresStartedAtMs
),
canStartJob: true,
using: dependencies
)
}
}
}
}
)
}
}
// MARK: - ExpirationUpdateJob.Details
extension ExpirationUpdateJob {
public struct Details: Codable {
private enum CodingKeys: String, CodingKey {
case serverHashes
case expirationTimestampMs
}
public let serverHashes: [String]
public let expirationTimestampMs: Int64
// MARK: - Initialization
public init(
serverHashes: [String],
expirationTimestampMs: Int64
) {
self.serverHashes = serverHashes
self.expirationTimestampMs = expirationTimestampMs
}
// MARK: - Codable
public init(from decoder: Decoder) throws {
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
self = Details(
serverHashes: try container.decode([String].self, forKey: .serverHashes),
expirationTimestampMs: try container.decode(Int64.self, forKey: .expirationTimestampMs)
)
}
public func encode(to encoder: Encoder) throws {
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
try container.encode(serverHashes, forKey: .serverHashes)
try container.encode(expirationTimestampMs, forKey: .expirationTimestampMs)
}
}
}

@ -15,6 +15,7 @@ public enum GarbageCollectionJob: JobExecutor {
public static var requiresThreadId: Bool = false
public static let requiresInteractionId: Bool = false
public static let approxSixMonthsInSeconds: TimeInterval = (6 * 30 * 24 * 60 * 60)
public static let fourteenDaysInSeconds: TimeInterval = (14 * 24 * 60 * 60)
private static let minInteractionsToTrim: Int = 2000
public static func run(
@ -292,6 +293,15 @@ public enum GarbageCollectionJob: JobExecutor {
""")
}
/// Remove interactions which should be disappearing after read but never be read within 14 days
if finalTypesToCollect.contains(.expiredUnreadDisappearingMessages) {
_ = try Interaction
.filter(Interaction.Columns.expiresInSeconds != 0)
.filter(Interaction.Columns.expiresStartedAtMs == nil)
.filter(Interaction.Columns.timestampMs < (timestampNow - fourteenDaysInSeconds) * 1000)
.deleteAll(db)
}
if finalTypesToCollect.contains(.expiredPendingReadReceipts) {
_ = try PendingReadReceipt
.filter(PendingReadReceipt.Columns.serverExpirationTimestamp <= timestampNow)
@ -478,6 +488,7 @@ extension GarbageCollectionJob {
case orphanedAttachments
case orphanedAttachmentFiles
case orphanedProfileAvatars
case expiredUnreadDisappearingMessages // unread disappearing messages after 14 days
case expiredPendingReadReceipts
case shadowThreads
}

@ -0,0 +1,178 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Combine
import GRDB
import SessionUtilitiesKit
import SessionSnodeKit
public enum GetExpirationJob: JobExecutor {
public static var maxFailureCount: Int = -1
public static var requiresThreadId: Bool = true
public static var requiresInteractionId: Bool = false
private static let minRunFrequency: TimeInterval = 5
public static func run(
_ job: Job,
queue: DispatchQueue,
success: @escaping (Job, Bool, Dependencies) -> (),
failure: @escaping (Job, Error?, Bool, Dependencies) -> (),
deferred: @escaping (Job, Dependencies) -> (),
using dependencies: Dependencies
) {
guard
let detailsData: Data = job.details,
let details: Details = try? JSONDecoder().decode(Details.self, from: detailsData)
else {
SNLog("[GetExpirationJob] Failing due to missing details")
failure(job, JobRunnerError.missingRequiredDetails, true, dependencies)
return
}
let expirationInfo: [String: TimeInterval] = dependencies.storage
.read(using: dependencies) { db -> [String: TimeInterval] in
details
.expirationInfo
.filter { Interaction.filter(Interaction.Columns.serverHash == $0.key).isNotEmpty(db) }
}
.defaulting(to: details.expirationInfo)
guard expirationInfo.count > 0 else {
success(job, false, dependencies)
return
}
let userPublicKey: String = getUserHexEncodedPublicKey(using: dependencies)
SnodeAPI
.getSwarm(for: userPublicKey, using: dependencies)
.tryFlatMap { swarm -> AnyPublisher<(ResponseInfoType, GetExpiriesResponse), Error> in
guard let snode = swarm.randomElement() else { throw SnodeAPIError.generic }
return SnodeAPI.getExpiries(
from: snode,
associatedWith: userPublicKey,
of: expirationInfo.map { $0.key },
using: dependencies
)
}
.subscribe(on: queue, using: dependencies)
.receive(on: queue, using: dependencies)
.map { _, response -> GetExpiriesResponse in response }
.sinkUntilComplete(
receiveCompletion: { result in
switch result {
case .finished: break
case .failure(let error): failure(job, error, true, dependencies)
}
},
receiveValue: { response in
let serverSpecifiedExpirationStartTimesMs: [String: TimeInterval] = response.expiries
.reduce(into: [:]) { result, next in
guard let expiresInSeconds: TimeInterval = expirationInfo[next.key] else { return }
result[next.key] = TimeInterval(next.value - UInt64(expiresInSeconds * 1000))
}
var hashesWithNoExiprationInfo: Set<String> = Set(expirationInfo.keys)
.subtracting(serverSpecifiedExpirationStartTimesMs.keys)
dependencies.storage.write(using: dependencies) { db in
try serverSpecifiedExpirationStartTimesMs.forEach { hash, expiresStartedAtMs in
try Interaction
.filter(Interaction.Columns.serverHash == hash)
.updateAll(
db,
Interaction.Columns.expiresStartedAtMs.set(to: expiresStartedAtMs)
)
}
let inferredExpiredMessageHashes: Set<String> = (try? Interaction
.select(Interaction.Columns.serverHash)
.filter(hashesWithNoExiprationInfo.contains(Interaction.Columns.serverHash))
.filter(Interaction.Columns.timestampMs + (Interaction.Columns.expiresInSeconds * 1000) <= details.startedAtTimestampMs)
.asRequest(of: String.self)
.fetchSet(db))
.defaulting(to: [])
hashesWithNoExiprationInfo = hashesWithNoExiprationInfo.subtracting(inferredExpiredMessageHashes)
if !inferredExpiredMessageHashes.isEmpty {
try Interaction
.filter(inferredExpiredMessageHashes.contains(Interaction.Columns.serverHash))
.deleteAll(db)
}
try Interaction
.filter(hashesWithNoExiprationInfo.contains(Interaction.Columns.serverHash))
.filter(Interaction.Columns.expiresStartedAtMs == nil)
.updateAll(
db,
Interaction.Columns.expiresStartedAtMs.set(to: details.startedAtTimestampMs)
)
dependencies.jobRunner
.upsert(
db,
job: DisappearingMessagesJob.updateNextRunIfNeeded(db),
canStartJob: true,
using: dependencies
)
}
guard hashesWithNoExiprationInfo.isEmpty else {
let updatedJob: Job? = dependencies.storage.write(using: dependencies) { db in
try job
.with(nextRunTimestamp: dependencies.dateNow.timeIntervalSince1970 + minRunFrequency)
.saved(db)
}
return deferred(updatedJob ?? job, dependencies)
}
success(job, false, dependencies)
}
)
}
}
// MARK: - GetExpirationJob.Details
extension GetExpirationJob {
public struct Details: Codable {
private enum CodingKeys: String, CodingKey {
case expirationInfo
case startedAtTimestampMs
}
public let expirationInfo: [String: TimeInterval]
public let startedAtTimestampMs: Double
// MARK: - Initialization
public init(
expirationInfo: [String: TimeInterval],
startedAtTimestampMs: Double
) {
self.expirationInfo = expirationInfo
self.startedAtTimestampMs = startedAtTimestampMs
}
// MARK: - Codable
public init(from decoder: Decoder) throws {
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
self = Details(
expirationInfo: try container.decode([String: TimeInterval].self, forKey: .expirationInfo),
startedAtTimestampMs: try container.decode(Double.self, forKey: .startedAtTimestampMs)
)
}
public func encode(to encoder: Encoder) throws {
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
try container.encode(expirationInfo, forKey: .expirationInfo)
try container.encode(startedAtTimestampMs, forKey: .startedAtTimestampMs)
}
}
}

@ -17,7 +17,8 @@ public final class CallMessage: ControlMessage {
/// See https://developer.mozilla.org/en-US/docs/Glossary/SDP for more information.
public var sdps: [String]
public override var ttl: UInt64 { 5 * 60 * 1000 } // 5 minutes
public override var isSelfSendValid: Bool {
switch kind {
case .answer, .endCall: return true
@ -165,7 +166,7 @@ public final class CallMessage: ControlMessage {
)
}
public override func toProto(_ db: Database) -> SNProtoContent? {
public override func toProto(_ db: Database, threadId: String) -> SNProtoContent? {
let type: SNProtoCallMessage.SNProtoCallMessageType
switch kind {
@ -188,6 +189,10 @@ public final class CallMessage: ControlMessage {
}
let contentProto = SNProtoContent.builder()
// DisappearingMessagesConfiguration
setDisappearingMessagesConfigurationIfNeeded(on: contentProto)
do {
contentProto.setCallMessage(try callMessageProto.build())

@ -293,7 +293,7 @@ public final class ClosedGroupControlMessage: ControlMessage {
}
}
public override func toProto(_ db: Database) -> SNProtoContent? {
public override func toProto(_ db: Database, threadId: String) -> SNProtoContent? {
guard let kind = kind else {
SNLog("Couldn't construct closed group update proto from: \(self).")
return nil
@ -338,6 +338,7 @@ public final class ClosedGroupControlMessage: ControlMessage {
let contentProto = SNProtoContent.builder()
let dataMessageProto = SNProtoDataMessage.builder()
dataMessageProto.setClosedGroupControlMessage(try closedGroupControlMessage.build())
contentProto.setDataMessage(try dataMessageProto.build())
return try contentProto.build()
} catch {

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

Loading…
Cancel
Save