Merge pull request #334 from twonlyapp/dev

Dev
This commit is contained in:
Tobi 2025-12-15 20:36:12 +01:00 committed by GitHub
commit 7768362eb5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
90 changed files with 8969 additions and 5779 deletions

7
.gitmodules vendored
View file

@ -1,3 +1,4 @@
[submodule "dependencies/flutter_zxing"]
path = dependencies/flutter_zxing
url = https://github.com/khoren93/flutter_zxing.git
[submodule "dependencies"]
path = dependencies
url = https://github.com/twonlyapp/twonly-app-dependencies.git

View file

@ -1,5 +1,12 @@
# Changelog
## 0.0.73
- Integrated QR code scanner in the main camera
- New profile share page
- New workflow for checking the security number
- Improved user interface for creating voice messages
## 0.0.69
- Option to export and import memories

View file

@ -16,6 +16,8 @@ analyzer:
- "lib/src/model/protobuf/api/websocket/**"
- "lib/generated/**"
- "dependencies/**"
- "pubspec.yaml"
- "*.arb"
- "test/drift/**"
- "**.g.dart"

View file

@ -1,9 +1,15 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<application android:usesCleartextTraffic="true" >
<!-- // https://github.com/juliansteenbakker/mobile_scanner/issues/553 -->
<meta-data android:name="firebase_performance_collection_deactivated" android:value="true" />
<!-- <service
android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
tools:node="remove">
</service> -->
</application>
</manifest>

View file

@ -1,4 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<application
android:label="twonly"
android:name="${applicationName}"
@ -26,6 +26,13 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="me.twonly.eu" />
<data android:scheme="https" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
@ -33,6 +40,12 @@
android:name="flutterEmbedding"
android:value="2" />
<!-- // https://github.com/juliansteenbakker/mobile_scanner/issues/553 -->
<meta-data android:name="firebase_performance_collection_deactivated" android:value="true" />
<service
android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
tools:node="remove">
</service>
<!-- <service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"

View file

@ -8,4 +8,5 @@
<uses-permission android:name="android.permission.CAMERA"/>
<application android:usesCleartextTraffic="true" >
</application>
<meta-data android:name="firebase_performance_collection_deactivated" android:value="true" />
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

1
dependencies Submodule

@ -0,0 +1 @@
Subproject commit fb66274bf729cde6f7184ec6f7f9ea89f12450fd

@ -1 +0,0 @@
Subproject commit ba65f2fb4a09f4e68f6de64aa1de41ba3dc4977e

View file

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
platform :ios, '15.0'
platform :ios, '15.5'
use_frameworks!
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.

View file

@ -1,4 +1,6 @@
PODS:
- app_links (7.0.0):
- Flutter
- audio_waveforms (0.0.1):
- Flutter
- background_downloader (0.0.1):
@ -122,11 +124,16 @@ PODS:
- FlutterMacOS
- flutter_volume_controller (0.0.1):
- Flutter
- flutter_zxing (0.0.1):
- Flutter
- gal (1.0.0):
- Flutter
- FlutterMacOS
- google_mlkit_barcode_scanning (0.14.1):
- Flutter
- google_mlkit_commons
- GoogleMLKit/BarcodeScanning (~> 7.0.0)
- google_mlkit_commons (0.11.0):
- Flutter
- MLKitVision
- GoogleAdsOnDeviceConversion (3.1.0):
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
@ -157,6 +164,16 @@ PODS:
- GoogleDataTransport (10.1.0):
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- GoogleMLKit/BarcodeScanning (7.0.0):
- GoogleMLKit/MLKitCore
- MLKitBarcodeScanning (~> 6.0.0)
- GoogleMLKit/MLKitCore (7.0.0):
- MLKitCommon (~> 12.0.0)
- GoogleToolboxForMac/Defines (4.2.1)
- GoogleToolboxForMac/Logger (4.2.1):
- GoogleToolboxForMac/Defines (= 4.2.1)
- "GoogleToolboxForMac/NSData+zlib (4.2.1)":
- GoogleToolboxForMac/Defines (= 4.2.1)
- GoogleUtilities (8.1.0):
- GoogleUtilities/AppDelegateSwizzler (= 8.1.0)
- GoogleUtilities/Environment (= 8.1.0)
@ -197,6 +214,7 @@ PODS:
- GoogleUtilities/UserDefaults (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GTMSessionFetcher/Core (3.5.0)
- image_picker_ios (0.0.1):
- Flutter
- libwebp (1.5.0):
@ -217,6 +235,23 @@ PODS:
- Mantle (2.2.0):
- Mantle/extobjc (= 2.2.0)
- Mantle/extobjc (2.2.0)
- MLImage (1.0.0-beta6)
- MLKitBarcodeScanning (6.0.0):
- MLKitCommon (~> 12.0)
- MLKitVision (~> 8.0)
- MLKitCommon (12.0.0):
- GoogleDataTransport (~> 10.0)
- GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1)
- "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)"
- GoogleUtilities/Logger (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- GTMSessionFetcher/Core (< 4.0, >= 3.3.2)
- MLKitVision (8.0.0):
- GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1)
- "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)"
- GTMSessionFetcher/Core (< 4.0, >= 3.3.2)
- MLImage (= 1.0.0-beta6)
- MLKitCommon (~> 12.0)
- nanopb (3.30910.0):
- nanopb/decode (= 3.30910.0)
- nanopb/encode (= 3.30910.0)
@ -291,6 +326,7 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
- app_links (from `.symlinks/plugins/app_links/ios`)
- audio_waveforms (from `.symlinks/plugins/audio_waveforms/ios`)
- background_downloader (from `.symlinks/plugins/background_downloader/ios`)
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
@ -312,8 +348,9 @@ DEPENDENCIES:
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
- flutter_zxing (from `.symlinks/plugins/flutter_zxing/ios`)
- gal (from `.symlinks/plugins/gal/darwin`)
- google_mlkit_barcode_scanning (from `.symlinks/plugins/google_mlkit_barcode_scanning/ios`)
- google_mlkit_commons (from `.symlinks/plugins/google_mlkit_commons/ios`)
- GoogleUtilities
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
@ -345,9 +382,16 @@ SPEC REPOS:
- GoogleAdsOnDeviceConversion
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleMLKit
- GoogleToolboxForMac
- GoogleUtilities
- GTMSessionFetcher
- libwebp
- Mantle
- MLImage
- MLKitBarcodeScanning
- MLKitCommon
- MLKitVision
- nanopb
- PromisesObjC
- ScreenProtectorKit
@ -359,6 +403,8 @@ SPEC REPOS:
- SwiftyGif
EXTERNAL SOURCES:
app_links:
:path: ".symlinks/plugins/app_links/ios"
audio_waveforms:
:path: ".symlinks/plugins/audio_waveforms/ios"
background_downloader:
@ -393,10 +439,12 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
flutter_volume_controller:
:path: ".symlinks/plugins/flutter_volume_controller/ios"
flutter_zxing:
:path: ".symlinks/plugins/flutter_zxing/ios"
gal:
:path: ".symlinks/plugins/gal/darwin"
google_mlkit_barcode_scanning:
:path: ".symlinks/plugins/google_mlkit_barcode_scanning/ios"
google_mlkit_commons:
:path: ".symlinks/plugins/google_mlkit_commons/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
local_auth_darwin:
@ -429,6 +477,7 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
SPEC CHECKSUMS:
app_links: a754cbec3c255bd4bbb4d236ecc06f28cd9a7ce8
audio_waveforms: a6dde7fe7c0ea05f06ffbdb0f7c1b2b2ba6cedcf
background_downloader: 50e91d979067b82081aba359d7d916b3ba5fadad
camera_avfoundation: 5675ca25298b6f81fa0a325188e7df62cc217741
@ -454,16 +503,24 @@ SPEC CHECKSUMS:
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468
flutter_volume_controller: c2be490cb0487e8b88d0d9fc2b7e1c139a4ebccb
flutter_zxing: e8bcc43bd3056c70c271b732ed94e7a16fd62f93
gal: baecd024ebfd13c441269ca7404792a7152fde89
google_mlkit_barcode_scanning: 8f5987f244a43fe1167689c548342a5174108159
google_mlkit_commons: 2abe6a70e1824e431d16a51085cb475b672c8aab
GoogleAdsOnDeviceConversion: e03a386840803ea7eef3fd22a061930142c039c1
GoogleAppMeasurement: 1e718274b7e015cefd846ac1fcf7820c70dc017d
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleMLKit: eff9e23ec1d90ea4157a1ee2e32a4f610c5b3318
GoogleToolboxForMac: d1a2cbf009c453f4d6ded37c105e2f67a32206d8
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
MLImage: 0ad1c5f50edd027672d8b26b0fee78a8b4a0fc56
MLKitBarcodeScanning: 0a3064da0a7f49ac24ceb3cb46a5bc67496facd2
MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d
MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
no_screenshot: 6d183496405a3ab709a67a54e5cd0f639e94729e
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
@ -487,6 +544,6 @@ SPEC CHECKSUMS:
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
PODFILE CHECKSUM: 47470fbd5b59affa461eaf943ac57acce81e0ee8
PODFILE CHECKSUM: c0c524475498435108850efecde62ba98e081c25
COCOAPODS: 1.16.2

View file

@ -52,7 +52,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"

View file

@ -85,5 +85,9 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<!--Disable Firebase Telemetry-->
<key>firebase_performance_collection_deactivated</key>
<true/>
<!--...-->
</dict>
</plist>

View file

@ -4,6 +4,10 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:me.twonly.eu</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)eu.twonly.shared</string>

View file

@ -155,6 +155,7 @@ class _AppMainWidgetState extends State<AppMainWidget> {
bool _showDatabaseMigration = false;
bool _showOnboarding = true;
bool _isLoaded = false;
bool _skipBackup = false;
(Future<int>?, bool) _proofOfWork = (null, false);
@ -203,9 +204,10 @@ class _AppMainWidgetState extends State<AppMainWidget> {
if (_showDatabaseMigration) {
child = const DatabaseMigrationView();
} else if (_isUserCreated) {
if (gUser.twonlySafeBackup == null) {
if (gUser.twonlySafeBackup == null && !_skipBackup) {
child = TwonlyIdentityBackupView(
callBack: () {
_skipBackup = true;
setState(() {});
},
);

View file

@ -1,785 +1,397 @@
{
"@@locale": "de",
"registerTitle": "Willkommen bei twonly!",
"@registerTitle": {},
"registerSlogan": "twonly, eine private und sichere Möglichkeit um mit Freunden in Kontakt zu bleiben.",
"@registerSlogan": {},
"onboardingWelcomeTitle": "Willkommen bei twonly!",
"@onboardingWelcomeTitle": {},
"onboardingWelcomeBody": "Erlebe eine private und sichere Möglichkeit mit Freunden in Kontakt zu bleiben, indem du spontane Bilder teilst.",
"@onboardingWelcomeBody": {},
"onboardingE2eTitle": "Unbekümmert teilen",
"@onboardingE2eTitle": {},
"onboardingE2eBody": "Genieße durch die Ende-zu-Ende-Verschlüsselung die Gewissheit, dass nur du und deine Freunde die geteilten Momente sehen können.",
"@onboardingE2eBody": {},
"onboardingFocusTitle": "Fokussiere dich auf das Teilen von Momenten",
"@onboardingFocusTitle": {},
"onboardingFocusBody": "Verabschiede dich von süchtig machenden Funktionen! twonly wurde für das Teilen von Momenten ohne nutzlose Ablenkungen oder Werbung entwickelt.",
"@onboardingFocusBody": {},
"onboardingSendTwonliesTitle": "twonlies senden",
"@onboardingSendTwonliesTitle": {},
"onboardingSendTwonliesBody": "Teile Momente sicher mit deinem Partner. twonly stellt sicher, dass nur dein Partner sie öffnen kann, sodass deine Momente mit deinem Partner eine two(o)nly Sache bleiben!",
"@onboardingSendTwonliesBody": {},
"onboardingNotProductTitle": "Du bist nicht das Produkt!",
"@onboardingNotProductTitle": {},
"onboardingNotProductBody": "twonly wird durch Spenden und ein optionales Abonnement finanziert. Deine Daten werden niemals verkauft.",
"@onboardingNotProductBody": {},
"onboardingBuyOneGetTwoTitle": "Kaufe eins, bekomme zwei",
"@onboardingBuyOneGetTwoTitle": {},
"onboardingBuyOneGetTwoBody": "twonly benötigt immer mindestens zwei Personen, daher erhältst du beim Kauf eine zweite kostenlose Lizenz für deinen twonly-Partner.",
"@onboardingBuyOneGetTwoBody": {},
"onboardingGetStartedTitle": "Auf geht's",
"@onboardingGetStartedTitle": {},
"onboardingGetStartedBody": "Du kannst twonly kostenlos im Preview-Modus testen. In diesem Modus kannst du von anderen gefunden werden und Bilder oder Videos empfangen, aber du kannst selbst keine senden.",
"@onboardingGetStartedBody": {},
"onboardingTryForFree": "Jetzt registrieren",
"@onboardingTryForFree": {},
"registerUsernameSlogan": "Bitte wähle einen Benutzernamen, damit dich andere finden können!",
"@registerUsernameSlogan": {},
"registerUsernameDecoration": "Benutzername",
"@registerUsernameDecoration": {},
"registerUsernameLimits": "Der Benutzername muss mindestens 3 Zeichen lang sein.",
"@registerUsernameLimits": {},
"registerSubmitButton": "Jetzt registrieren!",
"@registerSubmitButton": {},
"registerTwonlyCodeText": "Hast du einen twonly-Code erhalten? Dann löse ihn entweder direkt hier oder später ein!",
"@registerTwonlyCodeText": {},
"registerTwonlyCodeLabel": "twonly-Code",
"@registerTwonlyCodeLabel": {},
"newMessageTitle": "Neue Nachricht",
"@newMessageTitle": {},
"chatsTapToSend": "Klicke, um dein erstes Bild zu teilen.",
"@chatsTapToSend": {},
"cameraPreviewSendTo": "Senden an",
"@cameraPreviewSendTo": {},
"shareImageTitle": "Teilen mit",
"@shareImageTitle": {},
"shareImageBestFriends": "Beste Freunde",
"@shareImageBestFriends": {},
"shareImagePinnedContacts": "Angeheftet",
"@shareImagePinnedContacts": {},
"shareImagedEditorSendImage": "Senden",
"@shareImagedEditorSendImage": {},
"shareImagedEditorShareWith": "Teilen mit",
"@shareImagedEditorShareWith": {},
"shareImagedEditorSaveImage": "Speichern",
"@shareImagedEditorSaveImage": {},
"shareImagedEditorSavedImage": "Gespeichert",
"@shareImagedEditorSavedImage": {},
"shareImagedSelectAll": "Alle auswählen",
"@shareImagedSelectAll": {},
"shareImageAllUsers": "Alle Kontakte",
"@shareImageAllUsers": {},
"shareImageAllTwonlyWarning": "twonlies können nur an verifizierte Kontakte gesendet werden!",
"@shareImageAllTwonlyWarning": {},
"shareImageSearchAllContacts": "Alle Kontakte durchsuchen",
"@shareImageSearchAllContacts": {},
"shareImageUserNotVerified": "Benutzer ist nicht verifiziert",
"@shareImageUserNotVerified": {},
"shareImageUserNotVerifiedDesc": "twonlies können nur an verifizierte Nutzer gesendet werden. Um einen Nutzer zu verifizieren, gehe auf sein Profil und auf „Sicherheitsnummer verifizieren“.",
"@shareImageUserNotVerifiedDesc": {},
"shareImageShowArchived": "Archivierte Benutzer anzeigen",
"@shareImageShowArchived": {},
"startNewChatSearchHint": "Name, Benutzername oder Gruppenname",
"searchUsernameInput": "Benutzername",
"@searchUsernameInput": {},
"searchUsernameTitle": "Benutzernamen suchen",
"@searchUsernameTitle": {},
"searchUserNamePreview": "Um dich und andere twonly Benutzer vor Spam und Missbrauch zu schützen, ist es nicht möglich, im Preview-Modus nach anderen Personen zu suchen. Andere Benutzer können dich finden und deren Anfragen werden dann hier angezeigt!",
"@searchUserNamePreview": {},
"selectSubscription": "Abo auswählen",
"@selectSubscription": {},
"searchUsernameNotFound": "Benutzername nicht gefunden",
"@searchUsernameNotFound": {},
"searchUsernameNotFoundBody": "Es wurde kein Benutzer mit dem Benutzernamen \"{username}\" gefunden.",
"@searchUsernameNotFoundBody": {},
"searchUsernameNewFollowerTitle": "Folgeanfragen",
"@searchUsernameNewFollowerTitle": {},
"searchUsernameQrCodeBtn": "QR-Code scannen",
"@searchUsernameQrCodeBtn": {},
"searchUserNamePending": "Ausstehend",
"@searchUserNamePending": {},
"searchUserNameBlockUserTooltip": "Benutzer ohne Benachrichtigung blockieren.",
"@searchUserNameBlockUserTooltip": {},
"searchUserNameRejectUserTooltip": "Die Anfrage ablehnen und den Anfragenden informieren.",
"@searchUserNameRejectUserTooltip": {},
"searchUserNameArchiveUserTooltip": "Benutzer archivieren. Du wirst informiert sobald er deine Anfrage akzeptiert.",
"@searchUserNameArchiveUserTooltip": {},
"userFound": "Benutzer gefunden",
"@userFound": {},
"userFound": "{username} gefunden",
"userFoundBody": "Möchtest du eine Folgeanfrage stellen?",
"@userFoundBody": {},
"chatListViewSearchUserNameBtn": "Füge deinen ersten twonly-Kontakt hinzu!",
"@chatListViewSearchUserNameBtn": {},
"chatListViewSendFirstTwonly": "Sende dein erstes twonly!",
"@chatListViewSendFirstTwonly": {},
"chatListDetailInput": "Nachricht eingeben",
"@chatListDetailInput": {},
"userDeletedAccount": "Der Nutzer hat sein Konto gelöscht.",
"@userDeletedAccount": {},
"contextMenuUserProfile": "Userprofil",
"@contextMenuUserProfile": {},
"contextMenuVerifyUser": "Verifizieren",
"@contextMenuVerifyUser": {},
"contextMenuArchiveUser": "Archivieren",
"@contextMenuArchiveUser": {},
"contextMenuUndoArchiveUser": "Archivierung aufheben",
"@contextMenuUndoArchiveUser": {},
"startNewChatTitle": "Kontakt wählen",
"@startNewChatTitle": {},
"startNewChatNewContact": "Neuer Kontakt",
"@startNewChatNewContact": {},
"startNewChatYourContacts": "Deine Kontakte",
"@startNewChatYourContacts": {},
"contextMenuOpenChat": "Chat",
"@contextMenuOpenChat": {},
"contextMenuPin": "Anheften",
"@contextMenuPin": {},
"contextMenuUnpin": "Lösen",
"@contextMenuUnpin": {},
"mediaViewerAuthReason": "Bitte authentifiziere dich, um diesen twonly zu sehen!",
"@mediaViewerAuthReason": {},
"mediaViewerTwonlyTapToOpen": "Tippe um den twonly zu öffnen!",
"@mediaViewerTwonlyTapToOpen": {},
"messageSendState_Received": "Empfangen",
"@messageSendState_Received": {},
"messageSendState_Opened": "Geöffnet",
"@messageSendState_Opened": {},
"messageSendState_Send": "Gesendet",
"@messageSendState_Send": {},
"messageSendState_Sending": "Wird gesendet",
"@messageSendState_Sending": {},
"messageSendState_TapToLoad": "Tippe zum Laden",
"@messageSendState_TapToLoad": {},
"messageSendState_Loading": "Herunterladen",
"@messageSendState_Loading": {},
"messageStoredInGallery": "Gespeichert",
"@messageStoredInGallery": {},
"messageReopened": "Erneut geöffnet",
"@messageReopened": {},
"imageEditorDrawOk": "Zeichnung machen",
"@imageEditorDrawOk": {},
"settingsTitle": "Einstellungen",
"@settingsTitle": {},
"settingsChats": "Chats",
"@settingsChats": {},
"settingsStorageData": "Daten und Speicher",
"@settingsStorageData": {},
"settingsStorageDataStoreInGTitle": "In der Galerie speichern",
"@settingsStorageDataStoreInGTitle": {},
"settingsStorageDataStoreInGSubtitle": "Speichere Bilder zusätzlich in der Systemgalerie.",
"@settingsStorageDataStoreInGSubtitle": {},
"settingsStorageDataMediaAutoDownload": "Automatischer Mediendownload",
"@settingsStorageDataMediaAutoDownload": {},
"settingsStorageDataAutoDownMobile": "Bei Nutzung mobiler Daten",
"@settingsStorageDataAutoDownMobile": {},
"settingsStorageDataAutoDownWifi": "Bei Nutzung von WLAN",
"@settingsStorageDataAutoDownWifi": {},
"settingsPreSelectedReactions": "Vorgewählte Reaktions-Emojis",
"@settingsPreSelectedReactions": {},
"settingsPreSelectedReactionsError": "Es können maximal 12 Reaktionen ausgewählt werden.",
"@settingsPreSelectedReactionsError": {},
"settingsProfile": "Profil",
"@settingsProfile": {},
"settingsProfileCustomizeAvatar": "Avatar anpassen",
"@settingsProfileCustomizeAvatar": {},
"settingsProfileEditDisplayName": "Anzeigename",
"@settingsProfileEditDisplayName": {},
"settingsProfileEditDisplayNameNew": "Neuer Anzeigename",
"@settingsProfileEditDisplayNameNew": {},
"settingsAccount": "Konto",
"@settingsAccount": {},
"settingsSubscription": "Abonnement",
"@settingsSubscription": {},
"settingsAppearance": "Erscheinungsbild",
"@settingsAppearance": {},
"settingsPrivacy": "Datenschutz",
"@settingsPrivacy": {},
"settingsPrivacyBlockUsers": "Benutzer blockieren",
"@settingsPrivacyBlockUsers": {},
"settingsPrivacyBlockUsersDesc": "Blockierte Benutzer können nicht mit dir kommunizieren. Du kannst einen blockierten Benutzer jederzeit wieder entsperren.",
"@settingsPrivacyBlockUsersDesc": {},
"settingsPrivacyBlockUsersCount": "{len} Kontakt(e)",
"@settingsPrivacyBlockUsersCount": {},
"settingsNotification": "Benachrichtigung",
"@settingsNotification": {},
"settingsNotifyTroubleshooting": "Fehlersuche",
"@settingsNotifyTroubleshooting": {},
"settingsNotifyTroubleshootingDesc": "Hier klicken, wenn Probleme beim Empfang von Push-Benachrichtigungen auftreten.",
"@settingsNotifyTroubleshootingDesc": {},
"settingsNotifyTroubleshootingNoProblem": "Kein Problem festgestellt",
"@settingsNotifyTroubleshootingNoProblem": {},
"settingsNotifyTroubleshootingNoProblemDesc": "Klicke auf OK, um eine Testbenachrichtigung zu erhalten. Wenn du auch nach 10 Minuten warten keine Nachricht erhältst, sende uns bitte dein Diagnoseprotokoll unter Einstellungen > Hilfe > Diagnoseprotokoll, damit wir uns das Problem ansehen können.",
"@settingsNotifyTroubleshootingNoProblemDesc": {},
"settingsHelp": "Hilfe",
"@settingsHelp": {},
"settingsHelpFAQ": "FAQ",
"@settingsHelpFAQ": {},
"feedbackTooltip": "Feedback zur Verbesserung von twonly geben.",
"@feedbackTooltip": {},
"settingsHelpContactUs": "Kontaktiere uns",
"@settingsHelpContactUs": {},
"contactUsFaq": "FAQ schon gelesen?",
"@contactUsFaq": {},
"contactUsEmojis": "Wie fühlst du dich? (optional)",
"@contactUsEmojis": {},
"contactUsSelectOption": "Bitte wähle eine Option",
"@contactUsSelectOption": {},
"contactUsReason": "Sag uns, warum du uns kontaktierst",
"@contactUsReason": {},
"contactUsMessage": "Wenn du eine Antwort erhalten möchtest, füge bitte deine E-Mail-Adresse hinzu, damit wir dich kontaktieren können.",
"@contactUsMessage": {},
"contactUsYourMessage": "Deine Nachricht",
"@contactUsYourMessage": {},
"contactUsMessageTitle": "Erzähl uns, was los ist",
"@contactUsMessageTitle": {},
"contactUsReasonNotWorking": "Etwas funktioniert nicht",
"@contactUsReasonNotWorking": {},
"contactUsReasonFeatureRequest": "Funktionsanfrage",
"@contactUsReasonFeatureRequest": {},
"contactUsReasonQuestion": "Frage",
"@contactUsReasonQuestion": {},
"contactUsReasonFeedback": "Feedback",
"@contactUsReasonFeedback": {},
"contactUsReasonOther": "Sonstiges",
"@contactUsReasonOther": {},
"contactUsIncludeLog": "Debug-Protokoll anhängen.",
"@contactUsIncludeLog": {},
"contactUsWhatsThat": "Was ist das?",
"@contactUsWhatsThat": {},
"contactUsLastWarning": "Dies sind die Informationen, die an uns gesendet werden. Bitte prüfen Sie sie und klicke dann auf „Abschicken“.",
"@contactUsLastWarning": {},
"contactUsSuccess": "Feedback erfolgreich übermittelt!",
"@contactUsSuccess": {},
"contactUsShortcut": "Feedback-Symbol ausblenden",
"@contactUsShortcut": {},
"settingsHelpDiagnostics": "Diagnoseprotokoll",
"@settingsHelpDiagnostics": {},
"settingsHelpVersion": "Version",
"@settingsHelpVersion": {},
"settingsHelpLicenses": "Lizenzen (Source-Code)",
"@settingsHelpLicenses": {},
"settingsHelpCredits": "Lizenzen (Bilder)",
"@settingsHelpCredits": {},
"settingsHelpImprint": "Impressum & Datenschutzrichtlinie",
"@settingsHelpImprint": {},
"settingsHelpTerms": "Nutzungsbedingungen",
"@settingsHelpTerms": {},
"settingsAppearanceTheme": "Theme",
"@settingsAppearanceTheme": {},
"settingsAccountDeleteAccount": "Konto löschen",
"@settingsAccountDeleteAccount": {},
"settingsAccountDeleteAccountWithBallance": "Im nächsten Schritt kannst du auswählen, was du mit dem Restguthaben ({credit}) machen willst.",
"@settingsAccountDeleteAccountWithBallance": {},
"settingsAccountDeleteAccountNoInternet": "Zum Löschen deines Accounts ist eine Internetverbindung erforderlich.",
"@settingsAccountDeleteAccountNoInternet": {},
"settingsAccountDeleteAccountNoBallance": "Wenn du dein Konto gelöscht hast, gibt es keinen Weg zurück.",
"@settingsAccountDeleteAccountNoBallance": {},
"settingsAccountDeleteModalTitle": "Bist du sicher?",
"@settingsAccountDeleteModalTitle": {},
"settingsAccountDeleteModalBody": "Dein Konto wird gelöscht. Es gibt keine Möglichkeit, es wiederherzustellen.",
"@settingsAccountDeleteModalBody": {},
"contactVerifyNumberTitle": "Sicherheitsnummer verifizieren",
"@contactVerifyNumberTitle": {},
"contactVerifyNumberTapToScan": "Zum Scannen tippen",
"@contactVerifyNumberTapToScan": {},
"contactVerifyNumberMarkAsVerified": "Als verifiziert markieren",
"@contactVerifyNumberMarkAsVerified": {},
"contactVerifyNumberClearVerification": "Verifizierung aufheben",
"@contactVerifyNumberClearVerification": {},
"contactVerifyNumberLongDesc": "Um die Ende-zu-Ende-Verschlüsselung mit {username} zu verifizieren, vergleiche die Zahlen mit ihrem Gerät. Die Person kann auch deinen Code mit ihrem Gerät scannen.",
"@contactVerifyNumberLongDesc": {},
"contactNickname": "Spitzname",
"@contactNickname": {},
"contactNicknameNew": "Neuer Spitzname",
"@contactNicknameNew": {},
"contactBlock": "Blockieren",
"@contactBlock": {},
"contactRemove": "Benutzer löschen",
"@contactRemove": {},
"contactRemoveTitle": "{username} löschen?",
"@contactRemoveTitle": {},
"contactRemoveBody": "Entferne den Benutzer und lösche den Chat sowie alle zugehörigen Mediendateien dauerhaft. Dadurch wird auch DEIN KONTO VON DEM TELEFON DEINES KONTAKTS gelöscht.",
"@contactRemoveBody": {},
"deleteAllContactMessages": "Textnachrichten löschen",
"@deleteAllContactMessages": {},
"deleteAllContactMessagesBody": "Dadurch werden alle Nachrichten, ausgenommen gespeicherte Mediendateien, in deinem Chat mit {username} gelöscht. Dies löscht NICHT die auf dem Gerät von {username} gespeicherten Nachrichten!",
"@deleteAllContactMessagesBody": {},
"contactBlockTitle": "Blockiere {username}",
"@contactBlockTitle": {},
"contactBlockBody": "Ein blockierter Benutzer kann dir keine Nachrichten mehr senden, und sein Profil ist nicht mehr sichtbar. Um die Blockierung eines Benutzers aufzuheben, navigiere einfach zu Einstellungen > Datenschutz > Blockierte Benutzer.",
"@contactBlockBody": {},
"undo": "Rückgängig",
"@undo": {},
"redo": "Wiederholen",
"@redo": {},
"next": "Weiter",
"@next": {},
"submit": "Abschicken",
"@submit": {},
"close": "Schließen",
"@close": {},
"cancel": "Abbrechen",
"@cancel": {},
"edit": "Bearbeiten",
"@edit": {},
"ok": "Ok",
"@ok": {},
"now": "Jetzt",
"@now": {},
"you": "Du",
"@you": {},
"minutesShort": "Min.",
"@minutesShort": {},
"image": "Bild",
"@image": {},
"video": "Video",
"@video": {},
"react": "Reagieren",
"@react": {},
"reply": "Antworten",
"@reply": {},
"copy": "Kopieren",
"@copy": {},
"delete": "Löschen",
"@delete": {},
"info": "Info",
"@info": {},
"disable": "Deaktiviern",
"@disable": {},
"enable": "Aktivieren",
"@enable": {},
"switchFrontAndBackCamera": "Zwischen Front- und Rückkamera wechseln.",
"@switchFrontAndBackCamera": {},
"addTextItem": "Text",
"@addTextItem": {},
"protectAsARealTwonly": "Als echtes twonly senden!",
"@protectAsARealTwonly": {},
"addDrawing": "Zeichnung",
"@addDrawing": {},
"addEmoji": "Emoji",
"@addEmoji": {},
"toggleFlashLight": "Taschenlampe umschalten",
"@toggleFlashLight": {},
"toggleHighQuality": "Bessere Auflösung umschalten",
"@toggleHighQuality": {},
"searchUsernameNotFoundLong": "\"{username}\" ist kein twonly-Benutzer. Bitte überprüfe den Benutzernamen und versuche es erneut.",
"@searchUsernameNotFoundLong": {},
"errorUnknown": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es später erneut.",
"@errorUnknown": {},
"errorBadRequest": "Die Anfrage konnte vom Server aufgrund einer fehlerhaften Syntax nicht verstanden werden. Bitte überprüfe deine Eingabe und versuche es erneut.",
"@errorBadRequest": {},
"errorTooManyRequests": "Du hast in kurzer Zeit zu viele Anfragen gestellt. Bitte warte einen Moment, bevor du es erneut versuchst.",
"@errorTooManyRequests": {},
"errorInternalError": "Der Server ist derzeit nicht verfügbar. Bitte versuche es später erneut.",
"@errorInternalError": {},
"errorInvalidInvitationCode": "Der von dir angegebene Einladungscode ist ungültig. Bitte überprüfe den Code und versuche es erneut.",
"@errorInvalidInvitationCode": {},
"errorUsernameAlreadyTaken": "Der Benutzername ist bereits vergeben.",
"@errorUsernameAlreadyTaken": {},
"errorSignatureNotValid": "Die bereitgestellte Signatur ist nicht gültig. Bitte überprüfe deine Anmeldeinformationen und versuche es erneut.",
"@errorSignatureNotValid": {},
"errorUsernameNotFound": "Der eingegebene Benutzername existiert nicht. Bitte überprüfe die Schreibweise oder erstelle ein neues Konto.",
"@errorUsernameNotFound": {},
"errorUsernameNotValid": "Der von dir angegebene Benutzername entspricht nicht den erforderlichen Kriterien. Bitte wähle einen gültigen Benutzernamen.",
"@errorUsernameNotValid": {},
"errorInvalidPublicKey": "Der von dir angegebene öffentliche Schlüssel ist ungültig. Bitte überprüfe den Schlüssel und versuche es erneut.",
"@errorInvalidPublicKey": {},
"errorSessionAlreadyAuthenticated": "Du bist bereits angemeldet. Bitte melde dich ab, wenn du dich mit einem anderen Konto anmelden möchtest.",
"@errorSessionAlreadyAuthenticated": {},
"errorSessionNotAuthenticated": "Deine Sitzung ist nicht authentifiziert. Bitte melde dich an, um fortzufahren.",
"@errorSessionNotAuthenticated": {},
"errorOnlyOneSessionAllowed": "Es ist nur eine aktive Sitzung pro Benutzer erlaubt. Bitte melde dich von anderen Geräten ab, um fortzufahren.",
"@errorOnlyOneSessionAllowed": {},
"upgradeToPaidPlan": "Upgrade auf einen kostenpflichtigen Plan.",
"@upgradeToPaidPlan": {},
"upgradeToPaidPlanButton": "Auf {planId} upgraden",
"@upgradeToPaidPlanButton": {},
"partOfPaidPlanOf": "Du bist Teil des bezahlten Plans von {username}!",
"@partOfPaidPlanOf": {},
"errorNotEnoughCredit": "Du hast nicht genügend twonly-Guthaben.",
"@errorNotEnoughCredit": {},
"errorPlanLimitReached": "Du hast das Limit deines Plans erreicht. Bitte upgrade deinen Plan.",
"@errorPlanLimitReached": {},
"errorPlanNotAllowed": "Dieses Feature ist in deinem aktuellen Plan nicht verfügbar.",
"@errorPlanNotAllowed": {},
"errorVoucherInvalid": "Der eingegebene Gutschein-Code ist nicht gültig.",
"@errorVoucherInvalid": {},
"errorPlanUpgradeNotYearly": "Das Upgrade des Plans muss jährlich bezahlt werden, da der aktuelle Plan ebenfalls jährlich abgerechnet wird.",
"@errorPlanUpgradeNotYearly": {},
"proFeature1": "✓ Unbegrenzte Medien-Datei-Uploads",
"@proFeature1": {},
"proFeature2": "1 zusätzlicher Plus Benutzer",
"@proFeature2": {},
"proFeature3": "Flammen wiederherstellen",
"@proFeature3": {},
"proFeature4": "Cloud-Backup verschlüsselt (coming-soon)",
"@proFeature4": {},
"year": "year",
"@year": {},
"month": "month",
"@month": {},
"familyFeature1": "✓ Alles von Pro",
"@familyFeature1": {},
"familyFeature2": "4 zusätzliche Plus Benutzer",
"@familyFeature2": {},
"redeemUserInviteCode": "Oder löse einen twonly-Code ein.",
"@redeemUserInviteCode": {},
"freeFeature1": "10 Medien-Datei-Uploads pro Tag",
"@freeFeature1": {},
"plusFeature1": "✓ Unbegrenzte Medien-Datei-Uploads",
"@plusFeature1": {},
"plusFeature2": "Zusatzfunktionen (coming-soon)",
"@plusFeature2": {},
"transactionHistory": "Transaktionshistorie",
"@transactionHistory": {},
"currentBalance": "Dein Guthaben",
"@currentBalance": {},
"manageAdditionalUsers": "Zusätzliche Benutzer verwalten",
"@manageAdditionalUsers": {},
"manageSubscription": "Abonnement verwalten",
"@manageSubscription": {},
"nextPayment": "Nächste Zahlung",
"@nextPayment": {},
"open": "Offene",
"@open": {},
"buy": "Kaufen",
"@buy": {},
"createOrRedeemVoucher": "Gutschein erstellen oder einlösen",
"@createOrRedeemVoucher": {},
"subscriptionRefund": "Wenn du ein Upgrade durchführst, erhältst du eine Rückerstattung von {refund} für dein aktuelles Abonnement.",
"@subscriptionRefund": {},
"createVoucher": "Gutschein kaufen",
"@createVoucher": {},
"createVoucherDesc": "Wähle den Wert des Gutscheins. Der Wert des Gutschein wird von deinem twonly-Guthaben abgezogen.",
"@createVoucherDesc": {},
"redeemVoucher": "Gutschein einlösen",
"@redeemVoucher": {},
"redeemUserInviteCodeTitle": "twonly-Code einlösen",
"@redeemUserInviteCodeTitle": {},
"redeemUserInviteCodeSuccess": "Dein Plan wurde erfolgreich angepasst.",
"@redeemUserInviteCodeSuccess": {},
"voucherCreated": "Gutschein wurde erstellt",
"@voucherCreated": {},
"openVouchers": "Offene Gutscheine",
"@openVouchers": {},
"enterVoucherCode": "Gutschein Code eingeben",
"@enterVoucherCode": {},
"voucherRedeemed": "Gutschein eingelöst",
"@voucherRedeemed": {},
"requestedVouchers": "Beantragte Gutscheine",
"@requestedVouchers": {},
"redeemedVouchers": "Eingelöste Gutscheine",
"@redeemedVouchers": {},
"transactionCash": "Bargeldtransaktion",
"@transactionCash": {},
"transactionPlanUpgrade": "Planupgrade",
"@transactionPlanUpgrade": {},
"transactionRefund": "Rückerstattung",
"@transactionRefund": {},
"transactionAutoRenewal": "Automatische Verlängerung",
"@transactionAutoRenewal": {},
"refund": "Rückerstattung",
"@refund": {},
"transactionThanksForTesting": "Danke fürs Testen",
"@transactionThanksForTesting": {},
"transactionUnknown": "Unbekannte Transaktion",
"@transactionUnknown": {},
"transactionVoucherCreated": "Gutschein erstellt",
"@transactionVoucherCreated": {},
"transactionVoucherRedeemed": "Gutschein eingelöst",
"@transactionVoucherRedeemed": {},
"checkoutOptions": "Optionen",
"@checkoutOptions": {},
"checkoutPayYearly": "Jährlich bezahlen",
"@checkoutPayYearly": {},
"checkoutTotal": "Gesamt",
"@checkoutTotal": {},
"selectPaymentMethod": "Zahlungsmethode auswählen",
"@selectPaymentMethod": {},
"twonlyCredit": "twonly-Guthaben",
"@twonlyCredit": {},
"notEnoughCredit": "Du hast nicht genügend Guthaben!",
"@notEnoughCredit": {},
"chargeCredit": "Guthaben aufladen",
"@chargeCredit": {},
"autoRenewal": "Automatische Verlängerung",
"@autoRenewal": {},
"autoRenewalDesc": "Du kannst dies jederzeit ändern.",
"@autoRenewalDesc": {},
"autoRenewalLongDesc": "Wenn dein Abonnement ausläuft, wirst du automatisch auf den Preview-Plan zurückgestuft. Wenn du die automatische Verlängerung aktivierst, vergewissere dich bitte, dass du über genügend Guthaben für die automatische Erneuerung verfügst. Wir werden dich rechtzeitig vor der automatischen Erneuerung benachrichtigen.",
"@autoRenewalLongDesc": {},
"planSuccessUpgraded": "Dein Plan wurde erfolgreich aktualisiert.",
"@planSuccessUpgraded": {},
"checkoutSubmit": "Kostenpflichtig bestellen",
"@checkoutSubmit": {},
"additionalUsersList": "Ihre zusätzlichen Benutzer",
"@additionalUsersList": {},
"additionalUsersPlusTokens": "twonly-Codes für \"Plus\"-Benutzer",
"@additionalUsersPlusTokens": {},
"additionalUsersFreeTokens": "twonly-Codes für \"Free\"-Benutzer",
"@additionalUsersFreeTokens": {},
"planNotAllowed": "In deinem aktuellen Plan kannst du keine Mediendateien versenden. Aktualisiere deinen Plan jetzt, um die Mediendatei zu senden.",
"@planNotAllowed": {},
"planLimitReached": "Du hast dein Planlimit für heute erreicht. Aktualisiere deinen Plan jetzt, um die Mediendatei zu senden.",
"@planLimitReached": {},
"galleryDelete": "Datei löschen",
"@galleryDelete": {},
"galleryExport": "In Galerie exportieren",
"@galleryExport": {},
"galleryExportSuccess": "Erfolgreich in der Gallery gespeichert.",
"@galleryExportSuccess": {},
"galleryDetails": "Details anzeigen",
"@galleryDetails": {},
"settingsResetTutorials": "Tutorials erneut anzeigen",
"@settingsResetTutorials": {},
"settingsResetTutorialsDesc": "Klicke hier, um bereits angezeigte Tutorials erneut anzuzeigen.",
"@settingsResetTutorialsDesc": {},
"settingsResetTutorialsSuccess": "Tutorials werden erneut angezeigt.",
"@settingsResetTutorialsSuccess": {},
"tutorialChatListSearchUsersTitle": "Freunde finden und Freundschaftsanfragen verwalten",
"@tutorialChatListSearchUsersTitle": {},
"tutorialChatListSearchUsersDesc": "Wenn du die Benutzernamen deiner Freunde kennst, kannst du sie hier suchen und eine Freundschaftsanfrage senden. Außerdem siehst du hier alle Anfragen von anderen Nutzern, die du annehmen oder blockieren kannst.",
"@tutorialChatListSearchUsersDesc": {},
"tutorialChatListContextMenuTitle": "Klicke lange auf den Kontakt, um das Kontextmenü zu öffnen.",
"@tutorialChatListContextMenuTitle": {},
"tutorialChatListContextMenuDesc": "Mit dem Kontextmenü kannst du deine Kontakte anheften, archivieren und verschiedene Aktionen durchführen. Halte dazu einfach den Kontakt lange gedrückt und bewege dann deinen Finger auf die gewünschte Option oder tippe direkt darauf.",
"@tutorialChatListContextMenuDesc": {},
"tutorialChatMessagesVerifyShieldTitle": "Verifiziere deine Kontakte!",
"@tutorialChatMessagesVerifyShieldTitle": {},
"tutorialChatMessagesVerifyShieldDesc": "twonly nutzt das Signal-Protokoll für eine sichere Ende-zu-Ende Verschlüsselung. Bei der ersten Kontaktaufnahme wird dafür der öffentliche Identitätsschlüssel von deinem Kontakt heruntergeladen. Um sicherzustellen, dass dieser Schlüssel nicht von Dritten ausgetauscht wurde, solltest du ihn mit deinem Freund vergleichen, wenn ihr euch persönlich trefft. Sobald du den Benutzer verifiziert hast, kannst du auch beim verschicken von Bildern und Videos den twonly-Modus aktivieren.",
"@tutorialChatMessagesVerifyShieldDesc": {},
"tutorialChatMessagesReopenMessageTitle": "Bilder und Videos erneut öffnen",
"@tutorialChatMessagesReopenMessageTitle": {},
"tutorialChatMessagesReopenMessageDesc": "Wenn dein Freund dir ein Bild oder Video mit unendlicher Anzeigezeit gesendet hat, kannst du es bis zum Neustart der App jederzeit erneut öffnen. Um dies zu tun, musst du einfach doppelt auf die Nachricht klicken. Dein Freund erhält dann eine Benachrichtigung, dass du das Bild erneut angesehen hast.",
"@tutorialChatMessagesReopenMessageDesc": {},
"memoriesEmpty": "Sobald du Bilder oder Videos speicherst, landen sie hier in deinen Erinnerungen.",
"@memoriesEmpty": {},
"deleteTitle": "Bist du dir sicher?",
"@deleteTitle": {},
"deleteOkBtnForAll": "Für alle löschen",
"@deleteOkBtnForAll": {},
"deleteOkBtnForMe": "Für mich löschen",
"@deleteOkBtnForMe": {},
"deleteImageTitle": "Bist du dir sicher?",
"@deleteImageTitle": {},
"deleteImageBody": "Das Bild wird unwiderruflich gelöscht.",
"@deleteImageBody": {},
"backupNoticeTitle": "Kein Backup konfiguriert",
"@backupNoticeTitle": {},
"backupNoticeDesc": "Wenn du dein Gerät wechselst oder verlierst, kann ohne Backup niemand dein Account wiederherstellen. Sichere deshalb deine Daten.",
"@backupNoticeDesc": {},
"backupNoticeLater": "Später erinnern",
"@backupNoticeLater": {},
"backupNoticeOpenBackup": "Backup erstellen",
"@backupNoticeOpenBackup": {},
"backupPending": "Ausstehend",
"@backupPending": {},
"backupFailed": "Fehlgeschlagen",
"@backupFailed": {},
"backupSuccess": "Erfolgreich",
"@backupSuccess": {},
"backupTwonlySafeDesc": "Sichere deine twonly-Identität, da dies die einzige Möglichkeit ist, dein Konto wiederherzustellen, wenn du die App deinstallierst oder dein Handy verlierst.",
"@backupTwonlySafeDesc": {},
"backupServer": "Server",
"@backupServer": {},
"backupMaxBackupSize": "max. Backup-Größe",
"@backupMaxBackupSize": {},
"backupStorageRetention": "Speicheraufbewahrung",
"@backupStorageRetention": {},
"backupLastBackupDate": "Letztes Backup",
"@backupLastBackupDate": {},
"backupLastBackupSize": "Backup-Größe",
"@backupLastBackupSize": {},
"backupLastBackupResult": "Ergebnis",
"@backupLastBackupResult": {},
"deleteBackupTitle": "Bist du sicher?",
"@deleteBackupTitle": {},
"backupNoPasswordRecovery": "Aufgrund des Sicherheitssystems von twonly gibt es (derzeit) keine Funktion zur Wiederherstellung des Passworts. Daher musst du dir dein Passwort merken oder, besser noch, aufschreiben.",
"@backupNoPasswordRecovery": {},
"deleteBackupBody": "Ohne ein Backup kannst du dein Benutzerkonto nicht wiederherstellen.",
"@deleteBackupBody": {},
"backupData": "Daten-Backup",
"@backupData": {},
"backupDataDesc": "Das Daten-Backup enthält neben deiner twonly-Identität auch alle deine Mediendateien. Dieses Backup ist ebenfalls verschlüsselt, wird jedoch lokal gespeichert. Du musst es dann manuell auf deinen Laptop oder ein Gerät deiner Wahl kopieren.",
"@backupDataDesc": {},
"backupInsecurePassword": "Unsicheres Passwort",
"@backupInsecurePassword": {},
"backupInsecurePasswordDesc": "Das gewählte Passwort ist sehr unsicher und kann daher leicht von Angreifern erraten werden. Bitte wähle ein sicheres Passwort.",
"@backupInsecurePasswordDesc": {},
"backupInsecurePasswordOk": "Trotzdem fortfahren",
"@backupInsecurePasswordOk": {},
"backupInsecurePasswordCancel": "Erneut versuchen",
"@backupInsecurePasswordCancel": {},
"backupTwonlySafeLongDesc": "twonly hat keine zentralen Benutzerkonten. Während der Installation wird ein Schlüsselpaar erstellt, das aus einem öffentlichen und einem privaten Schlüssel besteht. Der private Schlüssel wird nur auf deinem Gerät gespeichert, um ihn vor unbefugtem Zugriff zu schützen. Der öffentliche Schlüssel wird auf den Server hochgeladen und mit deinem gewählten Benutzernamen verknüpft, damit andere dich finden können.\n\ntwonly Backup erstellt regelmäßig ein verschlüsseltes, anonymes Backup deines privaten Schlüssels zusammen mit deinen Kontakten und Einstellungen. Dein Benutzername und das gewählte Passwort reichen aus, um diese Daten auf einem anderen Gerät wiederherzustellen.",
"@backupTwonlySafeLongDesc": {},
"backupSelectStrongPassword": "Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Backup wiederherstellen möchtest.",
"@backupSelectStrongPassword": {},
"password": "Passwort",
"@password": {},
"passwordRepeated": "Passwort wiederholen",
"@passwordRepeated": {},
"passwordRepeatedNotEqual": "Passwörter stimmen nicht überein.",
"@passwordRepeatedNotEqual": {},
"backupPasswordRequirement": "Das Passwort muss mindestens 8 Zeichen lang sein.",
"@backupPasswordRequirement": {},
"backupExpertSettings": "Experteneinstellungen",
"@backupExpertSettings": {},
"backupEnableBackup": "Automatische Sicherung aktivieren",
"@backupEnableBackup": {},
"backupOwnServerDesc": "Speichere dein twonly Backup auf einem Server deiner Wahl.",
"@backupOwnServerDesc": {},
"backupUseOwnServer": "Server verwenden",
"@backupUseOwnServer": {},
"backupResetServer": "Standardserver verwenden",
"@backupResetServer": {},
"backupTwonlySaveNow": "Jetzt speichern",
"@backupTwonlySaveNow": {},
"backupChangePassword": "Password ändern",
"@backupChangePassword": {},
"inviteFriends": "Freunde einladen",
"@inviteFriends": {},
"inviteFriendsShareBtn": "Teilen",
"@inviteFriendsShareBtn": {},
"inviteFriendsShareText": "Wechseln wir zu twonly: {url}",
"@inviteFriendsShareText": {},
"appOutdated": "Deine Version von twonly ist veraltet.",
"@appOutdated": {},
"appOutdatedBtn": "Jetzt aktualisieren.",
"@appOutdatedBtn": {},
"doubleClickToReopen": "Doppelklicken zum\nerneuten Öffnen.",
"uploadLimitReached": "Das Upload-Limit wurde\nerreicht. Upgrade auf Pro\noder warte bis morgen.",
"@doubleClickToReopen": {},
"retransmissionRequested": "Wird erneut versucht.",
"@retransmissionRequested": {},
"testPaymentMethod": "Vielen Dank für dein Interesse an einem kostenpflichtigen Tarif. Die kostenpflichtigen Pläne sind derzeit noch deaktiviert. Sie werden aber bald aktiviert!",
"@testPaymentMethod": {},
"openChangeLog": "Changelog automatisch öffnen",
"@openChangeLog": {},
"reportUserTitle": "Melde {username}",
"@reportUserTitle": {},
"reportUserReason": "Meldegrund",
"@reportUserReason": {},
"reportUser": "Benutzer melden",
"@reportUser": {},
"newDeviceRegistered": "Du hast dich auf einem anderen Gerät angemeldet. Daher wurdest du hier abgemeldet.",
"@newDeviceRegistered": {},
"tabToRemoveEmoji": "Tippen um zu entfernen",
"@tabToRemoveEmoji": {},
"quotedMessageWasDeleted": "Die zitierte Nachricht wurde gelöscht.",
"@quotedMessageWasDeleted": {},
"messageWasDeleted": "Nachricht wurde gelöscht.",
"@messageWasDeleted": {},
"messageWasDeletedShort": "Gelöscht",
"@messageWasDeletedShort": {},
"sent": "Versendet",
"@sent": {},
"sentTo": "Zugestellt an",
"@sentTo": {},
"received": "Empfangen",
"@received": {},
"opened": "Geöffnet",
"@opened": {},
"waitingForInternet": "Warten auf Internet",
"@waitingForInternet": {},
"editHistory": "Bearbeitungshistorie",
"@editHistory": {},
"archivedChats": "Archivierte Chats",
"@archivedChats": {},
"durationShortSecond": "Sek.",
"@durationShortSecond": {},
"durationShortMinute": "Min.",
"@durationShortMinute": {},
"durationShortHour": "Std.",
"@durationShortHour": {},
"durationShortDays": "{count, plural, =1{1 Tag} other{{count} Tage}}",
"@durationShortDays": {},
"contacts": "Kontakte",
"groups": "Gruppen",
"@groups": {},
"newGroup": "Neue Gruppe",
"@newGroup": {},
"selectMembers": "Mitglieder auswählen",
"@selectMembers": {},
"selectGroupName": "Gruppennamen wählen",
"@selectGroupName": {},
"groupNameInput": "Gruppennamen",
"@groupNameInput": {},
"groupMembers": "Mitglieder",
"@groupMembers": {},
"createGroup": "Gruppe erstellen",
"@createGroup": {},
"addMember": "Mitglied hinzufügen",
"@addMember": {},
"leaveGroup": "Gruppe verlassen",
"@leaveGroup": {},
"createContactRequest": "Kontaktanfrage erstellen",
"@createContactRequest": {},
"contactRequestSend": "Kontakanfrage gesendet",
"makeAdmin": "Zum Admin machen",
"@makeAdmin": {},
"removeAdmin": "Als Admin entfernen",
"@removeAdmin": {},
"removeFromGroup": "Aus Gruppe entfernen",
"@removeFromGroup": {},
"admin": "Admin",
"@admin": {},
"revokeAdminRightsTitle": "Adminrechte von {username} entfernen?",
"@revokeAdminRightsTitle": {},
"revokeAdminRightsOkBtn": "Als Admin entfernen",
"@revokeAdminRightsOkBtn": {},
"makeAdminRightsTitle": "{username} zum Admin machen?",
"@makeAdminRightsTitle": {},
"makeAdminRightsBody": "{username} wird diese Gruppe und ihre Mitglieder bearbeiten können.",
"@makeAdminRightsBody": {},
"makeAdminRightsOkBtn": "Zum Admin machen",
"@makeAdminRightsOkBtn": {},
"updateGroup": "Gruppe aktualisieren",
"@updateGroup": {},
"alreadyInGroup": "Bereits Mitglied",
"@alreadyInGroup": {},
"removeContactFromGroupTitle": "{username} aus dieser Gruppe entfernen?",
"@removeContactFromGroupTitle": {},
"youChangedGroupName": "Du hast den Gruppennamen zu „{newGroupName}“ geändert.",
"@youChangedGroupName": {},
"makerChangedGroupName": "{maker} hat den Gruppennamen zu „{newGroupName}“ geändert.",
"@makerChangedGroupName": {},
"youCreatedGroup": "Du hast die Gruppe erstellt.",
"@youCreatedGroup": {},
"makerCreatedGroup": "{maker} hat die Gruppe erstellt.",
"@makerCreatedGroup": {},
"youRemovedMember": "Du hast {affected} aus der Gruppe entfernt.",
"@youRemovedMember": {},
"makerRemovedMember": "{maker} hat {affected} aus der Gruppe entfernt.",
"@makerRemovedMember": {},
"youAddedMember": "Du hast {affected} zur Gruppe hinzugefügt.",
"@youAddedMember": {},
"makerAddedMember": "{maker} hat {affected} zur Gruppe hinzugefügt.",
"@makerAddedMember": {},
"youMadeAdmin": "Du hast {affected} zum Administrator gemacht.",
"@youMadeAdmin": {},
"makerMadeAdmin": "{maker} hat {affected} zum Administrator gemacht.",
"@makerMadeAdmin": {},
"youRevokedAdminRights": "Du hast {affectedR} die Administratorrechte entzogen.",
"@youRevokedAdminRights": {},
"makerRevokedAdminRights": "{maker} hat {affectedR} die Administratorrechte entzogen.",
"@makerRevokedAdminRights": {},
"youLeftGroup": "Du hast die Gruppe verlassen.",
"@youLeftGroup": {},
"makerLeftGroup": "{maker} hat die Gruppe verlassen.",
"@makerLeftGroup": {},
"groupActionYou": "dich",
"@groupActionYou": {},
"groupActionYour": "deine",
"@groupActionYour": {},
"settingsBackup": "Backup",
"@settingsBackup": {},
"twonlySafeRecoverTitle": "Recovery",
"@twonlySafeRecoverTitle": {},
"twonlySafeRecoverDesc": "Wenn du ein Backup mit twonly Backup erstellt hast, kannst du es hier wiederherstellen.",
"@twonlySafeRecoverDesc": {},
"twonlySafeRecoverBtn": "Backup wiederherstellen",
"@twonlySafeRecoverBtn": {},
"notificationFillerIn": "in",
"notificationText": "hat eine Nachricht{inGroup} gesendet.",
"notificationTwonly": "hat ein twonly{inGroup} gesendet.",
@ -829,5 +441,15 @@
"inProcess": "Wird verarbeitet",
"draftMessage": "Entwurf",
"exportMemories": "Memories exportieren (Beta)",
"importMemories": "Memories importieren (Beta)"
"importMemories": "Memories importieren (Beta)",
"voiceMessageSlideToCancel": "Zum Abbrechen ziehen",
"voiceMessageCancel": "Abbrechen",
"shareYourProfile": "Teile dein Profil",
"scanOtherProfile": "Scanne ein anderes Profil",
"skipForNow": "Vorerst überspringen",
"linkFromUsername": "Ist der Link von {username}?",
"linkFromUsernameLong": "Wenn du den Link von der Person direkt erhalten hast, kannst du den Kontakt als verifiziert markieren, da der öffentliche Schlüssel im Link mit dem bereits für diesen Benutzer gespeicherten öffentlichen Schlüssel übereinstimmt.",
"gotLinkFromFriend": "Ja, der Link kommt direkt von der Person.",
"couldNotVerifyUsername": "{username} konnte nicht verifiziert werden",
"linkPubkeyDoesNotMatch": "Der öffentliche Schlüssel im Link stimmt nicht mit dem für diesen Kontakt gespeicherten öffentlichen Schlüssel überein. Triff die Person persönlich und scanne den QR-Code direkt!"
}

View file

@ -1,105 +1,58 @@
{
"@@locale": "en",
"registerTitle": "Welcome to twonly!",
"@registerTitle": {},
"registerSlogan": "twonly, a privacy friendly way to connect with friends through secure, spontaneous image sharing",
"@registerSlogan": {},
"onboardingWelcomeTitle": "Welcome to twonly!",
"@onboardingWelcomeTitle": {},
"onboardingWelcomeBody": "Experience a private and secure way to stay in touch with friends by sharing instant pictures.",
"@onboardingWelcomeBody": {},
"onboardingE2eTitle": "Carefree sharing",
"@onboardingE2eTitle": {},
"onboardingE2eBody": "With end-to-end encryption, enjoy the peace of mind that only you and your friends can see the moments you share.",
"@onboardingE2eBody": {},
"onboardingFocusTitle": "Focus on sharing moments",
"@onboardingFocusTitle": {},
"onboardingFocusBody": "Say goodbye to addictive features! twonly was created for sharing moments, free from useless distractions or ads.",
"@onboardingFocusBody": {},
"onboardingSendTwonliesTitle": "Send twonlies",
"@onboardingSendTwonliesTitle": {},
"onboardingSendTwonliesBody": "Share moments securely with your partner. twonly ensures that only your partner can open it, keeping your moments with your partner a two(o)nly thing!",
"@onboardingSendTwonliesBody": {},
"onboardingNotProductTitle": "You are not the product!",
"@onboardingNotProductTitle": {},
"onboardingNotProductBody": "twonly is financed by donations and an optional subscription. Your data will never be sold.",
"@onboardingNotProductBody": {},
"onboardingBuyOneGetTwoTitle": "Buy one get two",
"@onboardingBuyOneGetTwoTitle": {},
"onboardingBuyOneGetTwoBody": "twonly always requires at least two people, which is why you receive a second free license for your twonly partner with your purchase.",
"@onboardingBuyOneGetTwoBody": {},
"onboardingGetStartedTitle": "Let's go!",
"@onboardingGetStartedTitle": {},
"onboardingGetStartedBody": "You can test twonly free of charge in preview mode. In this mode you can be found by others and receive pictures or videos but you cannot send any yourself.",
"@onboardingGetStartedBody": {},
"onboardingTryForFree": "Try for free",
"@onboardingTryForFree": {},
"registerUsernameSlogan": "Please select a username so others can find you!",
"@registerUsernameSlogan": {},
"registerUsernameDecoration": "Username",
"@registerUsernameDecoration": {},
"registerUsernameLimits": "Your username must be at least 3 characters long.",
"@registerUsernameLimits": {},
"registerSubmitButton": "Register now!",
"@registerSubmitButton": {},
"registerTwonlyCodeText": "Have you received a twonly code? Then redeem it either directly here or later!",
"registerTwonlyCodeLabel": "twonly-Code",
"newMessageTitle": "New message",
"@newMessageTitle": {},
"chatsTapToSend": "Click to send your first image",
"@chatsTapToSend": {},
"cameraPreviewSendTo": "Send to",
"@cameraPreviewSendTo": {},
"shareImageTitle": "Share with",
"@shareImageTitle": {},
"shareImageBestFriends": "Best friends",
"@shareImageBestFriends": {},
"shareImagePinnedContacts": "Pinnded",
"@shareImagePinnedContacts": {},
"shareImagedEditorSendImage": "Send",
"@shareImagedEditorSendImage": {},
"shareImagedEditorShareWith": "Share with",
"@shareImagedEditorShareWith": {},
"shareImagedEditorSaveImage": "Save",
"@shareImagedEditorSaveImage": {},
"shareImagedEditorSavedImage": "Saved",
"@shareImagedEditorSavedImage": {},
"shareImageSearchAllContacts": "Search all contacts",
"@shareImageSearchAllContacts": {},
"startNewChatSearchHint": "Name, username or groupname",
"shareImagedSelectAll": "Select all",
"@shareImagedSelectAll": {},
"startNewChatTitle": "Select Contact",
"@startNewChatTitle": {},
"startNewChatNewContact": "New Contact",
"@startNewChatNewContact": {},
"startNewChatYourContacts": "Your Contacts",
"@startNewChatYourContacts": {},
"shareImageAllUsers": "All contacts",
"@shareImageAllUsers": {},
"shareImageAllTwonlyWarning": "twonlies can only be send to verified contacts!",
"@shareImageAllTwonlyWarning": {},
"shareImageUserNotVerified": "User is not verified",
"shareImageUserNotVerifiedDesc": "twonlies can only be sent to verified users. To verify a user, go to their profile and to verify security number.",
"shareImageShowArchived": "Show archived users",
"searchUsernameInput": "Username",
"@searchUsernameInput": {},
"searchUsernameTitle": "Search username",
"searchUserNamePreview": "To protect you and other twonly users from spam and abuse, it is not possible to search for other people in preview mode. Other users can find you and their requests will be displayed here!",
"@searchUserNamePreview": {},
"@searchUsernameTitle": {},
"selectSubscription": "Select subscription",
"@selectSubscription": {},
"searchUserNamePending": "Pending",
"@searchUserNamePending": {},
"searchUserNameBlockUserTooltip": "Block the user without informing.",
"@searchUserNameBlockUserTooltip": {},
"searchUserNameRejectUserTooltip": "Reject the request and let the requester know.",
"@searchUserNameRejectUserTooltip": {},
"searchUserNameArchiveUserTooltip": "Archive the user. He will appear again as soon as he accepts your request.",
"@searchUserNameArchiveUserTooltip": {},
"searchUsernameNotFound": "Username not found",
"@searchUsernameNotFound": {},
"searchUsernameNotFoundBody": "There is no user with the username \"{username}\" registered",
"@searchUsernameNotFoundBody": {
"placeholders": {
@ -107,91 +60,49 @@
}
},
"searchUsernameNewFollowerTitle": "Follow requests",
"@searchUsernameNewFollowerTitle": {},
"searchUsernameQrCodeBtn": "Scan QR code",
"@searchUsernameQrCodeBtn": {},
"chatListViewSearchUserNameBtn": "Add your first twonly contact!",
"@chatListViewSearchUserNameBtn": {},
"chatListViewSendFirstTwonly": "Send your first twonly!",
"@chatListViewSendFirstTwonly": {},
"chatListDetailInput": "Type a message",
"@chatListDetailInput": {},
"userDeletedAccount": "The user has deleted its account.",
"contextMenuUserProfile": "User profile",
"contextMenuVerifyUser": "Verify",
"@contextMenuVerifyUser": {},
"contextMenuArchiveUser": "Archive",
"@contextMenuArchiveUser": {},
"contextMenuUndoArchiveUser": "Undo archiving",
"@contextMenuUndoArchiveUser": {},
"contextMenuOpenChat": "Open chat",
"@contextMenuOpenChat": {},
"contextMenuPin": "Pin",
"@contextMenuPin": {},
"contextMenuUnpin": "Unpin",
"@contextMenuUnpin": {},
"mediaViewerAuthReason": "Please authenticate to see this twonly!",
"@mediaViewerAuthReason": {},
"mediaViewerTwonlyTapToOpen": "Tap to open your twonly!",
"@mediaViewerTwonlyTapToOpen": {},
"messageSendState_Received": "Received",
"@messageSendState_Received": {},
"messageSendState_Opened": "Opened",
"@messageSendState_Opened": {},
"messageSendState_Send": "Sent",
"@messageSendState_Send": {},
"messageSendState_Sending": "Sending",
"@messageSendState_Sending": {},
"messageSendState_TapToLoad": "Tap to load",
"@messageSendState_TapToLoad": {},
"messageSendState_Loading": "Downloading",
"@messageSendState_Loading": {},
"messageStoredInGallery": "Stored in gallery",
"@messageStoredInGallery": {},
"messageReopened": "Re-opened",
"@messageReopened": {},
"imageEditorDrawOk": "Take drawing",
"@imageEditorDrawOk": {},
"settingsTitle": "Settings",
"@settingsTitle": {},
"settingsChats": "Chats",
"@settingsChats": {},
"settingsPreSelectedReactions": "Preselected reaction emojis",
"@settingsPreSelectedReactions": {},
"settingsPreSelectedReactionsError": "A maximum of 12 reactions can be selected.",
"@settingsPreSelectedReactionsError": {},
"settingsProfile": "Profile",
"@settingsProfile": {},
"settingsStorageData": "Data and storage",
"@settingsStorageData": {},
"settingsStorageDataStoreInGTitle": "Store in Gallery",
"@settingsStorageDataStoreInGTitle": {},
"settingsStorageDataStoreInGSubtitle": "Store saved images additional in the systems gallery.",
"@settingsStorageDataStoreInGSubtitle": {},
"settingsStorageDataMediaAutoDownload": "Media auto-download",
"@settingsStorageDataMediaAutoDownload": {},
"settingsStorageDataAutoDownMobile": "When using mobile data",
"@settingsStorageDataAutoDownMobile": {},
"settingsStorageDataAutoDownWifi": "When using WI-FI",
"@settingsStorageDataAutoDownWifi": {},
"settingsProfileCustomizeAvatar": "Customize your avatar",
"@settingsProfileCustomizeAvatar": {},
"settingsProfileEditDisplayName": "Displayname",
"@settingsProfileEditDisplayName": {},
"settingsProfileEditDisplayNameNew": "New Displayname",
"@settingsProfileEditDisplayNameNew": {},
"settingsAccount": "Konto",
"@settingsAccount": {},
"settingsSubscription": "Subscription",
"@settingsSubscription": {},
"settingsAppearance": "Appearance",
"@settingsAppearance": {},
"settingsPrivacy": "Privacy",
"@settingsPrivacy": {},
"settingsPrivacyBlockUsers": "Block users",
"@settingsPrivacyBlockUsers": {},
"settingsPrivacyBlockUsersDesc": "Blocked users will not be able to communicate with you. You can unblock a blocked user at any time.",
"@settingsPrivacyBlockUsersDesc": {},
"settingsPrivacyBlockUsersCount": "{len} contact(s)",
"@settingsPrivacyBlockUsersCount": {
"placeholders": {
@ -199,30 +110,18 @@
}
},
"settingsNotification": "Notification",
"@settingsNotification": {},
"settingsNotifyTroubleshooting": "Troubleshooting",
"@settingsNotifyTroubleshooting": {},
"settingsNotifyTroubleshootingDesc": "Click here if you have problems receiving push notifications.",
"@settingsNotifyTroubleshootingDesc": {},
"settingsNotifyTroubleshootingNoProblem": "No problem detected",
"@settingsNotifyTroubleshootingNoProblem": {},
"settingsNotifyTroubleshootingNoProblemDesc": "Press OK to receive a test notification. When you receive no message even after waiting for 10 minutes, please send us your debug log in Settings > Help > Debug log, so we can look at that issue.",
"@settingsNotifyTroubleshootingNoProblemDesc": {},
"settingsHelp": "Help",
"@settingsHelp": {},
"settingsHelpDiagnostics": "Diagnostic protocol",
"@settingsHelpDiagnostics": {},
"settingsHelpFAQ": "FAQ",
"@settingsHelpFAQ": {},
"feedbackTooltip": "Give Feedback to improve twonly.",
"settingsHelpContactUs": "Contact us",
"@settingsHelpContactUs": {},
"settingsHelpVersion": "Version",
"@settingsHelpVersion": {},
"settingsHelpLicenses": "Licenses (Source-Code)",
"@settingsHelpLicenses": {},
"settingsHelpCredits": "Licenses (Images)",
"@settingsHelpCredits": {},
"settingsHelpImprint": "Imprint & Privacy Policy",
"contactUsFaq": "Have you read our FAQ yet?",
"contactUsEmojis": "How do you feel? (optional)",
@ -243,24 +142,16 @@
"contactUsShortcut": "Hide Feedback Icon",
"settingsHelpTerms": "Terms of Service",
"settingsAppearanceTheme": "Theme",
"@settingsAppearanceTheme": {},
"settingsAccountDeleteAccount": "Delete account",
"settingsAccountDeleteAccountWithBallance": "In the next step, you can select what you want to to with the remaining credit ({credit}).",
"settingsAccountDeleteAccountNoBallance": "Once you delete your account, there is no going back.",
"settingsAccountDeleteAccountNoInternet": "An Internet connection is required to delete your account.",
"@settingsAccountDeleteAccount": {},
"settingsAccountDeleteModalTitle": "Are you sure?",
"@settingsAccountDeleteModalTitle": {},
"settingsAccountDeleteModalBody": "Your account will be deleted. There is no change to restore it.",
"@settingsAccountDeleteModalBody": {},
"contactVerifyNumberTitle": "Verify safety number",
"@contactVerifyNumberTitle": {},
"contactVerifyNumberTapToScan": "Tap to scan",
"@contactVerifyNumberTapToScan": {},
"contactVerifyNumberMarkAsVerified": "Mark as verified",
"@contactVerifyNumberMarkAsVerified": {},
"contactVerifyNumberClearVerification": "Clear verification",
"@contactVerifyNumberClearVerification": {},
"contactVerifyNumberLongDesc": "To verify the end-to-end encryption with {username}, compare the numbers with their device. The person can also scan your code with their device.",
"@contactVerifyNumberLongDesc": {
"placeholders": {
@ -268,11 +159,8 @@
}
},
"contactNickname": "Nickname",
"@contactNickname": {},
"contactNicknameNew": "New nickname",
"@contactNicknameNew": {},
"deleteAllContactMessages": "Delete all text-messages",
"@deleteAllContactMessages": {},
"deleteAllContactMessagesBody": "This will remove all messages, except stored media files, in your chat with {username}. This will NOT delete the messages stored at {username}s device!",
"@deleteAllContactMessagesBody": {
"placeholders": {
@ -280,7 +168,6 @@
}
},
"contactBlock": "Block",
"@contactBlock": {},
"contactBlockTitle": "Block {username}",
"@contactBlockTitle": {
"placeholders": {
@ -288,7 +175,6 @@
}
},
"contactBlockBody": "A blocked user will no longer be able to send you messages and their profile will be hidden from view. To unblock a user, simply navigate to Settings > Privacy > Blocked Users.",
"@contactBlockBody": {},
"contactRemove": "Remove user",
"contactRemoveTitle": "Remove {username}",
"contactRemoveBody": "Remove the user and permanently delete the chat and all associated media files. This will also delete YOUR ACCOUNT FROM YOUR CONTACT'S PHONE.",
@ -313,23 +199,14 @@
"info": "Info",
"ok": "Ok",
"switchFrontAndBackCamera": "Switch between front and back camera.",
"@switchFrontAndBackCamera": {},
"addTextItem": "Text",
"@addTextItem": {},
"protectAsARealTwonly": "Send as real twonly!",
"@protectAsARealTwonly": {},
"addDrawing": "Drawing",
"@addDrawing": {},
"addEmoji": "Emoji",
"@addEmoji": {},
"toggleFlashLight": "Toggle the flash light",
"@toggleFlashLight": {},
"toggleHighQuality": "Toggle better resolution",
"@toggleHighQuality": {},
"userFound": "User found",
"@userFound": {},
"userFound": "{username} found",
"userFoundBody": "Do you want to create a follow request?",
"@userFoundBody": {},
"searchUsernameNotFoundLong": "\"{username}\" is not a twonly user. Please check the username and try again.",
"@searchUsernameNotFoundLong": {
"placeholders": {
@ -337,31 +214,18 @@
}
},
"errorUnknown": "An unexpected error has occurred. Please try again later.",
"@errorUnknown": {},
"errorBadRequest": "The request could not be understood by the server due to malformed syntax. Please check your input and try again.",
"@errorBadRequest": {},
"errorTooManyRequests": "You have made too many requests in a short period. Please wait a moment before trying again.",
"@errorTooManyRequests": {},
"errorInternalError": "The server is currently not available. Please try again later.",
"@errorInternalError": {},
"errorInvalidInvitationCode": "The invitation code you provided is invalid. Please check the code and try again.",
"@errorInvalidInvitationCode": {},
"errorUsernameAlreadyTaken": "The username is already taken.",
"@errorUsernameAlreadyTaken": {},
"errorSignatureNotValid": "The provided signature is not valid. Please check your credentials and try again.",
"@errorSignatureNotValid": {},
"errorUsernameNotFound": "The username you entered does not exist. Please check the spelling or create a new account.",
"@errorUsernameNotFound": {},
"errorUsernameNotValid": "The username you provided does not meet the required criteria. Please choose a valid username.",
"@errorUsernameNotValid": {},
"errorInvalidPublicKey": "The public key you provided is invalid. Please check the key and try again.",
"@errorInvalidPublicKey": {},
"errorSessionAlreadyAuthenticated": "You are already logged in. Please log out if you want to log in with a different account.",
"@errorSessionAlreadyAuthenticated": {},
"errorSessionNotAuthenticated": "Your session is not authenticated. Please log in to continue.",
"@errorSessionNotAuthenticated": {},
"errorOnlyOneSessionAllowed": "Only one active session is allowed per user. Please log out from other devices to continue.",
"@errorOnlyOneSessionAllowed": {},
"errorNotEnoughCredit": "You do not have enough twonly-credit.",
"errorVoucherInvalid": "The voucher code you entered is not valid.",
"errorPlanLimitReached": "You have reached your plans limit. Please upgrade your plan.",
@ -607,5 +471,15 @@
"inProcess": "In process",
"draftMessage": "Draft",
"exportMemories": "Export memories (Beta)",
"importMemories": "Import memories (Beta)"
"importMemories": "Import memories (Beta)",
"voiceMessageSlideToCancel": "Slide to cancel",
"voiceMessageCancel": "Cancel",
"shareYourProfile": "Share your profile",
"scanOtherProfile": "Scan other profile",
"skipForNow": "Skip for now",
"linkFromUsername": "Is the link from {username}?",
"linkFromUsernameLong": "If you received the link from your friend, you can mark the user as verified, as the public key in the link matches the public key already stored for that user?",
"gotLinkFromFriend": "Yes, I got the link from my friend!",
"couldNotVerifyUsername": "Could not verify {username}",
"linkPubkeyDoesNotMatch": "The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!"
}

View file

@ -1181,8 +1181,8 @@ abstract class AppLocalizations {
/// No description provided for @userFound.
///
/// In en, this message translates to:
/// **'User found'**
String get userFound;
/// **'{username} found'**
String userFound(Object username);
/// No description provided for @userFoundBody.
///
@ -2749,6 +2749,66 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Import memories (Beta)'**
String get importMemories;
/// No description provided for @voiceMessageSlideToCancel.
///
/// In en, this message translates to:
/// **'Slide to cancel'**
String get voiceMessageSlideToCancel;
/// No description provided for @voiceMessageCancel.
///
/// In en, this message translates to:
/// **'Cancel'**
String get voiceMessageCancel;
/// No description provided for @shareYourProfile.
///
/// In en, this message translates to:
/// **'Share your profile'**
String get shareYourProfile;
/// No description provided for @scanOtherProfile.
///
/// In en, this message translates to:
/// **'Scan other profile'**
String get scanOtherProfile;
/// No description provided for @skipForNow.
///
/// In en, this message translates to:
/// **'Skip for now'**
String get skipForNow;
/// No description provided for @linkFromUsername.
///
/// In en, this message translates to:
/// **'Is the link from {username}?'**
String linkFromUsername(Object username);
/// No description provided for @linkFromUsernameLong.
///
/// In en, this message translates to:
/// **'If you received the link from your friend, you can mark the user as verified, as the public key in the link matches the public key already stored for that user?'**
String get linkFromUsernameLong;
/// No description provided for @gotLinkFromFriend.
///
/// In en, this message translates to:
/// **'Yes, I got the link from my friend!'**
String get gotLinkFromFriend;
/// No description provided for @couldNotVerifyUsername.
///
/// In en, this message translates to:
/// **'Could not verify {username}'**
String couldNotVerifyUsername(Object username);
/// No description provided for @linkPubkeyDoesNotMatch.
///
/// In en, this message translates to:
/// **'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!'**
String get linkPubkeyDoesNotMatch;
}
class _AppLocalizationsDelegate

View file

@ -598,7 +598,9 @@ class AppLocalizationsDe extends AppLocalizations {
String get toggleHighQuality => 'Bessere Auflösung umschalten';
@override
String get userFound => 'Benutzer gefunden';
String userFound(Object username) {
return '$username gefunden';
}
@override
String get userFoundBody => 'Möchtest du eine Folgeanfrage stellen?';
@ -1516,4 +1518,40 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get importMemories => 'Memories importieren (Beta)';
@override
String get voiceMessageSlideToCancel => 'Zum Abbrechen ziehen';
@override
String get voiceMessageCancel => 'Abbrechen';
@override
String get shareYourProfile => 'Teile dein Profil';
@override
String get scanOtherProfile => 'Scanne ein anderes Profil';
@override
String get skipForNow => 'Vorerst überspringen';
@override
String linkFromUsername(Object username) {
return 'Ist der Link von $username?';
}
@override
String get linkFromUsernameLong =>
'Wenn du den Link von der Person direkt erhalten hast, kannst du den Kontakt als verifiziert markieren, da der öffentliche Schlüssel im Link mit dem bereits für diesen Benutzer gespeicherten öffentlichen Schlüssel übereinstimmt.';
@override
String get gotLinkFromFriend => 'Ja, der Link kommt direkt von der Person.';
@override
String couldNotVerifyUsername(Object username) {
return '$username konnte nicht verifiziert werden';
}
@override
String get linkPubkeyDoesNotMatch =>
'Der öffentliche Schlüssel im Link stimmt nicht mit dem für diesen Kontakt gespeicherten öffentlichen Schlüssel überein. Triff die Person persönlich und scanne den QR-Code direkt!';
}

View file

@ -593,7 +593,9 @@ class AppLocalizationsEn extends AppLocalizations {
String get toggleHighQuality => 'Toggle better resolution';
@override
String get userFound => 'User found';
String userFound(Object username) {
return '$username found';
}
@override
String get userFoundBody => 'Do you want to create a follow request?';
@ -1506,4 +1508,40 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get importMemories => 'Import memories (Beta)';
@override
String get voiceMessageSlideToCancel => 'Slide to cancel';
@override
String get voiceMessageCancel => 'Cancel';
@override
String get shareYourProfile => 'Share your profile';
@override
String get scanOtherProfile => 'Scan other profile';
@override
String get skipForNow => 'Skip for now';
@override
String linkFromUsername(Object username) {
return 'Is the link from $username?';
}
@override
String get linkFromUsernameLong =>
'If you received the link from your friend, you can mark the user as verified, as the public key in the link matches the public key already stored for that user?';
@override
String get gotLinkFromFriend => 'Yes, I got the link from my friend!';
@override
String couldNotVerifyUsername(Object username) {
return 'Could not verify $username';
}
@override
String get linkPubkeyDoesNotMatch =>
'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!';
}

View file

@ -31,6 +31,9 @@ class UserData {
@JsonKey(defaultValue: false)
bool isDeveloper = false;
@JsonKey(defaultValue: false)
bool disableVideoCompression = false;
@JsonKey(defaultValue: 0)
int deviceId = 0;

View file

@ -17,6 +17,8 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
..appVersion = (json['appVersion'] as num?)?.toInt() ?? 0
..avatarCounter = (json['avatarCounter'] as num?)?.toInt() ?? 0
..isDeveloper = json['isDeveloper'] as bool? ?? false
..disableVideoCompression =
json['disableVideoCompression'] as bool? ?? false
..deviceId = (json['deviceId'] as num?)?.toInt() ?? 0
..lastImageSend = json['lastImageSend'] == null
? null
@ -79,6 +81,7 @@ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
'appVersion': instance.appVersion,
'avatarCounter': instance.avatarCounter,
'isDeveloper': instance.isDeveloper,
'disableVideoCompression': instance.disableVideoCompression,
'deviceId': instance.deviceId,
'subscriptionPlan': instance.subscriptionPlan,
'lastImageSend': instance.lastImageSend?.toIso8601String(),

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,11 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/http/http_requests.proto
//
// @dart = 2.12
// Generated from api/http/http_requests.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/http/http_requests.proto
//
// @dart = 2.12
// Generated from api/http/http_requests.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -19,7 +20,15 @@ const TextMessage$json = {
'2': [
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'},
{'1': 'body', '3': 2, '4': 1, '5': 12, '10': 'body'},
{'1': 'push_data', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'pushData', '17': true},
{
'1': 'push_data',
'3': 3,
'4': 1,
'5': 12,
'9': 0,
'10': 'pushData',
'17': true
},
],
'8': [
{'1': '_push_data'},
@ -37,7 +46,14 @@ const UploadRequest$json = {
'2': [
{'1': 'encrypted_data', '3': 1, '4': 1, '5': 12, '10': 'encryptedData'},
{'1': 'download_tokens', '3': 2, '4': 3, '5': 12, '10': 'downloadTokens'},
{'1': 'messages_on_success', '3': 3, '4': 3, '5': 11, '6': '.http_requests.TextMessage', '10': 'messagesOnSuccess'},
{
'1': 'messages_on_success',
'3': 3,
'4': 3,
'5': 11,
'6': '.http_requests.TextMessage',
'10': 'messagesOnSuccess'
},
],
};
@ -52,7 +68,14 @@ final $typed_data.Uint8List uploadRequestDescriptor = $convert.base64Decode(
const UpdateGroupState$json = {
'1': 'UpdateGroupState',
'2': [
{'1': 'update', '3': 1, '4': 1, '5': 11, '6': '.http_requests.UpdateGroupState.UpdateTBS', '10': 'update'},
{
'1': 'update',
'3': 1,
'4': 1,
'5': 11,
'6': '.http_requests.UpdateGroupState.UpdateTBS',
'10': 'update'
},
{'1': 'signature', '3': 2, '4': 1, '5': 12, '10': 'signature'},
],
'3': [UpdateGroupState_UpdateTBS$json],
@ -63,10 +86,32 @@ const UpdateGroupState_UpdateTBS$json = {
'1': 'UpdateTBS',
'2': [
{'1': 'version_id', '3': 1, '4': 1, '5': 4, '10': 'versionId'},
{'1': 'encrypted_group_state', '3': 3, '4': 1, '5': 12, '10': 'encryptedGroupState'},
{
'1': 'encrypted_group_state',
'3': 3,
'4': 1,
'5': 12,
'10': 'encryptedGroupState'
},
{'1': 'public_key', '3': 4, '4': 1, '5': 12, '10': 'publicKey'},
{'1': 'remove_admin', '3': 5, '4': 1, '5': 12, '9': 0, '10': 'removeAdmin', '17': true},
{'1': 'add_admin', '3': 6, '4': 1, '5': 12, '9': 1, '10': 'addAdmin', '17': true},
{
'1': 'remove_admin',
'3': 5,
'4': 1,
'5': 12,
'9': 0,
'10': 'removeAdmin',
'17': true
},
{
'1': 'add_admin',
'3': 6,
'4': 1,
'5': 12,
'9': 1,
'10': 'addAdmin',
'17': true
},
{'1': 'nonce', '3': 7, '4': 1, '5': 12, '10': 'nonce'},
],
'8': [
@ -91,7 +136,13 @@ const NewGroupState$json = {
'2': [
{'1': 'group_id', '3': 1, '4': 1, '5': 9, '10': 'groupId'},
{'1': 'version_id', '3': 2, '4': 1, '5': 4, '10': 'versionId'},
{'1': 'encrypted_group_state', '3': 3, '4': 1, '5': 12, '10': 'encryptedGroupState'},
{
'1': 'encrypted_group_state',
'3': 3,
'4': 1,
'5': 12,
'10': 'encryptedGroupState'
},
{'1': 'public_key', '3': 4, '4': 1, '5': 12, '10': 'publicKey'},
],
};
@ -107,7 +158,14 @@ const AppendGroupState$json = {
'1': 'AppendGroupState',
'2': [
{'1': 'signature', '3': 1, '4': 1, '5': 12, '10': 'signature'},
{'1': 'appendTBS', '3': 2, '4': 1, '5': 11, '6': '.http_requests.AppendGroupState.AppendTBS', '10': 'appendTBS'},
{
'1': 'appendTBS',
'3': 2,
'4': 1,
'5': 11,
'6': '.http_requests.AppendGroupState.AppendTBS',
'10': 'appendTBS'
},
{'1': 'versionId', '3': 3, '4': 1, '5': 4, '10': 'versionId'},
],
'3': [AppendGroupState_AppendTBS$json],
@ -117,7 +175,13 @@ const AppendGroupState$json = {
const AppendGroupState_AppendTBS$json = {
'1': 'AppendTBS',
'2': [
{'1': 'encrypted_group_state_append', '3': 1, '4': 1, '5': 12, '10': 'encryptedGroupStateAppend'},
{
'1': 'encrypted_group_state_append',
'3': 1,
'4': 1,
'5': 12,
'10': 'encryptedGroupStateAppend'
},
{'1': 'public_key', '3': 2, '4': 1, '5': 12, '10': 'publicKey'},
{'1': 'group_id', '3': 3, '4': 1, '5': 9, '10': 'groupId'},
{'1': 'nonce', '3': 4, '4': 1, '5': 12, '10': 'nonce'},
@ -138,8 +202,21 @@ const GroupState$json = {
'1': 'GroupState',
'2': [
{'1': 'version_id', '3': 1, '4': 1, '5': 4, '10': 'versionId'},
{'1': 'encrypted_group_state', '3': 2, '4': 1, '5': 12, '10': 'encryptedGroupState'},
{'1': 'appended_group_states', '3': 3, '4': 3, '5': 11, '6': '.http_requests.AppendGroupState', '10': 'appendedGroupStates'},
{
'1': 'encrypted_group_state',
'3': 2,
'4': 1,
'5': 12,
'10': 'encryptedGroupState'
},
{
'1': 'appended_group_states',
'3': 3,
'4': 3,
'5': 11,
'6': '.http_requests.AppendGroupState',
'10': 'appendedGroupStates'
},
],
};
@ -154,7 +231,14 @@ final $typed_data.Uint8List groupStateDescriptor = $convert.base64Decode(
const AppendGroupStateHelper$json = {
'1': 'AppendGroupStateHelper',
'2': [
{'1': 'appended_group_states', '3': 1, '4': 3, '5': 11, '6': '.http_requests.AppendGroupState', '10': 'appendedGroupStates'},
{
'1': 'appended_group_states',
'3': 1,
'4': 3,
'5': 11,
'6': '.http_requests.AppendGroupState',
'10': 'appendedGroupStates'
},
],
};
@ -162,4 +246,3 @@ const AppendGroupStateHelper$json = {
final $typed_data.Uint8List appendGroupStateHelperDescriptor = $convert.base64Decode(
'ChZBcHBlbmRHcm91cFN0YXRlSGVscGVyElMKFWFwcGVuZGVkX2dyb3VwX3N0YXRlcxgBIAMoCz'
'IfLmh0dHBfcmVxdWVzdHMuQXBwZW5kR3JvdXBTdGF0ZVITYXBwZW5kZWRHcm91cFN0YXRlcw==');

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,11 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/websocket/client_to_server.proto
//
// @dart = 2.12
// Generated from api/websocket/client_to_server.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/websocket/client_to_server.proto
//
// @dart = 2.12
// Generated from api/websocket/client_to_server.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -17,7 +18,15 @@ import 'dart:typed_data' as $typed_data;
const ClientToServer$json = {
'1': 'ClientToServer',
'2': [
{'1': 'V0', '3': 1, '4': 1, '5': 11, '6': '.client_to_server.V0', '9': 0, '10': 'V0'},
{
'1': 'V0',
'3': 1,
'4': 1,
'5': 11,
'6': '.client_to_server.V0',
'9': 0,
'10': 'V0'
},
],
'8': [
{'1': 'v'},
@ -34,9 +43,33 @@ const V0$json = {
'1': 'V0',
'2': [
{'1': 'seq', '3': 1, '4': 1, '5': 4, '10': 'seq'},
{'1': 'handshake', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.Handshake', '9': 0, '10': 'handshake'},
{'1': 'applicationdata', '3': 3, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData', '9': 0, '10': 'applicationdata'},
{'1': 'response', '3': 4, '4': 1, '5': 11, '6': '.client_to_server.Response', '9': 0, '10': 'response'},
{
'1': 'handshake',
'3': 2,
'4': 1,
'5': 11,
'6': '.client_to_server.Handshake',
'9': 0,
'10': 'handshake'
},
{
'1': 'applicationdata',
'3': 3,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData',
'9': 0,
'10': 'applicationdata'
},
{
'1': 'response',
'3': 4,
'4': 1,
'5': 11,
'6': '.client_to_server.Response',
'9': 0,
'10': 'response'
},
],
'8': [
{'1': 'Kind'},
@ -55,13 +88,59 @@ final $typed_data.Uint8List v0Descriptor = $convert.base64Decode(
const Handshake$json = {
'1': 'Handshake',
'2': [
{'1': 'register', '3': 1, '4': 1, '5': 11, '6': '.client_to_server.Handshake.Register', '9': 0, '10': 'register'},
{'1': 'getAuthChallenge', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.Handshake.GetAuthChallenge', '9': 0, '10': 'getAuthChallenge'},
{'1': 'getAuthToken', '3': 3, '4': 1, '5': 11, '6': '.client_to_server.Handshake.GetAuthToken', '9': 0, '10': 'getAuthToken'},
{'1': 'authenticate', '3': 4, '4': 1, '5': 11, '6': '.client_to_server.Handshake.Authenticate', '9': 0, '10': 'authenticate'},
{'1': 'requestPOW', '3': 5, '4': 1, '5': 11, '6': '.client_to_server.Handshake.RequestPOW', '9': 0, '10': 'requestPOW'},
{
'1': 'register',
'3': 1,
'4': 1,
'5': 11,
'6': '.client_to_server.Handshake.Register',
'9': 0,
'10': 'register'
},
{
'1': 'getAuthChallenge',
'3': 2,
'4': 1,
'5': 11,
'6': '.client_to_server.Handshake.GetAuthChallenge',
'9': 0,
'10': 'getAuthChallenge'
},
{
'1': 'getAuthToken',
'3': 3,
'4': 1,
'5': 11,
'6': '.client_to_server.Handshake.GetAuthToken',
'9': 0,
'10': 'getAuthToken'
},
{
'1': 'authenticate',
'3': 4,
'4': 1,
'5': 11,
'6': '.client_to_server.Handshake.Authenticate',
'9': 0,
'10': 'authenticate'
},
{
'1': 'requestPOW',
'3': 5,
'4': 1,
'5': 11,
'6': '.client_to_server.Handshake.RequestPOW',
'9': 0,
'10': 'requestPOW'
},
],
'3': [
Handshake_RequestPOW$json,
Handshake_Register$json,
Handshake_GetAuthChallenge$json,
Handshake_GetAuthToken$json,
Handshake_Authenticate$json
],
'3': [Handshake_RequestPOW$json, Handshake_Register$json, Handshake_GetAuthChallenge$json, Handshake_GetAuthToken$json, Handshake_Authenticate$json],
'8': [
{'1': 'Handshake'},
],
@ -77,10 +156,30 @@ const Handshake_Register$json = {
'1': 'Register',
'2': [
{'1': 'username', '3': 1, '4': 1, '5': 9, '10': 'username'},
{'1': 'invite_code', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'inviteCode', '17': true},
{'1': 'public_identity_key', '3': 3, '4': 1, '5': 12, '10': 'publicIdentityKey'},
{
'1': 'invite_code',
'3': 2,
'4': 1,
'5': 9,
'9': 0,
'10': 'inviteCode',
'17': true
},
{
'1': 'public_identity_key',
'3': 3,
'4': 1,
'5': 12,
'10': 'publicIdentityKey'
},
{'1': 'signed_prekey', '3': 4, '4': 1, '5': 12, '10': 'signedPrekey'},
{'1': 'signed_prekey_signature', '3': 5, '4': 1, '5': 12, '10': 'signedPrekeySignature'},
{
'1': 'signed_prekey_signature',
'3': 5,
'4': 1,
'5': 12,
'10': 'signedPrekeySignature'
},
{'1': 'signed_prekey_id', '3': 6, '4': 1, '5': 3, '10': 'signedPrekeyId'},
{'1': 'registration_id', '3': 7, '4': 1, '5': 3, '10': 'registrationId'},
{'1': 'is_ios', '3': 8, '4': 1, '5': 8, '10': 'isIos'},
@ -112,8 +211,24 @@ const Handshake_Authenticate$json = {
'2': [
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'},
{'1': 'auth_token', '3': 2, '4': 1, '5': 12, '10': 'authToken'},
{'1': 'app_version', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'appVersion', '17': true},
{'1': 'device_id', '3': 4, '4': 1, '5': 3, '9': 1, '10': 'deviceId', '17': true},
{
'1': 'app_version',
'3': 3,
'4': 1,
'5': 9,
'9': 0,
'10': 'appVersion',
'17': true
},
{
'1': 'device_id',
'3': 4,
'4': 1,
'5': 3,
'9': 1,
'10': 'deviceId',
'17': true
},
],
'8': [
{'1': '_app_version'},
@ -148,30 +263,229 @@ final $typed_data.Uint8List handshakeDescriptor = $convert.base64Decode(
const ApplicationData$json = {
'1': 'ApplicationData',
'2': [
{'1': 'textMessage', '3': 1, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.TextMessage', '9': 0, '10': 'textMessage'},
{'1': 'getUserByUsername', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUserByUsername', '9': 0, '10': 'getUserByUsername'},
{'1': 'getPrekeysByUserId', '3': 3, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetPrekeysByUserId', '9': 0, '10': 'getPrekeysByUserId'},
{'1': 'getUserById', '3': 6, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUserById', '9': 0, '10': 'getUserById'},
{'1': 'updateGoogleFcmToken', '3': 8, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UpdateGoogleFcmToken', '9': 0, '10': 'updateGoogleFcmToken'},
{'1': 'getLocation', '3': 9, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetLocation', '9': 0, '10': 'getLocation'},
{'1': 'getCurrentPlanInfos', '3': 10, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetCurrentPlanInfos', '9': 0, '10': 'getCurrentPlanInfos'},
{'1': 'redeemVoucher', '3': 11, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.RedeemVoucher', '9': 0, '10': 'redeemVoucher'},
{'1': 'getAvailablePlans', '3': 12, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetAvailablePlans', '9': 0, '10': 'getAvailablePlans'},
{'1': 'createVoucher', '3': 13, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.CreateVoucher', '9': 0, '10': 'createVoucher'},
{'1': 'getVouchers', '3': 14, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetVouchers', '9': 0, '10': 'getVouchers'},
{'1': 'switchtoPayedPlan', '3': 15, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.SwitchToPayedPlan', '9': 0, '10': 'switchtoPayedPlan'},
{'1': 'getAddaccountsInvites', '3': 16, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetAddAccountsInvites', '9': 0, '10': 'getAddaccountsInvites'},
{'1': 'redeemAdditionalCode', '3': 17, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.RedeemAdditionalCode', '9': 0, '10': 'redeemAdditionalCode'},
{'1': 'removeAdditionalUser', '3': 18, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.RemoveAdditionalUser', '9': 0, '10': 'removeAdditionalUser'},
{'1': 'updatePlanOptions', '3': 19, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UpdatePlanOptions', '9': 0, '10': 'updatePlanOptions'},
{'1': 'downloadDone', '3': 20, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.DownloadDone', '9': 0, '10': 'downloadDone'},
{'1': 'getSignedPrekeyByUserid', '3': 22, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetSignedPreKeyByUserId', '9': 0, '10': 'getSignedPrekeyByUserid'},
{'1': 'updateSignedPrekey', '3': 23, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UpdateSignedPreKey', '9': 0, '10': 'updateSignedPrekey'},
{'1': 'deleteAccount', '3': 24, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.DeleteAccount', '9': 0, '10': 'deleteAccount'},
{'1': 'reportUser', '3': 25, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.ReportUser', '9': 0, '10': 'reportUser'},
{'1': 'changeUsername', '3': 26, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.ChangeUsername', '9': 0, '10': 'changeUsername'},
{
'1': 'textMessage',
'3': 1,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.TextMessage',
'9': 0,
'10': 'textMessage'
},
{
'1': 'getUserByUsername',
'3': 2,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetUserByUsername',
'9': 0,
'10': 'getUserByUsername'
},
{
'1': 'getPrekeysByUserId',
'3': 3,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetPrekeysByUserId',
'9': 0,
'10': 'getPrekeysByUserId'
},
{
'1': 'getUserById',
'3': 6,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetUserById',
'9': 0,
'10': 'getUserById'
},
{
'1': 'updateGoogleFcmToken',
'3': 8,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.UpdateGoogleFcmToken',
'9': 0,
'10': 'updateGoogleFcmToken'
},
{
'1': 'getLocation',
'3': 9,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetLocation',
'9': 0,
'10': 'getLocation'
},
{
'1': 'getCurrentPlanInfos',
'3': 10,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetCurrentPlanInfos',
'9': 0,
'10': 'getCurrentPlanInfos'
},
{
'1': 'redeemVoucher',
'3': 11,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.RedeemVoucher',
'9': 0,
'10': 'redeemVoucher'
},
{
'1': 'getAvailablePlans',
'3': 12,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetAvailablePlans',
'9': 0,
'10': 'getAvailablePlans'
},
{
'1': 'createVoucher',
'3': 13,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.CreateVoucher',
'9': 0,
'10': 'createVoucher'
},
{
'1': 'getVouchers',
'3': 14,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetVouchers',
'9': 0,
'10': 'getVouchers'
},
{
'1': 'switchtoPayedPlan',
'3': 15,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.SwitchToPayedPlan',
'9': 0,
'10': 'switchtoPayedPlan'
},
{
'1': 'getAddaccountsInvites',
'3': 16,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetAddAccountsInvites',
'9': 0,
'10': 'getAddaccountsInvites'
},
{
'1': 'redeemAdditionalCode',
'3': 17,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.RedeemAdditionalCode',
'9': 0,
'10': 'redeemAdditionalCode'
},
{
'1': 'removeAdditionalUser',
'3': 18,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.RemoveAdditionalUser',
'9': 0,
'10': 'removeAdditionalUser'
},
{
'1': 'updatePlanOptions',
'3': 19,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.UpdatePlanOptions',
'9': 0,
'10': 'updatePlanOptions'
},
{
'1': 'downloadDone',
'3': 20,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.DownloadDone',
'9': 0,
'10': 'downloadDone'
},
{
'1': 'getSignedPrekeyByUserid',
'3': 22,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.GetSignedPreKeyByUserId',
'9': 0,
'10': 'getSignedPrekeyByUserid'
},
{
'1': 'updateSignedPrekey',
'3': 23,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.UpdateSignedPreKey',
'9': 0,
'10': 'updateSignedPrekey'
},
{
'1': 'deleteAccount',
'3': 24,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.DeleteAccount',
'9': 0,
'10': 'deleteAccount'
},
{
'1': 'reportUser',
'3': 25,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.ReportUser',
'9': 0,
'10': 'reportUser'
},
{
'1': 'changeUsername',
'3': 26,
'4': 1,
'5': 11,
'6': '.client_to_server.ApplicationData.ChangeUsername',
'9': 0,
'10': 'changeUsername'
},
],
'3': [
ApplicationData_TextMessage$json,
ApplicationData_GetUserByUsername$json,
ApplicationData_ChangeUsername$json,
ApplicationData_UpdateGoogleFcmToken$json,
ApplicationData_GetUserById$json,
ApplicationData_RedeemVoucher$json,
ApplicationData_SwitchToPayedPlan$json,
ApplicationData_UpdatePlanOptions$json,
ApplicationData_CreateVoucher$json,
ApplicationData_GetLocation$json,
ApplicationData_GetVouchers$json,
ApplicationData_GetAvailablePlans$json,
ApplicationData_GetAddAccountsInvites$json,
ApplicationData_GetCurrentPlanInfos$json,
ApplicationData_RedeemAdditionalCode$json,
ApplicationData_RemoveAdditionalUser$json,
ApplicationData_GetPrekeysByUserId$json,
ApplicationData_GetSignedPreKeyByUserId$json,
ApplicationData_UpdateSignedPreKey$json,
ApplicationData_DownloadDone$json,
ApplicationData_ReportUser$json,
ApplicationData_DeleteAccount$json
],
'3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_ChangeUsername$json, ApplicationData_UpdateGoogleFcmToken$json, ApplicationData_GetUserById$json, ApplicationData_RedeemVoucher$json, ApplicationData_SwitchToPayedPlan$json, ApplicationData_UpdatePlanOptions$json, ApplicationData_CreateVoucher$json, ApplicationData_GetLocation$json, ApplicationData_GetVouchers$json, ApplicationData_GetAvailablePlans$json, ApplicationData_GetAddAccountsInvites$json, ApplicationData_GetCurrentPlanInfos$json, ApplicationData_RedeemAdditionalCode$json, ApplicationData_RemoveAdditionalUser$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetSignedPreKeyByUserId$json, ApplicationData_UpdateSignedPreKey$json, ApplicationData_DownloadDone$json, ApplicationData_ReportUser$json, ApplicationData_DeleteAccount$json],
'8': [
{'1': 'ApplicationData'},
],
@ -183,7 +497,15 @@ const ApplicationData_TextMessage$json = {
'2': [
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'},
{'1': 'body', '3': 3, '4': 1, '5': 12, '10': 'body'},
{'1': 'push_data', '3': 4, '4': 1, '5': 12, '9': 0, '10': 'pushData', '17': true},
{
'1': 'push_data',
'3': 4,
'4': 1,
'5': 12,
'9': 0,
'10': 'pushData',
'17': true
},
],
'8': [
{'1': '_push_data'},
@ -319,7 +641,13 @@ const ApplicationData_UpdateSignedPreKey$json = {
'2': [
{'1': 'signed_prekey_id', '3': 1, '4': 1, '5': 3, '10': 'signedPrekeyId'},
{'1': 'signed_prekey', '3': 2, '4': 1, '5': 12, '10': 'signedPrekey'},
{'1': 'signed_prekey_signature', '3': 3, '4': 1, '5': 12, '10': 'signedPrekeySignature'},
{
'1': 'signed_prekey_signature',
'3': 3,
'4': 1,
'5': 12,
'10': 'signedPrekeySignature'
},
],
};
@ -413,8 +741,24 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
const Response$json = {
'1': 'Response',
'2': [
{'1': 'ok', '3': 1, '4': 1, '5': 11, '6': '.client_to_server.Response.Ok', '9': 0, '10': 'ok'},
{'1': 'error', '3': 2, '4': 1, '5': 14, '6': '.error.ErrorCode', '9': 0, '10': 'error'},
{
'1': 'ok',
'3': 1,
'4': 1,
'5': 11,
'6': '.client_to_server.Response.Ok',
'9': 0,
'10': 'ok'
},
{
'1': 'error',
'3': 2,
'4': 1,
'5': 14,
'6': '.error.ErrorCode',
'9': 0,
'10': 'error'
},
],
'3': [Response_PreKey$json, Response_Prekeys$json, Response_Ok$json],
'8': [
@ -435,7 +779,14 @@ const Response_PreKey$json = {
const Response_Prekeys$json = {
'1': 'Prekeys',
'2': [
{'1': 'prekeys', '3': 1, '4': 3, '5': 11, '6': '.client_to_server.Response.PreKey', '10': 'prekeys'},
{
'1': 'prekeys',
'3': 1,
'4': 3,
'5': 11,
'6': '.client_to_server.Response.PreKey',
'10': 'prekeys'
},
],
};
@ -444,7 +795,15 @@ const Response_Ok$json = {
'1': 'Ok',
'2': [
{'1': 'None', '3': 1, '4': 1, '5': 8, '9': 0, '10': 'None'},
{'1': 'prekeys', '3': 2, '4': 1, '5': 11, '6': '.client_to_server.Response.Prekeys', '9': 0, '10': 'prekeys'},
{
'1': 'prekeys',
'3': 2,
'4': 1,
'5': 11,
'6': '.client_to_server.Response.Prekeys',
'9': 0,
'10': 'prekeys'
},
],
'8': [
{'1': 'Ok'},
@ -459,4 +818,3 @@ final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
'ByZWtleXMYASADKAsyIS5jbGllbnRfdG9fc2VydmVyLlJlc3BvbnNlLlByZUtleVIHcHJla2V5'
'cxpgCgJPaxIUCgROb25lGAEgASgISABSBE5vbmUSPgoHcHJla2V5cxgCIAEoCzIiLmNsaWVudF'
'90b19zZXJ2ZXIuUmVzcG9uc2UuUHJla2V5c0gAUgdwcmVrZXlzQgQKAk9rQgoKCFJlc3BvbnNl');

View file

@ -1,15 +1,17 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/websocket/error.proto
//
// @dart = 2.12
// Generated from api/websocket/error.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
export 'error.pbenum.dart';
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
export 'error.pbenum.dart';

View file

@ -1,55 +1,92 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/websocket/error.proto
//
// @dart = 2.12
// Generated from api/websocket/error.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class ErrorCode extends $pb.ProtobufEnum {
static const ErrorCode Unknown = ErrorCode._(0, _omitEnumNames ? '' : 'Unknown');
static const ErrorCode BadRequest = ErrorCode._(400, _omitEnumNames ? '' : 'BadRequest');
static const ErrorCode TooManyRequests = ErrorCode._(429, _omitEnumNames ? '' : 'TooManyRequests');
static const ErrorCode InternalError = ErrorCode._(500, _omitEnumNames ? '' : 'InternalError');
static const ErrorCode InvalidInvitationCode = ErrorCode._(1002, _omitEnumNames ? '' : 'InvalidInvitationCode');
static const ErrorCode UsernameAlreadyTaken = ErrorCode._(1003, _omitEnumNames ? '' : 'UsernameAlreadyTaken');
static const ErrorCode SignatureNotValid = ErrorCode._(1004, _omitEnumNames ? '' : 'SignatureNotValid');
static const ErrorCode UsernameNotFound = ErrorCode._(1005, _omitEnumNames ? '' : 'UsernameNotFound');
static const ErrorCode UsernameNotValid = ErrorCode._(1006, _omitEnumNames ? '' : 'UsernameNotValid');
static const ErrorCode InvalidPublicKey = ErrorCode._(1007, _omitEnumNames ? '' : 'InvalidPublicKey');
static const ErrorCode SessionAlreadyAuthenticated = ErrorCode._(1008, _omitEnumNames ? '' : 'SessionAlreadyAuthenticated');
static const ErrorCode SessionNotAuthenticated = ErrorCode._(1009, _omitEnumNames ? '' : 'SessionNotAuthenticated');
static const ErrorCode OnlyOneSessionAllowed = ErrorCode._(1010, _omitEnumNames ? '' : 'OnlyOneSessionAllowed');
static const ErrorCode UploadLimitReached = ErrorCode._(1011, _omitEnumNames ? '' : 'UploadLimitReached');
static const ErrorCode InvalidUpdateToken = ErrorCode._(1012, _omitEnumNames ? '' : 'InvalidUpdateToken');
static const ErrorCode InvalidOffset = ErrorCode._(1013, _omitEnumNames ? '' : 'InvalidOffset');
static const ErrorCode InvalidGoogleFcmToken = ErrorCode._(1014, _omitEnumNames ? '' : 'InvalidGoogleFcmToken');
static const ErrorCode UploadTokenIsBlocked = ErrorCode._(1015, _omitEnumNames ? '' : 'UploadTokenIsBlocked');
static const ErrorCode UploadChecksumInvalid = ErrorCode._(1016, _omitEnumNames ? '' : 'UploadChecksumInvalid');
static const ErrorCode InvalidDownloadToken = ErrorCode._(1017, _omitEnumNames ? '' : 'InvalidDownloadToken');
static const ErrorCode ApiEndpointNotFound = ErrorCode._(1018, _omitEnumNames ? '' : 'ApiEndpointNotFound');
static const ErrorCode AuthTokenNotValid = ErrorCode._(1019, _omitEnumNames ? '' : 'AuthTokenNotValid');
static const ErrorCode InvalidPreKeys = ErrorCode._(1020, _omitEnumNames ? '' : 'InvalidPreKeys');
static const ErrorCode VoucherInValid = ErrorCode._(1021, _omitEnumNames ? '' : 'VoucherInValid');
static const ErrorCode PlanNotAllowed = ErrorCode._(1022, _omitEnumNames ? '' : 'PlanNotAllowed');
static const ErrorCode PlanLimitReached = ErrorCode._(1023, _omitEnumNames ? '' : 'PlanLimitReached');
static const ErrorCode NotEnoughCredit = ErrorCode._(1024, _omitEnumNames ? '' : 'NotEnoughCredit');
static const ErrorCode PlanDowngrade = ErrorCode._(1025, _omitEnumNames ? '' : 'PlanDowngrade');
static const ErrorCode PlanUpgradeNotYearly = ErrorCode._(1026, _omitEnumNames ? '' : 'PlanUpgradeNotYearly');
static const ErrorCode InvalidSignedPreKey = ErrorCode._(1027, _omitEnumNames ? '' : 'InvalidSignedPreKey');
static const ErrorCode UserIdNotFound = ErrorCode._(1028, _omitEnumNames ? '' : 'UserIdNotFound');
static const ErrorCode UserIdAlreadyTaken = ErrorCode._(1029, _omitEnumNames ? '' : 'UserIdAlreadyTaken');
static const ErrorCode AppVersionOutdated = ErrorCode._(1030, _omitEnumNames ? '' : 'AppVersionOutdated');
static const ErrorCode NewDeviceRegistered = ErrorCode._(1031, _omitEnumNames ? '' : 'NewDeviceRegistered');
static const ErrorCode InvalidProofOfWork = ErrorCode._(1032, _omitEnumNames ? '' : 'InvalidProofOfWork');
static const ErrorCode RegistrationDisabled = ErrorCode._(1033, _omitEnumNames ? '' : 'RegistrationDisabled');
static const ErrorCode Unknown =
ErrorCode._(0, _omitEnumNames ? '' : 'Unknown');
static const ErrorCode BadRequest =
ErrorCode._(400, _omitEnumNames ? '' : 'BadRequest');
static const ErrorCode TooManyRequests =
ErrorCode._(429, _omitEnumNames ? '' : 'TooManyRequests');
static const ErrorCode InternalError =
ErrorCode._(500, _omitEnumNames ? '' : 'InternalError');
static const ErrorCode InvalidInvitationCode =
ErrorCode._(1002, _omitEnumNames ? '' : 'InvalidInvitationCode');
static const ErrorCode UsernameAlreadyTaken =
ErrorCode._(1003, _omitEnumNames ? '' : 'UsernameAlreadyTaken');
static const ErrorCode SignatureNotValid =
ErrorCode._(1004, _omitEnumNames ? '' : 'SignatureNotValid');
static const ErrorCode UsernameNotFound =
ErrorCode._(1005, _omitEnumNames ? '' : 'UsernameNotFound');
static const ErrorCode UsernameNotValid =
ErrorCode._(1006, _omitEnumNames ? '' : 'UsernameNotValid');
static const ErrorCode InvalidPublicKey =
ErrorCode._(1007, _omitEnumNames ? '' : 'InvalidPublicKey');
static const ErrorCode SessionAlreadyAuthenticated =
ErrorCode._(1008, _omitEnumNames ? '' : 'SessionAlreadyAuthenticated');
static const ErrorCode SessionNotAuthenticated =
ErrorCode._(1009, _omitEnumNames ? '' : 'SessionNotAuthenticated');
static const ErrorCode OnlyOneSessionAllowed =
ErrorCode._(1010, _omitEnumNames ? '' : 'OnlyOneSessionAllowed');
static const ErrorCode UploadLimitReached =
ErrorCode._(1011, _omitEnumNames ? '' : 'UploadLimitReached');
static const ErrorCode InvalidUpdateToken =
ErrorCode._(1012, _omitEnumNames ? '' : 'InvalidUpdateToken');
static const ErrorCode InvalidOffset =
ErrorCode._(1013, _omitEnumNames ? '' : 'InvalidOffset');
static const ErrorCode InvalidGoogleFcmToken =
ErrorCode._(1014, _omitEnumNames ? '' : 'InvalidGoogleFcmToken');
static const ErrorCode UploadTokenIsBlocked =
ErrorCode._(1015, _omitEnumNames ? '' : 'UploadTokenIsBlocked');
static const ErrorCode UploadChecksumInvalid =
ErrorCode._(1016, _omitEnumNames ? '' : 'UploadChecksumInvalid');
static const ErrorCode InvalidDownloadToken =
ErrorCode._(1017, _omitEnumNames ? '' : 'InvalidDownloadToken');
static const ErrorCode ApiEndpointNotFound =
ErrorCode._(1018, _omitEnumNames ? '' : 'ApiEndpointNotFound');
static const ErrorCode AuthTokenNotValid =
ErrorCode._(1019, _omitEnumNames ? '' : 'AuthTokenNotValid');
static const ErrorCode InvalidPreKeys =
ErrorCode._(1020, _omitEnumNames ? '' : 'InvalidPreKeys');
static const ErrorCode VoucherInValid =
ErrorCode._(1021, _omitEnumNames ? '' : 'VoucherInValid');
static const ErrorCode PlanNotAllowed =
ErrorCode._(1022, _omitEnumNames ? '' : 'PlanNotAllowed');
static const ErrorCode PlanLimitReached =
ErrorCode._(1023, _omitEnumNames ? '' : 'PlanLimitReached');
static const ErrorCode NotEnoughCredit =
ErrorCode._(1024, _omitEnumNames ? '' : 'NotEnoughCredit');
static const ErrorCode PlanDowngrade =
ErrorCode._(1025, _omitEnumNames ? '' : 'PlanDowngrade');
static const ErrorCode PlanUpgradeNotYearly =
ErrorCode._(1026, _omitEnumNames ? '' : 'PlanUpgradeNotYearly');
static const ErrorCode InvalidSignedPreKey =
ErrorCode._(1027, _omitEnumNames ? '' : 'InvalidSignedPreKey');
static const ErrorCode UserIdNotFound =
ErrorCode._(1028, _omitEnumNames ? '' : 'UserIdNotFound');
static const ErrorCode UserIdAlreadyTaken =
ErrorCode._(1029, _omitEnumNames ? '' : 'UserIdAlreadyTaken');
static const ErrorCode AppVersionOutdated =
ErrorCode._(1030, _omitEnumNames ? '' : 'AppVersionOutdated');
static const ErrorCode NewDeviceRegistered =
ErrorCode._(1031, _omitEnumNames ? '' : 'NewDeviceRegistered');
static const ErrorCode InvalidProofOfWork =
ErrorCode._(1032, _omitEnumNames ? '' : 'InvalidProofOfWork');
static const ErrorCode RegistrationDisabled =
ErrorCode._(1033, _omitEnumNames ? '' : 'RegistrationDisabled');
static const $core.List<ErrorCode> values = <ErrorCode>[
Unknown,
@ -90,11 +127,12 @@ class ErrorCode extends $pb.ProtobufEnum {
RegistrationDisabled,
];
static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);
static final $core.Map<$core.int, ErrorCode> _byValue =
$pb.ProtobufEnum.initByValue(values);
static ErrorCode? valueOf($core.int value) => _byValue[value];
const ErrorCode._($core.int v, $core.String n) : super(v, n);
const ErrorCode._(super.value, super.name);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/websocket/error.proto
//
// @dart = 2.12
// Generated from api/websocket/error.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -74,4 +75,3 @@ final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode(
'duZWRQcmVLZXkQgwgSEwoOVXNlcklkTm90Rm91bmQQhAgSFwoSVXNlcklkQWxyZWFkeVRha2Vu'
'EIUIEhcKEkFwcFZlcnNpb25PdXRkYXRlZBCGCBIYChNOZXdEZXZpY2VSZWdpc3RlcmVkEIcIEh'
'cKEkludmFsaWRQcm9vZk9mV29yaxCICBIZChRSZWdpc3RyYXRpb25EaXNhYmxlZBCJCA==');

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,39 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/websocket/server_to_client.proto
//
// @dart = 2.12
// Generated from api/websocket/server_to_client.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class Response_TransactionTypes extends $pb.ProtobufEnum {
static const Response_TransactionTypes Refund = Response_TransactionTypes._(0, _omitEnumNames ? '' : 'Refund');
static const Response_TransactionTypes VoucherRedeemed = Response_TransactionTypes._(1, _omitEnumNames ? '' : 'VoucherRedeemed');
static const Response_TransactionTypes VoucherCreated = Response_TransactionTypes._(2, _omitEnumNames ? '' : 'VoucherCreated');
static const Response_TransactionTypes Cash = Response_TransactionTypes._(3, _omitEnumNames ? '' : 'Cash');
static const Response_TransactionTypes PlanUpgrade = Response_TransactionTypes._(4, _omitEnumNames ? '' : 'PlanUpgrade');
static const Response_TransactionTypes Unknown = Response_TransactionTypes._(5, _omitEnumNames ? '' : 'Unknown');
static const Response_TransactionTypes ThanksForTesting = Response_TransactionTypes._(6, _omitEnumNames ? '' : 'ThanksForTesting');
static const Response_TransactionTypes AutoRenewal = Response_TransactionTypes._(7, _omitEnumNames ? '' : 'AutoRenewal');
static const Response_TransactionTypes Refund =
Response_TransactionTypes._(0, _omitEnumNames ? '' : 'Refund');
static const Response_TransactionTypes VoucherRedeemed =
Response_TransactionTypes._(1, _omitEnumNames ? '' : 'VoucherRedeemed');
static const Response_TransactionTypes VoucherCreated =
Response_TransactionTypes._(2, _omitEnumNames ? '' : 'VoucherCreated');
static const Response_TransactionTypes Cash =
Response_TransactionTypes._(3, _omitEnumNames ? '' : 'Cash');
static const Response_TransactionTypes PlanUpgrade =
Response_TransactionTypes._(4, _omitEnumNames ? '' : 'PlanUpgrade');
static const Response_TransactionTypes Unknown =
Response_TransactionTypes._(5, _omitEnumNames ? '' : 'Unknown');
static const Response_TransactionTypes ThanksForTesting =
Response_TransactionTypes._(6, _omitEnumNames ? '' : 'ThanksForTesting');
static const Response_TransactionTypes AutoRenewal =
Response_TransactionTypes._(7, _omitEnumNames ? '' : 'AutoRenewal');
static const $core.List<Response_TransactionTypes> values = <Response_TransactionTypes> [
static const $core.List<Response_TransactionTypes> values =
<Response_TransactionTypes>[
Refund,
VoucherRedeemed,
VoucherCreated,
@ -34,11 +44,13 @@ class Response_TransactionTypes extends $pb.ProtobufEnum {
AutoRenewal,
];
static final $core.Map<$core.int, Response_TransactionTypes> _byValue = $pb.ProtobufEnum.initByValue(values);
static Response_TransactionTypes? valueOf($core.int value) => _byValue[value];
static final $core.List<Response_TransactionTypes?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 7);
static Response_TransactionTypes? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const Response_TransactionTypes._($core.int v, $core.String n) : super(v, n);
const Response_TransactionTypes._(super.value, super.name);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: api/websocket/server_to_client.proto
//
// @dart = 2.12
// Generated from api/websocket/server_to_client.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -17,7 +18,15 @@ import 'dart:typed_data' as $typed_data;
const ServerToClient$json = {
'1': 'ServerToClient',
'2': [
{'1': 'V0', '3': 1, '4': 1, '5': 11, '6': '.server_to_client.V0', '9': 0, '10': 'V0'},
{
'1': 'V0',
'3': 1,
'4': 1,
'5': 11,
'6': '.server_to_client.V0',
'9': 0,
'10': 'V0'
},
],
'8': [
{'1': 'v'},
@ -34,10 +43,41 @@ const V0$json = {
'1': 'V0',
'2': [
{'1': 'seq', '3': 1, '4': 1, '5': 4, '10': 'seq'},
{'1': 'response', '3': 2, '4': 1, '5': 11, '6': '.server_to_client.Response', '9': 0, '10': 'response'},
{'1': 'newMessage', '3': 3, '4': 1, '5': 11, '6': '.server_to_client.NewMessage', '9': 0, '10': 'newMessage'},
{'1': 'RequestNewPreKeys', '3': 4, '4': 1, '5': 8, '9': 0, '10': 'RequestNewPreKeys'},
{'1': 'error', '3': 6, '4': 1, '5': 14, '6': '.error.ErrorCode', '9': 0, '10': 'error'},
{
'1': 'response',
'3': 2,
'4': 1,
'5': 11,
'6': '.server_to_client.Response',
'9': 0,
'10': 'response'
},
{
'1': 'newMessage',
'3': 3,
'4': 1,
'5': 11,
'6': '.server_to_client.NewMessage',
'9': 0,
'10': 'newMessage'
},
{
'1': 'RequestNewPreKeys',
'3': 4,
'4': 1,
'5': 8,
'9': 0,
'10': 'RequestNewPreKeys'
},
{
'1': 'error',
'3': 6,
'4': 1,
'5': 14,
'6': '.error.ErrorCode',
'9': 0,
'10': 'error'
},
],
'8': [
{'1': 'Kind'},
@ -70,10 +110,45 @@ final $typed_data.Uint8List newMessageDescriptor = $convert.base64Decode(
const Response$json = {
'1': 'Response',
'2': [
{'1': 'ok', '3': 1, '4': 1, '5': 11, '6': '.server_to_client.Response.Ok', '9': 0, '10': 'ok'},
{'1': 'error', '3': 2, '4': 1, '5': 14, '6': '.error.ErrorCode', '9': 0, '10': 'error'},
{
'1': 'ok',
'3': 1,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.Ok',
'9': 0,
'10': 'ok'
},
{
'1': 'error',
'3': 2,
'4': 1,
'5': 14,
'6': '.error.ErrorCode',
'9': 0,
'10': 'error'
},
],
'3': [
Response_Authenticated$json,
Response_Plan$json,
Response_Plans$json,
Response_AddAccountsInvite$json,
Response_AddAccountsInvites$json,
Response_Transaction$json,
Response_AdditionalAccount$json,
Response_Voucher$json,
Response_Vouchers$json,
Response_PlanBallance$json,
Response_Location$json,
Response_PreKey$json,
Response_SignedPreKey$json,
Response_UserData$json,
Response_UploadToken$json,
Response_DownloadTokens$json,
Response_ProofOfWork$json,
Response_Ok$json
],
'3': [Response_Authenticated$json, Response_Plan$json, Response_Plans$json, Response_AddAccountsInvite$json, Response_AddAccountsInvites$json, Response_Transaction$json, Response_AdditionalAccount$json, Response_Voucher$json, Response_Vouchers$json, Response_PlanBallance$json, Response_Location$json, Response_PreKey$json, Response_SignedPreKey$json, Response_UserData$json, Response_UploadToken$json, Response_DownloadTokens$json, Response_ProofOfWork$json, Response_Ok$json],
'4': [Response_TransactionTypes$json],
'8': [
{'1': 'Response'},
@ -94,14 +169,56 @@ const Response_Plan$json = {
'2': [
{'1': 'plan_id', '3': 1, '4': 1, '5': 9, '10': 'planId'},
{'1': 'upload_size_limit', '3': 2, '4': 1, '5': 3, '10': 'uploadSizeLimit'},
{'1': 'daily_media_upload_limit', '3': 3, '4': 1, '5': 3, '10': 'dailyMediaUploadLimit'},
{'1': 'maximal_upload_size_of_single_media_size', '3': 4, '4': 1, '5': 3, '10': 'maximalUploadSizeOfSingleMediaSize'},
{'1': 'additional_plus_accounts', '3': 5, '4': 1, '5': 3, '10': 'additionalPlusAccounts'},
{'1': 'additional_free_accounts', '3': 6, '4': 1, '5': 3, '10': 'additionalFreeAccounts'},
{'1': 'monthly_costs_cent', '3': 7, '4': 1, '5': 3, '10': 'monthlyCostsCent'},
{
'1': 'daily_media_upload_limit',
'3': 3,
'4': 1,
'5': 3,
'10': 'dailyMediaUploadLimit'
},
{
'1': 'maximal_upload_size_of_single_media_size',
'3': 4,
'4': 1,
'5': 3,
'10': 'maximalUploadSizeOfSingleMediaSize'
},
{
'1': 'additional_plus_accounts',
'3': 5,
'4': 1,
'5': 3,
'10': 'additionalPlusAccounts'
},
{
'1': 'additional_free_accounts',
'3': 6,
'4': 1,
'5': 3,
'10': 'additionalFreeAccounts'
},
{
'1': 'monthly_costs_cent',
'3': 7,
'4': 1,
'5': 3,
'10': 'monthlyCostsCent'
},
{'1': 'yearly_costs_cent', '3': 8, '4': 1, '5': 3, '10': 'yearlyCostsCent'},
{'1': 'allowed_to_send_text_messages', '3': 9, '4': 1, '5': 8, '10': 'allowedToSendTextMessages'},
{'1': 'is_additional_account', '3': 10, '4': 1, '5': 8, '10': 'isAdditionalAccount'},
{
'1': 'allowed_to_send_text_messages',
'3': 9,
'4': 1,
'5': 8,
'10': 'allowedToSendTextMessages'
},
{
'1': 'is_additional_account',
'3': 10,
'4': 1,
'5': 8,
'10': 'isAdditionalAccount'
},
],
};
@ -109,7 +226,14 @@ const Response_Plan$json = {
const Response_Plans$json = {
'1': 'Plans',
'2': [
{'1': 'plans', '3': 1, '4': 3, '5': 11, '6': '.server_to_client.Response.Plan', '10': 'plans'},
{
'1': 'plans',
'3': 1,
'4': 3,
'5': 11,
'6': '.server_to_client.Response.Plan',
'10': 'plans'
},
],
};
@ -126,7 +250,14 @@ const Response_AddAccountsInvite$json = {
const Response_AddAccountsInvites$json = {
'1': 'AddAccountsInvites',
'2': [
{'1': 'invites', '3': 1, '4': 3, '5': 11, '6': '.server_to_client.Response.AddAccountsInvite', '10': 'invites'},
{
'1': 'invites',
'3': 1,
'4': 3,
'5': 11,
'6': '.server_to_client.Response.AddAccountsInvite',
'10': 'invites'
},
],
};
@ -135,8 +266,21 @@ const Response_Transaction$json = {
'1': 'Transaction',
'2': [
{'1': 'deposit_cents', '3': 1, '4': 1, '5': 3, '10': 'depositCents'},
{'1': 'transaction_type', '3': 2, '4': 1, '5': 14, '6': '.server_to_client.Response.TransactionTypes', '10': 'transactionType'},
{'1': 'created_at_unix_timestamp', '3': 3, '4': 1, '5': 3, '10': 'createdAtUnixTimestamp'},
{
'1': 'transaction_type',
'3': 2,
'4': 1,
'5': 14,
'6': '.server_to_client.Response.TransactionTypes',
'10': 'transactionType'
},
{
'1': 'created_at_unix_timestamp',
'3': 3,
'4': 1,
'5': 3,
'10': 'createdAtUnixTimestamp'
},
],
};
@ -157,7 +301,13 @@ const Response_Voucher$json = {
{'1': 'value_cents', '3': 2, '4': 1, '5': 3, '10': 'valueCents'},
{'1': 'redeemed', '3': 3, '4': 1, '5': 8, '10': 'redeemed'},
{'1': 'requested', '3': 4, '4': 1, '5': 8, '10': 'requested'},
{'1': 'created_at_unix_timestamp', '3': 5, '4': 1, '5': 3, '10': 'createdAtUnixTimestamp'},
{
'1': 'created_at_unix_timestamp',
'3': 5,
'4': 1,
'5': 3,
'10': 'createdAtUnixTimestamp'
},
],
};
@ -165,7 +315,14 @@ const Response_Voucher$json = {
const Response_Vouchers$json = {
'1': 'Vouchers',
'2': [
{'1': 'vouchers', '3': 1, '4': 3, '5': 11, '6': '.server_to_client.Response.Voucher', '10': 'vouchers'},
{
'1': 'vouchers',
'3': 1,
'4': 3,
'5': 11,
'6': '.server_to_client.Response.Voucher',
'10': 'vouchers'
},
],
};
@ -173,14 +330,72 @@ const Response_Vouchers$json = {
const Response_PlanBallance$json = {
'1': 'PlanBallance',
'2': [
{'1': 'used_daily_media_upload_limit', '3': 1, '4': 1, '5': 3, '10': 'usedDailyMediaUploadLimit'},
{'1': 'used_upload_media_size_limit', '3': 2, '4': 1, '5': 3, '10': 'usedUploadMediaSizeLimit'},
{'1': 'payment_period_days', '3': 3, '4': 1, '5': 3, '9': 0, '10': 'paymentPeriodDays', '17': true},
{'1': 'last_payment_done_unix_timestamp', '3': 4, '4': 1, '5': 3, '9': 1, '10': 'lastPaymentDoneUnixTimestamp', '17': true},
{'1': 'transactions', '3': 5, '4': 3, '5': 11, '6': '.server_to_client.Response.Transaction', '10': 'transactions'},
{'1': 'additional_accounts', '3': 6, '4': 3, '5': 11, '6': '.server_to_client.Response.AdditionalAccount', '10': 'additionalAccounts'},
{'1': 'auto_renewal', '3': 7, '4': 1, '5': 8, '9': 2, '10': 'autoRenewal', '17': true},
{'1': 'additional_account_owner_id', '3': 8, '4': 1, '5': 3, '9': 3, '10': 'additionalAccountOwnerId', '17': true},
{
'1': 'used_daily_media_upload_limit',
'3': 1,
'4': 1,
'5': 3,
'10': 'usedDailyMediaUploadLimit'
},
{
'1': 'used_upload_media_size_limit',
'3': 2,
'4': 1,
'5': 3,
'10': 'usedUploadMediaSizeLimit'
},
{
'1': 'payment_period_days',
'3': 3,
'4': 1,
'5': 3,
'9': 0,
'10': 'paymentPeriodDays',
'17': true
},
{
'1': 'last_payment_done_unix_timestamp',
'3': 4,
'4': 1,
'5': 3,
'9': 1,
'10': 'lastPaymentDoneUnixTimestamp',
'17': true
},
{
'1': 'transactions',
'3': 5,
'4': 3,
'5': 11,
'6': '.server_to_client.Response.Transaction',
'10': 'transactions'
},
{
'1': 'additional_accounts',
'3': 6,
'4': 3,
'5': 11,
'6': '.server_to_client.Response.AdditionalAccount',
'10': 'additionalAccounts'
},
{
'1': 'auto_renewal',
'3': 7,
'4': 1,
'5': 8,
'9': 2,
'10': 'autoRenewal',
'17': true
},
{
'1': 'additional_account_owner_id',
'3': 8,
'4': 1,
'5': 3,
'9': 3,
'10': 'additionalAccountOwnerId',
'17': true
},
],
'8': [
{'1': '_payment_period_days'},
@ -215,7 +430,13 @@ const Response_SignedPreKey$json = {
'2': [
{'1': 'signed_prekey_id', '3': 1, '4': 1, '5': 3, '10': 'signedPrekeyId'},
{'1': 'signed_prekey', '3': 2, '4': 1, '5': 12, '10': 'signedPrekey'},
{'1': 'signed_prekey_signature', '3': 3, '4': 1, '5': 12, '10': 'signedPrekeySignature'},
{
'1': 'signed_prekey_signature',
'3': 3,
'4': 1,
'5': 12,
'10': 'signedPrekeySignature'
},
],
};
@ -224,12 +445,68 @@ const Response_UserData$json = {
'1': 'UserData',
'2': [
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'},
{'1': 'prekeys', '3': 2, '4': 3, '5': 11, '6': '.server_to_client.Response.PreKey', '10': 'prekeys'},
{'1': 'username', '3': 7, '4': 1, '5': 12, '9': 0, '10': 'username', '17': true},
{'1': 'public_identity_key', '3': 3, '4': 1, '5': 12, '9': 1, '10': 'publicIdentityKey', '17': true},
{'1': 'signed_prekey', '3': 4, '4': 1, '5': 12, '9': 2, '10': 'signedPrekey', '17': true},
{'1': 'signed_prekey_signature', '3': 5, '4': 1, '5': 12, '9': 3, '10': 'signedPrekeySignature', '17': true},
{'1': 'signed_prekey_id', '3': 6, '4': 1, '5': 3, '9': 4, '10': 'signedPrekeyId', '17': true},
{
'1': 'prekeys',
'3': 2,
'4': 3,
'5': 11,
'6': '.server_to_client.Response.PreKey',
'10': 'prekeys'
},
{
'1': 'username',
'3': 7,
'4': 1,
'5': 12,
'9': 0,
'10': 'username',
'17': true
},
{
'1': 'public_identity_key',
'3': 3,
'4': 1,
'5': 12,
'9': 1,
'10': 'publicIdentityKey',
'17': true
},
{
'1': 'signed_prekey',
'3': 4,
'4': 1,
'5': 12,
'9': 2,
'10': 'signedPrekey',
'17': true
},
{
'1': 'signed_prekey_signature',
'3': 5,
'4': 1,
'5': 12,
'9': 3,
'10': 'signedPrekeySignature',
'17': true
},
{
'1': 'signed_prekey_id',
'3': 6,
'4': 1,
'5': 3,
'9': 4,
'10': 'signedPrekeyId',
'17': true
},
{
'1': 'registration_id',
'3': 8,
'4': 1,
'5': 3,
'9': 5,
'10': 'registrationId',
'17': true
},
],
'8': [
{'1': '_username'},
@ -237,6 +514,7 @@ const Response_UserData$json = {
{'1': '_signed_prekey'},
{'1': '_signed_prekey_signature'},
{'1': '_signed_prekey_id'},
{'1': '_registration_id'},
],
};
@ -272,19 +550,114 @@ const Response_Ok$json = {
'2': [
{'1': 'None', '3': 1, '4': 1, '5': 8, '9': 0, '10': 'None'},
{'1': 'userid', '3': 2, '4': 1, '5': 3, '9': 0, '10': 'userid'},
{'1': 'authchallenge', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'authchallenge'},
{'1': 'uploadtoken', '3': 4, '4': 1, '5': 11, '6': '.server_to_client.Response.UploadToken', '9': 0, '10': 'uploadtoken'},
{'1': 'userdata', '3': 5, '4': 1, '5': 11, '6': '.server_to_client.Response.UserData', '9': 0, '10': 'userdata'},
{
'1': 'authchallenge',
'3': 3,
'4': 1,
'5': 12,
'9': 0,
'10': 'authchallenge'
},
{
'1': 'uploadtoken',
'3': 4,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.UploadToken',
'9': 0,
'10': 'uploadtoken'
},
{
'1': 'userdata',
'3': 5,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.UserData',
'9': 0,
'10': 'userdata'
},
{'1': 'authtoken', '3': 6, '4': 1, '5': 12, '9': 0, '10': 'authtoken'},
{'1': 'location', '3': 7, '4': 1, '5': 11, '6': '.server_to_client.Response.Location', '9': 0, '10': 'location'},
{'1': 'authenticated', '3': 8, '4': 1, '5': 11, '6': '.server_to_client.Response.Authenticated', '9': 0, '10': 'authenticated'},
{'1': 'plans', '3': 9, '4': 1, '5': 11, '6': '.server_to_client.Response.Plans', '9': 0, '10': 'plans'},
{'1': 'planballance', '3': 10, '4': 1, '5': 11, '6': '.server_to_client.Response.PlanBallance', '9': 0, '10': 'planballance'},
{'1': 'vouchers', '3': 11, '4': 1, '5': 11, '6': '.server_to_client.Response.Vouchers', '9': 0, '10': 'vouchers'},
{'1': 'addaccountsinvites', '3': 12, '4': 1, '5': 11, '6': '.server_to_client.Response.AddAccountsInvites', '9': 0, '10': 'addaccountsinvites'},
{'1': 'downloadtokens', '3': 13, '4': 1, '5': 11, '6': '.server_to_client.Response.DownloadTokens', '9': 0, '10': 'downloadtokens'},
{'1': 'signedprekey', '3': 14, '4': 1, '5': 11, '6': '.server_to_client.Response.SignedPreKey', '9': 0, '10': 'signedprekey'},
{'1': 'proofOfWork', '3': 15, '4': 1, '5': 11, '6': '.server_to_client.Response.ProofOfWork', '9': 0, '10': 'proofOfWork'},
{
'1': 'location',
'3': 7,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.Location',
'9': 0,
'10': 'location'
},
{
'1': 'authenticated',
'3': 8,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.Authenticated',
'9': 0,
'10': 'authenticated'
},
{
'1': 'plans',
'3': 9,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.Plans',
'9': 0,
'10': 'plans'
},
{
'1': 'planballance',
'3': 10,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.PlanBallance',
'9': 0,
'10': 'planballance'
},
{
'1': 'vouchers',
'3': 11,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.Vouchers',
'9': 0,
'10': 'vouchers'
},
{
'1': 'addaccountsinvites',
'3': 12,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.AddAccountsInvites',
'9': 0,
'10': 'addaccountsinvites'
},
{
'1': 'downloadtokens',
'3': 13,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.DownloadTokens',
'9': 0,
'10': 'downloadtokens'
},
{
'1': 'signedprekey',
'3': 14,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.SignedPreKey',
'9': 0,
'10': 'signedprekey'
},
{
'1': 'proofOfWork',
'3': 15,
'4': 1,
'5': 11,
'6': '.server_to_client.Response.ProofOfWork',
'9': 0,
'10': 'proofOfWork'
},
],
'8': [
{'1': 'Ok'},
@ -351,37 +724,37 @@ final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
'aWQYASABKANSAmlkEhYKBnByZWtleRgCIAEoDFIGcHJla2V5GpUBCgxTaWduZWRQcmVLZXkSKA'
'oQc2lnbmVkX3ByZWtleV9pZBgBIAEoA1IOc2lnbmVkUHJla2V5SWQSIwoNc2lnbmVkX3ByZWtl'
'eRgCIAEoDFIMc2lnbmVkUHJla2V5EjYKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAMgASgMUh'
'VzaWduZWRQcmVrZXlTaWduYXR1cmUatAMKCFVzZXJEYXRhEhcKB3VzZXJfaWQYASABKANSBnVz'
'VzaWduZWRQcmVrZXlTaWduYXR1cmUa9gMKCFVzZXJEYXRhEhcKB3VzZXJfaWQYASABKANSBnVz'
'ZXJJZBI7CgdwcmVrZXlzGAIgAygLMiEuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QcmVLZX'
'lSB3ByZWtleXMSHwoIdXNlcm5hbWUYByABKAxIAFIIdXNlcm5hbWWIAQESMwoTcHVibGljX2lk'
'ZW50aXR5X2tleRgDIAEoDEgBUhFwdWJsaWNJZGVudGl0eUtleYgBARIoCg1zaWduZWRfcHJla2'
'V5GAQgASgMSAJSDHNpZ25lZFByZWtleYgBARI7ChdzaWduZWRfcHJla2V5X3NpZ25hdHVyZRgF'
'IAEoDEgDUhVzaWduZWRQcmVrZXlTaWduYXR1cmWIAQESLQoQc2lnbmVkX3ByZWtleV9pZBgGIA'
'EoA0gEUg5zaWduZWRQcmVrZXlJZIgBAUILCglfdXNlcm5hbWVCFgoUX3B1YmxpY19pZGVudGl0'
'eV9rZXlCEAoOX3NpZ25lZF9wcmVrZXlCGgoYX3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlQhMKEV'
'9zaWduZWRfcHJla2V5X2lkGlkKC1VwbG9hZFRva2VuEiEKDHVwbG9hZF90b2tlbhgBIAEoDFIL'
'dXBsb2FkVG9rZW4SJwoPZG93bmxvYWRfdG9rZW5zGAIgAygMUg5kb3dubG9hZFRva2Vucxo5Cg'
'5Eb3dubG9hZFRva2VucxInCg9kb3dubG9hZF90b2tlbnMYASADKAxSDmRvd25sb2FkVG9rZW5z'
'GkUKC1Byb29mT2ZXb3JrEhYKBnByZWZpeBgBIAEoCVIGcHJlZml4Eh4KCmRpZmZpY3VsdHkYAi'
'ABKANSCmRpZmZpY3VsdHkawwcKAk9rEhQKBE5vbmUYASABKAhIAFIETm9uZRIYCgZ1c2VyaWQY'
'AiABKANIAFIGdXNlcmlkEiYKDWF1dGhjaGFsbGVuZ2UYAyABKAxIAFINYXV0aGNoYWxsZW5nZR'
'JKCgt1cGxvYWR0b2tlbhgEIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXBsb2Fk'
'VG9rZW5IAFILdXBsb2FkdG9rZW4SQQoIdXNlcmRhdGEYBSABKAsyIy5zZXJ2ZXJfdG9fY2xpZW'
'50LlJlc3BvbnNlLlVzZXJEYXRhSABSCHVzZXJkYXRhEh4KCWF1dGh0b2tlbhgGIAEoDEgAUglh'
'dXRodG9rZW4SQQoIbG9jYXRpb24YByABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLk'
'xvY2F0aW9uSABSCGxvY2F0aW9uElAKDWF1dGhlbnRpY2F0ZWQYCCABKAsyKC5zZXJ2ZXJfdG9f'
'Y2xpZW50LlJlc3BvbnNlLkF1dGhlbnRpY2F0ZWRIAFINYXV0aGVudGljYXRlZBI4CgVwbGFucx'
'gJIAEoCzIgLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuUGxhbnNIAFIFcGxhbnMSTQoMcGxh'
'bmJhbGxhbmNlGAogASgLMicuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QbGFuQmFsbGFuY2'
'VIAFIMcGxhbmJhbGxhbmNlEkEKCHZvdWNoZXJzGAsgASgLMiMuc2VydmVyX3RvX2NsaWVudC5S'
'ZXNwb25zZS5Wb3VjaGVyc0gAUgh2b3VjaGVycxJfChJhZGRhY2NvdW50c2ludml0ZXMYDCABKA'
'syLS5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkFkZEFjY291bnRzSW52aXRlc0gAUhJhZGRh'
'Y2NvdW50c2ludml0ZXMSUwoOZG93bmxvYWR0b2tlbnMYDSABKAsyKS5zZXJ2ZXJfdG9fY2xpZW'
'50LlJlc3BvbnNlLkRvd25sb2FkVG9rZW5zSABSDmRvd25sb2FkdG9rZW5zEk0KDHNpZ25lZHBy'
'ZWtleRgOIAEoCzInLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuU2lnbmVkUHJlS2V5SABSDH'
'NpZ25lZHByZWtleRJKCgtwcm9vZk9mV29yaxgPIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVz'
'cG9uc2UuUHJvb2ZPZldvcmtIAFILcHJvb2ZPZldvcmtCBAoCT2silgEKEFRyYW5zYWN0aW9uVH'
'lwZXMSCgoGUmVmdW5kEAASEwoPVm91Y2hlclJlZGVlbWVkEAESEgoOVm91Y2hlckNyZWF0ZWQQ'
'AhIICgRDYXNoEAMSDwoLUGxhblVwZ3JhZGUQBBILCgdVbmtub3duEAUSFAoQVGhhbmtzRm9yVG'
'VzdGluZxAGEg8KC0F1dG9SZW5ld2FsEAdCCgoIUmVzcG9uc2U=');
'EoA0gEUg5zaWduZWRQcmVrZXlJZIgBARIsCg9yZWdpc3RyYXRpb25faWQYCCABKANIBVIOcmVn'
'aXN0cmF0aW9uSWSIAQFCCwoJX3VzZXJuYW1lQhYKFF9wdWJsaWNfaWRlbnRpdHlfa2V5QhAKDl'
'9zaWduZWRfcHJla2V5QhoKGF9zaWduZWRfcHJla2V5X3NpZ25hdHVyZUITChFfc2lnbmVkX3By'
'ZWtleV9pZEISChBfcmVnaXN0cmF0aW9uX2lkGlkKC1VwbG9hZFRva2VuEiEKDHVwbG9hZF90b2'
'tlbhgBIAEoDFILdXBsb2FkVG9rZW4SJwoPZG93bmxvYWRfdG9rZW5zGAIgAygMUg5kb3dubG9h'
'ZFRva2Vucxo5Cg5Eb3dubG9hZFRva2VucxInCg9kb3dubG9hZF90b2tlbnMYASADKAxSDmRvd2'
'5sb2FkVG9rZW5zGkUKC1Byb29mT2ZXb3JrEhYKBnByZWZpeBgBIAEoCVIGcHJlZml4Eh4KCmRp'
'ZmZpY3VsdHkYAiABKANSCmRpZmZpY3VsdHkawwcKAk9rEhQKBE5vbmUYASABKAhIAFIETm9uZR'
'IYCgZ1c2VyaWQYAiABKANIAFIGdXNlcmlkEiYKDWF1dGhjaGFsbGVuZ2UYAyABKAxIAFINYXV0'
'aGNoYWxsZW5nZRJKCgt1cGxvYWR0b2tlbhgEIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVzcG'
'9uc2UuVXBsb2FkVG9rZW5IAFILdXBsb2FkdG9rZW4SQQoIdXNlcmRhdGEYBSABKAsyIy5zZXJ2'
'ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlVzZXJEYXRhSABSCHVzZXJkYXRhEh4KCWF1dGh0b2tlbh'
'gGIAEoDEgAUglhdXRodG9rZW4SQQoIbG9jYXRpb24YByABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50'
'LlJlc3BvbnNlLkxvY2F0aW9uSABSCGxvY2F0aW9uElAKDWF1dGhlbnRpY2F0ZWQYCCABKAsyKC'
'5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkF1dGhlbnRpY2F0ZWRIAFINYXV0aGVudGljYXRl'
'ZBI4CgVwbGFucxgJIAEoCzIgLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuUGxhbnNIAFIFcG'
'xhbnMSTQoMcGxhbmJhbGxhbmNlGAogASgLMicuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5Q'
'bGFuQmFsbGFuY2VIAFIMcGxhbmJhbGxhbmNlEkEKCHZvdWNoZXJzGAsgASgLMiMuc2VydmVyX3'
'RvX2NsaWVudC5SZXNwb25zZS5Wb3VjaGVyc0gAUgh2b3VjaGVycxJfChJhZGRhY2NvdW50c2lu'
'dml0ZXMYDCABKAsyLS5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkFkZEFjY291bnRzSW52aX'
'Rlc0gAUhJhZGRhY2NvdW50c2ludml0ZXMSUwoOZG93bmxvYWR0b2tlbnMYDSABKAsyKS5zZXJ2'
'ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkRvd25sb2FkVG9rZW5zSABSDmRvd25sb2FkdG9rZW5zEk'
'0KDHNpZ25lZHByZWtleRgOIAEoCzInLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuU2lnbmVk'
'UHJlS2V5SABSDHNpZ25lZHByZWtleRJKCgtwcm9vZk9mV29yaxgPIAEoCzImLnNlcnZlcl90b1'
'9jbGllbnQuUmVzcG9uc2UuUHJvb2ZPZldvcmtIAFILcHJvb2ZPZldvcmtCBAoCT2silgEKEFRy'
'YW5zYWN0aW9uVHlwZXMSCgoGUmVmdW5kEAASEwoPVm91Y2hlclJlZGVlbWVkEAESEgoOVm91Y2'
'hlckNyZWF0ZWQQAhIICgRDYXNoEAMSDwoLUGxhblVwZ3JhZGUQBBILCgdVbmtub3duEAUSFAoQ'
'VGhhbmtzRm9yVGVzdGluZxAGEg8KC0F1dG9SZW5ld2FsEAdCCgoIUmVzcG9uc2U=');

View file

@ -1,80 +1,91 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: backup.proto
//
// @dart = 2.12
// Generated from backup.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
class TwonlySafeBackupContent extends $pb.GeneratedMessage {
factory TwonlySafeBackupContent({
$core.String? secureStorageJson,
$core.List<$core.int>? twonlyDatabase,
}) {
final $result = create();
if (secureStorageJson != null) {
$result.secureStorageJson = secureStorageJson;
final result = create();
if (secureStorageJson != null) result.secureStorageJson = secureStorageJson;
if (twonlyDatabase != null) result.twonlyDatabase = twonlyDatabase;
return result;
}
if (twonlyDatabase != null) {
$result.twonlyDatabase = twonlyDatabase;
}
return $result;
}
TwonlySafeBackupContent._() : super();
factory TwonlySafeBackupContent.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory TwonlySafeBackupContent.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'TwonlySafeBackupContent', createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'secureStorageJson', protoName: 'secureStorageJson')
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'twonlyDatabase', $pb.PbFieldType.OY, protoName: 'twonlyDatabase')
..hasRequiredFields = false
;
TwonlySafeBackupContent._();
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
TwonlySafeBackupContent clone() => TwonlySafeBackupContent()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
TwonlySafeBackupContent copyWith(void Function(TwonlySafeBackupContent) updates) => super.copyWith((message) => updates(message as TwonlySafeBackupContent)) as TwonlySafeBackupContent;
factory TwonlySafeBackupContent.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TwonlySafeBackupContent.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TwonlySafeBackupContent',
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'secureStorageJson',
protoName: 'secureStorageJson')
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'twonlyDatabase', $pb.PbFieldType.OY,
protoName: 'twonlyDatabase')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TwonlySafeBackupContent clone() =>
TwonlySafeBackupContent()..mergeFromMessage(this);
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TwonlySafeBackupContent copyWith(
void Function(TwonlySafeBackupContent) updates) =>
super.copyWith((message) => updates(message as TwonlySafeBackupContent))
as TwonlySafeBackupContent;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TwonlySafeBackupContent create() => TwonlySafeBackupContent._();
@$core.override
TwonlySafeBackupContent createEmptyInstance() => create();
static $pb.PbList<TwonlySafeBackupContent> createRepeated() => $pb.PbList<TwonlySafeBackupContent>();
static $pb.PbList<TwonlySafeBackupContent> createRepeated() =>
$pb.PbList<TwonlySafeBackupContent>();
@$core.pragma('dart2js:noInline')
static TwonlySafeBackupContent getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TwonlySafeBackupContent>(create);
static TwonlySafeBackupContent getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<TwonlySafeBackupContent>(create);
static TwonlySafeBackupContent? _defaultInstance;
@$pb.TagNumber(1)
$core.String get secureStorageJson => $_getSZ(0);
@$pb.TagNumber(1)
set secureStorageJson($core.String v) { $_setString(0, v); }
set secureStorageJson($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasSecureStorageJson() => $_has(0);
@$pb.TagNumber(1)
void clearSecureStorageJson() => clearField(1);
void clearSecureStorageJson() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get twonlyDatabase => $_getN(1);
@$pb.TagNumber(2)
set twonlyDatabase($core.List<$core.int> v) { $_setBytes(1, v); }
set twonlyDatabase($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasTwonlyDatabase() => $_has(1);
@$pb.TagNumber(2)
void clearTwonlyDatabase() => clearField(2);
void clearTwonlyDatabase() => $_clearField(2);
}
class TwonlySafeBackupEncrypted extends $pb.GeneratedMessage {
@ -83,78 +94,86 @@ class TwonlySafeBackupEncrypted extends $pb.GeneratedMessage {
$core.List<$core.int>? nonce,
$core.List<$core.int>? cipherText,
}) {
final $result = create();
if (mac != null) {
$result.mac = mac;
final result = create();
if (mac != null) result.mac = mac;
if (nonce != null) result.nonce = nonce;
if (cipherText != null) result.cipherText = cipherText;
return result;
}
if (nonce != null) {
$result.nonce = nonce;
}
if (cipherText != null) {
$result.cipherText = cipherText;
}
return $result;
}
TwonlySafeBackupEncrypted._() : super();
factory TwonlySafeBackupEncrypted.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory TwonlySafeBackupEncrypted.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'TwonlySafeBackupEncrypted', createEmptyInstance: create)
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'mac', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'cipherText', $pb.PbFieldType.OY, protoName: 'cipherText')
..hasRequiredFields = false
;
TwonlySafeBackupEncrypted._();
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
TwonlySafeBackupEncrypted clone() => TwonlySafeBackupEncrypted()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
TwonlySafeBackupEncrypted copyWith(void Function(TwonlySafeBackupEncrypted) updates) => super.copyWith((message) => updates(message as TwonlySafeBackupEncrypted)) as TwonlySafeBackupEncrypted;
factory TwonlySafeBackupEncrypted.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory TwonlySafeBackupEncrypted.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'TwonlySafeBackupEncrypted',
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'mac', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
3, _omitFieldNames ? '' : 'cipherText', $pb.PbFieldType.OY,
protoName: 'cipherText')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TwonlySafeBackupEncrypted clone() =>
TwonlySafeBackupEncrypted()..mergeFromMessage(this);
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
TwonlySafeBackupEncrypted copyWith(
void Function(TwonlySafeBackupEncrypted) updates) =>
super.copyWith((message) => updates(message as TwonlySafeBackupEncrypted))
as TwonlySafeBackupEncrypted;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static TwonlySafeBackupEncrypted create() => TwonlySafeBackupEncrypted._();
@$core.override
TwonlySafeBackupEncrypted createEmptyInstance() => create();
static $pb.PbList<TwonlySafeBackupEncrypted> createRepeated() => $pb.PbList<TwonlySafeBackupEncrypted>();
static $pb.PbList<TwonlySafeBackupEncrypted> createRepeated() =>
$pb.PbList<TwonlySafeBackupEncrypted>();
@$core.pragma('dart2js:noInline')
static TwonlySafeBackupEncrypted getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TwonlySafeBackupEncrypted>(create);
static TwonlySafeBackupEncrypted getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<TwonlySafeBackupEncrypted>(create);
static TwonlySafeBackupEncrypted? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get mac => $_getN(0);
@$pb.TagNumber(1)
set mac($core.List<$core.int> v) { $_setBytes(0, v); }
set mac($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasMac() => $_has(0);
@$pb.TagNumber(1)
void clearMac() => clearField(1);
void clearMac() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get nonce => $_getN(1);
@$pb.TagNumber(2)
set nonce($core.List<$core.int> v) { $_setBytes(1, v); }
set nonce($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasNonce() => $_has(1);
@$pb.TagNumber(2)
void clearNonce() => clearField(2);
void clearNonce() => $_clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get cipherText => $_getN(2);
@$pb.TagNumber(3)
set cipherText($core.List<$core.int> v) { $_setBytes(2, v); }
set cipherText($core.List<$core.int> value) => $_setBytes(2, value);
@$pb.TagNumber(3)
$core.bool hasCipherText() => $_has(2);
@$pb.TagNumber(3)
void clearCipherText() => clearField(3);
void clearCipherText() => $_clearField(3);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View file

@ -1,11 +1,11 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: backup.proto
//
// @dart = 2.12
// Generated from backup.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: backup.proto
//
// @dart = 2.12
// Generated from backup.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -17,7 +18,13 @@ import 'dart:typed_data' as $typed_data;
const TwonlySafeBackupContent$json = {
'1': 'TwonlySafeBackupContent',
'2': [
{'1': 'secureStorageJson', '3': 1, '4': 1, '5': 9, '10': 'secureStorageJson'},
{
'1': 'secureStorageJson',
'3': 1,
'4': 1,
'5': 9,
'10': 'secureStorageJson'
},
{'1': 'twonlyDatabase', '3': 2, '4': 1, '5': 12, '10': 'twonlyDatabase'},
],
};
@ -38,7 +45,7 @@ const TwonlySafeBackupEncrypted$json = {
};
/// Descriptor for `TwonlySafeBackupEncrypted`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List twonlySafeBackupEncryptedDescriptor = $convert.base64Decode(
final $typed_data.Uint8List twonlySafeBackupEncryptedDescriptor =
$convert.base64Decode(
'ChlUd29ubHlTYWZlQmFja3VwRW5jcnlwdGVkEhAKA21hYxgBIAEoDFIDbWFjEhQKBW5vbmNlGA'
'IgASgMUgVub25jZRIeCgpjaXBoZXJUZXh0GAMgASgMUgpjaXBoZXJUZXh0');

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: groups.proto
//
// @dart = 2.12
// Generated from groups.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
@ -16,6 +17,8 @@ import 'package:protobuf/protobuf.dart' as $pb;
import 'groups.pbenum.dart';
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
export 'groups.pbenum.dart';
/// Stored encrypted on the server in the members columns.
@ -27,140 +30,157 @@ class EncryptedGroupState extends $pb.GeneratedMessage {
$fixnum.Int64? deleteMessagesAfterMilliseconds,
$core.List<$core.int>? padding,
}) {
final $result = create();
if (memberIds != null) {
$result.memberIds.addAll(memberIds);
final result = create();
if (memberIds != null) result.memberIds.addAll(memberIds);
if (adminIds != null) result.adminIds.addAll(adminIds);
if (groupName != null) result.groupName = groupName;
if (deleteMessagesAfterMilliseconds != null)
result.deleteMessagesAfterMilliseconds = deleteMessagesAfterMilliseconds;
if (padding != null) result.padding = padding;
return result;
}
if (adminIds != null) {
$result.adminIds.addAll(adminIds);
}
if (groupName != null) {
$result.groupName = groupName;
}
if (deleteMessagesAfterMilliseconds != null) {
$result.deleteMessagesAfterMilliseconds = deleteMessagesAfterMilliseconds;
}
if (padding != null) {
$result.padding = padding;
}
return $result;
}
EncryptedGroupState._() : super();
factory EncryptedGroupState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory EncryptedGroupState.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EncryptedGroupState', createEmptyInstance: create)
..p<$fixnum.Int64>(1, _omitFieldNames ? '' : 'memberIds', $pb.PbFieldType.K6, protoName: 'memberIds')
..p<$fixnum.Int64>(2, _omitFieldNames ? '' : 'adminIds', $pb.PbFieldType.K6, protoName: 'adminIds')
EncryptedGroupState._();
factory EncryptedGroupState.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EncryptedGroupState.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EncryptedGroupState',
createEmptyInstance: create)
..p<$fixnum.Int64>(
1, _omitFieldNames ? '' : 'memberIds', $pb.PbFieldType.K6,
protoName: 'memberIds')
..p<$fixnum.Int64>(2, _omitFieldNames ? '' : 'adminIds', $pb.PbFieldType.K6,
protoName: 'adminIds')
..aOS(3, _omitFieldNames ? '' : 'groupName', protoName: 'groupName')
..aInt64(4, _omitFieldNames ? '' : 'deleteMessagesAfterMilliseconds', protoName: 'deleteMessagesAfterMilliseconds')
..a<$core.List<$core.int>>(5, _omitFieldNames ? '' : 'padding', $pb.PbFieldType.OY)
..hasRequiredFields = false
;
..aInt64(4, _omitFieldNames ? '' : 'deleteMessagesAfterMilliseconds',
protoName: 'deleteMessagesAfterMilliseconds')
..a<$core.List<$core.int>>(
5, _omitFieldNames ? '' : 'padding', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedGroupState clone() => EncryptedGroupState()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
EncryptedGroupState copyWith(void Function(EncryptedGroupState) updates) => super.copyWith((message) => updates(message as EncryptedGroupState)) as EncryptedGroupState;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedGroupState copyWith(void Function(EncryptedGroupState) updates) =>
super.copyWith((message) => updates(message as EncryptedGroupState))
as EncryptedGroupState;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EncryptedGroupState create() => EncryptedGroupState._();
@$core.override
EncryptedGroupState createEmptyInstance() => create();
static $pb.PbList<EncryptedGroupState> createRepeated() => $pb.PbList<EncryptedGroupState>();
static $pb.PbList<EncryptedGroupState> createRepeated() =>
$pb.PbList<EncryptedGroupState>();
@$core.pragma('dart2js:noInline')
static EncryptedGroupState getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EncryptedGroupState>(create);
static EncryptedGroupState getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EncryptedGroupState>(create);
static EncryptedGroupState? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$fixnum.Int64> get memberIds => $_getList(0);
$pb.PbList<$fixnum.Int64> get memberIds => $_getList(0);
@$pb.TagNumber(2)
$core.List<$fixnum.Int64> get adminIds => $_getList(1);
$pb.PbList<$fixnum.Int64> get adminIds => $_getList(1);
@$pb.TagNumber(3)
$core.String get groupName => $_getSZ(2);
@$pb.TagNumber(3)
set groupName($core.String v) { $_setString(2, v); }
set groupName($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasGroupName() => $_has(2);
@$pb.TagNumber(3)
void clearGroupName() => clearField(3);
void clearGroupName() => $_clearField(3);
@$pb.TagNumber(4)
$fixnum.Int64 get deleteMessagesAfterMilliseconds => $_getI64(3);
@$pb.TagNumber(4)
set deleteMessagesAfterMilliseconds($fixnum.Int64 v) { $_setInt64(3, v); }
set deleteMessagesAfterMilliseconds($fixnum.Int64 value) =>
$_setInt64(3, value);
@$pb.TagNumber(4)
$core.bool hasDeleteMessagesAfterMilliseconds() => $_has(3);
@$pb.TagNumber(4)
void clearDeleteMessagesAfterMilliseconds() => clearField(4);
void clearDeleteMessagesAfterMilliseconds() => $_clearField(4);
@$pb.TagNumber(5)
$core.List<$core.int> get padding => $_getN(4);
@$pb.TagNumber(5)
set padding($core.List<$core.int> v) { $_setBytes(4, v); }
set padding($core.List<$core.int> value) => $_setBytes(4, value);
@$pb.TagNumber(5)
$core.bool hasPadding() => $_has(4);
@$pb.TagNumber(5)
void clearPadding() => clearField(5);
void clearPadding() => $_clearField(5);
}
class EncryptedAppendedGroupState extends $pb.GeneratedMessage {
factory EncryptedAppendedGroupState({
EncryptedAppendedGroupState_Type? type,
}) {
final $result = create();
if (type != null) {
$result.type = type;
final result = create();
if (type != null) result.type = type;
return result;
}
return $result;
}
EncryptedAppendedGroupState._() : super();
factory EncryptedAppendedGroupState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory EncryptedAppendedGroupState.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EncryptedAppendedGroupState', createEmptyInstance: create)
..e<EncryptedAppendedGroupState_Type>(1, _omitFieldNames ? '' : 'type', $pb.PbFieldType.OE, defaultOrMaker: EncryptedAppendedGroupState_Type.LEFT_GROUP, valueOf: EncryptedAppendedGroupState_Type.valueOf, enumValues: EncryptedAppendedGroupState_Type.values)
..hasRequiredFields = false
;
EncryptedAppendedGroupState._();
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
EncryptedAppendedGroupState clone() => EncryptedAppendedGroupState()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
EncryptedAppendedGroupState copyWith(void Function(EncryptedAppendedGroupState) updates) => super.copyWith((message) => updates(message as EncryptedAppendedGroupState)) as EncryptedAppendedGroupState;
factory EncryptedAppendedGroupState.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EncryptedAppendedGroupState.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EncryptedAppendedGroupState',
createEmptyInstance: create)
..e<EncryptedAppendedGroupState_Type>(
1, _omitFieldNames ? '' : 'type', $pb.PbFieldType.OE,
defaultOrMaker: EncryptedAppendedGroupState_Type.LEFT_GROUP,
valueOf: EncryptedAppendedGroupState_Type.valueOf,
enumValues: EncryptedAppendedGroupState_Type.values)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedAppendedGroupState clone() =>
EncryptedAppendedGroupState()..mergeFromMessage(this);
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedAppendedGroupState copyWith(
void Function(EncryptedAppendedGroupState) updates) =>
super.copyWith(
(message) => updates(message as EncryptedAppendedGroupState))
as EncryptedAppendedGroupState;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EncryptedAppendedGroupState create() => EncryptedAppendedGroupState._();
static EncryptedAppendedGroupState create() =>
EncryptedAppendedGroupState._();
@$core.override
EncryptedAppendedGroupState createEmptyInstance() => create();
static $pb.PbList<EncryptedAppendedGroupState> createRepeated() => $pb.PbList<EncryptedAppendedGroupState>();
static $pb.PbList<EncryptedAppendedGroupState> createRepeated() =>
$pb.PbList<EncryptedAppendedGroupState>();
@$core.pragma('dart2js:noInline')
static EncryptedAppendedGroupState getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EncryptedAppendedGroupState>(create);
static EncryptedAppendedGroupState getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EncryptedAppendedGroupState>(create);
static EncryptedAppendedGroupState? _defaultInstance;
@$pb.TagNumber(1)
EncryptedAppendedGroupState_Type get type => $_getN(0);
@$pb.TagNumber(1)
set type(EncryptedAppendedGroupState_Type v) { setField(1, v); }
set type(EncryptedAppendedGroupState_Type value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasType() => $_has(0);
@$pb.TagNumber(1)
void clearType() => clearField(1);
void clearType() => $_clearField(1);
}
class EncryptedGroupStateEnvelop extends $pb.GeneratedMessage {
@ -169,78 +189,88 @@ class EncryptedGroupStateEnvelop extends $pb.GeneratedMessage {
$core.List<$core.int>? encryptedGroupState,
$core.List<$core.int>? mac,
}) {
final $result = create();
if (nonce != null) {
$result.nonce = nonce;
final result = create();
if (nonce != null) result.nonce = nonce;
if (encryptedGroupState != null)
result.encryptedGroupState = encryptedGroupState;
if (mac != null) result.mac = mac;
return result;
}
if (encryptedGroupState != null) {
$result.encryptedGroupState = encryptedGroupState;
}
if (mac != null) {
$result.mac = mac;
}
return $result;
}
EncryptedGroupStateEnvelop._() : super();
factory EncryptedGroupStateEnvelop.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory EncryptedGroupStateEnvelop.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EncryptedGroupStateEnvelop', createEmptyInstance: create)
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'encryptedGroupState', $pb.PbFieldType.OY, protoName: 'encryptedGroupState')
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'mac', $pb.PbFieldType.OY)
..hasRequiredFields = false
;
EncryptedGroupStateEnvelop._();
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
EncryptedGroupStateEnvelop clone() => EncryptedGroupStateEnvelop()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
EncryptedGroupStateEnvelop copyWith(void Function(EncryptedGroupStateEnvelop) updates) => super.copyWith((message) => updates(message as EncryptedGroupStateEnvelop)) as EncryptedGroupStateEnvelop;
factory EncryptedGroupStateEnvelop.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EncryptedGroupStateEnvelop.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EncryptedGroupStateEnvelop',
createEmptyInstance: create)
..a<$core.List<$core.int>>(
1, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'encryptedGroupState', $pb.PbFieldType.OY,
protoName: 'encryptedGroupState')
..a<$core.List<$core.int>>(
3, _omitFieldNames ? '' : 'mac', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedGroupStateEnvelop clone() =>
EncryptedGroupStateEnvelop()..mergeFromMessage(this);
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedGroupStateEnvelop copyWith(
void Function(EncryptedGroupStateEnvelop) updates) =>
super.copyWith(
(message) => updates(message as EncryptedGroupStateEnvelop))
as EncryptedGroupStateEnvelop;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EncryptedGroupStateEnvelop create() => EncryptedGroupStateEnvelop._();
@$core.override
EncryptedGroupStateEnvelop createEmptyInstance() => create();
static $pb.PbList<EncryptedGroupStateEnvelop> createRepeated() => $pb.PbList<EncryptedGroupStateEnvelop>();
static $pb.PbList<EncryptedGroupStateEnvelop> createRepeated() =>
$pb.PbList<EncryptedGroupStateEnvelop>();
@$core.pragma('dart2js:noInline')
static EncryptedGroupStateEnvelop getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EncryptedGroupStateEnvelop>(create);
static EncryptedGroupStateEnvelop getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EncryptedGroupStateEnvelop>(create);
static EncryptedGroupStateEnvelop? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get nonce => $_getN(0);
@$pb.TagNumber(1)
set nonce($core.List<$core.int> v) { $_setBytes(0, v); }
set nonce($core.List<$core.int> value) => $_setBytes(0, value);
@$pb.TagNumber(1)
$core.bool hasNonce() => $_has(0);
@$pb.TagNumber(1)
void clearNonce() => clearField(1);
void clearNonce() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get encryptedGroupState => $_getN(1);
@$pb.TagNumber(2)
set encryptedGroupState($core.List<$core.int> v) { $_setBytes(1, v); }
set encryptedGroupState($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasEncryptedGroupState() => $_has(1);
@$pb.TagNumber(2)
void clearEncryptedGroupState() => clearField(2);
void clearEncryptedGroupState() => $_clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get mac => $_getN(2);
@$pb.TagNumber(3)
set mac($core.List<$core.int> v) { $_setBytes(2, v); }
set mac($core.List<$core.int> value) => $_setBytes(2, value);
@$pb.TagNumber(3)
$core.bool hasMac() => $_has(2);
@$pb.TagNumber(3)
void clearMac() => clearField(3);
void clearMac() => $_clearField(3);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View file

@ -1,30 +1,35 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: groups.proto
//
// @dart = 2.12
// Generated from groups.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class EncryptedAppendedGroupState_Type extends $pb.ProtobufEnum {
static const EncryptedAppendedGroupState_Type LEFT_GROUP = EncryptedAppendedGroupState_Type._(0, _omitEnumNames ? '' : 'LEFT_GROUP');
static const EncryptedAppendedGroupState_Type LEFT_GROUP =
EncryptedAppendedGroupState_Type._(0, _omitEnumNames ? '' : 'LEFT_GROUP');
static const $core.List<EncryptedAppendedGroupState_Type> values = <EncryptedAppendedGroupState_Type> [
static const $core.List<EncryptedAppendedGroupState_Type> values =
<EncryptedAppendedGroupState_Type>[
LEFT_GROUP,
];
static final $core.Map<$core.int, EncryptedAppendedGroupState_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static EncryptedAppendedGroupState_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<EncryptedAppendedGroupState_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 0);
static EncryptedAppendedGroupState_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const EncryptedAppendedGroupState_Type._($core.int v, $core.String n) : super(v, n);
const EncryptedAppendedGroupState_Type._(super.value, super.name);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: groups.proto
//
// @dart = 2.12
// Generated from groups.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -20,7 +21,15 @@ const EncryptedGroupState$json = {
{'1': 'memberIds', '3': 1, '4': 3, '5': 3, '10': 'memberIds'},
{'1': 'adminIds', '3': 2, '4': 3, '5': 3, '10': 'adminIds'},
{'1': 'groupName', '3': 3, '4': 1, '5': 9, '10': 'groupName'},
{'1': 'deleteMessagesAfterMilliseconds', '3': 4, '4': 1, '5': 3, '9': 0, '10': 'deleteMessagesAfterMilliseconds', '17': true},
{
'1': 'deleteMessagesAfterMilliseconds',
'3': 4,
'4': 1,
'5': 3,
'9': 0,
'10': 'deleteMessagesAfterMilliseconds',
'17': true
},
{'1': 'padding', '3': 5, '4': 1, '5': 12, '10': 'padding'},
],
'8': [
@ -40,7 +49,14 @@ final $typed_data.Uint8List encryptedGroupStateDescriptor = $convert.base64Decod
const EncryptedAppendedGroupState$json = {
'1': 'EncryptedAppendedGroupState',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedAppendedGroupState.Type', '10': 'type'},
{
'1': 'type',
'3': 1,
'4': 1,
'5': 14,
'6': '.EncryptedAppendedGroupState.Type',
'10': 'type'
},
],
'4': [EncryptedAppendedGroupState_Type$json],
};
@ -54,7 +70,8 @@ const EncryptedAppendedGroupState_Type$json = {
};
/// Descriptor for `EncryptedAppendedGroupState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List encryptedAppendedGroupStateDescriptor = $convert.base64Decode(
final $typed_data.Uint8List encryptedAppendedGroupStateDescriptor =
$convert.base64Decode(
'ChtFbmNyeXB0ZWRBcHBlbmRlZEdyb3VwU3RhdGUSNQoEdHlwZRgBIAEoDjIhLkVuY3J5cHRlZE'
'FwcGVuZGVkR3JvdXBTdGF0ZS5UeXBlUgR0eXBlIhYKBFR5cGUSDgoKTEVGVF9HUk9VUBAA');
@ -63,14 +80,20 @@ const EncryptedGroupStateEnvelop$json = {
'1': 'EncryptedGroupStateEnvelop',
'2': [
{'1': 'nonce', '3': 1, '4': 1, '5': 12, '10': 'nonce'},
{'1': 'encryptedGroupState', '3': 2, '4': 1, '5': 12, '10': 'encryptedGroupState'},
{
'1': 'encryptedGroupState',
'3': 2,
'4': 1,
'5': 12,
'10': 'encryptedGroupState'
},
{'1': 'mac', '3': 3, '4': 1, '5': 12, '10': 'mac'},
],
};
/// Descriptor for `EncryptedGroupStateEnvelop`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List encryptedGroupStateEnvelopDescriptor = $convert.base64Decode(
final $typed_data.Uint8List encryptedGroupStateEnvelopDescriptor =
$convert.base64Decode(
'ChpFbmNyeXB0ZWRHcm91cFN0YXRlRW52ZWxvcBIUCgVub25jZRgBIAEoDFIFbm9uY2USMAoTZW'
'5jcnlwdGVkR3JvdXBTdGF0ZRgCIAEoDFITZW5jcnlwdGVkR3JvdXBTdGF0ZRIQCgNtYWMYAyAB'
'KAxSA21hYw==');

File diff suppressed because it is too large Load diff

View file

@ -1,24 +1,30 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: messages.proto
//
// @dart = 2.12
// Generated from messages.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class Message_Type extends $pb.ProtobufEnum {
static const Message_Type SENDER_DELIVERY_RECEIPT = Message_Type._(0, _omitEnumNames ? '' : 'SENDER_DELIVERY_RECEIPT');
static const Message_Type PLAINTEXT_CONTENT = Message_Type._(1, _omitEnumNames ? '' : 'PLAINTEXT_CONTENT');
static const Message_Type CIPHERTEXT = Message_Type._(2, _omitEnumNames ? '' : 'CIPHERTEXT');
static const Message_Type PREKEY_BUNDLE = Message_Type._(3, _omitEnumNames ? '' : 'PREKEY_BUNDLE');
static const Message_Type TEST_NOTIFICATION = Message_Type._(4, _omitEnumNames ? '' : 'TEST_NOTIFICATION');
static const Message_Type SENDER_DELIVERY_RECEIPT =
Message_Type._(0, _omitEnumNames ? '' : 'SENDER_DELIVERY_RECEIPT');
static const Message_Type PLAINTEXT_CONTENT =
Message_Type._(1, _omitEnumNames ? '' : 'PLAINTEXT_CONTENT');
static const Message_Type CIPHERTEXT =
Message_Type._(2, _omitEnumNames ? '' : 'CIPHERTEXT');
static const Message_Type PREKEY_BUNDLE =
Message_Type._(3, _omitEnumNames ? '' : 'PREKEY_BUNDLE');
static const Message_Type TEST_NOTIFICATION =
Message_Type._(4, _omitEnumNames ? '' : 'TEST_NOTIFICATION');
static const $core.List<Message_Type> values = <Message_Type>[
SENDER_DELIVERY_RECEIPT,
@ -28,52 +34,75 @@ class Message_Type extends $pb.ProtobufEnum {
TEST_NOTIFICATION,
];
static final $core.Map<$core.int, Message_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static Message_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<Message_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 4);
static Message_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const Message_Type._($core.int v, $core.String n) : super(v, n);
const Message_Type._(super.value, super.name);
}
class PlaintextContent_DecryptionErrorMessage_Type extends $pb.ProtobufEnum {
static const PlaintextContent_DecryptionErrorMessage_Type UNKNOWN = PlaintextContent_DecryptionErrorMessage_Type._(0, _omitEnumNames ? '' : 'UNKNOWN');
static const PlaintextContent_DecryptionErrorMessage_Type PREKEY_UNKNOWN = PlaintextContent_DecryptionErrorMessage_Type._(1, _omitEnumNames ? '' : 'PREKEY_UNKNOWN');
static const PlaintextContent_DecryptionErrorMessage_Type UNKNOWN =
PlaintextContent_DecryptionErrorMessage_Type._(
0, _omitEnumNames ? '' : 'UNKNOWN');
static const PlaintextContent_DecryptionErrorMessage_Type PREKEY_UNKNOWN =
PlaintextContent_DecryptionErrorMessage_Type._(
1, _omitEnumNames ? '' : 'PREKEY_UNKNOWN');
static const $core.List<PlaintextContent_DecryptionErrorMessage_Type> values = <PlaintextContent_DecryptionErrorMessage_Type> [
static const $core.List<PlaintextContent_DecryptionErrorMessage_Type> values =
<PlaintextContent_DecryptionErrorMessage_Type>[
UNKNOWN,
PREKEY_UNKNOWN,
];
static final $core.Map<$core.int, PlaintextContent_DecryptionErrorMessage_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static PlaintextContent_DecryptionErrorMessage_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<PlaintextContent_DecryptionErrorMessage_Type?>
_byValue = $pb.ProtobufEnum.$_initByValueList(values, 1);
static PlaintextContent_DecryptionErrorMessage_Type? valueOf(
$core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const PlaintextContent_DecryptionErrorMessage_Type._($core.int v, $core.String n) : super(v, n);
const PlaintextContent_DecryptionErrorMessage_Type._(super.value, super.name);
}
class EncryptedContent_MessageUpdate_Type extends $pb.ProtobufEnum {
static const EncryptedContent_MessageUpdate_Type DELETE = EncryptedContent_MessageUpdate_Type._(0, _omitEnumNames ? '' : 'DELETE');
static const EncryptedContent_MessageUpdate_Type EDIT_TEXT = EncryptedContent_MessageUpdate_Type._(1, _omitEnumNames ? '' : 'EDIT_TEXT');
static const EncryptedContent_MessageUpdate_Type OPENED = EncryptedContent_MessageUpdate_Type._(2, _omitEnumNames ? '' : 'OPENED');
static const EncryptedContent_MessageUpdate_Type DELETE =
EncryptedContent_MessageUpdate_Type._(0, _omitEnumNames ? '' : 'DELETE');
static const EncryptedContent_MessageUpdate_Type EDIT_TEXT =
EncryptedContent_MessageUpdate_Type._(
1, _omitEnumNames ? '' : 'EDIT_TEXT');
static const EncryptedContent_MessageUpdate_Type OPENED =
EncryptedContent_MessageUpdate_Type._(2, _omitEnumNames ? '' : 'OPENED');
static const $core.List<EncryptedContent_MessageUpdate_Type> values = <EncryptedContent_MessageUpdate_Type> [
static const $core.List<EncryptedContent_MessageUpdate_Type> values =
<EncryptedContent_MessageUpdate_Type>[
DELETE,
EDIT_TEXT,
OPENED,
];
static final $core.Map<$core.int, EncryptedContent_MessageUpdate_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static EncryptedContent_MessageUpdate_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<EncryptedContent_MessageUpdate_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 2);
static EncryptedContent_MessageUpdate_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const EncryptedContent_MessageUpdate_Type._($core.int v, $core.String n) : super(v, n);
const EncryptedContent_MessageUpdate_Type._(super.value, super.name);
}
class EncryptedContent_Media_Type extends $pb.ProtobufEnum {
static const EncryptedContent_Media_Type REUPLOAD = EncryptedContent_Media_Type._(0, _omitEnumNames ? '' : 'REUPLOAD');
static const EncryptedContent_Media_Type IMAGE = EncryptedContent_Media_Type._(1, _omitEnumNames ? '' : 'IMAGE');
static const EncryptedContent_Media_Type VIDEO = EncryptedContent_Media_Type._(2, _omitEnumNames ? '' : 'VIDEO');
static const EncryptedContent_Media_Type GIF = EncryptedContent_Media_Type._(3, _omitEnumNames ? '' : 'GIF');
static const EncryptedContent_Media_Type AUDIO = EncryptedContent_Media_Type._(4, _omitEnumNames ? '' : 'AUDIO');
static const EncryptedContent_Media_Type REUPLOAD =
EncryptedContent_Media_Type._(0, _omitEnumNames ? '' : 'REUPLOAD');
static const EncryptedContent_Media_Type IMAGE =
EncryptedContent_Media_Type._(1, _omitEnumNames ? '' : 'IMAGE');
static const EncryptedContent_Media_Type VIDEO =
EncryptedContent_Media_Type._(2, _omitEnumNames ? '' : 'VIDEO');
static const EncryptedContent_Media_Type GIF =
EncryptedContent_Media_Type._(3, _omitEnumNames ? '' : 'GIF');
static const EncryptedContent_Media_Type AUDIO =
EncryptedContent_Media_Type._(4, _omitEnumNames ? '' : 'AUDIO');
static const $core.List<EncryptedContent_Media_Type> values = <EncryptedContent_Media_Type> [
static const $core.List<EncryptedContent_Media_Type> values =
<EncryptedContent_Media_Type>[
REUPLOAD,
IMAGE,
VIDEO,
@ -81,75 +110,101 @@ class EncryptedContent_Media_Type extends $pb.ProtobufEnum {
AUDIO,
];
static final $core.Map<$core.int, EncryptedContent_Media_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static EncryptedContent_Media_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<EncryptedContent_Media_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 4);
static EncryptedContent_Media_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const EncryptedContent_Media_Type._($core.int v, $core.String n) : super(v, n);
const EncryptedContent_Media_Type._(super.value, super.name);
}
class EncryptedContent_MediaUpdate_Type extends $pb.ProtobufEnum {
static const EncryptedContent_MediaUpdate_Type REOPENED = EncryptedContent_MediaUpdate_Type._(0, _omitEnumNames ? '' : 'REOPENED');
static const EncryptedContent_MediaUpdate_Type STORED = EncryptedContent_MediaUpdate_Type._(1, _omitEnumNames ? '' : 'STORED');
static const EncryptedContent_MediaUpdate_Type DECRYPTION_ERROR = EncryptedContent_MediaUpdate_Type._(2, _omitEnumNames ? '' : 'DECRYPTION_ERROR');
static const EncryptedContent_MediaUpdate_Type REOPENED =
EncryptedContent_MediaUpdate_Type._(0, _omitEnumNames ? '' : 'REOPENED');
static const EncryptedContent_MediaUpdate_Type STORED =
EncryptedContent_MediaUpdate_Type._(1, _omitEnumNames ? '' : 'STORED');
static const EncryptedContent_MediaUpdate_Type DECRYPTION_ERROR =
EncryptedContent_MediaUpdate_Type._(
2, _omitEnumNames ? '' : 'DECRYPTION_ERROR');
static const $core.List<EncryptedContent_MediaUpdate_Type> values = <EncryptedContent_MediaUpdate_Type> [
static const $core.List<EncryptedContent_MediaUpdate_Type> values =
<EncryptedContent_MediaUpdate_Type>[
REOPENED,
STORED,
DECRYPTION_ERROR,
];
static final $core.Map<$core.int, EncryptedContent_MediaUpdate_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static EncryptedContent_MediaUpdate_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<EncryptedContent_MediaUpdate_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 2);
static EncryptedContent_MediaUpdate_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const EncryptedContent_MediaUpdate_Type._($core.int v, $core.String n) : super(v, n);
const EncryptedContent_MediaUpdate_Type._(super.value, super.name);
}
class EncryptedContent_ContactRequest_Type extends $pb.ProtobufEnum {
static const EncryptedContent_ContactRequest_Type REQUEST = EncryptedContent_ContactRequest_Type._(0, _omitEnumNames ? '' : 'REQUEST');
static const EncryptedContent_ContactRequest_Type REJECT = EncryptedContent_ContactRequest_Type._(1, _omitEnumNames ? '' : 'REJECT');
static const EncryptedContent_ContactRequest_Type ACCEPT = EncryptedContent_ContactRequest_Type._(2, _omitEnumNames ? '' : 'ACCEPT');
static const EncryptedContent_ContactRequest_Type REQUEST =
EncryptedContent_ContactRequest_Type._(
0, _omitEnumNames ? '' : 'REQUEST');
static const EncryptedContent_ContactRequest_Type REJECT =
EncryptedContent_ContactRequest_Type._(1, _omitEnumNames ? '' : 'REJECT');
static const EncryptedContent_ContactRequest_Type ACCEPT =
EncryptedContent_ContactRequest_Type._(2, _omitEnumNames ? '' : 'ACCEPT');
static const $core.List<EncryptedContent_ContactRequest_Type> values = <EncryptedContent_ContactRequest_Type> [
static const $core.List<EncryptedContent_ContactRequest_Type> values =
<EncryptedContent_ContactRequest_Type>[
REQUEST,
REJECT,
ACCEPT,
];
static final $core.Map<$core.int, EncryptedContent_ContactRequest_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static EncryptedContent_ContactRequest_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<EncryptedContent_ContactRequest_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 2);
static EncryptedContent_ContactRequest_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const EncryptedContent_ContactRequest_Type._($core.int v, $core.String n) : super(v, n);
const EncryptedContent_ContactRequest_Type._(super.value, super.name);
}
class EncryptedContent_ContactUpdate_Type extends $pb.ProtobufEnum {
static const EncryptedContent_ContactUpdate_Type REQUEST = EncryptedContent_ContactUpdate_Type._(0, _omitEnumNames ? '' : 'REQUEST');
static const EncryptedContent_ContactUpdate_Type UPDATE = EncryptedContent_ContactUpdate_Type._(1, _omitEnumNames ? '' : 'UPDATE');
static const EncryptedContent_ContactUpdate_Type REQUEST =
EncryptedContent_ContactUpdate_Type._(0, _omitEnumNames ? '' : 'REQUEST');
static const EncryptedContent_ContactUpdate_Type UPDATE =
EncryptedContent_ContactUpdate_Type._(1, _omitEnumNames ? '' : 'UPDATE');
static const $core.List<EncryptedContent_ContactUpdate_Type> values = <EncryptedContent_ContactUpdate_Type> [
static const $core.List<EncryptedContent_ContactUpdate_Type> values =
<EncryptedContent_ContactUpdate_Type>[
REQUEST,
UPDATE,
];
static final $core.Map<$core.int, EncryptedContent_ContactUpdate_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static EncryptedContent_ContactUpdate_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<EncryptedContent_ContactUpdate_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 1);
static EncryptedContent_ContactUpdate_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const EncryptedContent_ContactUpdate_Type._($core.int v, $core.String n) : super(v, n);
const EncryptedContent_ContactUpdate_Type._(super.value, super.name);
}
class EncryptedContent_PushKeys_Type extends $pb.ProtobufEnum {
static const EncryptedContent_PushKeys_Type REQUEST = EncryptedContent_PushKeys_Type._(0, _omitEnumNames ? '' : 'REQUEST');
static const EncryptedContent_PushKeys_Type UPDATE = EncryptedContent_PushKeys_Type._(1, _omitEnumNames ? '' : 'UPDATE');
static const EncryptedContent_PushKeys_Type REQUEST =
EncryptedContent_PushKeys_Type._(0, _omitEnumNames ? '' : 'REQUEST');
static const EncryptedContent_PushKeys_Type UPDATE =
EncryptedContent_PushKeys_Type._(1, _omitEnumNames ? '' : 'UPDATE');
static const $core.List<EncryptedContent_PushKeys_Type> values = <EncryptedContent_PushKeys_Type> [
static const $core.List<EncryptedContent_PushKeys_Type> values =
<EncryptedContent_PushKeys_Type>[
REQUEST,
UPDATE,
];
static final $core.Map<$core.int, EncryptedContent_PushKeys_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static EncryptedContent_PushKeys_Type? valueOf($core.int value) => _byValue[value];
static final $core.List<EncryptedContent_PushKeys_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 1);
static EncryptedContent_PushKeys_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const EncryptedContent_PushKeys_Type._($core.int v, $core.String n) : super(v, n);
const EncryptedContent_PushKeys_Type._(super.value, super.name);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: messages.proto
//
// @dart = 2.12
// Generated from messages.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -19,8 +20,25 @@ const Message$json = {
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.Message.Type', '10': 'type'},
{'1': 'receiptId', '3': 2, '4': 1, '5': 9, '10': 'receiptId'},
{'1': 'encryptedContent', '3': 3, '4': 1, '5': 12, '9': 0, '10': 'encryptedContent', '17': true},
{'1': 'plaintextContent', '3': 4, '4': 1, '5': 11, '6': '.PlaintextContent', '9': 1, '10': 'plaintextContent', '17': true},
{
'1': 'encryptedContent',
'3': 3,
'4': 1,
'5': 12,
'9': 0,
'10': 'encryptedContent',
'17': true
},
{
'1': 'plaintextContent',
'3': 4,
'4': 1,
'5': 11,
'6': '.PlaintextContent',
'9': 1,
'10': 'plaintextContent',
'17': true
},
],
'4': [Message_Type$json],
'8': [
@ -55,10 +73,31 @@ final $typed_data.Uint8List messageDescriptor = $convert.base64Decode(
const PlaintextContent$json = {
'1': 'PlaintextContent',
'2': [
{'1': 'decryptionErrorMessage', '3': 1, '4': 1, '5': 11, '6': '.PlaintextContent.DecryptionErrorMessage', '9': 0, '10': 'decryptionErrorMessage', '17': true},
{'1': 'retryControlError', '3': 2, '4': 1, '5': 11, '6': '.PlaintextContent.RetryErrorMessage', '9': 1, '10': 'retryControlError', '17': true},
{
'1': 'decryptionErrorMessage',
'3': 1,
'4': 1,
'5': 11,
'6': '.PlaintextContent.DecryptionErrorMessage',
'9': 0,
'10': 'decryptionErrorMessage',
'17': true
},
{
'1': 'retryControlError',
'3': 2,
'4': 1,
'5': 11,
'6': '.PlaintextContent.RetryErrorMessage',
'9': 1,
'10': 'retryControlError',
'17': true
},
],
'3': [
PlaintextContent_RetryErrorMessage$json,
PlaintextContent_DecryptionErrorMessage$json
],
'3': [PlaintextContent_RetryErrorMessage$json, PlaintextContent_DecryptionErrorMessage$json],
'8': [
{'1': '_decryptionErrorMessage'},
{'1': '_retryControlError'},
@ -74,7 +113,14 @@ const PlaintextContent_RetryErrorMessage$json = {
const PlaintextContent_DecryptionErrorMessage$json = {
'1': 'DecryptionErrorMessage',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.PlaintextContent.DecryptionErrorMessage.Type', '10': 'type'},
{
'1': 'type',
'3': 1,
'4': 1,
'5': 14,
'6': '.PlaintextContent.DecryptionErrorMessage.Type',
'10': 'type'
},
],
'4': [PlaintextContent_DecryptionErrorMessage_Type$json],
};
@ -103,24 +149,179 @@ final $typed_data.Uint8List plaintextContentDescriptor = $convert.base64Decode(
const EncryptedContent$json = {
'1': 'EncryptedContent',
'2': [
{'1': 'groupId', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'groupId', '17': true},
{'1': 'isDirectChat', '3': 3, '4': 1, '5': 8, '9': 1, '10': 'isDirectChat', '17': true},
{'1': 'senderProfileCounter', '3': 4, '4': 1, '5': 3, '9': 2, '10': 'senderProfileCounter', '17': true},
{'1': 'messageUpdate', '3': 5, '4': 1, '5': 11, '6': '.EncryptedContent.MessageUpdate', '9': 3, '10': 'messageUpdate', '17': true},
{'1': 'media', '3': 6, '4': 1, '5': 11, '6': '.EncryptedContent.Media', '9': 4, '10': 'media', '17': true},
{'1': 'mediaUpdate', '3': 7, '4': 1, '5': 11, '6': '.EncryptedContent.MediaUpdate', '9': 5, '10': 'mediaUpdate', '17': true},
{'1': 'contactUpdate', '3': 8, '4': 1, '5': 11, '6': '.EncryptedContent.ContactUpdate', '9': 6, '10': 'contactUpdate', '17': true},
{'1': 'contactRequest', '3': 9, '4': 1, '5': 11, '6': '.EncryptedContent.ContactRequest', '9': 7, '10': 'contactRequest', '17': true},
{'1': 'flameSync', '3': 10, '4': 1, '5': 11, '6': '.EncryptedContent.FlameSync', '9': 8, '10': 'flameSync', '17': true},
{'1': 'pushKeys', '3': 11, '4': 1, '5': 11, '6': '.EncryptedContent.PushKeys', '9': 9, '10': 'pushKeys', '17': true},
{'1': 'reaction', '3': 12, '4': 1, '5': 11, '6': '.EncryptedContent.Reaction', '9': 10, '10': 'reaction', '17': true},
{'1': 'textMessage', '3': 13, '4': 1, '5': 11, '6': '.EncryptedContent.TextMessage', '9': 11, '10': 'textMessage', '17': true},
{'1': 'groupCreate', '3': 14, '4': 1, '5': 11, '6': '.EncryptedContent.GroupCreate', '9': 12, '10': 'groupCreate', '17': true},
{'1': 'groupJoin', '3': 15, '4': 1, '5': 11, '6': '.EncryptedContent.GroupJoin', '9': 13, '10': 'groupJoin', '17': true},
{'1': 'groupUpdate', '3': 16, '4': 1, '5': 11, '6': '.EncryptedContent.GroupUpdate', '9': 14, '10': 'groupUpdate', '17': true},
{'1': 'resendGroupPublicKey', '3': 17, '4': 1, '5': 11, '6': '.EncryptedContent.ResendGroupPublicKey', '9': 15, '10': 'resendGroupPublicKey', '17': true},
{
'1': 'groupId',
'3': 2,
'4': 1,
'5': 9,
'9': 0,
'10': 'groupId',
'17': true
},
{
'1': 'isDirectChat',
'3': 3,
'4': 1,
'5': 8,
'9': 1,
'10': 'isDirectChat',
'17': true
},
{
'1': 'senderProfileCounter',
'3': 4,
'4': 1,
'5': 3,
'9': 2,
'10': 'senderProfileCounter',
'17': true
},
{
'1': 'messageUpdate',
'3': 5,
'4': 1,
'5': 11,
'6': '.EncryptedContent.MessageUpdate',
'9': 3,
'10': 'messageUpdate',
'17': true
},
{
'1': 'media',
'3': 6,
'4': 1,
'5': 11,
'6': '.EncryptedContent.Media',
'9': 4,
'10': 'media',
'17': true
},
{
'1': 'mediaUpdate',
'3': 7,
'4': 1,
'5': 11,
'6': '.EncryptedContent.MediaUpdate',
'9': 5,
'10': 'mediaUpdate',
'17': true
},
{
'1': 'contactUpdate',
'3': 8,
'4': 1,
'5': 11,
'6': '.EncryptedContent.ContactUpdate',
'9': 6,
'10': 'contactUpdate',
'17': true
},
{
'1': 'contactRequest',
'3': 9,
'4': 1,
'5': 11,
'6': '.EncryptedContent.ContactRequest',
'9': 7,
'10': 'contactRequest',
'17': true
},
{
'1': 'flameSync',
'3': 10,
'4': 1,
'5': 11,
'6': '.EncryptedContent.FlameSync',
'9': 8,
'10': 'flameSync',
'17': true
},
{
'1': 'pushKeys',
'3': 11,
'4': 1,
'5': 11,
'6': '.EncryptedContent.PushKeys',
'9': 9,
'10': 'pushKeys',
'17': true
},
{
'1': 'reaction',
'3': 12,
'4': 1,
'5': 11,
'6': '.EncryptedContent.Reaction',
'9': 10,
'10': 'reaction',
'17': true
},
{
'1': 'textMessage',
'3': 13,
'4': 1,
'5': 11,
'6': '.EncryptedContent.TextMessage',
'9': 11,
'10': 'textMessage',
'17': true
},
{
'1': 'groupCreate',
'3': 14,
'4': 1,
'5': 11,
'6': '.EncryptedContent.GroupCreate',
'9': 12,
'10': 'groupCreate',
'17': true
},
{
'1': 'groupJoin',
'3': 15,
'4': 1,
'5': 11,
'6': '.EncryptedContent.GroupJoin',
'9': 13,
'10': 'groupJoin',
'17': true
},
{
'1': 'groupUpdate',
'3': 16,
'4': 1,
'5': 11,
'6': '.EncryptedContent.GroupUpdate',
'9': 14,
'10': 'groupUpdate',
'17': true
},
{
'1': 'resendGroupPublicKey',
'3': 17,
'4': 1,
'5': 11,
'6': '.EncryptedContent.ResendGroupPublicKey',
'9': 15,
'10': 'resendGroupPublicKey',
'17': true
},
],
'3': [
EncryptedContent_GroupCreate$json,
EncryptedContent_GroupJoin$json,
EncryptedContent_ResendGroupPublicKey$json,
EncryptedContent_GroupUpdate$json,
EncryptedContent_TextMessage$json,
EncryptedContent_Reaction$json,
EncryptedContent_MessageUpdate$json,
EncryptedContent_Media$json,
EncryptedContent_MediaUpdate$json,
EncryptedContent_ContactRequest$json,
EncryptedContent_ContactUpdate$json,
EncryptedContent_PushKeys$json,
EncryptedContent_FlameSync$json
],
'3': [EncryptedContent_GroupCreate$json, EncryptedContent_GroupJoin$json, EncryptedContent_ResendGroupPublicKey$json, EncryptedContent_GroupUpdate$json, EncryptedContent_TextMessage$json, EncryptedContent_Reaction$json, EncryptedContent_MessageUpdate$json, EncryptedContent_Media$json, EncryptedContent_MediaUpdate$json, EncryptedContent_ContactRequest$json, EncryptedContent_ContactUpdate$json, EncryptedContent_PushKeys$json, EncryptedContent_FlameSync$json],
'8': [
{'1': '_groupId'},
{'1': '_isDirectChat'},
@ -168,9 +369,33 @@ const EncryptedContent_GroupUpdate$json = {
'1': 'GroupUpdate',
'2': [
{'1': 'groupActionType', '3': 1, '4': 1, '5': 9, '10': 'groupActionType'},
{'1': 'affectedContactId', '3': 2, '4': 1, '5': 3, '9': 0, '10': 'affectedContactId', '17': true},
{'1': 'newGroupName', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'newGroupName', '17': true},
{'1': 'newDeleteMessagesAfterMilliseconds', '3': 4, '4': 1, '5': 3, '9': 2, '10': 'newDeleteMessagesAfterMilliseconds', '17': true},
{
'1': 'affectedContactId',
'3': 2,
'4': 1,
'5': 3,
'9': 0,
'10': 'affectedContactId',
'17': true
},
{
'1': 'newGroupName',
'3': 3,
'4': 1,
'5': 9,
'9': 1,
'10': 'newGroupName',
'17': true
},
{
'1': 'newDeleteMessagesAfterMilliseconds',
'3': 4,
'4': 1,
'5': 3,
'9': 2,
'10': 'newDeleteMessagesAfterMilliseconds',
'17': true
},
],
'8': [
{'1': '_affectedContactId'},
@ -186,7 +411,15 @@ const EncryptedContent_TextMessage$json = {
{'1': 'senderMessageId', '3': 1, '4': 1, '5': 9, '10': 'senderMessageId'},
{'1': 'text', '3': 2, '4': 1, '5': 9, '10': 'text'},
{'1': 'timestamp', '3': 3, '4': 1, '5': 3, '10': 'timestamp'},
{'1': 'quoteMessageId', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'quoteMessageId', '17': true},
{
'1': 'quoteMessageId',
'3': 4,
'4': 1,
'5': 9,
'9': 0,
'10': 'quoteMessageId',
'17': true
},
],
'8': [
{'1': '_quoteMessageId'},
@ -207,9 +440,30 @@ const EncryptedContent_Reaction$json = {
const EncryptedContent_MessageUpdate$json = {
'1': 'MessageUpdate',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.MessageUpdate.Type', '10': 'type'},
{'1': 'senderMessageId', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'senderMessageId', '17': true},
{'1': 'multipleTargetMessageIds', '3': 3, '4': 3, '5': 9, '10': 'multipleTargetMessageIds'},
{
'1': 'type',
'3': 1,
'4': 1,
'5': 14,
'6': '.EncryptedContent.MessageUpdate.Type',
'10': 'type'
},
{
'1': 'senderMessageId',
'3': 2,
'4': 1,
'5': 9,
'9': 0,
'10': 'senderMessageId',
'17': true
},
{
'1': 'multipleTargetMessageIds',
'3': 3,
'4': 3,
'5': 9,
'10': 'multipleTargetMessageIds'
},
{'1': 'text', '3': 4, '4': 1, '5': 9, '9': 1, '10': 'text', '17': true},
{'1': 'timestamp', '3': 5, '4': 1, '5': 3, '10': 'timestamp'},
],
@ -235,15 +489,76 @@ const EncryptedContent_Media$json = {
'1': 'Media',
'2': [
{'1': 'senderMessageId', '3': 1, '4': 1, '5': 9, '10': 'senderMessageId'},
{'1': 'type', '3': 2, '4': 1, '5': 14, '6': '.EncryptedContent.Media.Type', '10': 'type'},
{'1': 'displayLimitInMilliseconds', '3': 3, '4': 1, '5': 3, '9': 0, '10': 'displayLimitInMilliseconds', '17': true},
{'1': 'requiresAuthentication', '3': 4, '4': 1, '5': 8, '10': 'requiresAuthentication'},
{
'1': 'type',
'3': 2,
'4': 1,
'5': 14,
'6': '.EncryptedContent.Media.Type',
'10': 'type'
},
{
'1': 'displayLimitInMilliseconds',
'3': 3,
'4': 1,
'5': 3,
'9': 0,
'10': 'displayLimitInMilliseconds',
'17': true
},
{
'1': 'requiresAuthentication',
'3': 4,
'4': 1,
'5': 8,
'10': 'requiresAuthentication'
},
{'1': 'timestamp', '3': 5, '4': 1, '5': 3, '10': 'timestamp'},
{'1': 'quoteMessageId', '3': 6, '4': 1, '5': 9, '9': 1, '10': 'quoteMessageId', '17': true},
{'1': 'downloadToken', '3': 7, '4': 1, '5': 12, '9': 2, '10': 'downloadToken', '17': true},
{'1': 'encryptionKey', '3': 8, '4': 1, '5': 12, '9': 3, '10': 'encryptionKey', '17': true},
{'1': 'encryptionMac', '3': 9, '4': 1, '5': 12, '9': 4, '10': 'encryptionMac', '17': true},
{'1': 'encryptionNonce', '3': 10, '4': 1, '5': 12, '9': 5, '10': 'encryptionNonce', '17': true},
{
'1': 'quoteMessageId',
'3': 6,
'4': 1,
'5': 9,
'9': 1,
'10': 'quoteMessageId',
'17': true
},
{
'1': 'downloadToken',
'3': 7,
'4': 1,
'5': 12,
'9': 2,
'10': 'downloadToken',
'17': true
},
{
'1': 'encryptionKey',
'3': 8,
'4': 1,
'5': 12,
'9': 3,
'10': 'encryptionKey',
'17': true
},
{
'1': 'encryptionMac',
'3': 9,
'4': 1,
'5': 12,
'9': 4,
'10': 'encryptionMac',
'17': true
},
{
'1': 'encryptionNonce',
'3': 10,
'4': 1,
'5': 12,
'9': 5,
'10': 'encryptionNonce',
'17': true
},
],
'4': [EncryptedContent_Media_Type$json],
'8': [
@ -272,7 +587,14 @@ const EncryptedContent_Media_Type$json = {
const EncryptedContent_MediaUpdate$json = {
'1': 'MediaUpdate',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.MediaUpdate.Type', '10': 'type'},
{
'1': 'type',
'3': 1,
'4': 1,
'5': 14,
'6': '.EncryptedContent.MediaUpdate.Type',
'10': 'type'
},
{'1': 'targetMessageId', '3': 2, '4': 1, '5': 9, '10': 'targetMessageId'},
],
'4': [EncryptedContent_MediaUpdate_Type$json],
@ -292,7 +614,14 @@ const EncryptedContent_MediaUpdate_Type$json = {
const EncryptedContent_ContactRequest$json = {
'1': 'ContactRequest',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.ContactRequest.Type', '10': 'type'},
{
'1': 'type',
'3': 1,
'4': 1,
'5': 14,
'6': '.EncryptedContent.ContactRequest.Type',
'10': 'type'
},
],
'4': [EncryptedContent_ContactRequest_Type$json],
};
@ -311,10 +640,41 @@ const EncryptedContent_ContactRequest_Type$json = {
const EncryptedContent_ContactUpdate$json = {
'1': 'ContactUpdate',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.ContactUpdate.Type', '10': 'type'},
{'1': 'avatarSvgCompressed', '3': 2, '4': 1, '5': 12, '9': 0, '10': 'avatarSvgCompressed', '17': true},
{'1': 'username', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'username', '17': true},
{'1': 'displayName', '3': 4, '4': 1, '5': 9, '9': 2, '10': 'displayName', '17': true},
{
'1': 'type',
'3': 1,
'4': 1,
'5': 14,
'6': '.EncryptedContent.ContactUpdate.Type',
'10': 'type'
},
{
'1': 'avatarSvgCompressed',
'3': 2,
'4': 1,
'5': 12,
'9': 0,
'10': 'avatarSvgCompressed',
'17': true
},
{
'1': 'username',
'3': 3,
'4': 1,
'5': 9,
'9': 1,
'10': 'username',
'17': true
},
{
'1': 'displayName',
'3': 4,
'4': 1,
'5': 9,
'9': 2,
'10': 'displayName',
'17': true
},
],
'4': [EncryptedContent_ContactUpdate_Type$json],
'8': [
@ -337,10 +697,25 @@ const EncryptedContent_ContactUpdate_Type$json = {
const EncryptedContent_PushKeys$json = {
'1': 'PushKeys',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.PushKeys.Type', '10': 'type'},
{
'1': 'type',
'3': 1,
'4': 1,
'5': 14,
'6': '.EncryptedContent.PushKeys.Type',
'10': 'type'
},
{'1': 'keyId', '3': 2, '4': 1, '5': 3, '9': 0, '10': 'keyId', '17': true},
{'1': 'key', '3': 3, '4': 1, '5': 12, '9': 1, '10': 'key', '17': true},
{'1': 'createdAt', '3': 4, '4': 1, '5': 3, '9': 2, '10': 'createdAt', '17': true},
{
'1': 'createdAt',
'3': 4,
'4': 1,
'5': 3,
'9': 2,
'10': 'createdAt',
'17': true
},
],
'4': [EncryptedContent_PushKeys_Type$json],
'8': [
@ -364,7 +739,13 @@ const EncryptedContent_FlameSync$json = {
'1': 'FlameSync',
'2': [
{'1': 'flameCounter', '3': 1, '4': 1, '5': 3, '10': 'flameCounter'},
{'1': 'lastFlameCounterChange', '3': 2, '4': 1, '5': 3, '10': 'lastFlameCounterChange'},
{
'1': 'lastFlameCounterChange',
'3': 2,
'4': 1,
'5': 3,
'10': 'lastFlameCounterChange'
},
{'1': 'bestFriend', '3': 3, '4': 1, '5': 8, '10': 'bestFriend'},
{'1': 'forceUpdate', '3': 4, '4': 1, '5': 8, '10': 'forceUpdate'},
],
@ -445,4 +826,3 @@ final $typed_data.Uint8List encryptedContentDescriptor = $convert.base64Decode(
'dEIMCgpfZmxhbWVTeW5jQgsKCV9wdXNoS2V5c0ILCglfcmVhY3Rpb25CDgoMX3RleHRNZXNzYW'
'dlQg4KDF9ncm91cENyZWF0ZUIMCgpfZ3JvdXBKb2luQg4KDF9ncm91cFVwZGF0ZUIXChVfcmVz'
'ZW5kR3JvdXBQdWJsaWNLZXk=');

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: push_notification.proto
//
// @dart = 2.12
// Generated from push_notification.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
@ -16,6 +17,8 @@ import 'package:protobuf/protobuf.dart' as $pb;
import 'push_notification.pbenum.dart';
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
export 'push_notification.pbenum.dart';
class EncryptedPushNotification extends $pb.GeneratedMessage {
@ -25,89 +28,93 @@ class EncryptedPushNotification extends $pb.GeneratedMessage {
$core.List<$core.int>? ciphertext,
$core.List<$core.int>? mac,
}) {
final $result = create();
if (keyId != null) {
$result.keyId = keyId;
final result = create();
if (keyId != null) result.keyId = keyId;
if (nonce != null) result.nonce = nonce;
if (ciphertext != null) result.ciphertext = ciphertext;
if (mac != null) result.mac = mac;
return result;
}
if (nonce != null) {
$result.nonce = nonce;
}
if (ciphertext != null) {
$result.ciphertext = ciphertext;
}
if (mac != null) {
$result.mac = mac;
}
return $result;
}
EncryptedPushNotification._() : super();
factory EncryptedPushNotification.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory EncryptedPushNotification.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'EncryptedPushNotification', createEmptyInstance: create)
EncryptedPushNotification._();
factory EncryptedPushNotification.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory EncryptedPushNotification.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'EncryptedPushNotification',
createEmptyInstance: create)
..aInt64(1, _omitFieldNames ? '' : 'keyId', protoName: 'keyId')
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'ciphertext', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'mac', $pb.PbFieldType.OY)
..hasRequiredFields = false
;
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
3, _omitFieldNames ? '' : 'ciphertext', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
4, _omitFieldNames ? '' : 'mac', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
EncryptedPushNotification clone() => EncryptedPushNotification()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
EncryptedPushNotification copyWith(void Function(EncryptedPushNotification) updates) => super.copyWith((message) => updates(message as EncryptedPushNotification)) as EncryptedPushNotification;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedPushNotification clone() =>
EncryptedPushNotification()..mergeFromMessage(this);
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
EncryptedPushNotification copyWith(
void Function(EncryptedPushNotification) updates) =>
super.copyWith((message) => updates(message as EncryptedPushNotification))
as EncryptedPushNotification;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EncryptedPushNotification create() => EncryptedPushNotification._();
@$core.override
EncryptedPushNotification createEmptyInstance() => create();
static $pb.PbList<EncryptedPushNotification> createRepeated() => $pb.PbList<EncryptedPushNotification>();
static $pb.PbList<EncryptedPushNotification> createRepeated() =>
$pb.PbList<EncryptedPushNotification>();
@$core.pragma('dart2js:noInline')
static EncryptedPushNotification getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EncryptedPushNotification>(create);
static EncryptedPushNotification getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<EncryptedPushNotification>(create);
static EncryptedPushNotification? _defaultInstance;
@$pb.TagNumber(1)
$fixnum.Int64 get keyId => $_getI64(0);
@$pb.TagNumber(1)
set keyId($fixnum.Int64 v) { $_setInt64(0, v); }
set keyId($fixnum.Int64 value) => $_setInt64(0, value);
@$pb.TagNumber(1)
$core.bool hasKeyId() => $_has(0);
@$pb.TagNumber(1)
void clearKeyId() => clearField(1);
void clearKeyId() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get nonce => $_getN(1);
@$pb.TagNumber(2)
set nonce($core.List<$core.int> v) { $_setBytes(1, v); }
set nonce($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasNonce() => $_has(1);
@$pb.TagNumber(2)
void clearNonce() => clearField(2);
void clearNonce() => $_clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get ciphertext => $_getN(2);
@$pb.TagNumber(3)
set ciphertext($core.List<$core.int> v) { $_setBytes(2, v); }
set ciphertext($core.List<$core.int> value) => $_setBytes(2, value);
@$pb.TagNumber(3)
$core.bool hasCiphertext() => $_has(2);
@$pb.TagNumber(3)
void clearCiphertext() => clearField(3);
void clearCiphertext() => $_clearField(3);
@$pb.TagNumber(4)
$core.List<$core.int> get mac => $_getN(3);
@$pb.TagNumber(4)
set mac($core.List<$core.int> v) { $_setBytes(3, v); }
set mac($core.List<$core.int> value) => $_setBytes(3, value);
@$pb.TagNumber(4)
$core.bool hasMac() => $_has(3);
@$pb.TagNumber(4)
void clearMac() => clearField(4);
void clearMac() => $_clearField(4);
}
class PushNotification extends $pb.GeneratedMessage {
@ -116,120 +123,129 @@ class PushNotification extends $pb.GeneratedMessage {
$core.String? messageId,
$core.String? additionalContent,
}) {
final $result = create();
if (kind != null) {
$result.kind = kind;
final result = create();
if (kind != null) result.kind = kind;
if (messageId != null) result.messageId = messageId;
if (additionalContent != null) result.additionalContent = additionalContent;
return result;
}
if (messageId != null) {
$result.messageId = messageId;
}
if (additionalContent != null) {
$result.additionalContent = additionalContent;
}
return $result;
}
PushNotification._() : super();
factory PushNotification.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory PushNotification.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PushNotification', createEmptyInstance: create)
..e<PushKind>(1, _omitFieldNames ? '' : 'kind', $pb.PbFieldType.OE, defaultOrMaker: PushKind.reaction, valueOf: PushKind.valueOf, enumValues: PushKind.values)
PushNotification._();
factory PushNotification.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PushNotification.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PushNotification',
createEmptyInstance: create)
..e<PushKind>(1, _omitFieldNames ? '' : 'kind', $pb.PbFieldType.OE,
defaultOrMaker: PushKind.reaction,
valueOf: PushKind.valueOf,
enumValues: PushKind.values)
..aOS(2, _omitFieldNames ? '' : 'messageId', protoName: 'messageId')
..aOS(3, _omitFieldNames ? '' : 'additionalContent', protoName: 'additionalContent')
..hasRequiredFields = false
;
..aOS(3, _omitFieldNames ? '' : 'additionalContent',
protoName: 'additionalContent')
..hasRequiredFields = false;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushNotification clone() => PushNotification()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
PushNotification copyWith(void Function(PushNotification) updates) => super.copyWith((message) => updates(message as PushNotification)) as PushNotification;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushNotification copyWith(void Function(PushNotification) updates) =>
super.copyWith((message) => updates(message as PushNotification))
as PushNotification;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PushNotification create() => PushNotification._();
@$core.override
PushNotification createEmptyInstance() => create();
static $pb.PbList<PushNotification> createRepeated() => $pb.PbList<PushNotification>();
static $pb.PbList<PushNotification> createRepeated() =>
$pb.PbList<PushNotification>();
@$core.pragma('dart2js:noInline')
static PushNotification getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PushNotification>(create);
static PushNotification getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<PushNotification>(create);
static PushNotification? _defaultInstance;
@$pb.TagNumber(1)
PushKind get kind => $_getN(0);
@$pb.TagNumber(1)
set kind(PushKind v) { setField(1, v); }
set kind(PushKind value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasKind() => $_has(0);
@$pb.TagNumber(1)
void clearKind() => clearField(1);
void clearKind() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get messageId => $_getSZ(1);
@$pb.TagNumber(2)
set messageId($core.String v) { $_setString(1, v); }
set messageId($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasMessageId() => $_has(1);
@$pb.TagNumber(2)
void clearMessageId() => clearField(2);
void clearMessageId() => $_clearField(2);
@$pb.TagNumber(3)
$core.String get additionalContent => $_getSZ(2);
@$pb.TagNumber(3)
set additionalContent($core.String v) { $_setString(2, v); }
set additionalContent($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasAdditionalContent() => $_has(2);
@$pb.TagNumber(3)
void clearAdditionalContent() => clearField(3);
void clearAdditionalContent() => $_clearField(3);
}
class PushUsers extends $pb.GeneratedMessage {
factory PushUsers({
$core.Iterable<PushUser>? users,
}) {
final $result = create();
if (users != null) {
$result.users.addAll(users);
final result = create();
if (users != null) result.users.addAll(users);
return result;
}
return $result;
}
PushUsers._() : super();
factory PushUsers.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory PushUsers.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PushUsers', createEmptyInstance: create)
..pc<PushUser>(1, _omitFieldNames ? '' : 'users', $pb.PbFieldType.PM, subBuilder: PushUser.create)
..hasRequiredFields = false
;
PushUsers._();
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
factory PushUsers.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PushUsers.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PushUsers',
createEmptyInstance: create)
..pc<PushUser>(1, _omitFieldNames ? '' : 'users', $pb.PbFieldType.PM,
subBuilder: PushUser.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushUsers clone() => PushUsers()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
PushUsers copyWith(void Function(PushUsers) updates) => super.copyWith((message) => updates(message as PushUsers)) as PushUsers;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushUsers copyWith(void Function(PushUsers) updates) =>
super.copyWith((message) => updates(message as PushUsers)) as PushUsers;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PushUsers create() => PushUsers._();
@$core.override
PushUsers createEmptyInstance() => create();
static $pb.PbList<PushUsers> createRepeated() => $pb.PbList<PushUsers>();
@$core.pragma('dart2js:noInline')
static PushUsers getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PushUsers>(create);
static PushUsers getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PushUsers>(create);
static PushUsers? _defaultInstance;
@$pb.TagNumber(1)
$core.List<PushUser> get users => $_getList(0);
$pb.PbList<PushUser> get users => $_getList(0);
}
class PushUser extends $pb.GeneratedMessage {
@ -240,96 +256,92 @@ class PushUser extends $pb.GeneratedMessage {
$core.String? lastMessageId,
$core.Iterable<PushKey>? pushKeys,
}) {
final $result = create();
if (userId != null) {
$result.userId = userId;
final result = create();
if (userId != null) result.userId = userId;
if (displayName != null) result.displayName = displayName;
if (blocked != null) result.blocked = blocked;
if (lastMessageId != null) result.lastMessageId = lastMessageId;
if (pushKeys != null) result.pushKeys.addAll(pushKeys);
return result;
}
if (displayName != null) {
$result.displayName = displayName;
}
if (blocked != null) {
$result.blocked = blocked;
}
if (lastMessageId != null) {
$result.lastMessageId = lastMessageId;
}
if (pushKeys != null) {
$result.pushKeys.addAll(pushKeys);
}
return $result;
}
PushUser._() : super();
factory PushUser.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory PushUser.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PushUser', createEmptyInstance: create)
PushUser._();
factory PushUser.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PushUser.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PushUser',
createEmptyInstance: create)
..aInt64(1, _omitFieldNames ? '' : 'userId', protoName: 'userId')
..aOS(2, _omitFieldNames ? '' : 'displayName', protoName: 'displayName')
..aOB(3, _omitFieldNames ? '' : 'blocked')
..aOS(4, _omitFieldNames ? '' : 'lastMessageId', protoName: 'lastMessageId')
..pc<PushKey>(5, _omitFieldNames ? '' : 'pushKeys', $pb.PbFieldType.PM, protoName: 'pushKeys', subBuilder: PushKey.create)
..hasRequiredFields = false
;
..pc<PushKey>(5, _omitFieldNames ? '' : 'pushKeys', $pb.PbFieldType.PM,
protoName: 'pushKeys', subBuilder: PushKey.create)
..hasRequiredFields = false;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushUser clone() => PushUser()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
PushUser copyWith(void Function(PushUser) updates) => super.copyWith((message) => updates(message as PushUser)) as PushUser;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushUser copyWith(void Function(PushUser) updates) =>
super.copyWith((message) => updates(message as PushUser)) as PushUser;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PushUser create() => PushUser._();
@$core.override
PushUser createEmptyInstance() => create();
static $pb.PbList<PushUser> createRepeated() => $pb.PbList<PushUser>();
@$core.pragma('dart2js:noInline')
static PushUser getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PushUser>(create);
static PushUser getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PushUser>(create);
static PushUser? _defaultInstance;
@$pb.TagNumber(1)
$fixnum.Int64 get userId => $_getI64(0);
@$pb.TagNumber(1)
set userId($fixnum.Int64 v) { $_setInt64(0, v); }
set userId($fixnum.Int64 value) => $_setInt64(0, value);
@$pb.TagNumber(1)
$core.bool hasUserId() => $_has(0);
@$pb.TagNumber(1)
void clearUserId() => clearField(1);
void clearUserId() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get displayName => $_getSZ(1);
@$pb.TagNumber(2)
set displayName($core.String v) { $_setString(1, v); }
set displayName($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasDisplayName() => $_has(1);
@$pb.TagNumber(2)
void clearDisplayName() => clearField(2);
void clearDisplayName() => $_clearField(2);
@$pb.TagNumber(3)
$core.bool get blocked => $_getBF(2);
@$pb.TagNumber(3)
set blocked($core.bool v) { $_setBool(2, v); }
set blocked($core.bool value) => $_setBool(2, value);
@$pb.TagNumber(3)
$core.bool hasBlocked() => $_has(2);
@$pb.TagNumber(3)
void clearBlocked() => clearField(3);
void clearBlocked() => $_clearField(3);
@$pb.TagNumber(4)
$core.String get lastMessageId => $_getSZ(3);
@$pb.TagNumber(4)
set lastMessageId($core.String v) { $_setString(3, v); }
set lastMessageId($core.String value) => $_setString(3, value);
@$pb.TagNumber(4)
$core.bool hasLastMessageId() => $_has(3);
@$pb.TagNumber(4)
void clearLastMessageId() => clearField(4);
void clearLastMessageId() => $_clearField(4);
@$pb.TagNumber(5)
$core.List<PushKey> get pushKeys => $_getList(4);
$pb.PbList<PushKey> get pushKeys => $_getList(4);
}
class PushKey extends $pb.GeneratedMessage {
@ -338,78 +350,81 @@ class PushKey extends $pb.GeneratedMessage {
$core.List<$core.int>? key,
$fixnum.Int64? createdAtUnixTimestamp,
}) {
final $result = create();
if (id != null) {
$result.id = id;
final result = create();
if (id != null) result.id = id;
if (key != null) result.key = key;
if (createdAtUnixTimestamp != null)
result.createdAtUnixTimestamp = createdAtUnixTimestamp;
return result;
}
if (key != null) {
$result.key = key;
}
if (createdAtUnixTimestamp != null) {
$result.createdAtUnixTimestamp = createdAtUnixTimestamp;
}
return $result;
}
PushKey._() : super();
factory PushKey.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory PushKey.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PushKey', createEmptyInstance: create)
PushKey._();
factory PushKey.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PushKey.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PushKey',
createEmptyInstance: create)
..aInt64(1, _omitFieldNames ? '' : 'id')
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'key', $pb.PbFieldType.OY)
..aInt64(3, _omitFieldNames ? '' : 'createdAtUnixTimestamp', protoName: 'createdAtUnixTimestamp')
..hasRequiredFields = false
;
..a<$core.List<$core.int>>(
2, _omitFieldNames ? '' : 'key', $pb.PbFieldType.OY)
..aInt64(3, _omitFieldNames ? '' : 'createdAtUnixTimestamp',
protoName: 'createdAtUnixTimestamp')
..hasRequiredFields = false;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushKey clone() => PushKey()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
PushKey copyWith(void Function(PushKey) updates) => super.copyWith((message) => updates(message as PushKey)) as PushKey;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PushKey copyWith(void Function(PushKey) updates) =>
super.copyWith((message) => updates(message as PushKey)) as PushKey;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PushKey create() => PushKey._();
@$core.override
PushKey createEmptyInstance() => create();
static $pb.PbList<PushKey> createRepeated() => $pb.PbList<PushKey>();
@$core.pragma('dart2js:noInline')
static PushKey getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PushKey>(create);
static PushKey getDefault() =>
_defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PushKey>(create);
static PushKey? _defaultInstance;
@$pb.TagNumber(1)
$fixnum.Int64 get id => $_getI64(0);
@$pb.TagNumber(1)
set id($fixnum.Int64 v) { $_setInt64(0, v); }
set id($fixnum.Int64 value) => $_setInt64(0, value);
@$pb.TagNumber(1)
$core.bool hasId() => $_has(0);
@$pb.TagNumber(1)
void clearId() => clearField(1);
void clearId() => $_clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get key => $_getN(1);
@$pb.TagNumber(2)
set key($core.List<$core.int> v) { $_setBytes(1, v); }
set key($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(2)
$core.bool hasKey() => $_has(1);
@$pb.TagNumber(2)
void clearKey() => clearField(2);
void clearKey() => $_clearField(2);
@$pb.TagNumber(3)
$fixnum.Int64 get createdAtUnixTimestamp => $_getI64(2);
@$pb.TagNumber(3)
set createdAtUnixTimestamp($fixnum.Int64 v) { $_setInt64(2, v); }
set createdAtUnixTimestamp($fixnum.Int64 value) => $_setInt64(2, value);
@$pb.TagNumber(3)
$core.bool hasCreatedAtUnixTimestamp() => $_has(2);
@$pb.TagNumber(3)
void clearCreatedAtUnixTimestamp() => clearField(3);
void clearCreatedAtUnixTimestamp() => $_clearField(3);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View file

@ -1,35 +1,48 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: push_notification.proto
//
// @dart = 2.12
// Generated from push_notification.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class PushKind extends $pb.ProtobufEnum {
static const PushKind reaction = PushKind._(0, _omitEnumNames ? '' : 'reaction');
static const PushKind response = PushKind._(1, _omitEnumNames ? '' : 'response');
static const PushKind reaction =
PushKind._(0, _omitEnumNames ? '' : 'reaction');
static const PushKind response =
PushKind._(1, _omitEnumNames ? '' : 'response');
static const PushKind text = PushKind._(2, _omitEnumNames ? '' : 'text');
static const PushKind video = PushKind._(3, _omitEnumNames ? '' : 'video');
static const PushKind twonly = PushKind._(4, _omitEnumNames ? '' : 'twonly');
static const PushKind image = PushKind._(5, _omitEnumNames ? '' : 'image');
static const PushKind contactRequest = PushKind._(6, _omitEnumNames ? '' : 'contactRequest');
static const PushKind acceptRequest = PushKind._(7, _omitEnumNames ? '' : 'acceptRequest');
static const PushKind storedMediaFile = PushKind._(8, _omitEnumNames ? '' : 'storedMediaFile');
static const PushKind testNotification = PushKind._(9, _omitEnumNames ? '' : 'testNotification');
static const PushKind reopenedMedia = PushKind._(10, _omitEnumNames ? '' : 'reopenedMedia');
static const PushKind reactionToVideo = PushKind._(11, _omitEnumNames ? '' : 'reactionToVideo');
static const PushKind reactionToText = PushKind._(12, _omitEnumNames ? '' : 'reactionToText');
static const PushKind reactionToImage = PushKind._(13, _omitEnumNames ? '' : 'reactionToImage');
static const PushKind reactionToAudio = PushKind._(14, _omitEnumNames ? '' : 'reactionToAudio');
static const PushKind addedToGroup = PushKind._(15, _omitEnumNames ? '' : 'addedToGroup');
static const PushKind contactRequest =
PushKind._(6, _omitEnumNames ? '' : 'contactRequest');
static const PushKind acceptRequest =
PushKind._(7, _omitEnumNames ? '' : 'acceptRequest');
static const PushKind storedMediaFile =
PushKind._(8, _omitEnumNames ? '' : 'storedMediaFile');
static const PushKind testNotification =
PushKind._(9, _omitEnumNames ? '' : 'testNotification');
static const PushKind reopenedMedia =
PushKind._(10, _omitEnumNames ? '' : 'reopenedMedia');
static const PushKind reactionToVideo =
PushKind._(11, _omitEnumNames ? '' : 'reactionToVideo');
static const PushKind reactionToText =
PushKind._(12, _omitEnumNames ? '' : 'reactionToText');
static const PushKind reactionToImage =
PushKind._(13, _omitEnumNames ? '' : 'reactionToImage');
static const PushKind reactionToAudio =
PushKind._(14, _omitEnumNames ? '' : 'reactionToAudio');
static const PushKind addedToGroup =
PushKind._(15, _omitEnumNames ? '' : 'addedToGroup');
static const PushKind audio = PushKind._(16, _omitEnumNames ? '' : 'audio');
static const $core.List<PushKind> values = <PushKind>[
@ -52,11 +65,13 @@ class PushKind extends $pb.ProtobufEnum {
audio,
];
static final $core.Map<$core.int, PushKind> _byValue = $pb.ProtobufEnum.initByValue(values);
static PushKind? valueOf($core.int value) => _byValue[value];
static final $core.List<PushKind?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 16);
static PushKind? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const PushKind._($core.int v, $core.String n) : super(v, n);
const PushKind._(super.value, super.name);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -1,13 +1,14 @@
// This is a generated file - do not edit.
//
// Generated code. Do not modify.
// source: push_notification.proto
//
// @dart = 2.12
// Generated from push_notification.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
@ -68,8 +69,24 @@ const PushNotification$json = {
'1': 'PushNotification',
'2': [
{'1': 'kind', '3': 1, '4': 1, '5': 14, '6': '.PushKind', '10': 'kind'},
{'1': 'messageId', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'messageId', '17': true},
{'1': 'additionalContent', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'additionalContent', '17': true},
{
'1': 'messageId',
'3': 2,
'4': 1,
'5': 9,
'9': 0,
'10': 'messageId',
'17': true
},
{
'1': 'additionalContent',
'3': 3,
'4': 1,
'5': 9,
'9': 1,
'10': 'additionalContent',
'17': true
},
],
'8': [
{'1': '_messageId'},
@ -103,8 +120,23 @@ const PushUser$json = {
{'1': 'userId', '3': 1, '4': 1, '5': 3, '10': 'userId'},
{'1': 'displayName', '3': 2, '4': 1, '5': 9, '10': 'displayName'},
{'1': 'blocked', '3': 3, '4': 1, '5': 8, '10': 'blocked'},
{'1': 'lastMessageId', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'lastMessageId', '17': true},
{'1': 'pushKeys', '3': 5, '4': 3, '5': 11, '6': '.PushKey', '10': 'pushKeys'},
{
'1': 'lastMessageId',
'3': 4,
'4': 1,
'5': 9,
'9': 0,
'10': 'lastMessageId',
'17': true
},
{
'1': 'pushKeys',
'3': 5,
'4': 3,
'5': 11,
'6': '.PushKey',
'10': 'pushKeys'
},
],
'8': [
{'1': '_lastMessageId'},
@ -124,7 +156,13 @@ const PushKey$json = {
'2': [
{'1': 'id', '3': 1, '4': 1, '5': 3, '10': 'id'},
{'1': 'key', '3': 2, '4': 1, '5': 12, '10': 'key'},
{'1': 'createdAtUnixTimestamp', '3': 3, '4': 1, '5': 3, '10': 'createdAtUnixTimestamp'},
{
'1': 'createdAtUnixTimestamp',
'3': 3,
'4': 1,
'5': 3,
'10': 'createdAtUnixTimestamp'
},
],
};
@ -132,4 +170,3 @@ const PushKey$json = {
final $typed_data.Uint8List pushKeyDescriptor = $convert.base64Decode(
'CgdQdXNoS2V5Eg4KAmlkGAEgASgDUgJpZBIQCgNrZXkYAiABKAxSA2tleRI2ChZjcmVhdGVkQX'
'RVbml4VGltZXN0YW1wGAMgASgDUhZjcmVhdGVkQXRVbml4VGltZXN0YW1w');

View file

@ -0,0 +1,228 @@
// This is a generated file - do not edit.
//
// Generated from qr.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:protobuf/protobuf.dart' as $pb;
import 'qr.pbenum.dart';
export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions;
export 'qr.pbenum.dart';
class QREnvelope extends $pb.GeneratedMessage {
factory QREnvelope({
QREnvelope_Type? type,
$core.List<$core.int>? data,
}) {
final result = create();
if (type != null) result.type = type;
if (data != null) result.data = data;
return result;
}
QREnvelope._();
factory QREnvelope.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory QREnvelope.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'QREnvelope',
createEmptyInstance: create)
..e<QREnvelope_Type>(2, _omitFieldNames ? '' : 'type', $pb.PbFieldType.OE,
defaultOrMaker: QREnvelope_Type.PublicProfile,
valueOf: QREnvelope_Type.valueOf,
enumValues: QREnvelope_Type.values)
..a<$core.List<$core.int>>(
3, _omitFieldNames ? '' : 'data', $pb.PbFieldType.OY)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
QREnvelope clone() => QREnvelope()..mergeFromMessage(this);
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
QREnvelope copyWith(void Function(QREnvelope) updates) =>
super.copyWith((message) => updates(message as QREnvelope)) as QREnvelope;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static QREnvelope create() => QREnvelope._();
@$core.override
QREnvelope createEmptyInstance() => create();
static $pb.PbList<QREnvelope> createRepeated() => $pb.PbList<QREnvelope>();
@$core.pragma('dart2js:noInline')
static QREnvelope getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<QREnvelope>(create);
static QREnvelope? _defaultInstance;
@$pb.TagNumber(2)
QREnvelope_Type get type => $_getN(0);
@$pb.TagNumber(2)
set type(QREnvelope_Type value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasType() => $_has(0);
@$pb.TagNumber(2)
void clearType() => $_clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get data => $_getN(1);
@$pb.TagNumber(3)
set data($core.List<$core.int> value) => $_setBytes(1, value);
@$pb.TagNumber(3)
$core.bool hasData() => $_has(1);
@$pb.TagNumber(3)
void clearData() => $_clearField(3);
}
class PublicProfile extends $pb.GeneratedMessage {
factory PublicProfile({
$fixnum.Int64? userId,
$core.String? username,
$core.List<$core.int>? publicIdentityKey,
$core.List<$core.int>? signedPrekey,
$fixnum.Int64? registrationId,
$core.List<$core.int>? signedPrekeySignature,
$fixnum.Int64? signedPrekeyId,
}) {
final result = create();
if (userId != null) result.userId = userId;
if (username != null) result.username = username;
if (publicIdentityKey != null) result.publicIdentityKey = publicIdentityKey;
if (signedPrekey != null) result.signedPrekey = signedPrekey;
if (registrationId != null) result.registrationId = registrationId;
if (signedPrekeySignature != null)
result.signedPrekeySignature = signedPrekeySignature;
if (signedPrekeyId != null) result.signedPrekeyId = signedPrekeyId;
return result;
}
PublicProfile._();
factory PublicProfile.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PublicProfile.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PublicProfile',
createEmptyInstance: create)
..aInt64(1, _omitFieldNames ? '' : 'userId')
..aOS(2, _omitFieldNames ? '' : 'username')
..a<$core.List<$core.int>>(
3, _omitFieldNames ? '' : 'publicIdentityKey', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(
4, _omitFieldNames ? '' : 'signedPrekey', $pb.PbFieldType.OY)
..aInt64(5, _omitFieldNames ? '' : 'registrationId')
..a<$core.List<$core.int>>(
6, _omitFieldNames ? '' : 'signedPrekeySignature', $pb.PbFieldType.OY)
..aInt64(7, _omitFieldNames ? '' : 'signedPrekeyId')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PublicProfile clone() => PublicProfile()..mergeFromMessage(this);
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PublicProfile copyWith(void Function(PublicProfile) updates) =>
super.copyWith((message) => updates(message as PublicProfile))
as PublicProfile;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PublicProfile create() => PublicProfile._();
@$core.override
PublicProfile createEmptyInstance() => create();
static $pb.PbList<PublicProfile> createRepeated() =>
$pb.PbList<PublicProfile>();
@$core.pragma('dart2js:noInline')
static PublicProfile getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<PublicProfile>(create);
static PublicProfile? _defaultInstance;
@$pb.TagNumber(1)
$fixnum.Int64 get userId => $_getI64(0);
@$pb.TagNumber(1)
set userId($fixnum.Int64 value) => $_setInt64(0, value);
@$pb.TagNumber(1)
$core.bool hasUserId() => $_has(0);
@$pb.TagNumber(1)
void clearUserId() => $_clearField(1);
@$pb.TagNumber(2)
$core.String get username => $_getSZ(1);
@$pb.TagNumber(2)
set username($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasUsername() => $_has(1);
@$pb.TagNumber(2)
void clearUsername() => $_clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get publicIdentityKey => $_getN(2);
@$pb.TagNumber(3)
set publicIdentityKey($core.List<$core.int> value) => $_setBytes(2, value);
@$pb.TagNumber(3)
$core.bool hasPublicIdentityKey() => $_has(2);
@$pb.TagNumber(3)
void clearPublicIdentityKey() => $_clearField(3);
@$pb.TagNumber(4)
$core.List<$core.int> get signedPrekey => $_getN(3);
@$pb.TagNumber(4)
set signedPrekey($core.List<$core.int> value) => $_setBytes(3, value);
@$pb.TagNumber(4)
$core.bool hasSignedPrekey() => $_has(3);
@$pb.TagNumber(4)
void clearSignedPrekey() => $_clearField(4);
@$pb.TagNumber(5)
$fixnum.Int64 get registrationId => $_getI64(4);
@$pb.TagNumber(5)
set registrationId($fixnum.Int64 value) => $_setInt64(4, value);
@$pb.TagNumber(5)
$core.bool hasRegistrationId() => $_has(4);
@$pb.TagNumber(5)
void clearRegistrationId() => $_clearField(5);
@$pb.TagNumber(6)
$core.List<$core.int> get signedPrekeySignature => $_getN(5);
@$pb.TagNumber(6)
set signedPrekeySignature($core.List<$core.int> value) =>
$_setBytes(5, value);
@$pb.TagNumber(6)
$core.bool hasSignedPrekeySignature() => $_has(5);
@$pb.TagNumber(6)
void clearSignedPrekeySignature() => $_clearField(6);
@$pb.TagNumber(7)
$fixnum.Int64 get signedPrekeyId => $_getI64(6);
@$pb.TagNumber(7)
set signedPrekeyId($fixnum.Int64 value) => $_setInt64(6, value);
@$pb.TagNumber(7)
$core.bool hasSignedPrekeyId() => $_has(6);
@$pb.TagNumber(7)
void clearSignedPrekeyId() => $_clearField(7);
}
const $core.bool _omitFieldNames =
$core.bool.fromEnvironment('protobuf.omit_field_names');
const $core.bool _omitMessageNames =
$core.bool.fromEnvironment('protobuf.omit_message_names');

View file

@ -0,0 +1,34 @@
// This is a generated file - do not edit.
//
// Generated from qr.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class QREnvelope_Type extends $pb.ProtobufEnum {
static const QREnvelope_Type PublicProfile =
QREnvelope_Type._(0, _omitEnumNames ? '' : 'PublicProfile');
static const $core.List<QREnvelope_Type> values = <QREnvelope_Type>[
PublicProfile,
];
static final $core.List<QREnvelope_Type?> _byValue =
$pb.ProtobufEnum.$_initByValueList(values, 0);
static QREnvelope_Type? valueOf($core.int value) =>
value < 0 || value >= _byValue.length ? null : _byValue[value];
const QREnvelope_Type._(super.value, super.name);
}
const $core.bool _omitEnumNames =
$core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -0,0 +1,80 @@
// This is a generated file - do not edit.
//
// Generated from qr.proto.
// @dart = 3.3
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: curly_braces_in_flow_control_structures
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use qREnvelopeDescriptor instead')
const QREnvelope$json = {
'1': 'QREnvelope',
'2': [
{
'1': 'type',
'3': 2,
'4': 1,
'5': 14,
'6': '.QREnvelope.Type',
'10': 'type'
},
{'1': 'data', '3': 3, '4': 1, '5': 12, '10': 'data'},
],
'4': [QREnvelope_Type$json],
};
@$core.Deprecated('Use qREnvelopeDescriptor instead')
const QREnvelope_Type$json = {
'1': 'Type',
'2': [
{'1': 'PublicProfile', '2': 0},
],
};
/// Descriptor for `QREnvelope`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List qREnvelopeDescriptor = $convert.base64Decode(
'CgpRUkVudmVsb3BlEiQKBHR5cGUYAiABKA4yEC5RUkVudmVsb3BlLlR5cGVSBHR5cGUSEgoEZG'
'F0YRgDIAEoDFIEZGF0YSIZCgRUeXBlEhEKDVB1YmxpY1Byb2ZpbGUQAA==');
@$core.Deprecated('Use publicProfileDescriptor instead')
const PublicProfile$json = {
'1': 'PublicProfile',
'2': [
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'},
{'1': 'username', '3': 2, '4': 1, '5': 9, '10': 'username'},
{
'1': 'public_identity_key',
'3': 3,
'4': 1,
'5': 12,
'10': 'publicIdentityKey'
},
{'1': 'signed_prekey', '3': 4, '4': 1, '5': 12, '10': 'signedPrekey'},
{'1': 'registration_id', '3': 5, '4': 1, '5': 3, '10': 'registrationId'},
{
'1': 'signed_prekey_signature',
'3': 6,
'4': 1,
'5': 12,
'10': 'signedPrekeySignature'
},
{'1': 'signed_prekey_id', '3': 7, '4': 1, '5': 3, '10': 'signedPrekeyId'},
],
};
/// Descriptor for `PublicProfile`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List publicProfileDescriptor = $convert.base64Decode(
'Cg1QdWJsaWNQcm9maWxlEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBIaCgh1c2VybmFtZRgCIA'
'EoCVIIdXNlcm5hbWUSLgoTcHVibGljX2lkZW50aXR5X2tleRgDIAEoDFIRcHVibGljSWRlbnRp'
'dHlLZXkSIwoNc2lnbmVkX3ByZWtleRgEIAEoDFIMc2lnbmVkUHJla2V5EicKD3JlZ2lzdHJhdG'
'lvbl9pZBgFIAEoA1IOcmVnaXN0cmF0aW9uSWQSNgoXc2lnbmVkX3ByZWtleV9zaWduYXR1cmUY'
'BiABKAxSFXNpZ25lZFByZWtleVNpZ25hdHVyZRIoChBzaWduZWRfcHJla2V5X2lkGAcgASgDUg'
'5zaWduZWRQcmVrZXlJZA==');

View file

@ -0,0 +1,19 @@
syntax = "proto3";
message QREnvelope {
enum Type {
PublicProfile = 0;
}
Type type = 2;
bytes data = 3;
}
message PublicProfile {
int64 user_id = 1;
string username = 2;
bytes public_identity_key = 3;
bytes signed_prekey = 4;
int64 registration_id = 5;
bytes signed_prekey_signature = 6;
int64 signed_prekey_id = 7;
}

View file

@ -69,6 +69,11 @@ Future<void> compressAndOverlayVideo(MediaFileService media) async {
media.ffmpegOutputPath.deleteSync();
}
if (gUser.disableVideoCompression) {
media.originalPath.copySync(media.tempPath.path);
return;
}
var overLayCommand = '';
if (media.overlayImagePath.existsSync()) {
overLayCommand =

View file

@ -31,6 +31,7 @@ class MediaFileService {
for (final file in files) {
final mediaId = basename(file.path).split('.').first;
// in case the mediaID is unknown the file will be deleted
var delete = true;
final service = await MediaFileService.fromMediaId(mediaId);
@ -46,8 +47,10 @@ class MediaFileService {
// in case messages in empty the file will be deleted, as delete is true by default
for (final message in messages) {
if (message.senderId == null) {
// Media was send by me
if (service.mediaFile.type == MediaType.audio) {
delete = false; // do not delete voice messages
}
if (message.openedAt == null) {
// Message was not yet opened from all persons, so wait...
delete = false;
@ -58,19 +61,18 @@ class MediaFileService {
// this is just to make it easier to understand :)
} else if (message.openedAt!
.isAfter(DateTime.now().subtract(const Duration(days: 2)))) {
// Message was opened by all persons, as it can be reopened and then stored by a other person keep it for
// two day just to be sure.
// In case the image was opened, but send with unlimited time or no authentication.
if (message.senderId == null) {
delete = false;
}
} else {
// this media was received from another person
if (message.openedAt == null) {
// Message was not yet opened, so do not remove it.
// Check weather the image was send in a group. Then the images is preserved for two days in case another person stores the image.
// This also allows to reopen this image for two days.
final group = await twonlyDB.groupsDao.getGroup(message.groupId);
if (group != null && !group.isDirectChat) {
delete = false;
}
if (service.mediaFile.type == MediaType.audio) {
delete = false; // do not delete voice messages
}
// In case the app was send in a direct chat, then it can be deleted.
}
}
}

View file

@ -174,7 +174,9 @@ Future<void> showLocalPushNotification(
);
await flutterLocalNotificationsPlugin.show(
pushUser.userId.toInt(),
pushUser.userId.toInt() %
// ignore: avoid_js_rounded_ints
2373257871630019505, // Invalid argument (id): must fit within the size of a 32-bit integer
title,
body,
notificationDetails,

View file

@ -54,8 +54,9 @@ Future<CiphertextMessage?> signalEncryptMessage(
final tempIdentityKey = await signalStore.getIdentity(address);
if (tempIdentityKey != null) {
final registrationId = await session.getRemoteRegistrationId();
final preKeyBundle = PreKeyBundle(
target,
registrationId,
defaultDeviceId,
preKey?.preKeyId,
tempPrePublicKey,

View file

@ -56,7 +56,7 @@ Future<bool> createNewSignalSession(Response_UserData userData) async {
);
final preKeyBundle = PreKeyBundle(
userData.userId.toInt(),
userData.registrationId.toInt(),
defaultDeviceId,
tempPreKeyId,
tempPrePublicKey,
@ -105,3 +105,22 @@ Future<Fingerprint?> generateSessionFingerPrint(int target) async {
return null;
}
}
Future<Uint8List?> getPublicKeyFromContact(int contactId) async {
final signalStore = await getSignalStore();
if (signalStore == null) return null;
try {
final targetIdentity = await signalStore.getIdentity(
SignalProtocolAddress(
contactId.toString(),
defaultDeviceId,
),
);
if (targetIdentity != null) {
return targetIdentity.publicKey.serialize();
}
return null;
} catch (e) {
return null;
}
}

View file

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/utils/misc.dart';
@ -15,7 +16,7 @@ Future<void> createPushAvatars() async {
final pictureInfo = await vg.loadPicture(SvgStringLoader(avatarSvg), null);
final image = await pictureInfo.picture.toImage(300, 300);
final image = await pictureInfo.picture.toImage(270, 300);
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final pngBytes = byteData!.buffer.asUint8List();
@ -34,3 +35,23 @@ File avatarPNGFile(int contactId) {
}
return File('${avatarsDirectory.path}/$contactId.png');
}
Future<Uint8List> getUserAvatar() async {
if (gUser.avatarSvg == null) {
final data = await rootBundle.load('assets/images/default_avatar.png');
return data.buffer.asUint8List();
}
final pictureInfo =
await vg.loadPicture(SvgStringLoader(gUser.avatarSvg!), null);
final image = await pictureInfo.picture.toImage(270, 300);
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final pngBytes = byteData!.buffer.asUint8List();
final file = avatarPNGFile(gUser.userId)..writeAsBytesSync(pngBytes);
pictureInfo.picture.dispose();
return file.readAsBytesSync();
}

View file

@ -6,7 +6,6 @@ import 'package:flutter/services.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:gal/gal.dart';
import 'package:intl/intl.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:local_auth/local_auth.dart';
import 'package:provider/provider.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
@ -310,9 +309,6 @@ String getUUIDforDirectChat(int a, int b) {
if (a < 0 || b < 0) {
throw ArgumentError('Inputs must be non-negative integers.');
}
if (a > integerMax || b > integerMax) {
throw ArgumentError('Inputs must be <= 0x7fffffff.');
}
// Mask to 64 bits in case inputs exceed 64 bits
final mask64 = (BigInt.one << 64) - BigInt.one;

100
lib/src/utils/qr.dart Normal file
View file

@ -0,0 +1,100 @@
import 'package:drift/drift.dart' show Value;
import 'package:fixnum/fixnum.dart';
import 'package:flutter/foundation.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart';
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
import 'package:twonly/src/model/protobuf/client/generated/qr.pb.dart';
import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
import 'package:twonly/src/services/signal/identity.signal.dart';
import 'package:twonly/src/services/signal/session.signal.dart';
import 'package:twonly/src/services/signal/utils.signal.dart';
Future<Uint8List> getProfileQrCodeData() async {
final signalIdentity = (await getSignalIdentity())!;
final signalStore = await getSignalStoreFromIdentity(signalIdentity);
final signedPreKey = (await signalStore.loadSignedPreKeys())[0];
final publicProfile = PublicProfile(
userId: Int64(gUser.userId),
username: gUser.username,
publicIdentityKey:
(await signalStore.getIdentityKeyPair()).getPublicKey().serialize(),
registrationId: Int64(signalIdentity.registrationId),
signedPrekey: signedPreKey.getKeyPair().publicKey.serialize(),
signedPrekeySignature: signedPreKey.signature,
signedPrekeyId: Int64(signedPreKey.id),
);
final data = publicProfile.writeToBuffer();
final qrEnvelope = QREnvelope(
type: QREnvelope_Type.PublicProfile,
data: data,
);
return qrEnvelope.writeToBuffer();
}
Future<Uint8List> getUserPublicKey() async {
final signalIdentity = (await getSignalIdentity())!;
final signalStore = await getSignalStoreFromIdentity(signalIdentity);
return (await signalStore.getIdentityKeyPair()).getPublicKey().serialize();
}
PublicProfile? parseQrCodeData(Uint8List rawBytes) {
try {
final envelop = QREnvelope.fromBuffer(rawBytes);
if (envelop.type == QREnvelope_Type.PublicProfile) {
return PublicProfile.fromBuffer(envelop.data);
}
} catch (e) {
// Log.warn(e);
}
return null;
}
Future<void> addNewContactFromPublicProfile(PublicProfile profile) async {
final userdata = Response_UserData(
userId: profile.userId,
publicIdentityKey: profile.publicIdentityKey,
signedPrekey: profile.signedPrekey,
signedPrekeyId: profile.signedPrekeyId,
signedPrekeySignature: profile.signedPrekeySignature,
);
final added = await twonlyDB.contactsDao.insertOnConflictUpdate(
ContactsCompanion(
username: Value(profile.username),
userId: Value(profile.userId.toInt()),
requested: const Value(false),
blocked: const Value(false),
deletedByUser: const Value(false),
verified: const Value(
true,
), // This contact was added from a QR-Code scan, so the public key was not loaded from the server
),
);
if (added > 0) {
if (await createNewSignalSession(userdata)) {
// 1. Setup notifications keys with the other user
await setupNotificationWithUsers(
forceContact: userdata.userId.toInt(),
);
// 2. Then send user request
await sendCipherText(
userdata.userId.toInt(),
EncryptedContent(
contactRequest: EncryptedContent_ContactRequest(
type: EncryptedContent_ContactRequest_Type.REQUEST,
),
),
);
}
}
}

View file

@ -1,78 +1,44 @@
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart';
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
import 'package:twonly/src/views/components/media_view_sizing.dart';
class HomeViewCameraPreview extends StatelessWidget {
const HomeViewCameraPreview({
required this.controller,
required this.screenshotController,
class MainCameraPreview extends StatelessWidget {
const MainCameraPreview({
required this.mainCameraController,
super.key,
});
final CameraController? controller;
final ScreenshotController screenshotController;
final MainCameraController mainCameraController;
@override
Widget build(BuildContext context) {
if (controller == null || !controller!.value.isInitialized) {
if (mainCameraController.cameraController == null ||
!mainCameraController.cameraController!.value.isInitialized) {
return Container();
}
return Positioned.fill(
child: MediaViewSizing(
requiredHeight: 80,
requiredHeight: 0,
additionalPadding: 59,
bottomNavigation: Container(),
child: Screenshot(
controller: screenshotController,
controller: mainCameraController.screenshotController,
child: AspectRatio(
aspectRatio: 9 / 16,
child: ClipRect(
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
width: controller!.value.previewSize!.height,
height: controller!.value.previewSize!.width,
child: CameraPreview(controller!),
),
),
),
),
),
),
);
}
}
class SendToCameraPreview extends StatelessWidget {
const SendToCameraPreview({
required this.cameraController,
required this.screenshotController,
super.key,
});
final CameraController? cameraController;
final ScreenshotController screenshotController;
@override
Widget build(BuildContext context) {
if (cameraController == null || !cameraController!.value.isInitialized) {
return Container();
}
return Positioned.fill(
child: MediaViewSizing(
requiredHeight: 80,
bottomNavigation: Container(),
child: Screenshot(
controller: screenshotController,
child: AspectRatio(
aspectRatio: 9 / 16,
child: ClipRect(
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
width: cameraController!.value.previewSize!.height,
height: cameraController!.value.previewSize!.width,
child: CameraPreview(cameraController!),
width: mainCameraController
.cameraController!.value.previewSize!.height,
height: mainCameraController
.cameraController!.value.previewSize!.width,
child: CameraPreview(
mainCameraController.cameraController!,
child: mainCameraController.customPaint,
),
),
),
),

View file

@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
@ -8,23 +9,28 @@ import 'package:flutter_android_volume_keydown/flutter_android_volume_keydown.da
import 'package:flutter_volume_controller/flutter_volume_controller.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:image_picker/image_picker.dart';
import 'package:lottie/lottie.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:screenshot/screenshot.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/qr.dart';
import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
import 'package:twonly/src/views/camera/camera_preview_components/permissions_view.dart';
import 'package:twonly/src/views/camera/camera_preview_components/send_to.dart';
import 'package:twonly/src/views/camera/camera_preview_components/video_recording_time.dart';
import 'package:twonly/src/views/camera/camera_preview_components/zoom_selector.dart';
import 'package:twonly/src/views/camera/image_editor/action_button.dart';
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
import 'package:twonly/src/views/components/avatar_icon.component.dart';
import 'package:twonly/src/views/components/media_view_sizing.dart';
import 'package:twonly/src/views/home.view.dart';
import 'package:url_launcher/url_launcher_string.dart';
int maxVideoRecordingTime = 60;
@ -52,6 +58,8 @@ Future<(SelectedCameraDetails, CameraController)?> initializeCameraController(
gCameras[cameraId],
ResolutionPreset.high,
enableAudio: await Permission.microphone.isGranted,
imageFormatGroup:
Platform.isAndroid ? ImageFormatGroup.nv21 : ImageFormatGroup.bgra8888,
);
await cameraController.initialize().then((_) async {
@ -87,21 +95,17 @@ class SelectedCameraDetails {
class CameraPreviewControllerView extends StatelessWidget {
const CameraPreviewControllerView({
required this.cameraController,
required this.selectCamera,
required this.selectedCameraDetails,
required this.screenshotController,
required this.mainController,
required this.isVisible,
this.hideControllers = false,
super.key,
this.sendToGroup,
});
final MainCameraController mainController;
final Group? sendToGroup;
final Future<CameraController?> Function(int sCameraId, bool init)
selectCamera;
final CameraController? cameraController;
final SelectedCameraDetails selectedCameraDetails;
final ScreenshotController screenshotController;
final bool isVisible;
final bool hideControllers;
@override
Widget build(BuildContext context) {
@ -112,16 +116,14 @@ class CameraPreviewControllerView extends StatelessWidget {
if (snap.data!) {
return CameraPreviewView(
sendToGroup: sendToGroup,
selectCamera: selectCamera,
cameraController: cameraController,
selectedCameraDetails: selectedCameraDetails,
screenshotController: screenshotController,
mainCameraController: mainController,
isVisible: isVisible,
hideControllers: hideControllers,
);
} else {
return PermissionHandlerView(
onSuccess: () {
selectCamera(0, true);
mainController.selectCamera(0, true);
},
);
}
@ -135,23 +137,17 @@ class CameraPreviewControllerView extends StatelessWidget {
class CameraPreviewView extends StatefulWidget {
const CameraPreviewView({
required this.selectCamera,
required this.cameraController,
required this.selectedCameraDetails,
required this.screenshotController,
required this.mainCameraController,
required this.isVisible,
required this.hideControllers,
super.key,
this.sendToGroup,
});
final MainCameraController mainCameraController;
final Group? sendToGroup;
final Future<CameraController?> Function(
int sCameraId,
bool init,
) selectCamera;
final CameraController? cameraController;
final SelectedCameraDetails selectedCameraDetails;
final ScreenshotController screenshotController;
final bool isVisible;
final bool hideControllers;
@override
State<CameraPreviewView> createState() => _CameraPreviewViewState();
@ -172,6 +168,8 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
final GlobalKey keyTriggerButton = GlobalKey();
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
MainCameraController get mc => widget.mainCameraController;
StreamSubscription<HardwareButton>? androidVolumeDownSub;
@override
@ -280,18 +278,18 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
}
Future<void> updateScaleFactor(double newScale) async {
if (widget.selectedCameraDetails.scaleFactor == newScale ||
widget.cameraController == null) {
if (mc.selectedCameraDetails.scaleFactor == newScale ||
mc.cameraController == null) {
return;
}
await widget.cameraController?.setZoomLevel(
await mc.cameraController?.setZoomLevel(
newScale.clamp(
widget.selectedCameraDetails.minAvailableZoom,
widget.selectedCameraDetails.maxAvailableZoom,
mc.selectedCameraDetails.minAvailableZoom,
mc.selectedCameraDetails.maxAvailableZoom,
),
);
setState(() {
widget.selectedCameraDetails.scaleFactor = newScale;
mc.selectedCameraDetails.scaleFactor = newScale;
});
}
@ -323,31 +321,31 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
setState(() {
_sharePreviewIsShown = true;
});
if (widget.selectedCameraDetails.isFlashOn) {
if (mc.selectedCameraDetails.isFlashOn) {
if (isFront) {
setState(() {
_showSelfieFlash = true;
});
} else {
await widget.cameraController?.setFlashMode(FlashMode.torch);
await mc.cameraController?.setFlashMode(FlashMode.torch);
}
await Future.delayed(const Duration(milliseconds: 1000));
}
await widget.cameraController?.pausePreview();
await mc.cameraController?.pausePreview();
if (!mounted) {
return;
}
if (Platform.isIOS) {
// android has a problem with this. Flash is turned off in the pausePreview function.
await widget.cameraController?.setFlashMode(FlashMode.off);
await mc.cameraController?.setFlashMode(FlashMode.off);
}
if (!mounted) {
return;
}
imageBytes = widget.screenshotController
imageBytes = mc.screenshotController
.capture(pixelRatio: MediaQuery.of(context).devicePixelRatio);
if (await pushMediaEditor(imageBytes, null)) {
@ -424,33 +422,33 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
}
return true;
}
await widget.selectCamera(
widget.selectedCameraDetails.cameraId,
await mc.selectCamera(
mc.selectedCameraDetails.cameraId,
false,
);
return false;
}
bool get isFront =>
widget.cameraController?.description.lensDirection ==
mc.cameraController?.description.lensDirection ==
CameraLensDirection.front;
Future<void> onPanUpdate(dynamic details) async {
if (isFront || details == null) {
return;
}
if (widget.cameraController == null ||
!widget.cameraController!.value.isInitialized) {
if (mc.cameraController == null ||
!mc.cameraController!.value.isInitialized) {
return;
}
widget.selectedCameraDetails.scaleFactor = (_baseScaleFactor +
mc.selectedCameraDetails.scaleFactor = (_baseScaleFactor +
// ignore: avoid_dynamic_calls
(_basePanY - (details.localPosition.dy as double)) / 30)
.clamp(1, widget.selectedCameraDetails.maxAvailableZoom);
.clamp(1, mc.selectedCameraDetails.maxAvailableZoom);
await widget.cameraController!
.setZoomLevel(widget.selectedCameraDetails.scaleFactor);
await mc.cameraController!
.setZoomLevel(mc.selectedCameraDetails.scaleFactor);
if (mounted) {
setState(() {});
}
@ -507,8 +505,8 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
}
Future<void> startVideoRecording() async {
if (widget.cameraController != null &&
widget.cameraController!.value.isRecordingVideo) {
if (mc.cameraController != null &&
mc.cameraController!.value.isRecordingVideo) {
return;
}
setState(() {
@ -516,7 +514,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
});
try {
await widget.cameraController?.startVideoRecording();
await mc.cameraController?.startVideoRecording();
_videoRecordingTimer =
Timer.periodic(const Duration(milliseconds: 15), (timer) {
setState(() {
@ -554,8 +552,8 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
_isVideoRecording = false;
});
if (widget.cameraController == null ||
!widget.cameraController!.value.isRecordingVideo) {
if (mc.cameraController == null ||
!mc.cameraController!.value.isRecordingVideo) {
return;
}
@ -564,9 +562,9 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
});
try {
final videoPath = await widget.cameraController?.stopVideoRecording();
final videoPath = await mc.cameraController?.stopVideoRecording();
if (videoPath == null) return;
await widget.cameraController?.pausePreview();
await mc.cameraController?.pausePreview();
if (await pushMediaEditor(null, File(videoPath.path))) {
return;
}
@ -593,12 +591,13 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
@override
Widget build(BuildContext context) {
if (widget.selectedCameraDetails.cameraId >= gCameras.length ||
widget.cameraController == null) {
if (mc.selectedCameraDetails.cameraId >= gCameras.length ||
mc.cameraController == null) {
return Container();
}
return MediaViewSizing(
requiredHeight: 80,
requiredHeight: 0,
additionalPadding: 59,
bottomNavigation: Container(),
child: GestureDetector(
onPanStart: (details) async {
@ -607,14 +606,14 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
}
setState(() {
_basePanY = details.localPosition.dy;
_baseScaleFactor = widget.selectedCameraDetails.scaleFactor;
_baseScaleFactor = mc.selectedCameraDetails.scaleFactor;
});
},
onLongPressMoveUpdate: onPanUpdate,
onLongPressStart: (details) {
setState(() {
_basePanY = details.localPosition.dy;
_baseScaleFactor = widget.selectedCameraDetails.scaleFactor;
_baseScaleFactor = mc.selectedCameraDetails.scaleFactor;
});
// Get the position of the pointer
final renderBox =
@ -652,7 +651,9 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
widget.sendToGroup != null &&
!_isVideoRecording)
SendToWidget(sendTo: widget.sendToGroup!.groupName),
if (!_sharePreviewIsShown && !_isVideoRecording)
if (!_sharePreviewIsShown &&
!_isVideoRecording &&
!widget.hideControllers)
Positioned(
right: 5,
top: 0,
@ -667,29 +668,29 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
Icons.repeat_rounded,
tooltipText: context.lang.switchFrontAndBackCamera,
onPressed: () async {
await widget.selectCamera(
(widget.selectedCameraDetails.cameraId + 1) % 2,
await mc.selectCamera(
(mc.selectedCameraDetails.cameraId + 1) % 2,
false,
);
},
),
ActionButton(
widget.selectedCameraDetails.isFlashOn
mc.selectedCameraDetails.isFlashOn
? Icons.flash_on_rounded
: Icons.flash_off_rounded,
tooltipText: context.lang.toggleFlashLight,
color: widget.selectedCameraDetails.isFlashOn
color: mc.selectedCameraDetails.isFlashOn
? Colors.white
: Colors.white.withAlpha(160),
onPressed: () async {
if (widget.selectedCameraDetails.isFlashOn) {
await widget.cameraController
if (mc.selectedCameraDetails.isFlashOn) {
await mc.cameraController
?.setFlashMode(FlashMode.off);
widget.selectedCameraDetails.isFlashOn = false;
mc.selectedCameraDetails.isFlashOn = false;
} else {
await widget.cameraController
await mc.cameraController
?.setFlashMode(FlashMode.always);
widget.selectedCameraDetails.isFlashOn = true;
mc.selectedCameraDetails.isFlashOn = true;
}
setState(() {});
},
@ -707,7 +708,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
),
),
),
if (!_sharePreviewIsShown)
if (!_sharePreviewIsShown && !widget.hideControllers)
Positioned(
bottom: 30,
left: 0,
@ -716,20 +717,19 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
alignment: Alignment.bottomCenter,
child: Column(
children: [
if (widget.cameraController!.value.isInitialized &&
widget.selectedCameraDetails.isZoomAble &&
if (mc.cameraController!.value.isInitialized &&
mc.selectedCameraDetails.isZoomAble &&
!isFront &&
!_isVideoRecording)
SizedBox(
width: 120,
child: CameraZoomButtons(
key: widget.key,
scaleFactor:
widget.selectedCameraDetails.scaleFactor,
scaleFactor: mc.selectedCameraDetails.scaleFactor,
updateScaleFactor: updateScaleFactor,
selectCamera: widget.selectCamera,
selectedCameraDetails: widget.selectedCameraDetails,
controller: widget.cameraController!,
selectCamera: mc.selectCamera,
selectedCameraDetails: mc.selectedCameraDetails,
controller: mc.cameraController!,
),
),
const SizedBox(height: 30),
@ -787,7 +787,8 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
videoRecordingStarted: _videoRecordingStarted,
maxVideoRecordingTime: maxVideoRecordingTime,
),
if (!_sharePreviewIsShown && widget.sendToGroup != null)
if (!_sharePreviewIsShown && widget.sendToGroup != null ||
widget.hideControllers)
Positioned(
left: 5,
top: 10,
@ -808,6 +809,156 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
),
),
),
Positioned(
right: 8,
top: 170,
child: SizedBox(
height: 200,
width: 150,
child: ListView(
children: [
...widget.mainCameraController.scannedNewProfiles.values
.map(
(c) {
return GestureDetector(
onTap: () async {
if (c.isLoading) return;
c.isLoading = true;
widget.mainCameraController.setState();
await addNewContactFromPublicProfile(c.profile);
widget.mainCameraController.scannedNewProfiles
.remove(c.profile.userId.toInt());
widget.mainCameraController.setState();
},
child: Container(
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: context.color.surfaceContainer,
),
child: Row(
children: [
Text(c.profile.username),
Expanded(child: Container()),
if (c.isLoading)
const SizedBox(
width: 12,
height: 12,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
else
ColoredBox(
color: Colors.transparent,
child: FaIcon(
FontAwesomeIcons.userPlus,
color: isDarkMode(context)
? Colors.white
: Colors.black,
size: 17,
),
),
],
),
),
);
},
),
...widget.mainCameraController.contactsVerified.values.map(
(c) {
return Container(
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: context.color.surfaceContainer,
),
child: Row(
children: [
AvatarIcon(
contactId: c.contact.userId,
fontSize: 14,
),
const SizedBox(width: 10),
Text(
getContactDisplayName(
c.contact,
maxLength: 13,
),
),
Expanded(
child: Container(),
),
ColoredBox(
color: Colors.transparent,
child: SizedBox(
width: 30,
child: Lottie.asset(
c.verificationOk
? 'assets/animations/success.json'
: 'assets/animations/failed.json',
repeat: false,
onLoaded: (p0) {
Future.delayed(const Duration(seconds: 4),
() {
widget.mainCameraController.setState();
});
},
),
),
),
],
),
);
},
),
if (widget.mainCameraController.scannedUrl != null)
GestureDetector(
onTap: () {
launchUrlString(
widget.mainCameraController.scannedUrl!,
);
},
child: Container(
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: context.color.surfaceContainer,
),
child: Row(
children: [
Text(
substringBy(
widget.mainCameraController.scannedUrl!,
25,
),
style: const TextStyle(fontSize: 8),
),
Expanded(
child: Container(),
),
Expanded(child: Container()),
ColoredBox(
color: Colors.transparent,
child: FaIcon(
FontAwesomeIcons.shareFromSquare,
color: isDarkMode(context)
? Colors.white
: Colors.black,
size: 17,
),
),
],
),
),
),
],
),
),
),
],
),
),

View file

@ -0,0 +1,234 @@
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:collection/collection.dart';
import 'package:drift/drift.dart' show Value;
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:google_mlkit_barcode_scanning/google_mlkit_barcode_scanning.dart';
import 'package:screenshot/screenshot.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/model/protobuf/client/generated/qr.pb.dart';
import 'package:twonly/src/services/signal/session.signal.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/qr.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
import 'package:twonly/src/views/camera/painters/barcode_detector_painter.dart';
class ScannedVerifiedContact {
ScannedVerifiedContact({
required this.contact,
required this.verificationOk,
});
Contact contact;
bool verificationOk;
}
class ScannedNewProfile {
ScannedNewProfile({
required this.profile,
this.isLoading = false,
});
PublicProfile profile;
bool isLoading;
}
class MainCameraController {
late void Function() setState;
CameraController? cameraController;
ScreenshotController screenshotController = ScreenshotController();
SelectedCameraDetails selectedCameraDetails = SelectedCameraDetails();
bool initCameraStarted = true;
Map<int, ScannedVerifiedContact> contactsVerified = {};
Map<int, ScannedNewProfile> scannedNewProfiles = {};
String? scannedUrl;
Future<void> closeCamera() async {
contactsVerified = {};
scannedNewProfiles = {};
scannedUrl = null;
try {
await cameraController?.stopImageStream();
} catch (e) {
Log.warn(e);
}
await cameraController?.dispose();
cameraController = null;
initCameraStarted = false;
selectedCameraDetails = SelectedCameraDetails();
}
Future<CameraController?> selectCamera(int sCameraId, bool init) async {
initCameraStarted = true;
final opts = await initializeCameraController(
selectedCameraDetails,
sCameraId,
init,
);
if (opts != null) {
selectedCameraDetails = opts.$1;
cameraController = opts.$2;
}
if (cameraController?.description.lensDirection ==
CameraLensDirection.back) {
await cameraController?.startImageStream(_processCameraImage);
}
setState();
return cameraController;
}
Future<void> toggleSelectedCamera() async {
if (cameraController == null) return;
// do not allow switching camera when recording
if (cameraController!.value.isRecordingVideo) {
return;
}
try {
await cameraController!.stopImageStream();
} catch (e) {
Log.warn(e);
}
await cameraController!.dispose();
cameraController = null;
await selectCamera((selectedCameraDetails.cameraId + 1) % 2, false);
}
final BarcodeScanner _barcodeScanner = BarcodeScanner();
bool _isBusy = false;
CustomPaint? customPaint;
final Map<DeviceOrientation, int> _orientations = {
DeviceOrientation.portraitUp: 0,
DeviceOrientation.landscapeLeft: 90,
DeviceOrientation.portraitDown: 180,
DeviceOrientation.landscapeRight: 270,
};
void _processCameraImage(CameraImage image) {
final inputImage = _inputImageFromCameraImage(image);
if (inputImage == null) return;
_processImage(inputImage);
}
InputImage? _inputImageFromCameraImage(CameraImage image) {
if (cameraController == null) return null;
final camera = cameraController!.description;
final sensorOrientation = camera.sensorOrientation;
InputImageRotation? rotation;
if (Platform.isIOS) {
rotation = InputImageRotationValue.fromRawValue(sensorOrientation);
} else if (Platform.isAndroid) {
var rotationCompensation =
_orientations[cameraController!.value.deviceOrientation];
if (rotationCompensation == null) return null;
if (camera.lensDirection == CameraLensDirection.front) {
// front-facing
rotationCompensation = (sensorOrientation + rotationCompensation) % 360;
} else {
// back-facing
rotationCompensation =
(sensorOrientation - rotationCompensation + 360) % 360;
}
rotation = InputImageRotationValue.fromRawValue(rotationCompensation);
// print('rotationCompensation: $rotationCompensation');
}
if (rotation == null) return null;
// print('final rotation: $rotation');
// get image format
var format = InputImageFormatValue.fromRawValue(image.format.raw as int);
// validate format depending on platform
// only supported formats:
// * nv21 for Android
// * bgra8888 for iOS
if (Platform.isAndroid && format == InputImageFormat.yuv420) {
// https://developer.android.com/reference/kotlin/androidx/camera/core/ImageAnalysis#OUTPUT_IMAGE_FORMAT_NV21()
format = InputImageFormat.nv21;
}
if (format == null ||
(Platform.isAndroid && format != InputImageFormat.nv21) ||
(Platform.isIOS && format != InputImageFormat.bgra8888)) {
return null;
}
// since format is constraint to nv21 or bgra8888, both only have one plane
if (image.planes.length != 1) return null;
final plane = image.planes.first;
// compose InputImage using bytes
return InputImage.fromBytes(
bytes: plane.bytes,
metadata: InputImageMetadata(
size: Size(image.width.toDouble(), image.height.toDouble()),
rotation: rotation, // used only in Android
format: format, // used only in iOS
bytesPerRow: plane.bytesPerRow, // used only in iOS
),
);
}
Future<void> _processImage(InputImage inputImage) async {
if (_isBusy) return;
_isBusy = true;
final barcodes = await _barcodeScanner.processImage(inputImage);
if (inputImage.metadata?.size != null &&
inputImage.metadata?.rotation != null &&
cameraController != null) {
final painter = BarcodeDetectorPainter(
barcodes,
inputImage.metadata!.size,
inputImage.metadata!.rotation,
cameraController!.description.lensDirection,
);
customPaint = CustomPaint(painter: painter);
for (final barcode in barcodes) {
if (barcode.displayValue != null) {
if (barcode.displayValue!.startsWith('http://') ||
barcode.displayValue!.startsWith('https://')) {
scannedUrl = barcode.displayValue;
}
}
if (barcode.rawBytes == null) continue;
final profile = parseQrCodeData(barcode.rawBytes!);
if (profile == null) continue;
final contact =
await twonlyDB.contactsDao.getContactById(profile.userId.toInt());
if (contact != null && contact.accepted) {
if (contactsVerified[contact.userId] == null) {
final storedPublicKey =
await getPublicKeyFromContact(contact.userId);
if (storedPublicKey != null) {
final verificationOk =
profile.publicIdentityKey.equals(storedPublicKey.toList());
contactsVerified[contact.userId] = ScannedVerifiedContact(
contact: contact,
verificationOk: verificationOk,
);
if (verificationOk) {
await twonlyDB.contactsDao.updateContact(
contact.userId,
const ContactsCompanion(verified: Value(true)),
);
}
}
}
} else {
if (scannedNewProfiles[profile.userId.toInt()] == null) {
scannedNewProfiles[profile.userId.toInt()] = ScannedNewProfile(
profile: profile,
);
}
}
}
}
_isBusy = false;
setState();
}
}

View file

@ -6,7 +6,7 @@ import 'dart:math';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/views/camera/camera_preview_controller_view.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
class CameraZoomButtons extends StatefulWidget {
const CameraZoomButtons({

View file

@ -0,0 +1,51 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
class QrCodeScanner extends StatefulWidget {
const QrCodeScanner({super.key});
@override
State<QrCodeScanner> createState() => QrCodeScannerState();
}
class QrCodeScannerState extends State<QrCodeScanner> {
final MainCameraController _mainCameraController = MainCameraController();
@override
void initState() {
super.initState();
_mainCameraController.setState = () {
if (mounted) setState(() {});
};
unawaited(_mainCameraController.selectCamera(0, true));
}
@override
void dispose() {
_mainCameraController.closeCamera();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onDoubleTap: _mainCameraController.toggleSelectedCamera,
child: Stack(
children: [
MainCameraPreview(
mainCameraController: _mainCameraController,
),
CameraPreviewControllerView(
mainController: _mainCameraController,
hideControllers: true,
isVisible: true,
),
],
),
),
);
}
}

View file

@ -1,11 +1,9 @@
import 'dart:async';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
import 'package:twonly/src/views/camera/camera_preview_controller_view.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
class CameraSendToView extends StatefulWidget {
const CameraSendToView(this.sendToGroup, {super.key});
@ -15,70 +13,36 @@ class CameraSendToView extends StatefulWidget {
}
class CameraSendToViewState extends State<CameraSendToView> {
CameraController? cameraController;
ScreenshotController screenshotController = ScreenshotController();
SelectedCameraDetails selectedCameraDetails = SelectedCameraDetails();
final MainCameraController _mainCameraController = MainCameraController();
@override
void initState() {
super.initState();
unawaited(selectCamera(0, true));
_mainCameraController.setState = () {
if (mounted) setState(() {});
};
unawaited(_mainCameraController.selectCamera(0, true));
}
@override
void dispose() {
cameraController?.dispose();
cameraController = null;
selectedCameraDetails = SelectedCameraDetails();
_mainCameraController.closeCamera();
super.dispose();
}
Future<CameraController?> selectCamera(
int sCameraId,
bool init,
) async {
final opts = await initializeCameraController(
selectedCameraDetails,
sCameraId,
init,
);
if (opts != null) {
selectedCameraDetails = opts.$1;
cameraController = opts.$2;
}
setState(() {});
return cameraController;
}
/// same function also in home.view.dart
Future<void> toggleSelectedCamera() async {
if (cameraController == null) return;
// do not allow switching camera when recording
if (cameraController!.value.isRecordingVideo) {
return;
}
await cameraController!.dispose();
cameraController = null;
await selectCamera((selectedCameraDetails.cameraId + 1) % 2, false);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onDoubleTap: toggleSelectedCamera,
onDoubleTap: _mainCameraController.toggleSelectedCamera,
child: Stack(
children: [
SendToCameraPreview(
cameraController: cameraController,
screenshotController: screenshotController,
MainCameraPreview(
mainCameraController: _mainCameraController,
),
CameraPreviewControllerView(
selectCamera: selectCamera,
mainController: _mainCameraController,
sendToGroup: widget.sendToGroup,
cameraController: cameraController,
selectedCameraDetails: selectedCameraDetails,
screenshotController: screenshotController,
isVisible: true,
),
],

View file

@ -0,0 +1,58 @@
import 'dart:ui';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:google_mlkit_barcode_scanning/google_mlkit_barcode_scanning.dart';
import 'coordinates_translator.dart';
class BarcodeDetectorPainter extends CustomPainter {
BarcodeDetectorPainter(
this.barcodes,
this.imageSize,
this.rotation,
this.cameraLensDirection,
);
final List<Barcode> barcodes;
final Size imageSize;
final InputImageRotation rotation;
final CameraLensDirection cameraLensDirection;
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 3.0
..color = Colors.lightGreenAccent;
for (final barcode in barcodes) {
final cornerPoints = <Offset>[];
for (final point in barcode.cornerPoints) {
final x = translateX(
point.x.toDouble(),
size,
imageSize,
rotation,
cameraLensDirection,
);
final y = translateY(
point.y.toDouble(),
size,
imageSize,
rotation,
cameraLensDirection,
);
cornerPoints.add(Offset(x, y));
}
cornerPoints.add(cornerPoints.first);
canvas.drawPoints(PointMode.polygon, cornerPoints, paint);
}
}
@override
bool shouldRepaint(BarcodeDetectorPainter oldDelegate) {
return oldDelegate.imageSize != imageSize ||
oldDelegate.barcodes != barcodes;
}
}

View file

@ -0,0 +1,53 @@
import 'dart:io';
import 'dart:ui';
import 'package:camera/camera.dart';
import 'package:google_mlkit_barcode_scanning/google_mlkit_barcode_scanning.dart';
double translateX(
double x,
Size canvasSize,
Size imageSize,
InputImageRotation rotation,
CameraLensDirection cameraLensDirection,
) {
switch (rotation) {
case InputImageRotation.rotation90deg:
return x *
canvasSize.width /
(Platform.isIOS ? imageSize.width : imageSize.height);
case InputImageRotation.rotation270deg:
return canvasSize.width -
x *
canvasSize.width /
(Platform.isIOS ? imageSize.width : imageSize.height);
case InputImageRotation.rotation0deg:
case InputImageRotation.rotation180deg:
switch (cameraLensDirection) {
case CameraLensDirection.back:
return x * canvasSize.width / imageSize.width;
// ignore: no_default_cases
default:
return canvasSize.width - x * canvasSize.width / imageSize.width;
}
}
}
double translateY(
double y,
Size canvasSize,
Size imageSize,
InputImageRotation rotation,
CameraLensDirection cameraLensDirection,
) {
switch (rotation) {
case InputImageRotation.rotation90deg:
case InputImageRotation.rotation270deg:
return y *
canvasSize.height /
(Platform.isIOS ? imageSize.height : imageSize.width);
case InputImageRotation.rotation0deg:
case InputImageRotation.rotation180deg:
return y * canvasSize.height / imageSize.height;
}
}

View file

@ -403,7 +403,9 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
for (final x in layers) {
x.showCustomButtons = true;
}
if (mounted) {
setState(() {});
}
return image;
}
@ -531,7 +533,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
setState(() {});
},
child: MediaViewSizing(
requiredHeight: 80,
requiredHeight: 59,
bottomNavigation: ColoredBox(
color: Theme.of(context).colorScheme.surface,
child: Row(

View file

@ -1,4 +1,5 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:drift/drift.dart' hide Column;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -16,7 +17,14 @@ import 'package:twonly/src/views/components/avatar_icon.component.dart';
import 'package:twonly/src/views/components/headline.dart';
class AddNewUserView extends StatefulWidget {
const AddNewUserView({super.key});
const AddNewUserView({
this.username,
this.publicKey,
super.key,
});
final String? username;
final Uint8List? publicKey;
@override
State<AddNewUserView> createState() => _SearchUsernameView();
@ -38,6 +46,13 @@ class _SearchUsernameView extends State<AddNewUserView> {
contacts = update;
}),
);
if (widget.username != null) {
searchUserName.text = widget.username!;
WidgetsBinding.instance.addPostFrameCallback((_) {
_addNewUser(context);
});
}
}
@override
@ -73,7 +88,7 @@ class _SearchUsernameView extends State<AddNewUserView> {
final addUser = await showAlertDialog(
context,
context.lang.userFound,
context.lang.userFound(searchUserName.text),
context.lang.userFoundBody,
);
@ -88,6 +103,10 @@ class _SearchUsernameView extends State<AddNewUserView> {
requested: const Value(false),
blocked: const Value(false),
deletedByUser: const Value(false),
verified: Value(
!(widget.publicKey == null) &&
userdata.publicIdentityKey.equals(widget.publicKey!),
),
),
);

View file

@ -19,11 +19,11 @@ import 'package:twonly/src/views/chats/chat_list_components/group_list_item.dart
import 'package:twonly/src/views/chats/start_new_chat.view.dart';
import 'package:twonly/src/views/components/avatar_icon.component.dart';
import 'package:twonly/src/views/components/notification_badge.dart';
import 'package:twonly/src/views/public_profile.view.dart';
import 'package:twonly/src/views/settings/help/changelog.view.dart';
import 'package:twonly/src/views/settings/profile/profile.view.dart';
import 'package:twonly/src/views/settings/settings_main.view.dart';
import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
import 'package:twonly/src/views/tutorial/tutorials.dart';
class ChatListView extends StatefulWidget {
const ChatListView({super.key});
@ -38,7 +38,6 @@ class _ChatListViewState extends State<ChatListView> {
List<Group> _groupsArchived = [];
GlobalKey searchForOtherUsers = GlobalKey();
Timer? tutorial;
bool showFeedbackShortcut = false;
@override
@ -58,16 +57,6 @@ class _ChatListViewState extends State<ChatListView> {
});
});
tutorial = Timer(const Duration(seconds: 1), () async {
tutorial = null;
if (!mounted) return;
await showChatListTutorialSearchOtherUsers(context, searchForOtherUsers);
if (!mounted) return;
// if (_groupsNotPinned.isNotEmpty) {
// await showChatListTutorialContextMenu(context, firstUserListItemKey);
// }
});
final changeLog = await rootBundle.loadString('CHANGELOG.md');
final changeLogHash =
(await compute(Sha256().hash, changeLog.codeUnits)).bytes;
@ -97,7 +86,6 @@ class _ChatListViewState extends State<ChatListView> {
@override
void dispose() {
tutorial?.cancel();
_contactsSub.cancel();
super.dispose();
}
@ -303,7 +291,29 @@ class _ChatListViewState extends State<ChatListView> {
),
floatingActionButton: Padding(
padding: const EdgeInsets.only(bottom: 30),
child: FloatingActionButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton.small(
backgroundColor: context.color.primary,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return const PublicProfileView();
},
),
);
},
child: FaIcon(
FontAwesomeIcons.qrcode,
color: isDarkMode(context) ? Colors.black : Colors.white,
),
),
const SizedBox(height: 12),
FloatingActionButton(
backgroundColor: context.color.primary,
onPressed: () {
Navigator.push(
context,
@ -314,7 +324,12 @@ class _ChatListViewState extends State<ChatListView> {
),
);
},
child: const FaIcon(FontAwesomeIcons.penToSquare),
child: FaIcon(
FontAwesomeIcons.penToSquare,
color: isDarkMode(context) ? Colors.black : Colors.white,
),
),
],
),
),
);

View file

@ -22,7 +22,6 @@ import 'package:twonly/src/views/components/flame.dart';
import 'package:twonly/src/views/components/verified_shield.dart';
import 'package:twonly/src/views/contact/contact.view.dart';
import 'package:twonly/src/views/groups/group.view.dart';
import 'package:twonly/src/views/tutorial/tutorials.dart';
Color getMessageColor(Message message) {
return (message.senderId == null)
@ -89,7 +88,6 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
Message? quotesMessage;
GlobalKey verifyShieldKey = GlobalKey();
late FocusNode textFieldFocus;
Timer? tutorial;
final ItemScrollController itemScrollController = ItemScrollController();
int? focusedScrollItem;
@ -99,12 +97,6 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
group = widget.group;
textFieldFocus = FocusNode();
initStreams();
tutorial = Timer(const Duration(seconds: 1), () async {
tutorial = null;
if (!mounted) return;
await showVerifyShieldTutorial(context, verifyShieldKey);
});
}
@override
@ -114,7 +106,6 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
contactSub?.cancel();
groupActionsSub?.cancel();
lastOpenedMessageByContactSub?.cancel();
tutorial?.cancel();
super.dispose();
}

View file

@ -84,11 +84,6 @@ class ChatAudioEntry extends StatelessWidget {
path: mediaService.tempPath.path,
message: message,
)
: (mediaService.originalPath.existsSync())
? InChatAudioPlayer(
path: mediaService.originalPath.path,
message: message,
)
: Container()
else
MessageSendStateIcon([message], [mediaService.mediaFile]),
@ -138,14 +133,22 @@ class _InChatAudioPlayerState extends State<InChatAudioPlayer> {
}
});
_playerController.onCurrentDurationChanged.listen((duration) {
_playerController.onPlayerStateChanged.listen((a) async {
if (a == PlayerState.initialized) {
_displayDuration =
await _playerController.getDuration(DurationType.max);
_maxDuration = _displayDuration;
setState(() {});
}
});
_playerController.onCurrentDurationChanged.listen((duration) async {
if (mounted) {
setState(() {
_displayDuration = _maxDuration - duration;
});
}
});
initAsync();
}
@override
@ -154,13 +157,6 @@ class _InChatAudioPlayerState extends State<InChatAudioPlayer> {
super.dispose();
}
Future<void> initAsync() async {
_displayDuration = await _playerController.getDuration(DurationType.max);
_maxDuration = _displayDuration;
if (!mounted) return;
setState(() {});
}
bool _isPlaying = false;
@override

View file

@ -15,6 +15,7 @@ import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera/camera_send_to_view.dart';
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_audio_entry.dart';
class MessageInput extends StatefulWidget {
const MessageInput({
@ -41,6 +42,10 @@ class _MessageInputState extends State<MessageInput> {
late final RecorderController recorderController;
final bool isApple = Platform.isIOS;
bool _emojiShowing = false;
bool _audioRecordingLock = false;
int _currentDuration = 0;
double _cancelSlideOffset = 0;
Offset _recordingOffset = Offset.zero;
RecordingState _recordingState = RecordingState.none;
Future<void> _sendMessage() async {
@ -72,11 +77,17 @@ class _MessageInputState extends State<MessageInput> {
void dispose() {
widget.textFieldFocus.removeListener(_handleTextFocusChange);
widget.textFieldFocus.dispose();
recorderController.dispose();
super.dispose();
}
void _initializeControllers() {
recorderController = RecorderController();
recorderController.onCurrentDuration.listen((duration) {
setState(() {
_currentDuration = duration.inMilliseconds;
});
});
}
void _handleTextFocusChange() {
@ -87,9 +98,37 @@ class _MessageInputState extends State<MessageInput> {
}
}
Future<void> _startAudioRecording() async {
if (!await Permission.microphone.isGranted) {
final statuses = await [
Permission.microphone,
].request();
if (statuses[Permission.microphone]!.isPermanentlyDenied) {
await openAppSettings();
return;
}
if (!await Permission.microphone.isGranted) {
return;
}
}
setState(() {
_recordingState = RecordingState.recording;
});
await HapticFeedback.heavyImpact();
final audioTmpPath =
'${(await getApplicationCacheDirectory()).path}/recording.m4a';
unawaited(
recorderController.record(
path: audioTmpPath,
),
);
}
Future<void> _stopAudioRecording() async {
await HapticFeedback.heavyImpact();
setState(() {
_audioRecordingLock = false;
_cancelSlideOffset = 0;
_recordingState = RecordingState.none;
});
@ -114,6 +153,19 @@ class _MessageInputState extends State<MessageInput> {
);
}
Future<void> _cancelAudioRecording() async {
setState(() {
_audioRecordingLock = false;
_cancelSlideOffset = 0;
_recordingState = RecordingState.none;
});
final path = await recorderController.stop();
if (path == null) return;
if (File(path).existsSync()) {
File(path).deleteSync();
}
}
@override
Widget build(BuildContext context) {
return Column(
@ -169,27 +221,54 @@ class _MessageInputState extends State<MessageInput> {
),
Expanded(
child: (_recordingState == RecordingState.recording)
? AudioWaveforms(
enableGesture: true,
size: Size(
MediaQuery.of(context).size.width / 2,
50,
? Row(
children: [
const Padding(
padding: EdgeInsets.only(
top: 14,
bottom: 14,
left: 12,
right: 8,
),
recorderController: recorderController,
waveStyle: WaveStyle(
waveColor: isDarkMode(context)
? Colors.white
: Colors.black,
extendWaveform: true,
showMiddleLine: false,
child: FaIcon(
FontAwesomeIcons.microphone,
size: 20,
color: Colors.red,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: context.color.surfaceContainer,
),
padding: const EdgeInsets.only(left: 18),
margin:
const EdgeInsets.symmetric(horizontal: 15),
const SizedBox(width: 10),
Text(
formatMsToMinSec(
_currentDuration,
),
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
if (!_audioRecordingLock) ...[
SizedBox(
width: (100 - _cancelSlideOffset) % 101,
),
Text(
context.lang.voiceMessageSlideToCancel,
),
] else ...[
Expanded(
child: Container(),
),
GestureDetector(
onTap: _cancelAudioRecording,
child: Text(
context.lang.voiceMessageCancel,
style: const TextStyle(
color: Colors.red,
),
),
),
const SizedBox(width: 20),
],
],
)
: TextField(
controller: _textFieldController,
@ -220,47 +299,84 @@ class _MessageInputState extends State<MessageInput> {
),
if (_textFieldController.text == '')
GestureDetector(
onLongPressStart: (a) async {
if (!await Permission.microphone.isGranted) {
final statuses = await [
Permission.microphone,
].request();
if (statuses[Permission.microphone]!
.isPermanentlyDenied) {
await openAppSettings();
return;
}
if (!await Permission.microphone.isGranted) {
return;
}
}
onLongPressMoveUpdate: (details) {
if (_audioRecordingLock) return;
if (_recordingOffset.dy -
details.localPosition.dy >=
100) {
HapticFeedback.heavyImpact();
setState(() {
_recordingState = RecordingState.recording;
_audioRecordingLock = true;
});
await HapticFeedback.heavyImpact();
final audioTmpPath =
'${(await getApplicationCacheDirectory()).path}/recording.m4a';
unawaited(
recorderController.record(
path: audioTmpPath,
),
);
},
onLongPressCancel: () async {
final path = await recorderController.stop();
if (path == null) return;
if (File(path).existsSync()) {
File(path).deleteSync();
}
setState(() {
if (_recordingOffset.dx -
details.localPosition.dx >=
90 &&
_recordingState == RecordingState.recording) {
_recordingState = RecordingState.none;
HapticFeedback.heavyImpact();
_cancelAudioRecording();
}
setState(() {
final a = _recordingOffset.dx -
details.localPosition.dx;
if (a > 0 && a <= 90) {
_cancelSlideOffset = _recordingOffset.dx -
details.localPosition.dx;
}
});
},
onLongPressEnd: (a) => _stopAudioRecording(),
onLongPressStart: (a) {
_recordingOffset = a.localPosition;
_startAudioRecording();
},
onLongPressCancel: _cancelAudioRecording,
onLongPressEnd: (a) {
if (_recordingState != RecordingState.recording) {
return;
}
if (!_audioRecordingLock) {
_stopAudioRecording();
}
},
child: Stack(
clipBehavior: Clip.none,
children: [
if (_recordingState == RecordingState.recording)
if (_recordingState == RecordingState.recording &&
!_audioRecordingLock)
Positioned.fill(
top: -120,
left: -5,
child: Align(
alignment: AlignmentGeometry.topCenter,
child: Container(
padding: const EdgeInsets.only(top: 13),
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(90),
color: Colors.black,
),
child: const Center(
child: Column(
children: [
FaIcon(
FontAwesomeIcons.lock,
size: 16,
),
SizedBox(height: 5),
FaIcon(
FontAwesomeIcons.angleUp,
size: 16,
),
],
),
),
),
),
),
if (_recordingState == RecordingState.recording &&
!_audioRecordingLock)
Positioned.fill(
top: -20,
left: -25,
@ -275,6 +391,7 @@ class _MessageInputState extends State<MessageInput> {
height: 60,
),
),
if (!_audioRecordingLock)
ColoredBox(
color: Colors.transparent,
child: Padding(
@ -306,14 +423,15 @@ class _MessageInputState extends State<MessageInput> {
),
),
),
if (_textFieldController.text != '')
if (_textFieldController.text != '' || _audioRecordingLock)
IconButton(
padding: const EdgeInsets.all(15),
icon: FaIcon(
color: context.color.primary,
FontAwesomeIcons.solidPaperPlane,
),
onPressed: _sendMessage,
onPressed:
_audioRecordingLock ? _stopAudioRecording : _sendMessage,
)
else
IconButton(

View file

@ -22,6 +22,7 @@ import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera/camera_send_to_view.dart';
import 'package:twonly/src/views/chats/media_viewer_components/reaction_buttons.component.dart';
import 'package:twonly/src/views/components/animate_icon.dart';
import 'package:twonly/src/views/components/loader.dart';
import 'package:twonly/src/views/components/media_view_sizing.dart';
import 'package:video_player/video_player.dart';
@ -58,6 +59,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
bool imageSaved = false;
bool imageSaving = false;
bool displayTwonlyPresent = false;
bool _showDownloadingLoader = false;
late String _currentMediaSender;
final emojiKey = GlobalKey<EmojiFloatWidgetState>();
@ -183,6 +185,9 @@ class _MediaViewerViewState extends State<MediaViewerView> {
downloadStateListener = stream.listen((updated) async {
if (updated == null) return;
if (updated.downloadState != DownloadState.ready) {
setState(() {
_showDownloadingLoader = true;
});
if (!downloadTriggered) {
downloadTriggered = true;
final mediaFile = await twonlyDB.mediaFilesDao
@ -204,6 +209,9 @@ class _MediaViewerViewState extends State<MediaViewerView> {
bool showTwonly,
) async {
if (allMediaFiles.isEmpty) return;
setState(() {
_showDownloadingLoader = false;
});
final currentMediaLocal =
await MediaFileService.fromMediaId(allMediaFiles.first.mediaId!);
if (currentMediaLocal == null || !mounted) return;
@ -382,6 +390,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (currentMedia != null &&
!currentMedia!.mediaFile.requiresAuthentication &&
currentMedia!.mediaFile.displayLimitInMilliseconds == null)
OutlinedButton(
style: OutlinedButton.styleFrom(
@ -502,6 +511,17 @@ class _MediaViewerViewState extends State<MediaViewerView> {
child: Stack(
fit: StackFit.expand,
children: [
if (_showDownloadingLoader)
Center(
child: SizedBox(
height: 60,
width: 60,
child: ThreeRotatingDots(
size: 40,
color: context.color.primary,
),
),
),
if ((currentMedia != null || videoController != null) &&
(canBeSeenUntil == null || progress >= 0))
GestureDetector(
@ -517,7 +537,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
},
child: MediaViewSizing(
bottomNavigation: bottomNavigation(),
requiredHeight: 80,
requiredHeight: 55,
child: Stack(
children: [
if (videoController != null)

View file

@ -0,0 +1,248 @@
// Credits: https://github.com/watery-desert/loading_animation_widget/tree/main/lib/src/three_rotating_dots
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
extension LoadingAnimationControllerX on AnimationController {
T eval<T>(Tween<T> tween, {Curve curve = Curves.linear}) =>
tween.transform(curve.transform(value));
double evalDouble({
double from = 0,
double to = 1,
double begin = 0,
double end = 1,
Curve curve = Curves.linear,
}) {
return eval(
Tween<double>(begin: from, end: to),
curve: Interval(begin, end, curve: curve),
);
}
}
class ThreeRotatingDots extends StatefulWidget {
const ThreeRotatingDots({
required this.color,
required this.size,
super.key,
});
final double size;
final Color color;
@override
State<ThreeRotatingDots> createState() => _ThreeRotatingDotsState();
}
class _ThreeRotatingDotsState extends State<ThreeRotatingDots>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 2000),
)..repeat();
}
@override
Widget build(BuildContext context) {
final color = widget.color;
final size = widget.size;
final dotSize = size / 3;
final edgeOffset = (size - dotSize) / 2;
const firstDotsInterval = Interval(
0,
0.50,
curve: Curves.easeInOutCubic,
);
const secondDotsInterval = Interval(
0.50,
1,
curve: Curves.easeInOutCubic,
);
return SizedBox(
width: size,
height: size,
child: AnimatedBuilder(
animation: _animationController,
builder: (_, __) => Transform.translate(
offset: Offset(0, size / 12),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
_BuildDot.first(
color: color,
size: dotSize,
controller: _animationController,
dotOffset: edgeOffset,
beginAngle: math.pi,
endAngle: 0,
interval: firstDotsInterval,
),
_BuildDot.first(
color: color,
size: dotSize,
controller: _animationController,
dotOffset: edgeOffset,
beginAngle: 5 * math.pi / 3,
endAngle: 2 * math.pi / 3,
interval: firstDotsInterval,
),
_BuildDot.first(
color: color,
size: dotSize,
controller: _animationController,
dotOffset: edgeOffset,
beginAngle: 7 * math.pi / 3,
endAngle: 4 * math.pi / 3,
interval: firstDotsInterval,
),
/// Next 3 dots
_BuildDot.second(
controller: _animationController,
beginAngle: 0,
endAngle: -math.pi,
interval: secondDotsInterval,
dotOffset: edgeOffset,
color: color,
size: dotSize,
),
_BuildDot.second(
controller: _animationController,
beginAngle: 2 * math.pi / 3,
endAngle: -math.pi / 3,
interval: secondDotsInterval,
dotOffset: edgeOffset,
color: color,
size: dotSize,
),
_BuildDot.second(
controller: _animationController,
beginAngle: 4 * math.pi / 3,
endAngle: math.pi / 3,
interval: secondDotsInterval,
dotOffset: edgeOffset,
color: color,
size: dotSize,
),
],
),
),
),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
class _BuildDot extends StatelessWidget {
const _BuildDot.second({
required this.controller,
required this.beginAngle,
required this.endAngle,
required this.interval,
required this.dotOffset,
required this.color,
required this.size,
}) : first = false;
const _BuildDot.first({
required this.controller,
required this.beginAngle,
required this.endAngle,
required this.interval,
required this.dotOffset,
required this.color,
required this.size,
}) : first = true;
final AnimationController controller;
final double beginAngle;
final double endAngle;
final Interval interval;
final double dotOffset;
final Color color;
final double size;
final bool first;
@override
Widget build(BuildContext context) {
return Visibility(
visible: first
? controller.value <= interval.end
: controller.value >= interval.begin,
child: Transform.rotate(
angle: controller.eval(
Tween<double>(begin: beginAngle, end: endAngle),
curve: interval,
),
child: Transform.translate(
offset: controller.eval(
Tween<Offset>(
begin: first ? Offset.zero : Offset(0, -dotOffset),
end: first ? Offset(0, -dotOffset) : Offset.zero,
),
curve: interval,
),
child: DrawDot.circular(
color: color,
dotSize: size,
),
),
),
);
}
}
class DrawDot extends StatelessWidget {
const DrawDot.circular({
required double dotSize,
required this.color,
super.key,
}) : width = dotSize,
height = dotSize,
circular = true;
const DrawDot.elliptical({
required this.width,
required this.height,
required this.color,
super.key,
}) : circular = false;
final double width;
final double height;
final bool circular;
final Color color;
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
decoration: BoxDecoration(
color: color,
shape: circular ? BoxShape.circle : BoxShape.rectangle,
borderRadius: circular
? null
: BorderRadius.all(Radius.elliptical(width, height)),
),
);
}
}

View file

@ -6,9 +6,11 @@ class MediaViewSizing extends StatefulWidget {
super.key,
this.requiredHeight,
this.bottomNavigation,
this.additionalPadding,
});
final double? requiredHeight;
final double? additionalPadding;
final Widget? bottomNavigation;
final Widget child;
@ -20,19 +22,22 @@ class _MediaViewSizingState extends State<MediaViewSizing> {
@override
Widget build(BuildContext context) {
var needToDownSizeImage = false;
var availableHeight = MediaQuery.of(context).size.height;
if (widget.requiredHeight != null) {
// Get the screen size and safe area padding
final screenSize = MediaQuery.of(context).size;
final safeAreaPadding = MediaQuery.of(context).padding;
// Calculate the available width and height
final availableWidth = screenSize.width;
final availableHeight =
screenSize.height - safeAreaPadding.top - safeAreaPadding.bottom;
availableHeight = screenSize.height -
safeAreaPadding.top -
safeAreaPadding.bottom -
(widget.additionalPadding ?? 0);
final aspectRatioWidth = availableWidth;
final aspectRatioHeight = (aspectRatioWidth * 16) / 9;
if (widget.requiredHeight != null) {
if (aspectRatioHeight < availableHeight) {
if ((screenSize.height - widget.requiredHeight!) < aspectRatioHeight) {
needToDownSizeImage = true;
@ -43,6 +48,7 @@ class _MediaViewSizingState extends State<MediaViewSizing> {
Widget imageChild = Align(
alignment: Alignment.topCenter,
child: SizedBox(
// height: availableHeight,
child: AspectRatio(
aspectRatio: 9 / 16,
child: ClipRRect(
@ -68,9 +74,14 @@ class _MediaViewSizingState extends State<MediaViewSizing> {
}
return SafeArea(
child: Container(
constraints: BoxConstraints(
maxHeight: availableHeight,
),
child: Column(
children: [imageChild, bottomNavigation],
),
),
);
}
}

View file

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/views/contact/contact_verify.view.dart';
import 'package:twonly/src/views/public_profile.view.dart';
class VerifiedShield extends StatefulWidget {
const VerifiedShield({
@ -63,7 +63,7 @@ class _VerifiedShieldState extends State<VerifiedShield> {
context,
MaterialPageRoute(
builder: (context) {
return ContactVerifyView(contact!);
return const PublicProfileView();
},
),
);

View file

@ -13,8 +13,8 @@ import 'package:twonly/src/views/components/flame.dart';
import 'package:twonly/src/views/components/max_flame_list_title.dart';
import 'package:twonly/src/views/components/select_chat_deletion_time.comp.dart';
import 'package:twonly/src/views/components/verified_shield.dart';
import 'package:twonly/src/views/contact/contact_verify.view.dart';
import 'package:twonly/src/views/groups/group.view.dart';
import 'package:twonly/src/views/public_profile.view.dart';
class ContactView extends StatefulWidget {
const ContactView(this.userId, {super.key});
@ -159,7 +159,7 @@ class _ContactViewState extends State<ContactView> {
context,
MaterialPageRoute(
builder: (context) {
return ContactVerifyView(contact);
return const PublicProfileView();
},
),
);

View file

@ -1,265 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'package:drift/drift.dart' hide Column;
import 'package:flutter/material.dart';
import 'package:flutter_zxing/flutter_zxing.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:image/image.dart' as imglib;
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:lottie/lottie.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/signal/session.signal.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/components/fingerprint_text.dart';
import 'package:twonly/src/views/contact/contact_verify_qr_scan.view.dart';
import 'package:url_launcher/url_launcher.dart';
class ContactVerifyView extends StatefulWidget {
const ContactVerifyView(this.contact, {super.key});
final Contact contact;
@override
State<ContactVerifyView> createState() => _ContactVerifyViewState();
}
// ignore: constant_identifier_names
enum ScanResult { None, Success, Failed }
class _ContactVerifyViewState extends State<ContactVerifyView> {
Fingerprint? _fingerprint;
late Contact _contact;
late StreamSubscription<Contact?> _contactSub;
ScanResult _scanResult = ScanResult.None;
Uint8List? _qrCodeImageBytes;
@override
void initState() {
super.initState();
_contact = widget.contact;
unawaited(loadAsync());
}
@override
void dispose() {
unawaited(_contactSub.cancel());
super.dispose();
}
Future<void> loadAsync() async {
_fingerprint = await generateSessionFingerPrint(widget.contact.userId);
if (_fingerprint != null) {
final result = zx.encodeBarcode(
contents: base64Encode(
_fingerprint!.scannableFingerprint.fingerprints,
),
params: EncodeParams(
width: 150,
height: 150,
),
);
if (result.isValid && result.data != null) {
final img = imglib.Image.fromBytes(
width: 150,
height: 150,
bytes: result.data!.buffer,
numChannels: 1,
);
_qrCodeImageBytes = imglib.encodePng(img);
}
}
final contact = twonlyDB.contactsDao
.getContactByUserId(widget.contact.userId)
.watchSingleOrNull();
_contactSub = contact.listen((contact) {
if (contact == null) return;
setState(() {
_contact = contact;
});
});
setState(() {});
}
Future<void> openQrScanner() async {
if (_fingerprint == null) return;
final isValid = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ContactVerifyQrScanView(
widget.contact,
fingerprint: _fingerprint!,
);
},
),
) as bool?;
if (isValid == null) {
return; // user just returned...
}
if (isValid) {
_scanResult = ScanResult.Success;
await updateUserVerifyState(true);
} else {
_scanResult = ScanResult.Failed;
await updateUserVerifyState(false);
}
setState(() {});
}
Future<void> updateUserVerifyState(bool verified) async {
final update = ContactsCompanion(verified: Value(verified));
await twonlyDB.contactsDao.updateContact(_contact.userId, update);
}
Widget get qrWidget => (_qrCodeImageBytes == null)
? const SizedBox(
width: 150,
height: 150,
)
: Image.memory(_qrCodeImageBytes!);
Widget get resultAnimation => SizedBox(
width: 150,
child: Lottie.asset(
(_scanResult == ScanResult.Success)
? 'assets/animations/success.json'
: 'assets/animations/failed.json',
repeat: false,
onLoaded: (p0) {
Future.delayed(const Duration(seconds: 3), () {
if (mounted) {
setState(() {
_scanResult = ScanResult.None;
});
}
});
},
),
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(context.lang.contactVerifyNumberTitle),
),
body: (_fingerprint == null)
? const Center(child: CircularProgressIndicator())
: ListView(
children: [
Center(
child: Padding(
padding: const EdgeInsets.all(20),
child: Container(
padding: const EdgeInsets.all(25),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Theme.of(context).colorScheme.primary,
),
child: GestureDetector(
onTap: openQrScanner,
child: Column(
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
),
padding: const EdgeInsets.symmetric(vertical: 20),
child: Column(
children: [
if (_scanResult == ScanResult.None)
qrWidget
else
resultAnimation,
const SizedBox(height: 10),
SizedBox(
width: 200,
child: Text(
(_scanResult == ScanResult.None)
? context
.lang.contactVerifyNumberTapToScan
: '',
style: const TextStyle(
color: Colors.black,
fontSize: 15,
),
textAlign: TextAlign.center,
),
),
],
),
),
const SizedBox(height: 20),
FingerprintText(
_fingerprint!.displayableFingerprint
.getDisplayText(),
),
],
),
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Text(
context.lang.contactVerifyNumberLongDesc(
getContactDisplayName(_contact),
),
textAlign: TextAlign.center,
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
child: GestureDetector(
onTap: () async {
await launchUrl(
Uri.parse(
'https://twonly.eu/en/faq/security/verify-security-number.html',
),
);
},
child: Text(
'Read more.',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
),
),
],
),
bottomNavigationBar: SafeArea(
child: Padding(
padding: const EdgeInsets.only(bottom: 60),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_contact.verified)
OutlinedButton.icon(
onPressed: () => updateUserVerifyState(false),
label:
Text(context.lang.contactVerifyNumberClearVerification),
)
else
FilledButton.icon(
icon: const FaIcon(FontAwesomeIcons.shieldHeart),
onPressed: () => updateUserVerifyState(true),
label: Text(
context.lang.contactVerifyNumberMarkAsVerified,
),
),
],
),
),
),
);
}
}

View file

@ -1,45 +0,0 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_zxing/flutter_zxing.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
class ContactVerifyQrScanView extends StatefulWidget {
const ContactVerifyQrScanView(
this.contact, {
required this.fingerprint,
super.key,
});
final Fingerprint fingerprint;
final Contact contact;
@override
State<ContactVerifyQrScanView> createState() =>
_ContactVerifyQrScanViewState();
}
class _ContactVerifyQrScanViewState extends State<ContactVerifyQrScanView> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ReaderWidget(
onScan: (result) async {
var isValid = false;
try {
if (result.text != null) {
final otherFingerPrint = base64Decode(result.text!);
isValid = widget.fingerprint.scannableFingerprint.compareTo(
otherFingerPrint,
);
}
} catch (e) {
Log.error('$e');
}
return Navigator.pop(context, isValid);
},
),
);
}
}

View file

@ -1,18 +1,29 @@
import 'dart:async';
import 'package:camera/camera.dart';
import 'dart:convert';
import 'dart:typed_data';
import 'package:app_links/app_links.dart';
import 'package:collection/collection.dart';
import 'package:drift/drift.dart' show Value;
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:screenshot/screenshot.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/services/notifications/setup.notifications.dart';
import 'package:twonly/src/services/signal/session.signal.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview.dart';
import 'package:twonly/src/views/camera/camera_preview_controller_view.dart';
import 'package:twonly/src/views/camera/camera_preview_components/camera_preview_controller_view.dart';
import 'package:twonly/src/views/camera/camera_preview_components/main_camera_controller.dart';
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
import 'package:twonly/src/views/chats/add_new_user.view.dart';
import 'package:twonly/src/views/chats/chat_list.view.dart';
import 'package:twonly/src/views/components/alert_dialog.dart';
import 'package:twonly/src/views/contact/contact.view.dart';
import 'package:twonly/src/views/memories/memories.view.dart';
import 'package:twonly/src/views/public_profile.view.dart';
void Function(int) globalUpdateOfHomeViewPageIndex = (a) {};
@ -47,7 +58,10 @@ class Shade extends StatelessWidget {
class HomeViewState extends State<HomeView> {
int activePageIdx = 0;
final MainCameraController _mainCameraController = MainCameraController();
final PageController homeViewPageController = PageController(initialPage: 1);
late StreamSubscription<Uri> _deepLinkSub;
double buttonDiameter = 100;
double offsetRatio = 0;
@ -55,11 +69,6 @@ class HomeViewState extends State<HomeView> {
double lastChange = 0;
Timer? disableCameraTimer;
bool initCameraStarted = true;
CameraController? cameraController;
ScreenshotController screenshotController = ScreenshotController();
SelectedCameraDetails selectedCameraDetails = SelectedCameraDetails();
bool onPageView(ScrollNotification notification) {
disableCameraTimer?.cancel();
@ -71,15 +80,19 @@ class HomeViewState extends State<HomeView> {
offsetRatio = offsetFromOne.abs();
});
}
if (cameraController == null && !initCameraStarted && offsetRatio < 1) {
initCameraStarted = true;
unawaited(selectCamera(selectedCameraDetails.cameraId, false));
if (_mainCameraController.cameraController == null &&
!_mainCameraController.initCameraStarted &&
offsetRatio < 1) {
unawaited(
_mainCameraController.selectCamera(
_mainCameraController.selectedCameraDetails.cameraId,
false,
),
);
}
if (offsetRatio == 1) {
disableCameraTimer = Timer(const Duration(milliseconds: 500), () async {
await cameraController?.dispose();
cameraController = null;
selectedCameraDetails = SelectedCameraDetails();
await _mainCameraController.closeCamera();
disableCameraTimer = null;
});
}
@ -89,6 +102,9 @@ class HomeViewState extends State<HomeView> {
@override
void initState() {
super.initState();
_mainCameraController.setState = () {
if (mounted) setState(() {});
};
activePageIdx = widget.initialPage;
globalUpdateOfHomeViewPageIndex = (index) {
homeViewPageController.jumpToPage(index);
@ -100,45 +116,116 @@ class HomeViewState extends State<HomeView> {
.listen((NotificationResponse? response) async {
globalUpdateOfHomeViewPageIndex(0);
});
unawaited(selectCamera(0, true));
unawaited(_mainCameraController.selectCamera(0, true));
unawaited(initAsync());
// Subscribe to all events (initial link and further)
_deepLinkSub = AppLinks().uriLinkStream.listen((uri) async {
if (!uri.scheme.startsWith('http')) return;
if (uri.host != 'me.twonly.eu') return;
if (uri.hasEmptyPath) return;
final publicKey = uri.hasFragment ? uri.fragment : null;
final userPaths = uri.path.split('/');
if (userPaths.length != 2) return;
final username = userPaths[1];
if (!mounted) return;
if (username == gUser.username) {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return const PublicProfileView();
},
),
);
return;
}
Log.info(
'Opened via deep link!: username = $username public_key = ${uri.fragment}',
);
final contacts =
await twonlyDB.contactsDao.getContactsByUsername(username);
if (contacts.isEmpty) {
if (!mounted) return;
Uint8List? publicKeyBytes;
if (publicKey != null) {
publicKeyBytes = base64Url.decode(publicKey);
}
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return AddNewUserView(
username: username,
publicKey: publicKeyBytes,
);
},
),
);
} else if (publicKey != null) {
try {
final contact = contacts.first;
final storedPublicKey = await getPublicKeyFromContact(contact.userId);
final receivedPublicKey = base64Url.decode(publicKey);
if (storedPublicKey == null ||
receivedPublicKey.isEmpty ||
!mounted) {
return;
}
if (storedPublicKey.equals(receivedPublicKey)) {
if (!contact.verified) {
final markAsVerified = await showAlertDialog(
context,
context.lang.linkFromUsername(contact.username),
context.lang.linkFromUsernameLong,
customOk: context.lang.gotLinkFromFriend,
);
if (markAsVerified) {
await twonlyDB.contactsDao.updateContact(
contact.userId,
const ContactsCompanion(
verified: Value(true),
),
);
}
} else {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ContactView(contact.userId);
},
),
);
}
} else {
await showAlertDialog(
context,
context.lang.couldNotVerifyUsername(contact.username),
context.lang.linkPubkeyDoesNotMatch,
customCancel: '',
);
}
} catch (e) {
Log.warn(e);
}
}
});
}
@override
void dispose() {
unawaited(selectNotificationStream.close());
disableCameraTimer?.cancel();
cameraController?.dispose();
_mainCameraController.closeCamera();
_deepLinkSub.cancel();
super.dispose();
}
Future<CameraController?> selectCamera(int sCameraId, bool init) async {
final opts = await initializeCameraController(
selectedCameraDetails,
sCameraId,
init,
);
if (opts != null) {
selectedCameraDetails = opts.$1;
cameraController = opts.$2;
initCameraStarted = false;
}
setState(() {});
return cameraController;
}
/// same function also in camera_send_to_view
Future<void> toggleSelectedCamera() async {
if (cameraController == null) return;
// do not allow switching camera when recording
if (cameraController!.value.isRecordingVideo) {
return;
}
await cameraController!.dispose();
cameraController = null;
await selectCamera((selectedCameraDetails.cameraId + 1) % 2, false);
}
Future<void> initAsync() async {
final notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
@ -168,13 +255,12 @@ class HomeViewState extends State<HomeView> {
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onDoubleTap: offsetRatio == 0 ? toggleSelectedCamera : null,
onDoubleTap: offsetRatio == 0
? _mainCameraController.toggleSelectedCamera
: null,
child: Stack(
children: <Widget>[
HomeViewCameraPreview(
controller: cameraController,
screenshotController: screenshotController,
),
MainCameraPreview(mainCameraController: _mainCameraController),
Shade(
opacity: offsetRatio,
),
@ -206,10 +292,7 @@ class HomeViewState extends State<HomeView> {
child: Opacity(
opacity: 1 - (offsetRatio * 4) % 1,
child: CameraPreviewControllerView(
cameraController: cameraController,
screenshotController: screenshotController,
selectedCameraDetails: selectedCameraDetails,
selectCamera: selectCamera,
mainController: _mainCameraController,
isVisible:
((1 - (offsetRatio * 4) % 1) == 1) && activePageIdx == 1,
),

View file

@ -0,0 +1,129 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:share_plus/share_plus.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/utils/avatars.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/qr.dart';
import 'package:twonly/src/views/camera/camera_qr_scanner.view.dart';
import 'package:twonly/src/views/components/better_list_title.dart';
class PublicProfileView extends StatefulWidget {
const PublicProfileView({super.key});
@override
State<PublicProfileView> createState() => _PublicProfileViewState();
}
class _PublicProfileViewState extends State<PublicProfileView> {
Uint8List? _qrCode;
Uint8List? _userAvatar;
Uint8List? _publicKey;
@override
void initState() {
initAsync();
super.initState();
}
Future<void> initAsync() async {
_qrCode = await getProfileQrCodeData();
_userAvatar = await getUserAvatar();
_publicKey = await getUserPublicKey();
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Container(width: double.infinity),
const SizedBox(
height: 30,
),
if (_qrCode != null && _userAvatar != null)
Container(
decoration: BoxDecoration(
color: context.color.primary,
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 6,
offset: Offset(0, 2),
),
],
),
child: QrImageView.withQr(
qr: QrCode.fromUint8List(
data: _qrCode!,
errorCorrectLevel: QrErrorCorrectLevel.M,
),
eyeStyle: QrEyeStyle(
color: isDarkMode(context) ? Colors.black : Colors.white,
borderRadius: 2,
),
dataModuleStyle: QrDataModuleStyle(
color: isDarkMode(context) ? Colors.black : Colors.white,
borderRadius: 2,
),
gapless: false,
embeddedImage: MemoryImage(_userAvatar!),
embeddedImageStyle: QrEmbeddedImageStyle(
size: const Size(60, 66),
embeddedImageShape: EmbeddedImageShape.square,
shapeColor: context.color.primary,
safeArea: true,
),
size: 250,
),
),
const SizedBox(height: 20),
Text(
gUser.username,
style: const TextStyle(fontSize: 24),
),
const SizedBox(height: 20),
const Divider(),
const SizedBox(height: 20),
BetterListTile(
leading: const FaIcon(FontAwesomeIcons.qrcode),
text: context.lang.scanOtherProfile,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const QrCodeScanner(),
),
);
},
),
BetterListTile(
leading: const FaIcon(
FontAwesomeIcons.shareFromSquare,
size: 18,
),
text: context.lang.shareYourProfile,
subtitle: (_publicKey == null)
? null
: Text('https://me.twonly.eu/${gUser.username}'),
onTap: () {
final params = ShareParams(
text:
'https://me.twonly.eu/${gUser.username}#${base64Url.encode(_publicKey!)}',
);
SharePlus.instance.share(params);
},
),
],
),
);
}
}

View file

@ -221,6 +221,21 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
),
),
),
const SizedBox(height: 12),
GestureDetector(
onTap: () {
if (widget.callBack != null) {
widget.callBack!();
} else {
Navigator.pop(context);
}
},
child: Text(
context.lang.skipForNow,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 8, color: Colors.grey),
),
),
],
),
),

View file

@ -1,6 +1,7 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/settings/developer/automated_testing.view.dart';
import 'package:twonly/src/views/settings/developer/retransmission_data.view.dart';
@ -13,20 +14,9 @@ class DeveloperSettingsView extends StatefulWidget {
}
class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
bool isDeveloper = true;
@override
void initState() {
super.initState();
unawaited(initAsync());
}
Future<void> initAsync() async {
final user = await getUser();
if (user == null) return;
setState(() {
isDeveloper = user.isDeveloper;
});
}
Future<void> toggleDeveloperSettings() async {
@ -34,7 +24,15 @@ class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
u.isDeveloper = !u.isDeveloper;
return u;
});
await initAsync();
setState(() {});
}
Future<void> toggleVideoCompression() async {
await updateUserdata((u) {
u.disableVideoCompression = !u.disableVideoCompression;
return u;
});
setState(() {});
}
@override
@ -49,7 +47,7 @@ class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
title: const Text('Show Developer Settings'),
onTap: toggleDeveloperSettings,
trailing: Switch(
value: isDeveloper,
value: gUser.isDeveloper,
onChanged: (a) => toggleDeveloperSettings(),
),
),
@ -66,14 +64,17 @@ class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
);
},
),
// if (!kReleaseMode)
// ListTile(
// title: const Text('FlameSync Test'),
// onTap: () async {
// await twonlyDB.contactsDao.modifyFlameCounterForTesting();
// await syncFlameCounters();
// },
// ),
ListTile(
title: const Text('Disable ffmpeg'),
subtitle: const Text(
'If your smartphone crashes, you can disable ffmpeg. This will prevent your videos from being compressed and NO FILTER will be applied to the video! This is a workaround, until the root-cause in ffmpeg is found.',
),
onTap: toggleVideoCompression,
trailing: Switch(
value: gUser.disableVideoCompression,
onChanged: (a) => toggleVideoCompression(),
),
),
if (!kReleaseMode)
ListTile(
title: const Text('Automated Testing'),

View file

@ -62,26 +62,26 @@ class _HelpViewState extends State<HelpView> {
);
},
),
ListTile(
title: Text(context.lang.settingsResetTutorials),
subtitle: Text(
context.lang.settingsResetTutorialsDesc,
style: const TextStyle(fontSize: 12),
),
onTap: () async {
await updateUserdata((user) {
user.tutorialDisplayed = [];
return user;
});
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(context.lang.settingsResetTutorialsSuccess),
duration: const Duration(seconds: 3),
),
);
},
),
// ListTile(
// title: Text(context.lang.settingsResetTutorials),
// subtitle: Text(
// context.lang.settingsResetTutorialsDesc,
// style: const TextStyle(fontSize: 12),
// ),
// onTap: () async {
// await updateUserdata((user) {
// user.tutorialDisplayed = [];
// return user;
// });
// if (!context.mounted) return;
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(context.lang.settingsResetTutorialsSuccess),
// duration: const Duration(seconds: 3),
// ),
// );
// },
// ),
const Divider(),
ListTile(
title: Text(context.lang.allowErrorTracking),

View file

@ -1,114 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart';
Future<void> showTutorial(
BuildContext context,
List<TargetFocus> targets,
) async {
final completer = Completer<dynamic>();
TutorialCoachMark(
targets: targets,
colorShadow: context.color.primary,
textSkip: context.lang.ok,
alignSkip: Alignment.bottomCenter,
textStyleSkip: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20,
),
onSkip: () {
completer.complete();
return true;
},
onFinish: () {
completer.complete();
},
).show(context: context);
await completer.future;
}
Future<bool> checkIfTutorialAlreadyShown(String tutorialId) async {
final user = await getUser();
if (user == null) return true;
user.tutorialDisplayed ??= [];
if (user.tutorialDisplayed!.contains(tutorialId)) {
return true;
}
user.tutorialDisplayed!.add(tutorialId);
await updateUserdata((u) {
u.tutorialDisplayed = user.tutorialDisplayed;
return u;
});
return false;
}
TargetFocus getTargetFocus(
BuildContext context,
GlobalKey key,
String title,
String body,
) {
final renderBox = key.currentContext!.findRenderObject()! as RenderBox;
final position = renderBox.localToGlobal(Offset.zero);
final screenHeight = MediaQuery.of(context).size.height;
final centerY = screenHeight / 2;
double top = 0;
double bottom = 0;
if (position.dy < centerY) {
bottom = 0;
top = position.dy;
} else {
bottom = centerY;
top = 0;
}
return TargetFocus(
identify: title,
keyTarget: key,
contents: [
TargetContent(
align: ContentAlign.custom,
customPosition: CustomTargetContentPosition(
left: 0,
right: 0,
top: top,
bottom: bottom,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 20,
),
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Text(
body,
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
),
),
),
],
),
),
],
);
}

View file

@ -1,91 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mutex/mutex.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/tutorial/show_tutorial.dart';
final lockDisplayTutorial = Mutex();
Future<void> showChatListTutorialSearchOtherUsers(
BuildContext context,
GlobalKey searchForOtherUsers,
) async {
await lockDisplayTutorial.protect(() async {
if (await checkIfTutorialAlreadyShown('chat_list:search_users')) {
return;
}
if (!context.mounted) return;
final targets = <TargetFocus>[
getTargetFocus(
context,
searchForOtherUsers,
context.lang.tutorialChatListSearchUsersTitle,
context.lang.tutorialChatListSearchUsersDesc,
),
];
await showTutorial(context, targets);
});
}
Future<void> showChatListTutorialContextMenu(
BuildContext context,
GlobalKey firstUserListItemKey,
) async {
await lockDisplayTutorial.protect(() async {
if (await checkIfTutorialAlreadyShown('chat_list:context_menu')) {
return;
}
if (!context.mounted) return;
final targets = <TargetFocus>[
getTargetFocus(
context,
firstUserListItemKey,
context.lang.tutorialChatListContextMenuTitle,
context.lang.tutorialChatListContextMenuDesc,
),
];
await showTutorial(context, targets);
});
}
Future<void> showVerifyShieldTutorial(
BuildContext context,
GlobalKey firstUserListItemKey,
) async {
await lockDisplayTutorial.protect(() async {
if (await checkIfTutorialAlreadyShown('chat_messages:verify_shield')) {
return;
}
if (!context.mounted) return;
final targets = <TargetFocus>[
getTargetFocus(
context,
firstUserListItemKey,
context.lang.tutorialChatMessagesVerifyShieldTitle,
context.lang.tutorialChatMessagesVerifyShieldDesc,
),
];
await showTutorial(context, targets);
});
}
Future<void> showReopenMediaFilesTutorial(
BuildContext context,
GlobalKey firstUserListItemKey,
) async {
await lockDisplayTutorial.protect(() async {
if (await checkIfTutorialAlreadyShown('chat_messages:reopen_message')) {
return;
}
if (!context.mounted) return;
final targets = <TargetFocus>[
getTargetFocus(
context,
firstUserListItemKey,
context.lang.tutorialChatMessagesReopenMessageTitle,
context.lang.tutorialChatMessagesReopenMessageDesc,
),
];
await showTutorial(context, targets);
});
}

View file

@ -18,12 +18,11 @@ packages:
source: hosted
version: "1.3.64"
adaptive_number:
dependency: transitive
dependency: "direct overridden"
description:
name: adaptive_number
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
url: "https://pub.dev"
source: hosted
path: "dependencies/adaptive_number"
relative: true
source: path
version: "1.0.0"
analyzer:
dependency: transitive
@ -33,6 +32,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.4.1"
app_links:
dependency: "direct main"
description:
name: app_links
sha256: "3462d9defc61565fde4944858b59bec5be2b9d5b05f20aed190adb3ad08a7abc"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
app_links_linux:
dependency: transitive
description:
name: app_links_linux
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
url: "https://pub.dev"
source: hosted
version: "1.0.3"
app_links_platform_interface:
dependency: transitive
description:
name: app_links_platform_interface
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
app_links_web:
dependency: transitive
description:
name: app_links_web
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
url: "https://pub.dev"
source: hosted
version: "1.0.4"
archive:
dependency: "direct main"
description:
@ -173,11 +204,11 @@ packages:
dependency: "direct overridden"
description:
path: "packages/camera/camera_android_camerax"
ref: aef58af205a5f3ce6588a5c59bb2e734aab943f0
resolved-ref: aef58af205a5f3ce6588a5c59bb2e734aab943f0
ref: "43b87faec960306f98d767253b9bf2cee61be630"
resolved-ref: "43b87faec960306f98d767253b9bf2cee61be630"
url: "https://github.com/otsmr/flutter-packages.git"
source: git
version: "0.6.23+2"
version: "0.6.25+1"
camera_avfoundation:
dependency: transitive
description:
@ -275,7 +306,7 @@ packages:
source: hosted
version: "2.0.1"
convert:
dependency: transitive
dependency: "direct main"
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
@ -291,7 +322,7 @@ packages:
source: hosted
version: "0.3.5"
crypto:
dependency: transitive
dependency: "direct main"
description:
name: crypto
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
@ -355,12 +386,11 @@ packages:
source: hosted
version: "7.0.3"
dots_indicator:
dependency: transitive
dependency: "direct overridden"
description:
name: dots_indicator
sha256: c070af5058a084ba7b354df4b4c26c719595d70a3531eea6edd8af8716684ba3
url: "https://pub.dev"
source: hosted
path: "dependencies/dots_indicator"
relative: true
source: path
version: "4.0.1"
drift:
dependency: "direct main"
@ -387,12 +417,11 @@ packages:
source: hosted
version: "0.2.7"
ed25519_edwards:
dependency: transitive
dependency: "direct overridden"
description:
name: ed25519_edwards
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
url: "https://pub.dev"
source: hosted
path: "dependencies/ed25519_edwards"
relative: true
source: path
version: "0.3.1"
emoji_picker_flutter:
dependency: "direct main"
@ -786,13 +815,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_zxing:
dependency: "direct main"
description:
path: "dependencies/flutter_zxing"
relative: true
source: path
version: "2.1.0"
font_awesome_flutter:
dependency: "direct main"
description:
@ -825,6 +847,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.3"
google_mlkit_barcode_scanning:
dependency: "direct main"
description:
name: google_mlkit_barcode_scanning
sha256: b38505df2d3fdf7830979d60fee55039c2f442d189b2e06fcb2fe494ba65d0db
url: "https://pub.dev"
source: hosted
version: "0.14.1"
google_mlkit_commons:
dependency: transitive
description:
name: google_mlkit_commons
sha256: "8f40fbac10685cad4715d11e6a0d86837d9ad7168684dfcad29610282a88e67a"
url: "https://pub.dev"
source: hosted
version: "0.11.0"
graphs:
dependency: transitive
description:
@ -833,6 +871,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
gtk:
dependency: transitive
description:
name: gtk
sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c
url: "https://pub.dev"
source: hosted
version: "2.1.0"
hand_signature:
dependency: "direct main"
description:
@ -844,18 +890,16 @@ packages:
hashlib:
dependency: "direct main"
description:
name: hashlib
sha256: "408af9bfb16289d433822635f0b6890e4440b74fe7acd40014983abeef6d33f0"
url: "https://pub.dev"
source: hosted
path: "dependencies/hashlib"
relative: true
source: path
version: "2.2.0"
hashlib_codecs:
dependency: transitive
dependency: "direct overridden"
description:
name: hashlib_codecs
sha256: "0e1a17c47792fd131a9bf49b811c394b22516287746ee14cd0b0c22a34136699"
url: "https://pub.dev"
source: hosted
path: "dependencies/hashlib_codecs"
relative: true
source: path
version: "3.0.1"
html:
dependency: transitive
@ -972,10 +1016,9 @@ packages:
introduction_screen:
dependency: "direct main"
description:
name: introduction_screen
sha256: "47ad51281f86c3ed47e0c1a0008899ad253ca71e8b626fd862e55993825a271b"
url: "https://pub.dev"
source: hosted
path: "dependencies/introduction_screen"
relative: true
source: path
version: "4.0.0"
io:
dependency: transitive
@ -1044,10 +1087,9 @@ packages:
libsignal_protocol_dart:
dependency: "direct main"
description:
name: libsignal_protocol_dart
sha256: "2b18de43016474ab85d21553a88f59d6f4fea8c2eddf35be7e24ab5f8969a81d"
url: "https://pub.dev"
source: hosted
path: "dependencies/libsignal_protocol_dart"
relative: true
source: path
version: "0.7.4"
lints:
dependency: transitive
@ -1108,10 +1150,9 @@ packages:
lottie:
dependency: "direct main"
description:
name: lottie
sha256: "8ae0be46dbd9e19641791dc12ee480d34e1fd3f84c749adc05f3ad9342b71b95"
url: "https://pub.dev"
source: hosted
path: "dependencies/lottie"
relative: true
source: path
version: "3.3.2"
matcher:
dependency: transitive
@ -1130,7 +1171,7 @@ packages:
source: hosted
version: "0.11.1"
meta:
dependency: transitive
dependency: "direct main"
description:
name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
@ -1148,10 +1189,9 @@ packages:
mutex:
dependency: "direct main"
description:
name: mutex
sha256: "8827da25de792088eb33e572115a5eb0d61d61a3c01acbc8bcbe76ed78f1a1f2"
url: "https://pub.dev"
source: hosted
path: "dependencies/mutex"
relative: true
source: path
version: "3.1.0"
nested:
dependency: transitive
@ -1194,12 +1234,11 @@ packages:
source: hosted
version: "2.1.0"
optional:
dependency: transitive
dependency: "direct overridden"
description:
name: optional
sha256: f80327d7a3335a0be68418072668043c7ab291df575c21aa42e0c5633641da39
url: "https://pub.dev"
source: hosted
path: "dependencies/optional"
relative: true
source: path
version: "6.1.0+1"
package_config:
dependency: transitive
@ -1348,10 +1387,9 @@ packages:
photo_view:
dependency: "direct main"
description:
name: photo_view
sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e"
url: "https://pub.dev"
source: hosted
path: "dependencies/photo_view"
relative: true
source: path
version: "0.15.0"
platform:
dependency: transitive
@ -1370,12 +1408,11 @@ packages:
source: hosted
version: "2.1.8"
pointycastle:
dependency: transitive
dependency: "direct overridden"
description:
name: pointycastle
sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5"
url: "https://pub.dev"
source: hosted
path: "dependencies/pointycastle"
relative: true
source: path
version: "4.0.0"
pool:
dependency: transitive
@ -1425,6 +1462,20 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.5.0"
qr:
dependency: "direct overridden"
description:
path: "dependencies/qr"
relative: true
source: path
version: "3.1.0-wip"
qr_flutter:
dependency: "direct main"
description:
path: "dependencies/qr_flutter"
relative: true
source: path
version: "4.1.0"
recase:
dependency: transitive
description:
@ -1726,14 +1777,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.10.1"
tutorial_coach_mark:
dependency: "direct main"
description:
name: tutorial_coach_mark
sha256: "5a325d53bcf16ce7a969e2ab8d4dc9610f39ee3eab2b3cc57d5c98936129b891"
url: "https://pub.dev"
source: hosted
version: "1.3.3"
typed_data:
dependency: transitive
description:
@ -1951,12 +1994,11 @@ packages:
source: hosted
version: "2.1.0"
x25519:
dependency: transitive
dependency: "direct overridden"
description:
name: x25519
sha256: cec3c125f0d934dccba6c4cab48f3fbf866dc78895dcc5a1584d35b0a845005b
url: "https://pub.dev"
source: hosted
path: "dependencies/x25519"
relative: true
source: path
version: "0.1.1"
xdg_directories:
dependency: transitive
@ -1983,5 +2025,5 @@ packages:
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.9.0 <4.0.0"
flutter: ">=3.35.0"
dart: ">=3.10.0 <4.0.0"
flutter: ">=3.38.1"

View file

@ -9,83 +9,134 @@ environment:
sdk: ^3.6.0
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# Trusted published dart.dev or tools.dart.dev
collection: ^1.18.0
fixnum: ^1.1.1
meta: ^1.17.0
http: ^1.3.0
intl: ^0.20.2
path: ^1.9.0
logging: ^1.3.0
web_socket_channel: ^3.0.1
convert: ^3.1.2
crypto: ^3.0.7
# Trusted publisher flutter.dev
camera: ^0.11.2
flutter_svg: ^2.0.17
image_picker: ^1.1.2
local_auth: ^3.0.0
path_provider: ^2.1.5
url_launcher: ^6.3.2
vector_graphics: ^1.1.19
video_player: ^2.10.1
# Trusted publisher fluttercommunity.dev
connectivity_plus: ^7.0.0
device_info_plus: ^12.1.0
font_awesome_flutter: ^10.10.0
share_plus: ^12.0.0
package_info_plus: ^9.0.0
# Trustworthy publishers
firebase_core: ^4.2.0 # firebase.google.com
firebase_messaging: ^16.0.3 # firebase.google.com
json_annotation: ^4.9.0 # google.dev
protobuf: ^4.0.0 # google.dev
scrollable_positioned_list: ^0.3.8 # google.dev
# Not yet checked
archive: ^4.0.7
audio_waveforms: ^2.0.0
avatar_maker: ^0.4.0
background_downloader: ^9.4.0
cached_network_image: ^3.4.1
camera: ^0.11.2
collection: ^1.18.0
connectivity_plus: ^7.0.0
cryptography_flutter_plus: ^2.3.4
cryptography_plus: ^2.7.0
device_info_plus: ^12.1.0
drift: ^2.25.1
drift_flutter: ^0.2.4
emoji_picker_flutter: ^4.3.0
ffmpeg_kit_flutter_new: ^4.1.0
file_picker: ^10.3.6
firebase_core: ^4.2.0
firebase_messaging: ^16.0.3
fixnum: ^1.1.1
flutter:
sdk: flutter
flutter_android_volume_keydown: ^1.0.1
flutter_image_compress: ^2.4.0
flutter_local_notifications: ^19.1.0
flutter_localizations:
sdk: flutter
flutter_secure_storage:
git:
url: https://github.com/juliansteenbakker/flutter_secure_storage.git
ref: a06ead81809c900e7fc421a30db0adf3b5919139 # from develop
path: flutter_secure_storage/
flutter_svg: ^2.0.17
flutter_volume_controller: ^1.3.4
flutter_zxing:
path: ./dependencies/flutter_zxing
font_awesome_flutter: ^10.10.0
gal: ^2.3.1
get: ^4.7.2
google_mlkit_barcode_scanning: ^0.14.1
hand_signature: ^3.0.3
hashlib: ^2.0.0
http: ^1.3.0
image: ^4.3.0
image_picker: ^1.1.2
intl: ^0.20.2
introduction_screen: ^4.0.0
json_annotation: ^4.9.0
libsignal_protocol_dart: ^0.7.4
local_auth: ^3.0.0
logging: ^1.3.0
lottie: ^3.3.1
mutex: ^3.1.0
no_screenshot: ^0.3.1
package_info_plus: ^9.0.0
path: ^1.9.0
path_provider: ^2.1.5
permission_handler: ^12.0.0+1
photo_view: ^0.15.0
protobuf: ^4.0.0
provider: ^6.1.2
restart_app: ^1.3.2
screenshot: ^3.0.0
scrollable_positioned_list: ^0.3.8
sentry_flutter: ^9.8.0
share_plus: ^12.0.0
tutorial_coach_mark: ^1.3.0
url_launcher: ^6.3.2
vector_graphics: ^1.1.19
video_player: ^2.10.1
web_socket_channel: ^3.0.1
# Overwritten by self-controlled repository
emoji_picker_flutter: ^4.3.0
# Packages which got overwritten using the twonly-app-dependencies repository
photo_view: ^0.15.0
hashlib: ^2.0.0
libsignal_protocol_dart: ^0.7.4
lottie: ^3.3.1
mutex: ^3.1.0
introduction_screen: ^4.0.0
qr_flutter: ^4.1.0
app_links: ^7.0.0
dependency_overrides:
dots_indicator:
path: ./dependencies/dots_indicator
hashlib:
path: ./dependencies/hashlib
introduction_screen:
path: ./dependencies/introduction_screen
libsignal_protocol_dart:
path: ./dependencies/libsignal_protocol_dart
lottie:
path: ./dependencies/lottie
mutex:
path: ./dependencies/mutex
photo_view:
path: ./dependencies/photo_view
qr:
path: ./dependencies/qr
adaptive_number:
path: ./dependencies/adaptive_number
ed25519_edwards:
path: ./dependencies/ed25519_edwards
hashlib_codecs:
path: ./dependencies/hashlib_codecs
optional:
path: ./dependencies/optional
pointycastle:
path: ./dependencies/pointycastle
x25519:
path: ./dependencies/x25519
qr_flutter:
path: ./dependencies/qr_flutter
camera_android_camerax:
# path: ../flutter-packages/packages/camera/camera_android_camerax
git:
url: https://github.com/otsmr/flutter-packages.git
path: packages/camera/camera_android_camerax
ref: aef58af205a5f3ce6588a5c59bb2e734aab943f0
ref: 43b87faec960306f98d767253b9bf2cee61be630
emoji_picker_flutter:
# Fixes the issue with recent emojis (solved by https://github.com/Fintasys/emoji_picker_flutter/pull/238)
# Using override until this gets merged.

View file

@ -14,6 +14,7 @@ CLIENT_DIR="./lib/src/model/protobuf/client/"
protoc --proto_path="$CLIENT_DIR" --dart_out="$GENERATED_DIR" "backup.proto"
protoc --proto_path="$CLIENT_DIR" --dart_out="$GENERATED_DIR" "messages.proto"
protoc --proto_path="$CLIENT_DIR" --dart_out="$GENERATED_DIR" "groups.proto"
protoc --proto_path="$CLIENT_DIR" --dart_out="$GENERATED_DIR" "qr.proto"
protoc --proto_path="$CLIENT_DIR" --dart_out="$GENERATED_DIR" "push_notification.proto"
protoc --proto_path="$CLIENT_DIR" --swift_out="./ios/NotificationService/" "push_notification.proto"

View file

@ -57,9 +57,16 @@ void main() {
'00000000-1234-5678-0000-00000abcdef0',
);
});
test('Reject values > 0x7fffffff', () {
expect(() => getUUIDforDirectChat(0x80000000, 0), throwsArgumentError);
test('Arbitrary within 32-bit range', () {
expect(
// ignore: avoid_js_rounded_ints
getUUIDforDirectChat(0x7dc8a4f20a75de46, 0x7ffffffffffffff8),
'7fffffff-ffff-fff8-7dc8-a4f20a75de46',
);
});
// test('Reject values > 0x7fffffff', () {
// expect(() => getUUIDforDirectChat(0x80000000, 0), throwsArgumentError);
// });
});
}