diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md index 832bc213f1..0ab4a752eb 100644 --- a/ACKNOWLEDGMENTS.md +++ b/ACKNOWLEDGMENTS.md @@ -4373,7 +4373,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see ``` -## attest 0.1.0, device-transfer 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-core 0.1.0, libsignal-ffi 0.46.2, libsignal-jni 0.46.2, libsignal-message-backup 0.1.0, libsignal-message-backup-io 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, libsignal-node 0.46.2, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, poksho 0.7.0, signal-crypto 0.1.0, signal-media 0.1.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, signal-pin 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0 +## attest 0.1.0, device-transfer 0.1.0, libsignal-bridge 0.1.0, libsignal-bridge-macros 0.1.0, libsignal-core 0.1.0, libsignal-ffi 0.50.0, libsignal-jni 0.50.0, libsignal-message-backup 0.1.0, libsignal-message-backup-macros 0.1.0, libsignal-net 0.1.0, libsignal-node 0.50.0, libsignal-protocol 0.1.0, libsignal-svr3 0.1.0, poksho 0.7.0, signal-crypto 0.1.0, signal-media 0.1.0, signal-neon-futures 0.1.0, signal-neon-futures-tests 0.1.0, signal-pin 0.1.0, usernames 0.1.0, zkcredential 0.1.0, zkgroup 0.9.0 ``` GNU AFFERO GENERAL PUBLIC LICENSE @@ -5237,7 +5237,7 @@ You should also get your employer (if you work as a programmer) or school, if an ``` -## ryu 1.0.17 +## ryu 1.0.18 ``` Apache License @@ -5419,7 +5419,7 @@ END OF TERMS AND CONDITIONS ``` -## debugid 0.8.0, prost 0.12.3, prost-build 0.12.3, prost-derive 0.12.3, prost-types 0.12.3 +## debugid 0.8.0, prost 0.12.6, prost-build 0.12.6, prost-derive 0.12.6, prost-types 0.12.6 ``` Apache License @@ -5922,7 +5922,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` -## encoding_rs 0.8.33 +## encoding_rs 0.8.34 ``` Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). @@ -6173,7 +6173,7 @@ THIS SOFTWARE. ``` -## rustls-webpki 0.102.2 +## rustls-webpki 0.102.4 ``` Except as otherwise noted, this project is licensed under the following @@ -6198,7 +6198,7 @@ third-party/chromium/LICENSE. ``` -## windows-core 0.52.0, windows-sys 0.45.0, windows-sys 0.48.0, windows-sys 0.52.0, windows-targets 0.42.2, windows-targets 0.48.5, windows-targets 0.52.4, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.48.5, windows_aarch64_msvc 0.52.4, windows_x86_64_gnu 0.48.5, windows_x86_64_gnu 0.52.4, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.48.5, windows_x86_64_msvc 0.52.4 +## windows-core 0.52.0, windows-sys 0.45.0, windows-sys 0.48.0, windows-sys 0.52.0, windows-targets 0.42.2, windows-targets 0.48.5, windows-targets 0.52.5, windows_aarch64_msvc 0.42.2, windows_aarch64_msvc 0.48.5, windows_aarch64_msvc 0.52.5, windows_x86_64_gnu 0.48.5, windows_x86_64_gnu 0.52.5, windows_x86_64_msvc 0.42.2, windows_x86_64_msvc 0.48.5, windows_x86_64_msvc 0.52.5 ``` MIT License @@ -6289,7 +6289,7 @@ DEALINGS IN THE SOFTWARE. ``` -## lazy_static 1.4.0, rayon 1.9.0, rayon-core 1.12.1 +## lazy_static 1.4.0, rayon 1.10.0, rayon-core 1.12.1 ``` Copyright (c) 2010 The Rust Project Developers @@ -6439,7 +6439,7 @@ DEALINGS IN THE SOFTWARE. ``` -## backtrace 0.3.69, cc 1.0.90, cfg-if 1.0.0, cmake 0.1.48, flate2 1.0.28, openssl-probe 0.1.5, rustc-demangle 0.1.23, socket2 0.5.6 +## backtrace 0.3.71, cc 1.0.98, cfg-if 1.0.0, cmake 0.1.48, flate2 1.0.30, openssl-probe 0.1.5, rustc-demangle 0.1.24, socket2 0.5.7 ``` Copyright (c) 2014 Alex Crichton @@ -6502,7 +6502,7 @@ DEALINGS IN THE SOFTWARE. ``` -## jobserver 0.1.28 +## jobserver 0.1.31 ``` Copyright (c) 2014 Alex Crichton @@ -6590,7 +6590,7 @@ DEALINGS IN THE SOFTWARE. ``` -## bitflags 1.3.2, bitflags 2.4.2, glob 0.3.1, log 0.4.21, num-bigint 0.4.4, num-derive 0.4.2, num-integer 0.1.46, num-traits 0.2.18, range-map 0.2.0, regex 1.10.3, regex-automata 0.4.6, regex-syntax 0.8.2 +## bitflags 2.5.0, glob 0.3.1, log 0.4.21, num-bigint 0.4.5, num-derive 0.4.2, num-integer 0.1.46, num-traits 0.2.19, range-map 0.2.0, regex 1.10.4, regex-automata 0.4.6, regex-syntax 0.8.3 ``` Copyright (c) 2014 The Rust Project Developers @@ -6621,7 +6621,7 @@ DEALINGS IN THE SOFTWARE. ``` -## uuid 1.7.0 +## uuid 1.8.0 ``` Copyright (c) 2014 The Rust Project Developers @@ -6679,7 +6679,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## libc 0.2.153 +## libc 0.2.155 ``` Copyright (c) 2014-2020 The Rust Project Developers @@ -6735,7 +6735,7 @@ THE SOFTWARE. ``` -## either 1.10.0, itertools 0.11.0, itertools 0.12.1, petgraph 0.6.4 +## either 1.12.0, itertools 0.12.1, petgraph 0.6.5 ``` Copyright (c) 2015 @@ -6817,7 +6817,7 @@ THE SOFTWARE. ``` -## anstyle-wincon 3.0.2 +## anstyle-wincon 3.0.3 ``` Copyright (c) 2015 Josh Triplett, 2022 The rust-cli Developers @@ -7283,7 +7283,7 @@ DEALINGS IN THE SOFTWARE. ``` -## hashbrown 0.12.3, hashbrown 0.14.3 +## hashbrown 0.12.3, hashbrown 0.14.5 ``` Copyright (c) 2016 Amanieu d'Antras @@ -7345,7 +7345,7 @@ DEALINGS IN THE SOFTWARE. ``` -## anstyle-parse 0.2.3 +## anstyle-parse 0.2.4 ``` Copyright (c) 2016 Joe Wilm and individual contributors @@ -7376,7 +7376,7 @@ DEALINGS IN THE SOFTWARE. ``` -## rustls 0.23.4, rustls-native-certs 0.7.0, rustls-pemfile 2.1.2 +## rustls 0.23.8, rustls-native-certs 0.7.0, rustls-pemfile 2.1.2 ``` Copyright (c) 2016 Joseph Birr-Pixton @@ -7558,7 +7558,7 @@ DEALINGS IN THE SOFTWARE. ``` -## multimap 0.8.3 +## multimap 0.10.0 ``` Copyright (c) 2016 multimap developers @@ -7589,7 +7589,7 @@ DEALINGS IN THE SOFTWARE. ``` -## indexmap 1.9.3, indexmap 2.2.5 +## indexmap 1.9.3, indexmap 2.2.6 ``` Copyright (c) 2016--2017 @@ -7940,7 +7940,7 @@ SOFTWARE. ``` -## h2 0.4.4 +## h2 0.4.5 ``` Copyright (c) 2017 h2 authors @@ -8065,7 +8065,7 @@ DEALINGS IN THE SOFTWARE. ``` -## bytes 1.5.0 +## bytes 1.6.0 ``` Copyright (c) 2018 Carl Lerche @@ -8127,7 +8127,7 @@ DEALINGS IN THE SOFTWARE. ``` -## autocfg 1.1.0 +## autocfg 1.3.0 ``` Copyright (c) 2018 Josh Stone @@ -8158,7 +8158,7 @@ DEALINGS IN THE SOFTWARE. ``` -## smallvec 1.13.1 +## smallvec 1.13.2 ``` Copyright (c) 2018 The Servo Project Developers @@ -8277,7 +8277,7 @@ DEALINGS IN THE SOFTWARE. ``` -## platforms 3.3.0 +## platforms 3.4.0 ``` Copyright (c) 2018-2020 The Rust Secure Code Working Group @@ -8398,7 +8398,7 @@ DEALINGS IN THE SOFTWARE. ``` -## getrandom 0.2.12 +## getrandom 0.2.15 ``` Copyright (c) 2018-2024 The rust-random Project Developers @@ -8796,7 +8796,7 @@ DEALINGS IN THE SOFTWARE. ``` -## downcast-rs 1.2.0 +## downcast-rs 1.2.1 ``` Copyright (c) 2020 Ashish Myles and contributors @@ -9040,7 +9040,7 @@ DEALINGS IN THE SOFTWARE. ``` -## anstyle 1.0.6 +## anstyle 1.0.7 ``` Copyright (c) 2022 The rust-cli Developers @@ -9090,7 +9090,7 @@ SOFTWARE. ``` -## rustls-pki-types 1.4.1 +## rustls-pki-types 1.7.0 ``` Copyright (c) 2023 Dirkjan Ochtman @@ -9171,7 +9171,7 @@ SOFTWARE. ``` -## hyper-util 0.1.3 +## hyper-util 0.1.4 ``` Copyright (c) 2023 Sean McArthur @@ -9196,7 +9196,7 @@ THE SOFTWARE. ``` -## tokio 1.36.0, tokio-macros 2.2.0, tokio-stream 0.1.14, tokio-util 0.7.10 +## tokio 1.37.0, tokio-macros 2.2.0, tokio-stream 0.1.15, tokio-util 0.7.11 ``` Copyright (c) 2023 Tokio Contributors @@ -9227,7 +9227,7 @@ DEALINGS IN THE SOFTWARE. ``` -## time 0.3.34 +## time 0.3.36 ``` Copyright (c) 2024 Jacob Pratt et al. @@ -9252,7 +9252,7 @@ SOFTWARE. ``` -## anstream 0.6.13, anstyle-query 1.0.2, clap 4.4.18, colorchoice 1.0.0, env_logger 0.10.2, toml_datetime 0.6.5, toml_edit 0.19.15 +## anstream 0.6.14, anstyle-query 1.0.3, clap 4.4.18, colorchoice 1.0.1, env_logger 0.10.2, is_terminal_polyfill 1.70.0, toml_datetime 0.6.6, toml_edit 0.19.15 ``` Copyright (c) Individual contributors @@ -9352,7 +9352,7 @@ DEALINGS IN THE SOFTWARE. ``` -## encoding_rs 0.8.33 +## encoding_rs 0.8.34 ``` Copyright Mozilla Foundation @@ -9464,7 +9464,7 @@ SOFTWARE. ``` -## miniz_oxide 0.7.2 +## miniz_oxide 0.7.3 ``` MIT License @@ -9572,7 +9572,7 @@ SOFTWARE. ``` -## crc32fast 1.4.0 +## crc32fast 1.4.2 ``` MIT License @@ -9626,6 +9626,33 @@ SOFTWARE. ``` +## macro_rules_attribute 0.2.0, macro_rules_attribute-proc_macro 0.2.0 + +``` +MIT License + +Copyright (c) 2019 Daniel Henry-Mantilla + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +``` + ## strum 0.26.2, strum_macros 0.26.2 ``` @@ -9868,7 +9895,7 @@ SOFTWARE. ``` -## cesu8 1.1.0, curve25519-dalek-derive 0.1.0, half 2.4.0, pqcrypto-internals 0.2.5, pqcrypto-kyber 0.7.9, pqcrypto-kyber 0.8.1, pqcrypto-traits 0.3.5, rustls-platform-verifier 0.3.1, rustls-platform-verifier-android 0.1.0 +## cesu8 1.1.0, curve25519-dalek-derive 0.1.0, half 2.4.1, pqcrypto-internals 0.2.5, pqcrypto-kyber 0.7.9, pqcrypto-kyber 0.8.1, pqcrypto-traits 0.3.5, rustls-platform-verifier 0.3.1, rustls-platform-verifier-android 0.1.0 ``` MIT License @@ -9935,7 +9962,7 @@ SOFTWARE. ``` -## bytemuck 1.14.3 +## bytemuck 1.16.0 ``` MIT License @@ -9982,7 +10009,7 @@ DEALINGS IN THE SOFTWARE. ``` -## adler 1.0.2, anyhow 1.0.80, async-trait 0.1.77, dyn-clone 1.0.17, fastrand 2.0.1, home 0.5.9, is-terminal 0.4.12, itoa 1.0.10, linkme 0.3.25, linkme-impl 0.3.25, linux-raw-sys 0.4.13, minimal-lexical 0.2.1, num_enum 0.6.1, num_enum_derive 0.6.1, once_cell 1.19.0, paste 1.0.14, pin-project-lite 0.2.13, prettyplease 0.2.16, proc-macro-crate 1.3.1, proc-macro2 1.0.78, quote 1.0.35, rustc-hash 1.1.0, rustix 0.38.31, rustversion 1.0.14, semver 1.0.22, send_wrapper 0.6.0, serde 1.0.197, serde_derive 1.0.197, serde_json 1.0.114, syn 1.0.109, syn 2.0.52, syn-mid 0.6.0, thiserror 1.0.57, thiserror-impl 1.0.57, unicode-ident 1.0.12, utf-8 0.7.6 +## adler 1.0.2, anyhow 1.0.86, async-trait 0.1.80, atomic-waker 1.1.2, dyn-clone 1.0.17, fastrand 2.1.0, home 0.5.9, is-terminal 0.4.12, itoa 1.0.11, linkme 0.3.26, linkme-impl 0.3.26, linux-raw-sys 0.4.14, minimal-lexical 0.2.1, num_enum 0.6.1, num_enum_derive 0.6.1, once_cell 1.19.0, paste 1.0.15, pin-project-lite 0.2.14, prettyplease 0.2.20, proc-macro-crate 1.3.1, proc-macro2 1.0.83, quote 1.0.36, rustc-hash 1.1.0, rustix 0.38.34, rustversion 1.0.17, semver 1.0.23, send_wrapper 0.6.0, serde 1.0.202, serde_derive 1.0.202, serde_json 1.0.117, syn 1.0.109, syn 2.0.66, syn-mid 0.6.0, thiserror 1.0.61, thiserror-impl 1.0.61, unicode-ident 1.0.12, utf-8 0.7.6 ``` Permission is hereby granted, free of charge, to any @@ -10154,7 +10181,7 @@ SOFTWARE. ``` -## chrono 0.4.35 +## chrono 0.4.38 ``` The MIT License (MIT) @@ -10180,7 +10207,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## base64 0.21.7, base64 0.22.0 +## base64 0.21.7, base64 0.22.1 ``` The MIT License (MIT) @@ -10207,7 +10234,7 @@ THE SOFTWARE. ``` -## aho-corasick 1.1.2, byteorder 1.5.0, memchr 2.7.1, termcolor 1.4.1, walkdir 2.5.0 +## aho-corasick 1.1.3, byteorder 1.5.0, memchr 2.7.2, termcolor 1.4.1, walkdir 2.5.0 ``` The MIT License (MIT) @@ -10263,7 +10290,7 @@ SOFTWARE. ``` -## combine 4.6.6 +## combine 4.6.7 ``` The MIT License (MIT) @@ -10318,7 +10345,7 @@ THE SOFTWARE. ``` -## security-framework 2.10.0, security-framework-sys 2.10.0 +## security-framework 2.11.0, security-framework-sys 2.11.0 ``` The MIT License (MIT) @@ -10344,7 +10371,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## data-encoding 2.5.0 +## data-encoding 2.6.0 ``` The MIT License (MIT) @@ -10480,7 +10507,7 @@ SOFTWARE. ``` -## same-file 1.0.6, winapi-util 0.1.6 +## same-file 1.0.6, winapi-util 0.1.8 ``` The MIT License (MIT) @@ -10507,7 +10534,7 @@ THE SOFTWARE. ``` -## async-compression 0.4.6 +## async-compression 0.4.10 ``` The MIT License (MIT) @@ -10534,7 +10561,40 @@ SOFTWARE. ``` -## crossbeam-deque 0.8.5, crossbeam-epoch 0.9.18, crossbeam-utils 0.8.19 +## atomic-take 1.1.0 + +``` +The MIT License (MIT) + +Copyright (c) 2019 Alice Ryhl + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +``` + +## crossbeam-deque 0.8.5, crossbeam-epoch 0.9.18, crossbeam-utils 0.8.20 ``` The MIT License (MIT) diff --git a/package.json b/package.json index f4f81d56c0..5e5a662db3 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "@react-aria/utils": "3.16.0", "@react-spring/web": "9.5.5", "@signalapp/better-sqlite3": "8.7.1", - "@signalapp/libsignal-client": "0.46.2", + "@signalapp/libsignal-client": "0.50.0", "@signalapp/ringrtc": "2.42.0", "@signalapp/windows-dummy-keystroke": "1.0.0", "@types/fabric": "4.5.3", diff --git a/protos/Backups.proto b/protos/Backups.proto index bea6fb5307..bfc08e4c99 100644 --- a/protos/Backups.proto +++ b/protos/Backups.proto @@ -80,16 +80,21 @@ message AccountData { ChatStyle defaultChatStyle = 18; } + message SubscriberData { + bytes subscriberId = 1; + string currencyCode = 2; + bool manuallyCancelled = 3; + } + bytes profileKey = 1; optional string username = 2; UsernameLink usernameLink = 3; string givenName = 4; string familyName = 5; string avatarUrlPath = 6; - bytes subscriberId = 7; - string subscriberCurrencyCode = 8; - bool subscriptionManuallyCancelled = 9; - AccountSettings accountSettings = 10; + SubscriberData donationSubscriberData = 7; + SubscriberData backupsSubscriberData = 8; + AccountSettings accountSettings = 9; } message Recipient { @@ -97,7 +102,7 @@ message Recipient { oneof destination { Contact contact = 2; Group group = 3; - DistributionList distributionList = 4; + DistributionListItem distributionList = 4; Self self = 5; ReleaseNotes releaseNotes = 6; CallLink callLink = 7; @@ -105,10 +110,15 @@ message Recipient { } message Contact { - enum Registered { - UNKNOWN = 0; - REGISTERED = 1; - NOT_REGISTERED = 2; + message Registered { } + message NotRegistered { + uint64 unregisteredTimestamp = 1; + } + + enum Visibility { + VISIBLE = 0; + HIDDEN = 1; + HIDDEN_MESSAGE_REQUEST = 2; } optional bytes aci = 1; // should be 16 bytes @@ -116,9 +126,13 @@ message Contact { optional string username = 3; optional uint64 e164 = 4; bool blocked = 5; - bool hidden = 6; - Registered registered = 7; - uint64 unregisteredTimestamp = 8; + Visibility visibility = 6; + + oneof registration { + Registered registered = 7; + NotRegistered notRegistered = 8; + } + optional bytes profileKey = 9; bool profileSharing = 10; optional string profileGivenName = 11; @@ -267,6 +281,15 @@ message AdHocCall { uint64 callTimestamp = 4; } +message DistributionListItem { + bytes distributionId = 1; // distribution list ids are uuids + + oneof item { + uint64 deletionTimestamp = 2; + DistributionList distributionList = 3; + } +} + message DistributionList { enum PrivacyMode { UNKNOWN = 0; @@ -276,11 +299,9 @@ message DistributionList { } string name = 1; - bytes distributionId = 2; // distribution list ids are uuids - bool allowReplies = 3; - uint64 deletionTimestamp = 4; - PrivacyMode privacyMode = 5; - repeated uint64 memberRecipientIds = 6; // generated recipient id + bool allowReplies = 2; + PrivacyMode privacyMode = 3; + repeated uint64 memberRecipientIds = 4; // generated recipient id } message Identity { @@ -646,6 +667,7 @@ message ChatUpdateMessage { SessionSwitchoverChatUpdate sessionSwitchover = 6; IndividualCall individualCall = 7; GroupCall groupCall = 8; + LearnedProfileChatUpdate learnedProfileChange = 9; } } @@ -743,6 +765,13 @@ message ProfileChangeChatUpdate { string newName = 2; } +message LearnedProfileChatUpdate { + oneof previousName { + uint64 e164 = 1; + string username = 2; + } +} + message ThreadMergeChatUpdate { uint64 previousE164 = 1; } diff --git a/protos/SignalStorage.proto b/protos/SignalStorage.proto index b7d5a08848..1bcaa76d6b 100644 --- a/protos/SignalStorage.proto +++ b/protos/SignalStorage.proto @@ -206,6 +206,8 @@ message AccountRecord { optional string username = 33; optional bool hasCompletedUsernameOnboarding = 34; optional UsernameLink usernameLink = 35; + optional bytes backupsSubscriberId = 36; + optional string backupsSubscriberCurrencyCode = 37; } message StoryDistributionListRecord { diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index dddc5ff150..eaeecd5959 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -3373,6 +3373,10 @@ export class ConversationModel extends window.Backbone return; } + if (this.attributes.removalStage !== 'justNotification') { + return; + } + if (this.get('pendingRemovedContactNotification')) { return; } @@ -4140,6 +4144,11 @@ export class ConversationModel extends window.Backbone this.maybeSetPendingUniversalTimer(stats.hasUserInitiatedMessages) ) ); + drop( + this.queueJob('maybeAddRemovedNotificaiton', async () => + this.maybeSetContactRemoved() + ) + ); const { preview, activity } = stats; let previewMessage: MessageModel | undefined; diff --git a/ts/services/backups/export.ts b/ts/services/backups/export.ts index f564989edb..ba4bcb8c00 100644 --- a/ts/services/backups/export.ts +++ b/ts/services/backups/export.ts @@ -70,6 +70,7 @@ import { isVerifiedChange, isChangeNumberNotification, isJoinedSignalNotification, + isTitleTransitionNotification, } from '../../state/selectors/message'; import * as Bytes from '../../Bytes'; import { canBeSynced as canPreferredReactionEmojiBeSynced } from '../../reactions/preferredReactionEmoji'; @@ -258,16 +259,21 @@ export class BackupExportStream extends Readable { recipient: { id: this.getDistributionListRecipientId(), distributionList: { - name: list.name, distributionId: uuidToBytes(list.id), - allowReplies: list.allowsReplies, deletionTimestamp: list.deletedAtTimestamp ? Long.fromNumber(list.deletedAtTimestamp) : null, - privacyMode, - memberRecipientIds: list.members.map(serviceId => - this.getOrPushPrivateRecipient({ serviceId }) - ), + + distributionList: list.deletedAtTimestamp + ? null + : { + name: list.name, + allowReplies: list.allowsReplies, + privacyMode, + memberRecipientIds: list.members.map(serviceId => + this.getOrPushPrivateRecipient({ serviceId }) + ), + }, }, }, }); @@ -451,6 +457,9 @@ export class BackupExportStream extends Readable { const usernameLink = storage.get('usernameLink'); + const subscriberId = storage.get('subscriberId'); + const backupsSubscriberId = storage.get('backupsSubscriberId'); + return { profileKey: storage.get('profileKey'), username: me.get('username') || null, @@ -465,8 +474,18 @@ export class BackupExportStream extends Readable { givenName: me.get('profileName'), familyName: me.get('profileFamilyName'), avatarUrlPath: storage.get('avatarUrl'), - subscriberId: storage.get('subscriberId'), - subscriberCurrencyCode: storage.get('subscriberCurrencyCode'), + backupsSubscriberData: Bytes.isNotEmpty(backupsSubscriberId) + ? { + subscriberId: backupsSubscriberId, + currencyCode: storage.get('backupsSubscriberCurrencyCode'), + } + : null, + donationSubscriberData: Bytes.isNotEmpty(subscriberId) + ? { + subscriberId, + currencyCode: storage.get('subscriberCurrencyCode'), + } + : null, accountSettings: { readReceipts: storage.get('read-receipt-setting'), sealedSenderIndicators: storage.get('sealedSenderIndicators'), @@ -567,7 +586,17 @@ export class BackupExportStream extends Readable { if (isMe(convo)) { res.self = {}; } else if (isDirectConversation(convo)) { - const { Registered } = Backups.Contact; + let visibility: Backups.Contact.Visibility; + if (convo.removalStage == null) { + visibility = Backups.Contact.Visibility.VISIBLE; + } else if (convo.removalStage === 'justNotification') { + visibility = Backups.Contact.Visibility.HIDDEN; + } else if (convo.removalStage === 'messageRequest') { + visibility = Backups.Contact.Visibility.HIDDEN_MESSAGE_REQUEST; + } else { + throw missingCaseError(convo.removalStage); + } + res.contact = { aci: convo.serviceId && convo.serviceId !== convo.pni @@ -581,13 +610,18 @@ export class BackupExportStream extends Readable { blocked: convo.serviceId ? window.storage.blocked.isServiceIdBlocked(convo.serviceId) : null, - hidden: convo.removalStage !== undefined, - registered: isConversationUnregistered(convo) - ? Registered.NOT_REGISTERED - : Registered.REGISTERED, - unregisteredTimestamp: convo.firstUnregisteredAt - ? Long.fromNumber(convo.firstUnregisteredAt) - : null, + visibility, + ...(isConversationUnregistered(convo) + ? { + notRegistered: { + unregisteredTimestamp: convo.firstUnregisteredAt + ? Long.fromNumber(convo.firstUnregisteredAt) + : null, + }, + } + : { + registered: {}, + }), profileKey: convo.profileKey ? Bytes.fromBase64(convo.profileKey) : null, @@ -1089,6 +1123,27 @@ export class BackupExportStream extends Readable { return { kind: NonBubbleResultKind.Directionless, patch }; } + if (isTitleTransitionNotification(message)) { + strictAssert( + message.titleTransition != null, + 'Missing title transition data' + ); + const { renderInfo } = message.titleTransition; + if (renderInfo.e164) { + updateMessage.learnedProfileChange = { + e164: Long.fromString(renderInfo.e164), + }; + } else { + strictAssert( + renderInfo.username, + 'Title transition must have username or e164' + ); + updateMessage.learnedProfileChange = { username: renderInfo.username }; + } + + return { kind: NonBubbleResultKind.Directionless, patch }; + } + if (isDeliveryIssue(message)) { updateMessage.simpleUpdate = { type: Backups.SimpleChatUpdate.Type.BAD_DECRYPT, @@ -1129,7 +1184,6 @@ export class BackupExportStream extends Readable { if (isContactRemovedNotification(message)) { // Transient, drop it - // TODO: DESKTOP-7124 return { kind: NonBubbleResultKind.Drop }; } @@ -1138,9 +1192,8 @@ export class BackupExportStream extends Readable { } if (isGroupUpdate(message)) { - // TODO (DESKTOP-6964) - // these old-school message types are no longer generated but we probably - // still want to render them + // GV1 is deprecated. + return { kind: NonBubbleResultKind.Drop }; } if (isUnsupportedMessage(message)) { diff --git a/ts/services/backups/import.ts b/ts/services/backups/import.ts index ec4184868e..16b1d0a1e4 100644 --- a/ts/services/backups/import.ts +++ b/ts/services/backups/import.ts @@ -9,6 +9,7 @@ import { isNumber } from 'lodash'; import { Backups, SignalService } from '../../protobuf'; import Data from '../../sql/Client'; +import type { StoryDistributionWithMembersType } from '../../sql/Interface'; import * as log from '../../logging/log'; import { StorySendMode } from '../../types/Stories'; import type { ServiceIdString, AciString } from '../../types/ServiceId'; @@ -426,8 +427,8 @@ export class BackupImportStream extends Writable { givenName, familyName, avatarUrlPath, - subscriberId, - subscriberCurrencyCode, + backupsSubscriberData, + donationSubscriberData, accountSettings, }: Backups.IAccountData): Promise { strictAssert(this.ourConversation === undefined, 'Duplicate AccountData'); @@ -466,11 +467,23 @@ export class BackupImportStream extends Writable { if (avatarUrlPath != null) { await storage.put('avatarUrl', avatarUrlPath); } - if (subscriberId != null) { - await storage.put('subscriberId', subscriberId); + if (donationSubscriberData != null) { + const { subscriberId, currencyCode } = donationSubscriberData; + if (Bytes.isNotEmpty(subscriberId)) { + await storage.put('subscriberId', subscriberId); + } + if (currencyCode != null) { + await storage.put('subscriberCurrencyCode', currencyCode); + } } - if (subscriberCurrencyCode != null) { - await storage.put('subscriberCurrencyCode', subscriberCurrencyCode); + if (backupsSubscriberData != null) { + const { subscriberId, currencyCode } = backupsSubscriberData; + if (Bytes.isNotEmpty(subscriberId)) { + await storage.put('backupsSubscriberId', subscriberId); + } + if (currencyCode != null) { + await storage.put('backupsSubscriberCurrencyCode', currencyCode); + } } await storage.put( @@ -576,6 +589,20 @@ export class BackupImportStream extends Writable { : undefined; const e164 = contact.e164 ? `+${contact.e164}` : undefined; + let removalStage: 'justNotification' | 'messageRequest' | undefined; + switch (contact.visibility) { + case Backups.Contact.Visibility.HIDDEN: + removalStage = 'justNotification'; + break; + case Backups.Contact.Visibility.HIDDEN_MESSAGE_REQUEST: + removalStage = 'messageRequest'; + break; + case Backups.Contact.Visibility.VISIBLE: + default: + removalStage = undefined; + break; + } + const attrs: ConversationAttributesType = { id: generateUuid(), type: 'private', @@ -583,7 +610,7 @@ export class BackupImportStream extends Writable { serviceId: aci ?? pni, pni, e164, - removalStage: contact.hidden ? 'messageRequest' : undefined, + removalStage, profileKey: contact.profileKey ? Bytes.toBase64(contact.profileKey) : undefined, @@ -593,10 +620,16 @@ export class BackupImportStream extends Writable { hideStory: contact.hideStory === true, }; - if (contact.registered === Backups.Contact.Registered.NOT_REGISTERED) { - const timestamp = contact.unregisteredTimestamp?.toNumber() ?? Date.now(); + if (contact.notRegistered) { + const timestamp = + contact.notRegistered.unregisteredTimestamp?.toNumber() ?? Date.now(); attrs.discoveredUnregisteredAt = timestamp; attrs.firstUnregisteredAt = timestamp; + } else { + strictAssert( + contact.registered, + 'contact is either registered or unregistered' + ); } if (contact.blocked) { @@ -644,72 +677,92 @@ export class BackupImportStream extends Writable { } private async fromDistributionList( - list: Backups.IDistributionList + listItem: Backups.IDistributionListItem ): Promise { strictAssert( - Bytes.isNotEmpty(list.distributionId), + Bytes.isNotEmpty(listItem.distributionId), 'Missing distribution list id' ); - const id = bytesToUuid(list.distributionId); + const id = bytesToUuid(listItem.distributionId); strictAssert(isStoryDistributionId(id), 'Invalid distribution list id'); - strictAssert( - list.privacyMode != null, - 'Missing distribution list privacy mode' - ); - - let isBlockList: boolean; - const { PrivacyMode } = Backups.DistributionList; - switch (list.privacyMode) { - case PrivacyMode.ALL: - strictAssert( - !list.memberRecipientIds?.length, - 'Distribution list with ALL privacy mode has members' - ); - isBlockList = true; - break; - case PrivacyMode.ALL_EXCEPT: - strictAssert( - list.memberRecipientIds?.length, - 'Distribution list with ALL_EXCEPT privacy mode has no members' - ); - isBlockList = true; - break; - case PrivacyMode.ONLY_WITH: - isBlockList = false; - break; - case PrivacyMode.UNKNOWN: - throw new Error('Invalid privacy mode for distribution list'); - default: - throw missingCaseError(list.privacyMode); - } - - const result = { + const commonFields = { id, - name: list.name ?? '', - deletedAtTimestamp: - list.deletionTimestamp == null - ? undefined - : getTimestampFromLong(list.deletionTimestamp), - allowsReplies: list.allowReplies === true, - isBlockList, - members: (list.memberRecipientIds || []).map(recipientId => { - const convo = this.recipientIdToConvo.get(recipientId.toNumber()); - strictAssert(convo != null, 'Missing story distribution list member'); - strictAssert( - convo.serviceId, - 'Story distribution list member has no serviceId' - ); - - return convo.serviceId; - }), // Default values senderKeyInfo: undefined, storageNeedsSync: false, }; + let result: StoryDistributionWithMembersType; + if (listItem.deletionTimestamp == null) { + const { distributionList: list } = listItem; + strictAssert( + list != null, + 'Distribution list is either present or deleted' + ); + + strictAssert( + list.privacyMode != null, + 'Missing distribution list privacy mode' + ); + + let isBlockList: boolean; + const { PrivacyMode } = Backups.DistributionList; + switch (list.privacyMode) { + case PrivacyMode.ALL: + strictAssert( + !list.memberRecipientIds?.length, + 'Distribution list with ALL privacy mode has members' + ); + isBlockList = true; + break; + case PrivacyMode.ALL_EXCEPT: + strictAssert( + list.memberRecipientIds?.length, + 'Distribution list with ALL_EXCEPT privacy mode has no members' + ); + isBlockList = true; + break; + case PrivacyMode.ONLY_WITH: + isBlockList = false; + break; + case PrivacyMode.UNKNOWN: + throw new Error('Invalid privacy mode for distribution list'); + default: + throw missingCaseError(list.privacyMode); + } + + result = { + ...commonFields, + name: list.name ?? '', + allowsReplies: list.allowReplies === true, + isBlockList, + members: (list.memberRecipientIds || []).map(recipientId => { + const convo = this.recipientIdToConvo.get(recipientId.toNumber()); + strictAssert(convo != null, 'Missing story distribution list member'); + strictAssert( + convo.serviceId, + 'Story distribution list member has no serviceId' + ); + + return convo.serviceId; + }), + }; + } else { + result = { + ...commonFields, + + name: '', + allowsReplies: false, + isBlockList: false, + members: [], + + deletedAtTimestamp: getTimestampFromLong(listItem.deletionTimestamp), + }; + } + await Data.createNewStoryDistribution(result); } @@ -1426,6 +1479,27 @@ export class BackupImportStream extends Writable { }; } + if (updateMessage.learnedProfileChange) { + const { e164, username } = updateMessage.learnedProfileChange; + strictAssert( + e164 != null || username != null, + 'learnedProfileChange must have an old name' + ); + return { + message: { + type: 'title-transition-notification', + titleTransition: { + renderInfo: { + type: 'private', + e164: e164 && !e164.isZero() ? `+${e164}` : undefined, + username: dropNull(username), + }, + }, + }, + additionalMessages: [], + }; + } + if (updateMessage.threadMerge) { const { previousE164 } = updateMessage.threadMerge; strictAssert(previousE164 != null, 'threadMerge must have an old e164'); diff --git a/ts/services/storageRecordOps.ts b/ts/services/storageRecordOps.ts index c8aa9d4e60..3b195b34ce 100644 --- a/ts/services/storageRecordOps.ts +++ b/ts/services/storageRecordOps.ts @@ -388,13 +388,25 @@ export function toAccountRecord( accountRecord.pinnedConversations = pinnedConversations; const subscriberId = window.storage.get('subscriberId'); - if (subscriberId instanceof Uint8Array) { + if (Bytes.isNotEmpty(subscriberId)) { accountRecord.subscriberId = subscriberId; } - const subscriberCurrencyCode = window.storage.get('subscriberCurrencyCode'); + const subscriberCurrencyCode = window.storage.get( + 'backupsSubscriberCurrencyCode' + ); if (typeof subscriberCurrencyCode === 'string') { accountRecord.subscriberCurrencyCode = subscriberCurrencyCode; } + const backupsSubscriberId = window.storage.get('backupsSubscriberId'); + if (Bytes.isNotEmpty(backupsSubscriberId)) { + accountRecord.backupsSubscriberId = backupsSubscriberId; + } + const backupsSubscriberCurrencyCode = window.storage.get( + 'backupsSubscriberCurrencyCode' + ); + if (typeof backupsSubscriberCurrencyCode === 'string') { + accountRecord.backupsSubscriberCurrencyCode = backupsSubscriberCurrencyCode; + } const displayBadgesOnProfile = window.storage.get('displayBadgesOnProfile'); if (displayBadgesOnProfile !== undefined) { accountRecord.displayBadgesOnProfile = displayBadgesOnProfile; @@ -1223,6 +1235,8 @@ export async function mergeAccountRecord( preferredReactionEmoji: rawPreferredReactionEmoji, subscriberId, subscriberCurrencyCode, + backupsSubscriberId, + backupsSubscriberCurrencyCode, displayBadgesOnProfile, keepMutedChatsArchived, hasCompletedUsernameOnboarding, @@ -1428,12 +1442,21 @@ export async function mergeAccountRecord( ); } - if (subscriberId instanceof Uint8Array) { + if (Bytes.isNotEmpty(subscriberId)) { await window.storage.put('subscriberId', subscriberId); } if (typeof subscriberCurrencyCode === 'string') { await window.storage.put('subscriberCurrencyCode', subscriberCurrencyCode); } + if (Bytes.isNotEmpty(backupsSubscriberId)) { + await window.storage.put('backupsSubscriberId', backupsSubscriberId); + } + if (typeof backupsSubscriberCurrencyCode === 'string') { + await window.storage.put( + 'backupsSubscriberCurrencyCode', + backupsSubscriberCurrencyCode + ); + } await window.storage.put( 'displayBadgesOnProfile', Boolean(displayBadgesOnProfile) diff --git a/ts/test-electron/backup/non_bubble_test.ts b/ts/test-electron/backup/non_bubble_test.ts index b40e5bf028..c9bf2f690a 100644 --- a/ts/test-electron/backup/non_bubble_test.ts +++ b/ts/test-electron/backup/non_bubble_test.ts @@ -418,6 +418,26 @@ describe('backup/non-bubble messages', () => { ]); }); + it('roundtrips title transition notification', async () => { + await symmetricRoundtripHarness([ + { + conversationId: contactA.id, + id: generateGuid(), + type: 'title-transition-notification', + received_at: 1, + sent_at: 1, + timestamp: 1, + sourceServiceId: CONTACT_A, + titleTransition: { + renderInfo: { + type: 'private', + e164: '+12125551234', + }, + }, + }, + ]); + }); + it('roundtrips thread merge', async () => { await symmetricRoundtripHarness([ { diff --git a/ts/types/Storage.d.ts b/ts/types/Storage.d.ts index 14ca43d69a..c1fcb5f49b 100644 --- a/ts/types/Storage.d.ts +++ b/ts/types/Storage.d.ts @@ -154,6 +154,8 @@ export type StorageAccessType = { areWeASubscriber: boolean; subscriberId: Uint8Array; subscriberCurrencyCode: string; + backupsSubscriberId: Uint8Array; + backupsSubscriberCurrencyCode: string; displayBadgesOnProfile: boolean; keepMutedChatsArchived: boolean; usernameLastIntegrityCheck: number; diff --git a/yarn.lock b/yarn.lock index 925a351906..dcad0fe3f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3993,10 +3993,10 @@ bindings "^1.5.0" tar "^6.1.0" -"@signalapp/libsignal-client@0.46.2": - version "0.46.2" - resolved "https://registry.yarnpkg.com/@signalapp/libsignal-client/-/libsignal-client-0.46.2.tgz#5f6139a7f585259dc5603ef27990b345afbbcc60" - integrity sha512-N6nfIkp3tkMQ1SCYMEOp8jdCiikWjjvkvHAp0M+FMA6dkrhj011nvDWjRAWNj+mCGmJCrLEqrhahaDKChWwHsg== +"@signalapp/libsignal-client@0.50.0": + version "0.50.0" + resolved "https://registry.yarnpkg.com/@signalapp/libsignal-client/-/libsignal-client-0.50.0.tgz#5cff29a49b658916aa277943d0fc01a2668ef0c6" + integrity sha512-sMkcdVEAZBCEMl6NoMX7jvuV+V3nEasCFe/j1ch+f/Dja4dkyMZovoBki6NqeU5rAry7Vj8ynJiMYAfpwCH8YA== dependencies: node-gyp-build "^4.2.3" type-fest "^3.5.0" @@ -7617,7 +7617,7 @@ caniuse-lite@^1.0.30001349, caniuse-lite@^1.0.30001541: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz" integrity sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw== -canvas@^2.6.1, "canvas@https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz", dmg-license@^1.0.11, "dmg-license@https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz", jsdom@^15.2.1, "jsdom@https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz": +canvas@^2.6.1, "canvas@https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz": version "1.0.0" resolved "https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz#cb46cf7e01574aa6390858149f66897afe53c9ca" @@ -9028,6 +9028,10 @@ dmg-builder@24.6.3: optionalDependencies: dmg-license "^1.0.11" +dmg-license@^1.0.11, "dmg-license@https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz": + version "1.0.0" + resolved "https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz#cb46cf7e01574aa6390858149f66897afe53c9ca" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -13537,6 +13541,10 @@ jsdoc@^4.0.0: strip-json-comments "^3.1.0" underscore "~1.13.2" +jsdom@^15.2.1, "jsdom@https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz": + version "1.0.0" + resolved "https://registry.yarnpkg.com/nop/-/nop-1.0.0.tgz#cb46cf7e01574aa6390858149f66897afe53c9ca" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -18719,7 +18727,7 @@ string-length@^5.0.1: char-regex "^2.0.0" strip-ansi "^7.0.1" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18763,6 +18771,15 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -18843,7 +18860,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18878,6 +18895,13 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -20529,7 +20553,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20564,6 +20588,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"