Compare commits

...

22 Commits
main ... 5.30.x

Author SHA1 Message Date
Josh Perez 44be6939b0 v5.30.0 2022-02-02 16:17:15 -05:00
automated-signal 8d170dcf74
sendContentMessageToGroup: Comprehensive error check before failover
Co-authored-by: Scott Nonnenberg <scott@signal.org>
2022-01-31 17:33:01 -08:00
automated-signal 84dc49f2ea
Increase fallback `Retry-After` time to 1 minute
Co-authored-by: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com>
2022-01-31 15:31:16 -06:00
Evan Hahn 0d5940dc3e
Simplify spellcheck download URL, disable spellcheck in most windows
(cherry picked from commit 1c43e7501c)
2022-01-31 09:29:21 -08:00
Fedor Indutny 54136ecc31
Create contacts during processing of group updates 2022-01-27 16:35:11 -08:00
automated-signal a1d11010b5
Improve performance of isEmojiOnlyText
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
2022-01-27 13:50:11 -08:00
Scott Nonnenberg b4db39d512 TaskWithTimeout: After suspend, don't start timers for new tasks 2022-01-26 15:27:55 -08:00
automated-signal 713180d620 Remove white border around QR code in dark mode
Co-authored-by: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com>
2022-01-26 15:27:55 -08:00
Fedor Indutny e2f7c2dd45 MessageReceiver.maybeUpdateTimestamp: Annotate group identifier for log
Co-authored-by: Scott Nonnenberg <scott@signal.org>
2022-01-26 15:27:52 -08:00
Fedor Indutnyy 3a04de8a60 v5.30.0-beta.2 2022-01-25 11:59:53 -08:00
Fedor Indutnyy 6a95919de3 Update strings 2022-01-25 11:59:44 -08:00
automated-signal 99f2a9fe7e
Fix stuck safety number modal overlay
Co-authored-by: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com>
2022-01-25 11:19:40 -08:00
automated-signal 7b5ac8401e
Avoid calling `tray.destroy()` when quitting
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
2022-01-24 16:48:22 -08:00
automated-signal 137002ee91
Fix logging overflow
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
2022-01-24 16:20:14 -08:00
automated-signal 7cb8d89cda
Remove env vars
Co-authored-by: Josh Perez <60019601+josh-signal@users.noreply.github.com>
2022-01-24 16:19:16 -08:00
automated-signal 1f407beb6b
Don't let unidentifiedStatus change e164
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
2022-01-24 16:18:54 -08:00
automated-signal 72bcb120f7
Revert "MessageReceiver: Pause processing of new messages on suspend"
This reverts commit d74424a3b8.

Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
2022-01-24 16:18:26 -08:00
automated-signal 10c55e696b
Update badge placement on 52x52 avatars
Co-authored-by: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com>
2022-01-24 15:37:04 -08:00
automated-signal b8e59dc330
Fix typo in unknownContact
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
2022-01-24 15:36:41 -08:00
automated-signal a273ccf25b
Fix incorrect translation key: unknownUser -> unnkownContact
Co-authored-by: Scott Nonnenberg <scott@signal.org>
2022-01-24 12:54:08 -08:00
automated-signal 71bf37fa55
Properly handle read syncs while offline
Co-authored-by: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com>
2022-01-21 18:09:45 -08:00
automated-signal 22d1e10c1c
Use message.groupV2.revision during first fetch
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
2022-01-21 15:03:12 -08:00
94 changed files with 929 additions and 695 deletions

View File

@ -122,12 +122,6 @@ const typescriptRules = {
'error',
{
paths: [
{
name: 'electron',
importNames: ['BrowserWindow'],
message: 'Please use createBrowserWindow',
allowTypeImports: true,
},
{
name: 'chai',
importNames: ['expect', 'should', 'Should'],

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nou",
"message": "Nou",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "ما الجديد",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "يحتوي هذا الإصدار على عدد من التعديلات الصغيرة وإصلاحات الأخطاء للحفاظ على تشغيل Signal بسلاسة.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "يحتوي هذا الإصدار على عدد من التعديلات الصغيرة وإصلاحات الأخطاء للحفاظ على تشغيل Signal بسلاسة.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "indi",
"message": "İndicə",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Yeni nə var",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Bu versiya, Signal-ın problemsiz işləməsini təmin etmək üçün kiçik düzəltmələr və xəta düzəltmələri ehtiva edir.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Bu versiya, Signal-ın problemsiz işləməsini təmin etmək üçün kiçik düzəltmələr və xəta düzəltmələri ehtiva edir.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "сега",
"message": "Току що",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "নতুন কি",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "সিগন্যালকে মসৃণভাবে চলমান রাখতে এই সংস্করণে অনেকগুলি ছোটখাট পরিবর্তন রয়েছে এবং বাগ সংশোধন করা হয়েছে।",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "সিগন্যালকে মসৃণভাবে চলমান রাখতে এই সংস্করণে অনেকগুলি ছোটখাট পরিবর্তন রয়েছে এবং বাগ সংশোধন করা হয়েছে।",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "ara",
"message": "Ara",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Què hi ha de nou",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Aquesta versió conté una sèrie de petites modificacions i correccions d'errors per tal que el Signal funcioni sense problemes.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Aquesta versió conté una sèrie de petites modificacions i correccions d'errors per tal que el Signal funcioni sense problemes.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "teď",
"message": "Teď",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal se po havárii znovu spustil. Můžete odeslat hlášení o pádu a pomoci tak společnosti Signal problém prošetřit.",
"message": "Signal se restartoval po selhání. Můžete odeslat zprávu o selhání a pomoci tím daný problém vyřešit.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Co je nového",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Tato verze obsahuje řadu drobných úprav a oprav chyb, aby Signal fungoval hladce.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Tato verze obsahuje řadu drobných úprav a oprav chyb, aby Signal fungoval hladce.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nawr",
"message": "Nawr",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Ailgychwynnodd Signal ar ôl chwalu. Gallwch ddarparu adroddiad chwalu i Signal archwilio rhesymau dros y chwalu.",
"message": "Ailgychwynnodd Signal ar ôl chwalu. Gallwch ddarparu adroddiad chwalu i Signal archwilio'r mater.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Be sy'n Newydd",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Mae'r fersiwn hon yn cynnwys nifer o drydariadau bach a chywiriadau gwallau i gadw Signal yn rhedeg yn llyfn.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Mae'r fersiwn hon yn cynnwys nifer o drydariadau bach a chywiriadau gwallau i gadw Signal yn rhedeg yn llyfn.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -188,15 +188,15 @@
"description": "One of the menu options available in the Avatar popup menu"
},
"loading": {
"message": "Indlæser...",
"message": "Indlæser ...",
"description": "Message shown on the loading screen before we've loaded any messages"
},
"optimizingApplication": {
"message": "Optimerer applikationen...",
"message": "Optimerer applikation ...",
"description": "Message shown on the loading screen while we are doing application optimizations"
},
"migratingToSQLCipher": {
"message": "Optimering af beskeder... $status$ fuldført.",
"message": "Optimering af beskeder ... $status$ fuldført.",
"description": "Message shown on the loading screen while we are doing application optimizations",
"placeholders": {
"status": {
@ -302,11 +302,11 @@
"description": "Message shown as the export location if we didn't capture the target directory"
},
"upgradingDatabase": {
"message": "Opgraderer database. Det kan godt tage lidt tid...",
"message": "Opgraderer database. Det kan godt tage lidt tid ...",
"description": "Message shown on the loading screen when we're changing database structure on first run of a new version"
},
"loadingMessages": {
"message": "Indlæser beskeder. $count$ indtil videre...",
"message": "Indlæser beskeder. $count$ indtil videre ...",
"description": "Message shown on the loading screen when we're catching up on the backlog of messages",
"placeholders": {
"count": {
@ -470,7 +470,7 @@
"description": "Shown in conversation banner when more than one group member's safety number has changed, but they were previously verified."
},
"debugLogExplanation": {
"message": "Denne log vil blive offentliggjort online, så bidragsydere kan se den. Du kan downloade hele loggen, inden du indsender den.",
"message": "Denne log vil blive offentliggjort online, så bidragsydere kan se den. Du kan hente hele loggen, inden du indsender den.",
"description": ""
},
"debugLogError": {
@ -614,7 +614,7 @@
"description": "Shown in toast when user attempts to send .exe file, for example"
},
"loadingPreview": {
"message": "Indlæser forhåndsvisning...",
"message": "Indlæser forhåndsvisning ...",
"description": "Shown while Signal Desktop is fetching metadata for a url in composition area"
},
"stagedPreviewThumbnail": {
@ -690,7 +690,7 @@
"description": "Displayed when the desktop client cannot connect to the server."
},
"connecting": {
"message": "Forbinder...",
"message": "Forbinder ...",
"description": "Displayed when the desktop client is currently connecting to the server."
},
"connect": {
@ -2070,7 +2070,7 @@
"description": "Label for a button that syncs contacts and groups from your phone"
},
"syncing": {
"message": "Importerer...",
"message": "Importerer ...",
"description": "Label for a disabled sync button while sync is in progress."
},
"syncFailed": {
@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nu",
"message": "Nu",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -2330,7 +2330,7 @@
"description": "Label text for menu bar visibility setting"
},
"startConversation": {
"message": "Start ny samtale...",
"message": "Start ny samtale ...",
"description": "Label underneath number a user enters that is not an existing contact"
},
"newConversation": {
@ -2490,7 +2490,7 @@
"description": ""
},
"downloadNewVersionMessage": {
"message": "Klik for at downloade opdatering",
"message": "Klik for at hente opdatering",
"description": ""
},
"autoUpdateNewVersionInstructions": {
@ -2760,7 +2760,7 @@
"description": "Shown in the sticker picker when one or more stickers could not be downloaded."
},
"stickers--StickerPicker--DownloadPending": {
"message": "Installerer klistermærkepakke...",
"message": "Installerer klistermærkepakke ...",
"description": "Shown in the sticker picker when one or more stickers are still downloading."
},
"stickers--StickerPicker--Empty": {
@ -3224,7 +3224,7 @@
"description": "Help text for the drop stage of the sticker creator"
},
"StickerCreator--MetaStage--title": {
"message": "Lige et par detaljer mere...",
"message": "Lige et par detaljer mere ...",
"description": "Title for the meta stage of the sticker creator"
},
"StickerCreator--MetaStage--Field--title": {
@ -3720,11 +3720,11 @@
"description": "Shown in conversation history when your video call is missed or declined"
},
"incomingAudioCall": {
"message": "Indgående lydopkald...",
"message": "Indgående lydopkald ...",
"description": "Shown in both the incoming call bar and notification for an incoming audio call"
},
"incomingVideoCall": {
"message": "Indgående videoopkald...",
"message": "Indgående videoopkald ...",
"description": "Shown in both the incoming call bar and notification for an incoming video call"
},
"incomingGroupCall__ringing-you": {
@ -3810,7 +3810,7 @@
}
},
"outgoingCallRinging": {
"message": "Ringer...",
"message": "Ringer ...",
"description": "Shown in the call screen when placing an outgoing call that is now ringing"
},
"makeOutgoingCall": {
@ -3836,7 +3836,7 @@
}
},
"callReconnecting": {
"message": "Forbinder igen...",
"message": "Forbinder igen ...",
"description": "Shown in the call screen when the call is reconnecting due to network issues"
},
"callDuration": {
@ -4156,7 +4156,7 @@
"description": "Label for describing the general non-privileged members of a group"
},
"updating": {
"message": "Opdaterer...",
"message": "Opdaterer ...",
"description": "Shown along with a spinner when an update operation takes longer than one second"
},
"GroupV2--create--you": {
@ -5938,7 +5938,7 @@
"description": "Aria label for audio attachment's Download button"
},
"MessageAudio--pending": {
"message": "Henter vedhæftet lydfil...",
"message": "Henter vedhæftet lydfil ...",
"description": "Aria label for pending audio attachment spinner"
},
"MessageAudio--slider": {
@ -6194,7 +6194,7 @@
"description": "Modal title for the custom color editor"
},
"customDisappearingTimeOption": {
"message": "Tilpas udløbstid...",
"message": "Tilpas udløbstid ...",
"description": "Text for an option in Disappearing Messages menu and Conversation Details Disappearing Messages setting when no user value is available"
},
"selectedCustomDisappearingTimeOption": {
@ -6264,7 +6264,7 @@
"description": "Label text shown when editing group description"
},
"ConversationDetailsHeader--add-group-description": {
"message": "Tilføj gruppebeskrivelse...",
"message": "Tilføj gruppebeskrivelse ...",
"description": "Placeholder text in the details header for those that can edit the group description"
},
"MediaQualitySelector--button": {
@ -6384,7 +6384,7 @@
"description": "Shown in dialog button if user has saved an empty string to delete their username"
},
"ProfileEditor--about-placeholder": {
"message": "Skriv lidt om dig selv...",
"message": "Skriv lidt om dig selv ...",
"description": "Placeholder text for about input field"
},
"ProfileEditor--first-name": {
@ -6574,7 +6574,7 @@
}
},
"Preferences__who-can--title": {
"message": "Hvem kan...",
"message": "Hvem kan ...",
"description": "Title for the 'who can do X' setting"
},
"Preferences__privacy--description": {
@ -6763,10 +6763,6 @@
"message": "Nyheder",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Denne version indeholder en række småjusteringer og fejlrettelser som sikrer, at Signal kører problemfrit.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Denne version indeholder en række småjusteringer og fejlrettelser som sikrer, at Signal kører problemfrit.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -230,7 +230,7 @@
"description": "Shown in menu for conversation, and marks conversation as unread"
},
"moveConversationToInbox": {
"message": "In Eingang verschieben",
"message": "Rückgängig",
"description": "Undoes Archive Conversation action, and moves archived conversation back to the main conversation list"
},
"pinConversation": {
@ -1050,7 +1050,7 @@
"description": "Shown in a button when a conversation is muted"
},
"mute": {
"message": "Stummschalten",
"message": "Stumm",
"description": "Shown in a button when a conversation is unmuted and can be muted"
},
"cannotUpdateDetail": {
@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "jetzt",
"message": "Jetzt",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -3628,7 +3628,7 @@
}
},
"member-of-more-than-3-groups--multiple-more": {
"message": "Mitglied von $group1$, $group2$, $group3$ und $remainingCount$ weiteren Gruppe",
"message": "Mitglied von $group1$, $group2$, $group3$ und $remainingCount$ weiteren Gruppen",
"description": "Shown in the conversation hero to indicate this user is a member of 5+ mutual groups.",
"placeholders": {
"group1": {
@ -6688,7 +6688,7 @@
"description": "Label for the sticker button in the media editor"
},
"MediaEditor__control--crop": {
"message": "Zuschneiden und Drehen",
"message": "Zuschneiden und drehen",
"description": "Label for the crop & rotate button in the media editor"
},
"MediaEditor__control--undo": {
@ -6763,10 +6763,6 @@
"message": "Was ist neu",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Diese Version enthält eine Reihe kleinerer Optimierungen und Fehlerbehebungen, damit Signal weiterhin reibungslos funktioniert.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Diese Version enthält eine Reihe kleinerer Optimierungen und Fehlerbehebungen, damit Signal weiterhin reibungslos funktioniert.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "τώρα",
"message": "Τώρα",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Νέες δυνατότητες",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Αυτή η έκδοση περιλαμβάνει διάφορες μικρές βελτιώσεις και αποσφαλματώσεις για να συνεχίσει το Signal να λειτουργεί ομαλά.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Αυτή η έκδοση περιλαμβάνει διάφορες μικρές βελτιώσεις και αποσφαλματώσεις για να συνεχίσει το Signal να λειτουργεί ομαλά.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nun",
"message": "Nun",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Kio novas",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Tiu versio enhavas kelkajn optimumaĵojn kaj riparetojn, por ke Signal plu funkciu bone.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Tiu versio enhavas kelkajn optimumaĵojn kaj riparetojn, por ke Signal plu funkciu bone.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "ahora",
"message": "Ahora",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal se ha reiniciado tras un fallo. Puedes enviarnos un informe del fallo para que investiguemos el problema.",
"message": "Signal se ha reiniciado tras un fallo. Puedes enviarnos un informe del fallo para ayudarnos a investigar el problema.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Novedades",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Esta versión contiene un par de pequeñas mejoras para que Signal funcione sin problemas.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Esta versión contiene un par de pequeñas mejoras para que Signal funcione sin problemas.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nüüd",
"message": "Nüüd",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Mis on uut",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "See versioon sisaldab paljusid väikseid parendusi, mis Signali sujuvalt käimas.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "See versioon sisaldab paljusid väikseid parendusi, mis Signali sujuvalt käimas.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "orain",
"message": "Orain",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -8,7 +8,7 @@
"description": "Shown in the about box for the link to https://signal.org/legal"
},
"copyErrorAndQuit": {
"message": "کپی خطا و خروج",
"message": "کپی از خطا و خروج",
"description": "Shown in the top-level error popup, allowing user to copy the error text and close the app"
},
"unknownContact": {
@ -474,7 +474,7 @@
"description": ""
},
"debugLogError": {
"message": "Something went wrong with the upload! Please email support@signal.org and attach your log as a text file.",
"message": "مشکلی در آپلود رخ داد. لطفا گزارش خود را بعنوان یک فایل متنی به support@signal.org ایمیل کنید.",
"description": ""
},
"debugLogSuccess": {
@ -482,7 +482,7 @@
"description": "Title of the success page for submitting a debug log"
},
"debugLogSuccessNextSteps": {
"message": "Debug log uploaded. When you contact support, copy the link below and attach it along with a description of the problem you saw and steps to reproduce it.",
"message": "گزارش رفع عیب آپلود شد. هنگام ارتباط با پشتیبانی، لینک زیر را کپی کنید و آن را همراه با تشریح مشکل دیده شده و اقداماتی که منجر به تکرار آن می شود را پیوست کنید.",
"description": "Explanation of next steps to take when submitting debug log"
},
"debugLogCopy": {
@ -648,7 +648,7 @@
}
},
"decryptionErrorToast": {
"message": "Desktop ran into a decryption error from $name$, device $deviceId$",
"message": "برنامه دسکتاپ در رمزگشایی از سمت $name$، دستگاه $deviceId$ دچار خطا شد.",
"description": "An error popup when we haven't added an in-timeline error for decryption error, only for beta/internal users.",
"placeholders": {
"name": {
@ -1170,7 +1170,7 @@
"description": "This is a menu item for viewing all media (images + video) in a conversation, using the imperative case, as in a command."
},
"verifyHelp": {
"message": "To verify the security of your end-to-end encryption with $name$, compare the numbers above with their device.",
"message": "برای بررسی امنیت رمزنگاری دوطرفه شما با $name$، شماره های فوق را با دستگاه ایشان مقایسه کنید.",
"description": "",
"placeholders": {
"name": {
@ -1282,7 +1282,7 @@
}
},
"ChangeNumber--notification": {
"message": "$sender$ changed their phone number",
"message": "$sender$شماره تلفن خود را تغییر داد",
"description": "Shown in timeline when a member of a conversation changes their phone number",
"placeholders": {
"sender": {
@ -1340,15 +1340,15 @@
"description": "The menu option shown in Signal iOS to add a new linked device"
},
"Install__scan-this-code": {
"message": "Scan this code in the Signal app on your phone",
"message": "این کد را در برنامه سیگنال روی گوشی خود اسکن کنید",
"description": "Title of the device link screen. Also used as alt text for the QR code on the device link screen"
},
"Install__instructions__1": {
"message": "Open Signal on your phone",
"message": "باز کردن سیگنال روی گوشی",
"description": "Instructions on the device link screen"
},
"Install__instructions__2": {
"message": "Tap into $settings$, then tap $linkedDevices$",
"message": "روی $settings$کلیک کنید، سپس روی $linkedDevices$کلیک کنید.",
"description": "Instructions on the device link screen",
"placeholders": {
"settings": {
@ -1366,7 +1366,7 @@
"description": "Part of the 2nd instruction on the device link screen"
},
"Install__instructions__3": {
"message": "Tap $plusButton$ (Android) or $linkNewDevice$ (iPhone)",
"message": "روی $plusButton$ (اندروید) یا $linkNewDevice$(آیفون) کلیک کنید.",
"description": "Instructions on the device link screen",
"placeholders": {
"plusButton": {
@ -1380,7 +1380,7 @@
}
},
"Install__qr-failed": {
"message": "The QR code couldn't load. Check your internet and try again. $learnMore$",
"message": "کد QR بارگزاری نشد. اینترنت خود را بررسی کنید و مجددا سعی کنید. $learnMore$",
"description": "Shown on the install screen if the QR code fails to load",
"placeholders": {
"learnMore": {
@ -1398,11 +1398,11 @@
"description": "Shown on the install screen. Link takes users to a support page"
},
"Install__choose-device-name__description": {
"message": "You'll see this name under \"Linked Devices\" on your phone",
"message": "این نام را زیر \"دستگاه های متصل\" روی گوشی خود خواهید دید.",
"description": "The subheader shown on the 'choose device name' screen in the device linking process"
},
"Install__choose-device-name__placeholder": {
"message": "My Computer",
"message": "کامپیوتر من",
"description": "The placeholder for the 'choose device name' input"
},
"Preferences--device-name": {
@ -1422,7 +1422,7 @@
"description": "Shown during initial link while contacts and groups are being pulled from mobile device"
},
"initialSync__subtitle": {
"message": "Note: Your chat history will not be synced to this device",
"message": "نکته: تاریخچه گفتگوی شما با این دستگاه همگام‌سازی نخواهد شد.",
"description": "Shown during initial link while contacts and groups are being pulled from mobile device"
},
"installConnectionFailed": {
@ -1442,7 +1442,7 @@
"description": ""
},
"installUnknownError": {
"message": "An unexpected error occurred. Please try again.",
"message": "خطای غیرمنتظره ای رخ داد. لطفا مجددا تلاش کنید.",
"description": ""
},
"installTryAgain": {
@ -1478,7 +1478,7 @@
"description": "Button label in the call lobby for returning to a call"
},
"calling__lobby-automatically-muted-because-there-are-a-lot-of-people": {
"message": "Microphone muted due to the size of the call",
"message": "میکروفون بدلیل حجم تماس، بسته شد.",
"description": "Shown in a call lobby toast if there are a lot of people already on the call"
},
"calling__call-is-full": {
@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "اکنون",
"message": "حالا",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -2350,11 +2350,11 @@
"description": "Label shown when there are no conversations to compose to"
},
"Toast--failed-to-fetch-username": {
"message": "Failed to fetch username. Check your connection and try again.",
"message": "خطا در دریافت نام کاربری. اینترنت خود را بررسی کنید و مجددا تلاش کنید.",
"description": "Shown if request to Signal servers to find username fails"
},
"startConversation--username-not-found": {
"message": "User not found. $atUsername$ is not a Signal user; make sure youve entered the complete username.",
"message": "کاربر یافت نشد. $atUsername$کاربر سیگنال نیست. مطمئن شوید که نام کاربری را کامل وارد کرده اید.",
"description": "Shown in dialog if username is not found. Note that 'username' will be the output of at-username",
"placeholders": {
"atUsername": {
@ -2506,7 +2506,7 @@
"description": ""
},
"autoUpdateIgnoreButtonLabel": {
"message": "Ignore update",
"message": "رد بروزرسانی",
"description": ""
},
"leftTheGroup": {
@ -2582,7 +2582,7 @@
}
},
"ConversationList__aria-label": {
"message": "Conversation with $title$, $unreadCount$ new messages, last message: $lastMessage$.",
"message": "مکالمه با $title$، $unreadCount$ پیام جدید، آخرین پیام: $lastMessage$.",
"description": "Aria label for the conversation list item",
"placeholders": {
"title": {
@ -2600,11 +2600,11 @@
}
},
"ConversationList__last-message-undefined": {
"message": "The last message may have been deleted.",
"message": "آخرین پیام ممکن است حذف شده باشد",
"description": "For aria-label within conversation list. Describes if last message is not defined."
},
"BaseConversationListItem__aria-label": {
"message": "Go to conversation with $title$",
"message": "برو به مکالمه با $title$",
"description": "Aria label for the conversation list item button",
"placeholders": {
"title": {
@ -3190,11 +3190,11 @@
"description": "Title for the drop stage of the sticker creator"
},
"StickerCreator--DropStage--removeSticker": {
"message": "Remove sticker",
"message": "حذف استیکر",
"description": "Label for the X button used to remove a staged sticker"
},
"StickerCreator--DropStage--dragDrop": {
"message": "Click or drag/drop a file to add a sticker",
"message": "برای افزودن یک استیکر کلیک کنید یا یک فایل را اینجا بکشید",
"description": "Shown on the + section of the file addition stage of sticker pack creation"
},
"StickerCreator--DropStage--help": {
@ -3610,7 +3610,7 @@
}
},
"member-of-more-than-3-groups--one-more": {
"message": "Member of $group1$, $group2$, $group3$ and one more",
"message": "عضو $group1$، $group2$، $group3$ و یک گروه دیگر",
"description": "Shown in the conversation hero to indicate this user is a member of four mutual groups",
"placeholders": {
"group1": {
@ -3924,7 +3924,7 @@
"description": "Title for the select your screen sharing sources modal"
},
"calling__SelectPresentingSourcesModal--confirm": {
"message": "Start sharing",
"message": "شروع اشتراک گذاری",
"description": "Confirm button for sharing screen modal"
},
"calling__SelectPresentingSourcesModal--entireScreen": {
@ -5392,11 +5392,11 @@
"description": "In the instructions for becoming a sustainer. The heading."
},
"BadgeSustainerInstructions__subheader": {
"message": "Signal is powered by people like you. Contribute and receive a badge.",
"message": "فدرت سیگنال در حضور افرادی چون شماست. مشارکت کنید و یک نشان دریافت کنید.",
"description": "In the instructions for becoming a sustainer. The subheading."
},
"BadgeSustainerInstructions__instructions__1": {
"message": "Open Signal on your phone",
"message": "باز کردن سیگنال روی گوشی",
"description": "In the instructions for becoming a sustainer. First instruction."
},
"BadgeSustainerInstructions__instructions__2": {
@ -5404,7 +5404,7 @@
"description": "In the instructions for becoming a sustainer. Second instruction."
},
"BadgeSustainerInstructions__instructions__3": {
"message": "Tap on \"Become a Sustainer\" and subscribe",
"message": "روی \"حامی شدن\" کلیک کنید و اشتراک بگیرید.",
"description": "In the instructions for becoming a sustainer. Third instruction."
},
"CompositionArea--expand": {
@ -5454,7 +5454,7 @@
}
},
"ContactModal--rm-admin-info": {
"message": "Remove $contact$ as group admin?",
"message": "حذف $contact$بعنوان مدیر گروه؟",
"description": "Shown in a confirmation dialog when you are about to remove admin privileges from someone",
"placeholders": {
"contact": {
@ -5480,7 +5480,7 @@
"description": "This is a button in the conversation context menu to show chat settings"
},
"ConversationDetails__unmute--title": {
"message": "Unmute this chat?",
"message": "این گفتگو صدادار بشود؟",
"description": "Title for the modal to unmute a chat"
},
"ConversationDetails--group-link": {
@ -5496,7 +5496,7 @@
"description": "This is the info about the disappearing messages setting, in groups"
},
"ConversationDetails--disappearing-messages-info--direct": {
"message": "When enabled, messages sent and received in this 1:1 chat will disappear after they've been seen.",
"message": "وقتی فعال بشود، پیام های ارسالی و دریافتی در این گفتگوی 1به1 پس از دیده شدن ناپدید خواهند شد",
"description": "This is the info about the disappearing messages setting, for direct conversations"
},
"ConversationDetails--notifications": {
@ -5740,7 +5740,7 @@
}
},
"PendingInvites--revoke-from-plural": {
"message": "Revoke $number$ invites sent by \"$name$\"?",
"message": "لغو $number$دعوت ارسالی از \"$name$\"؟",
"description": "This is the modal content when confirming revoking multiple invites",
"placeholders": {
"number": {
@ -5892,7 +5892,7 @@
"description": "The text of the button to create new groups"
},
"selectContact": {
"message": "Select contact $name$",
"message": "انتخاب $name$",
"description": "The label for contact checkboxes that are non-selected (clicking them should select the contact)",
"placeholders": {
"name": {
@ -5902,7 +5902,7 @@
}
},
"deselectContact": {
"message": "De-select contact $name$",
"message": "عدم انتخاب $name$",
"description": "The label for contact checkboxes that are selected (clicking them should de-select the contact)",
"placeholders": {
"name": {
@ -5912,7 +5912,7 @@
}
},
"cannotSelectContact": {
"message": "Cannot select contact $name$",
"message": "امکان انتخاب $name$ ممکن نیست",
"description": "The label for contact checkboxes that are disabled",
"placeholders": {
"name": {
@ -6332,7 +6332,7 @@
"description": "Shown on the edit username screen"
},
"ProfileEditor--username--check-characters": {
"message": "Usernames may only contain a-z, 0-9 and _",
"message": "نام کاربری فقط میتواند شامل حروف، 0-9 و _ باشد",
"description": "Shown if user has attempted to use forbidden characters"
},
"ProfileEditor--username--check-starting-character": {
@ -6340,7 +6340,7 @@
"description": "Shown if user has attempted to begin their username with a number"
},
"ProfileEditor--username--check-character-min": {
"message": "Usernames must have a least $min$ characters.",
"message": "نام کاربری حتما باید دارای حداقل $min$کاراکتر باشد",
"description": "Shown if user has attempted to enter a username with too few characters - currently min is 3",
"placeholders": {
"min": {
@ -6350,7 +6350,7 @@
}
},
"ProfileEditor--username--check-character-max": {
"message": "Usernames must have at most $max$ characters.",
"message": "نام کاربری حتما باید دارای حداکثر $max$کاراکتر باشد",
"description": "Shown if user has attempted to enter a username with too many characters - currently min is 25",
"placeholders": {
"max": {
@ -6364,19 +6364,19 @@
"description": "Shown if user has attempted to save a username which is not available"
},
"ProfileEditor--username--general-error": {
"message": "Your username couldnt be saved. Check your connection and try again.",
"message": "نام کاربری شما ذخیره نشد. ارتباط خود را چک کنید و مجددا تلاش کنید",
"description": "Shown if something unknown has gone wrong with username save."
},
"ProfileEditor--username--delete-general-error": {
"message": "Your username couldnt be removed. Check your connection and try again.",
"message": "نام کاربری شما حذف نشد. ارتباط خود را چک کنید و مجددا تلاش کنید",
"description": "Shown if something unknown has gone wrong with username delete."
},
"ProfileEditor--username--delete-username": {
"message": "Delete username",
"message": "حذف نام کاربری",
"description": "Shown as aria label for trash icon next to username"
},
"ProfileEditor--username--confirm-delete-body": {
"message": "This will remove your username, allowing other users to claim it. Are you sure?",
"message": "این کار، نام کاربری شما را حذف خواهد کرد و منجر می شود دیگران بتوانند از آن استفاده بکنند. آیا مطمئن هستید؟",
"description": "Shown in dialog body if user has saved an empty string to delete their username"
},
"ProfileEditor--username--confirm-delete-button": {
@ -6446,7 +6446,7 @@
"description": "Title for about editing"
},
"ProfileEditorModal--avatar": {
"message": "Your Avatar",
"message": "آواتار شما",
"description": "Title for profile avatar editing"
},
"ProfileEditorModal--username": {
@ -6640,19 +6640,19 @@
}
},
"NSIS__retry-dialog--first-line": {
"message": "Signal cannot be closed.",
"message": "سیگنال بسته نمی شود",
"description": "First line of the dialog displayed when Windows installer can't close application automatically and needs user intervention to complete the installation."
},
"NSIS__retry-dialog--second-line": {
"message": "Please close it manually and click Retry to continue.",
"message": "لطفاً آن را بصورت دستی ببندید و برای ادامه روی تلاش مجدد کلیک کنید",
"description": "Second line of the dialog displayed when Windows installer can't close application automatically and needs user intervention to complete the installation."
},
"CrashReportDialog__title": {
"message": "Application crashed",
"message": "برنامه خراب شد",
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "سیگنال بعد از خرابی ریستارت شد. شما میتوانید گزارش خرابی را برای کمک به سیگنال جهت تحقیق روی این موضوع ثبت کنید.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6660,7 +6660,7 @@
"description": "A button label for submission of the crash reporter data after a recent crash"
},
"CrashReportDialog__erase": {
"message": "Don't Send",
"message": "ارسال نکن",
"description": "A button label for erasure of the crash reporter data after a recent crash and continuing to start the app"
},
"CustomizingPreferredReactions__title": {
@ -6668,11 +6668,11 @@
"description": "Shown in the header of the modal for customizing the preferred reactions. Also shown in the tooltip for the button that opens this modal."
},
"CustomizingPreferredReactions__subtitle": {
"message": "Click to replace an emoji",
"message": "برای جایگزینی یک ایموجی کلیک کنید",
"description": "Instructions in the modal for customizing the preferred reactions."
},
"CustomizingPreferredReactions__had-save-error": {
"message": "There was an error when saving your settings. Please try again.",
"message": "خطایی در زمان ذخیره‌سازی تنظیمات شما رخ داد. لطفاً مجددا تلاش کنید",
"description": "Shown if there is an error when saving your preferred reaction settings. Should be very rare to see this message."
},
"MediaEditor__control--draw": {
@ -6680,7 +6680,7 @@
"description": "Label for the draw button in the media editor"
},
"MediaEditor__control--text": {
"message": "Add text",
"message": "افزودن متن",
"description": "Label for the text button in the media editor"
},
"MediaEditor__control--sticker": {
@ -6688,7 +6688,7 @@
"description": "Label for the sticker button in the media editor"
},
"MediaEditor__control--crop": {
"message": "Crop and rotate",
"message": "برش و چرخش",
"description": "Label for the crop & rotate button in the media editor"
},
"MediaEditor__control--undo": {
@ -6700,35 +6700,35 @@
"description": "Label for the redo button in the media editor"
},
"MediaEditor__text--regular": {
"message": "Regular",
"message": "معمولی",
"description": "Describes what attribute the color picker will change on the text"
},
"MediaEditor__text--highlight": {
"message": "Highlight",
"message": "هایلایت",
"description": "Describes what attribute the color picker will change on the text"
},
"MediaEditor__text--outline": {
"message": "Outline",
"message": "خط بیرونی",
"description": "Describes what attribute the color picker will change on the text"
},
"MediaEditor__text--underline": {
"message": "Underline",
"message": "خط زیرین",
"description": "Describes what attribute the color picker will change on the text"
},
"MediaEditor__draw--pen": {
"message": "Pen",
"message": "قلم",
"description": "Type of brush to free draw"
},
"MediaEditor__draw--highlighter": {
"message": "Highlighter",
"message": "ماژیک",
"description": "Type of brush to free draw"
},
"MediaEditor__draw--thin": {
"message": "Thin",
"message": "نازک",
"description": "Tip width of the brush"
},
"MediaEditor__draw--regular": {
"message": "Regular",
"message": "معمولی",
"description": "Tip width of the brush"
},
"MediaEditor__draw--medium": {
@ -6736,7 +6736,7 @@
"description": "Tip width of the brush"
},
"MediaEditor__draw--heavy": {
"message": "Heavy",
"message": "ضخیم",
"description": "Tip width of the brush"
},
"MediaEditor__crop--reset": {
@ -6744,7 +6744,7 @@
"description": "Reset the crop state"
},
"MediaEditor__crop--rotate": {
"message": "Rotate",
"message": "چرخش",
"description": "Rotate the canvas"
},
"MediaEditor__crop--flip": {
@ -6756,31 +6756,27 @@
"description": "Lock the aspect ratio"
},
"MediaEditor__crop--crop": {
"message": "Crop",
"message": "برش",
"description": "Performs the crop"
},
"WhatsNew__modal-title": {
"message": "تازه‌ها",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"message": "این نسخه شامل شماری از بهینه سازی های کوچک و رفع عیب برای تداوم اجرای راحت سیگنال می باشد",
"description": "Release notes for releases that only include bug fixes"
},
"WhatsNew__v5.26--1": {
"message": "Tired: Sending plain un-edited images on Signal. Wired: Adding cat stickers, neon text, and drawing happy trees on your images before sending them on Signal.",
"message": "اگر از ارسال تصاویر ساده ویرایش نشده روی سیگنال خسته شده اید، میتوانید استیکر گربه، متن چراغانی، و نقاشی درختان شاد رو قبل از ارسال روی سیگنال اضافه بکنید",
"description": "Release notes for v5.26"
},
"WhatsNew__v5.26--2": {
"message": "Ever feel like you need more pixels on the right pane in your life? Are you a fan of avatars, but only avatars and nothing else? Do you have a \"Save the screen real estate\" bumper sticker on your car? If you answered yes or no to any of those questions, then this update has got some collapsible left pane for you.",
"message": "آیا تا به حال احساس کرده اید که در زندگی خود به پیکسل های بیشتری در صفحه سمت راست نیاز دارید؟ آیا شما طرفدار آواتارها هستید، اما فقط آواتارها و نه چیز دیگری؟ آیا برچسب \"کاکام ممد\" روی سپر ماشین خود دارید؟ اگر به هر یک از این سؤالات پاسخ مثبت یا خیر داده اید، این به روز رسانی برای شما یک صفحه جمع شونده سمت چپ دارد.",
"description": "Release notes for v5.26"
},
"WhatsNew__macos-m1": {
"message": "Signal Desktop is now optimized for Apple's M1 chip which is used in their newer computers. If you're on one of those new-fangled devices, the app should be much snappier. If you're not, give a warm welcome to the users that are. Huge thanks to $dennis$ for his hard work here!",
"message": "اپ سیگنال دسکتاپ هم اکنون برای چیپست M1 اپل بهینه سازی شده است که در کامپیوترهای جدیدشان استفاده می شود. اگر شما هم یکی از آن دستگاه ها را دارید، اپ سیگنال باید بسیار سریع تر باشد. اگر هم نه، به کاربرانی که آن را دارند خوش آمد بگویید. با تشکر فراوان از $dennis$بابت کار هایی که اینجا کرد.",
"description": "Release note for the macOS M1 release",
"placeholders": {
"dennis": {
@ -6790,19 +6786,19 @@
}
},
"WhatsNew__v5.27--1": {
"message": "On a long call? Your system should stay awake the whole time, instead of falling asleep while you're in the middle of an important discussion.",
"message": "تماس طولانی دارید؟ سیستم شما بجای خوابیدن در زمانی که وسط یک مباحثه مهم هستید، باید در تمام مدت روشن باشد.",
"description": "Release notes for v5.27"
},
"WhatsNew__v5.27--2": {
"message": "There are also a number of small tweaks and bug fixes to keep Signal running smoothly, including several calling-related improvements.",
"message": "همچنین شماری از بهینه سازی های کوچک و رفع عیب هایی برای حفظ اجرای راحت سیگنال وجود دارند، همانند: چندین بهینه سازی مرتبط با تماس ها.",
"description": "Release notes for v5.27"
},
"WhatsNew__v5.28--1": {
"message": "New year, new initial setup screen. We've redesigned the initial setup screens just in time for 2022.",
"message": "سال نو هست و تنظیمات صفحه رو جدید کن. ما تنظیمات صفحه اولیه رو برای سال 2022 بازطراحی کردیم",
"description": "Release notes for v5.28"
},
"WhatsNew__v5.29--1": {
"message": "Now, with fewer frantic searches for the loud typist or heavy chewer! In the call lobby, Desktop will now automatically disable audio if there are eight or more people in the call.",
"message": "الان، انگار سروصدا زیاد هست. توی لابی تماس، اگر هشت نفر یا بیشتر توی تماس باشن، اپ دسکتاپ بصورت خودکار صدا را غیرفعال خواهد کرد.",
"description": "Release notes for v5.28"
}
}

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nyt",
"message": "Nyt",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Uudet ominaisuudet",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Tämä versio sisältää useita pieniä parannuksia ja virhekorjauksia, jotka pitävät Signalin toiminnan sujuvana.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Tämä versio sisältää useita pieniä parannuksia ja virhekorjauksia, jotka pitävät Signalin toiminnan sujuvana.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "maintenant",
"message": "À linstant",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal a redémarré après un plantage. Vous pouvez envoyer un rapport de plantage pour aider Signal à enquêter sur le problème.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Les nouveautés",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Cette version contient un certain nombre de petits ajustements et de corrections de bogues pour assurer le bon fonctionnement de Signal.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Cette version contient un certain nombre de petits ajustements et de corrections de bogues pour assurer le bon fonctionnement de Signal.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "હમણાં ",
"message": "હમણાં",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "כעת",
"message": "עכשיו",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "מה חדש",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "גרסה זו מכילה מספר של שפצורים קטנים ותיקוני תקלים כדי לשמור על Signal שירוץ באופן חלק.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "גרסה זו מכילה מספר של שפצורים קטנים ותיקוני תקלים כדי לשמור על Signal שירוץ באופן חלק.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "नया क्या है",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "सिग्नल को सही रूप से चलाने के लिए इस वर्शन में कई छोटे बदलाव और बग फ़िक्स शामिल हैं.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "सिग्नल को सही रूप से चलाने के लिए इस वर्शन में कई छोटे बदलाव और बग फ़िक्स शामिल हैं.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "sada",
"message": "Sada",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "mostanában",
"message": "Most",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Újdonságok",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Ebbe a verzióba néhány kisebb újítás és hibajavítás került annak érdekében, hogy a Signal továbbra is gond nélkül fusson.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Ebbe a verzióba néhány kisebb újítás és hibajavítás került annak érdekében, hogy a Signal továbbra is gond nélkül fusson.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "sekarang",
"message": "Sekarang",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Yang Baru",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Versi ini mengandung sejumlah perubahan kecil dan perbaikan bug agar Signal tetap berjalan lancar.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Versi ini mengandung sejumlah perubahan kecil dan perbaikan bug agar Signal tetap berjalan lancar.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "núna",
"message": "Núna",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal endurræsti eftir hrun. Þú getur sent inn hrunskýrslu til að hjálpa Signal við að rannsaka vandamálið.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Hvað er nýtt",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Þessi útgáfa inniheldur nokkrar villuleiðréttingar og fínstillingar til að Signal keyri sem áreiðanlegast.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Þessi útgáfa inniheldur nokkrar villuleiðréttingar og fínstillingar til að Signal keyri sem áreiðanlegast.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "ora",
"message": "Ora",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Cosa c'è di nuovo",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Questa versione contiene una serie di piccole modifiche e correzioni di bug per far funzionare Signal senza problemi.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Questa versione contiene una serie di piccole modifiche e correzioni di bug per far funzionare Signal senza problemi.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signalはクラッシュ後に再起動しました。クラッシュレポートをSignalに送信いただくと、この問題の解決に役立ちます。",
"message": "Signalがクラッシュ後に再起動しました。クラッシュレポートを提出いただくと、Signalの問題の調査に役立てられます。",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "更新情報",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "このバージョンではSignalをより良くするために、細かい変更とバグ修正を行いました。",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Signalをスムーズに動作させるための微調整とバグ修正を行いました。",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "ឥឡូវ",
"message": "ឥឡូវនេះ",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "aniha",
"message": "Aniha",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "ດຽວນີ້",
"message": "Now",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -1478,7 +1478,7 @@
"description": "Button label in the call lobby for returning to a call"
},
"calling__lobby-automatically-muted-because-there-are-a-lot-of-people": {
"message": "Microphone muted due to the size of the call",
"message": "Mikrofonas nutildytas dėl skambutyje dalyvaujančių žmonių skaičiaus",
"description": "Shown in a call lobby toast if there are a lot of people already on the call"
},
"calling__call-is-full": {
@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "dabar",
"message": "Dabar",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal buvo paleista iš naujo po strigties. Galite pateikti pranešimą apie strigtį, kad padėtumėte Signal ištirti problemą.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Kas naujo",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Šioje versijoje yra daug smulkių patobulinimų ir klaidų ištaisymų, kurie padės Signal sklandžiai veikti.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Šioje versijoje yra daug smulkių patobulinimų ir klaidų ištaisymų, kurie padės Signal sklandžiai veikti.",
"description": "Release notes for releases that only include bug fixes"
@ -6802,7 +6798,7 @@
"description": "Release notes for v5.28"
},
"WhatsNew__v5.29--1": {
"message": "Now, with fewer frantic searches for the loud typist or heavy chewer! In the call lobby, Desktop will now automatically disable audio if there are eight or more people in the call.",
"message": "Dabar, nebereikia ieškoti, kas garsiai rašo klaviatūra ar čepsi! Programa automatiškai išjungs garsą laukimo salėje, jei skambutyje dalyvaus aštuoni ar daugiau kaip aštuoni žmonės.",
"description": "Release notes for v5.28"
}
}

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "tagad",
"message": "Tagad",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "сега",
"message": "Сега",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -1534,11 +1534,11 @@
"description": "Button tooltip label for stopping screen sharing"
},
"calling__button--ring__label": {
"message": "Ring",
"message": "റിംഗ്",
"description": "Label under the ring button"
},
"calling__button--ring__disabled-because-group-is-too-large": {
"message": "Group is too large to ring the participants.",
"message": "പങ്കെടുക്കുന്നവരെ വിളിക്കാൻ കഴിയാത്തത്ര വലുതാണ് ഗ്രൂപ്പ്.",
"description": "Button tooltip label when you can't ring because the group is too large"
},
"calling__button--ring__off": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6676,7 +6676,7 @@
"description": "Shown if there is an error when saving your preferred reaction settings. Should be very rare to see this message."
},
"MediaEditor__control--draw": {
"message": "Draw",
"message": "വരയ്ക്കുക",
"description": "Label for the draw button in the media editor"
},
"MediaEditor__control--text": {
@ -6748,7 +6748,7 @@
"description": "Rotate the canvas"
},
"MediaEditor__crop--flip": {
"message": "Flip",
"message": "തിരിക്കൂ",
"description": "Flip/mirror the canvas"
},
"MediaEditor__crop--lock": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "नवीन काय आहे",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Signal निर्विघ्नपणे चालत ठेवण्यासाठी या आवृत्तीत अनेक लहान समन्वय आणि त्रुटी दुरुस्त्या समाविष्ट आहेत.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Signal निर्विघ्नपणे चालत ठेवण्यासाठी या आवृत्तीत अनेक लहान समन्वय आणि त्रुटी दुरुस्त्या समाविष्ट आहेत",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "sekarang",
"message": "Sekarang",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Perkara Baharu",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Versi ini mengandungi sedikit tweak kecil dan pembetulan pepijat untuk memastikan Signal berjalan dengan lancar.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Versi ini mengandungi sedikit tweak kecil dan pembetulan pepijat untuk memastikan Signal berjalan dengan lancar.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nå",
"message": "Nå",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -1282,7 +1282,7 @@
}
},
"ChangeNumber--notification": {
"message": "$sender$ heeft zijn of haar telefoonnummer veranderd",
"message": "$sender$ heeft zijn of haar telefoonnummer gewijzigd",
"description": "Shown in timeline when a member of a conversation changes their phone number",
"placeholders": {
"sender": {
@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nu",
"message": "Nu",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "wat er nieuw is",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Deze versie bevat een aantal kleine foutoplossingen waardoor Signal voor nog meer mensen goed werkt.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Deze versie bevat een aantal kleine foutoplossingen waardoor Signal voor nog meer mensen goed werkt.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "no",
"message": "No",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Kva er nytt",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nå",
"message": "Nå",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "ਨਵਾਂ ਕੀ ਹੈ",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "teraz",
"message": "Teraz",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Aplikacja Signal została ponownie uruchomiona po napotkaniu błędu. Możesz przesłać raport o błędzie, aby pomóc Signal zbadać ten problem.",
"message": "Aplikacja Signal odzyskała sprawność po napotkaniu błędu. Możesz przesłać raport o błędzie, aby pomóc Signal zbadać ten problem.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Co nowego",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Ta wersja zawiera wiele drobnych ulepszeń i poprawek błędów, zapewniających płynne działanie aplikacji Signal.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Ta wersja zawiera wiele drobnych ulepszeń i poprawek błędów, zapewniających płynne działanie aplikacji Signal.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "څه شی نوي دي",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "دغه نسخه یو شمېر واړه کارونه او د بوګ جوړونې لري تر څو Signal په روانه توګه سره کار ورکړي.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "دغه نسخه یو شمېر واړه کارونه او د بوګ جوړونې لري تر څو Signal په روانه توګه سره کار ورکړي.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "agora",
"message": "Agora",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Novidades",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Essa versão contém pequenos retoques e consertos no Signal para ele continuar funcionando confortavelmente.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Essa versão contém pequenos retoques e consertos no Signal para ele continuar funcionando confortavelmente.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "agora",
"message": "Agora",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6598,7 +6598,7 @@
"description": "Title for the messaging settings"
},
"Preferences--see-me": {
"message": "Ver o meu número de telemóvel",
"message": "Ver o meu número de telefone",
"description": "Label for the see my phone number setting"
},
"Preferences--find-me": {
@ -6763,10 +6763,6 @@
"message": "Novidades",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Esta versão contém um número de pequenas funcionalidades e correções de erros de forma a manter o Signal a correr suavemente.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Esta versão contém um número de pequenas funcionalidades e correções de erros de forma a manter o Signal a correr suavemente.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "acum",
"message": "Acum",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Ce este nou",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Această versiune conține o serie de mici modificări și remedieri ale unor erori pentru ca Signal să funcționeze fără probleme.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Această versiune conține o serie de mici modificări și remedieri ale unor erori pentru ca Signal să funcționeze fără probleme.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "сейчас",
"message": "Сейчас",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Что нового",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Эта версия содержит несколько небольших изменений и исправлений ошибок.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Эта версия содержит несколько небольших изменений и исправлений ошибок.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "teraz",
"message": "Teraz",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal sa po zlyhaní reštartuje. Môžete odoslať hlásenie o zlyhaní, ktoré spoločnosti Signal pomôže problém preskúmať.",
"message": "Signal sa sa reštartoval po zlyhaní. Môžete odoslať správu o zlyhaní, ktorá Signal-u pomôže problém preskúmať.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Čo je nové",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Táto verzia obsahuje množstvo drobných vylepšení a opráv chýb, ktoré zaisťujú bezproblémový chod systému Signal.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Táto verzia obsahuje množstvo drobných vylepšení a opráv chýb, ktoré zaisťujú bezproblémový chod systému Signal.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "ravnokar",
"message": "Ravnokar",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6763,10 +6763,6 @@
"message": "Kaj je novega",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "tani",
"message": "Tani",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal-i u rinis pas një vithisje. Mund të parashtroni një raport vithisjeje, për ta ndihmuar Signal-in të hetojë problemin.",
"message": "Signal-i u rinis pas një vithisjeje. Mund të parashtroni një njoftim vithisjeje, për ta ndihmuar Signal-in të hetojë problemin.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": ka të Re",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Ky version përmban një numër përimtimesh të vockla dhe ndreqje të metash për ta mbajtur të rrjedhshme punën e Signal-it.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Ky version përmban një numër përimtimesh të vockla dhe ndreqje të metash për ta mbajtur të rrjedhshme punën e Signal-it.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "сада",
"message": "Сада",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal поново покренут након пада. Можете да поднесете извештај да бисте помогли Signal-у да види проблем.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Шта ново",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -1348,7 +1348,7 @@
"description": "Instructions on the device link screen"
},
"Install__instructions__2": {
"message": "Tap into $settings$, then tap $linkedDevices$",
"message": "Tryck på $settings$, tryck sedan på $linkedDevices$",
"description": "Instructions on the device link screen",
"placeholders": {
"settings": {
@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "nu",
"message": "Nu",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -3628,7 +3628,7 @@
}
},
"member-of-more-than-3-groups--multiple-more": {
"message": "Medlem i $group1$, $group2$, $group3$ och $remainingCount$ fler",
"message": "Medlem i $group1$, $group2$, $group3$ och $remainingCount$ till",
"description": "Shown in the conversation hero to indicate this user is a member of 5+ mutual groups.",
"placeholders": {
"group1": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal startade om efter en krasch. Du kan skicka en kraschrapport för att hjälpa Signal att undersöka problemet.",
"message": "Signal startade om efter en krasch. Du kan skicka in en kraschrapport för att hjälpa Signal att undersöka problemet.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Vad är nytt",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Den här versionen innehåller ett antal små justeringar och felrättningar för att Signal ska fungera smidigt.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Den här versionen innehåller ett antal små justeringar och felrättningar för att Signal ska fungera smidigt.",
"description": "Release notes for releases that only include bug fixes"
@ -6776,7 +6772,7 @@
"description": "Release notes for v5.26"
},
"WhatsNew__v5.26--2": {
"message": "Ever feel like you need more pixels on the right pane in your life? Are you a fan of avatars, but only avatars and nothing else? Do you have a \"Save the screen real estate\" bumper sticker on your car? If you answered yes or no to any of those questions, then this update has got some collapsible left pane for you.",
"message": "Har du någonsin känt att du behöver fler pixlar på den högra rutan i ditt liv? Är du ett fan av avatarer, men bara avatarer och inget annat? Har du en \"Save the screen real estate\"-dekal på din bil? Om du svarade ja eller nej på någon av dessa frågor, så har den här uppdateringen en hopfällbar vänstra ruta för dig.",
"description": "Release notes for v5.26"
},
"WhatsNew__macos-m1": {
@ -6798,7 +6794,7 @@
"description": "Release notes for v5.27"
},
"WhatsNew__v5.28--1": {
"message": "New year, new initial setup screen. We've redesigned the initial setup screens just in time for 2022.",
"message": "Nytt år, ny inledande inställningsskärm. Vi har gjort om de första inställningsskärmarna lagom till 2022.",
"description": "Release notes for v5.28"
},
"WhatsNew__v5.29--1": {

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "เดี๋ยวนี้",
"message": "ตอนนี้",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "şimdi",
"message": "Şimdi",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal bir hata sonrası yeniden başlatıldı. Bir hata raporu gönderek Signal'in sorunu incelemesine yardımcı olabilirsin.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Neler Yeni",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Bu sürüm Signal'in sorunsuz çalışması için gereken bir takım küçük düzeltme ve hata gidermelerini içerir.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Bu sürüm Signal'in sorunsuz çalışması için gereken bir takım küçük düzeltme ve hata gidermelerini içerir.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "зараз",
"message": "Зараз",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal запущено знов після аварійного завершення роботи. Ви можете подати звіт про це, щоб допомогти Signal з'ясувати обставини цієї проблеми.",
"message": "Signal запущено знов після аварійного завершення роботи. Ви можете подати звіт про це, щоб допомогти Signal розібратись у цій проблемі.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Що нового",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Ця версія містить ряд невеликих налаштувань і виправлень помилок, щоб забезпечити безперебійну роботу Signal.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Ця версія містить ряд невеликих налаштувань і виправлень помилок для забезпечення безперебійної роботи Signal.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "vừa xong",
"message": "Vừa xong",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "Có gì mới",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "Phiên bản này có một số chỉnh sửa nhỏ và sửa lỗi để giữ cho Signal hoạt động mượt mà.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "Phiên bản này có một số chỉnh sửa nhỏ và sửa lỗi để giữ cho Signal hoạt động mượt mà.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "现在",
"message": "刚刚",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal restarted after a crash. You can submit a crash a report to help Signal investigate the issue.",
"message": "Signal restarted after a crash. You can submit a crash report to help Signal investigate the issue.",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "What's New",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "This version contains a number of small tweaks and bug fixes to keep Signal running smoothly.",
"description": "Release notes for releases that only include bug fixes"

View File

@ -2110,7 +2110,7 @@
}
},
"justNow": {
"message": "剛剛",
"message": "現在",
"description": "Shown if a message is very recent, less than 60 seconds old"
},
"timestampFormat_M": {
@ -6652,7 +6652,7 @@
"description": "A title of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__body": {
"message": "Signal 在當掉後重新啟動。你可以提交當機報告以幫助 Signal 研究問題。",
"message": "Signal 在當掉後重新啟動。你可以提交當機報告以協助 Signal 調查問題。",
"description": "The body of the dialog displayed when starting an application after a recent crash"
},
"CrashReportDialog__submit": {
@ -6763,10 +6763,6 @@
"message": "有甚麼新的",
"description": "Title for the whats new modal"
},
"WhatsNew__v5.25--1": {
"message": "此版本包含許多小調整和錯誤修復,以維持 Signal 穩定運作。",
"description": "Release notes for v5.25"
},
"WhatsNew__bugfixes": {
"message": "此版本包含許多小調整和錯誤修復,以維持 Signal 穩定運作。",
"description": "Release notes for releases that only include bug fixes"

View File

@ -7,6 +7,13 @@ import { Menu, Tray, app, nativeImage } from 'electron';
import * as log from '../ts/logging/log';
import type { LocaleMessagesType } from '../ts/types/I18N';
export type SystemTrayServiceOptionsType = Readonly<{
messages: LocaleMessagesType;
// For testing
createTrayInstance?: (icon: NativeImage) => Tray;
}>;
/**
* A class that manages an [Electron `Tray` instance][0]. It's responsible for creating
* and destroying a `Tray`, and listening to the associated `BrowserWindow`'s visibility
@ -23,14 +30,19 @@ export class SystemTrayService {
private isEnabled = false;
private isQuitting = false;
private unreadCount = 0;
private boundRender: typeof SystemTrayService.prototype.render;
constructor({ messages }: Readonly<{ messages: LocaleMessagesType }>) {
private createTrayInstance: (icon: NativeImage) => Tray;
constructor({ messages, createTrayInstance }: SystemTrayServiceOptionsType) {
log.info('System tray service: created');
this.messages = messages;
this.boundRender = this.render.bind(this);
this.createTrayInstance = createTrayInstance || (icon => new Tray(icon));
}
/**
@ -92,6 +104,19 @@ export class SystemTrayService {
this.render();
}
/**
* Workaround for: https://github.com/electron/electron/issues/32581#issuecomment-1020359931
*
* Tray is automatically destroyed when app quits so we shouldn't destroy it
* twice when all windows will close.
*/
markShouldQuit(): void {
log.info('System tray service: markShouldQuit');
this.tray = undefined;
this.isQuitting = true;
}
private render(): void {
if (this.isEnabled && this.browserWindow) {
this.renderEnabled();
@ -101,6 +126,11 @@ export class SystemTrayService {
}
private renderEnabled() {
if (this.isQuitting) {
log.info('System tray service: not rendering the tray, quitting');
return;
}
log.info('System tray service: rendering the tray');
this.tray = this.tray || this.createTray();
@ -177,7 +207,7 @@ export class SystemTrayService {
log.info('System tray service: creating the tray');
// This icon may be swiftly overwritten.
const result = new Tray(getDefaultIcon());
const result = this.createTrayInstance(getDefaultIcon());
// Note: "When app indicator is used on Linux, the click event is ignored." This
// doesn't mean that the click event is always ignored on Linux; it depends on how

View File

@ -1,4 +1,4 @@
// Copyright 2017-2021 Signal Messenger, LLC
// Copyright 2017-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { join, normalize } from 'path';
@ -11,19 +11,20 @@ import normalizePath from 'normalize-path';
import fastGlob from 'fast-glob';
import PQueue from 'p-queue';
import { get, pick, isNumber, isBoolean, some, debounce, noop } from 'lodash';
import type { BrowserWindow } from 'electron';
import {
app,
BrowserWindow,
clipboard,
desktopCapturer,
dialog,
ipcMain as ipc,
Menu,
powerSaveBlocker,
protocol as electronProtocol,
screen,
session,
shell,
systemPreferences,
desktopCapturer,
} from 'electron';
import { z } from 'zod';
@ -55,6 +56,7 @@ import * as attachments from './attachments';
import * as attachmentChannel from './attachment_channel';
import * as bounce from '../ts/services/bounce';
import * as updater from '../ts/updater/index';
import { updateDefaultSession } from './updateDefaultSession';
import { PreventDisplaySleepService } from './PreventDisplaySleepService';
import { SystemTrayService } from './SystemTrayService';
import { SystemTraySettingCache } from './SystemTraySettingCache';
@ -72,7 +74,6 @@ import type { MenuOptionsType } from './menu';
import { createTemplate } from './menu';
import { installFileHandler, installWebHandler } from './protocol_filter';
import * as OS from '../ts/OS';
import { createBrowserWindow } from '../ts/util/createBrowserWindow';
import { isProduction } from '../ts/util/version';
import {
isSgnlHref,
@ -135,6 +136,7 @@ const defaultWebPrefs = {
process.argv.some(arg => arg === '--enable-dev-tools') ||
getEnvironment() !== Environment.Production ||
!isProduction(app.getVersion()),
spellcheck: false,
};
function showWindow() {
@ -530,7 +532,7 @@ async function createWindow() {
);
// Create the browser window.
mainWindow = createBrowserWindow(windowOptions);
mainWindow = new BrowserWindow(windowOptions);
if (settingsChannel) {
settingsChannel.setMainWindow(mainWindow);
}
@ -968,7 +970,7 @@ function showScreenShareWindow(sourceName: string) {
y: 24,
};
screenShareWindow = createBrowserWindow(options);
screenShareWindow = new BrowserWindow(options);
handleCommonWindowEvents(screenShareWindow);
@ -1014,7 +1016,7 @@ function showAbout() {
},
};
aboutWindow = createBrowserWindow(options);
aboutWindow = new BrowserWindow(options);
handleCommonWindowEvents(aboutWindow);
@ -1057,7 +1059,7 @@ function showSettingsWindow() {
},
};
settingsWindow = createBrowserWindow(options);
settingsWindow = new BrowserWindow(options);
handleCommonWindowEvents(settingsWindow);
@ -1128,7 +1130,7 @@ async function showStickerCreator() {
},
};
stickerCreatorWindow = createBrowserWindow(options);
stickerCreatorWindow = new BrowserWindow(options);
setupSpellChecker(stickerCreatorWindow, getLocale());
handleCommonWindowEvents(stickerCreatorWindow);
@ -1193,7 +1195,7 @@ async function showDebugLogWindow() {
fullscreenable: !OS.isMacOS(),
};
debugLogWindow = createBrowserWindow(options);
debugLogWindow = new BrowserWindow(options);
handleCommonWindowEvents(debugLogWindow);
@ -1253,7 +1255,7 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
parent: mainWindow,
};
permissionsPopupWindow = createBrowserWindow(options);
permissionsPopupWindow = new BrowserWindow(options);
handleCommonWindowEvents(permissionsPopupWindow);
@ -1387,13 +1389,6 @@ ipc.on('database-error', (_event: Electron.Event, error: string) => {
});
function getAppLocale(): string {
const { env } = process;
const envLocale = env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE;
if (envLocale) {
return envLocale.replace(/_/g, '-');
}
return getEnvironment() === Environment.Test ? 'en' : app.getLocale();
}
@ -1402,6 +1397,8 @@ function getAppLocale(): string {
// Some APIs can only be used after this event occurs.
let ready = false;
app.on('ready', async () => {
updateDefaultSession(session.defaultSession);
const [userDataPath, crashDumpsPath] = await Promise.all([
realpath(app.getPath('userData')),
realpath(app.getPath('crashDumps')),
@ -1506,7 +1503,7 @@ app.on('ready', async () => {
'sql.initialize is taking more than three seconds; showing loading dialog'
);
loadingWindow = createBrowserWindow({
loadingWindow = new BrowserWindow({
show: false,
width: 300,
height: 265,
@ -1736,6 +1733,7 @@ app.on('before-quit', () => {
shouldQuit: windowState.shouldQuit(),
});
systemTrayService?.markShouldQuit();
windowState.markShouldQuit();
if (mainWindow) {

View File

@ -0,0 +1,12 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Session } from 'electron';
const SPELL_CHECKER_DICTIONARY_DOWNLOAD_URL = `https://updates.signal.org/desktop/hunspell_dictionaries/${process.versions.electron}/`;
export function updateDefaultSession(session: Session): void {
session.setSpellCheckerDictionaryDownloadURL(
SPELL_CHECKER_DICTIONARY_DOWNLOAD_URL
);
}

View File

@ -4,7 +4,7 @@
"description": "Private messaging from your desktop",
"desktopName": "signal.desktop",
"repository": "https://github.com/signalapp/Signal-Desktop.git",
"version": "5.30.0-beta.1",
"version": "5.30.0",
"license": "AGPL-3.0-only",
"author": {
"name": "Open Whisper Systems",

View File

@ -24,18 +24,15 @@
}
&__qr-code {
// This should match the size defined in the JavaScript.
$size: 256px;
align-items: center;
border: 2px solid transparent;
border-radius: 4px;
box-sizing: content-box;
display: flex;
padding: 8px;
flex-direction: column;
justify-content: center;
margin-right: 38px;
margin: 8px 38px 8px 8px;
min-height: $size;
min-width: $size;
width: $size;
@ -46,6 +43,7 @@
&--load-failed {
@include font-subtitle;
border-radius: 4px;
@include light-theme {
color: $color-gray-60;

View File

@ -714,11 +714,7 @@ export async function startApp(): Promise<void> {
}
// This one should always be last - it could restart the app
if (
window.isBeforeVersion(lastVersion, 'v1.15.0-beta.5') ||
(window.isAfterVersion(lastVersion, 'v5.24.0-alpha') &&
window.isBeforeVersion(lastVersion, 'v5.25.0'))
) {
if (window.isBeforeVersion(lastVersion, 'v5.30.0-alpha')) {
await deleteAllLogs();
window.restart();
return;
@ -1568,15 +1564,13 @@ export async function startApp(): Promise<void> {
window.Whisper.events.on('powerMonitorSuspend', () => {
log.info('powerMonitor: suspend');
messageReceiver?.pause();
suspendTasksWithTimeout();
});
window.Whisper.events.on('powerMonitorResume', () => {
log.info('powerMonitor: resume');
messageReceiver?.resume();
resumeTasksWithTimeout();
server?.checkSockets();
resumeTasksWithTimeout();
});
const reconnectToWebSocketQueue = new LatestQueue();
@ -3060,8 +3054,6 @@ export async function startApp(): Promise<void> {
{
uuid: destinationUuid,
e164: destination,
highTrust: true,
reason: `unidentifiedStatus(${timestamp})`,
}
);
if (!conversationId || conversationId === ourId) {

View File

@ -1,4 +1,4 @@
// Copyright 2018-2021 Signal Messenger, LLC
// Copyright 2018-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type {
@ -85,6 +85,7 @@ const BADGE_PLACEMENT_BY_SIZE = new Map<number, BadgePlacementType>([
[36, { bottom: -3, right: 0 }],
[40, { bottom: -6, right: -4 }],
[48, { bottom: -6, right: -4 }],
[52, { bottom: -6, right: -2 }],
[56, { bottom: -6, right: 0 }],
[64, { bottom: -6, right: 0 }],
[80, { bottom: -8, right: 0 }],

View File

@ -12,6 +12,7 @@ import {
import type { ClientZkGroupCipher } from '@signalapp/signal-client/zkgroup';
import { v4 as getGuid } from 'uuid';
import LRU from 'lru-cache';
import PQueue from 'p-queue';
import * as log from './logging/log';
import {
getCredentialsForToday,
@ -2794,6 +2795,8 @@ async function updateGroup(
},
{ viaSync = false } = {}
): Promise<void> {
const logId = conversation.idForLogging();
const { newAttributes, groupChangeMessages, members } = updates;
const ourUuid = window.textsecure.storage.user.getCheckedUuid();
@ -2859,6 +2862,38 @@ async function updateGroup(
};
});
const contactsWithoutProfileKey = new Array<ConversationModel>();
// Capture profile key for each member in the group, if we don't have it yet
members.forEach(member => {
const contact = window.ConversationController.getOrCreate(
member.uuid,
'private'
);
if (member.profileKey && !contact.get('profileKey')) {
contactsWithoutProfileKey.push(contact);
contact.setProfileKey(member.profileKey);
}
});
if (contactsWithoutProfileKey.length !== 0) {
log.info(
`updateGroup/${logId}: fetching ` +
`${contactsWithoutProfileKey.length} missing profiles`
);
const profileFetchQueue = new PQueue({
concurrency: 3,
});
await profileFetchQueue.addAll(
contactsWithoutProfileKey.map(contact => () => {
const active = contact.getActiveProfileFetch();
return active || contact.getProfiles();
})
);
}
if (changeMessagesToSave.length > 0) {
await window.Signal.Data.saveMessages(changeMessagesToSave, {
forceSave: true,
@ -2871,15 +2906,6 @@ async function updateGroup(
});
}
// Capture profile key for each member in the group, if we don't have it yet
members.forEach(member => {
const contact = window.ConversationController.get(member.uuid);
if (member.profileKey && contact && !contact.get('profileKey')) {
contact.setProfileKey(member.profileKey);
}
});
// No need for convo.updateLastMessage(), 'newmessage' handler does that
}
@ -2946,24 +2972,63 @@ async function getGroupUpdates({
group,
serverPublicParamsBase64,
newRevision,
// If we just linked and this is a group where we have been a member
// from the beggining - applying all changes since the start is the best
// case scenario.
fallbackRevision: 0,
});
return result;
} catch (error) {
const nextStep = isFirstFetch
? `fetching logs since ${newRevision}`
: 'fetching full state';
if (error.code === TEMPORAL_AUTH_REJECTED_CODE) {
// We will fail over to the updateGroupViaState call below
log.info(
`getGroupUpdates/${logId}: Temporal credential failure, now fetching full group state`
`getGroupUpdates/${logId}: Temporal credential failure, now ${nextStep}`
);
} else if (error.code === GROUP_ACCESS_DENIED_CODE) {
// We will fail over to the updateGroupViaState call below
log.info(
`getGroupUpdates/${logId}: Log access denied, now fetching full group state`
`getGroupUpdates/${logId}: Log access denied, now ${nextStep}`
);
} else {
throw error;
}
}
// Fetch of logs starting from the revision 0 failed, so we probably were
// just invited to the group. Try fetching logs from the same revision as in
// this message.
if (isFirstFetch) {
try {
const result = await updateGroupViaLogs({
group,
serverPublicParamsBase64,
newRevision,
fallbackRevision: newRevision,
});
return result;
} catch (error) {
if (error.code === TEMPORAL_AUTH_REJECTED_CODE) {
// We will fail over to the updateGroupViaState call below
log.info(
`getGroupUpdates/${logId}: Temporal credential failure, now fetching full state`
);
} else if (error.code === GROUP_ACCESS_DENIED_CODE) {
// We will fail over to the updateGroupViaState call below
log.info(
`getGroupUpdates/${logId}: Log access denied, now fetching full state`
);
} else {
throw error;
}
}
}
}
if (window.GV2_ENABLE_STATE_PROCESSING) {
@ -3081,9 +3146,11 @@ async function updateGroupViaSingleChange({
async function updateGroupViaLogs({
group,
serverPublicParamsBase64,
fallbackRevision,
newRevision,
}: {
group: ConversationAttributesType;
fallbackRevision: number;
newRevision: number;
serverPublicParamsBase64: string;
}): Promise<UpdatesResultType> {
@ -3096,6 +3163,7 @@ async function updateGroupViaLogs({
const groupCredentials = getCredentialsForToday(data);
const deltaOptions = {
group,
fallbackRevision,
newRevision,
serverPublicParamsBase64,
authCredentialBase64: groupCredentials.today.credential,
@ -3219,11 +3287,13 @@ function getGroupCredentials({
async function getGroupDelta({
group,
newRevision,
fallbackRevision,
serverPublicParamsBase64,
authCredentialBase64,
}: {
group: ConversationAttributesType;
newRevision: number;
fallbackRevision: number;
serverPublicParamsBase64: string;
authCredentialBase64: string;
}): Promise<UpdatesResultType> {
@ -3246,7 +3316,9 @@ async function getGroupDelta({
});
const currentRevision = group.revision;
let revisionToFetch = isNumber(currentRevision) ? currentRevision + 1 : 0;
let revisionToFetch = isNumber(currentRevision)
? currentRevision + 1
: fallbackRevision;
let response;
const changes: Array<Proto.IGroupChanges> = [];

View File

@ -70,27 +70,18 @@ export async function runReadOrViewSyncJob({
syncs: ReadonlyArray<SyncType>;
timestamp: number;
}>): Promise<void> {
let sendType: SendTypesType;
let doSync:
| typeof window.textsecure.messaging.syncReadMessages
| typeof window.textsecure.messaging.syncView;
if (isView) {
sendType = 'viewSync';
doSync = window.textsecure.messaging.syncView.bind(
window.textsecure.messaging
);
} else {
sendType = 'readSync';
doSync = window.textsecure.messaging.syncReadMessages.bind(
window.textsecure.messaging
);
}
if (!syncs.length) {
log.info("skipping this job because there's nothing to sync");
return;
}
let sendType: SendTypesType;
if (isView) {
sendType = 'viewSync';
} else {
sendType = 'readSync';
}
const syncTimestamps = syncs.map(sync => sync.timestamp);
log.info(
`sending ${sendType}(s) for timestamp(s) ${syncTimestamps.join(', ')}`
@ -115,6 +106,19 @@ export async function runReadOrViewSyncJob({
syncMessage: true,
});
let doSync:
| typeof window.textsecure.messaging.syncReadMessages
| typeof window.textsecure.messaging.syncView;
if (isView) {
doSync = window.textsecure.messaging.syncView.bind(
window.textsecure.messaging
);
} else {
doSync = window.textsecure.messaging.syncReadMessages.bind(
window.textsecure.messaging
);
}
try {
await Promise.all(
chunk(syncs, CHUNK_SIZE).map(batch => {

View File

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as log from '../logging/log';
@ -7,19 +7,19 @@ import type { MessageAttributesType } from '../model-types.d';
import * as Errors from '../types/errors';
export async function getMessagesById(
messageIds: ReadonlyArray<string>
messageIds: Iterable<string>
): Promise<Array<MessageModel>> {
const messagesFromMemory: Array<MessageModel> = [];
const messageIdsToLookUpInDatabase: Array<string> = [];
messageIds.forEach(messageId => {
for (const messageId of messageIds) {
const message = window.MessageController.getById(messageId);
if (message) {
messagesFromMemory.push(message);
} else {
messageIdsToLookUpInDatabase.push(messageId);
}
});
}
let rawMessagesFromDatabase: Array<MessageAttributesType>;
try {

View File

@ -213,6 +213,8 @@ export class ConversationModel extends window.Backbone
private isInReduxBatch = false;
private _activeProfileFetch?: Promise<void>;
override defaults(): Partial<ConversationAttributesType> {
return {
unreadCount: 0,
@ -4634,12 +4636,29 @@ export class ConversationModel extends window.Backbone
const queue = new PQueue({
concurrency: 3,
});
await queue.addAll(
conversations.map(
conversation => () =>
getProfile(conversation.get('uuid'), conversation.get('e164'))
)
);
// Convert Promise<void[]> that is returned by addAll() to Promise<void>
const promise = (async () => {
await queue.addAll(
conversations.map(
conversation => () =>
getProfile(conversation.get('uuid'), conversation.get('e164'))
)
);
})();
this._activeProfileFetch = promise;
try {
await promise;
} finally {
if (this._activeProfileFetch === promise) {
this._activeProfileFetch = undefined;
}
}
}
getActiveProfileFetch(): Promise<void> | undefined {
return this._activeProfileFetch;
}
async setEncryptedProfileName(encryptedName: string): Promise<void> {

View File

@ -461,7 +461,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
window.ConversationController.get(conversationId);
return conversation
? conversation.getTitle()
: window.i18n('unknownUser');
: window.i18n('unknownContact');
},
renderString: (
key: string,

View File

@ -369,12 +369,17 @@ export const getConversationCallMode = (
return CallMode.None;
};
const retryMessages = async (messageIds: Iterable<string>): Promise<void> => {
const messages = await getMessagesById(messageIds);
await Promise.all(messages.map(message => message.retrySend()));
};
// Actions
const CLEAR_MESSAGES_PENDING_CONVERSATION_VERIFICATION =
'conversations/CLEAR_MESSAGES_PENDING_CONVERSATION_VERIFICATION';
export const COLORS_CHANGED = 'conversations/COLORS_CHANGED';
export const COLOR_SELECTED = 'conversations/COLOR_SELECTED';
const CANCEL_MESSAGES_PENDING_CONVERSATION_VERIFICATION =
'conversations/CANCEL_MESSAGES_PENDING_CONVERSATION_VERIFICATION';
const COMPOSE_TOGGLE_EDITING_AVATAR =
'conversations/compose/COMPOSE_TOGGLE_EDITING_AVATAR';
const COMPOSE_ADD_AVATAR = 'conversations/compose/ADD_AVATAR';
@ -386,9 +391,6 @@ const MESSAGE_STOPPED_BY_MISSING_VERIFICATION =
const REPLACE_AVATARS = 'conversations/REPLACE_AVATARS';
const UPDATE_USERNAME_SAVE_STATE = 'conversations/UPDATE_USERNAME_SAVE_STATE';
type CancelMessagesPendingConversationVerificationActionType = {
type: typeof CANCEL_MESSAGES_PENDING_CONVERSATION_VERIFICATION;
};
type CantAddContactToGroupActionType = {
type: 'CANT_ADD_CONTACT_TO_GROUP';
payload: {
@ -399,6 +401,9 @@ type ClearGroupCreationErrorActionType = { type: 'CLEAR_GROUP_CREATION_ERROR' };
type ClearInvitedUuidsForNewlyCreatedGroupActionType = {
type: 'CLEAR_INVITED_UUIDS_FOR_NEWLY_CREATED_GROUP';
};
type ClearMessagesPendingConversationVerificationActionType = {
type: typeof CLEAR_MESSAGES_PENDING_CONVERSATION_VERIFICATION;
};
type CloseCantAddContactToGroupModalActionType = {
type: 'CLOSE_CANT_ADD_CONTACT_TO_GROUP_MODAL';
};
@ -730,11 +735,11 @@ type ReplaceAvatarsActionType = {
};
};
export type ConversationActionType =
| CancelMessagesPendingConversationVerificationActionType
| CantAddContactToGroupActionType
| ClearChangedMessagesActionType
| ClearGroupCreationErrorActionType
| ClearInvitedUuidsForNewlyCreatedGroupActionType
| ClearMessagesPendingConversationVerificationActionType
| ClearSelectedMessageActionType
| ClearUnreadMetricsActionType
| CloseCantAddContactToGroupModalActionType
@ -1243,19 +1248,39 @@ function verifyConversationsStoppingMessageSend(): ThunkAction<
void,
RootStateType,
unknown,
never
ClearMessagesPendingConversationVerificationActionType
> {
return async (_dispatch, getState) => {
const conversationIds = Object.keys(
getState().conversations.outboundMessagesPendingConversationVerification
return async (dispatch, getState) => {
const { outboundMessagesPendingConversationVerification } =
getState().conversations;
const allMessageIds = new Set<string>();
const promises: Array<Promise<unknown>> = [];
Object.entries(outboundMessagesPendingConversationVerification).forEach(
([conversationId, messageIds]) => {
for (const messageId of messageIds) {
allMessageIds.add(messageId);
}
const conversation = window.ConversationController.get(conversationId);
if (!conversation) {
return;
}
if (conversation.isUnverified()) {
promises.push(conversation.setVerifiedDefault());
}
promises.push(conversation.setApproved());
}
);
await Promise.all(
conversationIds.map(async conversationId => {
const conversation = window.ConversationController.get(conversationId);
await conversation?.setVerifiedDefault();
})
);
promises.push(retryMessages(allMessageIds));
dispatch({
type: CLEAR_MESSAGES_PENDING_CONVERSATION_VERIFICATION,
});
await Promise.all(promises);
};
}
@ -1317,7 +1342,7 @@ function cancelMessagesPendingConversationVerification(): ThunkAction<
void,
RootStateType,
unknown,
CancelMessagesPendingConversationVerificationActionType
ClearMessagesPendingConversationVerificationActionType
> {
return async (dispatch, getState) => {
const messageIdsPending = getMessageIdsPendingBecauseOfVerification(
@ -1329,7 +1354,7 @@ function cancelMessagesPendingConversationVerification(): ThunkAction<
});
dispatch({
type: CANCEL_MESSAGES_PENDING_CONVERSATION_VERIFICATION,
type: CLEAR_MESSAGES_PENDING_CONVERSATION_VERIFICATION,
});
await window.Signal.Data.saveMessages(
@ -1384,10 +1409,7 @@ function conversationChanged(
id
) ?? [];
if (messageIdsPending.length) {
const messagesPending = await getMessagesById(messageIdsPending);
messagesPending.forEach(message => {
message.retrySend();
});
retryMessages(messageIdsPending);
}
}
@ -2237,7 +2259,7 @@ export function reducer(
state: Readonly<ConversationsStateType> = getEmptyState(),
action: Readonly<ConversationActionType>
): ConversationsStateType {
if (action.type === CANCEL_MESSAGES_PENDING_CONVERSATION_VERIFICATION) {
if (action.type === CLEAR_MESSAGES_PENDING_CONVERSATION_VERIFICATION) {
return {
...state,
outboundMessagesPendingConversationVerification: {},

View File

@ -0,0 +1,28 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { isEmojiOnlyText } from '../../util/isEmojiOnlyText';
describe('isEmojiOnlyText', () => {
it('returns false on empty string', () => {
assert.isFalse(isEmojiOnlyText(''));
});
it('returns false on non-emoji string', () => {
assert.isFalse(isEmojiOnlyText('123'));
});
it('returns false on mixed emoji/text string', () => {
assert.isFalse(isEmojiOnlyText('12😎3'));
});
it('returns false on mixed emoji/text string starting with emoji', () => {
assert.isFalse(isEmojiOnlyText('😎12😎3'));
});
it('returns true on all emoji string', () => {
assert.isTrue(isEmojiOnlyText('😎👍😀😮‍💨'));
});
});

View File

@ -1,19 +1,20 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { MINUTE } from '../../util/durations';
import { parseRetryAfter } from '../../util/parseRetryAfter';
describe('parseRetryAfter', () => {
it('should return 1 second when passed non-strings', () => {
assert.equal(parseRetryAfter(undefined), 1000);
assert.equal(parseRetryAfter(1234), 1000);
it('should return 1 minute when passed non-strings', () => {
assert.equal(parseRetryAfter(undefined), MINUTE);
assert.equal(parseRetryAfter(1234), MINUTE);
});
it('should return 1 second with invalid strings', () => {
assert.equal(parseRetryAfter('nope'), 1000);
assert.equal(parseRetryAfter('1ff'), 1000);
it('should return 1 minute with invalid strings', () => {
assert.equal(parseRetryAfter('nope'), MINUTE);
assert.equal(parseRetryAfter('1ff'), MINUTE);
});
it('should return milliseconds on valid input', () => {

View File

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
@ -57,6 +57,7 @@ describe('<Avatar>', () => {
[36, { bottom: -3, right: 0 }],
[40, { bottom: -6, right: -4 }],
[48, { bottom: -6, right: -4 }],
[52, { bottom: -6, right: -2 }],
[56, { bottom: -6, right: 0 }],
[64, { bottom: -6, right: 0 }],
[80, { bottom: -8, right: 0 }],

View File

@ -3,9 +3,24 @@
import { assert } from 'chai';
import { _analyzeSenderKeyDevices, _waitForAll } from '../../util/sendToGroup';
import {
_analyzeSenderKeyDevices,
_waitForAll,
_shouldFailSend,
} from '../../util/sendToGroup';
import type { DeviceType } from '../../textsecure/Types.d';
import {
ConnectTimeoutError,
HTTPError,
MessageError,
OutgoingIdentityKeyError,
OutgoingMessageError,
SendMessageChallengeError,
SendMessageNetworkError,
SendMessageProtoError,
UnregisteredUserError,
} from '../../textsecure/Errors';
describe('sendToGroup', () => {
describe('#_analyzeSenderKeyDevices', () => {
@ -135,7 +150,7 @@ describe('sendToGroup', () => {
});
describe('#_waitForAll', () => {
it('returns nothing if new and previous lists are the same', async () => {
it('returns result of provided tasks', async () => {
const task1 = () => Promise.resolve(1);
const task2 = () => Promise.resolve(2);
const task3 = () => Promise.resolve(3);
@ -148,4 +163,158 @@ describe('sendToGroup', () => {
assert.deepEqual(result, [1, 2, 3]);
});
});
describe('#_shouldFailSend', () => {
it('returns false for a generic error', async () => {
const error = new Error('generic');
assert.isFalse(_shouldFailSend(error, 'testing generic'));
});
it("returns true for any error with 'untrusted' identity", async () => {
const error = new Error('This was an untrusted identity.');
assert.isTrue(_shouldFailSend(error, 'logId'));
});
it('returns true for certain types of error subclasses', async () => {
assert.isTrue(
_shouldFailSend(
new OutgoingIdentityKeyError(
'something',
new Uint8Array(),
200,
new Uint8Array()
),
'testing OutgoingIdentityKeyError'
)
);
assert.isTrue(
_shouldFailSend(
new UnregisteredUserError(
'something',
new HTTPError('something', {
code: 400,
headers: {},
})
),
'testing UnregisteredUserError'
)
);
assert.isTrue(
_shouldFailSend(
new ConnectTimeoutError('something'),
'testing ConnectTimeoutError'
)
);
});
it('returns false for unspecified error codes', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const error: any = new Error('generic');
error.code = 422;
assert.isFalse(_shouldFailSend(error, 'testing generic 422'));
error.code = 204;
assert.isFalse(_shouldFailSend(error, 'testing generic 204'));
});
it('returns true for a specified error codes', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const error: any = new Error('generic');
error.code = 401;
assert.isTrue(_shouldFailSend(error, 'testing generic'));
assert.isTrue(
_shouldFailSend(
new HTTPError('something', {
code: 404,
headers: {},
}),
'testing HTTPError'
)
);
assert.isTrue(
_shouldFailSend(
new OutgoingMessageError(
'something',
null,
null,
new HTTPError('something', {
code: 413,
headers: {},
})
),
'testing OutgoingMessageError'
)
);
assert.isTrue(
_shouldFailSend(
new SendMessageNetworkError(
'something',
null,
new HTTPError('something', {
code: 428,
headers: {},
})
),
'testing SendMessageNetworkError'
)
);
assert.isTrue(
_shouldFailSend(
new SendMessageChallengeError(
'something',
new HTTPError('something', {
code: 500,
headers: {},
})
),
'testing SendMessageChallengeError'
)
);
assert.isTrue(
_shouldFailSend(
new MessageError(
'something',
new HTTPError('something', {
code: 508,
headers: {},
})
),
'testing MessageError'
)
);
});
it('returns true for errors inside of SendMessageProtoError', () => {
assert.isTrue(
_shouldFailSend(
new SendMessageProtoError({}),
'testing missing errors list'
)
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const error: any = new Error('generic');
error.code = 401;
assert.isTrue(
_shouldFailSend(
new SendMessageProtoError({ errors: [error] }),
'testing one error with code'
)
);
assert.isTrue(
_shouldFailSend(
new SendMessageProtoError({
errors: [
new Error('something'),
new ConnectTimeoutError('something'),
],
}),
'testing ConnectTimeoutError'
)
);
});
});
});

View File

@ -8,6 +8,7 @@ import { BrowserWindow, Tray, nativeImage } from 'electron';
import * as path from 'path';
import { MINUTE } from '../../util/durations';
import type { SystemTrayServiceOptionsType } from '../../../app/SystemTrayService';
import { SystemTrayService } from '../../../app/SystemTrayService';
describe('SystemTrayService', function thisNeeded() {
@ -23,7 +24,9 @@ describe('SystemTrayService', function thisNeeded() {
*
* This only affects these tests, not the "real" code.
*/
function newService(): SystemTrayService {
function newService(
options?: Partial<SystemTrayServiceOptionsType>
): SystemTrayService {
const result = new SystemTrayService({
messages: {
hide: { message: 'Hide' },
@ -31,6 +34,7 @@ describe('SystemTrayService', function thisNeeded() {
show: { message: 'Show' },
signalDesktop: { message: 'Signal' },
},
...options,
});
servicesCreated.add(result);
return result;
@ -258,4 +262,16 @@ describe('SystemTrayService', function thisNeeded() {
sinon.assert.calledWith(setImageStub, sinon.match.string);
sinon.assert.calledWith(setImageStub, sinon.match.instanceOf(NativeImage));
});
it('should not create new Tray after markShouldQuit', () => {
const createTrayInstance = sandbox.stub();
const service = newService({ createTrayInstance });
service.setMainWindow(new BrowserWindow({ show: false }));
service.markShouldQuit();
service.setEnabled(true);
sinon.assert.notCalled(createTrayInstance);
});
});

View File

@ -0,0 +1,33 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as sinon from 'sinon';
import { session } from 'electron';
import { v4 as uuid } from 'uuid';
import { updateDefaultSession } from '../../../app/updateDefaultSession';
describe('updateDefaultSession', () => {
let sandbox: sinon.SinonSandbox;
beforeEach(() => {
sandbox = sinon.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
it('sets the spellcheck URL', () => {
const sesh = session.fromPartition(uuid());
const stub = sandbox.stub(sesh, 'setSpellCheckerDictionaryDownloadURL');
updateDefaultSession(sesh);
sinon.assert.calledOnce(stub);
sinon.assert.calledWith(
stub,
`https://updates.signal.org/desktop/hunspell_dictionaries/${process.versions.electron}/`
);
});
});

View File

@ -5,15 +5,18 @@ import { assert } from 'chai';
import { findRetryAfterTimeFromError } from '../../../jobs/helpers/findRetryAfterTimeFromError';
import { HTTPError } from '../../../textsecure/Errors';
import { MINUTE } from '../../../util/durations';
describe('findRetryAfterTimeFromError', () => {
it('returns 1 second if no Retry-After time is found', () => {
it('returns 1 minute if no Retry-After time is found', () => {
[
undefined,
null,
{},
{ responseHeaders: {} },
{ responseHeaders: { 'retry-after': 'garbage' } },
{ responseHeaders: { 'retry-after': '0.5' } },
{ responseHeaders: { 'retry-after': '12.34' } },
{
httpError: new HTTPError('Slow down', {
code: 413,
@ -29,20 +32,20 @@ describe('findRetryAfterTimeFromError', () => {
}),
},
].forEach(input => {
assert.strictEqual(findRetryAfterTimeFromError(input), 1000);
assert.strictEqual(findRetryAfterTimeFromError(input), MINUTE);
});
});
it("returns 1 second if a Retry-After time is found, but it's less than 1 second", () => {
['0', '-99', '0.5'].forEach(headerValue => {
['0', '-99'].forEach(headerValue => {
const input = { responseHeaders: { 'retry-after': headerValue } };
assert.strictEqual(findRetryAfterTimeFromError(input), 1000);
});
});
it('returns 1 second for extremely large numbers', () => {
it('returns 1 minute for extremely large numbers', () => {
const input = { responseHeaders: { 'retry-after': '999999999999999999' } };
assert.strictEqual(findRetryAfterTimeFromError(input), 1000);
assert.strictEqual(findRetryAfterTimeFromError(input), MINUTE);
});
it('finds the retry-after time on top-level response headers', () => {

View File

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
@ -39,19 +39,19 @@ describe('sleepFor413RetryAfterTimeIfApplicable', () => {
sinon.assert.notCalled(log.info);
});
it('waits for 1 second if the error lacks Retry-After info', async () => {
it('waits for 1 minute if the error lacks Retry-After info', async () => {
let done = false;
(async () => {
await sleepFor413RetryAfterTime({
err: {},
log: createLogger(),
timeRemaining: 1234,
timeRemaining: 12345678,
});
done = true;
})();
await clock.tickAsync(999);
await clock.tickAsync(durations.MINUTE - 1);
assert.isFalse(done);
await clock.tickAsync(2);

View File

@ -1,14 +0,0 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { BrowserWindow } from 'electron';
import { createBrowserWindow } from '../../util/createBrowserWindow';
describe('createBrowserWindow', () => {
it('returns a BrowserWindow', () => {
const result = createBrowserWindow({ show: false });
assert.instanceOf(result, BrowserWindow);
});
});

View File

@ -187,22 +187,6 @@ export default class MessageReceiver
private stoppingProcessing?: boolean;
pause(): void {
this.incomingQueue.pause();
this.encryptedQueue.pause();
this.decryptedQueue.pause();
this.appQueue.pause();
log.info('MessageReceiver: Paused');
}
resume(): void {
this.appQueue.start();
this.decryptedQueue.start();
this.encryptedQueue.start();
this.incomingQueue.start();
log.info('MessageReceiver: Resumed');
}
constructor({ server, storage, serverTrustRoot }: MessageReceiverOptions) {
super();
@ -219,24 +203,20 @@ export default class MessageReceiver
this.incomingQueue = new PQueue({
concurrency: 1,
timeout: 1000 * 60 * 2,
throwOnTimeout: true,
});
this.appQueue = new PQueue({
concurrency: 1,
timeout: 1000 * 60 * 2,
throwOnTimeout: true,
});
// All envelopes start in encryptedQueue and progress to decryptedQueue
this.encryptedQueue = new PQueue({
concurrency: 1,
timeout: 1000 * 60 * 2,
throwOnTimeout: true,
});
this.decryptedQueue = new PQueue({
concurrency: 1,
timeout: 1000 * 60 * 2,
throwOnTimeout: true,
});
@ -270,9 +250,11 @@ export default class MessageReceiver
request.respond(200, 'OK');
if (request.verb === 'PUT' && request.path === '/api/v1/queue/empty') {
this.incomingQueue.add(() => {
this.onEmpty();
});
this.incomingQueue.add(
createTaskWithTimeout(async () => {
this.onEmpty();
}, 'incomingQueue/onEmpty')
);
}
return;
}
@ -341,12 +323,19 @@ export default class MessageReceiver
}
};
this.incomingQueue.add(job);
this.incomingQueue.add(
createTaskWithTimeout(job, 'incomingQueue/websocket')
);
}
public reset(): void {
// We always process our cache before processing a new websocket message
this.incomingQueue.add(async () => this.queueAllCached());
this.incomingQueue.add(
createTaskWithTimeout(
async () => this.queueAllCached(),
'incomingQueue/queueAllCached'
)
);
this.count = 0;
this.isEmptied = false;
@ -363,14 +352,24 @@ export default class MessageReceiver
public async drain(): Promise<void> {
const waitForEncryptedQueue = async () =>
this.addToQueue(async () => {
log.info('drained');
}, TaskType.Decrypted);
this.addToQueue(
async () => {
log.info('drained');
},
'drain/waitForDecrypted',
TaskType.Decrypted
);
const waitForIncomingQueue = async () =>
this.addToQueue(waitForEncryptedQueue, TaskType.Encrypted);
this.addToQueue(
waitForEncryptedQueue,
'drain/waitForEncrypted',
TaskType.Encrypted
);
return this.incomingQueue.add(waitForIncomingQueue);
return this.incomingQueue.add(
createTaskWithTimeout(waitForIncomingQueue, 'drain/waitForIncoming')
);
}
//
@ -523,7 +522,12 @@ export default class MessageReceiver
//
private async dispatchAndWait(event: Event): Promise<void> {
this.appQueue.add(async () => Promise.all(this.dispatchEvent(event)));
this.appQueue.add(
createTaskWithTimeout(
async () => Promise.all(this.dispatchEvent(event)),
'dispatchEvent'
)
);
}
private calculateMessageAge(
@ -557,6 +561,7 @@ export default class MessageReceiver
private async addToQueue<T>(
task: () => Promise<T>,
id: string,
taskType: TaskType
): Promise<T> {
if (taskType === TaskType.Encrypted) {
@ -569,7 +574,7 @@ export default class MessageReceiver
: this.decryptedQueue;
try {
return await queue.add(task);
return await queue.add(createTaskWithTimeout(task, id));
} finally {
this.updateProgress(this.count);
}
@ -595,24 +600,34 @@ export default class MessageReceiver
);
// We don't await here because we don't want this to gate future message processing
this.appQueue.add(emitEmpty);
this.appQueue.add(createTaskWithTimeout(emitEmpty, 'emitEmpty'));
};
const waitForEncryptedQueue = async () => {
this.addToQueue(waitForDecryptedQueue, TaskType.Decrypted);
this.addToQueue(
waitForDecryptedQueue,
'onEmpty/waitForDecrypted',
TaskType.Decrypted
);
};
const waitForIncomingQueue = () => {
this.addToQueue(waitForEncryptedQueue, TaskType.Encrypted);
const waitForIncomingQueue = async () => {
// Note: this.count is used in addToQueue
// Resetting count so everything from the websocket after this starts at zero
this.count = 0;
this.addToQueue(
waitForEncryptedQueue,
'onEmpty/waitForEncrypted',
TaskType.Encrypted
);
};
const waitForCacheAddBatcher = async () => {
await this.decryptAndCacheBatcher.onIdle();
this.incomingQueue.add(waitForIncomingQueue);
this.incomingQueue.add(
createTaskWithTimeout(waitForIncomingQueue, 'onEmpty/waitForIncoming')
);
};
waitForCacheAddBatcher();
@ -690,9 +705,13 @@ export default class MessageReceiver
}
// Maintain invariant: encrypted queue => decrypted queue
this.addToQueue(async () => {
this.queueDecryptedEnvelope(envelope, payloadPlaintext);
}, TaskType.Encrypted);
this.addToQueue(
async () => {
this.queueDecryptedEnvelope(envelope, payloadPlaintext);
},
'queueDecryptedEnvelope',
TaskType.Encrypted
);
} else {
this.queueCachedEnvelope(item, envelope);
}
@ -744,7 +763,12 @@ export default class MessageReceiver
if (this.isEmptied) {
this.clearRetryTimeout();
this.retryCachedTimeout = setTimeout(() => {
this.incomingQueue.add(async () => this.queueAllCached());
this.incomingQueue.add(
createTaskWithTimeout(
async () => this.queueAllCached(),
'queueAllCached'
)
);
}, RETRY_TIMEOUT);
}
}
@ -982,7 +1006,11 @@ export default class MessageReceiver
);
try {
await this.addToQueue(taskWithTimeout, TaskType.Decrypted);
await this.addToQueue(
taskWithTimeout,
'dispatchEvent',
TaskType.Decrypted
);
} catch (error) {
log.error(
`queueDecryptedEnvelope error handling envelope ${id}:`,
@ -999,7 +1027,7 @@ export default class MessageReceiver
let logId = this.getEnvelopeId(envelope);
log.info(`queueing ${uuidKind} envelope`, logId);
const task = createTaskWithTimeout(async (): Promise<DecryptResult> => {
const task = async (): Promise<DecryptResult> => {
const unsealedEnvelope = await this.unsealEnvelope(
stores,
envelope,
@ -1015,14 +1043,19 @@ export default class MessageReceiver
this.addToQueue(
async () => this.dispatchEvent(new EnvelopeEvent(unsealedEnvelope)),
'dispatchEvent',
TaskType.Decrypted
);
return this.decryptEnvelope(stores, unsealedEnvelope, uuidKind);
}, `MessageReceiver: unseal and decrypt ${logId}`);
};
try {
return await this.addToQueue(task, TaskType.Encrypted);
return await this.addToQueue(
task,
`MessageReceiver: unseal and decrypt ${logId}`,
TaskType.Encrypted
);
} catch (error) {
const args = [
'queueEncryptedEnvelope error handling envelope',
@ -1645,6 +1678,7 @@ export default class MessageReceiver
// Avoid deadlocks by scheduling processing on decrypted queue
this.addToQueue(
async () => this.dispatchEvent(event),
'decrypted/dispatchEvent',
TaskType.Decrypted
);
} else {
@ -1863,8 +1897,11 @@ export default class MessageReceiver
try {
if (!conversation) {
const idForLogging = envelope.groupId
? `groupv2(${envelope.groupId})`
: envelope.sourceUuid;
log.info(
`maybeUpdateTimestamp/${timestamp}: No conversation found for identifier ${identifier}`
`maybeUpdateTimestamp/${timestamp}: No conversation found for identifier ${idForLogging}`
);
return envelope;
}

View File

@ -12,9 +12,11 @@ type TaskType = {
};
const tasks = new Set<TaskType>();
let shouldStartTimers = true;
export function suspendTasksWithTimeout(): void {
log.info(`TaskWithTimeout: suspending ${tasks.size} tasks`);
shouldStartTimers = false;
for (const task of tasks) {
task.suspend();
}
@ -22,6 +24,7 @@ export function suspendTasksWithTimeout(): void {
export function resumeTasksWithTimeout(): void {
log.info(`TaskWithTimeout: resuming ${tasks.size} tasks`);
shouldStartTimers = true;
for (const task of tasks) {
task.resume();
}
@ -75,7 +78,9 @@ export default function createTaskWithTimeout<T, Args extends Array<unknown>>(
};
tasks.add(entry);
startTimer();
if (shouldStartTimers) {
startTimer();
}
let result: unknown;

View File

@ -1,25 +0,0 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
// This is the one place that *should* be able to import `BrowserWindow`.
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { BrowserWindow } from 'electron';
import type { BrowserWindowConstructorOptions } from 'electron';
const SPELL_CHECKER_DICTIONARY_DOWNLOAD_URL = `https://updates.signal.org/desktop/hunspell_dictionaries/${process.versions.electron}/`;
/**
* A wrapper around `new BrowserWindow` that updates the spell checker download URL. This
* function should be used instead of `new BrowserWindow`.
*/
export function createBrowserWindow(
options: BrowserWindowConstructorOptions
): BrowserWindow {
const result = new BrowserWindow(options);
result.webContents.session.setSpellCheckerDictionaryDownloadURL(
SPELL_CHECKER_DICTIONARY_DOWNLOAD_URL
);
return result;
}

View File

@ -1,9 +1,22 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as grapheme from './grapheme';
import { getEmojiCount } from '../components/emoji/lib';
import emojiRegex from 'emoji-regex';
export function isEmojiOnlyText(text: string): boolean {
return grapheme.count(text) === getEmojiCount(text);
if (text.length === 0) {
return false;
}
const regex = emojiRegex();
let len = 0;
for (const match of text.matchAll(regex)) {
// Skipped some non-emoji text, return early
if (match.index !== len) {
return false;
}
len += match[0].length;
}
return len === text.length;
}

View File

@ -1,19 +1,20 @@
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { SECOND } from './durations';
import { SECOND, MINUTE } from './durations';
import { isNormalNumber } from './isNormalNumber';
const DEFAULT_RETRY_AFTER = MINUTE;
const MINIMAL_RETRY_AFTER = SECOND;
export function parseRetryAfter(value: unknown): number {
if (typeof value !== 'string') {
return MINIMAL_RETRY_AFTER;
return DEFAULT_RETRY_AFTER;
}
let retryAfter = parseInt(value, 10);
const retryAfter = parseInt(value, 10);
if (!isNormalNumber(retryAfter) || retryAfter.toString() !== value) {
retryAfter = 0;
return DEFAULT_RETRY_AFTER;
}
return Math.max(retryAfter * SECOND, MINIMAL_RETRY_AFTER);

View File

@ -23,12 +23,19 @@ import { Address } from '../types/Address';
import { QualifiedAddress } from '../types/QualifiedAddress';
import { UUID } from '../types/UUID';
import { isEnabled } from '../RemoteConfig';
import { isRecord } from './isRecord';
import { isOlderThan } from './timestamp';
import type {
GroupSendOptionsType,
SendOptionsType,
} from '../textsecure/SendMessage';
import {
ConnectTimeoutError,
OutgoingIdentityKeyError,
SendMessageProtoError,
UnregisteredUserError,
} from '../textsecure/Errors';
import type { HTTPError } from '../textsecure/Errors';
import { IdentityKeys, SenderKeys, Sessions } from '../LibSignalStores';
import type { ConversationModel } from '../models/conversations';
@ -188,10 +195,7 @@ export async function sendContentMessageToGroup({
throw error;
}
if (error.name.includes('untrusted identity')) {
log.error(
`sendToGroup/${logId}: Failed with 'untrusted identity' error, re-throwing`
);
if (_shouldFailSend(error, logId)) {
throw error;
}
@ -653,6 +657,86 @@ export async function sendToGroupViaSenderKey(options: {
// Utility Methods
export function _shouldFailSend(error: unknown, logId: string): boolean {
const logError = (message: string) => {
log.error(`_shouldFailSend/${logId}: ${message}`);
};
if (error instanceof Error && error.message.includes('untrusted identity')) {
logError("'untrusted identity' error, failing.");
return true;
}
if (error instanceof OutgoingIdentityKeyError) {
logError('OutgoingIdentityKeyError error, failing.');
return true;
}
if (error instanceof UnregisteredUserError) {
logError('UnregisteredUserError error, failing.');
return true;
}
if (error instanceof ConnectTimeoutError) {
logError('ConnectTimeoutError error, failing.');
return true;
}
// Known error types captured here:
// HTTPError
// OutgoingMessageError
// SendMessageNetworkError
// SendMessageChallengeError
// MessageError
if (isRecord(error) && typeof error.code === 'number') {
if (error.code === 401) {
logError('Permissions error, failing.');
return true;
}
if (error.code === 404) {
logError('Missing user or endpoint error, failing.');
return true;
}
if (error.code === 413) {
logError('Rate limit error, failing.');
return true;
}
if (error.code === 428) {
logError('Challenge error, failing.');
return true;
}
if (error.code === 500) {
logError('Server error, failing.');
return true;
}
if (error.code === 508) {
logError('Fail job error, failing.');
return true;
}
}
if (error instanceof SendMessageProtoError) {
if (!error.errors || !error.errors.length) {
logError('SendMessageProtoError had no errors, failing.');
return true;
}
for (const innerError of error.errors) {
const shouldFail = _shouldFailSend(innerError, logId);
if (shouldFail) {
return true;
}
}
}
return false;
}
export async function _waitForAll<T>({
tasks,
maxConcurrency = MAX_CONCURRENCY,