Merge pull request #293 from twonlyapp/dev

This release adds group support with multiple admins, richer media controls (editing, embedding, longer videos, audio removal), new input options (volume-button image capture, improved emoji picker), better video compression and UI enhancements.

New features

- Support for groups with multiple administrators
- Edit and delete messages
- Create images using volume buttons
- New and improved emoji picker
- Removing audio after recording is possible
- Edited image is now embedded into the video
- Video max length increased to 60 seconds
- Switched to FFmpeg for improved video compression
- New context menu and other UI enhancements

Technical changes

- Client-to-client protocol migrated to Protocol Buffers (Protobuf)
- Database identifiers converted to UUIDs and the database schema completely redesigned
- Improved reliability of client-to-client messaging
- Multiple bug fixes
This commit is contained in:
Tobi 2025-11-08 15:08:41 +01:00 committed by GitHub
commit 58fbd94130
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
243 changed files with 35298 additions and 8583 deletions

6
.gitmodules vendored
View file

@ -1,9 +1,3 @@
[submodule "dependencies/flutter_secure_storage"]
path = dependencies/flutter_secure_storage
url = https://github.com/juliansteenbakker/flutter_secure_storage
[submodule "dependencies/flutter_zxing"]
path = dependencies/flutter_zxing
url = https://github.com/khoren93/flutter_zxing.git
[submodule "dependencies/flutter-pie-menu"]
path = dependencies/flutter-pie-menu
url = https://github.com/otsmr/flutter-pie-menu.git

30
.metadata Normal file
View file

@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: macos
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View file

@ -1,5 +1,22 @@
# Changelog
## 0.0.62
- Support for groups with multiple administrators
- Edit and delete messages
- Create images using volume buttons
- New and improved emoji picker
- Removing audio after recording is possible
- Edited image is now embedded into the video
- Video max length increased to 60 seconds
- Switched to FFmpeg for improved video compression
- New context menu and other UI enhancements
- Client-to-client protocol migrated to Protocol Buffers (Protobuf)
- Database identifiers converted to UUIDs and the database schema completely redesigned
- Improved reliability of client-to-client messaging
- Multiple bug fixes
## 0.0.61
- Improving image editor when changing colors

View file

@ -8,15 +8,17 @@ This repository contains the complete source code of the [twonly](https://twonly
- Offer a Snapchat™ like experience
- End-to-End encryption using the [Signal Protocol](https://de.wikipedia.org/wiki/Signal-Protokoll)
- twonly is Open Source and can be downloaded directly from GitHub
- Developed by humans not by AI or Vibe Coding
- No email or phone number required to register
- Privacy friendly - Everything is stored on the device
- The backend is hosted exclusively in Europe
## In work
## Planned
- For Android: Using [UnifiedPush](https://unifiedpush.org/) instead of FCM
- For Android: Reproducible Builds + Publishing on Github/F-Droid
- For Android: Optional support for [UnifiedPush](https://unifiedpush.org/)
- For Android: Reproducible Builds
- Implementing [Sealed Sender](https://signal.org/blog/sealed-sender/) to minimize metadata
- Maybe: Switching from the Signal Protocol to [MLS](https://openmls.tech/).
## Security Issues
If you discover a security issue in twonly, please adhere to the coordinated vulnerability disclosure model. Please send
@ -33,8 +35,6 @@ guarantee a bounty currently :/
Some dependencies are downloaded directly from the source as there are some new changes which are not yet published on
pub.dev or because they require some special installation.
- `flutter_secure_storage`: We need the 10.0.0-beta version, but this version has some issues which are fixed but [not yet published](https://github.com/juliansteenbakker/flutter_secure_storage/issues/866):
```bash
git submodule update --init --recursive

View file

@ -55,6 +55,9 @@ android {
debug {
applicationIdSuffix ".testing"
}
// profile {
// applicationIdSuffix ".STOP"
// }
release {
signingConfig signingConfigs.release
}

View file

@ -1,5 +1,21 @@
package eu.twonly
import io.flutter.embedding.android.FlutterFragmentActivity
import android.view.KeyEvent
import dev.darttools.flutter_android_volume_keydown.FlutterAndroidVolumeKeydownPlugin.eventSink
import android.view.KeyEvent.KEYCODE_VOLUME_DOWN
import android.view.KeyEvent.KEYCODE_VOLUME_UP
class MainActivity: FlutterFragmentActivity()
class MainActivity : FlutterFragmentActivity() {
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KEYCODE_VOLUME_DOWN && eventSink != null) {
eventSink!!.success(true)
return true
}
if (keyCode == KEYCODE_VOLUME_UP && eventSink != null) {
eventSink!!.success(false)
return true
}
return super.onKeyDown(keyCode, event)
}
}

View file

@ -6,4 +6,6 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA"/>
<application android:usesCleartextTraffic="true" >
</application>
</manifest>

View file

@ -10,4 +10,5 @@ targets:
drift_dev:
options:
databases:
twonly_database: lib/src/database/twonly_database.dart
twonly_db: lib/src/database/twonly.db.dart
twonly_database: lib/src/database/twonly_database_old.dart

@ -1 +0,0 @@
Subproject commit 22df3f2ab9ad71db60526668578a5309b3cc84ef

@ -1 +0,0 @@
Subproject commit 71b75a36f35f2ce945998e20c6c6aa1820babfc6

View file

@ -35,6 +35,7 @@ class NotificationService: UNNotificationServiceExtension {
bestAttemptContent.body = data!.body
bestAttemptContent.threadIdentifier = String(format: "%d", data!.notificationId)
} else {
NSLog("Could not decrypt message. Show default.")
bestAttemptContent.title = "\(bestAttemptContent.title)"
}
@ -81,8 +82,9 @@ func getPushNotificationData(pushData: String) -> (
key: pushKey.key, pushData: pushData)
if pushNotification != nil {
pushUser = tryPushUser
if pushNotification!.messageID <= pushUser!.lastMessageID {
return ("blocked", "blocked", 0)
if isUUIDNewer(pushUser!.lastMessageID, pushNotification!.messageID)
{
//return ("blocked", "blocked", 0)
}
break
}
@ -107,11 +109,12 @@ func getPushNotificationData(pushData: String) -> (
} else if pushUser != nil {
return (
pushUser!.displayName,
getPushNotificationText(pushNotification: pushNotification), pushUser!.userID
getPushNotificationText(pushNotification: pushNotification).0, pushUser!.userID
)
} else {
let content = getPushNotificationText(pushNotification: pushNotification)
return (
"", getPushNotificationTextWithoutUserId(pushKind: pushNotification.kind), 1
content.1, content.0, 1
)
}
@ -125,6 +128,16 @@ func getPushNotificationData(pushData: String) -> (
}
}
func isUUIDNewer(_ uuid1: String, _ uuid2: String) -> Bool {
guard uuid1.count >= 8, uuid2.count >= 8 else { return true }
let hex1 = String(uuid1.prefix(8))
let hex2 = String(uuid2.prefix(8))
guard let timestamp1 = UInt32(hex1, radix: 16),
let timestamp2 = UInt32(hex2, radix: 16)
else { return true }
return timestamp1 > timestamp2
}
func tryDecryptMessage(key: Data, pushData: EncryptedPushNotification) -> PushNotification? {
do {
@ -152,8 +165,8 @@ func tryDecryptMessage(key: Data, pushData: EncryptedPushNotification) -> PushNo
func getPushUsers() -> [PushUser]? {
// Retrieve the data from secure storage (Keychain)
guard let pushUsersB64 = readFromKeychain(key: "receiving_push_keys") else {
NSLog("No data found for key: receiving_push_keys")
guard let pushUsersB64 = readFromKeychain(key: "push_keys_receiving") else {
NSLog("No data found for key: push_keys_receiving")
return nil
}
guard let pushUsersBytes = Data(base64Encoded: pushUsersB64) else {
@ -192,100 +205,66 @@ func readFromKeychain(key: String) -> String? {
return nil
}
func getPushNotificationText(pushNotification: PushNotification) -> String {
func getPushNotificationText(pushNotification: PushNotification) -> (String, String) {
let systemLanguage = Locale.current.language.languageCode?.identifier ?? "en" // Get the current system language
var pushNotificationText: [PushKind: String] = [:]
var title = "Someone"
// Define the messages based on the system language
if systemLanguage.contains("de") { // German
title = "Jemand"
pushNotificationText = [
.text: "hat dir eine Nachricht gesendet.",
.twonly: "hat dir ein twonly gesendet.",
.video: "hat dir ein Video gesendet.",
.image: "hat dir ein Bild gesendet.",
.text: "hat eine Nachricht{inGroup} gesendet.",
.twonly: "hat ein twonly{inGroup} gesendet.",
.video: "hat ein Video{inGroup} gesendet.",
.image: "hat ein Bild{inGroup} gesendet.",
.audio: "hat eine Sprachnachricht{inGroup} gesendet.",
.contactRequest: "möchte sich mit dir vernetzen.",
.acceptRequest: "ist jetzt mit dir vernetzt.",
.storedMediaFile: "hat dein Bild gespeichert.",
.reaction: "hat auf dein Bild reagiert.",
.testNotification: "Das ist eine Testbenachrichtigung.",
.reopenedMedia: "hat dein Bild erneut geöffnet.",
.reactionToVideo: "hat mit {{reaction}} auf dein Video reagiert.",
.reactionToText: "hat mit {{reaction}} auf deinen Text reagiert.",
.reactionToImage: "hat mit {{reaction}} auf dein Bild reagiert.",
.response: "hat dir geantwortet.",
.reactionToVideo: "hat mit {{content}} auf dein Video reagiert.",
.reactionToText: "hat mit {{content}} auf deinen Text reagiert.",
.reactionToImage: "hat mit {{content}} auf dein Bild reagiert.",
.reactionToAudio: "hat mit {{content}} auf deine Sprachnachricht reagiert.",
.response: "hat dir{inGroup} geantwortet.",
.addedToGroup: "hat dich zu \"{{content}}\" hinzugefügt.",
]
} else { // Default to English
pushNotificationText = [
.text: "has sent you a message.",
.twonly: "has sent you a twonly.",
.video: "has sent you a video.",
.image: "has sent you an image.",
.text: "sent a message{inGroup}.",
.twonly: "sent a twonly{inGroup}.",
.video: "sent a video{inGroup}.",
.image: "sent a image{inGroup}.",
.audio: "sent a voice message{inGroup}.",
.contactRequest: "wants to connect with you.",
.acceptRequest: "is now connected with you.",
.storedMediaFile: "has stored your image.",
.reaction: "has reacted to your image.",
.testNotification: "This is a test notification.",
.reopenedMedia: "has reopened your image.",
.reactionToVideo: "has reacted with {{reaction}} to your video.",
.reactionToText: "has reacted with {{reaction}} to your text.",
.reactionToImage: "has reacted with {{reaction}} to your image.",
.response: "has responded.",
.reactionToVideo: "has reacted with {{content}} to your video.",
.reactionToText: "has reacted with {{content}} to your text.",
.reactionToImage: "has reacted with {{content}} to your image.",
.reactionToAudio: "has reacted with {{content}} to your voice message.",
.response: "has responded{inGroup}.",
.addedToGroup: "has added you to \"{{content}}\"",
]
}
var content = pushNotificationText[pushNotification.kind] ?? ""
if pushNotification.hasReactionContent {
content.replace("{{reaction}}", with: pushNotification.reactionContent)
if pushNotification.hasAdditionalContent {
content.replace("{{content}}", with: pushNotification.additionalContent)
content.replace("{inGroup}", with: " in {inGroup}")
content.replace("{inGroup}", with: pushNotification.additionalContent)
} else {
content.replace("{inGroup}", with: "")
}
// Return the corresponding message or an empty string if not found
return content
}
func getPushNotificationTextWithoutUserId(pushKind: PushKind) -> String {
let systemLanguage = Locale.current.language.languageCode?.identifier ?? "en" // Get the current system language
var pushNotificationText: [PushKind: String] = [:]
// Define the messages based on the system language
if systemLanguage.contains("de") { // German
pushNotificationText = [
.text: "Du hast eine Nachricht erhalten.",
.twonly: "Du hast ein twonly erhalten.",
.video: "Du hast ein Video erhalten.",
.image: "Du hast ein Bild erhalten.",
.contactRequest: "Du hast eine Kontaktanfrage erhalten.",
.acceptRequest: "Deine Kontaktanfrage wurde angenommen.",
.storedMediaFile: "Dein Bild wurde gespeichert.",
.reaction: "Du hast eine Reaktion auf dein Bild erhalten.",
.testNotification: "Das ist eine Testbenachrichtigung.",
.reopenedMedia: "hat dein Bild erneut geöffnet.",
.reactionToVideo: "Du hast eine Reaktion auf dein Video erhalten.",
.reactionToText: "Du hast eine Reaktion auf deinen Text erhalten.",
.reactionToImage: "Du hast eine Reaktion auf dein Bild erhalten.",
.response: "Du hast eine Antwort erhalten.",
]
} else { // Default to English
pushNotificationText = [
.text: "You got a message.",
.twonly: "You got a twonly.",
.video: "You got a video.",
.image: "You got an image.",
.contactRequest: "You got a contact request.",
.acceptRequest: "Your contact request has been accepted.",
.storedMediaFile: "Your image has been saved.",
.reaction: "You got a reaction to your image.",
.testNotification: "This is a test notification.",
.reopenedMedia: "has reopened your image.",
.reactionToVideo: "You got a reaction to your video.",
.reactionToText: "You got a reaction to your text.",
.reactionToImage: "You got a reaction to your image.",
.response: "You got a response.",
]
}
// Return the corresponding message or an empty string if not found
return pushNotificationText[pushKind] ?? ""
return (content, title)
}

View file

@ -37,6 +37,9 @@ enum PushKind: SwiftProtobuf.Enum, Swift.CaseIterable {
case reactionToVideo // = 11
case reactionToText // = 12
case reactionToImage // = 13
case reactionToAudio // = 14
case addedToGroup // = 15
case audio // = 16
case UNRECOGNIZED(Int)
init() {
@ -59,6 +62,9 @@ enum PushKind: SwiftProtobuf.Enum, Swift.CaseIterable {
case 11: self = .reactionToVideo
case 12: self = .reactionToText
case 13: self = .reactionToImage
case 14: self = .reactionToAudio
case 15: self = .addedToGroup
case 16: self = .audio
default: self = .UNRECOGNIZED(rawValue)
}
}
@ -79,6 +85,9 @@ enum PushKind: SwiftProtobuf.Enum, Swift.CaseIterable {
case .reactionToVideo: return 11
case .reactionToText: return 12
case .reactionToImage: return 13
case .reactionToAudio: return 14
case .addedToGroup: return 15
case .audio: return 16
case .UNRECOGNIZED(let i): return i
}
}
@ -99,11 +108,14 @@ enum PushKind: SwiftProtobuf.Enum, Swift.CaseIterable {
.reactionToVideo,
.reactionToText,
.reactionToImage,
.reactionToAudio,
.addedToGroup,
.audio,
]
}
struct EncryptedPushNotification: @unchecked Sendable {
struct EncryptedPushNotification: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
@ -128,8 +140,8 @@ struct PushNotification: Sendable {
var kind: PushKind = .reaction
var messageID: Int64 {
get {return _messageID ?? 0}
var messageID: String {
get {return _messageID ?? String()}
set {_messageID = newValue}
}
/// Returns true if `messageID` has been explicitly set.
@ -137,21 +149,21 @@ struct PushNotification: Sendable {
/// Clears the value of `messageID`. Subsequent reads from it will return its default value.
mutating func clearMessageID() {self._messageID = nil}
var reactionContent: String {
get {return _reactionContent ?? String()}
set {_reactionContent = newValue}
var additionalContent: String {
get {return _additionalContent ?? String()}
set {_additionalContent = newValue}
}
/// Returns true if `reactionContent` has been explicitly set.
var hasReactionContent: Bool {return self._reactionContent != nil}
/// Clears the value of `reactionContent`. Subsequent reads from it will return its default value.
mutating func clearReactionContent() {self._reactionContent = nil}
/// Returns true if `additionalContent` has been explicitly set.
var hasAdditionalContent: Bool {return self._additionalContent != nil}
/// Clears the value of `additionalContent`. Subsequent reads from it will return its default value.
mutating func clearAdditionalContent() {self._additionalContent = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _messageID: Int64? = nil
fileprivate var _reactionContent: String? = nil
fileprivate var _messageID: String? = nil
fileprivate var _additionalContent: String? = nil
}
struct PushUsers: Sendable {
@ -177,8 +189,8 @@ struct PushUser: Sendable {
var blocked: Bool = false
var lastMessageID: Int64 {
get {return _lastMessageID ?? 0}
var lastMessageID: String {
get {return _lastMessageID ?? String()}
set {_lastMessageID = newValue}
}
/// Returns true if `lastMessageID` has been explicitly set.
@ -192,10 +204,10 @@ struct PushUser: Sendable {
init() {}
fileprivate var _lastMessageID: Int64? = nil
fileprivate var _lastMessageID: String? = nil
}
struct PushKey: @unchecked Sendable {
struct PushKey: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
@ -214,32 +226,12 @@ struct PushKey: @unchecked Sendable {
// MARK: - Code below here is support for the SwiftProtobuf runtime.
extension PushKind: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "reaction"),
1: .same(proto: "response"),
2: .same(proto: "text"),
3: .same(proto: "video"),
4: .same(proto: "twonly"),
5: .same(proto: "image"),
6: .same(proto: "contactRequest"),
7: .same(proto: "acceptRequest"),
8: .same(proto: "storedMediaFile"),
9: .same(proto: "testNotification"),
10: .same(proto: "reopenedMedia"),
11: .same(proto: "reactionToVideo"),
12: .same(proto: "reactionToText"),
13: .same(proto: "reactionToImage"),
]
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0reaction\0\u{1}response\0\u{1}text\0\u{1}video\0\u{1}twonly\0\u{1}image\0\u{1}contactRequest\0\u{1}acceptRequest\0\u{1}storedMediaFile\0\u{1}testNotification\0\u{1}reopenedMedia\0\u{1}reactionToVideo\0\u{1}reactionToText\0\u{1}reactionToImage\0\u{1}reactionToAudio\0\u{1}addedToGroup\0\u{1}audio\0")
}
extension EncryptedPushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "EncryptedPushNotification"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "keyId"),
2: .same(proto: "nonce"),
3: .same(proto: "ciphertext"),
4: .same(proto: "mac"),
]
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}keyId\0\u{1}nonce\0\u{1}ciphertext\0\u{1}mac\0")
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
@ -284,11 +276,7 @@ extension EncryptedPushNotification: SwiftProtobuf.Message, SwiftProtobuf._Messa
extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "PushNotification"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "kind"),
2: .same(proto: "messageId"),
3: .same(proto: "reactionContent"),
]
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}kind\0\u{1}messageId\0\u{1}additionalContent\0")
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
@ -297,8 +285,8 @@ extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularEnumField(value: &self.kind) }()
case 2: try { try decoder.decodeSingularInt64Field(value: &self._messageID) }()
case 3: try { try decoder.decodeSingularStringField(value: &self._reactionContent) }()
case 2: try { try decoder.decodeSingularStringField(value: &self._messageID) }()
case 3: try { try decoder.decodeSingularStringField(value: &self._additionalContent) }()
default: break
}
}
@ -313,9 +301,9 @@ extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme
try visitor.visitSingularEnumField(value: self.kind, fieldNumber: 1)
}
try { if let v = self._messageID {
try visitor.visitSingularInt64Field(value: v, fieldNumber: 2)
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
} }()
try { if let v = self._reactionContent {
try { if let v = self._additionalContent {
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
@ -324,7 +312,7 @@ extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme
static func ==(lhs: PushNotification, rhs: PushNotification) -> Bool {
if lhs.kind != rhs.kind {return false}
if lhs._messageID != rhs._messageID {return false}
if lhs._reactionContent != rhs._reactionContent {return false}
if lhs._additionalContent != rhs._additionalContent {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
@ -332,9 +320,7 @@ extension PushNotification: SwiftProtobuf.Message, SwiftProtobuf._MessageImpleme
extension PushUsers: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "PushUsers"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "users"),
]
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}users\0")
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
@ -364,13 +350,7 @@ extension PushUsers: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
extension PushUser: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "PushUser"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "userId"),
2: .same(proto: "displayName"),
3: .same(proto: "blocked"),
4: .same(proto: "lastMessageId"),
5: .same(proto: "pushKeys"),
]
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}userId\0\u{1}displayName\0\u{1}blocked\0\u{1}lastMessageId\0\u{1}pushKeys\0")
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
@ -381,7 +361,7 @@ extension PushUser: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
case 1: try { try decoder.decodeSingularInt64Field(value: &self.userID) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.displayName) }()
case 3: try { try decoder.decodeSingularBoolField(value: &self.blocked) }()
case 4: try { try decoder.decodeSingularInt64Field(value: &self._lastMessageID) }()
case 4: try { try decoder.decodeSingularStringField(value: &self._lastMessageID) }()
case 5: try { try decoder.decodeRepeatedMessageField(value: &self.pushKeys) }()
default: break
}
@ -403,7 +383,7 @@ extension PushUser: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
try visitor.visitSingularBoolField(value: self.blocked, fieldNumber: 3)
}
try { if let v = self._lastMessageID {
try visitor.visitSingularInt64Field(value: v, fieldNumber: 4)
try visitor.visitSingularStringField(value: v, fieldNumber: 4)
} }()
if !self.pushKeys.isEmpty {
try visitor.visitRepeatedMessageField(value: self.pushKeys, fieldNumber: 5)
@ -424,11 +404,7 @@ extension PushUser: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
extension PushKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = "PushKey"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "id"),
2: .same(proto: "key"),
3: .same(proto: "createdAtUnixTimestamp"),
]
static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0\u{1}key\0\u{1}createdAtUnixTimestamp\0")
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {

View file

@ -1,4 +1,6 @@
PODS:
- audio_waveforms (0.0.1):
- Flutter
- background_downloader (0.0.1):
- Flutter
- camera_avfoundation (0.0.1):
@ -9,6 +11,13 @@ PODS:
- Flutter
- device_info_plus (0.0.1):
- Flutter
- emoji_picker_flutter (0.0.1):
- Flutter
- ffmpeg_kit_flutter_new (1.0.0):
- ffmpeg_kit_flutter_new/full-gpl (= 1.0.0)
- Flutter
- ffmpeg_kit_flutter_new/full-gpl (1.0.0):
- Flutter
- Firebase (12.4.0):
- Firebase/Core (= 12.4.0)
- Firebase/Core (12.4.0):
@ -77,6 +86,8 @@ PODS:
- flutter_secure_storage_darwin (10.0.0):
- Flutter
- FlutterMacOS
- flutter_volume_controller (0.0.1):
- Flutter
- flutter_zxing (0.0.1):
- Flutter
- gal (1.0.0):
@ -233,21 +244,19 @@ PODS:
- SwiftProtobuf (1.32.0)
- url_launcher_ios (0.0.1):
- Flutter
- video_compress (0.3.0):
- Flutter
- video_player_avfoundation (0.0.1):
- Flutter
- FlutterMacOS
- video_thumbnail (0.0.1):
- Flutter
- libwebp
DEPENDENCIES:
- audio_waveforms (from `.symlinks/plugins/audio_waveforms/ios`)
- background_downloader (from `.symlinks/plugins/background_downloader/ios`)
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- cryptography_flutter_plus (from `.symlinks/plugins/cryptography_flutter_plus/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- emoji_picker_flutter (from `.symlinks/plugins/emoji_picker_flutter/ios`)
- ffmpeg_kit_flutter_new (from `.symlinks/plugins/ffmpeg_kit_flutter_new/ios`)
- Firebase
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
@ -259,6 +268,7 @@ DEPENDENCIES:
- flutter_keyboard_visibility_temp_fork (from `.symlinks/plugins/flutter_keyboard_visibility_temp_fork/ios`)
- 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`)
- GoogleUtilities
@ -275,9 +285,7 @@ DEPENDENCIES:
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- SwiftProtobuf
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_compress (from `.symlinks/plugins/video_compress/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
- video_thumbnail (from `.symlinks/plugins/video_thumbnail/ios`)
SPEC REPOS:
trunk:
@ -302,6 +310,8 @@ SPEC REPOS:
- SwiftProtobuf
EXTERNAL SOURCES:
audio_waveforms:
:path: ".symlinks/plugins/audio_waveforms/ios"
background_downloader:
:path: ".symlinks/plugins/background_downloader/ios"
camera_avfoundation:
@ -312,6 +322,10 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/cryptography_flutter_plus/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
emoji_picker_flutter:
:path: ".symlinks/plugins/emoji_picker_flutter/ios"
ffmpeg_kit_flutter_new:
:path: ".symlinks/plugins/ffmpeg_kit_flutter_new/ios"
firebase_core:
:path: ".symlinks/plugins/firebase_core/ios"
firebase_messaging:
@ -326,6 +340,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_secure_storage_darwin:
: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:
@ -354,19 +370,18 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
video_compress:
:path: ".symlinks/plugins/video_compress/ios"
video_player_avfoundation:
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
video_thumbnail:
:path: ".symlinks/plugins/video_thumbnail/ios"
SPEC CHECKSUMS:
audio_waveforms: a6dde7fe7c0ea05f06ffbdb0f7c1b2b2ba6cedcf
background_downloader: 50e91d979067b82081aba359d7d916b3ba5fadad
camera_avfoundation: 5675ca25298b6f81fa0a325188e7df62cc217741
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
cryptography_flutter_plus: 44f4e9e4079395fcbb3e7809c0ac2c6ae2d9576f
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
emoji_picker_flutter: ece213fc274bdddefb77d502d33080dc54e616cc
ffmpeg_kit_flutter_new: 12426a19f10ac81186c67c6ebc4717f8f4364b7f
Firebase: f07b15ae5a6ec0f93713e30b923d9970d144af3e
firebase_core: 744984dbbed8b3036abf34f0b98d80f130a7e464
firebase_messaging: 82c70650c426a0a14873e1acdb9ec2b443c4e8b4
@ -380,20 +395,21 @@ SPEC CHECKSUMS:
flutter_keyboard_visibility_temp_fork: 95b2d534bacf6ac62e7fcbe5c2a9e2c2a17ce06f
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468
flutter_volume_controller: c2be490cb0487e8b88d0d9fc2b7e1c139a4ebccb
flutter_zxing: e8bcc43bd3056c70c271b732ed94e7a16fd62f93
gal: baecd024ebfd13c441269ca7404792a7152fde89
GoogleAdsOnDeviceConversion: e03a386840803ea7eef3fd22a061930142c039c1
GoogleAppMeasurement: 1e718274b7e015cefd846ac1fcf7820c70dc017d
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
no_screenshot: 6d183496405a3ab709a67a54e5cd0f639e94729e
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
restart_app: 9cda5378aacc5000e3f66ee76a9201534e7d3ecf
@ -401,15 +417,13 @@ SPEC CHECKSUMS:
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
SwiftProtobuf: 81e341191afbddd64aa031bd12862dccfab2f639
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
video_compress: f2133a07762889d67f0711ac831faa26f956980e
video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
video_thumbnail: b637e0ad5f588ca9945f6e2c927f73a69a661140
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
PODFILE CHECKSUM: 47470fbd5b59affa461eaf943ac57acce81e0ee8

View file

@ -263,8 +263,8 @@
D21FCEAC2D9F2B750088701D /* Embed Foundation Extensions */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
A3027D78D4FF6E79C9EFD470 /* [CP] Copy Pods Resources */,
32D7521D6B8F508A844DBC22 /* [CP] Embed Pods Frameworks */,
A7154597C13DDED7C7F2355C /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -485,7 +485,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
A3027D78D4FF6E79C9EFD470 /* [CP] Copy Pods Resources */ = {
A7154597C13DDED7C7F2355C /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (

View file

@ -6,12 +6,16 @@ import 'package:twonly/globals.dart';
import 'package:twonly/src/localization/generated/app_localizations.dart';
import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/providers/settings.provider.dart';
import 'package:twonly/src/services/api/media_upload.dart';
import 'package:twonly/src/services/subscription.service.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/pow.dart';
import 'package:twonly/src/utils/storage.dart';
import 'package:twonly/src/views/components/app_outdated.dart';
import 'package:twonly/src/views/home.view.dart';
import 'package:twonly/src/views/onboarding/onboarding.view.dart';
import 'package:twonly/src/views/onboarding/register.view.dart';
import 'package:twonly/src/views/settings/backup/twonly_safe_backup.view.dart';
import 'package:twonly/src/views/updates/62_database_migration.view.dart';
class App extends StatefulWidget {
const App({super.key});
@ -35,8 +39,8 @@ class _AppState extends State<App> with WidgetsBindingObserver {
await setUserPlan();
};
globalCallbackUpdatePlan = (String planId) async {
await context.read<CustomChangeProvider>().updatePlan(planId);
globalCallbackUpdatePlan = (SubscriptionPlan plan) async {
await context.read<CustomChangeProvider>().updatePlan(plan);
};
unawaited(initAsync());
@ -44,22 +48,11 @@ class _AppState extends State<App> with WidgetsBindingObserver {
Future<void> setUserPlan() async {
final user = await getUser();
globalBestFriendUserId = -1;
if (user != null && mounted) {
if (user.myBestFriendContactId != null) {
final contact = await twonlyDB.contactsDao
.getContactByUserId(user.myBestFriendContactId!)
.getSingleOrNull();
if (contact != null) {
if (contact.alsoBestFriend) {
globalBestFriendUserId = user.myBestFriendContactId ?? 0;
}
}
}
if (mounted) {
await context
.read<CustomChangeProvider>()
.updatePlan(user.subscriptionPlan);
await context.read<CustomChangeProvider>().updatePlan(
planFromString(user.subscriptionPlan),
);
}
}
}
@ -68,8 +61,6 @@ class _AppState extends State<App> with WidgetsBindingObserver {
await setUserPlan();
await apiService.connect(force: true);
await apiService.listenToNetworkChanges();
// call this function so invalid media files are get purged
await retryMediaUpload(true);
}
@override
@ -84,7 +75,6 @@ class _AppState extends State<App> with WidgetsBindingObserver {
} else if (state == AppLifecycleState.paused) {
wasPaused = true;
globalIsAppInBackground = true;
unawaited(handleUploadWhenAppGoesBackground());
}
}
@ -92,7 +82,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
void dispose() {
WidgetsBinding.instance.removeObserver(this);
globalCallbackConnectionState = ({required bool isConnected}) {};
globalCallbackUpdatePlan = (String planId) {};
globalCallbackUpdatePlan = (SubscriptionPlan planId) {};
super.dispose();
}
@ -131,6 +121,8 @@ class _AppState extends State<App> with WidgetsBindingObserver {
colorScheme: ColorScheme.fromSeed(
brightness: Brightness.dark,
seedColor: const Color(0xFF57CC99),
surface: const Color.fromARGB(255, 20, 18, 23),
surfaceContainer: const Color.fromARGB(255, 33, 30, 39),
),
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
@ -159,36 +151,85 @@ class AppMainWidget extends StatefulWidget {
}
class _AppMainWidgetState extends State<AppMainWidget> {
Future<bool> userCreated = isUserCreated();
bool showOnboarding = true;
bool _isUserCreated = false;
bool _showDatabaseMigration = false;
bool _showOnboarding = true;
bool _isLoaded = false;
(Future<int>?, bool) _proofOfWork = (null, false);
@override
void initState() {
initAsync();
super.initState();
}
Future<void> initAsync() async {
_isUserCreated = await isUserCreated();
if (_isUserCreated) {
if (gUser.appVersion < 62) {
_showDatabaseMigration = true;
}
}
if (!_isUserCreated && !_showDatabaseMigration) {
// This means the user is in the onboarding screen, so start with the Proof of Work.
final (proof, disabled) = await apiService.getProofOfWork();
if (proof != null) {
Log.info('Starting with proof of work calculation.');
// Starting with the proof of work.
_proofOfWork =
(calculatePoW(proof.prefix, proof.difficulty.toInt()), false);
} else {
_proofOfWork = (null, disabled);
}
}
setState(() {
_isLoaded = true;
});
}
@override
Widget build(BuildContext context) {
if (!_isLoaded) {
return Center(child: Container());
}
late Widget child;
if (_showDatabaseMigration) {
child = const DatabaseMigrationView();
} else if (_isUserCreated) {
if (gUser.twonlySafeBackup == null) {
child = TwonlyIdentityBackupView(
callBack: () {
setState(() {});
},
);
} else {
child = HomeView(
initialPage: widget.initialPage,
);
}
} else if (_showOnboarding) {
child = OnboardingView(
callbackOnSuccess: () => setState(() {
_showOnboarding = false;
}),
);
} else {
child = RegisterView(
callbackOnSuccess: initAsync,
proofOfWork: _proofOfWork,
);
}
return Stack(
children: [
FutureBuilder<bool>(
future: userCreated,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: Container());
} else if (snapshot.data!) {
return HomeView(
initialPage: widget.initialPage,
);
} else if (showOnboarding) {
return OnboardingView(
callbackOnSuccess: () => setState(() {
showOnboarding = false;
}),
);
}
return RegisterView(
callbackOnSuccess: () => setState(() {
userCreated = isUserCreated();
}),
);
},
),
child,
const AppOutdated(),
],
);

View file

@ -1,14 +1,22 @@
import 'dart:ui';
import 'package:camera/camera.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/model/json/userdata.dart';
import 'package:twonly/src/services/api.service.dart';
import 'package:twonly/src/services/subscription.service.dart';
late ApiService apiService;
// uses for background notification
late TwonlyDatabase twonlyDB;
late TwonlyDB twonlyDB;
List<CameraDescription> gCameras = <CameraDescription>[];
// Cached UserData in the memory. Every time the user data is changed the `updateUserdata` function is called,
// which will update this global variable. The variable is set in the main.dart and after the user has registered in the register.view.dart
late UserData gUser;
// The following global function can be called from anywhere to update
// the UI when something changed. The callbacks will be set by
// App widget.
@ -19,7 +27,9 @@ void Function({required bool isConnected}) globalCallbackConnectionState = ({
}) {};
void Function() globalCallbackAppIsOutdated = () {};
void Function() globalCallbackNewDeviceRegistered = () {};
void Function(String planId) globalCallbackUpdatePlan = (String planId) {};
void Function(SubscriptionPlan plan) globalCallbackUpdatePlan =
(SubscriptionPlan plan) {};
Map<String, VoidCallback> globalUserDataChangedCallBack = {};
bool globalIsAppInBackground = true;
int globalBestFriendUserId = -1;

View file

@ -1,25 +1,30 @@
// ignore_for_file: unused_import
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:twonly/app.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/providers/connection.provider.dart';
import 'package:twonly/src/providers/image_editor.provider.dart';
import 'package:twonly/src/providers/settings.provider.dart';
import 'package:twonly/src/services/api.service.dart';
import 'package:twonly/src/services/api/media_download.dart';
import 'package:twonly/src/services/api/media_upload.dart';
import 'package:twonly/src/services/api/mediafiles/media_background.service.dart';
import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
import 'package:twonly/src/services/fcm.service.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/services/notifications/setup.notifications.dart';
import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/storage.dart';
import 'app.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initFCMService();
@ -28,9 +33,7 @@ void main() async {
final user = await getUser();
if (user != null) {
if (user.isDemoUser) {
await deleteLocalUserData();
}
gUser = user;
}
final settingsController = SettingsChangeProvider();
@ -42,21 +45,26 @@ void main() async {
gCameras = await availableCameras();
// try {
// File(join((await getApplicationSupportDirectory()).path, 'twonly.sqlite'))
// .deleteSync();
// } catch (e) {}
// await updateUserdata((u) {
// u.appVersion = 0;
// return u;
// });
apiService = ApiService();
twonlyDB = TwonlyDatabase();
await twonlyDB.messagesDao.resetPendingDownloadState();
await twonlyDB.messagesDao.handleMediaFilesOlderThan30Days();
await twonlyDB.messageRetransmissionDao.purgeOldRetransmissions();
await twonlyDB.signalDao.purgeOutDatedPreKeys();
// Purge media files in the background
unawaited(purgeReceivedMediaFiles());
unawaited(purgeSendMediaFiles());
unawaited(performTwonlySafeBackup());
twonlyDB = TwonlyDB();
await initFileDownloader();
unawaited(finishStartedPreprocessing());
unawaited(MediaFileService.purgeTempFolder());
unawaited(createPushAvatars());
await twonlyDB.messagesDao.purgeMessageTable();
unawaited(performTwonlySafeBackup());
runApp(
MultiProvider(

View file

@ -6,6 +6,6 @@ class SecureStorageKeys {
static const String userData = 'userData';
static const String twonlySafeLastBackupHash = 'twonly_safe_last_backup_hash';
static const String receivingPushKeys = 'receiving_push_keys';
static const String sendingPushKeys = 'sending_push_keys';
static const String receivingPushKeys = 'push_keys_receiving';
static const String sendingPushKeys = 'push_keys_sending';
}

View file

@ -0,0 +1,171 @@
import 'package:drift/drift.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/database/twonly_database_old.dart' as old;
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
import 'package:twonly/src/utils/log.dart';
part 'contacts.dao.g.dart';
@DriftAccessor(tables: [Contacts])
class ContactsDao extends DatabaseAccessor<TwonlyDB> with _$ContactsDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
ContactsDao(super.db);
Future<int?> insertContact(ContactsCompanion contact) async {
try {
return await into(contacts).insert(contact);
} catch (e) {
Log.error(e);
return null;
}
}
Future<int> insertOnConflictUpdate(ContactsCompanion contact) async {
try {
return await into(contacts).insertOnConflictUpdate(contact);
} catch (e) {
Log.error(e);
return 0;
}
}
SingleOrNullSelectable<Contact> getContactByUserId(int userId) {
return select(contacts)..where((t) => t.userId.equals(userId));
}
Future<Contact?> getContactById(int userId) async {
return (select(contacts)..where((t) => t.userId.equals(userId)))
.getSingleOrNull();
}
Future<List<Contact>> getContactsByUsername(String username) async {
return (select(contacts)..where((t) => t.username.equals(username))).get();
}
Future<void> deleteContactByUserId(int userId) {
return (delete(contacts)..where((t) => t.userId.equals(userId))).go();
}
Future<void> updateContact(
int userId,
ContactsCompanion updatedValues,
) async {
await (update(contacts)..where((c) => c.userId.equals(userId)))
.write(updatedValues);
if (updatedValues.blocked.present ||
updatedValues.displayName.present ||
updatedValues.nickName.present) {
final contact = await getContactByUserId(userId).getSingleOrNull();
if (contact != null) {
await updatePushUser(contact);
final group = await twonlyDB.groupsDao.getDirectChat(userId);
if (group != null) {
await twonlyDB.groupsDao.updateGroup(
group.groupId,
GroupsCompanion(
groupName: Value(getContactDisplayName(contact)),
),
);
}
}
}
}
Stream<List<Contact>> watchNotAcceptedContacts() {
return (select(contacts)
..where(
(t) =>
t.accepted.equals(false) &
t.blocked.equals(false) &
t.deletedByUser.equals(false),
))
.watch();
}
Stream<Contact?> watchContact(int userid) {
return (select(contacts)..where((t) => t.userId.equals(userid)))
.watchSingleOrNull();
}
Future<List<Contact>> getAllNotBlockedContacts() {
return select(contacts).get();
}
Stream<int?> watchContactsBlocked() {
final count = contacts.userId.count();
final query = selectOnly(contacts)
..where(contacts.blocked.equals(true))
..addColumns([count]);
return query.map((row) => row.read(count)).watchSingle();
}
Stream<int?> watchContactsRequested() {
final count = contacts.requested.count(distinct: true);
final query = selectOnly(contacts)
..where(
contacts.requested.equals(true) &
contacts.accepted.equals(false) &
contacts.deletedByUser.equals(false) &
contacts.blocked.equals(false),
)
..addColumns([count]);
return query.map((row) => row.read(count)).watchSingle();
}
Stream<List<Contact>> watchAllAcceptedContacts() {
return (select(contacts)
..where((t) => t.blocked.equals(false) & t.accepted.equals(true)))
.watch();
}
Stream<List<Contact>> watchAllContacts() {
return select(contacts).watch();
}
}
String getContactDisplayName(Contact user, {int? maxLength}) {
var name = user.username;
if (user.nickName != null && user.nickName != '') {
name = user.nickName!;
} else if (user.displayName != null) {
name = user.displayName!;
}
if (user.accountDeleted) {
name = applyStrikethrough(name);
}
if (maxLength != null) {
name = substringBy(name, maxLength);
}
return name;
}
String substringBy(String string, int maxLength) {
if (string.length > maxLength) {
return '${string.substring(0, maxLength - 3)}...';
}
return string;
}
String getContactDisplayNameOld(old.Contact user) {
var name = user.username;
if (user.nickName != null && user.nickName != '') {
name = user.nickName!;
} else if (user.displayName != null) {
name = user.displayName!;
}
if (user.deleted) {
name = applyStrikethrough(name);
}
if (name.length > 12) {
return '${name.substring(0, 12)}...';
}
return name;
}
String applyStrikethrough(String text) {
return text.split('').map((char) => '$char\u0336').join();
}

View file

@ -1,8 +1,8 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'contacts_dao.dart';
part of 'contacts.dao.dart';
// ignore_for_file: type=lint
mixin _$ContactsDaoMixin on DatabaseAccessor<TwonlyDatabase> {
mixin _$ContactsDaoMixin on DatabaseAccessor<TwonlyDB> {
$ContactsTable get contacts => attachedDatabase.contacts;
}

View file

@ -1,254 +0,0 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts_table.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
part 'contacts_dao.g.dart';
@DriftAccessor(tables: [Contacts])
class ContactsDao extends DatabaseAccessor<TwonlyDatabase>
with _$ContactsDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
ContactsDao(super.db);
Future<int> insertContact(ContactsCompanion contact) async {
try {
return await into(contacts).insert(contact);
} catch (e) {
return 0;
}
}
Future<int> incFlameCounter(
int contactId,
bool received,
DateTime timestamp,
) async {
final contact = (await (select(contacts)
..where((t) => t.userId.equals(contactId)))
.get())
.first;
final totalMediaCounter = contact.totalMediaCounter + 1;
var flameCounter = contact.flameCounter;
if (contact.lastMessageReceived != null &&
contact.lastMessageSend != null) {
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
final twoDaysAgo = startOfToday.subtract(const Duration(days: 2));
if (contact.lastMessageSend!.isBefore(twoDaysAgo) ||
contact.lastMessageReceived!.isBefore(twoDaysAgo)) {
flameCounter = 0;
}
}
var lastMessageSend = const Value<DateTime?>.absent();
var lastMessageReceived = const Value<DateTime?>.absent();
var lastFlameCounterChange = const Value<DateTime?>.absent();
if (contact.lastFlameCounterChange != null) {
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
if (contact.lastFlameCounterChange!.isBefore(startOfToday)) {
// last flame update was yesterday. check if it can be updated.
var updateFlame = false;
if (received) {
if (contact.lastMessageSend != null &&
contact.lastMessageSend!.isAfter(startOfToday)) {
// today a message was already send -> update flame
updateFlame = true;
}
} else if (contact.lastMessageReceived != null &&
contact.lastMessageReceived!.isAfter(startOfToday)) {
// today a message was already received -> update flame
updateFlame = true;
}
if (updateFlame) {
flameCounter += 1;
lastFlameCounterChange = Value(timestamp);
}
}
} else {
// There where no message until no...
lastFlameCounterChange = Value(timestamp);
}
if (received) {
lastMessageReceived = Value(timestamp);
} else {
lastMessageSend = Value(timestamp);
}
return (update(contacts)..where((t) => t.userId.equals(contactId))).write(
ContactsCompanion(
totalMediaCounter: Value(totalMediaCounter),
lastFlameCounterChange: lastFlameCounterChange,
lastMessageReceived: lastMessageReceived,
lastMessageSend: lastMessageSend,
flameCounter: Value(flameCounter),
),
);
}
SingleOrNullSelectable<Contact> getContactByUserId(int userId) {
return select(contacts)..where((t) => t.userId.equals(userId));
}
Future<void> deleteContactByUserId(int userId) {
return (delete(contacts)..where((t) => t.userId.equals(userId))).go();
}
Future<void> updateContact(
int userId,
ContactsCompanion updatedValues,
) async {
await (update(contacts)..where((c) => c.userId.equals(userId)))
.write(updatedValues);
if (updatedValues.blocked.present ||
updatedValues.displayName.present ||
updatedValues.nickName.present) {
final contact = await getContactByUserId(userId).getSingleOrNull();
if (contact != null) {
await updatePushUser(contact);
}
}
}
Stream<List<Contact>> watchNotAcceptedContacts() {
return (select(contacts)
..where(
(t) =>
t.accepted.equals(false) &
t.archived.equals(false) &
t.blocked.equals(false),
))
.watch();
// return (select(contacts)).watch();
}
Stream<Contact?> watchContact(int userid) {
return (select(contacts)..where((t) => t.userId.equals(userid)))
.watchSingleOrNull();
}
Stream<List<Contact>> watchContactsForShareView() {
return (select(contacts)
..where(
(t) =>
t.accepted.equals(true) &
t.blocked.equals(false) &
t.deleted.equals(false),
)
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch();
}
Stream<List<Contact>> watchContactsForStartNewChat() {
return (select(contacts)
..where((t) => t.accepted.equals(true) & t.blocked.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch();
}
Stream<List<Contact>> watchContactsForChatList() {
return (select(contacts)
..where(
(t) =>
t.accepted.equals(true) &
t.blocked.equals(false) &
t.archived.equals(false),
)
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch();
}
Future<List<Contact>> getAllNotBlockedContacts() {
return (select(contacts)
..where((t) => t.blocked.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.get();
}
Stream<int?> watchContactsBlocked() {
final count = contacts.userId.count();
final query = selectOnly(contacts)
..where(contacts.blocked.equals(true))
..addColumns([count]);
return query.map((row) => row.read(count)).watchSingle();
}
Stream<int?> watchContactsRequested() {
final count = contacts.requested.count(distinct: true);
final query = selectOnly(contacts)
..where(
contacts.requested.equals(true) & contacts.accepted.equals(true).not(),
)
..addColumns([count]);
return query.map((row) => row.read(count)).watchSingle();
}
Stream<List<Contact>> watchAllContacts() {
return select(contacts).watch();
}
Future<void> modifyFlameCounterForTesting() async {
await update(contacts).write(
ContactsCompanion(
lastFlameCounterChange: Value(DateTime.now()),
flameCounter: const Value(1337),
lastFlameSync: const Value(null),
),
);
}
Stream<int> watchFlameCounter(int userId) {
return (select(contacts)
..where(
(u) =>
u.userId.equals(userId) &
u.lastMessageReceived.isNotNull() &
u.lastMessageSend.isNotNull(),
))
.watchSingle()
.asyncMap(getFlameCounterFromContact);
}
}
String getContactDisplayName(Contact user) {
var name = user.username;
if (user.nickName != null && user.nickName != '') {
name = user.nickName!;
} else if (user.displayName != null) {
name = user.displayName!;
}
if (user.deleted) {
name = applyStrikethrough(name);
}
if (name.length > 12) {
return '${name.substring(0, 12)}...';
}
return name;
}
String applyStrikethrough(String text) {
return text.split('').map((char) => '$char\u0336').join();
}
int getFlameCounterFromContact(Contact contact) {
if (contact.lastMessageSend == null || contact.lastMessageReceived == null) {
return 0;
}
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
final twoDaysAgo = startOfToday.subtract(const Duration(days: 2));
if (contact.lastMessageSend!.isAfter(twoDaysAgo) &&
contact.lastMessageReceived!.isAfter(twoDaysAgo)) {
return contact.flameCounter + 1;
} else {
return 0;
}
}

View file

@ -0,0 +1,395 @@
import 'package:drift/drift.dart';
import 'package:hashlib/random.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/tables/groups.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart';
part 'groups.dao.g.dart';
@DriftAccessor(
tables: [
Groups,
GroupMembers,
GroupHistories,
],
)
class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
GroupsDao(super.db);
Future<bool> isContactInGroup(int contactId, String groupId) async {
final entry = await (select(groupMembers)..where(
// ignore: require_trailing_commas
(t) => t.contactId.equals(contactId) & t.groupId.equals(groupId)))
.getSingleOrNull();
return entry != null;
}
Future<void> deleteGroup(String groupId) async {
await (delete(groups)..where((t) => t.groupId.equals(groupId))).go();
}
Future<void> updateGroup(
String groupId,
GroupsCompanion updates,
) async {
await (update(groups)..where((c) => c.groupId.equals(groupId)))
.write(updates);
}
Future<List<GroupMember>> getGroupNonLeftMembers(String groupId) async {
return (select(groupMembers)
..where(
(t) =>
t.groupId.equals(groupId) &
(t.memberState.equals(MemberState.leftGroup.name).not() |
t.memberState.isNull()),
))
.get();
}
Future<List<GroupMember>> getAllGroupMembers(String groupId) async {
return (select(groupMembers)..where((t) => t.groupId.equals(groupId)))
.get();
}
Future<GroupMember?> getGroupMemberByPublicKey(Uint8List publicKey) async {
return (select(groupMembers)
..where((t) => t.groupPublicKey.equals(publicKey)))
.getSingleOrNull();
}
Future<Group?> createNewGroup(GroupsCompanion group) async {
return _insertGroup(group);
}
Future<void> insertOrUpdateGroupMember(GroupMembersCompanion members) async {
await into(groupMembers).insertOnConflictUpdate(members);
}
Future<void> insertGroupAction(GroupHistoriesCompanion action) async {
var insertAction = action;
if (!action.groupHistoryId.present) {
insertAction = action.copyWith(
groupHistoryId: Value(uuid.v4()),
);
}
await into(groupHistories).insert(insertAction);
}
Stream<List<GroupHistory>> watchGroupActions(String groupId) {
return (select(groupHistories)
..where((t) => t.groupId.equals(groupId))
..orderBy([(t) => OrderingTerm.asc(t.actionAt)]))
.watch();
}
Future<void> updateMember(
String groupId,
int contactId,
GroupMembersCompanion updates,
) async {
await (update(groupMembers)
..where(
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
))
.write(updates);
}
Future<void> removeMember(String groupId, int contactId) async {
await (delete(groupMembers)
..where(
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
))
.go();
}
Future<Group?> createNewDirectChat(
int contactId,
GroupsCompanion group,
) async {
final groupIdDirectChat = getUUIDforDirectChat(contactId, gUser.userId);
final insertGroup = group.copyWith(
groupId: Value(groupIdDirectChat),
isDirectChat: const Value(true),
isGroupAdmin: const Value(true),
joinedGroup: const Value(true),
);
final result = await _insertGroup(insertGroup);
if (result != null) {
await into(groupMembers).insert(
GroupMembersCompanion(
groupId: Value(result.groupId),
contactId: Value(
contactId,
),
),
);
}
return result;
}
Future<Group?> _insertGroup(GroupsCompanion group) async {
try {
await into(groups).insert(group);
return await (select(groups)
..where((t) => t.groupId.equals(group.groupId.value)))
.getSingle();
} catch (e) {
Log.error('Could not insert group: $e');
return null;
}
}
Future<List<Contact>> getGroupContact(String groupId) async {
final query = (select(contacts).join([
leftOuterJoin(
groupMembers,
groupMembers.contactId.equalsExp(contacts.userId),
useColumns: false,
),
])
..orderBy([OrderingTerm.desc(groupMembers.lastMessage)])
..where(groupMembers.groupId.equals(groupId)));
return query.map((row) => row.readTable(contacts)).get();
}
Stream<List<Contact>> watchGroupContact(String groupId) {
final query = (select(contacts).join([
leftOuterJoin(
groupMembers,
groupMembers.contactId.equalsExp(contacts.userId),
useColumns: false,
),
])
..orderBy([OrderingTerm.desc(groupMembers.lastMessage)])
..where(groupMembers.groupId.equals(groupId)));
return query.map((row) => row.readTable(contacts)).watch();
}
Stream<List<(Contact, GroupMember)>> watchGroupMembers(String groupId) {
final query =
(select(groupMembers)..where((t) => t.groupId.equals(groupId))).join([
leftOuterJoin(
contacts,
contacts.userId.equalsExp(groupMembers.contactId),
),
]);
return query
.map((row) => (row.readTable(contacts), row.readTable(groupMembers)))
.watch();
}
Stream<List<Group>> watchGroupsForShareImage() {
return (select(groups)
..where(
(g) => g.leftGroup.equals(false) & g.deletedContent.equals(false),
))
.watch();
}
Stream<Group?> watchGroup(String groupId) {
return (select(groups)..where((t) => t.groupId.equals(groupId)))
.watchSingleOrNull();
}
Stream<Group?> watchDirectChat(int contactId) {
final groupId = getUUIDforDirectChat(contactId, gUser.userId);
return (select(groups)..where((t) => t.groupId.equals(groupId)))
.watchSingleOrNull();
}
Stream<List<Group>> watchGroupsForChatList() {
return (select(groups)
..where((t) => t.deletedContent.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
.watch();
}
Stream<List<Group>> watchGroupsForStartNewChat() {
return (select(groups)
..where((t) => t.isDirectChat.equals(false))
..orderBy([(t) => OrderingTerm.asc(t.groupName)]))
.watch();
}
Future<Group?> getGroup(String groupId) {
return (select(groups)..where((t) => t.groupId.equals(groupId)))
.getSingleOrNull();
}
Stream<int> watchFlameCounter(String groupId) {
return (select(groups)
..where(
(u) =>
u.groupId.equals(groupId) &
u.lastMessageReceived.isNotNull() &
u.lastMessageSend.isNotNull(),
))
.watchSingleOrNull()
.asyncMap(getFlameCounterFromGroup);
}
Future<List<Group>> getAllDirectChats() {
return (select(groups)..where((t) => t.isDirectChat.equals(true))).get();
}
Future<List<Group>> getAllNotJoinedGroups() {
return (select(groups)
..where(
(t) => t.joinedGroup.equals(false) & t.isDirectChat.equals(false),
))
.get();
}
Future<List<GroupMember>> getAllGroupMemberWithoutPublicKey() {
final query =
((select(groups)..where((t) => t.isDirectChat.equals(false))).join([
leftOuterJoin(
groupMembers,
groupMembers.groupId.equalsExp(groups.groupId),
),
])
..where(groupMembers.groupPublicKey.isNull()));
return query.map((row) => row.readTable(groupMembers)).get();
}
Future<Group?> getDirectChat(int userId) async {
final query =
((select(groups)..where((t) => t.isDirectChat.equals(true))).join([
leftOuterJoin(
groupMembers,
groupMembers.groupId.equalsExp(groups.groupId),
),
])
..where(groupMembers.contactId.equals(userId)));
return query.map((row) => row.readTable(groups)).getSingleOrNull();
}
Future<void> incFlameCounter(
String groupId,
bool received,
DateTime timestamp,
) async {
final group = await (select(groups)
..where((t) => t.groupId.equals(groupId)))
.getSingle();
final totalMediaCounter = group.totalMediaCounter + (received ? 0 : 1);
var flameCounter = group.flameCounter;
var maxFlameCounter = group.maxFlameCounter;
var maxFlameCounterFrom = group.maxFlameCounterFrom;
if (group.lastMessageReceived != null && group.lastMessageSend != null) {
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
final twoDaysAgo = startOfToday.subtract(const Duration(days: 2));
if (group.lastMessageSend!.isBefore(twoDaysAgo) ||
group.lastMessageReceived!.isBefore(twoDaysAgo)) {
flameCounter = 0;
}
}
var lastMessageSend = const Value<DateTime?>.absent();
var lastMessageReceived = const Value<DateTime?>.absent();
var lastFlameCounterChange = const Value<DateTime?>.absent();
if (group.lastFlameCounterChange != null) {
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
if (group.lastFlameCounterChange!.isBefore(startOfToday)) {
// last flame update was yesterday. check if it can be updated.
var updateFlame = false;
if (received) {
if (group.lastMessageSend != null &&
group.lastMessageSend!.isAfter(startOfToday)) {
// today a message was already send -> update flame
updateFlame = true;
}
} else if (group.lastMessageReceived != null &&
group.lastMessageReceived!.isAfter(startOfToday)) {
// today a message was already received -> update flame
updateFlame = true;
}
if (updateFlame) {
flameCounter += 1;
lastFlameCounterChange = Value(timestamp);
// Overwrite max flame counter either the current is bigger or the th max flame counter is older then 4 days
if ((flameCounter + 1) >= maxFlameCounter ||
maxFlameCounterFrom == null ||
maxFlameCounterFrom
.isBefore(DateTime.now().subtract(const Duration(days: 5)))) {
maxFlameCounter = flameCounter + 1;
maxFlameCounterFrom = DateTime.now();
}
}
}
} else {
// There where no message until no...
lastFlameCounterChange = Value(timestamp);
}
if (received) {
lastMessageReceived = Value(timestamp);
} else {
lastMessageSend = Value(timestamp);
}
await (update(groups)..where((t) => t.groupId.equals(groupId))).write(
GroupsCompanion(
totalMediaCounter: Value(totalMediaCounter),
lastFlameCounterChange: lastFlameCounterChange,
lastMessageReceived: lastMessageReceived,
lastMessageSend: lastMessageSend,
flameCounter: Value(flameCounter),
maxFlameCounter: Value(maxFlameCounter),
maxFlameCounterFrom: Value(maxFlameCounterFrom),
),
);
}
Stream<int> watchSumTotalMediaCounter() {
final query = selectOnly(groups)
..addColumns([groups.totalMediaCounter.sum()]);
return query.watch().map((rows) {
final expr = rows.first.read(groups.totalMediaCounter.sum());
return expr ?? 0;
});
}
Future<void> increaseLastMessageExchange(
String groupId,
DateTime newLastMessage,
) async {
await (update(groups)
..where(
(t) =>
t.groupId.equals(groupId) &
(t.lastMessageExchange.isSmallerThanValue(newLastMessage)),
))
.write(GroupsCompanion(lastMessageExchange: Value(newLastMessage)));
}
}
int getFlameCounterFromGroup(Group? group) {
if (group == null) return 0;
if (group.lastMessageSend == null || group.lastMessageReceived == null) {
return 0;
}
final now = DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
final twoDaysAgo = startOfToday.subtract(const Duration(days: 2));
if (group.lastMessageSend!.isAfter(twoDaysAgo) &&
group.lastMessageReceived!.isAfter(twoDaysAgo)) {
return group.flameCounter + 1;
} else {
return 0;
}
}

View file

@ -0,0 +1,11 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'groups.dao.dart';
// ignore_for_file: type=lint
mixin _$GroupsDaoMixin on DatabaseAccessor<TwonlyDB> {
$GroupsTable get groups => attachedDatabase.groups;
$ContactsTable get contacts => attachedDatabase.contacts;
$GroupMembersTable get groupMembers => attachedDatabase.groupMembers;
$GroupHistoriesTable get groupHistories => attachedDatabase.groupHistories;
}

View file

@ -1,50 +0,0 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/media_uploads_table.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/utils/log.dart';
part 'media_uploads_dao.g.dart';
@DriftAccessor(tables: [MediaUploads])
class MediaUploadsDao extends DatabaseAccessor<TwonlyDatabase>
with _$MediaUploadsDaoMixin {
// ignore: matching_super_parameters
MediaUploadsDao(super.db);
Future<List<MediaUpload>> getMediaUploadsForRetry() {
return (select(mediaUploads)
..where(
(t) => t.state.equals(UploadState.receiverNotified.name).not(),
))
.get();
}
Future<int> updateMediaUpload(
int mediaUploadId,
MediaUploadsCompanion updatedValues,
) {
return (update(mediaUploads)
..where((c) => c.mediaUploadId.equals(mediaUploadId)))
.write(updatedValues);
}
Future<int?> insertMediaUpload(MediaUploadsCompanion values) async {
try {
return await into(mediaUploads).insert(values);
} catch (e) {
Log.error('Error while inserting media upload: $e');
return null;
}
}
Future<void> deleteMediaUpload(int mediaUploadId) {
return (delete(mediaUploads)
..where((t) => t.mediaUploadId.equals(mediaUploadId)))
.go();
}
SingleOrNullSelectable<MediaUpload> getMediaUploadById(int mediaUploadId) {
return select(mediaUploads)
..where((t) => t.mediaUploadId.equals(mediaUploadId));
}
}

View file

@ -1,8 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'media_uploads_dao.dart';
// ignore_for_file: type=lint
mixin _$MediaUploadsDaoMixin on DatabaseAccessor<TwonlyDatabase> {
$MediaUploadsTable get mediaUploads => attachedDatabase.mediaUploads;
}

View file

@ -0,0 +1,123 @@
import 'package:drift/drift.dart';
import 'package:hashlib/random.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
part 'mediafiles.dao.g.dart';
@DriftAccessor(tables: [MediaFiles])
class MediaFilesDao extends DatabaseAccessor<TwonlyDB>
with _$MediaFilesDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
MediaFilesDao(super.db);
Future<MediaFile?> insertMedia(MediaFilesCompanion mediaFile) async {
try {
var insertMediaFile = mediaFile;
if (insertMediaFile.mediaId == const Value.absent()) {
insertMediaFile = mediaFile.copyWith(
mediaId: Value(uuid.v7()),
);
}
final rowId = await into(mediaFiles).insert(insertMediaFile);
return await (select(mediaFiles)..where((t) => t.rowId.equals(rowId)))
.getSingle();
} catch (e) {
Log.error('Could not insert media file: $e');
return null;
}
}
Future<void> deleteMediaFile(String mediaId) async {
await (delete(mediaFiles)
..where(
(t) => t.mediaId.equals(mediaId),
))
.go();
}
Future<void> updateMedia(
String mediaId,
MediaFilesCompanion updates,
) async {
await (update(mediaFiles)..where((c) => c.mediaId.equals(mediaId)))
.write(updates);
}
Future<void> updateAllMediaFiles(
MediaFilesCompanion updates,
) async {
await update(mediaFiles).write(updates);
}
Future<MediaFile?> getMediaFileById(String mediaId) async {
return (select(mediaFiles)..where((t) => t.mediaId.equals(mediaId)))
.getSingleOrNull();
}
Future<MediaFile?> getDraftMediaFile() async {
final medias = await (select(mediaFiles)
..where((t) => t.isDraftMedia.equals(true)))
.get();
if (medias.isEmpty) {
return null;
}
return medias.first;
}
Stream<MediaFile?> watchMedia(String mediaId) {
return (select(mediaFiles)..where((t) => t.mediaId.equals(mediaId)))
.watchSingleOrNull();
}
Future<void> resetPendingDownloadState() async {
await (update(mediaFiles)
..where(
(c) => c.downloadState.equals(
DownloadState.downloading.name,
),
))
.write(
const MediaFilesCompanion(
downloadState: Value(DownloadState.pending),
),
);
}
Future<List<MediaFile>> getAllMediaFilesPendingDownload() async {
return (select(mediaFiles)
..where(
(t) =>
t.downloadState.equals(DownloadState.pending.name) |
t.downloadState.equals(DownloadState.downloading.name),
))
.get();
}
Future<List<MediaFile>> getAllMediaFilesPendingUpload() async {
return (select(mediaFiles)
..where(
(t) => (t.uploadState.equals(UploadState.initialized.name) |
t.uploadState.equals(UploadState.uploadLimitReached.name) |
t.uploadState.equals(UploadState.preprocessing.name)),
))
.get();
}
Stream<List<MediaFile>> watchAllStoredMediaFiles() {
return (select(mediaFiles)..where((t) => t.stored.equals(true))).watch();
}
Stream<List<MediaFile>> watchNewestMediaFiles() {
return (select(mediaFiles)
..orderBy([(t) => OrderingTerm.desc(t.createdAt)])
..limit(100))
.watch();
}
}

View file

@ -0,0 +1,8 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'mediafiles.dao.dart';
// ignore_for_file: type=lint
mixin _$MediaFilesDaoMixin on DatabaseAccessor<TwonlyDB> {
$MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles;
}

View file

@ -1,123 +0,0 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/message_retransmissions.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/utils/log.dart';
part 'message_retransmissions.dao.g.dart';
@DriftAccessor(tables: [MessageRetransmissions])
class MessageRetransmissionDao extends DatabaseAccessor<TwonlyDatabase>
with _$MessageRetransmissionDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
MessageRetransmissionDao(super.db);
Future<int?> insertRetransmission(
MessageRetransmissionsCompanion message,
) async {
try {
return await into(messageRetransmissions).insert(message);
} catch (e) {
Log.error('Error while inserting message for retransmission: $e');
return null;
}
}
Future<void> purgeOldRetransmissions() async {
// delete entries older than two weeks
await (delete(messageRetransmissions)
..where(
(t) => (t.acknowledgeByServerAt.isSmallerThanValue(
DateTime.now().subtract(
const Duration(days: 25),
),
)),
))
.go();
}
Future<List<int>> getRetransmitAbleMessages() async {
final countDeleted = await (delete(messageRetransmissions)
..where(
(t) =>
t.encryptedHash.isNull() & t.acknowledgeByServerAt.isNotNull(),
))
.go();
if (countDeleted > 0) {
Log.info('Deleted $countDeleted faulty retransmissions');
}
return (await (select(messageRetransmissions)
..where((t) => t.acknowledgeByServerAt.isNull()))
.get())
.map((msg) => msg.retransmissionId)
.toList();
}
SingleOrNullSelectable<MessageRetransmission> getRetransmissionById(
int retransmissionId,
) {
return select(messageRetransmissions)
..where((t) => t.retransmissionId.equals(retransmissionId));
}
Stream<List<MessageRetransmission>> watchAllMessages() {
return (select(messageRetransmissions)
..orderBy([(t) => OrderingTerm.asc(t.retransmissionId)]))
.watch();
}
Future<void> updateRetransmission(
int retransmissionId,
MessageRetransmissionsCompanion updatedValues,
) {
return (update(messageRetransmissions)
..where((c) => c.retransmissionId.equals(retransmissionId)))
.write(updatedValues);
}
Future<int> resetAckStatusFor(int fromUserId, Uint8List encryptedHash) async {
return ((update(messageRetransmissions))
..where(
(m) =>
m.contactId.equals(fromUserId) &
m.encryptedHash.equals(encryptedHash),
))
.write(
const MessageRetransmissionsCompanion(
acknowledgeByServerAt: Value(null),
),
);
}
Future<MessageRetransmission?> getRetransmissionFromHash(
int fromUserId,
Uint8List encryptedHash,
) async {
return ((select(messageRetransmissions))
..where(
(m) =>
m.contactId.equals(fromUserId) &
m.encryptedHash.equals(encryptedHash),
))
.getSingleOrNull();
}
Future<void> deleteRetransmissionById(int retransmissionId) {
return (delete(messageRetransmissions)
..where((t) => t.retransmissionId.equals(retransmissionId)))
.go();
}
Future<void> clearRetransmissionTable() {
return delete(messageRetransmissions).go();
}
Future<void> deleteRetransmissionByMessageId(int messageId) {
return (delete(messageRetransmissions)
..where((t) => t.messageId.equals(messageId)))
.go();
}
}

View file

@ -1,11 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'message_retransmissions.dao.dart';
// ignore_for_file: type=lint
mixin _$MessageRetransmissionDaoMixin on DatabaseAccessor<TwonlyDatabase> {
$ContactsTable get contacts => attachedDatabase.contacts;
$MessagesTable get messages => attachedDatabase.messages;
$MessageRetransmissionsTable get messageRetransmissions =>
attachedDatabase.messageRetransmissions;
}

View file

@ -0,0 +1,550 @@
import 'package:drift/drift.dart';
import 'package:hashlib/random.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/tables/groups.table.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/tables/reactions.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/utils/log.dart';
part 'messages.dao.g.dart';
@DriftAccessor(
tables: [
Messages,
Contacts,
MediaFiles,
Reactions,
MessageHistories,
GroupMembers,
MessageActions,
Groups,
],
)
class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
MessagesDao(super.db);
Stream<List<Message>> watchMessageNotOpened(String groupId) {
return (select(messages)
..where(
(t) =>
t.openedAt.isNull() &
t.groupId.equals(groupId) &
t.isDeletedFromSender.equals(false),
)
..orderBy([(t) => OrderingTerm.desc(t.createdAt)]))
.watch();
}
Stream<List<Message>> watchMediaNotOpened(String groupId) {
final query = select(messages).join([
leftOuterJoin(mediaFiles, mediaFiles.mediaId.equalsExp(messages.mediaId)),
])
..where(
mediaFiles.downloadState
.equals(DownloadState.reuploadRequested.name)
.not() &
mediaFiles.type.equals(MediaType.audio.name).not() &
messages.openedAt.isNull() &
messages.groupId.equals(groupId) &
messages.mediaId.isNotNull() &
messages.senderId.isNotNull() &
messages.type.equals(MessageType.media.name),
);
return query.map((row) => row.readTable(messages)).watch();
}
Stream<Message?> watchLastMessage(String groupId) {
return (select(messages)
..where((t) => t.groupId.equals(groupId))
..orderBy([(t) => OrderingTerm.desc(t.createdAt)])
..limit(1))
.watchSingleOrNull();
}
Stream<List<Message>> watchByGroupId(String groupId) {
return ((select(messages)
..where(
(t) =>
t.groupId.equals(groupId) &
(t.isDeletedFromSender.equals(true) |
((t.type.equals(MessageType.text.name) &
t.content.isNotNull()) |
(t.type.equals(MessageType.media.name) &
t.mediaId.isNotNull()))),
))
..orderBy([(t) => OrderingTerm.asc(t.createdAt)]))
.watch();
}
Stream<List<(GroupMember, Contact)>> watchMembersByGroupId(String groupId) {
final query = (select(groupMembers).join([
leftOuterJoin(
contacts,
contacts.userId.equalsExp(groupMembers.contactId),
),
])
..where(groupMembers.groupId.equals(groupId)));
return query
.map((row) => (row.readTable(groupMembers), row.readTable(contacts)))
.watch();
}
Stream<List<MessageAction>> watchMessageActionChanges(String messageId) {
return (select(messageActions)..where((t) => t.messageId.equals(messageId)))
.watch();
}
Stream<Message?> watchMessageById(String messageId) {
return (select(messages)..where((t) => t.messageId.equals(messageId)))
.watchSingleOrNull();
}
Future<void> purgeMessageTable() async {
final allGroups = await select(groups).get();
for (final group in allGroups) {
final deletionTime = DateTime.now().subtract(
Duration(
milliseconds: group.deleteMessagesAfterMilliseconds,
),
);
final affected = await (delete(messages)
..where(
(m) =>
m.groupId.equals(group.groupId) &
// m.messageId.equals(lastMessage.messageId).not() &
(m.mediaStored.equals(true) &
m.isDeletedFromSender.equals(true) |
m.mediaStored.equals(false)) &
(m.openedByAll.isSmallerThanValue(deletionTime) |
(m.isDeletedFromSender.equals(true) &
m.createdAt.isSmallerThanValue(deletionTime))),
))
.go();
Log.info('Deleted $affected messages.');
}
}
// Future<List<Message>> getAllMessagesPendingDownloading() {
// return (select(messages)
// ..where(
// (t) =>
// t.downloadState.equals(DownloadState.downloaded.index).not() &
// t.messageOtherId.isNotNull() &
// t.errorWhileSending.equals(false) &
// t.kind.equals(MessageKind.media.name),
// ))
// .get();
// }
// Future<List<Message>> getAllNonACKMessagesFromUser() {
// return (select(messages)
// ..where(
// (t) =>
// t.acknowledgeByUser.equals(false) &
// t.messageOtherId.isNull() &
// t.errorWhileSending.equals(false) &
// t.sendAt.isBiggerThanValue(
// DateTime.now().subtract(const Duration(minutes: 10)),
// ),
// ))
// .get();
// }
// Stream<List<Message>> getAllStoredMediaFiles() {
// return (select(messages)
// ..where((t) => t.mediaStored.equals(true))
// ..orderBy([(t) => OrderingTerm.desc(t.sendAt)]))
// .watch();
// }
// Future<List<Message>> getAllMessagesPendingUpload() {
// return (select(messages)
// ..where(
// (t) =>
// t.acknowledgeByServer.equals(false) &
// t.messageOtherId.isNull() &
// t.mediaUploadId.isNotNull() &
// t.downloadState.equals(DownloadState.pending.index) &
// t.errorWhileSending.equals(false) &
// t.kind.equals(MessageKind.media.name),
// ))
// .get();
// }
Future<void> openedAllTextMessages(String groupId) {
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
return (update(messages)
..where(
(t) =>
t.groupId.equals(groupId) &
t.senderId.isNotNull() &
t.openedAt.isNull() &
t.type.equals(MessageType.text.name),
))
.write(updates);
}
Future<void> handleMessageDeletion(
int? contactId,
String messageId,
DateTime timestamp,
) async {
final msg = await getMessageById(messageId).getSingleOrNull();
if (msg == null || msg.senderId != contactId) {
Log.error('Message does not exists or contact is not owner.');
return;
}
if (msg.mediaId != null && contactId != null) {
// contactId -> When a image is send to multiple and one message is delete the image should be still available...
await (delete(mediaFiles)..where((t) => t.mediaId.equals(msg.mediaId!)))
.go();
final mediaService = await MediaFileService.fromMediaId(msg.mediaId!);
if (mediaService != null) {
mediaService.fullMediaRemoval();
}
}
await (delete(messageHistories)
..where((t) => t.messageId.equals(messageId)))
.go();
await (update(messages)
..where(
(t) => t.messageId.equals(messageId),
))
.write(
const MessagesCompanion(
isDeletedFromSender: Value(true),
content: Value(null),
mediaId: Value(null),
),
);
}
Future<void> handleTextEdit(
int? contactId,
String messageId,
String text,
DateTime timestamp,
) async {
final msg = await getMessageById(messageId).getSingleOrNull();
if (msg == null || msg.content == null || msg.senderId != contactId) {
return;
}
await into(messageHistories).insert(
MessageHistoriesCompanion(
messageId: Value(messageId),
content: Value(msg.content),
createdAt: Value(timestamp),
),
);
await (update(messages)
..where(
(t) => t.messageId.equals(messageId),
))
.write(
MessagesCompanion(
content: Value(text),
modifiedAt: Value(timestamp),
),
);
}
Future<void> handleMessageOpened(
int contactId,
String messageId,
DateTime timestamp,
) async {
await into(messageActions).insertOnConflictUpdate(
MessageActionsCompanion(
messageId: Value(messageId),
contactId: Value(contactId),
type: const Value(MessageActionType.openedAt),
actionAt: Value(timestamp),
),
);
// Directly show as message opened as soon as one person has opened it
final openedByAll =
await haveAllMembers(messageId, MessageActionType.openedAt)
? DateTime.now()
: null;
await twonlyDB.messagesDao.updateMessageId(
messageId,
MessagesCompanion(
openedAt: Value(DateTime.now()),
openedByAll: Value(openedByAll),
),
);
}
Future<void> handleMessageAckByServer(
int contactId,
String messageId,
DateTime timestamp,
) async {
await into(messageActions).insertOnConflictUpdate(
MessageActionsCompanion(
messageId: Value(messageId),
contactId: Value(contactId),
type: const Value(MessageActionType.ackByServerAt),
actionAt: Value(timestamp),
),
);
await twonlyDB.messagesDao.updateMessageId(
messageId,
MessagesCompanion(ackByServer: Value(DateTime.now())),
);
}
Future<bool> haveAllMembers(
String messageId,
MessageActionType action,
) async {
final message =
await twonlyDB.messagesDao.getMessageById(messageId).getSingleOrNull();
if (message == null) return true;
final members =
await twonlyDB.groupsDao.getGroupNonLeftMembers(message.groupId);
final actions = await (select(messageActions)
..where(
(t) => t.type.equals(action.name) & t.messageId.equals(messageId),
))
.get();
return members.length == actions.length;
}
// Future<void> updateMessageByOtherUser(
// int userId,
// int messageId,
// MessagesCompanion updatedValues,
// ) {
// return (update(messages)
// ..where(
// (c) => c.contactId.equals(userId) & c.messageId.equals(messageId),
// ))
// .write(updatedValues);
// }
// Future<void> updateMessageByOtherMessageId(
// int userId,
// int messageOtherId,
// MessagesCompanion updatedValues,
// ) {
// return (update(messages)
// ..where(
// (c) =>
// c.contactId.equals(userId) &
// c.messageOtherId.equals(messageOtherId),
// ))
// .write(updatedValues);
// }
Future<void> updateMessageId(
String messageId,
MessagesCompanion updatedValues,
) async {
await (update(messages)..where((c) => c.messageId.equals(messageId)))
.write(updatedValues);
}
Future<void> updateMessagesByMediaId(
String mediaId,
MessagesCompanion updatedValues,
) {
return (update(messages)..where((c) => c.mediaId.equals(mediaId)))
.write(updatedValues);
}
Future<Message?> insertMessage(MessagesCompanion message) async {
try {
var insertMessage = message;
if (message.messageId == const Value.absent()) {
insertMessage = message.copyWith(
messageId: Value(uuid.v7()),
);
}
final rowId = await into(messages).insert(insertMessage);
await twonlyDB.groupsDao.updateGroup(
message.groupId.value,
GroupsCompanion(
lastMessageExchange: Value(DateTime.now()),
archived: const Value(false),
deletedContent: const Value(false),
),
);
if (message.senderId.present) {
await twonlyDB.groupsDao.updateMember(
message.groupId.value,
message.senderId.value!,
GroupMembersCompanion(
lastMessage: Value(DateTime.now()),
),
);
}
return await (select(messages)..where((t) => t.rowId.equals(rowId)))
.getSingle();
} catch (e) {
Log.error('Could not insert message: $e');
return null;
}
}
Future<MessageAction?> getLastMessageAction(String messageId) async {
return (((select(messageActions)
..where(
(t) => t.messageId.equals(messageId),
))
..orderBy([(t) => OrderingTerm.desc(t.actionAt)]))
..limit(1))
.getSingleOrNull();
}
Stream<Future<List<(Message, Contact)>>> watchLastOpenedMessagePerContact(
String groupId,
) {
const sql = '''
SELECT m.*, c.*
FROM (
SELECT ma.contact_id, ma.message_id,
ROW_NUMBER() OVER (PARTITION BY ma.contact_id
ORDER BY ma.action_at DESC, ma.message_id DESC) AS rn
FROM message_actions ma
WHERE ma.type = 'openedAt'
) last_open
JOIN messages m ON m.message_id = last_open.message_id
JOIN contacts c ON c.user_id = last_open.contact_id
WHERE last_open.rn = 1 AND m.group_id = ?;
''';
return customSelect(
sql,
variables: [Variable.withString(groupId)],
readsFrom: {messages, messageActions, contacts},
).watch().map((rows) async {
final res = <(Message, Contact)>[];
for (final row in rows) {
final message = await messages.mapFromRow(row);
final contact = await contacts.mapFromRow(row);
res.add((message, contact));
}
return res;
});
}
// Future<void> deleteMessagesByContactId(int contactId) {
// return (delete(messages)
// ..where(
// (t) => t.contactId.equals(contactId) & t.mediaStored.equals(false),
// ))
// .go();
// }
// Future<void> deleteMessagesByContactIdAndOtherMessageId(
// int contactId,
// int messageOtherId,
// ) {
// return (delete(messages)
// ..where(
// (t) =>
// t.contactId.equals(contactId) &
// t.messageOtherId.equals(messageOtherId),
// ))
// .go();
// }
Future<void> deleteMessagesById(String messageId) {
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
}
Future<void> deleteMessagesByGroupId(String groupId) {
return (delete(messages)..where((t) => t.groupId.equals(groupId))).go();
}
// Future<void> deleteAllMessagesByContactId(int contactId) {
// return (delete(messages)..where((t) => t.contactId.equals(contactId))).go();
// }
// Future<bool> containsOtherMessageId(
// int fromUserId,
// int messageOtherId,
// ) async {
// final query = select(messages)
// ..where(
// (t) =>
// t.messageOtherId.equals(messageOtherId) &
// t.contactId.equals(fromUserId),
// );
// final entry = await query.get();
// return entry.isNotEmpty;
// }
SingleOrNullSelectable<Message> getMessageById(String messageId) {
return select(messages)..where((t) => t.messageId.equals(messageId));
}
Future<List<Message>> getMessagesByMediaId(String mediaId) async {
return (select(messages)..where((t) => t.mediaId.equals(mediaId))).get();
}
Stream<List<(MessageAction, Contact)>> watchMessageActions(String messageId) {
final query = (select(messageActions).join([
leftOuterJoin(
contacts,
contacts.userId.equalsExp(messageActions.contactId),
),
])
..where(messageActions.messageId.equals(messageId)));
return query
.map((row) => (row.readTable(messageActions), row.readTable(contacts)))
.watch();
}
Stream<List<MessageHistory>> watchMessageHistory(String messageId) {
return (select(messageHistories)
..where((t) => t.messageId.equals(messageId))
..orderBy([(t) => OrderingTerm.desc(t.createdAt)]))
.watch();
}
// Future<List<Message>> getMessagesByMediaUploadId(int mediaUploadId) async {
// return (select(messages)
// ..where((t) => t.mediaUploadId.equals(mediaUploadId)))
// .get();
// }
// SingleOrNullSelectable<Message> getMessageByOtherMessageId(
// int fromUserId,
// int messageId,
// ) {
// return select(messages)
// ..where(
// (t) =>
// t.messageOtherId.equals(messageId) & t.contactId.equals(fromUserId),
// );
// }
// SingleOrNullSelectable<Message> getMessageByIdAndContactId(
// int fromUserId,
// int messageId,
// ) {
// return select(messages)
// ..where(
// (t) => t.messageId.equals(messageId) & t.contactId.equals(fromUserId),
// );
// }
}

View file

@ -0,0 +1,16 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'messages.dao.dart';
// ignore_for_file: type=lint
mixin _$MessagesDaoMixin on DatabaseAccessor<TwonlyDB> {
$GroupsTable get groups => attachedDatabase.groups;
$ContactsTable get contacts => attachedDatabase.contacts;
$MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles;
$MessagesTable get messages => attachedDatabase.messages;
$ReactionsTable get reactions => attachedDatabase.reactions;
$MessageHistoriesTable get messageHistories =>
attachedDatabase.messageHistories;
$GroupMembersTable get groupMembers => attachedDatabase.groupMembers;
$MessageActionsTable get messageActions => attachedDatabase.messageActions;
}

View file

@ -1,311 +0,0 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts_table.dart';
import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/utils/log.dart';
part 'messages_dao.g.dart';
@DriftAccessor(tables: [Messages, Contacts])
class MessagesDao extends DatabaseAccessor<TwonlyDatabase>
with _$MessagesDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
MessagesDao(super.db);
Stream<List<Message>> watchMessageNotOpened(int contactId) {
return (select(messages)
..where(
(t) =>
t.openedAt.isNull() &
t.contactId.equals(contactId) &
t.errorWhileSending.equals(false),
)
..orderBy([(t) => OrderingTerm.desc(t.sendAt)]))
.watch();
}
Stream<List<Message>> watchMediaMessageNotOpened(int contactId) {
return (select(messages)
..where(
(t) =>
t.openedAt.isNull() &
t.contactId.equals(contactId) &
t.errorWhileSending.equals(false) &
t.messageOtherId.isNotNull() &
t.kind.equals(MessageKind.media.name),
)
..orderBy([(t) => OrderingTerm.asc(t.sendAt)]))
.watch();
}
Stream<List<Message>> watchLastMessage(int contactId) {
return (select(messages)
..where((t) => t.contactId.equals(contactId))
..orderBy([(t) => OrderingTerm.desc(t.sendAt)])
..limit(1))
.watch();
}
Stream<List<Message>> watchAllMessagesFrom(int contactId) {
return (select(messages)
..where(
(t) =>
t.contactId.equals(contactId) &
t.contentJson.isNotNull() &
(t.openedAt.isNull() |
t.mediaStored.equals(true) |
t.openedAt.isBiggerThanValue(
DateTime.now().subtract(const Duration(days: 1)),
)),
)
..orderBy([(t) => OrderingTerm.asc(t.sendAt)]))
.watch();
}
Future<void> removeOldMessages() {
return (update(messages)
..where(
(t) =>
(t.openedAt.isSmallerThanValue(
DateTime.now().subtract(const Duration(days: 1)),
) |
(t.sendAt.isSmallerThanValue(
DateTime.now().subtract(const Duration(days: 3)),
) &
t.errorWhileSending.equals(true))) &
t.kind.equals(MessageKind.textMessage.name),
))
.write(const MessagesCompanion(contentJson: Value(null)));
}
Future<void> handleMediaFilesOlderThan30Days() {
/// media files will be deleted by the server after 30 days, so delete them here also
return (update(messages)
..where(
(t) => (t.kind.equals(MessageKind.media.name) &
t.openedAt.isNull() &
t.messageOtherId.isNull() &
(t.sendAt.isSmallerThanValue(
DateTime.now().subtract(
const Duration(days: 30),
),
))),
))
.write(const MessagesCompanion(errorWhileSending: Value(true)));
}
Future<List<Message>> getAllMessagesPendingDownloading() {
return (select(messages)
..where(
(t) =>
t.downloadState.equals(DownloadState.downloaded.index).not() &
t.messageOtherId.isNotNull() &
t.errorWhileSending.equals(false) &
t.kind.equals(MessageKind.media.name),
))
.get();
}
Future<List<Message>> getAllNonACKMessagesFromUser() {
return (select(messages)
..where(
(t) =>
t.acknowledgeByUser.equals(false) &
t.messageOtherId.isNull() &
t.errorWhileSending.equals(false) &
t.sendAt.isBiggerThanValue(
DateTime.now().subtract(const Duration(minutes: 10)),
),
))
.get();
}
Stream<List<Message>> getAllStoredMediaFiles() {
return (select(messages)
..where((t) => t.mediaStored.equals(true))
..orderBy([(t) => OrderingTerm.desc(t.sendAt)]))
.watch();
}
Future<List<Message>> getAllMessagesPendingUpload() {
return (select(messages)
..where(
(t) =>
t.acknowledgeByServer.equals(false) &
t.messageOtherId.isNull() &
t.mediaUploadId.isNotNull() &
t.downloadState.equals(DownloadState.pending.index) &
t.errorWhileSending.equals(false) &
t.kind.equals(MessageKind.media.name),
))
.get();
}
Future<void> openedAllNonMediaMessages(int contactId) {
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
return (update(messages)
..where(
(t) =>
t.contactId.equals(contactId) &
t.messageOtherId.isNotNull() &
t.openedAt.isNull() &
t.kind.equals(MessageKind.media.name).not(),
))
.write(updates);
}
Future<void> resetPendingDownloadState() {
// All media files in the downloading state are reset to the pending state
// When the app is used in mobile network, they will not be downloaded at the start
// if they are not yet downloaded...
const updates =
MessagesCompanion(downloadState: Value(DownloadState.pending));
return (update(messages)
..where(
(t) =>
t.messageOtherId.isNotNull() &
t.downloadState.equals(DownloadState.downloading.index) &
t.kind.equals(MessageKind.media.name),
))
.write(updates);
}
Future<void> openedAllNonMediaMessagesFromOtherUser(int contactId) {
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
return (update(messages)
..where(
(t) =>
t.contactId.equals(contactId) &
t.messageOtherId
.isNull() & // only mark messages open that where send
t.openedAt.isNull() &
t.kind.equals(MessageKind.media.name).not(),
))
.write(updates);
}
Future<void> updateMessageByOtherUser(
int userId,
int messageId,
MessagesCompanion updatedValues,
) {
return (update(messages)
..where(
(c) => c.contactId.equals(userId) & c.messageId.equals(messageId),
))
.write(updatedValues);
}
Future<void> updateMessageByOtherMessageId(
int userId,
int messageOtherId,
MessagesCompanion updatedValues,
) {
return (update(messages)
..where(
(c) =>
c.contactId.equals(userId) &
c.messageOtherId.equals(messageOtherId),
))
.write(updatedValues);
}
Future<void> updateMessageByMessageId(
int messageId,
MessagesCompanion updatedValues,
) {
return (update(messages)..where((c) => c.messageId.equals(messageId)))
.write(updatedValues);
}
Future<int?> insertMessage(MessagesCompanion message) async {
try {
await (update(contacts)
..where(
(c) => c.userId.equals(message.contactId.value),
))
.write(ContactsCompanion(lastMessageExchange: Value(DateTime.now())));
return await into(messages).insert(message);
} catch (e) {
Log.error('Error while inserting message: $e');
return null;
}
}
Future<void> deleteMessagesByContactId(int contactId) {
return (delete(messages)
..where(
(t) => t.contactId.equals(contactId) & t.mediaStored.equals(false),
))
.go();
}
Future<void> deleteMessagesByContactIdAndOtherMessageId(
int contactId,
int messageOtherId,
) {
return (delete(messages)
..where(
(t) =>
t.contactId.equals(contactId) &
t.messageOtherId.equals(messageOtherId),
))
.go();
}
Future<void> deleteMessagesByMessageId(int messageId) {
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
}
Future<void> deleteAllMessagesByContactId(int contactId) {
return (delete(messages)..where((t) => t.contactId.equals(contactId))).go();
}
Future<bool> containsOtherMessageId(
int fromUserId,
int messageOtherId,
) async {
final query = select(messages)
..where(
(t) =>
t.messageOtherId.equals(messageOtherId) &
t.contactId.equals(fromUserId),
);
final entry = await query.get();
return entry.isNotEmpty;
}
SingleOrNullSelectable<Message> getMessageByMessageId(int messageId) {
return select(messages)..where((t) => t.messageId.equals(messageId));
}
Future<List<Message>> getMessagesByMediaUploadId(int mediaUploadId) async {
return (select(messages)
..where((t) => t.mediaUploadId.equals(mediaUploadId)))
.get();
}
SingleOrNullSelectable<Message> getMessageByOtherMessageId(
int fromUserId,
int messageId,
) {
return select(messages)
..where(
(t) =>
t.messageOtherId.equals(messageId) & t.contactId.equals(fromUserId),
);
}
SingleOrNullSelectable<Message> getMessageByIdAndContactId(
int fromUserId,
int messageId,
) {
return select(messages)
..where(
(t) => t.messageId.equals(messageId) & t.contactId.equals(fromUserId),
);
}
}

View file

@ -1,9 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'messages_dao.dart';
// ignore_for_file: type=lint
mixin _$MessagesDaoMixin on DatabaseAccessor<TwonlyDatabase> {
$ContactsTable get contacts => attachedDatabase.contacts;
$MessagesTable get messages => attachedDatabase.messages;
}

View file

@ -0,0 +1,129 @@
import 'package:drift/drift.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/tables/reactions.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/views/components/animate_icon.dart';
part 'reactions.dao.g.dart';
@DriftAccessor(tables: [Reactions, Contacts])
class ReactionsDao extends DatabaseAccessor<TwonlyDB> with _$ReactionsDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
ReactionsDao(super.db);
Future<void> updateReaction(
int contactId,
String messageId,
String groupId,
String emoji,
bool remove,
) async {
if (!isEmoji(emoji)) {
Log.error('Did not update reaction as it is not an emoji!');
return;
}
final msg =
await twonlyDB.messagesDao.getMessageById(messageId).getSingleOrNull();
if (msg == null || msg.groupId != groupId) return;
try {
if (remove) {
await (delete(reactions)
..where(
(t) =>
t.senderId.equals(contactId) &
t.messageId.equals(messageId) &
t.emoji.equals(emoji),
))
.go();
} else {
await into(reactions).insertOnConflictUpdate(
ReactionsCompanion(
messageId: Value(messageId),
emoji: Value(emoji),
senderId: Value(contactId),
),
);
}
} catch (e) {
Log.error(e);
}
}
Future<void> updateMyReaction(
String messageId,
String emoji,
bool remove,
) async {
if (!isEmoji(emoji)) {
Log.error('Did not update reaction as it is not an emoji!');
return;
}
final msg =
await twonlyDB.messagesDao.getMessageById(messageId).getSingleOrNull();
if (msg == null) return;
try {
await (delete(reactions)
..where(
(t) =>
t.senderId.isNull() &
t.messageId.equals(messageId) &
t.emoji.equals(emoji),
))
.go();
if (!remove) {
await into(reactions).insert(
ReactionsCompanion(
messageId: Value(messageId),
emoji: Value(emoji),
senderId: const Value(null),
),
);
}
} catch (e) {
Log.error(e);
}
}
Stream<List<Reaction>> watchReactions(String messageId) {
return (select(reactions)
..where((t) => t.messageId.equals(messageId))
..orderBy([(t) => OrderingTerm.desc(t.createdAt)]))
.watch();
}
Stream<Reaction?> watchLastReactions(String groupId) {
final query = (select(reactions)
..orderBy([(t) => OrderingTerm.desc(t.createdAt)]))
.join(
[
innerJoin(
messages,
messages.messageId.equalsExp(reactions.messageId),
useColumns: false,
),
],
)
..where(messages.groupId.equals(groupId))
// ..orderBy([(t) => OrderingTerm.asc(t.createdAt)]))
..limit(1);
return query.map((row) => row.readTable(reactions)).watchSingleOrNull();
}
Stream<List<(Reaction, Contact?)>> watchReactionWithContacts(
String messageId,
) {
final query = (select(reactions)).join(
[leftOuterJoin(contacts, contacts.userId.equalsExp(reactions.senderId))],
)..where(reactions.messageId.equals(messageId));
return query
.map((row) => (row.readTable(reactions), row.readTableOrNull(contacts)))
.watch();
}
}

View file

@ -0,0 +1,12 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'reactions.dao.dart';
// ignore_for_file: type=lint
mixin _$ReactionsDaoMixin on DatabaseAccessor<TwonlyDB> {
$GroupsTable get groups => attachedDatabase.groups;
$ContactsTable get contacts => attachedDatabase.contacts;
$MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles;
$MessagesTable get messages => attachedDatabase.messages;
$ReactionsTable get reactions => attachedDatabase.reactions;
}

View file

@ -0,0 +1,114 @@
import 'package:drift/drift.dart';
import 'package:hashlib/random.dart';
import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/tables/receipts.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
part 'receipts.dao.g.dart';
@DriftAccessor(tables: [Receipts, Messages, MessageActions, ReceivedReceipts])
class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
ReceiptsDao(super.db);
Future<void> confirmReceipt(String receiptId, int fromUserId) async {
final receipt = await (select(receipts)
..where(
(t) =>
t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId),
))
.getSingleOrNull();
if (receipt == null) return;
if (receipt.messageId != null) {
await into(messageActions).insert(
MessageActionsCompanion(
messageId: Value(receipt.messageId!),
contactId: Value(fromUserId),
type: const Value(MessageActionType.ackByUserAt),
),
);
}
await (delete(receipts)
..where(
(t) =>
t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId),
))
.go();
}
Future<void> deleteReceipt(String receiptId) async {
await (delete(receipts)
..where(
(t) => t.receiptId.equals(receiptId),
))
.go();
}
Future<Receipt?> insertReceipt(ReceiptsCompanion entry) async {
try {
var insertEntry = entry;
if (entry.receiptId == const Value.absent()) {
insertEntry = entry.copyWith(
receiptId: Value(uuid.v4()),
);
}
final id = await into(receipts).insert(insertEntry);
return await (select(receipts)..where((t) => t.rowId.equals(id)))
.getSingle();
} catch (e) {
Log.error(e);
return null;
}
}
Future<Receipt?> getReceiptById(String receiptId) async {
try {
return await (select(receipts)
..where(
(t) => t.receiptId.equals(receiptId),
))
.getSingleOrNull();
} catch (e) {
Log.error(e);
return null;
}
}
Future<List<Receipt>> getReceiptsNotAckByServer() async {
return (select(receipts)
..where(
(t) => t.ackByServerAt.isNull(),
))
.get();
}
Stream<List<Receipt>> watchAll() {
return select(receipts).watch();
}
Future<void> updateReceipt(
String receiptId,
ReceiptsCompanion updates,
) async {
await (update(receipts)..where((c) => c.receiptId.equals(receiptId)))
.write(updates);
}
Future<bool> isDuplicated(String receiptId) async {
return await (select(receivedReceipts)
..where((t) => t.receiptId.equals(receiptId)))
.getSingleOrNull() !=
null;
}
Future<void> gotReceipt(String receiptId) async {
await into(receivedReceipts)
.insert(ReceivedReceiptsCompanion(receiptId: Value(receiptId)));
}
}

View file

@ -0,0 +1,15 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'receipts.dao.dart';
// ignore_for_file: type=lint
mixin _$ReceiptsDaoMixin on DatabaseAccessor<TwonlyDB> {
$ContactsTable get contacts => attachedDatabase.contacts;
$GroupsTable get groups => attachedDatabase.groups;
$MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles;
$MessagesTable get messages => attachedDatabase.messages;
$ReceiptsTable get receipts => attachedDatabase.receipts;
$MessageActionsTable get messageActions => attachedDatabase.messageActions;
$ReceivedReceiptsTable get receivedReceipts =>
attachedDatabase.receivedReceipts;
}

View file

@ -1,11 +1,11 @@
import 'package:drift/drift.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/tables/signal_contact_prekey_table.dart';
import 'package:twonly/src/database/tables/signal_contact_signed_prekey_table.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/tables/signal_contact_prekey.table.dart';
import 'package:twonly/src/database/tables/signal_contact_signed_prekey.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
part 'signal_dao.g.dart';
part 'signal.dao.g.dart';
@DriftAccessor(
tables: [
@ -13,7 +13,7 @@ part 'signal_dao.g.dart';
SignalContactSignedPreKeys,
],
)
class SignalDao extends DatabaseAccessor<TwonlyDatabase> with _$SignalDaoMixin {
class SignalDao extends DatabaseAccessor<TwonlyDB> with _$SignalDaoMixin {
// this constructor is required so that the main database can create an instance
// of this object.
// ignore: matching_super_parameters
@ -57,7 +57,7 @@ class SignalDao extends DatabaseAccessor<TwonlyDatabase> with _$SignalDaoMixin {
tbl.preKeyId.equals(preKey.preKeyId),
))
.go();
Log.info('Using prekey ${preKey.preKeyId} for $contactId');
Log.info('[PREKEY] Using prekey ${preKey.preKeyId} for $contactId');
return preKey;
}
return null;
@ -68,6 +68,7 @@ class SignalDao extends DatabaseAccessor<TwonlyDatabase> with _$SignalDaoMixin {
List<SignalContactPreKeysCompanion> preKeys,
) async {
for (final preKey in preKeys) {
Log.info('[PREKEY] Inserting others ${preKey.preKeyId}');
try {
await into(signalContactPreKeys).insert(preKey);
} catch (e) {

View file

@ -1,9 +1,10 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'signal_dao.dart';
part of 'signal.dao.dart';
// ignore_for_file: type=lint
mixin _$SignalDaoMixin on DatabaseAccessor<TwonlyDatabase> {
mixin _$SignalDaoMixin on DatabaseAccessor<TwonlyDB> {
$ContactsTable get contacts => attachedDatabase.contacts;
$SignalContactPreKeysTable get signalContactPreKeys =>
attachedDatabase.signalContactPreKeys;
$SignalContactSignedPreKeysTable get signalContactSignedPreKeys =>

View file

@ -2,7 +2,7 @@ import 'package:collection/collection.dart';
import 'package:drift/drift.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/twonly.db.dart';
class ConnectIdentityKeyStore extends IdentityKeyStore {
ConnectIdentityKeyStore(this.identityKeyPair, this.localRegistrationId);

View file

@ -1,7 +1,7 @@
import 'package:drift/drift.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/log.dart';
class ConnectPreKeyStore extends PreKeyStore {
@ -19,15 +19,18 @@ class ConnectPreKeyStore extends PreKeyStore {
..where((tbl) => tbl.preKeyId.equals(preKeyId)))
.get();
if (preKeyRecord.isEmpty) {
throw InvalidKeyIdException('No such preKey record! - $preKeyId');
throw InvalidKeyIdException(
'[PREKEY] No such preKey record! - $preKeyId',
);
}
Log.info('Contact used preKey $preKeyId');
Log.info('[PREKEY] Contact used my preKey $preKeyId');
final preKey = preKeyRecord.first.preKey;
return PreKeyRecord.fromBuffer(preKey);
}
@override
Future<void> removePreKey(int preKeyId) async {
Log.info('[PREKEY] Removing $preKeyId from my own storage.');
await (twonlyDB.delete(twonlyDB.signalPreKeyStores)
..where((tbl) => tbl.preKeyId.equals(preKeyId)))
.go();
@ -40,6 +43,7 @@ class ConnectPreKeyStore extends PreKeyStore {
preKey: Value(record.serialize()),
);
Log.info('[PREKEY] Storing $preKeyId from my own storage.');
try {
await twonlyDB.into(twonlyDB.signalPreKeyStores).insert(preKeyCompanion);
} catch (e) {

View file

@ -1,7 +1,7 @@
import 'package:drift/drift.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/twonly.db.dart';
class ConnectSenderKeyStore extends SenderKeyStore {
@override

View file

@ -1,7 +1,7 @@
import 'package:drift/drift.dart';
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/database/twonly.db.dart';
class ConnectSessionStore extends SessionStore {
@override

View file

@ -0,0 +1,27 @@
import 'package:drift/drift.dart';
class Contacts extends Table {
IntColumn get userId => integer()();
TextColumn get username => text()();
TextColumn get displayName => text().nullable()();
TextColumn get nickName => text().nullable()();
BlobColumn get avatarSvgCompressed => blob().nullable()();
IntColumn get senderProfileCounter =>
integer().withDefault(const Constant(0))();
BoolColumn get accepted => boolean().withDefault(const Constant(false))();
BoolColumn get deletedByUser =>
boolean().withDefault(const Constant(false))();
BoolColumn get requested => boolean().withDefault(const Constant(false))();
BoolColumn get blocked => boolean().withDefault(const Constant(false))();
BoolColumn get verified => boolean().withDefault(const Constant(false))();
BoolColumn get accountDeleted =>
boolean().withDefault(const Constant(false))();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {userId};
}

View file

@ -0,0 +1,113 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
const int defaultDeleteMessagesAfterMilliseconds = 1000 * 60 * 60 * 24;
@DataClassName('Group')
class Groups extends Table {
TextColumn get groupId => text()();
BoolColumn get isGroupAdmin => boolean().withDefault(const Constant(false))();
BoolColumn get isDirectChat => boolean().withDefault(const Constant(false))();
BoolColumn get pinned => boolean().withDefault(const Constant(false))();
BoolColumn get archived => boolean().withDefault(const Constant(false))();
BoolColumn get joinedGroup => boolean().withDefault(const Constant(false))();
BoolColumn get leftGroup => boolean().withDefault(const Constant(false))();
BoolColumn get deletedContent =>
boolean().withDefault(const Constant(false))();
IntColumn get stateVersionId => integer().withDefault(const Constant(0))();
BlobColumn get stateEncryptionKey => blob().nullable()();
BlobColumn get myGroupPrivateKey => blob().nullable()();
TextColumn get groupName => text()();
IntColumn get totalMediaCounter => integer().withDefault(const Constant(0))();
BoolColumn get alsoBestFriend =>
boolean().withDefault(const Constant(false))();
IntColumn get deleteMessagesAfterMilliseconds => integer()
.withDefault(const Constant(defaultDeleteMessagesAfterMilliseconds))();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
DateTimeColumn get lastMessageSend => dateTime().nullable()();
DateTimeColumn get lastMessageReceived => dateTime().nullable()();
DateTimeColumn get lastFlameCounterChange => dateTime().nullable()();
DateTimeColumn get lastFlameSync => dateTime().nullable()();
IntColumn get flameCounter => integer().withDefault(const Constant(0))();
IntColumn get maxFlameCounter => integer().withDefault(const Constant(0))();
DateTimeColumn get maxFlameCounterFrom => dateTime().nullable()();
DateTimeColumn get lastMessageExchange =>
dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {groupId};
}
enum MemberState { normal, admin, leftGroup }
@DataClassName('GroupMember')
class GroupMembers extends Table {
TextColumn get groupId =>
text().references(Groups, #groupId, onDelete: KeyAction.cascade)();
IntColumn get contactId => integer().references(Contacts, #userId)();
TextColumn get memberState => textEnum<MemberState>().nullable()();
BlobColumn get groupPublicKey => blob().nullable()();
DateTimeColumn get lastMessage => dateTime().nullable()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {groupId, contactId};
}
enum GroupActionType {
createdGroup,
removedMember,
addMember,
leftGroup,
promoteToAdmin,
demoteToMember,
updatedGroupName,
changeDisplayMaxTime,
}
@DataClassName('GroupHistory')
class GroupHistories extends Table {
TextColumn get groupHistoryId => text()();
TextColumn get groupId =>
text().references(Groups, #groupId, onDelete: KeyAction.cascade)();
IntColumn get contactId =>
integer().nullable().references(Contacts, #userId)();
IntColumn get affectedContactId =>
integer().nullable().references(Contacts, #userId)();
TextColumn get oldGroupName => text().nullable()();
TextColumn get newGroupName => text().nullable()();
IntColumn get newDeleteMessagesAfterMilliseconds => integer().nullable()();
TextColumn get type => textEnum<GroupActionType>()();
DateTimeColumn get actionAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {groupHistoryId};
}
GroupActionType? groupActionTypeFromString(String name) {
for (final v in GroupActionType.values) {
if (v.name == name) return v;
}
return null;
}

View file

@ -0,0 +1,81 @@
import 'dart:convert';
import 'package:drift/drift.dart';
enum MediaType {
image,
video,
gif,
audio,
}
enum UploadState {
// Image/Video was taken. A database entry was created to track it...
initialized,
// Image was stored but not send
storedOnly,
// At this point the user is finished with editing, and the media file can be uploaded
preprocessing,
uploading,
backgroundUploadTaskStarted,
uploaded,
uploadLimitReached,
// readyToUpload,
// uploadTaskStarted,
// receiverNotified,
}
enum DownloadState {
pending,
downloading,
downloaded,
ready,
reuploadRequested
}
@DataClassName('MediaFile')
class MediaFiles extends Table {
TextColumn get mediaId => text()();
TextColumn get type => textEnum<MediaType>()();
TextColumn get uploadState => textEnum<UploadState>().nullable()();
TextColumn get downloadState => textEnum<DownloadState>().nullable()();
BoolColumn get requiresAuthentication =>
boolean().withDefault(const Constant(false))();
BoolColumn get reopenByContact =>
boolean().withDefault(const Constant(false))();
BoolColumn get stored => boolean().withDefault(const Constant(false))();
BoolColumn get isDraftMedia => boolean().withDefault(const Constant(false))();
TextColumn get reuploadRequestedBy =>
text().map(IntListTypeConverter()).nullable()();
IntColumn get displayLimitInMilliseconds => integer().nullable()();
BoolColumn get removeAudio => boolean().nullable()();
BlobColumn get downloadToken => blob().nullable()();
BlobColumn get encryptionKey => blob().nullable()();
BlobColumn get encryptionMac => blob().nullable()();
BlobColumn get encryptionNonce => blob().nullable()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {mediaId};
}
class IntListTypeConverter extends TypeConverter<List<int>, String> {
@override
List<int> fromSql(String fromDb) {
return List<int>.from(jsonDecode(fromDb) as Iterable<dynamic>);
}
@override
String toSql(List<int> value) {
return json.encode(value);
}
}

View file

@ -0,0 +1,84 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/tables/groups.table.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
enum MessageType { media, text }
@DataClassName('Message')
class Messages extends Table {
TextColumn get groupId =>
text().references(Groups, #groupId, onDelete: KeyAction.cascade)();
TextColumn get messageId => text()();
// in case senderId is null, it was send by user itself
IntColumn get senderId =>
integer().nullable().references(Contacts, #userId)();
TextColumn get type => textEnum<MessageType>()();
TextColumn get content => text().nullable()();
TextColumn get mediaId => text()
.nullable()
.references(MediaFiles, #mediaId, onDelete: KeyAction.setNull)();
BoolColumn get mediaStored => boolean().withDefault(const Constant(false))();
BlobColumn get downloadToken => blob().nullable()();
TextColumn get quotesMessageId => text().nullable()();
BoolColumn get isDeletedFromSender =>
boolean().withDefault(const Constant(false))();
DateTimeColumn get openedAt => dateTime().nullable()();
DateTimeColumn get openedByAll => dateTime().nullable()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
DateTimeColumn get modifiedAt => dateTime().nullable()();
DateTimeColumn get ackByUser => dateTime().nullable()();
DateTimeColumn get ackByServer => dateTime().nullable()();
@override
Set<Column> get primaryKey => {messageId};
}
enum MessageActionType {
openedAt,
ackByUserAt,
ackByServerAt,
}
@DataClassName('MessageAction')
class MessageActions extends Table {
TextColumn get messageId =>
text().references(Messages, #messageId, onDelete: KeyAction.cascade)();
IntColumn get contactId =>
integer().references(Contacts, #contactId, onDelete: KeyAction.cascade)();
TextColumn get type => textEnum<MessageActionType>()();
DateTimeColumn get actionAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {messageId, contactId, type};
}
@DataClassName('MessageHistory')
class MessageHistories extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get messageId =>
text().references(Messages, #messageId, onDelete: KeyAction.cascade)();
IntColumn get contactId => integer()
.nullable()
.references(Contacts, #contactId, onDelete: KeyAction.cascade)();
TextColumn get content => text().nullable()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {id};
}

View file

@ -0,0 +1,21 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart';
@DataClassName('Reaction')
class Reactions extends Table {
TextColumn get messageId =>
text().references(Messages, #messageId, onDelete: KeyAction.cascade)();
TextColumn get emoji => text()();
// in case senderId is null, it was send by user itself
IntColumn get senderId => integer()
.nullable()
.references(Contacts, #userId, onDelete: KeyAction.cascade)();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {messageId, senderId, emoji};
}

View file

@ -0,0 +1,42 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart';
@DataClassName('Receipt')
class Receipts extends Table {
TextColumn get receiptId => text()();
IntColumn get contactId =>
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
// in case a message is deleted, it should be also deleted from the receipts table
TextColumn get messageId => text()
.nullable()
.references(Messages, #messageId, onDelete: KeyAction.cascade)();
/// This is the protobuf 'Message'
BlobColumn get message => blob()();
BoolColumn get contactWillSendsReceipt =>
boolean().withDefault(const Constant(true))();
DateTimeColumn get ackByServerAt => dateTime().nullable()();
IntColumn get retryCount => integer().withDefault(const Constant(0))();
DateTimeColumn get lastRetry => dateTime().nullable()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {receiptId};
}
@DataClassName('ReceivedReceipt')
class ReceivedReceipts extends Table {
TextColumn get receiptId => text()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {receiptId};
}

View file

@ -0,0 +1,13 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
@DataClassName('SignalContactPreKey')
class SignalContactPreKeys extends Table {
IntColumn get contactId =>
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
IntColumn get preKeyId => integer()();
BlobColumn get preKey => blob()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {contactId, preKeyId};
}

View file

@ -0,0 +1,14 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
@DataClassName('SignalContactSignedPreKey')
class SignalContactSignedPreKeys extends Table {
IntColumn get contactId =>
integer().references(Contacts, #userId, onDelete: KeyAction.cascade)();
IntColumn get signedPreKeyId => integer()();
BlobColumn get signedPreKey => blob()();
BlobColumn get signedPreKeySignature => blob()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {contactId};
}

View file

@ -1,6 +1,6 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts_table.dart';
import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/database/tables_old/contacts_table.dart';
import 'package:twonly/src/database/tables_old/messages_table.dart';
@DataClassName('MessageRetransmission')
class MessageRetransmissions extends Table {

View file

@ -1,5 +1,5 @@
import 'package:drift/drift.dart';
import 'package:twonly/src/database/tables/contacts_table.dart';
import 'package:twonly/src/database/tables_old/contacts_table.dart';
enum MessageKind {
textMessage,

View file

@ -0,0 +1,12 @@
import 'package:drift/drift.dart';
@DataClassName('SignalIdentityKeyStore')
class SignalIdentityKeyStores extends Table {
IntColumn get deviceId => integer()();
TextColumn get name => text()();
BlobColumn get identityKey => blob()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {deviceId, name};
}

View file

@ -0,0 +1,11 @@
import 'package:drift/drift.dart';
@DataClassName('SignalPreKeyStore')
class SignalPreKeyStores extends Table {
IntColumn get preKeyId => integer()();
BlobColumn get preKey => blob()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {preKeyId};
}

View file

@ -0,0 +1,10 @@
import 'package:drift/drift.dart';
@DataClassName('SignalSenderKeyStore')
class SignalSenderKeyStores extends Table {
TextColumn get senderKeyName => text()();
BlobColumn get senderKey => blob()();
@override
Set<Column> get primaryKey => {senderKeyName};
}

View file

@ -0,0 +1,12 @@
import 'package:drift/drift.dart';
@DataClassName('SignalSessionStore')
class SignalSessionStores extends Table {
IntColumn get deviceId => integer()();
TextColumn get name => text()();
BlobColumn get sessionRecord => blob()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
@override
Set<Column> get primaryKey => {deviceId, name};
}

View file

@ -0,0 +1,129 @@
import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart'
show DriftNativeOptions, driftDatabase;
import 'package:path_provider/path_provider.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/daos/groups.dao.dart';
import 'package:twonly/src/database/daos/mediafiles.dao.dart';
import 'package:twonly/src/database/daos/messages.dao.dart';
import 'package:twonly/src/database/daos/reactions.dao.dart';
import 'package:twonly/src/database/daos/receipts.dao.dart';
import 'package:twonly/src/database/daos/signal.dao.dart';
import 'package:twonly/src/database/tables/contacts.table.dart';
import 'package:twonly/src/database/tables/groups.table.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/tables/reactions.table.dart';
import 'package:twonly/src/database/tables/receipts.table.dart';
import 'package:twonly/src/database/tables/signal_contact_prekey.table.dart';
import 'package:twonly/src/database/tables/signal_contact_signed_prekey.table.dart';
import 'package:twonly/src/database/tables/signal_identity_key_store.table.dart';
import 'package:twonly/src/database/tables/signal_pre_key_store.table.dart';
import 'package:twonly/src/database/tables/signal_sender_key_store.table.dart';
import 'package:twonly/src/database/tables/signal_session_store.table.dart';
import 'package:twonly/src/utils/log.dart';
part 'twonly.db.g.dart';
// You can then create a database class that includes this table
@DriftDatabase(
tables: [
Contacts,
Messages,
MessageHistories,
MediaFiles,
Reactions,
Groups,
GroupMembers,
Receipts,
ReceivedReceipts,
SignalIdentityKeyStores,
SignalPreKeyStores,
SignalSenderKeyStores,
SignalSessionStores,
SignalContactPreKeys,
SignalContactSignedPreKeys,
MessageActions,
GroupHistories,
],
daos: [
MessagesDao,
ContactsDao,
SignalDao,
ReceiptsDao,
GroupsDao,
ReactionsDao,
MediaFilesDao,
],
)
class TwonlyDB extends _$TwonlyDB {
TwonlyDB([QueryExecutor? e])
: super(
e ?? _openConnection(),
);
// ignore: matching_super_parameters
TwonlyDB.forTesting(DatabaseConnection super.connection);
@override
int get schemaVersion => 1;
static QueryExecutor _openConnection() {
return driftDatabase(
name: 'twonly',
native: const DriftNativeOptions(
databaseDirectory: getApplicationSupportDirectory,
),
);
}
@override
MigrationStrategy get migration {
return MigrationStrategy(
beforeOpen: (details) async {
await customStatement('PRAGMA foreign_keys = ON');
},
// onUpgrade: stepByStep(),
);
}
void markUpdated() {
notifyUpdates({TableUpdate.onTable(messages, kind: UpdateKind.update)});
notifyUpdates({TableUpdate.onTable(contacts, kind: UpdateKind.update)});
}
Future<void> printTableSizes() async {
final result = await customSelect(
'SELECT name, SUM(pgsize) as size FROM dbstat GROUP BY name',
).get();
for (final row in result) {
final tableName = row.read<String>('name');
final tableSize = row.read<String>('size');
Log.info('Table: $tableName, Size: $tableSize bytes');
}
}
Future<void> deleteDataForTwonlySafe() async {
// await delete(messages).go();
// await delete(messageRetransmissions).go();
// await delete(mediaUploads).go();
// await update(contacts).write(
// const ContactsCompanion(
// avatarSvg: Value(null),
// myAvatarCounter: Value(0),
// ),
// );
// await delete(signalContactPreKeys).go();
// await delete(signalContactSignedPreKeys).go();
// await (delete(signalPreKeyStores)
// ..where(
// (t) => (t.createdAt.isSmallerThanValue(
// DateTime.now().subtract(
// const Duration(days: 25),
// ),
// )),
// ))
// .go();
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,25 +2,20 @@ import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart'
show DriftNativeOptions, driftDatabase;
import 'package:path_provider/path_provider.dart';
import 'package:twonly/src/database/daos/contacts_dao.dart';
import 'package:twonly/src/database/daos/media_uploads_dao.dart';
import 'package:twonly/src/database/daos/message_retransmissions.dao.dart';
import 'package:twonly/src/database/daos/messages_dao.dart';
import 'package:twonly/src/database/daos/signal_dao.dart';
import 'package:twonly/src/database/tables/contacts_table.dart';
import 'package:twonly/src/database/tables/media_uploads_table.dart';
import 'package:twonly/src/database/tables/message_retransmissions.dart';
import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/database/tables/signal_contact_prekey_table.dart';
import 'package:twonly/src/database/tables/signal_contact_signed_prekey_table.dart';
import 'package:twonly/src/database/tables/signal_identity_key_store_table.dart';
import 'package:twonly/src/database/tables/signal_pre_key_store_table.dart';
import 'package:twonly/src/database/tables/signal_sender_key_store_table.dart';
import 'package:twonly/src/database/tables/signal_session_store_table.dart';
import 'package:twonly/src/database/twonly_database.steps.dart';
import 'package:twonly/src/database/tables_old/contacts_table.dart';
import 'package:twonly/src/database/tables_old/media_uploads_table.dart';
import 'package:twonly/src/database/tables_old/message_retransmissions.dart';
import 'package:twonly/src/database/tables_old/messages_table.dart';
import 'package:twonly/src/database/tables_old/signal_contact_prekey_table.dart';
import 'package:twonly/src/database/tables_old/signal_contact_signed_prekey_table.dart';
import 'package:twonly/src/database/tables_old/signal_identity_key_store_table.dart';
import 'package:twonly/src/database/tables_old/signal_pre_key_store_table.dart';
import 'package:twonly/src/database/tables_old/signal_sender_key_store_table.dart';
import 'package:twonly/src/database/tables_old/signal_session_store_table.dart';
import 'package:twonly/src/database/twonly_database_old.steps.dart';
import 'package:twonly/src/utils/log.dart';
part 'twonly_database.g.dart';
part 'twonly_database_old.g.dart';
// You can then create a database class that includes this table
@DriftDatabase(
@ -36,22 +31,16 @@ part 'twonly_database.g.dart';
SignalContactSignedPreKeys,
MessageRetransmissions,
],
daos: [
MessagesDao,
ContactsDao,
MediaUploadsDao,
SignalDao,
MessageRetransmissionDao,
],
daos: [],
)
class TwonlyDatabase extends _$TwonlyDatabase {
TwonlyDatabase([QueryExecutor? e])
class TwonlyDatabaseOld extends _$TwonlyDatabaseOld {
TwonlyDatabaseOld([QueryExecutor? e])
: super(
e ?? _openConnection(),
);
// ignore: matching_super_parameters
TwonlyDatabase.forTesting(DatabaseConnection super.connection);
TwonlyDatabaseOld.forTesting(DatabaseConnection super.connection);
@override
int get schemaVersion => 17;

View file

@ -1,6 +1,6 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'twonly_database.dart';
part of 'twonly_database_old.dart';
// ignore_for_file: type=lint
class $ContactsTable extends Contacts with TableInfo<$ContactsTable, Contact> {
@ -4443,9 +4443,9 @@ class MessageRetransmissionsCompanion
}
}
abstract class _$TwonlyDatabase extends GeneratedDatabase {
_$TwonlyDatabase(QueryExecutor e) : super(e);
$TwonlyDatabaseManager get managers => $TwonlyDatabaseManager(this);
abstract class _$TwonlyDatabaseOld extends GeneratedDatabase {
_$TwonlyDatabaseOld(QueryExecutor e) : super(e);
$TwonlyDatabaseOldManager get managers => $TwonlyDatabaseOldManager(this);
late final $ContactsTable contacts = $ContactsTable(this);
late final $MessagesTable messages = $MessagesTable(this);
late final $MediaUploadsTable mediaUploads = $MediaUploadsTable(this);
@ -4463,13 +4463,6 @@ abstract class _$TwonlyDatabase extends GeneratedDatabase {
$SignalContactSignedPreKeysTable(this);
late final $MessageRetransmissionsTable messageRetransmissions =
$MessageRetransmissionsTable(this);
late final MessagesDao messagesDao = MessagesDao(this as TwonlyDatabase);
late final ContactsDao contactsDao = ContactsDao(this as TwonlyDatabase);
late final MediaUploadsDao mediaUploadsDao =
MediaUploadsDao(this as TwonlyDatabase);
late final SignalDao signalDao = SignalDao(this as TwonlyDatabase);
late final MessageRetransmissionDao messageRetransmissionDao =
MessageRetransmissionDao(this as TwonlyDatabase);
@override
Iterable<TableInfo<Table, Object?>> get allTables =>
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
@ -4559,11 +4552,11 @@ typedef $$ContactsTableUpdateCompanionBuilder = ContactsCompanion Function({
});
final class $$ContactsTableReferences
extends BaseReferences<_$TwonlyDatabase, $ContactsTable, Contact> {
extends BaseReferences<_$TwonlyDatabaseOld, $ContactsTable, Contact> {
$$ContactsTableReferences(super.$_db, super.$_table, super.$_typedResult);
static MultiTypedResultKey<$MessagesTable, List<Message>> _messagesRefsTable(
_$TwonlyDatabase db) =>
_$TwonlyDatabaseOld db) =>
MultiTypedResultKey.fromTable(db.messages,
aliasName:
$_aliasNameGenerator(db.contacts.userId, db.messages.contactId));
@ -4579,7 +4572,7 @@ final class $$ContactsTableReferences
static MultiTypedResultKey<$MessageRetransmissionsTable,
List<MessageRetransmission>> _messageRetransmissionsRefsTable(
_$TwonlyDatabase db) =>
_$TwonlyDatabaseOld db) =>
MultiTypedResultKey.fromTable(db.messageRetransmissions,
aliasName: $_aliasNameGenerator(
db.contacts.userId, db.messageRetransmissions.contactId));
@ -4599,7 +4592,7 @@ final class $$ContactsTableReferences
}
class $$ContactsTableFilterComposer
extends Composer<_$TwonlyDatabase, $ContactsTable> {
extends Composer<_$TwonlyDatabaseOld, $ContactsTable> {
$$ContactsTableFilterComposer({
required super.$db,
required super.$table,
@ -4730,7 +4723,7 @@ class $$ContactsTableFilterComposer
}
class $$ContactsTableOrderingComposer
extends Composer<_$TwonlyDatabase, $ContactsTable> {
extends Composer<_$TwonlyDatabaseOld, $ContactsTable> {
$$ContactsTableOrderingComposer({
required super.$db,
required super.$table,
@ -4819,7 +4812,7 @@ class $$ContactsTableOrderingComposer
}
class $$ContactsTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $ContactsTable> {
extends Composer<_$TwonlyDatabaseOld, $ContactsTable> {
$$ContactsTableAnnotationComposer({
required super.$db,
required super.$table,
@ -4942,7 +4935,7 @@ class $$ContactsTableAnnotationComposer
}
class $$ContactsTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$ContactsTable,
Contact,
$$ContactsTableFilterComposer,
@ -4954,7 +4947,7 @@ class $$ContactsTableTableManager extends RootTableManager<
Contact,
PrefetchHooks Function(
{bool messagesRefs, bool messageRetransmissionsRefs})> {
$$ContactsTableTableManager(_$TwonlyDatabase db, $ContactsTable table)
$$ContactsTableTableManager(_$TwonlyDatabaseOld db, $ContactsTable table)
: super(TableManagerState(
db: db,
table: table,
@ -5112,7 +5105,7 @@ class $$ContactsTableTableManager extends RootTableManager<
}
typedef $$ContactsTableProcessedTableManager = ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$ContactsTable,
Contact,
$$ContactsTableFilterComposer,
@ -5166,10 +5159,10 @@ typedef $$MessagesTableUpdateCompanionBuilder = MessagesCompanion Function({
});
final class $$MessagesTableReferences
extends BaseReferences<_$TwonlyDatabase, $MessagesTable, Message> {
extends BaseReferences<_$TwonlyDatabaseOld, $MessagesTable, Message> {
$$MessagesTableReferences(super.$_db, super.$_table, super.$_typedResult);
static $ContactsTable _contactIdTable(_$TwonlyDatabase db) =>
static $ContactsTable _contactIdTable(_$TwonlyDatabaseOld db) =>
db.contacts.createAlias(
$_aliasNameGenerator(db.messages.contactId, db.contacts.userId));
@ -5186,7 +5179,7 @@ final class $$MessagesTableReferences
static MultiTypedResultKey<$MessageRetransmissionsTable,
List<MessageRetransmission>> _messageRetransmissionsRefsTable(
_$TwonlyDatabase db) =>
_$TwonlyDatabaseOld db) =>
MultiTypedResultKey.fromTable(db.messageRetransmissions,
aliasName: $_aliasNameGenerator(
db.messages.messageId, db.messageRetransmissions.messageId));
@ -5206,7 +5199,7 @@ final class $$MessagesTableReferences
}
class $$MessagesTableFilterComposer
extends Composer<_$TwonlyDatabase, $MessagesTable> {
extends Composer<_$TwonlyDatabaseOld, $MessagesTable> {
$$MessagesTableFilterComposer({
required super.$db,
required super.$table,
@ -5324,7 +5317,7 @@ class $$MessagesTableFilterComposer
}
class $$MessagesTableOrderingComposer
extends Composer<_$TwonlyDatabase, $MessagesTable> {
extends Composer<_$TwonlyDatabaseOld, $MessagesTable> {
$$MessagesTableOrderingComposer({
required super.$db,
required super.$table,
@ -5415,7 +5408,7 @@ class $$MessagesTableOrderingComposer
}
class $$MessagesTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $MessagesTable> {
extends Composer<_$TwonlyDatabaseOld, $MessagesTable> {
$$MessagesTableAnnotationComposer({
required super.$db,
required super.$table,
@ -5521,7 +5514,7 @@ class $$MessagesTableAnnotationComposer
}
class $$MessagesTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$MessagesTable,
Message,
$$MessagesTableFilterComposer,
@ -5532,7 +5525,7 @@ class $$MessagesTableTableManager extends RootTableManager<
(Message, $$MessagesTableReferences),
Message,
PrefetchHooks Function({bool contactId, bool messageRetransmissionsRefs})> {
$$MessagesTableTableManager(_$TwonlyDatabase db, $MessagesTable table)
$$MessagesTableTableManager(_$TwonlyDatabaseOld db, $MessagesTable table)
: super(TableManagerState(
db: db,
table: table,
@ -5684,7 +5677,7 @@ class $$MessagesTableTableManager extends RootTableManager<
}
typedef $$MessagesTableProcessedTableManager = ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$MessagesTable,
Message,
$$MessagesTableFilterComposer,
@ -5713,7 +5706,7 @@ typedef $$MediaUploadsTableUpdateCompanionBuilder = MediaUploadsCompanion
});
class $$MediaUploadsTableFilterComposer
extends Composer<_$TwonlyDatabase, $MediaUploadsTable> {
extends Composer<_$TwonlyDatabaseOld, $MediaUploadsTable> {
$$MediaUploadsTableFilterComposer({
required super.$db,
required super.$table,
@ -5748,7 +5741,7 @@ class $$MediaUploadsTableFilterComposer
}
class $$MediaUploadsTableOrderingComposer
extends Composer<_$TwonlyDatabase, $MediaUploadsTable> {
extends Composer<_$TwonlyDatabaseOld, $MediaUploadsTable> {
$$MediaUploadsTableOrderingComposer({
required super.$db,
required super.$table,
@ -5775,7 +5768,7 @@ class $$MediaUploadsTableOrderingComposer
}
class $$MediaUploadsTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $MediaUploadsTable> {
extends Composer<_$TwonlyDatabaseOld, $MediaUploadsTable> {
$$MediaUploadsTableAnnotationComposer({
required super.$db,
required super.$table,
@ -5802,7 +5795,7 @@ class $$MediaUploadsTableAnnotationComposer
}
class $$MediaUploadsTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$MediaUploadsTable,
MediaUpload,
$$MediaUploadsTableFilterComposer,
@ -5812,11 +5805,12 @@ class $$MediaUploadsTableTableManager extends RootTableManager<
$$MediaUploadsTableUpdateCompanionBuilder,
(
MediaUpload,
BaseReferences<_$TwonlyDatabase, $MediaUploadsTable, MediaUpload>
BaseReferences<_$TwonlyDatabaseOld, $MediaUploadsTable, MediaUpload>
),
MediaUpload,
PrefetchHooks Function()> {
$$MediaUploadsTableTableManager(_$TwonlyDatabase db, $MediaUploadsTable table)
$$MediaUploadsTableTableManager(
_$TwonlyDatabaseOld db, $MediaUploadsTable table)
: super(TableManagerState(
db: db,
table: table,
@ -5862,7 +5856,7 @@ class $$MediaUploadsTableTableManager extends RootTableManager<
}
typedef $$MediaUploadsTableProcessedTableManager = ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$MediaUploadsTable,
MediaUpload,
$$MediaUploadsTableFilterComposer,
@ -5872,7 +5866,7 @@ typedef $$MediaUploadsTableProcessedTableManager = ProcessedTableManager<
$$MediaUploadsTableUpdateCompanionBuilder,
(
MediaUpload,
BaseReferences<_$TwonlyDatabase, $MediaUploadsTable, MediaUpload>
BaseReferences<_$TwonlyDatabaseOld, $MediaUploadsTable, MediaUpload>
),
MediaUpload,
PrefetchHooks Function()>;
@ -5894,7 +5888,7 @@ typedef $$SignalIdentityKeyStoresTableUpdateCompanionBuilder
});
class $$SignalIdentityKeyStoresTableFilterComposer
extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable> {
$$SignalIdentityKeyStoresTableFilterComposer({
required super.$db,
required super.$table,
@ -5916,7 +5910,7 @@ class $$SignalIdentityKeyStoresTableFilterComposer
}
class $$SignalIdentityKeyStoresTableOrderingComposer
extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable> {
$$SignalIdentityKeyStoresTableOrderingComposer({
required super.$db,
required super.$table,
@ -5938,7 +5932,7 @@ class $$SignalIdentityKeyStoresTableOrderingComposer
}
class $$SignalIdentityKeyStoresTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $SignalIdentityKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable> {
$$SignalIdentityKeyStoresTableAnnotationComposer({
required super.$db,
required super.$table,
@ -5960,7 +5954,7 @@ class $$SignalIdentityKeyStoresTableAnnotationComposer
}
class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalIdentityKeyStoresTable,
SignalIdentityKeyStore,
$$SignalIdentityKeyStoresTableFilterComposer,
@ -5970,13 +5964,13 @@ class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager<
$$SignalIdentityKeyStoresTableUpdateCompanionBuilder,
(
SignalIdentityKeyStore,
BaseReferences<_$TwonlyDatabase, $SignalIdentityKeyStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable,
SignalIdentityKeyStore>
),
SignalIdentityKeyStore,
PrefetchHooks Function()> {
$$SignalIdentityKeyStoresTableTableManager(
_$TwonlyDatabase db, $SignalIdentityKeyStoresTable table)
_$TwonlyDatabaseOld db, $SignalIdentityKeyStoresTable table)
: super(TableManagerState(
db: db,
table: table,
@ -6026,7 +6020,7 @@ class $$SignalIdentityKeyStoresTableTableManager extends RootTableManager<
typedef $$SignalIdentityKeyStoresTableProcessedTableManager
= ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalIdentityKeyStoresTable,
SignalIdentityKeyStore,
$$SignalIdentityKeyStoresTableFilterComposer,
@ -6036,7 +6030,7 @@ typedef $$SignalIdentityKeyStoresTableProcessedTableManager
$$SignalIdentityKeyStoresTableUpdateCompanionBuilder,
(
SignalIdentityKeyStore,
BaseReferences<_$TwonlyDatabase, $SignalIdentityKeyStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalIdentityKeyStoresTable,
SignalIdentityKeyStore>
),
SignalIdentityKeyStore,
@ -6055,7 +6049,7 @@ typedef $$SignalPreKeyStoresTableUpdateCompanionBuilder
});
class $$SignalPreKeyStoresTableFilterComposer
extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable> {
$$SignalPreKeyStoresTableFilterComposer({
required super.$db,
required super.$table,
@ -6074,7 +6068,7 @@ class $$SignalPreKeyStoresTableFilterComposer
}
class $$SignalPreKeyStoresTableOrderingComposer
extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable> {
$$SignalPreKeyStoresTableOrderingComposer({
required super.$db,
required super.$table,
@ -6093,7 +6087,7 @@ class $$SignalPreKeyStoresTableOrderingComposer
}
class $$SignalPreKeyStoresTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $SignalPreKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable> {
$$SignalPreKeyStoresTableAnnotationComposer({
required super.$db,
required super.$table,
@ -6112,7 +6106,7 @@ class $$SignalPreKeyStoresTableAnnotationComposer
}
class $$SignalPreKeyStoresTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalPreKeyStoresTable,
SignalPreKeyStore,
$$SignalPreKeyStoresTableFilterComposer,
@ -6122,13 +6116,13 @@ class $$SignalPreKeyStoresTableTableManager extends RootTableManager<
$$SignalPreKeyStoresTableUpdateCompanionBuilder,
(
SignalPreKeyStore,
BaseReferences<_$TwonlyDatabase, $SignalPreKeyStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable,
SignalPreKeyStore>
),
SignalPreKeyStore,
PrefetchHooks Function()> {
$$SignalPreKeyStoresTableTableManager(
_$TwonlyDatabase db, $SignalPreKeyStoresTable table)
_$TwonlyDatabaseOld db, $SignalPreKeyStoresTable table)
: super(TableManagerState(
db: db,
table: table,
@ -6167,7 +6161,7 @@ class $$SignalPreKeyStoresTableTableManager extends RootTableManager<
}
typedef $$SignalPreKeyStoresTableProcessedTableManager = ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalPreKeyStoresTable,
SignalPreKeyStore,
$$SignalPreKeyStoresTableFilterComposer,
@ -6177,7 +6171,7 @@ typedef $$SignalPreKeyStoresTableProcessedTableManager = ProcessedTableManager<
$$SignalPreKeyStoresTableUpdateCompanionBuilder,
(
SignalPreKeyStore,
BaseReferences<_$TwonlyDatabase, $SignalPreKeyStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalPreKeyStoresTable,
SignalPreKeyStore>
),
SignalPreKeyStore,
@ -6196,7 +6190,7 @@ typedef $$SignalSenderKeyStoresTableUpdateCompanionBuilder
});
class $$SignalSenderKeyStoresTableFilterComposer
extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable> {
$$SignalSenderKeyStoresTableFilterComposer({
required super.$db,
required super.$table,
@ -6212,7 +6206,7 @@ class $$SignalSenderKeyStoresTableFilterComposer
}
class $$SignalSenderKeyStoresTableOrderingComposer
extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable> {
$$SignalSenderKeyStoresTableOrderingComposer({
required super.$db,
required super.$table,
@ -6229,7 +6223,7 @@ class $$SignalSenderKeyStoresTableOrderingComposer
}
class $$SignalSenderKeyStoresTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $SignalSenderKeyStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable> {
$$SignalSenderKeyStoresTableAnnotationComposer({
required super.$db,
required super.$table,
@ -6245,7 +6239,7 @@ class $$SignalSenderKeyStoresTableAnnotationComposer
}
class $$SignalSenderKeyStoresTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalSenderKeyStoresTable,
SignalSenderKeyStore,
$$SignalSenderKeyStoresTableFilterComposer,
@ -6255,13 +6249,13 @@ class $$SignalSenderKeyStoresTableTableManager extends RootTableManager<
$$SignalSenderKeyStoresTableUpdateCompanionBuilder,
(
SignalSenderKeyStore,
BaseReferences<_$TwonlyDatabase, $SignalSenderKeyStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable,
SignalSenderKeyStore>
),
SignalSenderKeyStore,
PrefetchHooks Function()> {
$$SignalSenderKeyStoresTableTableManager(
_$TwonlyDatabase db, $SignalSenderKeyStoresTable table)
_$TwonlyDatabaseOld db, $SignalSenderKeyStoresTable table)
: super(TableManagerState(
db: db,
table: table,
@ -6303,7 +6297,7 @@ class $$SignalSenderKeyStoresTableTableManager extends RootTableManager<
typedef $$SignalSenderKeyStoresTableProcessedTableManager
= ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalSenderKeyStoresTable,
SignalSenderKeyStore,
$$SignalSenderKeyStoresTableFilterComposer,
@ -6313,7 +6307,7 @@ typedef $$SignalSenderKeyStoresTableProcessedTableManager
$$SignalSenderKeyStoresTableUpdateCompanionBuilder,
(
SignalSenderKeyStore,
BaseReferences<_$TwonlyDatabase, $SignalSenderKeyStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalSenderKeyStoresTable,
SignalSenderKeyStore>
),
SignalSenderKeyStore,
@ -6336,7 +6330,7 @@ typedef $$SignalSessionStoresTableUpdateCompanionBuilder
});
class $$SignalSessionStoresTableFilterComposer
extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalSessionStoresTable> {
$$SignalSessionStoresTableFilterComposer({
required super.$db,
required super.$table,
@ -6358,7 +6352,7 @@ class $$SignalSessionStoresTableFilterComposer
}
class $$SignalSessionStoresTableOrderingComposer
extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalSessionStoresTable> {
$$SignalSessionStoresTableOrderingComposer({
required super.$db,
required super.$table,
@ -6381,7 +6375,7 @@ class $$SignalSessionStoresTableOrderingComposer
}
class $$SignalSessionStoresTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $SignalSessionStoresTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalSessionStoresTable> {
$$SignalSessionStoresTableAnnotationComposer({
required super.$db,
required super.$table,
@ -6403,7 +6397,7 @@ class $$SignalSessionStoresTableAnnotationComposer
}
class $$SignalSessionStoresTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalSessionStoresTable,
SignalSessionStore,
$$SignalSessionStoresTableFilterComposer,
@ -6413,13 +6407,13 @@ class $$SignalSessionStoresTableTableManager extends RootTableManager<
$$SignalSessionStoresTableUpdateCompanionBuilder,
(
SignalSessionStore,
BaseReferences<_$TwonlyDatabase, $SignalSessionStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalSessionStoresTable,
SignalSessionStore>
),
SignalSessionStore,
PrefetchHooks Function()> {
$$SignalSessionStoresTableTableManager(
_$TwonlyDatabase db, $SignalSessionStoresTable table)
_$TwonlyDatabaseOld db, $SignalSessionStoresTable table)
: super(TableManagerState(
db: db,
table: table,
@ -6467,7 +6461,7 @@ class $$SignalSessionStoresTableTableManager extends RootTableManager<
}
typedef $$SignalSessionStoresTableProcessedTableManager = ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalSessionStoresTable,
SignalSessionStore,
$$SignalSessionStoresTableFilterComposer,
@ -6477,7 +6471,7 @@ typedef $$SignalSessionStoresTableProcessedTableManager = ProcessedTableManager<
$$SignalSessionStoresTableUpdateCompanionBuilder,
(
SignalSessionStore,
BaseReferences<_$TwonlyDatabase, $SignalSessionStoresTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalSessionStoresTable,
SignalSessionStore>
),
SignalSessionStore,
@ -6500,7 +6494,7 @@ typedef $$SignalContactPreKeysTableUpdateCompanionBuilder
});
class $$SignalContactPreKeysTableFilterComposer
extends Composer<_$TwonlyDatabase, $SignalContactPreKeysTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalContactPreKeysTable> {
$$SignalContactPreKeysTableFilterComposer({
required super.$db,
required super.$table,
@ -6522,7 +6516,7 @@ class $$SignalContactPreKeysTableFilterComposer
}
class $$SignalContactPreKeysTableOrderingComposer
extends Composer<_$TwonlyDatabase, $SignalContactPreKeysTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalContactPreKeysTable> {
$$SignalContactPreKeysTableOrderingComposer({
required super.$db,
required super.$table,
@ -6544,7 +6538,7 @@ class $$SignalContactPreKeysTableOrderingComposer
}
class $$SignalContactPreKeysTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $SignalContactPreKeysTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalContactPreKeysTable> {
$$SignalContactPreKeysTableAnnotationComposer({
required super.$db,
required super.$table,
@ -6566,7 +6560,7 @@ class $$SignalContactPreKeysTableAnnotationComposer
}
class $$SignalContactPreKeysTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalContactPreKeysTable,
SignalContactPreKey,
$$SignalContactPreKeysTableFilterComposer,
@ -6576,13 +6570,13 @@ class $$SignalContactPreKeysTableTableManager extends RootTableManager<
$$SignalContactPreKeysTableUpdateCompanionBuilder,
(
SignalContactPreKey,
BaseReferences<_$TwonlyDatabase, $SignalContactPreKeysTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalContactPreKeysTable,
SignalContactPreKey>
),
SignalContactPreKey,
PrefetchHooks Function()> {
$$SignalContactPreKeysTableTableManager(
_$TwonlyDatabase db, $SignalContactPreKeysTable table)
_$TwonlyDatabaseOld db, $SignalContactPreKeysTable table)
: super(TableManagerState(
db: db,
table: table,
@ -6631,7 +6625,7 @@ class $$SignalContactPreKeysTableTableManager extends RootTableManager<
typedef $$SignalContactPreKeysTableProcessedTableManager
= ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalContactPreKeysTable,
SignalContactPreKey,
$$SignalContactPreKeysTableFilterComposer,
@ -6641,7 +6635,7 @@ typedef $$SignalContactPreKeysTableProcessedTableManager
$$SignalContactPreKeysTableUpdateCompanionBuilder,
(
SignalContactPreKey,
BaseReferences<_$TwonlyDatabase, $SignalContactPreKeysTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalContactPreKeysTable,
SignalContactPreKey>
),
SignalContactPreKey,
@ -6664,7 +6658,7 @@ typedef $$SignalContactSignedPreKeysTableUpdateCompanionBuilder
});
class $$SignalContactSignedPreKeysTableFilterComposer
extends Composer<_$TwonlyDatabase, $SignalContactSignedPreKeysTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable> {
$$SignalContactSignedPreKeysTableFilterComposer({
required super.$db,
required super.$table,
@ -6691,7 +6685,7 @@ class $$SignalContactSignedPreKeysTableFilterComposer
}
class $$SignalContactSignedPreKeysTableOrderingComposer
extends Composer<_$TwonlyDatabase, $SignalContactSignedPreKeysTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable> {
$$SignalContactSignedPreKeysTableOrderingComposer({
required super.$db,
required super.$table,
@ -6719,7 +6713,7 @@ class $$SignalContactSignedPreKeysTableOrderingComposer
}
class $$SignalContactSignedPreKeysTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $SignalContactSignedPreKeysTable> {
extends Composer<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable> {
$$SignalContactSignedPreKeysTableAnnotationComposer({
required super.$db,
required super.$table,
@ -6744,7 +6738,7 @@ class $$SignalContactSignedPreKeysTableAnnotationComposer
}
class $$SignalContactSignedPreKeysTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalContactSignedPreKeysTable,
SignalContactSignedPreKey,
$$SignalContactSignedPreKeysTableFilterComposer,
@ -6754,13 +6748,13 @@ class $$SignalContactSignedPreKeysTableTableManager extends RootTableManager<
$$SignalContactSignedPreKeysTableUpdateCompanionBuilder,
(
SignalContactSignedPreKey,
BaseReferences<_$TwonlyDatabase, $SignalContactSignedPreKeysTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable,
SignalContactSignedPreKey>
),
SignalContactSignedPreKey,
PrefetchHooks Function()> {
$$SignalContactSignedPreKeysTableTableManager(
_$TwonlyDatabase db, $SignalContactSignedPreKeysTable table)
_$TwonlyDatabaseOld db, $SignalContactSignedPreKeysTable table)
: super(TableManagerState(
db: db,
table: table,
@ -6810,7 +6804,7 @@ class $$SignalContactSignedPreKeysTableTableManager extends RootTableManager<
typedef $$SignalContactSignedPreKeysTableProcessedTableManager
= ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$SignalContactSignedPreKeysTable,
SignalContactSignedPreKey,
$$SignalContactSignedPreKeysTableFilterComposer,
@ -6820,7 +6814,7 @@ typedef $$SignalContactSignedPreKeysTableProcessedTableManager
$$SignalContactSignedPreKeysTableUpdateCompanionBuilder,
(
SignalContactSignedPreKey,
BaseReferences<_$TwonlyDatabase, $SignalContactSignedPreKeysTable,
BaseReferences<_$TwonlyDatabaseOld, $SignalContactSignedPreKeysTable,
SignalContactSignedPreKey>
),
SignalContactSignedPreKey,
@ -6851,11 +6845,11 @@ typedef $$MessageRetransmissionsTableUpdateCompanionBuilder
});
final class $$MessageRetransmissionsTableReferences extends BaseReferences<
_$TwonlyDatabase, $MessageRetransmissionsTable, MessageRetransmission> {
_$TwonlyDatabaseOld, $MessageRetransmissionsTable, MessageRetransmission> {
$$MessageRetransmissionsTableReferences(
super.$_db, super.$_table, super.$_typedResult);
static $ContactsTable _contactIdTable(_$TwonlyDatabase db) =>
static $ContactsTable _contactIdTable(_$TwonlyDatabaseOld db) =>
db.contacts.createAlias($_aliasNameGenerator(
db.messageRetransmissions.contactId, db.contacts.userId));
@ -6870,7 +6864,7 @@ final class $$MessageRetransmissionsTableReferences extends BaseReferences<
manager.$state.copyWith(prefetchedData: [item]));
}
static $MessagesTable _messageIdTable(_$TwonlyDatabase db) =>
static $MessagesTable _messageIdTable(_$TwonlyDatabaseOld db) =>
db.messages.createAlias($_aliasNameGenerator(
db.messageRetransmissions.messageId, db.messages.messageId));
@ -6887,7 +6881,7 @@ final class $$MessageRetransmissionsTableReferences extends BaseReferences<
}
class $$MessageRetransmissionsTableFilterComposer
extends Composer<_$TwonlyDatabase, $MessageRetransmissionsTable> {
extends Composer<_$TwonlyDatabaseOld, $MessageRetransmissionsTable> {
$$MessageRetransmissionsTableFilterComposer({
required super.$db,
required super.$table,
@ -6961,7 +6955,7 @@ class $$MessageRetransmissionsTableFilterComposer
}
class $$MessageRetransmissionsTableOrderingComposer
extends Composer<_$TwonlyDatabase, $MessageRetransmissionsTable> {
extends Composer<_$TwonlyDatabaseOld, $MessageRetransmissionsTable> {
$$MessageRetransmissionsTableOrderingComposer({
required super.$db,
required super.$table,
@ -7036,7 +7030,7 @@ class $$MessageRetransmissionsTableOrderingComposer
}
class $$MessageRetransmissionsTableAnnotationComposer
extends Composer<_$TwonlyDatabase, $MessageRetransmissionsTable> {
extends Composer<_$TwonlyDatabaseOld, $MessageRetransmissionsTable> {
$$MessageRetransmissionsTableAnnotationComposer({
required super.$db,
required super.$table,
@ -7107,7 +7101,7 @@ class $$MessageRetransmissionsTableAnnotationComposer
}
class $$MessageRetransmissionsTableTableManager extends RootTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$MessageRetransmissionsTable,
MessageRetransmission,
$$MessageRetransmissionsTableFilterComposer,
@ -7119,7 +7113,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
MessageRetransmission,
PrefetchHooks Function({bool contactId, bool messageId})> {
$$MessageRetransmissionsTableTableManager(
_$TwonlyDatabase db, $MessageRetransmissionsTable table)
_$TwonlyDatabaseOld db, $MessageRetransmissionsTable table)
: super(TableManagerState(
db: db,
table: table,
@ -7234,7 +7228,7 @@ class $$MessageRetransmissionsTableTableManager extends RootTableManager<
typedef $$MessageRetransmissionsTableProcessedTableManager
= ProcessedTableManager<
_$TwonlyDatabase,
_$TwonlyDatabaseOld,
$MessageRetransmissionsTable,
MessageRetransmission,
$$MessageRetransmissionsTableFilterComposer,
@ -7246,9 +7240,9 @@ typedef $$MessageRetransmissionsTableProcessedTableManager
MessageRetransmission,
PrefetchHooks Function({bool contactId, bool messageId})>;
class $TwonlyDatabaseManager {
final _$TwonlyDatabase _db;
$TwonlyDatabaseManager(this._db);
class $TwonlyDatabaseOldManager {
final _$TwonlyDatabaseOld _db;
$TwonlyDatabaseOldManager(this._db);
$$ContactsTableTableManager get contacts =>
$$ContactsTableTableManager(_db, _db.contacts);
$$MessagesTableTableManager get messages =>

View file

@ -1,54 +1,102 @@
{
"@@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.",
@ -62,10 +110,15 @@
"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",
@ -79,261 +132,691 @@
"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.",
"errorUsernameAlreadyTaken": "Der Benutzername, den du verwenden möchtest, ist bereits vergeben. Bitte wähle einen anderen Benutzernamen.",
"@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",
"proFeature3": "Zusatzfunktionen (coming-soon)",
"@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?",
"deleteOkBtn": "Für mich löschen",
"@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",
"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 Safe 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.",
"backupSelectStrongPassword": "Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Safe-Backup wiederherstellen möchtest.",
"@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",
"backupOwnServerDesc": "Speichere dein twonly Safe-Backups auf einem Server deiner Wahl.",
"@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",
"newDeviceRegistered": "Du hast dich auf einem anderen Gerät angemeldet. Daher wurdest du hier abgemeldet."
"@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.",
"notificationVideo": "hat ein Video{inGroup} gesendet.",
"notificationImage": "hat ein Bild{inGroup} gesendet.",
"notificationAudio": "hat eine Sprachnachricht{inGroup} gesendet.",
"notificationAddedToGroup": "hat dich zu \"{groupname}\" hinzugefügt.",
"notificationContactRequest": "möchte sich mit dir vernetzen.",
"notificationAcceptRequest": "ist jetzt mit dir vernetzt.",
"notificationStoredMediaFile": "hat dein Bild gespeichert.",
"notificationReaction": "hat auf dein Bild reagiert.",
"notificationReopenedMedia": "hat dein Bild erneut geöffnet.",
"notificationReactionToVideo": "hat mit {reaction} auf dein Video reagiert.",
"notificationReactionToText": "hat mit {reaction} auf deine Nachricht reagiert.",
"notificationReactionToImage": "hat mit {reaction} auf dein Bild reagiert.",
"notificationReactionToAudio": "hat mit {reaction} auf deine Sprachnachricht reagiert.",
"notificationResponse": "hat dir{inGroup} geantwortet.",
"notificationTitleUnknownUser": "Jemand",
"notificationCategoryMessageTitle": "Nachrichten",
"notificationCategoryMessageDesc": "Nachrichten von anderen Benutzern.",
"groupContextMenuDeleteGroup": "Dadurch werden alle Nachrichten in diesem Chat dauerhaft gelöscht.",
"groupYouAreNowLongerAMember": "Du bist nicht mehr Mitglied dieser Gruppe.",
"groupNetworkIssue": "Netzwerkproblem. Bitte probiere es später noch einmal.",
"leaveGroupSelectOtherAdminTitle": "Einen Admin auswählen",
"leaveGroupSelectOtherAdminBody": "Um die Gruppe zu verlassen, musst du zuerst einen neuen Administrator auswählen.",
"leaveGroupSureTitle": "Gruppe verlassen",
"leaveGroupSureBody": "Willst du die Gruppe wirklich verlassen?",
"leaveGroupSureOkBtn": "Gruppe verlassen",
"changeDisplayMaxTime": "Chats werden ab jetzt nach {time} gelöscht ({username}).",
"youChangedDisplayMaxTime": "Chats werden ab jetzt nach {time} gelöscht.",
"userGotReported": "Benutzer wurde gemeldet.",
"deleteChatAfter": "Chat löschen nach...",
"deleteChatAfterAnHour": "einer Stunde.",
"deleteChatAfterADay": "einem Tag.",
"deleteChatAfterAWeek": "einer Woche.",
"deleteChatAfterAMonth": "einem Monat.",
"deleteChatAfterAYear": "einem Jahr.",
"yourTwonlyScore": "Dein twonly-Score",
"registrationClosed": "Aufgrund des aktuell sehr hohen Aufkommens haben wir die Registrierung vorübergehend deaktiviert, damit der Dienst zuverlässig bleibt. Bitte versuche es in ein paar Tagen noch einmal."
}

View file

@ -66,6 +66,7 @@
"@shareImagedEditorSavedImage": {},
"shareImageSearchAllContacts": "Search all contacts",
"@shareImageSearchAllContacts": {},
"startNewChatSearchHint": "Name, username or groupname",
"shareImagedSelectAll": "Select all",
"@shareImagedSelectAll": {},
"startNewChatTitle": "Select Contact",
@ -299,9 +300,15 @@
"disable": "Disable",
"enable": "Enable",
"cancel": "Cancel",
"now": "Now",
"you": "You",
"minutesShort": "min.",
"image": "Image",
"video": "Video",
"react": "React",
"reply": "Reply",
"copy": "Copy",
"edit": "Edit",
"delete": "Delete",
"info": "Info",
"ok": "Ok",
@ -339,7 +346,7 @@
"@errorInternalError": {},
"errorInvalidInvitationCode": "The invitation code you provided is invalid. Please check the code and try again.",
"@errorInvalidInvitationCode": {},
"errorUsernameAlreadyTaken": "The username you want to use is already taken. Please choose a different username.",
"errorUsernameAlreadyTaken": "The username is already taken.",
"@errorUsernameAlreadyTaken": {},
"errorSignatureNotValid": "The provided signature is not valid. Please check your credentials and try again.",
"@errorSignatureNotValid": {},
@ -438,7 +445,8 @@
"tutorialChatMessagesReopenMessageDesc": "If your friend has sent you a picture or video with infinite display time, you can open it again at any time until you restart the app. To do this, simply double-click on the message. Your friend will then receive a notification that you have viewed the picture again.",
"memoriesEmpty": "As soon as you save pictures or videos, they end up here in your memories.",
"deleteTitle": "Are you sure?",
"deleteOkBtn": "Delete for me",
"deleteOkBtnForAll": "Delete for all",
"deleteOkBtnForMe": "Delete for me",
"deleteImageTitle": "Are you sure?",
"deleteImageBody": "The image will be irrevocably deleted.",
"settingsBackup": "Backup",
@ -450,6 +458,7 @@
"backupFailed": "Failed",
"backupSuccess": "Success",
"backupTwonlySafeDesc": "Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.",
"backupNoPasswordRecovery": "Due to twonly's security system, there is (currently) no password recovery function. Therefore, you must remember your password or, better yet, write it down.",
"backupServer": "Server",
"backupMaxBackupSize": "max. backup size",
"backupStorageRetention": "Storage retention",
@ -464,20 +473,21 @@
"backupInsecurePasswordDesc": "The chosen password is very insecure and can therefore easily be guessed by attackers. Please choose a secure password.",
"backupInsecurePasswordOk": "Continue anyway",
"backupInsecurePasswordCancel": "Try again",
"backupTwonlySafeLongDesc": "twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.",
"backupSelectStrongPassword": "Choose a secure password. This is required if you want to restore your twonly Safe backup.",
"backupTwonlySafeLongDesc": "twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Backup regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.",
"backupSelectStrongPassword": "Choose a secure password. This is required if you want to restore your twonly Backup.",
"password": "Password",
"passwordRepeated": "Repeat password",
"passwordRepeatedNotEqual": "Passwords do not match.",
"backupPasswordRequirement": "Password must be at least 8 characters long.",
"backupExpertSettings": "Expert settings",
"backupEnableBackup": "Activate automatic backup",
"backupOwnServerDesc": "Save your twonly safe backups at twonly or on any server of your choice.",
"backupOwnServerDesc": "Save your twonly Backup at twonly or on any server of your choice.",
"backupUseOwnServer": "Use server",
"backupResetServer": "Use standard server",
"backupTwonlySaveNow": "Save now",
"backupChangePassword": "Change password",
"twonlySafeRecoverTitle": "Recovery",
"twonlySafeRecoverDesc": "If you have created a backup with twonly Safe, you can restore it here.",
"twonlySafeRecoverDesc": "If you have created a backup with twonly Backup, you can restore it here.",
"twonlySafeRecoverBtn": "Restore backup",
"inviteFriends": "Invite your friends",
"inviteFriendsShareBtn": "Share",
@ -485,11 +495,106 @@
"appOutdated": "Your version of twonly is out of date.",
"appOutdatedBtn": "Update Now",
"doubleClickToReopen": "Double-click\nto open again",
"uploadLimitReached": "The upload limit has\been reached. Upgrade to Pro\nor wait until tomorrow.",
"retransmissionRequested": "Retransmission requested",
"testPaymentMethod": "Thanks for the interest in a paid plan. Currently the paid plans are still deactivated. But they will be activated soon!",
"openChangeLog": "Open changelog automatically",
"reportUserTitle": "Report {username}",
"reportUserReason": "Reporting reason",
"reportUser": "Report user",
"newDeviceRegistered": "You have logged in on another device. You have therefore been logged out here."
"newDeviceRegistered": "You have logged in on another device. You have therefore been logged out here.",
"tabToRemoveEmoji": "Tab to remove",
"quotedMessageWasDeleted": "The quoted message has been deleted.",
"messageWasDeleted": "Message has been deleted.",
"messageWasDeletedShort": "Deleted",
"sent": "Delivered",
"sentTo": "Delivered to",
"received": "Received",
"opened": "Opened",
"waitingForInternet": "Waiting for internet",
"editHistory": "Edit history",
"archivedChats": "Archived chats",
"durationShortSecond": "Sec.",
"durationShortMinute": "Min.",
"durationShortHour": "Hrs.",
"durationShortDays": "{count, plural, =1{1 Day} other{{count} Days}}",
"contacts": "Contacts",
"groups": "Groups",
"newGroup": "New group",
"selectMembers": "Select members",
"selectGroupName": "Select group name",
"groupNameInput": "Group name",
"groupMembers": "Members",
"addMember": "Add member",
"createGroup": "Create group",
"leaveGroup": "Leave group",
"createContactRequest": "Create contact request",
"contactRequestSend": "Contact request send",
"makeAdmin": "Make admin",
"removeAdmin": "Remove as admin",
"removeFromGroup": "Remove from group",
"admin": "Admin",
"revokeAdminRightsTitle": "Revoke {username}'s admin rights?",
"revokeAdminRightsOkBtn": "Remove as admin",
"makeAdminRightsTitle": "Make {username} an admin?",
"makeAdminRightsBody": "{username} will be able to edit this group and its members.",
"makeAdminRightsOkBtn": "Make admin",
"updateGroup": "Update group",
"alreadyInGroup": "Already in Group",
"removeContactFromGroupTitle": "Remove {username} from this group?",
"youChangedGroupName": "You have changed the group name to \"{newGroupName}\".",
"makerChangedGroupName": "{maker} has changed the group name to \"{newGroupName}\".",
"youCreatedGroup": "You have created the group.",
"makerCreatedGroup": "{maker} has created the group.",
"youRemovedMember": "You have removed {affected} from the group.",
"makerRemovedMember": "{maker} has removed {affected} from the group.",
"youAddedMember": "You have added {affected} to the group.",
"makerAddedMember": "{maker} has added {affected} to the group.",
"youMadeAdmin": "You made {affected} an admin.",
"makerMadeAdmin": "{maker} made {affected} an admin.",
"youRevokedAdminRights": "You revoked {affectedR} admin rights.",
"makerRevokedAdminRights": "{maker} revoked {affectedR} admin rights.",
"youLeftGroup": "You have left the group.",
"makerLeftGroup": "{maker} has left the group.",
"groupActionYou": "you",
"groupActionYour": "your",
"notificationFillerIn": "in",
"notificationText": "sent a message{inGroup}.",
"notificationTwonly": "sent a twonly{inGroup}.",
"notificationVideo": "sent a video{inGroup}.",
"notificationImage": "sent a image{inGroup}.",
"notificationAudio": "sent a voice message{inGroup}.",
"notificationAddedToGroup": "has added you to \"{groupname}\"",
"notificationContactRequest": "wants to connect with you.",
"notificationAcceptRequest": "is now connected with you.",
"notificationStoredMediaFile": "has stored your image.",
"notificationReaction": "has reacted to your image.",
"notificationReopenedMedia": "has reopened your image.",
"notificationReactionToVideo": "has reacted with {reaction} to your video.",
"notificationReactionToText": "has reacted with {reaction} to your message.",
"notificationReactionToImage": "has reacted with {reaction} to your image.",
"notificationReactionToAudio": "has reacted with {reaction} to your audio message.",
"notificationResponse": "has responded{inGroup}.",
"notificationTitleUnknownUser": "Someone",
"notificationCategoryMessageTitle": "Messages",
"notificationCategoryMessageDesc": "Messages from other users.",
"groupContextMenuDeleteGroup": "This will permanently delete all messages in this chat.",
"groupYouAreNowLongerAMember": "You are no longer part of this group.",
"groupNetworkIssue": "Network issue. Try again later.",
"leaveGroupSelectOtherAdminTitle": "Select another admin",
"leaveGroupSelectOtherAdminBody": "To leave the group, you must first select a new administrator.",
"leaveGroupSureTitle": "Leave group",
"leaveGroupSureBody": "Do you really want to leave the group?",
"leaveGroupSureOkBtn": "Leave group",
"changeDisplayMaxTime": "Chats will now be deleted after {time} ({username}).",
"youChangedDisplayMaxTime": "Chats will now be deleted after {time}.",
"userGotReported": "User has been reported.",
"deleteChatAfter": "Delete chat after...",
"deleteChatAfterAnHour": "one hour.",
"deleteChatAfterADay": "one day.",
"deleteChatAfterAWeek": "one week.",
"deleteChatAfterAMonth": "one month.",
"deleteChatAfterAYear": "one year.",
"yourTwonlyScore": "Your twonly-Score",
"registrationClosed": "Due to the current high volume of registrations, we have temporarily disabled registration to ensure that the service remains reliable. Please try again in a few days."
}

View file

@ -302,6 +302,12 @@ abstract class AppLocalizations {
/// **'Search all contacts'**
String get shareImageSearchAllContacts;
/// No description provided for @startNewChatSearchHint.
///
/// In en, this message translates to:
/// **'Name, username or groupname'**
String get startNewChatSearchHint;
/// No description provided for @shareImagedSelectAll.
///
/// In en, this message translates to:
@ -1058,6 +1064,36 @@ abstract class AppLocalizations {
/// **'Cancel'**
String get cancel;
/// No description provided for @now.
///
/// In en, this message translates to:
/// **'Now'**
String get now;
/// No description provided for @you.
///
/// In en, this message translates to:
/// **'You'**
String get you;
/// No description provided for @minutesShort.
///
/// In en, this message translates to:
/// **'min.'**
String get minutesShort;
/// No description provided for @image.
///
/// In en, this message translates to:
/// **'Image'**
String get image;
/// No description provided for @video.
///
/// In en, this message translates to:
/// **'Video'**
String get video;
/// No description provided for @react.
///
/// In en, this message translates to:
@ -1076,6 +1112,12 @@ abstract class AppLocalizations {
/// **'Copy'**
String get copy;
/// No description provided for @edit.
///
/// In en, this message translates to:
/// **'Edit'**
String get edit;
/// No description provided for @delete.
///
/// In en, this message translates to:
@ -1187,7 +1229,7 @@ abstract class AppLocalizations {
/// No description provided for @errorUsernameAlreadyTaken.
///
/// In en, this message translates to:
/// **'The username you want to use is already taken. Please choose a different username.'**
/// **'The username is already taken.'**
String get errorUsernameAlreadyTaken;
/// No description provided for @errorSignatureNotValid.
@ -1730,11 +1772,17 @@ abstract class AppLocalizations {
/// **'Are you sure?'**
String get deleteTitle;
/// No description provided for @deleteOkBtn.
/// No description provided for @deleteOkBtnForAll.
///
/// In en, this message translates to:
/// **'Delete for all'**
String get deleteOkBtnForAll;
/// No description provided for @deleteOkBtnForMe.
///
/// In en, this message translates to:
/// **'Delete for me'**
String get deleteOkBtn;
String get deleteOkBtnForMe;
/// No description provided for @deleteImageTitle.
///
@ -1802,6 +1850,12 @@ abstract class AppLocalizations {
/// **'Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.'**
String get backupTwonlySafeDesc;
/// No description provided for @backupNoPasswordRecovery.
///
/// In en, this message translates to:
/// **'Due to twonly\'s security system, there is (currently) no password recovery function. Therefore, you must remember your password or, better yet, write it down.'**
String get backupNoPasswordRecovery;
/// No description provided for @backupServer.
///
/// In en, this message translates to:
@ -1889,13 +1943,13 @@ abstract class AppLocalizations {
/// No description provided for @backupTwonlySafeLongDesc.
///
/// In en, this message translates to:
/// **'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.'**
/// **'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Backup regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.'**
String get backupTwonlySafeLongDesc;
/// No description provided for @backupSelectStrongPassword.
///
/// In en, this message translates to:
/// **'Choose a secure password. This is required if you want to restore your twonly Safe backup.'**
/// **'Choose a secure password. This is required if you want to restore your twonly Backup.'**
String get backupSelectStrongPassword;
/// No description provided for @password.
@ -1937,7 +1991,7 @@ abstract class AppLocalizations {
/// No description provided for @backupOwnServerDesc.
///
/// In en, this message translates to:
/// **'Save your twonly safe backups at twonly or on any server of your choice.'**
/// **'Save your twonly Backup at twonly or on any server of your choice.'**
String get backupOwnServerDesc;
/// No description provided for @backupUseOwnServer.
@ -1958,6 +2012,12 @@ abstract class AppLocalizations {
/// **'Save now'**
String get backupTwonlySaveNow;
/// No description provided for @backupChangePassword.
///
/// In en, this message translates to:
/// **'Change password'**
String get backupChangePassword;
/// No description provided for @twonlySafeRecoverTitle.
///
/// In en, this message translates to:
@ -1967,7 +2027,7 @@ abstract class AppLocalizations {
/// No description provided for @twonlySafeRecoverDesc.
///
/// In en, this message translates to:
/// **'If you have created a backup with twonly Safe, you can restore it here.'**
/// **'If you have created a backup with twonly Backup, you can restore it here.'**
String get twonlySafeRecoverDesc;
/// No description provided for @twonlySafeRecoverBtn.
@ -2012,6 +2072,12 @@ abstract class AppLocalizations {
/// **'Double-click\nto open again'**
String get doubleClickToReopen;
/// No description provided for @uploadLimitReached.
///
/// In en, this message translates to:
/// **'The upload limit has\been reached. Upgrade to Pro\nor wait until tomorrow.'**
String get uploadLimitReached;
/// No description provided for @retransmissionRequested.
///
/// In en, this message translates to:
@ -2053,6 +2119,570 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'You have logged in on another device. You have therefore been logged out here.'**
String get newDeviceRegistered;
/// No description provided for @tabToRemoveEmoji.
///
/// In en, this message translates to:
/// **'Tab to remove'**
String get tabToRemoveEmoji;
/// No description provided for @quotedMessageWasDeleted.
///
/// In en, this message translates to:
/// **'The quoted message has been deleted.'**
String get quotedMessageWasDeleted;
/// No description provided for @messageWasDeleted.
///
/// In en, this message translates to:
/// **'Message has been deleted.'**
String get messageWasDeleted;
/// No description provided for @messageWasDeletedShort.
///
/// In en, this message translates to:
/// **'Deleted'**
String get messageWasDeletedShort;
/// No description provided for @sent.
///
/// In en, this message translates to:
/// **'Delivered'**
String get sent;
/// No description provided for @sentTo.
///
/// In en, this message translates to:
/// **'Delivered to'**
String get sentTo;
/// No description provided for @received.
///
/// In en, this message translates to:
/// **'Received'**
String get received;
/// No description provided for @opened.
///
/// In en, this message translates to:
/// **'Opened'**
String get opened;
/// No description provided for @waitingForInternet.
///
/// In en, this message translates to:
/// **'Waiting for internet'**
String get waitingForInternet;
/// No description provided for @editHistory.
///
/// In en, this message translates to:
/// **'Edit history'**
String get editHistory;
/// No description provided for @archivedChats.
///
/// In en, this message translates to:
/// **'Archived chats'**
String get archivedChats;
/// No description provided for @durationShortSecond.
///
/// In en, this message translates to:
/// **'Sec.'**
String get durationShortSecond;
/// No description provided for @durationShortMinute.
///
/// In en, this message translates to:
/// **'Min.'**
String get durationShortMinute;
/// No description provided for @durationShortHour.
///
/// In en, this message translates to:
/// **'Hrs.'**
String get durationShortHour;
/// No description provided for @durationShortDays.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 Day} other{{count} Days}}'**
String durationShortDays(num count);
/// No description provided for @contacts.
///
/// In en, this message translates to:
/// **'Contacts'**
String get contacts;
/// No description provided for @groups.
///
/// In en, this message translates to:
/// **'Groups'**
String get groups;
/// No description provided for @newGroup.
///
/// In en, this message translates to:
/// **'New group'**
String get newGroup;
/// No description provided for @selectMembers.
///
/// In en, this message translates to:
/// **'Select members'**
String get selectMembers;
/// No description provided for @selectGroupName.
///
/// In en, this message translates to:
/// **'Select group name'**
String get selectGroupName;
/// No description provided for @groupNameInput.
///
/// In en, this message translates to:
/// **'Group name'**
String get groupNameInput;
/// No description provided for @groupMembers.
///
/// In en, this message translates to:
/// **'Members'**
String get groupMembers;
/// No description provided for @addMember.
///
/// In en, this message translates to:
/// **'Add member'**
String get addMember;
/// No description provided for @createGroup.
///
/// In en, this message translates to:
/// **'Create group'**
String get createGroup;
/// No description provided for @leaveGroup.
///
/// In en, this message translates to:
/// **'Leave group'**
String get leaveGroup;
/// No description provided for @createContactRequest.
///
/// In en, this message translates to:
/// **'Create contact request'**
String get createContactRequest;
/// No description provided for @contactRequestSend.
///
/// In en, this message translates to:
/// **'Contact request send'**
String get contactRequestSend;
/// No description provided for @makeAdmin.
///
/// In en, this message translates to:
/// **'Make admin'**
String get makeAdmin;
/// No description provided for @removeAdmin.
///
/// In en, this message translates to:
/// **'Remove as admin'**
String get removeAdmin;
/// No description provided for @removeFromGroup.
///
/// In en, this message translates to:
/// **'Remove from group'**
String get removeFromGroup;
/// No description provided for @admin.
///
/// In en, this message translates to:
/// **'Admin'**
String get admin;
/// No description provided for @revokeAdminRightsTitle.
///
/// In en, this message translates to:
/// **'Revoke {username}\'s admin rights?'**
String revokeAdminRightsTitle(Object username);
/// No description provided for @revokeAdminRightsOkBtn.
///
/// In en, this message translates to:
/// **'Remove as admin'**
String get revokeAdminRightsOkBtn;
/// No description provided for @makeAdminRightsTitle.
///
/// In en, this message translates to:
/// **'Make {username} an admin?'**
String makeAdminRightsTitle(Object username);
/// No description provided for @makeAdminRightsBody.
///
/// In en, this message translates to:
/// **'{username} will be able to edit this group and its members.'**
String makeAdminRightsBody(Object username);
/// No description provided for @makeAdminRightsOkBtn.
///
/// In en, this message translates to:
/// **'Make admin'**
String get makeAdminRightsOkBtn;
/// No description provided for @updateGroup.
///
/// In en, this message translates to:
/// **'Update group'**
String get updateGroup;
/// No description provided for @alreadyInGroup.
///
/// In en, this message translates to:
/// **'Already in Group'**
String get alreadyInGroup;
/// No description provided for @removeContactFromGroupTitle.
///
/// In en, this message translates to:
/// **'Remove {username} from this group?'**
String removeContactFromGroupTitle(Object username);
/// No description provided for @youChangedGroupName.
///
/// In en, this message translates to:
/// **'You have changed the group name to \"{newGroupName}\".'**
String youChangedGroupName(Object newGroupName);
/// No description provided for @makerChangedGroupName.
///
/// In en, this message translates to:
/// **'{maker} has changed the group name to \"{newGroupName}\".'**
String makerChangedGroupName(Object maker, Object newGroupName);
/// No description provided for @youCreatedGroup.
///
/// In en, this message translates to:
/// **'You have created the group.'**
String get youCreatedGroup;
/// No description provided for @makerCreatedGroup.
///
/// In en, this message translates to:
/// **'{maker} has created the group.'**
String makerCreatedGroup(Object maker);
/// No description provided for @youRemovedMember.
///
/// In en, this message translates to:
/// **'You have removed {affected} from the group.'**
String youRemovedMember(Object affected);
/// No description provided for @makerRemovedMember.
///
/// In en, this message translates to:
/// **'{maker} has removed {affected} from the group.'**
String makerRemovedMember(Object affected, Object maker);
/// No description provided for @youAddedMember.
///
/// In en, this message translates to:
/// **'You have added {affected} to the group.'**
String youAddedMember(Object affected);
/// No description provided for @makerAddedMember.
///
/// In en, this message translates to:
/// **'{maker} has added {affected} to the group.'**
String makerAddedMember(Object affected, Object maker);
/// No description provided for @youMadeAdmin.
///
/// In en, this message translates to:
/// **'You made {affected} an admin.'**
String youMadeAdmin(Object affected);
/// No description provided for @makerMadeAdmin.
///
/// In en, this message translates to:
/// **'{maker} made {affected} an admin.'**
String makerMadeAdmin(Object affected, Object maker);
/// No description provided for @youRevokedAdminRights.
///
/// In en, this message translates to:
/// **'You revoked {affectedR} admin rights.'**
String youRevokedAdminRights(Object affectedR);
/// No description provided for @makerRevokedAdminRights.
///
/// In en, this message translates to:
/// **'{maker} revoked {affectedR} admin rights.'**
String makerRevokedAdminRights(Object affectedR, Object maker);
/// No description provided for @youLeftGroup.
///
/// In en, this message translates to:
/// **'You have left the group.'**
String get youLeftGroup;
/// No description provided for @makerLeftGroup.
///
/// In en, this message translates to:
/// **'{maker} has left the group.'**
String makerLeftGroup(Object maker);
/// No description provided for @groupActionYou.
///
/// In en, this message translates to:
/// **'you'**
String get groupActionYou;
/// No description provided for @groupActionYour.
///
/// In en, this message translates to:
/// **'your'**
String get groupActionYour;
/// No description provided for @notificationFillerIn.
///
/// In en, this message translates to:
/// **'in'**
String get notificationFillerIn;
/// No description provided for @notificationText.
///
/// In en, this message translates to:
/// **'sent a message{inGroup}.'**
String notificationText(Object inGroup);
/// No description provided for @notificationTwonly.
///
/// In en, this message translates to:
/// **'sent a twonly{inGroup}.'**
String notificationTwonly(Object inGroup);
/// No description provided for @notificationVideo.
///
/// In en, this message translates to:
/// **'sent a video{inGroup}.'**
String notificationVideo(Object inGroup);
/// No description provided for @notificationImage.
///
/// In en, this message translates to:
/// **'sent a image{inGroup}.'**
String notificationImage(Object inGroup);
/// No description provided for @notificationAudio.
///
/// In en, this message translates to:
/// **'sent a voice message{inGroup}.'**
String notificationAudio(Object inGroup);
/// No description provided for @notificationAddedToGroup.
///
/// In en, this message translates to:
/// **'has added you to \"{groupname}\"'**
String notificationAddedToGroup(Object groupname);
/// No description provided for @notificationContactRequest.
///
/// In en, this message translates to:
/// **'wants to connect with you.'**
String get notificationContactRequest;
/// No description provided for @notificationAcceptRequest.
///
/// In en, this message translates to:
/// **'is now connected with you.'**
String get notificationAcceptRequest;
/// No description provided for @notificationStoredMediaFile.
///
/// In en, this message translates to:
/// **'has stored your image.'**
String get notificationStoredMediaFile;
/// No description provided for @notificationReaction.
///
/// In en, this message translates to:
/// **'has reacted to your image.'**
String get notificationReaction;
/// No description provided for @notificationReopenedMedia.
///
/// In en, this message translates to:
/// **'has reopened your image.'**
String get notificationReopenedMedia;
/// No description provided for @notificationReactionToVideo.
///
/// In en, this message translates to:
/// **'has reacted with {reaction} to your video.'**
String notificationReactionToVideo(Object reaction);
/// No description provided for @notificationReactionToText.
///
/// In en, this message translates to:
/// **'has reacted with {reaction} to your message.'**
String notificationReactionToText(Object reaction);
/// No description provided for @notificationReactionToImage.
///
/// In en, this message translates to:
/// **'has reacted with {reaction} to your image.'**
String notificationReactionToImage(Object reaction);
/// No description provided for @notificationReactionToAudio.
///
/// In en, this message translates to:
/// **'has reacted with {reaction} to your audio message.'**
String notificationReactionToAudio(Object reaction);
/// No description provided for @notificationResponse.
///
/// In en, this message translates to:
/// **'has responded{inGroup}.'**
String notificationResponse(Object inGroup);
/// No description provided for @notificationTitleUnknownUser.
///
/// In en, this message translates to:
/// **'Someone'**
String get notificationTitleUnknownUser;
/// No description provided for @notificationCategoryMessageTitle.
///
/// In en, this message translates to:
/// **'Messages'**
String get notificationCategoryMessageTitle;
/// No description provided for @notificationCategoryMessageDesc.
///
/// In en, this message translates to:
/// **'Messages from other users.'**
String get notificationCategoryMessageDesc;
/// No description provided for @groupContextMenuDeleteGroup.
///
/// In en, this message translates to:
/// **'This will permanently delete all messages in this chat.'**
String get groupContextMenuDeleteGroup;
/// No description provided for @groupYouAreNowLongerAMember.
///
/// In en, this message translates to:
/// **'You are no longer part of this group.'**
String get groupYouAreNowLongerAMember;
/// No description provided for @groupNetworkIssue.
///
/// In en, this message translates to:
/// **'Network issue. Try again later.'**
String get groupNetworkIssue;
/// No description provided for @leaveGroupSelectOtherAdminTitle.
///
/// In en, this message translates to:
/// **'Select another admin'**
String get leaveGroupSelectOtherAdminTitle;
/// No description provided for @leaveGroupSelectOtherAdminBody.
///
/// In en, this message translates to:
/// **'To leave the group, you must first select a new administrator.'**
String get leaveGroupSelectOtherAdminBody;
/// No description provided for @leaveGroupSureTitle.
///
/// In en, this message translates to:
/// **'Leave group'**
String get leaveGroupSureTitle;
/// No description provided for @leaveGroupSureBody.
///
/// In en, this message translates to:
/// **'Do you really want to leave the group?'**
String get leaveGroupSureBody;
/// No description provided for @leaveGroupSureOkBtn.
///
/// In en, this message translates to:
/// **'Leave group'**
String get leaveGroupSureOkBtn;
/// No description provided for @changeDisplayMaxTime.
///
/// In en, this message translates to:
/// **'Chats will now be deleted after {time} ({username}).'**
String changeDisplayMaxTime(Object time, Object username);
/// No description provided for @youChangedDisplayMaxTime.
///
/// In en, this message translates to:
/// **'Chats will now be deleted after {time}.'**
String youChangedDisplayMaxTime(Object time);
/// No description provided for @userGotReported.
///
/// In en, this message translates to:
/// **'User has been reported.'**
String get userGotReported;
/// No description provided for @deleteChatAfter.
///
/// In en, this message translates to:
/// **'Delete chat after...'**
String get deleteChatAfter;
/// No description provided for @deleteChatAfterAnHour.
///
/// In en, this message translates to:
/// **'one hour.'**
String get deleteChatAfterAnHour;
/// No description provided for @deleteChatAfterADay.
///
/// In en, this message translates to:
/// **'one day.'**
String get deleteChatAfterADay;
/// No description provided for @deleteChatAfterAWeek.
///
/// In en, this message translates to:
/// **'one week.'**
String get deleteChatAfterAWeek;
/// No description provided for @deleteChatAfterAMonth.
///
/// In en, this message translates to:
/// **'one month.'**
String get deleteChatAfterAMonth;
/// No description provided for @deleteChatAfterAYear.
///
/// In en, this message translates to:
/// **'one year.'**
String get deleteChatAfterAYear;
/// No description provided for @yourTwonlyScore.
///
/// In en, this message translates to:
/// **'Your twonly-Score'**
String get yourTwonlyScore;
/// No description provided for @registrationClosed.
///
/// In en, this message translates to:
/// **'Due to the current high volume of registrations, we have temporarily disabled registration to ensure that the service remains reliable. Please try again in a few days.'**
String get registrationClosed;
}
class _AppLocalizationsDelegate

View file

@ -122,6 +122,9 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get shareImageSearchAllContacts => 'Alle Kontakte durchsuchen';
@override
String get startNewChatSearchHint => 'Name, Benutzername oder Gruppenname';
@override
String get shareImagedSelectAll => 'Alle auswählen';
@ -536,6 +539,21 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get cancel => 'Abbrechen';
@override
String get now => 'Jetzt';
@override
String get you => 'Du';
@override
String get minutesShort => 'Min.';
@override
String get image => 'Bild';
@override
String get video => 'Video';
@override
String get react => 'Reagieren';
@ -545,6 +563,9 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get copy => 'Kopieren';
@override
String get edit => 'Bearbeiten';
@override
String get delete => 'Löschen';
@ -609,7 +630,7 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get errorUsernameAlreadyTaken =>
'Der Benutzername, den du verwenden möchtest, ist bereits vergeben. Bitte wähle einen anderen Benutzernamen.';
'Der Benutzername ist bereits vergeben.';
@override
String get errorSignatureNotValid =>
@ -684,7 +705,7 @@ class AppLocalizationsDe extends AppLocalizations {
String get proFeature2 => '1 zusätzlicher Plus Benutzer';
@override
String get proFeature3 => 'Zusatzfunktionen (coming-soon)';
String get proFeature3 => 'Flammen wiederherstellen';
@override
String get proFeature4 => 'Cloud-Backup verschlüsselt (coming-soon)';
@ -915,7 +936,10 @@ class AppLocalizationsDe extends AppLocalizations {
String get deleteTitle => 'Bist du dir sicher?';
@override
String get deleteOkBtn => 'Für mich löschen';
String get deleteOkBtnForAll => 'Für alle löschen';
@override
String get deleteOkBtnForMe => 'Für mich löschen';
@override
String get deleteImageTitle => 'Bist du dir sicher?';
@ -952,6 +976,10 @@ class AppLocalizationsDe extends AppLocalizations {
String get 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.';
@override
String get 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.';
@override
String get backupServer => 'Server';
@ -999,11 +1027,11 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get 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 Safe 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.';
'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.';
@override
String get backupSelectStrongPassword =>
'Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Safe-Backup wiederherstellen möchtest.';
'Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Backup wiederherstellen möchtest.';
@override
String get password => 'Passwort';
@ -1026,7 +1054,7 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get backupOwnServerDesc =>
'Speichere dein twonly Safe-Backups auf einem Server deiner Wahl.';
'Speichere dein twonly Backup auf einem Server deiner Wahl.';
@override
String get backupUseOwnServer => 'Server verwenden';
@ -1037,15 +1065,18 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get backupTwonlySaveNow => 'Jetzt speichern';
@override
String get backupChangePassword => 'Password ändern';
@override
String get twonlySafeRecoverTitle => 'Recovery';
@override
String get twonlySafeRecoverDesc =>
'If you have created a backup with twonly Safe, you can restore it here.';
'Wenn du ein Backup mit twonly Backup erstellt hast, kannst du es hier wiederherstellen.';
@override
String get twonlySafeRecoverBtn => 'Restore backup';
String get twonlySafeRecoverBtn => 'Backup wiederherstellen';
@override
String get inviteFriends => 'Freunde einladen';
@ -1067,6 +1098,10 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get doubleClickToReopen => 'Doppelklicken zum\nerneuten Öffnen.';
@override
String get uploadLimitReached =>
'Das Upload-Limit wurde\nerreicht. Upgrade auf Pro\noder warte bis morgen.';
@override
String get retransmissionRequested => 'Wird erneut versucht.';
@ -1091,4 +1126,359 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get newDeviceRegistered =>
'Du hast dich auf einem anderen Gerät angemeldet. Daher wurdest du hier abgemeldet.';
@override
String get tabToRemoveEmoji => 'Tippen um zu entfernen';
@override
String get quotedMessageWasDeleted =>
'Die zitierte Nachricht wurde gelöscht.';
@override
String get messageWasDeleted => 'Nachricht wurde gelöscht.';
@override
String get messageWasDeletedShort => 'Gelöscht';
@override
String get sent => 'Versendet';
@override
String get sentTo => 'Zugestellt an';
@override
String get received => 'Empfangen';
@override
String get opened => 'Geöffnet';
@override
String get waitingForInternet => 'Warten auf Internet';
@override
String get editHistory => 'Bearbeitungshistorie';
@override
String get archivedChats => 'Archivierte Chats';
@override
String get durationShortSecond => 'Sek.';
@override
String get durationShortMinute => 'Min.';
@override
String get durationShortHour => 'Std.';
@override
String durationShortDays(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Tage',
one: '1 Tag',
);
return '$_temp0';
}
@override
String get contacts => 'Kontakte';
@override
String get groups => 'Gruppen';
@override
String get newGroup => 'Neue Gruppe';
@override
String get selectMembers => 'Mitglieder auswählen';
@override
String get selectGroupName => 'Gruppennamen wählen';
@override
String get groupNameInput => 'Gruppennamen';
@override
String get groupMembers => 'Mitglieder';
@override
String get addMember => 'Mitglied hinzufügen';
@override
String get createGroup => 'Gruppe erstellen';
@override
String get leaveGroup => 'Gruppe verlassen';
@override
String get createContactRequest => 'Kontaktanfrage erstellen';
@override
String get contactRequestSend => 'Kontakanfrage gesendet';
@override
String get makeAdmin => 'Zum Admin machen';
@override
String get removeAdmin => 'Als Admin entfernen';
@override
String get removeFromGroup => 'Aus Gruppe entfernen';
@override
String get admin => 'Admin';
@override
String revokeAdminRightsTitle(Object username) {
return 'Adminrechte von $username entfernen?';
}
@override
String get revokeAdminRightsOkBtn => 'Als Admin entfernen';
@override
String makeAdminRightsTitle(Object username) {
return '$username zum Admin machen?';
}
@override
String makeAdminRightsBody(Object username) {
return '$username wird diese Gruppe und ihre Mitglieder bearbeiten können.';
}
@override
String get makeAdminRightsOkBtn => 'Zum Admin machen';
@override
String get updateGroup => 'Gruppe aktualisieren';
@override
String get alreadyInGroup => 'Bereits Mitglied';
@override
String removeContactFromGroupTitle(Object username) {
return '$username aus dieser Gruppe entfernen?';
}
@override
String youChangedGroupName(Object newGroupName) {
return 'Du hast den Gruppennamen zu „$newGroupName“ geändert.';
}
@override
String makerChangedGroupName(Object maker, Object newGroupName) {
return '$maker hat den Gruppennamen zu „$newGroupName“ geändert.';
}
@override
String get youCreatedGroup => 'Du hast die Gruppe erstellt.';
@override
String makerCreatedGroup(Object maker) {
return '$maker hat die Gruppe erstellt.';
}
@override
String youRemovedMember(Object affected) {
return 'Du hast $affected aus der Gruppe entfernt.';
}
@override
String makerRemovedMember(Object affected, Object maker) {
return '$maker hat $affected aus der Gruppe entfernt.';
}
@override
String youAddedMember(Object affected) {
return 'Du hast $affected zur Gruppe hinzugefügt.';
}
@override
String makerAddedMember(Object affected, Object maker) {
return '$maker hat $affected zur Gruppe hinzugefügt.';
}
@override
String youMadeAdmin(Object affected) {
return 'Du hast $affected zum Administrator gemacht.';
}
@override
String makerMadeAdmin(Object affected, Object maker) {
return '$maker hat $affected zum Administrator gemacht.';
}
@override
String youRevokedAdminRights(Object affectedR) {
return 'Du hast $affectedR die Administratorrechte entzogen.';
}
@override
String makerRevokedAdminRights(Object affectedR, Object maker) {
return '$maker hat $affectedR die Administratorrechte entzogen.';
}
@override
String get youLeftGroup => 'Du hast die Gruppe verlassen.';
@override
String makerLeftGroup(Object maker) {
return '$maker hat die Gruppe verlassen.';
}
@override
String get groupActionYou => 'dich';
@override
String get groupActionYour => 'deine';
@override
String get notificationFillerIn => 'in';
@override
String notificationText(Object inGroup) {
return 'hat eine Nachricht$inGroup gesendet.';
}
@override
String notificationTwonly(Object inGroup) {
return 'hat ein twonly$inGroup gesendet.';
}
@override
String notificationVideo(Object inGroup) {
return 'hat ein Video$inGroup gesendet.';
}
@override
String notificationImage(Object inGroup) {
return 'hat ein Bild$inGroup gesendet.';
}
@override
String notificationAudio(Object inGroup) {
return 'hat eine Sprachnachricht$inGroup gesendet.';
}
@override
String notificationAddedToGroup(Object groupname) {
return 'hat dich zu \"$groupname\" hinzugefügt.';
}
@override
String get notificationContactRequest => 'möchte sich mit dir vernetzen.';
@override
String get notificationAcceptRequest => 'ist jetzt mit dir vernetzt.';
@override
String get notificationStoredMediaFile => 'hat dein Bild gespeichert.';
@override
String get notificationReaction => 'hat auf dein Bild reagiert.';
@override
String get notificationReopenedMedia => 'hat dein Bild erneut geöffnet.';
@override
String notificationReactionToVideo(Object reaction) {
return 'hat mit $reaction auf dein Video reagiert.';
}
@override
String notificationReactionToText(Object reaction) {
return 'hat mit $reaction auf deine Nachricht reagiert.';
}
@override
String notificationReactionToImage(Object reaction) {
return 'hat mit $reaction auf dein Bild reagiert.';
}
@override
String notificationReactionToAudio(Object reaction) {
return 'hat mit $reaction auf deine Sprachnachricht reagiert.';
}
@override
String notificationResponse(Object inGroup) {
return 'hat dir$inGroup geantwortet.';
}
@override
String get notificationTitleUnknownUser => 'Jemand';
@override
String get notificationCategoryMessageTitle => 'Nachrichten';
@override
String get notificationCategoryMessageDesc =>
'Nachrichten von anderen Benutzern.';
@override
String get groupContextMenuDeleteGroup =>
'Dadurch werden alle Nachrichten in diesem Chat dauerhaft gelöscht.';
@override
String get groupYouAreNowLongerAMember =>
'Du bist nicht mehr Mitglied dieser Gruppe.';
@override
String get groupNetworkIssue =>
'Netzwerkproblem. Bitte probiere es später noch einmal.';
@override
String get leaveGroupSelectOtherAdminTitle => 'Einen Admin auswählen';
@override
String get leaveGroupSelectOtherAdminBody =>
'Um die Gruppe zu verlassen, musst du zuerst einen neuen Administrator auswählen.';
@override
String get leaveGroupSureTitle => 'Gruppe verlassen';
@override
String get leaveGroupSureBody => 'Willst du die Gruppe wirklich verlassen?';
@override
String get leaveGroupSureOkBtn => 'Gruppe verlassen';
@override
String changeDisplayMaxTime(Object time, Object username) {
return 'Chats werden ab jetzt nach $time gelöscht ($username).';
}
@override
String youChangedDisplayMaxTime(Object time) {
return 'Chats werden ab jetzt nach $time gelöscht.';
}
@override
String get userGotReported => 'Benutzer wurde gemeldet.';
@override
String get deleteChatAfter => 'Chat löschen nach...';
@override
String get deleteChatAfterAnHour => 'einer Stunde.';
@override
String get deleteChatAfterADay => 'einem Tag.';
@override
String get deleteChatAfterAWeek => 'einer Woche.';
@override
String get deleteChatAfterAMonth => 'einem Monat.';
@override
String get deleteChatAfterAYear => 'einem Jahr.';
@override
String get yourTwonlyScore => 'Dein twonly-Score';
@override
String get registrationClosed =>
'Aufgrund des aktuell sehr hohen Aufkommens haben wir die Registrierung vorübergehend deaktiviert, damit der Dienst zuverlässig bleibt. Bitte versuche es in ein paar Tagen noch einmal.';
}

View file

@ -121,6 +121,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get shareImageSearchAllContacts => 'Search all contacts';
@override
String get startNewChatSearchHint => 'Name, username or groupname';
@override
String get shareImagedSelectAll => 'Select all';
@ -531,6 +534,21 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get cancel => 'Cancel';
@override
String get now => 'Now';
@override
String get you => 'You';
@override
String get minutesShort => 'min.';
@override
String get image => 'Image';
@override
String get video => 'Video';
@override
String get react => 'React';
@ -540,6 +558,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get copy => 'Copy';
@override
String get edit => 'Edit';
@override
String get delete => 'Delete';
@ -603,8 +624,7 @@ class AppLocalizationsEn extends AppLocalizations {
'The invitation code you provided is invalid. Please check the code and try again.';
@override
String get errorUsernameAlreadyTaken =>
'The username you want to use is already taken. Please choose a different username.';
String get errorUsernameAlreadyTaken => 'The username is already taken.';
@override
String get errorSignatureNotValid =>
@ -909,7 +929,10 @@ class AppLocalizationsEn extends AppLocalizations {
String get deleteTitle => 'Are you sure?';
@override
String get deleteOkBtn => 'Delete for me';
String get deleteOkBtnForAll => 'Delete for all';
@override
String get deleteOkBtnForMe => 'Delete for me';
@override
String get deleteImageTitle => 'Are you sure?';
@ -946,6 +969,10 @@ class AppLocalizationsEn extends AppLocalizations {
String get backupTwonlySafeDesc =>
'Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.';
@override
String get backupNoPasswordRecovery =>
'Due to twonly\'s security system, there is (currently) no password recovery function. Therefore, you must remember your password or, better yet, write it down.';
@override
String get backupServer => 'Server';
@ -993,11 +1020,11 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get backupTwonlySafeLongDesc =>
'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.';
'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Backup regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.';
@override
String get backupSelectStrongPassword =>
'Choose a secure password. This is required if you want to restore your twonly Safe backup.';
'Choose a secure password. This is required if you want to restore your twonly Backup.';
@override
String get password => 'Password';
@ -1020,7 +1047,7 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get backupOwnServerDesc =>
'Save your twonly safe backups at twonly or on any server of your choice.';
'Save your twonly Backup at twonly or on any server of your choice.';
@override
String get backupUseOwnServer => 'Use server';
@ -1031,12 +1058,15 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get backupTwonlySaveNow => 'Save now';
@override
String get backupChangePassword => 'Change password';
@override
String get twonlySafeRecoverTitle => 'Recovery';
@override
String get twonlySafeRecoverDesc =>
'If you have created a backup with twonly Safe, you can restore it here.';
'If you have created a backup with twonly Backup, you can restore it here.';
@override
String get twonlySafeRecoverBtn => 'Restore backup';
@ -1061,6 +1091,10 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get doubleClickToReopen => 'Double-click\nto open again';
@override
String get uploadLimitReached =>
'The upload limit has\been reached. Upgrade to Pro\nor wait until tomorrow.';
@override
String get retransmissionRequested => 'Retransmission requested';
@ -1085,4 +1119,356 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get newDeviceRegistered =>
'You have logged in on another device. You have therefore been logged out here.';
@override
String get tabToRemoveEmoji => 'Tab to remove';
@override
String get quotedMessageWasDeleted => 'The quoted message has been deleted.';
@override
String get messageWasDeleted => 'Message has been deleted.';
@override
String get messageWasDeletedShort => 'Deleted';
@override
String get sent => 'Delivered';
@override
String get sentTo => 'Delivered to';
@override
String get received => 'Received';
@override
String get opened => 'Opened';
@override
String get waitingForInternet => 'Waiting for internet';
@override
String get editHistory => 'Edit history';
@override
String get archivedChats => 'Archived chats';
@override
String get durationShortSecond => 'Sec.';
@override
String get durationShortMinute => 'Min.';
@override
String get durationShortHour => 'Hrs.';
@override
String durationShortDays(num count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Days',
one: '1 Day',
);
return '$_temp0';
}
@override
String get contacts => 'Contacts';
@override
String get groups => 'Groups';
@override
String get newGroup => 'New group';
@override
String get selectMembers => 'Select members';
@override
String get selectGroupName => 'Select group name';
@override
String get groupNameInput => 'Group name';
@override
String get groupMembers => 'Members';
@override
String get addMember => 'Add member';
@override
String get createGroup => 'Create group';
@override
String get leaveGroup => 'Leave group';
@override
String get createContactRequest => 'Create contact request';
@override
String get contactRequestSend => 'Contact request send';
@override
String get makeAdmin => 'Make admin';
@override
String get removeAdmin => 'Remove as admin';
@override
String get removeFromGroup => 'Remove from group';
@override
String get admin => 'Admin';
@override
String revokeAdminRightsTitle(Object username) {
return 'Revoke $username\'s admin rights?';
}
@override
String get revokeAdminRightsOkBtn => 'Remove as admin';
@override
String makeAdminRightsTitle(Object username) {
return 'Make $username an admin?';
}
@override
String makeAdminRightsBody(Object username) {
return '$username will be able to edit this group and its members.';
}
@override
String get makeAdminRightsOkBtn => 'Make admin';
@override
String get updateGroup => 'Update group';
@override
String get alreadyInGroup => 'Already in Group';
@override
String removeContactFromGroupTitle(Object username) {
return 'Remove $username from this group?';
}
@override
String youChangedGroupName(Object newGroupName) {
return 'You have changed the group name to \"$newGroupName\".';
}
@override
String makerChangedGroupName(Object maker, Object newGroupName) {
return '$maker has changed the group name to \"$newGroupName\".';
}
@override
String get youCreatedGroup => 'You have created the group.';
@override
String makerCreatedGroup(Object maker) {
return '$maker has created the group.';
}
@override
String youRemovedMember(Object affected) {
return 'You have removed $affected from the group.';
}
@override
String makerRemovedMember(Object affected, Object maker) {
return '$maker has removed $affected from the group.';
}
@override
String youAddedMember(Object affected) {
return 'You have added $affected to the group.';
}
@override
String makerAddedMember(Object affected, Object maker) {
return '$maker has added $affected to the group.';
}
@override
String youMadeAdmin(Object affected) {
return 'You made $affected an admin.';
}
@override
String makerMadeAdmin(Object affected, Object maker) {
return '$maker made $affected an admin.';
}
@override
String youRevokedAdminRights(Object affectedR) {
return 'You revoked $affectedR admin rights.';
}
@override
String makerRevokedAdminRights(Object affectedR, Object maker) {
return '$maker revoked $affectedR admin rights.';
}
@override
String get youLeftGroup => 'You have left the group.';
@override
String makerLeftGroup(Object maker) {
return '$maker has left the group.';
}
@override
String get groupActionYou => 'you';
@override
String get groupActionYour => 'your';
@override
String get notificationFillerIn => 'in';
@override
String notificationText(Object inGroup) {
return 'sent a message$inGroup.';
}
@override
String notificationTwonly(Object inGroup) {
return 'sent a twonly$inGroup.';
}
@override
String notificationVideo(Object inGroup) {
return 'sent a video$inGroup.';
}
@override
String notificationImage(Object inGroup) {
return 'sent a image$inGroup.';
}
@override
String notificationAudio(Object inGroup) {
return 'sent a voice message$inGroup.';
}
@override
String notificationAddedToGroup(Object groupname) {
return 'has added you to \"$groupname\"';
}
@override
String get notificationContactRequest => 'wants to connect with you.';
@override
String get notificationAcceptRequest => 'is now connected with you.';
@override
String get notificationStoredMediaFile => 'has stored your image.';
@override
String get notificationReaction => 'has reacted to your image.';
@override
String get notificationReopenedMedia => 'has reopened your image.';
@override
String notificationReactionToVideo(Object reaction) {
return 'has reacted with $reaction to your video.';
}
@override
String notificationReactionToText(Object reaction) {
return 'has reacted with $reaction to your message.';
}
@override
String notificationReactionToImage(Object reaction) {
return 'has reacted with $reaction to your image.';
}
@override
String notificationReactionToAudio(Object reaction) {
return 'has reacted with $reaction to your audio message.';
}
@override
String notificationResponse(Object inGroup) {
return 'has responded$inGroup.';
}
@override
String get notificationTitleUnknownUser => 'Someone';
@override
String get notificationCategoryMessageTitle => 'Messages';
@override
String get notificationCategoryMessageDesc => 'Messages from other users.';
@override
String get groupContextMenuDeleteGroup =>
'This will permanently delete all messages in this chat.';
@override
String get groupYouAreNowLongerAMember =>
'You are no longer part of this group.';
@override
String get groupNetworkIssue => 'Network issue. Try again later.';
@override
String get leaveGroupSelectOtherAdminTitle => 'Select another admin';
@override
String get leaveGroupSelectOtherAdminBody =>
'To leave the group, you must first select a new administrator.';
@override
String get leaveGroupSureTitle => 'Leave group';
@override
String get leaveGroupSureBody => 'Do you really want to leave the group?';
@override
String get leaveGroupSureOkBtn => 'Leave group';
@override
String changeDisplayMaxTime(Object time, Object username) {
return 'Chats will now be deleted after $time ($username).';
}
@override
String youChangedDisplayMaxTime(Object time) {
return 'Chats will now be deleted after $time.';
}
@override
String get userGotReported => 'User has been reported.';
@override
String get deleteChatAfter => 'Delete chat after...';
@override
String get deleteChatAfterAnHour => 'one hour.';
@override
String get deleteChatAfterADay => 'one day.';
@override
String get deleteChatAfterAWeek => 'one week.';
@override
String get deleteChatAfterAMonth => 'one month.';
@override
String get deleteChatAfterAYear => 'one year.';
@override
String get yourTwonlyScore => 'Your twonly-Score';
@override
String get registrationClosed =>
'Due to the current high volume of registrations, we have temporarily disabled registration to ensure that the service remains reliable. Please try again in a few days.';
}

View file

@ -1,331 +0,0 @@
// ignore_for_file: strict_raw_type, prefer_constructors_over_static_methods
import 'package:flutter/material.dart';
import 'package:twonly/src/database/tables/messages_table.dart';
import 'package:twonly/src/utils/misc.dart';
Color getMessageColorFromType(MessageContent content, BuildContext context) {
Color color;
if (content is TextMessageContent) {
color = Colors.blueAccent;
} else {
if (content is MediaMessageContent) {
if (content.isRealTwonly) {
color = context.color.primary;
} else {
if (content.isVideo) {
color = const Color.fromARGB(255, 243, 33, 208);
} else {
color = Colors.redAccent;
}
}
} else {
return (isDarkMode(context)) ? Colors.white : Colors.black;
}
}
return color;
}
extension MessageKindExtension on MessageKind {
String get name => toString().split('.').last;
static MessageKind fromString(String name) {
return MessageKind.values.firstWhere((e) => e.name == name);
}
}
class MessageJson {
MessageJson({
required this.kind,
required this.content,
required this.timestamp,
this.messageReceiverId,
this.messageSenderId,
this.retransId,
});
final MessageKind kind;
final MessageContent? content;
final int? messageReceiverId;
final int? messageSenderId;
int? retransId;
DateTime timestamp;
@override
String toString() {
return 'Message(kind: $kind, content: $content, timestamp: $timestamp)';
}
static MessageJson fromJson(Map<String, dynamic> json) {
final kind = MessageKindExtension.fromString(json['kind'] as String);
return MessageJson(
kind: kind,
messageReceiverId: (json['messageReceiverId'] as num?)?.toInt(),
messageSenderId: (json['messageSenderId'] as num?)?.toInt(),
retransId: (json['retransId'] as num?)?.toInt(),
content: MessageContent.fromJson(
kind,
json['content'] as Map<String, dynamic>,
),
timestamp: DateTime.fromMillisecondsSinceEpoch(json['timestamp'] as int),
);
}
Map<String, dynamic> toJson() => <String, dynamic>{
'kind': kind.name,
'content': content?.toJson(),
'messageReceiverId': messageReceiverId,
'messageSenderId': messageSenderId,
'retransId': retransId,
'timestamp': timestamp.toUtc().millisecondsSinceEpoch,
};
}
class MessageContent {
MessageContent();
static MessageContent? fromJson(MessageKind kind, Map json) {
switch (kind) {
case MessageKind.media:
return MediaMessageContent.fromJson(json);
case MessageKind.textMessage:
return TextMessageContent.fromJson(json);
case MessageKind.profileChange:
return ProfileContent.fromJson(json);
case MessageKind.pushKey:
return PushKeyContent.fromJson(json);
case MessageKind.reopenedMedia:
return ReopenedMediaFileContent.fromJson(json);
case MessageKind.flameSync:
return FlameSyncContent.fromJson(json);
case MessageKind.ack:
return AckContent.fromJson(json);
case MessageKind.signalDecryptError:
return SignalDecryptErrorContent.fromJson(json);
case MessageKind.storedMediaFile:
case MessageKind.contactRequest:
case MessageKind.rejectRequest:
case MessageKind.acceptRequest:
case MessageKind.opened:
case MessageKind.requestPushKey:
case MessageKind.receiveMediaError:
}
return null;
}
Map toJson() {
return {};
}
}
class MediaMessageContent extends MessageContent {
MediaMessageContent({
required this.maxShowTime,
required this.isRealTwonly,
required this.isVideo,
required this.mirrorVideo,
this.downloadToken,
this.encryptionKey,
this.encryptionMac,
this.encryptionNonce,
});
final int maxShowTime;
final bool isRealTwonly;
final bool isVideo;
final bool mirrorVideo;
final List<int>? downloadToken;
final List<int>? encryptionKey;
final List<int>? encryptionMac;
final List<int>? encryptionNonce;
static MediaMessageContent fromJson(Map json) {
return MediaMessageContent(
downloadToken: json['downloadToken'] == null
? null
: List<int>.from(json['downloadToken'] as List),
encryptionKey: json['encryptionKey'] == null
? null
: List<int>.from(json['encryptionKey'] as List),
encryptionMac: json['encryptionMac'] == null
? null
: List<int>.from(json['encryptionMac'] as List),
encryptionNonce: json['encryptionNonce'] == null
? null
: List<int>.from(json['encryptionNonce'] as List),
maxShowTime: json['maxShowTime'] as int,
isRealTwonly: json['isRealTwonly'] as bool,
isVideo: json['isVideo'] as bool? ?? false,
mirrorVideo: json['mirrorVideo'] as bool? ?? false,
);
}
@override
Map toJson() {
return {
'downloadToken': downloadToken,
'encryptionKey': encryptionKey,
'encryptionMac': encryptionMac,
'encryptionNonce': encryptionNonce,
'isRealTwonly': isRealTwonly,
'maxShowTime': maxShowTime,
'isVideo': isVideo,
'mirrorVideo': mirrorVideo,
};
}
}
class TextMessageContent extends MessageContent {
TextMessageContent({
required this.text,
this.responseToMessageId,
this.responseToOtherMessageId,
});
String text;
int? responseToMessageId;
int? responseToOtherMessageId;
static TextMessageContent fromJson(Map json) {
return TextMessageContent(
text: json['text'] as String,
responseToOtherMessageId: json.containsKey('responseToOtherMessageId')
? json['responseToOtherMessageId'] as int?
: null,
responseToMessageId: json.containsKey('responseToMessageId')
? json['responseToMessageId'] as int?
: null,
);
}
@override
Map toJson() {
return {
'text': text,
'responseToMessageId': responseToMessageId,
'responseToOtherMessageId': responseToOtherMessageId,
};
}
}
class ReopenedMediaFileContent extends MessageContent {
ReopenedMediaFileContent({required this.messageId});
int messageId;
static ReopenedMediaFileContent fromJson(Map json) {
return ReopenedMediaFileContent(messageId: json['messageId'] as int);
}
@override
Map toJson() {
return {'messageId': messageId};
}
}
class SignalDecryptErrorContent extends MessageContent {
SignalDecryptErrorContent({required this.encryptedHash});
List<int> encryptedHash;
static SignalDecryptErrorContent fromJson(Map json) {
return SignalDecryptErrorContent(
encryptedHash: List<int>.from(json['encryptedHash'] as List),
);
}
@override
Map toJson() {
return {
'encryptedHash': encryptedHash,
};
}
}
class AckContent extends MessageContent {
AckContent({required this.messageIdToAck, required this.retransIdToAck});
int? messageIdToAck;
int retransIdToAck;
static AckContent fromJson(Map json) {
return AckContent(
messageIdToAck: json['messageIdToAck'] as int?,
retransIdToAck: json['retransIdToAck'] as int,
);
}
@override
Map toJson() {
return {
'messageIdToAck': messageIdToAck,
'retransIdToAck': retransIdToAck,
};
}
}
class ProfileContent extends MessageContent {
ProfileContent({required this.avatarSvg, required this.displayName});
String avatarSvg;
String displayName;
static ProfileContent fromJson(Map json) {
return ProfileContent(
avatarSvg: json['avatarSvg'] as String,
displayName: json['displayName'] as String,
);
}
@override
Map toJson() {
return {'avatarSvg': avatarSvg, 'displayName': displayName};
}
}
class PushKeyContent extends MessageContent {
PushKeyContent({required this.keyId, required this.key});
int keyId;
List<int> key;
static PushKeyContent fromJson(Map json) {
return PushKeyContent(
keyId: json['keyId'] as int,
key: List<int>.from(json['key'] as List),
);
}
@override
Map toJson() {
return {
'keyId': keyId,
'key': key,
};
}
}
class FlameSyncContent extends MessageContent {
FlameSyncContent({
required this.flameCounter,
required this.bestFriend,
required this.lastFlameCounterChange,
});
int flameCounter;
DateTime lastFlameCounterChange;
bool bestFriend;
static FlameSyncContent fromJson(Map json) {
return FlameSyncContent(
flameCounter: json['flameCounter'] as int,
bestFriend: json['bestFriend'] as bool,
lastFlameCounterChange: DateTime.fromMillisecondsSinceEpoch(
json['lastFlameCounterChange'] as int,
),
);
}
@override
Map toJson() {
return {
'flameCounter': flameCounter,
'bestFriend': bestFriend,
'lastFlameCounterChange':
lastFlameCounterChange.toUtc().millisecondsSinceEpoch,
};
}
}

View file

@ -9,16 +9,12 @@ class UserData {
required this.username,
required this.displayName,
required this.subscriptionPlan,
required this.isDemoUser,
});
factory UserData.fromJson(Map<String, dynamic> json) =>
_$UserDataFromJson(json);
final int userId;
@JsonKey(defaultValue: false)
bool isDemoUser = false;
// -- USER PROFILE --
String username;
@ -26,6 +22,9 @@ class UserData {
String? avatarSvg;
String? avatarJson;
@JsonKey(defaultValue: 0)
int appVersion = 0;
@JsonKey(defaultValue: 0)
int avatarCounter = 0;
@ -65,14 +64,12 @@ class UserData {
@JsonKey(defaultValue: false)
bool storeMediaFilesInGallery = false;
List<String>? lastUsedEditorEmojis;
String? lastPlanBallance;
String? additionalUserInvites;
List<String>? tutorialDisplayed;
int? myBestFriendContactId;
String? myBestFriendGroupId;
DateTime? signalLastSignedPreKeyUpdated;

View file

@ -11,10 +11,10 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
username: json['username'] as String,
displayName: json['displayName'] as String,
subscriptionPlan: json['subscriptionPlan'] as String? ?? 'Free',
isDemoUser: json['isDemoUser'] as bool? ?? false,
)
..avatarSvg = json['avatarSvg'] as String?
..avatarJson = json['avatarJson'] as String?
..appVersion = (json['appVersion'] as num?)?.toInt() ?? 0
..avatarCounter = (json['avatarCounter'] as num?)?.toInt() ?? 0
..isDeveloper = json['isDeveloper'] as bool? ?? false
..deviceId = (json['deviceId'] as num?)?.toInt() ?? 0
@ -40,15 +40,12 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
)
..storeMediaFilesInGallery =
json['storeMediaFilesInGallery'] as bool? ?? false
..lastUsedEditorEmojis = (json['lastUsedEditorEmojis'] as List<dynamic>?)
?.map((e) => e as String)
.toList()
..lastPlanBallance = json['lastPlanBallance'] as String?
..additionalUserInvites = json['additionalUserInvites'] as String?
..tutorialDisplayed = (json['tutorialDisplayed'] as List<dynamic>?)
?.map((e) => e as String)
.toList()
..myBestFriendContactId = (json['myBestFriendContactId'] as num?)?.toInt()
..myBestFriendGroupId = json['myBestFriendGroupId'] as String?
..signalLastSignedPreKeyUpdated =
json['signalLastSignedPreKeyUpdated'] == null
? null
@ -74,11 +71,11 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
'userId': instance.userId,
'isDemoUser': instance.isDemoUser,
'username': instance.username,
'displayName': instance.displayName,
'avatarSvg': instance.avatarSvg,
'avatarJson': instance.avatarJson,
'appVersion': instance.appVersion,
'avatarCounter': instance.avatarCounter,
'isDeveloper': instance.isDeveloper,
'deviceId': instance.deviceId,
@ -93,11 +90,10 @@ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
'preSelectedEmojies': instance.preSelectedEmojies,
'autoDownloadOptions': instance.autoDownloadOptions,
'storeMediaFilesInGallery': instance.storeMediaFilesInGallery,
'lastUsedEditorEmojis': instance.lastUsedEditorEmojis,
'lastPlanBallance': instance.lastPlanBallance,
'additionalUserInvites': instance.additionalUserInvites,
'tutorialDisplayed': instance.tutorialDisplayed,
'myBestFriendContactId': instance.myBestFriendContactId,
'myBestFriendGroupId': instance.myBestFriendGroupId,
'signalLastSignedPreKeyUpdated':
instance.signalLastSignedPreKeyUpdated?.toIso8601String(),
'currentPreKeyIndexStart': instance.currentPreKeyIndexStart,

View file

@ -1,88 +1,34 @@
import 'dart:convert';
import 'dart:io';
import 'package:drift/drift.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/services/api/media_upload.dart' as send;
import 'package:twonly/src/services/thumbnail.service.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
class MemoryItem {
MemoryItem({
required this.id,
required this.mediaService,
required this.messages,
required this.date,
required this.mirrorVideo,
required this.thumbnailPath,
this.imagePath,
this.videoPath,
});
final int id;
final bool mirrorVideo;
final List<Message> messages;
final DateTime date;
final File thumbnailPath;
final File? imagePath;
final File? videoPath;
final MediaFileService mediaService;
static Future<Map<int, MemoryItem>> convertFromMessages(
static Future<Map<String, MemoryItem>> convertFromMessages(
List<Message> messages,
) async {
final items = <int, MemoryItem>{};
final items = <String, MemoryItem>{};
for (final message in messages) {
final isSend = message.messageOtherId == null;
final id = message.mediaUploadId ?? message.messageId;
final basePath = await send.getMediaFilePath(
id,
isSend ? 'send' : 'received',
);
File? imagePath;
late File thumbnailFile;
File? videoPath;
if (File('$basePath.mp4').existsSync()) {
videoPath = File('$basePath.mp4');
thumbnailFile = getThumbnailPath(videoPath);
if (!thumbnailFile.existsSync()) {
await createThumbnailsForVideo(videoPath);
}
} else if (File('$basePath.png').existsSync()) {
imagePath = File('$basePath.png');
thumbnailFile = getThumbnailPath(imagePath);
if (!thumbnailFile.existsSync()) {
await createThumbnailsForImage(imagePath);
}
} else {
if (message.mediaStored) {
/// media file was deleted, ... remove the file
await twonlyDB.messagesDao.updateMessageByMessageId(
message.messageId,
const MessagesCompanion(
mediaStored: Value(false),
),
);
}
if (message.mediaId == null) continue;
final mediaService = await MediaFileService.fromMediaId(message.mediaId!);
if (mediaService == null) continue;
if (!mediaService.imagePreviewAvailable) {
continue;
}
var mirrorVideo = false;
if (videoPath != null) {
final content = MediaMessageContent.fromJson(
jsonDecode(message.contentJson!) as Map,
);
mirrorVideo = content.mirrorVideo;
}
items
.putIfAbsent(
id,
message.mediaId!,
() => MemoryItem(
id: id,
mediaService: mediaService,
messages: [],
date: message.sendAt,
mirrorVideo: mirrorVideo,
thumbnailPath: thumbnailFile,
imagePath: imagePath,
videoPath: videoPath,
),
)
.messages

View file

@ -158,6 +158,575 @@ class UploadRequest extends $pb.GeneratedMessage {
$core.List<TextMessage> get messagesOnSuccess => $_getList(2);
}
class UpdateGroupState_UpdateTBS extends $pb.GeneratedMessage {
factory UpdateGroupState_UpdateTBS({
$fixnum.Int64? versionId,
$core.List<$core.int>? encryptedGroupState,
$core.List<$core.int>? publicKey,
$core.List<$core.int>? removeAdmin,
$core.List<$core.int>? addAdmin,
$core.List<$core.int>? nonce,
}) {
final $result = create();
if (versionId != null) {
$result.versionId = versionId;
}
if (encryptedGroupState != null) {
$result.encryptedGroupState = encryptedGroupState;
}
if (publicKey != null) {
$result.publicKey = publicKey;
}
if (removeAdmin != null) {
$result.removeAdmin = removeAdmin;
}
if (addAdmin != null) {
$result.addAdmin = addAdmin;
}
if (nonce != null) {
$result.nonce = nonce;
}
return $result;
}
UpdateGroupState_UpdateTBS._() : super();
factory UpdateGroupState_UpdateTBS.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory UpdateGroupState_UpdateTBS.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'UpdateGroupState.UpdateTBS', package: const $pb.PackageName(_omitMessageNames ? '' : 'http_requests'), createEmptyInstance: create)
..a<$fixnum.Int64>(1, _omitFieldNames ? '' : 'versionId', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'encryptedGroupState', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'publicKey', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(5, _omitFieldNames ? '' : 'removeAdmin', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(6, _omitFieldNames ? '' : 'addAdmin', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(7, _omitFieldNames ? '' : 'nonce', $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')
UpdateGroupState_UpdateTBS clone() => UpdateGroupState_UpdateTBS()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
UpdateGroupState_UpdateTBS copyWith(void Function(UpdateGroupState_UpdateTBS) updates) => super.copyWith((message) => updates(message as UpdateGroupState_UpdateTBS)) as UpdateGroupState_UpdateTBS;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static UpdateGroupState_UpdateTBS create() => UpdateGroupState_UpdateTBS._();
UpdateGroupState_UpdateTBS createEmptyInstance() => create();
static $pb.PbList<UpdateGroupState_UpdateTBS> createRepeated() => $pb.PbList<UpdateGroupState_UpdateTBS>();
@$core.pragma('dart2js:noInline')
static UpdateGroupState_UpdateTBS getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UpdateGroupState_UpdateTBS>(create);
static UpdateGroupState_UpdateTBS? _defaultInstance;
@$pb.TagNumber(1)
$fixnum.Int64 get versionId => $_getI64(0);
@$pb.TagNumber(1)
set versionId($fixnum.Int64 v) { $_setInt64(0, v); }
@$pb.TagNumber(1)
$core.bool hasVersionId() => $_has(0);
@$pb.TagNumber(1)
void clearVersionId() => clearField(1);
@$pb.TagNumber(3)
$core.List<$core.int> get encryptedGroupState => $_getN(1);
@$pb.TagNumber(3)
set encryptedGroupState($core.List<$core.int> v) { $_setBytes(1, v); }
@$pb.TagNumber(3)
$core.bool hasEncryptedGroupState() => $_has(1);
@$pb.TagNumber(3)
void clearEncryptedGroupState() => clearField(3);
@$pb.TagNumber(4)
$core.List<$core.int> get publicKey => $_getN(2);
@$pb.TagNumber(4)
set publicKey($core.List<$core.int> v) { $_setBytes(2, v); }
@$pb.TagNumber(4)
$core.bool hasPublicKey() => $_has(2);
@$pb.TagNumber(4)
void clearPublicKey() => clearField(4);
/// public group key
@$pb.TagNumber(5)
$core.List<$core.int> get removeAdmin => $_getN(3);
@$pb.TagNumber(5)
set removeAdmin($core.List<$core.int> v) { $_setBytes(3, v); }
@$pb.TagNumber(5)
$core.bool hasRemoveAdmin() => $_has(3);
@$pb.TagNumber(5)
void clearRemoveAdmin() => clearField(5);
@$pb.TagNumber(6)
$core.List<$core.int> get addAdmin => $_getN(4);
@$pb.TagNumber(6)
set addAdmin($core.List<$core.int> v) { $_setBytes(4, v); }
@$pb.TagNumber(6)
$core.bool hasAddAdmin() => $_has(4);
@$pb.TagNumber(6)
void clearAddAdmin() => clearField(6);
@$pb.TagNumber(7)
$core.List<$core.int> get nonce => $_getN(5);
@$pb.TagNumber(7)
set nonce($core.List<$core.int> v) { $_setBytes(5, v); }
@$pb.TagNumber(7)
$core.bool hasNonce() => $_has(5);
@$pb.TagNumber(7)
void clearNonce() => clearField(7);
}
/// plaintext message send to the server
class UpdateGroupState extends $pb.GeneratedMessage {
factory UpdateGroupState({
UpdateGroupState_UpdateTBS? update,
$core.List<$core.int>? signature,
}) {
final $result = create();
if (update != null) {
$result.update = update;
}
if (signature != null) {
$result.signature = signature;
}
return $result;
}
UpdateGroupState._() : super();
factory UpdateGroupState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory UpdateGroupState.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'UpdateGroupState', package: const $pb.PackageName(_omitMessageNames ? '' : 'http_requests'), createEmptyInstance: create)
..aOM<UpdateGroupState_UpdateTBS>(1, _omitFieldNames ? '' : 'update', subBuilder: UpdateGroupState_UpdateTBS.create)
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'signature', $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')
UpdateGroupState clone() => UpdateGroupState()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
UpdateGroupState copyWith(void Function(UpdateGroupState) updates) => super.copyWith((message) => updates(message as UpdateGroupState)) as UpdateGroupState;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static UpdateGroupState create() => UpdateGroupState._();
UpdateGroupState createEmptyInstance() => create();
static $pb.PbList<UpdateGroupState> createRepeated() => $pb.PbList<UpdateGroupState>();
@$core.pragma('dart2js:noInline')
static UpdateGroupState getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UpdateGroupState>(create);
static UpdateGroupState? _defaultInstance;
@$pb.TagNumber(1)
UpdateGroupState_UpdateTBS get update => $_getN(0);
@$pb.TagNumber(1)
set update(UpdateGroupState_UpdateTBS v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasUpdate() => $_has(0);
@$pb.TagNumber(1)
void clearUpdate() => clearField(1);
@$pb.TagNumber(1)
UpdateGroupState_UpdateTBS ensureUpdate() => $_ensure(0);
@$pb.TagNumber(2)
$core.List<$core.int> get signature => $_getN(1);
@$pb.TagNumber(2)
set signature($core.List<$core.int> v) { $_setBytes(1, v); }
@$pb.TagNumber(2)
$core.bool hasSignature() => $_has(1);
@$pb.TagNumber(2)
void clearSignature() => clearField(2);
}
class NewGroupState extends $pb.GeneratedMessage {
factory NewGroupState({
$core.String? groupId,
$fixnum.Int64? versionId,
$core.List<$core.int>? encryptedGroupState,
$core.List<$core.int>? publicKey,
}) {
final $result = create();
if (groupId != null) {
$result.groupId = groupId;
}
if (versionId != null) {
$result.versionId = versionId;
}
if (encryptedGroupState != null) {
$result.encryptedGroupState = encryptedGroupState;
}
if (publicKey != null) {
$result.publicKey = publicKey;
}
return $result;
}
NewGroupState._() : super();
factory NewGroupState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory NewGroupState.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'NewGroupState', package: const $pb.PackageName(_omitMessageNames ? '' : 'http_requests'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'groupId')
..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'versionId', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'encryptedGroupState', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'publicKey', $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')
NewGroupState clone() => NewGroupState()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
NewGroupState copyWith(void Function(NewGroupState) updates) => super.copyWith((message) => updates(message as NewGroupState)) as NewGroupState;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static NewGroupState create() => NewGroupState._();
NewGroupState createEmptyInstance() => create();
static $pb.PbList<NewGroupState> createRepeated() => $pb.PbList<NewGroupState>();
@$core.pragma('dart2js:noInline')
static NewGroupState getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<NewGroupState>(create);
static NewGroupState? _defaultInstance;
@$pb.TagNumber(1)
$core.String get groupId => $_getSZ(0);
@$pb.TagNumber(1)
set groupId($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasGroupId() => $_has(0);
@$pb.TagNumber(1)
void clearGroupId() => clearField(1);
@$pb.TagNumber(2)
$fixnum.Int64 get versionId => $_getI64(1);
@$pb.TagNumber(2)
set versionId($fixnum.Int64 v) { $_setInt64(1, v); }
@$pb.TagNumber(2)
$core.bool hasVersionId() => $_has(1);
@$pb.TagNumber(2)
void clearVersionId() => clearField(2);
@$pb.TagNumber(3)
$core.List<$core.int> get encryptedGroupState => $_getN(2);
@$pb.TagNumber(3)
set encryptedGroupState($core.List<$core.int> v) { $_setBytes(2, v); }
@$pb.TagNumber(3)
$core.bool hasEncryptedGroupState() => $_has(2);
@$pb.TagNumber(3)
void clearEncryptedGroupState() => clearField(3);
@$pb.TagNumber(4)
$core.List<$core.int> get publicKey => $_getN(3);
@$pb.TagNumber(4)
set publicKey($core.List<$core.int> v) { $_setBytes(3, v); }
@$pb.TagNumber(4)
$core.bool hasPublicKey() => $_has(3);
@$pb.TagNumber(4)
void clearPublicKey() => clearField(4);
}
class AppendGroupState_AppendTBS extends $pb.GeneratedMessage {
factory AppendGroupState_AppendTBS({
$core.List<$core.int>? encryptedGroupStateAppend,
$core.List<$core.int>? publicKey,
$core.String? groupId,
$core.List<$core.int>? nonce,
}) {
final $result = create();
if (encryptedGroupStateAppend != null) {
$result.encryptedGroupStateAppend = encryptedGroupStateAppend;
}
if (publicKey != null) {
$result.publicKey = publicKey;
}
if (groupId != null) {
$result.groupId = groupId;
}
if (nonce != null) {
$result.nonce = nonce;
}
return $result;
}
AppendGroupState_AppendTBS._() : super();
factory AppendGroupState_AppendTBS.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory AppendGroupState_AppendTBS.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AppendGroupState.AppendTBS', package: const $pb.PackageName(_omitMessageNames ? '' : 'http_requests'), createEmptyInstance: create)
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'encryptedGroupStateAppend', $pb.PbFieldType.OY)
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'publicKey', $pb.PbFieldType.OY)
..aOS(3, _omitFieldNames ? '' : 'groupId')
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'nonce', $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')
AppendGroupState_AppendTBS clone() => AppendGroupState_AppendTBS()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
AppendGroupState_AppendTBS copyWith(void Function(AppendGroupState_AppendTBS) updates) => super.copyWith((message) => updates(message as AppendGroupState_AppendTBS)) as AppendGroupState_AppendTBS;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AppendGroupState_AppendTBS create() => AppendGroupState_AppendTBS._();
AppendGroupState_AppendTBS createEmptyInstance() => create();
static $pb.PbList<AppendGroupState_AppendTBS> createRepeated() => $pb.PbList<AppendGroupState_AppendTBS>();
@$core.pragma('dart2js:noInline')
static AppendGroupState_AppendTBS getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AppendGroupState_AppendTBS>(create);
static AppendGroupState_AppendTBS? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get encryptedGroupStateAppend => $_getN(0);
@$pb.TagNumber(1)
set encryptedGroupStateAppend($core.List<$core.int> v) { $_setBytes(0, v); }
@$pb.TagNumber(1)
$core.bool hasEncryptedGroupStateAppend() => $_has(0);
@$pb.TagNumber(1)
void clearEncryptedGroupStateAppend() => clearField(1);
@$pb.TagNumber(2)
$core.List<$core.int> get publicKey => $_getN(1);
@$pb.TagNumber(2)
set publicKey($core.List<$core.int> v) { $_setBytes(1, v); }
@$pb.TagNumber(2)
$core.bool hasPublicKey() => $_has(1);
@$pb.TagNumber(2)
void clearPublicKey() => clearField(2);
@$pb.TagNumber(3)
$core.String get groupId => $_getSZ(2);
@$pb.TagNumber(3)
set groupId($core.String v) { $_setString(2, v); }
@$pb.TagNumber(3)
$core.bool hasGroupId() => $_has(2);
@$pb.TagNumber(3)
void clearGroupId() => clearField(3);
@$pb.TagNumber(4)
$core.List<$core.int> get nonce => $_getN(3);
@$pb.TagNumber(4)
set nonce($core.List<$core.int> v) { $_setBytes(3, v); }
@$pb.TagNumber(4)
$core.bool hasNonce() => $_has(3);
@$pb.TagNumber(4)
void clearNonce() => clearField(4);
}
class AppendGroupState extends $pb.GeneratedMessage {
factory AppendGroupState({
$core.List<$core.int>? signature,
AppendGroupState_AppendTBS? appendTBS,
$fixnum.Int64? versionId,
}) {
final $result = create();
if (signature != null) {
$result.signature = signature;
}
if (appendTBS != null) {
$result.appendTBS = appendTBS;
}
if (versionId != null) {
$result.versionId = versionId;
}
return $result;
}
AppendGroupState._() : super();
factory AppendGroupState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory AppendGroupState.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AppendGroupState', package: const $pb.PackageName(_omitMessageNames ? '' : 'http_requests'), createEmptyInstance: create)
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY)
..aOM<AppendGroupState_AppendTBS>(2, _omitFieldNames ? '' : 'appendTBS', protoName: 'appendTBS', subBuilder: AppendGroupState_AppendTBS.create)
..a<$fixnum.Int64>(3, _omitFieldNames ? '' : 'versionId', $pb.PbFieldType.OU6, protoName: 'versionId', defaultOrMaker: $fixnum.Int64.ZERO)
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
AppendGroupState clone() => AppendGroupState()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
AppendGroupState copyWith(void Function(AppendGroupState) updates) => super.copyWith((message) => updates(message as AppendGroupState)) as AppendGroupState;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AppendGroupState create() => AppendGroupState._();
AppendGroupState createEmptyInstance() => create();
static $pb.PbList<AppendGroupState> createRepeated() => $pb.PbList<AppendGroupState>();
@$core.pragma('dart2js:noInline')
static AppendGroupState getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AppendGroupState>(create);
static AppendGroupState? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$core.int> get signature => $_getN(0);
@$pb.TagNumber(1)
set signature($core.List<$core.int> v) { $_setBytes(0, v); }
@$pb.TagNumber(1)
$core.bool hasSignature() => $_has(0);
@$pb.TagNumber(1)
void clearSignature() => clearField(1);
@$pb.TagNumber(2)
AppendGroupState_AppendTBS get appendTBS => $_getN(1);
@$pb.TagNumber(2)
set appendTBS(AppendGroupState_AppendTBS v) { setField(2, v); }
@$pb.TagNumber(2)
$core.bool hasAppendTBS() => $_has(1);
@$pb.TagNumber(2)
void clearAppendTBS() => clearField(2);
@$pb.TagNumber(2)
AppendGroupState_AppendTBS ensureAppendTBS() => $_ensure(1);
@$pb.TagNumber(3)
$fixnum.Int64 get versionId => $_getI64(2);
@$pb.TagNumber(3)
set versionId($fixnum.Int64 v) { $_setInt64(2, v); }
@$pb.TagNumber(3)
$core.bool hasVersionId() => $_has(2);
@$pb.TagNumber(3)
void clearVersionId() => clearField(3);
}
class GroupState extends $pb.GeneratedMessage {
factory GroupState({
$fixnum.Int64? versionId,
$core.List<$core.int>? encryptedGroupState,
$core.Iterable<AppendGroupState>? appendedGroupStates,
}) {
final $result = create();
if (versionId != null) {
$result.versionId = versionId;
}
if (encryptedGroupState != null) {
$result.encryptedGroupState = encryptedGroupState;
}
if (appendedGroupStates != null) {
$result.appendedGroupStates.addAll(appendedGroupStates);
}
return $result;
}
GroupState._() : super();
factory GroupState.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory GroupState.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GroupState', package: const $pb.PackageName(_omitMessageNames ? '' : 'http_requests'), createEmptyInstance: create)
..a<$fixnum.Int64>(1, _omitFieldNames ? '' : 'versionId', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'encryptedGroupState', $pb.PbFieldType.OY)
..pc<AppendGroupState>(3, _omitFieldNames ? '' : 'appendedGroupStates', $pb.PbFieldType.PM, subBuilder: AppendGroupState.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')
GroupState clone() => GroupState()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
GroupState copyWith(void Function(GroupState) updates) => super.copyWith((message) => updates(message as GroupState)) as GroupState;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static GroupState create() => GroupState._();
GroupState createEmptyInstance() => create();
static $pb.PbList<GroupState> createRepeated() => $pb.PbList<GroupState>();
@$core.pragma('dart2js:noInline')
static GroupState getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GroupState>(create);
static GroupState? _defaultInstance;
@$pb.TagNumber(1)
$fixnum.Int64 get versionId => $_getI64(0);
@$pb.TagNumber(1)
set versionId($fixnum.Int64 v) { $_setInt64(0, v); }
@$pb.TagNumber(1)
$core.bool hasVersionId() => $_has(0);
@$pb.TagNumber(1)
void clearVersionId() => 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); }
@$pb.TagNumber(2)
$core.bool hasEncryptedGroupState() => $_has(1);
@$pb.TagNumber(2)
void clearEncryptedGroupState() => clearField(2);
@$pb.TagNumber(3)
$core.List<AppendGroupState> get appendedGroupStates => $_getList(2);
}
/// this is just a database helper to store multiple appends
class AppendGroupStateHelper extends $pb.GeneratedMessage {
factory AppendGroupStateHelper({
$core.Iterable<AppendGroupState>? appendedGroupStates,
}) {
final $result = create();
if (appendedGroupStates != null) {
$result.appendedGroupStates.addAll(appendedGroupStates);
}
return $result;
}
AppendGroupStateHelper._() : super();
factory AppendGroupStateHelper.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory AppendGroupStateHelper.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AppendGroupStateHelper', package: const $pb.PackageName(_omitMessageNames ? '' : 'http_requests'), createEmptyInstance: create)
..pc<AppendGroupState>(1, _omitFieldNames ? '' : 'appendedGroupStates', $pb.PbFieldType.PM, subBuilder: AppendGroupState.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')
AppendGroupStateHelper clone() => AppendGroupStateHelper()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
AppendGroupStateHelper copyWith(void Function(AppendGroupStateHelper) updates) => super.copyWith((message) => updates(message as AppendGroupStateHelper)) as AppendGroupStateHelper;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static AppendGroupStateHelper create() => AppendGroupStateHelper._();
AppendGroupStateHelper createEmptyInstance() => create();
static $pb.PbList<AppendGroupStateHelper> createRepeated() => $pb.PbList<AppendGroupStateHelper>();
@$core.pragma('dart2js:noInline')
static AppendGroupStateHelper getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AppendGroupStateHelper>(create);
static AppendGroupStateHelper? _defaultInstance;
@$pb.TagNumber(1)
$core.List<AppendGroupState> get appendedGroupStates => $_getList(0);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');

View file

@ -48,3 +48,118 @@ final $typed_data.Uint8List uploadRequestDescriptor = $convert.base64Decode(
'c3VjY2VzcxgDIAMoCzIaLmh0dHBfcmVxdWVzdHMuVGV4dE1lc3NhZ2VSEW1lc3NhZ2VzT25TdW'
'NjZXNz');
@$core.Deprecated('Use updateGroupStateDescriptor instead')
const UpdateGroupState$json = {
'1': 'UpdateGroupState',
'2': [
{'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],
};
@$core.Deprecated('Use updateGroupStateDescriptor instead')
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': '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': 'nonce', '3': 7, '4': 1, '5': 12, '10': 'nonce'},
],
'8': [
{'1': '_remove_admin'},
{'1': '_add_admin'},
],
};
/// Descriptor for `UpdateGroupState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List updateGroupStateDescriptor = $convert.base64Decode(
'ChBVcGRhdGVHcm91cFN0YXRlEkEKBnVwZGF0ZRgBIAEoCzIpLmh0dHBfcmVxdWVzdHMuVXBkYX'
'RlR3JvdXBTdGF0ZS5VcGRhdGVUQlNSBnVwZGF0ZRIcCglzaWduYXR1cmUYAiABKAxSCXNpZ25h'
'dHVyZRr8AQoJVXBkYXRlVEJTEh0KCnZlcnNpb25faWQYASABKARSCXZlcnNpb25JZBIyChVlbm'
'NyeXB0ZWRfZ3JvdXBfc3RhdGUYAyABKAxSE2VuY3J5cHRlZEdyb3VwU3RhdGUSHQoKcHVibGlj'
'X2tleRgEIAEoDFIJcHVibGljS2V5EiYKDHJlbW92ZV9hZG1pbhgFIAEoDEgAUgtyZW1vdmVBZG'
'1pbogBARIgCglhZGRfYWRtaW4YBiABKAxIAVIIYWRkQWRtaW6IAQESFAoFbm9uY2UYByABKAxS'
'BW5vbmNlQg8KDV9yZW1vdmVfYWRtaW5CDAoKX2FkZF9hZG1pbg==');
@$core.Deprecated('Use newGroupStateDescriptor instead')
const NewGroupState$json = {
'1': 'NewGroupState',
'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': 'public_key', '3': 4, '4': 1, '5': 12, '10': 'publicKey'},
],
};
/// Descriptor for `NewGroupState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List newGroupStateDescriptor = $convert.base64Decode(
'Cg1OZXdHcm91cFN0YXRlEhkKCGdyb3VwX2lkGAEgASgJUgdncm91cElkEh0KCnZlcnNpb25faW'
'QYAiABKARSCXZlcnNpb25JZBIyChVlbmNyeXB0ZWRfZ3JvdXBfc3RhdGUYAyABKAxSE2VuY3J5'
'cHRlZEdyb3VwU3RhdGUSHQoKcHVibGljX2tleRgEIAEoDFIJcHVibGljS2V5');
@$core.Deprecated('Use appendGroupStateDescriptor instead')
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': 'versionId', '3': 3, '4': 1, '5': 4, '10': 'versionId'},
],
'3': [AppendGroupState_AppendTBS$json],
};
@$core.Deprecated('Use appendGroupStateDescriptor instead')
const AppendGroupState_AppendTBS$json = {
'1': 'AppendTBS',
'2': [
{'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'},
],
};
/// Descriptor for `AppendGroupState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List appendGroupStateDescriptor = $convert.base64Decode(
'ChBBcHBlbmRHcm91cFN0YXRlEhwKCXNpZ25hdHVyZRgBIAEoDFIJc2lnbmF0dXJlEkcKCWFwcG'
'VuZFRCUxgCIAEoCzIpLmh0dHBfcmVxdWVzdHMuQXBwZW5kR3JvdXBTdGF0ZS5BcHBlbmRUQlNS'
'CWFwcGVuZFRCUxIcCgl2ZXJzaW9uSWQYAyABKARSCXZlcnNpb25JZBqcAQoJQXBwZW5kVEJTEj'
'8KHGVuY3J5cHRlZF9ncm91cF9zdGF0ZV9hcHBlbmQYASABKAxSGWVuY3J5cHRlZEdyb3VwU3Rh'
'dGVBcHBlbmQSHQoKcHVibGljX2tleRgCIAEoDFIJcHVibGljS2V5EhkKCGdyb3VwX2lkGAMgAS'
'gJUgdncm91cElkEhQKBW5vbmNlGAQgASgMUgVub25jZQ==');
@$core.Deprecated('Use groupStateDescriptor instead')
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'},
],
};
/// Descriptor for `GroupState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List groupStateDescriptor = $convert.base64Decode(
'CgpHcm91cFN0YXRlEh0KCnZlcnNpb25faWQYASABKARSCXZlcnNpb25JZBIyChVlbmNyeXB0ZW'
'RfZ3JvdXBfc3RhdGUYAiABKAxSE2VuY3J5cHRlZEdyb3VwU3RhdGUSUwoVYXBwZW5kZWRfZ3Jv'
'dXBfc3RhdGVzGAMgAygLMh8uaHR0cF9yZXF1ZXN0cy5BcHBlbmRHcm91cFN0YXRlUhNhcHBlbm'
'RlZEdyb3VwU3RhdGVz');
@$core.Deprecated('Use appendGroupStateHelperDescriptor instead')
const AppendGroupStateHelper$json = {
'1': 'AppendGroupStateHelper',
'2': [
{'1': 'appended_group_states', '3': 1, '4': 3, '5': 11, '6': '.http_requests.AppendGroupState', '10': 'appendedGroupStates'},
],
};
/// Descriptor for `AppendGroupStateHelper`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List appendGroupStateHelperDescriptor = $convert.base64Decode(
'ChZBcHBlbmRHcm91cFN0YXRlSGVscGVyElMKFWFwcGVuZGVkX2dyb3VwX3N0YXRlcxgBIAMoCz'
'IfLmh0dHBfcmVxdWVzdHMuQXBwZW5kR3JvdXBTdGF0ZVITYXBwZW5kZWRHcm91cFN0YXRlcw==');

View file

@ -196,6 +196,38 @@ class V0 extends $pb.GeneratedMessage {
Response ensureResponse() => $_ensure(3);
}
class Handshake_RequestPOW extends $pb.GeneratedMessage {
factory Handshake_RequestPOW() => create();
Handshake_RequestPOW._() : super();
factory Handshake_RequestPOW.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory Handshake_RequestPOW.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake.RequestPOW', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: 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')
Handshake_RequestPOW clone() => Handshake_RequestPOW()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
Handshake_RequestPOW copyWith(void Function(Handshake_RequestPOW) updates) => super.copyWith((message) => updates(message as Handshake_RequestPOW)) as Handshake_RequestPOW;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Handshake_RequestPOW create() => Handshake_RequestPOW._();
Handshake_RequestPOW createEmptyInstance() => create();
static $pb.PbList<Handshake_RequestPOW> createRepeated() => $pb.PbList<Handshake_RequestPOW>();
@$core.pragma('dart2js:noInline')
static Handshake_RequestPOW getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Handshake_RequestPOW>(create);
static Handshake_RequestPOW? _defaultInstance;
}
class Handshake_Register extends $pb.GeneratedMessage {
factory Handshake_Register({
$core.String? username,
@ -206,6 +238,8 @@ class Handshake_Register extends $pb.GeneratedMessage {
$fixnum.Int64? signedPrekeyId,
$fixnum.Int64? registrationId,
$core.bool? isIos,
$core.String? langCode,
$fixnum.Int64? proofOfWork,
}) {
final $result = create();
if (username != null) {
@ -232,6 +266,12 @@ class Handshake_Register extends $pb.GeneratedMessage {
if (isIos != null) {
$result.isIos = isIos;
}
if (langCode != null) {
$result.langCode = langCode;
}
if (proofOfWork != null) {
$result.proofOfWork = proofOfWork;
}
return $result;
}
Handshake_Register._() : super();
@ -247,6 +287,8 @@ class Handshake_Register extends $pb.GeneratedMessage {
..aInt64(6, _omitFieldNames ? '' : 'signedPrekeyId')
..aInt64(7, _omitFieldNames ? '' : 'registrationId')
..aOB(8, _omitFieldNames ? '' : 'isIos')
..aOS(9, _omitFieldNames ? '' : 'langCode')
..aInt64(10, _omitFieldNames ? '' : 'proofOfWork')
..hasRequiredFields = false
;
@ -342,6 +384,24 @@ class Handshake_Register extends $pb.GeneratedMessage {
$core.bool hasIsIos() => $_has(7);
@$pb.TagNumber(8)
void clearIsIos() => clearField(8);
@$pb.TagNumber(9)
$core.String get langCode => $_getSZ(8);
@$pb.TagNumber(9)
set langCode($core.String v) { $_setString(8, v); }
@$pb.TagNumber(9)
$core.bool hasLangCode() => $_has(8);
@$pb.TagNumber(9)
void clearLangCode() => clearField(9);
@$pb.TagNumber(10)
$fixnum.Int64 get proofOfWork => $_getI64(9);
@$pb.TagNumber(10)
set proofOfWork($fixnum.Int64 v) { $_setInt64(9, v); }
@$pb.TagNumber(10)
$core.bool hasProofOfWork() => $_has(9);
@$pb.TagNumber(10)
void clearProofOfWork() => clearField(10);
}
class Handshake_GetAuthChallenge extends $pb.GeneratedMessage {
@ -534,32 +594,37 @@ class Handshake_Authenticate extends $pb.GeneratedMessage {
enum Handshake_Handshake {
register,
getauthchallenge,
getauthtoken,
getAuthChallenge,
getAuthToken,
authenticate,
requestPOW,
notSet
}
class Handshake extends $pb.GeneratedMessage {
factory Handshake({
Handshake_Register? register,
Handshake_GetAuthChallenge? getauthchallenge,
Handshake_GetAuthToken? getauthtoken,
Handshake_GetAuthChallenge? getAuthChallenge,
Handshake_GetAuthToken? getAuthToken,
Handshake_Authenticate? authenticate,
Handshake_RequestPOW? requestPOW,
}) {
final $result = create();
if (register != null) {
$result.register = register;
}
if (getauthchallenge != null) {
$result.getauthchallenge = getauthchallenge;
if (getAuthChallenge != null) {
$result.getAuthChallenge = getAuthChallenge;
}
if (getauthtoken != null) {
$result.getauthtoken = getauthtoken;
if (getAuthToken != null) {
$result.getAuthToken = getAuthToken;
}
if (authenticate != null) {
$result.authenticate = authenticate;
}
if (requestPOW != null) {
$result.requestPOW = requestPOW;
}
return $result;
}
Handshake._() : super();
@ -568,17 +633,19 @@ class Handshake extends $pb.GeneratedMessage {
static const $core.Map<$core.int, Handshake_Handshake> _Handshake_HandshakeByTag = {
1 : Handshake_Handshake.register,
2 : Handshake_Handshake.getauthchallenge,
3 : Handshake_Handshake.getauthtoken,
2 : Handshake_Handshake.getAuthChallenge,
3 : Handshake_Handshake.getAuthToken,
4 : Handshake_Handshake.authenticate,
5 : Handshake_Handshake.requestPOW,
0 : Handshake_Handshake.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Handshake', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
..oo(0, [1, 2, 3, 4])
..oo(0, [1, 2, 3, 4, 5])
..aOM<Handshake_Register>(1, _omitFieldNames ? '' : 'register', subBuilder: Handshake_Register.create)
..aOM<Handshake_GetAuthChallenge>(2, _omitFieldNames ? '' : 'getauthchallenge', subBuilder: Handshake_GetAuthChallenge.create)
..aOM<Handshake_GetAuthToken>(3, _omitFieldNames ? '' : 'getauthtoken', subBuilder: Handshake_GetAuthToken.create)
..aOM<Handshake_GetAuthChallenge>(2, _omitFieldNames ? '' : 'getAuthChallenge', protoName: 'getAuthChallenge', subBuilder: Handshake_GetAuthChallenge.create)
..aOM<Handshake_GetAuthToken>(3, _omitFieldNames ? '' : 'getAuthToken', protoName: 'getAuthToken', subBuilder: Handshake_GetAuthToken.create)
..aOM<Handshake_Authenticate>(4, _omitFieldNames ? '' : 'authenticate', subBuilder: Handshake_Authenticate.create)
..aOM<Handshake_RequestPOW>(5, _omitFieldNames ? '' : 'requestPOW', protoName: 'requestPOW', subBuilder: Handshake_RequestPOW.create)
..hasRequiredFields = false
;
@ -618,26 +685,26 @@ class Handshake extends $pb.GeneratedMessage {
Handshake_Register ensureRegister() => $_ensure(0);
@$pb.TagNumber(2)
Handshake_GetAuthChallenge get getauthchallenge => $_getN(1);
Handshake_GetAuthChallenge get getAuthChallenge => $_getN(1);
@$pb.TagNumber(2)
set getauthchallenge(Handshake_GetAuthChallenge v) { setField(2, v); }
set getAuthChallenge(Handshake_GetAuthChallenge v) { setField(2, v); }
@$pb.TagNumber(2)
$core.bool hasGetauthchallenge() => $_has(1);
$core.bool hasGetAuthChallenge() => $_has(1);
@$pb.TagNumber(2)
void clearGetauthchallenge() => clearField(2);
void clearGetAuthChallenge() => clearField(2);
@$pb.TagNumber(2)
Handshake_GetAuthChallenge ensureGetauthchallenge() => $_ensure(1);
Handshake_GetAuthChallenge ensureGetAuthChallenge() => $_ensure(1);
@$pb.TagNumber(3)
Handshake_GetAuthToken get getauthtoken => $_getN(2);
Handshake_GetAuthToken get getAuthToken => $_getN(2);
@$pb.TagNumber(3)
set getauthtoken(Handshake_GetAuthToken v) { setField(3, v); }
set getAuthToken(Handshake_GetAuthToken v) { setField(3, v); }
@$pb.TagNumber(3)
$core.bool hasGetauthtoken() => $_has(2);
$core.bool hasGetAuthToken() => $_has(2);
@$pb.TagNumber(3)
void clearGetauthtoken() => clearField(3);
void clearGetAuthToken() => clearField(3);
@$pb.TagNumber(3)
Handshake_GetAuthToken ensureGetauthtoken() => $_ensure(2);
Handshake_GetAuthToken ensureGetAuthToken() => $_ensure(2);
@$pb.TagNumber(4)
Handshake_Authenticate get authenticate => $_getN(3);
@ -649,6 +716,17 @@ class Handshake extends $pb.GeneratedMessage {
void clearAuthenticate() => clearField(4);
@$pb.TagNumber(4)
Handshake_Authenticate ensureAuthenticate() => $_ensure(3);
@$pb.TagNumber(5)
Handshake_RequestPOW get requestPOW => $_getN(4);
@$pb.TagNumber(5)
set requestPOW(Handshake_RequestPOW v) { setField(5, v); }
@$pb.TagNumber(5)
$core.bool hasRequestPOW() => $_has(4);
@$pb.TagNumber(5)
void clearRequestPOW() => clearField(5);
@$pb.TagNumber(5)
Handshake_RequestPOW ensureRequestPOW() => $_ensure(4);
}
class ApplicationData_TextMessage extends $pb.GeneratedMessage {
@ -779,6 +857,56 @@ class ApplicationData_GetUserByUsername extends $pb.GeneratedMessage {
void clearUsername() => clearField(1);
}
class ApplicationData_ChangeUsername extends $pb.GeneratedMessage {
factory ApplicationData_ChangeUsername({
$core.String? username,
}) {
final $result = create();
if (username != null) {
$result.username = username;
}
return $result;
}
ApplicationData_ChangeUsername._() : super();
factory ApplicationData_ChangeUsername.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory ApplicationData_ChangeUsername.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.ChangeUsername', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'username')
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ApplicationData_ChangeUsername clone() => ApplicationData_ChangeUsername()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ApplicationData_ChangeUsername copyWith(void Function(ApplicationData_ChangeUsername) updates) => super.copyWith((message) => updates(message as ApplicationData_ChangeUsername)) as ApplicationData_ChangeUsername;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ApplicationData_ChangeUsername create() => ApplicationData_ChangeUsername._();
ApplicationData_ChangeUsername createEmptyInstance() => create();
static $pb.PbList<ApplicationData_ChangeUsername> createRepeated() => $pb.PbList<ApplicationData_ChangeUsername>();
@$core.pragma('dart2js:noInline')
static ApplicationData_ChangeUsername getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ApplicationData_ChangeUsername>(create);
static ApplicationData_ChangeUsername? _defaultInstance;
@$pb.TagNumber(1)
$core.String get username => $_getSZ(0);
@$pb.TagNumber(1)
set username($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasUsername() => $_has(0);
@$pb.TagNumber(1)
void clearUsername() => clearField(1);
}
class ApplicationData_UpdateGoogleFcmToken extends $pb.GeneratedMessage {
factory ApplicationData_UpdateGoogleFcmToken({
$core.String? googleFcm,
@ -1692,117 +1820,122 @@ class ApplicationData_DeleteAccount extends $pb.GeneratedMessage {
}
enum ApplicationData_ApplicationData {
textmessage,
getuserbyusername,
getprekeysbyuserid,
getuserbyid,
updategooglefcmtoken,
getlocation,
getcurrentplaninfos,
redeemvoucher,
getavailableplans,
createvoucher,
getvouchers,
switchtopayedplan,
getaddaccountsinvites,
redeemadditionalcode,
removeadditionaluser,
updateplanoptions,
downloaddone,
getsignedprekeybyuserid,
updatesignedprekey,
deleteaccount,
reportuser,
textMessage,
getUserByUsername,
getPrekeysByUserId,
getUserById,
updateGoogleFcmToken,
getLocation,
getCurrentPlanInfos,
redeemVoucher,
getAvailablePlans,
createVoucher,
getVouchers,
switchtoPayedPlan,
getAddaccountsInvites,
redeemAdditionalCode,
removeAdditionalUser,
updatePlanOptions,
downloadDone,
getSignedPrekeyByUserid,
updateSignedPrekey,
deleteAccount,
reportUser,
changeUsername,
notSet
}
class ApplicationData extends $pb.GeneratedMessage {
factory ApplicationData({
ApplicationData_TextMessage? textmessage,
ApplicationData_GetUserByUsername? getuserbyusername,
ApplicationData_GetPrekeysByUserId? getprekeysbyuserid,
ApplicationData_GetUserById? getuserbyid,
ApplicationData_UpdateGoogleFcmToken? updategooglefcmtoken,
ApplicationData_GetLocation? getlocation,
ApplicationData_GetCurrentPlanInfos? getcurrentplaninfos,
ApplicationData_RedeemVoucher? redeemvoucher,
ApplicationData_GetAvailablePlans? getavailableplans,
ApplicationData_CreateVoucher? createvoucher,
ApplicationData_GetVouchers? getvouchers,
ApplicationData_SwitchToPayedPlan? switchtopayedplan,
ApplicationData_GetAddAccountsInvites? getaddaccountsinvites,
ApplicationData_RedeemAdditionalCode? redeemadditionalcode,
ApplicationData_RemoveAdditionalUser? removeadditionaluser,
ApplicationData_UpdatePlanOptions? updateplanoptions,
ApplicationData_DownloadDone? downloaddone,
ApplicationData_GetSignedPreKeyByUserId? getsignedprekeybyuserid,
ApplicationData_UpdateSignedPreKey? updatesignedprekey,
ApplicationData_DeleteAccount? deleteaccount,
ApplicationData_ReportUser? reportuser,
ApplicationData_TextMessage? textMessage,
ApplicationData_GetUserByUsername? getUserByUsername,
ApplicationData_GetPrekeysByUserId? getPrekeysByUserId,
ApplicationData_GetUserById? getUserById,
ApplicationData_UpdateGoogleFcmToken? updateGoogleFcmToken,
ApplicationData_GetLocation? getLocation,
ApplicationData_GetCurrentPlanInfos? getCurrentPlanInfos,
ApplicationData_RedeemVoucher? redeemVoucher,
ApplicationData_GetAvailablePlans? getAvailablePlans,
ApplicationData_CreateVoucher? createVoucher,
ApplicationData_GetVouchers? getVouchers,
ApplicationData_SwitchToPayedPlan? switchtoPayedPlan,
ApplicationData_GetAddAccountsInvites? getAddaccountsInvites,
ApplicationData_RedeemAdditionalCode? redeemAdditionalCode,
ApplicationData_RemoveAdditionalUser? removeAdditionalUser,
ApplicationData_UpdatePlanOptions? updatePlanOptions,
ApplicationData_DownloadDone? downloadDone,
ApplicationData_GetSignedPreKeyByUserId? getSignedPrekeyByUserid,
ApplicationData_UpdateSignedPreKey? updateSignedPrekey,
ApplicationData_DeleteAccount? deleteAccount,
ApplicationData_ReportUser? reportUser,
ApplicationData_ChangeUsername? changeUsername,
}) {
final $result = create();
if (textmessage != null) {
$result.textmessage = textmessage;
if (textMessage != null) {
$result.textMessage = textMessage;
}
if (getuserbyusername != null) {
$result.getuserbyusername = getuserbyusername;
if (getUserByUsername != null) {
$result.getUserByUsername = getUserByUsername;
}
if (getprekeysbyuserid != null) {
$result.getprekeysbyuserid = getprekeysbyuserid;
if (getPrekeysByUserId != null) {
$result.getPrekeysByUserId = getPrekeysByUserId;
}
if (getuserbyid != null) {
$result.getuserbyid = getuserbyid;
if (getUserById != null) {
$result.getUserById = getUserById;
}
if (updategooglefcmtoken != null) {
$result.updategooglefcmtoken = updategooglefcmtoken;
if (updateGoogleFcmToken != null) {
$result.updateGoogleFcmToken = updateGoogleFcmToken;
}
if (getlocation != null) {
$result.getlocation = getlocation;
if (getLocation != null) {
$result.getLocation = getLocation;
}
if (getcurrentplaninfos != null) {
$result.getcurrentplaninfos = getcurrentplaninfos;
if (getCurrentPlanInfos != null) {
$result.getCurrentPlanInfos = getCurrentPlanInfos;
}
if (redeemvoucher != null) {
$result.redeemvoucher = redeemvoucher;
if (redeemVoucher != null) {
$result.redeemVoucher = redeemVoucher;
}
if (getavailableplans != null) {
$result.getavailableplans = getavailableplans;
if (getAvailablePlans != null) {
$result.getAvailablePlans = getAvailablePlans;
}
if (createvoucher != null) {
$result.createvoucher = createvoucher;
if (createVoucher != null) {
$result.createVoucher = createVoucher;
}
if (getvouchers != null) {
$result.getvouchers = getvouchers;
if (getVouchers != null) {
$result.getVouchers = getVouchers;
}
if (switchtopayedplan != null) {
$result.switchtopayedplan = switchtopayedplan;
if (switchtoPayedPlan != null) {
$result.switchtoPayedPlan = switchtoPayedPlan;
}
if (getaddaccountsinvites != null) {
$result.getaddaccountsinvites = getaddaccountsinvites;
if (getAddaccountsInvites != null) {
$result.getAddaccountsInvites = getAddaccountsInvites;
}
if (redeemadditionalcode != null) {
$result.redeemadditionalcode = redeemadditionalcode;
if (redeemAdditionalCode != null) {
$result.redeemAdditionalCode = redeemAdditionalCode;
}
if (removeadditionaluser != null) {
$result.removeadditionaluser = removeadditionaluser;
if (removeAdditionalUser != null) {
$result.removeAdditionalUser = removeAdditionalUser;
}
if (updateplanoptions != null) {
$result.updateplanoptions = updateplanoptions;
if (updatePlanOptions != null) {
$result.updatePlanOptions = updatePlanOptions;
}
if (downloaddone != null) {
$result.downloaddone = downloaddone;
if (downloadDone != null) {
$result.downloadDone = downloadDone;
}
if (getsignedprekeybyuserid != null) {
$result.getsignedprekeybyuserid = getsignedprekeybyuserid;
if (getSignedPrekeyByUserid != null) {
$result.getSignedPrekeyByUserid = getSignedPrekeyByUserid;
}
if (updatesignedprekey != null) {
$result.updatesignedprekey = updatesignedprekey;
if (updateSignedPrekey != null) {
$result.updateSignedPrekey = updateSignedPrekey;
}
if (deleteaccount != null) {
$result.deleteaccount = deleteaccount;
if (deleteAccount != null) {
$result.deleteAccount = deleteAccount;
}
if (reportuser != null) {
$result.reportuser = reportuser;
if (reportUser != null) {
$result.reportUser = reportUser;
}
if (changeUsername != null) {
$result.changeUsername = changeUsername;
}
return $result;
}
@ -1811,52 +1944,54 @@ class ApplicationData extends $pb.GeneratedMessage {
factory ApplicationData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static const $core.Map<$core.int, ApplicationData_ApplicationData> _ApplicationData_ApplicationDataByTag = {
1 : ApplicationData_ApplicationData.textmessage,
2 : ApplicationData_ApplicationData.getuserbyusername,
3 : ApplicationData_ApplicationData.getprekeysbyuserid,
6 : ApplicationData_ApplicationData.getuserbyid,
8 : ApplicationData_ApplicationData.updategooglefcmtoken,
9 : ApplicationData_ApplicationData.getlocation,
10 : ApplicationData_ApplicationData.getcurrentplaninfos,
11 : ApplicationData_ApplicationData.redeemvoucher,
12 : ApplicationData_ApplicationData.getavailableplans,
13 : ApplicationData_ApplicationData.createvoucher,
14 : ApplicationData_ApplicationData.getvouchers,
15 : ApplicationData_ApplicationData.switchtopayedplan,
16 : ApplicationData_ApplicationData.getaddaccountsinvites,
17 : ApplicationData_ApplicationData.redeemadditionalcode,
18 : ApplicationData_ApplicationData.removeadditionaluser,
19 : ApplicationData_ApplicationData.updateplanoptions,
20 : ApplicationData_ApplicationData.downloaddone,
22 : ApplicationData_ApplicationData.getsignedprekeybyuserid,
23 : ApplicationData_ApplicationData.updatesignedprekey,
24 : ApplicationData_ApplicationData.deleteaccount,
25 : ApplicationData_ApplicationData.reportuser,
1 : ApplicationData_ApplicationData.textMessage,
2 : ApplicationData_ApplicationData.getUserByUsername,
3 : ApplicationData_ApplicationData.getPrekeysByUserId,
6 : ApplicationData_ApplicationData.getUserById,
8 : ApplicationData_ApplicationData.updateGoogleFcmToken,
9 : ApplicationData_ApplicationData.getLocation,
10 : ApplicationData_ApplicationData.getCurrentPlanInfos,
11 : ApplicationData_ApplicationData.redeemVoucher,
12 : ApplicationData_ApplicationData.getAvailablePlans,
13 : ApplicationData_ApplicationData.createVoucher,
14 : ApplicationData_ApplicationData.getVouchers,
15 : ApplicationData_ApplicationData.switchtoPayedPlan,
16 : ApplicationData_ApplicationData.getAddaccountsInvites,
17 : ApplicationData_ApplicationData.redeemAdditionalCode,
18 : ApplicationData_ApplicationData.removeAdditionalUser,
19 : ApplicationData_ApplicationData.updatePlanOptions,
20 : ApplicationData_ApplicationData.downloadDone,
22 : ApplicationData_ApplicationData.getSignedPrekeyByUserid,
23 : ApplicationData_ApplicationData.updateSignedPrekey,
24 : ApplicationData_ApplicationData.deleteAccount,
25 : ApplicationData_ApplicationData.reportUser,
26 : ApplicationData_ApplicationData.changeUsername,
0 : ApplicationData_ApplicationData.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
..oo(0, [1, 2, 3, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25])
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textmessage', subBuilder: ApplicationData_TextMessage.create)
..aOM<ApplicationData_GetUserByUsername>(2, _omitFieldNames ? '' : 'getuserbyusername', subBuilder: ApplicationData_GetUserByUsername.create)
..aOM<ApplicationData_GetPrekeysByUserId>(3, _omitFieldNames ? '' : 'getprekeysbyuserid', subBuilder: ApplicationData_GetPrekeysByUserId.create)
..aOM<ApplicationData_GetUserById>(6, _omitFieldNames ? '' : 'getuserbyid', subBuilder: ApplicationData_GetUserById.create)
..aOM<ApplicationData_UpdateGoogleFcmToken>(8, _omitFieldNames ? '' : 'updategooglefcmtoken', subBuilder: ApplicationData_UpdateGoogleFcmToken.create)
..aOM<ApplicationData_GetLocation>(9, _omitFieldNames ? '' : 'getlocation', subBuilder: ApplicationData_GetLocation.create)
..aOM<ApplicationData_GetCurrentPlanInfos>(10, _omitFieldNames ? '' : 'getcurrentplaninfos', subBuilder: ApplicationData_GetCurrentPlanInfos.create)
..aOM<ApplicationData_RedeemVoucher>(11, _omitFieldNames ? '' : 'redeemvoucher', subBuilder: ApplicationData_RedeemVoucher.create)
..aOM<ApplicationData_GetAvailablePlans>(12, _omitFieldNames ? '' : 'getavailableplans', subBuilder: ApplicationData_GetAvailablePlans.create)
..aOM<ApplicationData_CreateVoucher>(13, _omitFieldNames ? '' : 'createvoucher', subBuilder: ApplicationData_CreateVoucher.create)
..aOM<ApplicationData_GetVouchers>(14, _omitFieldNames ? '' : 'getvouchers', subBuilder: ApplicationData_GetVouchers.create)
..aOM<ApplicationData_SwitchToPayedPlan>(15, _omitFieldNames ? '' : 'Switchtopayedplan', protoName: 'Switchtopayedplan', subBuilder: ApplicationData_SwitchToPayedPlan.create)
..aOM<ApplicationData_GetAddAccountsInvites>(16, _omitFieldNames ? '' : 'getaddaccountsinvites', subBuilder: ApplicationData_GetAddAccountsInvites.create)
..aOM<ApplicationData_RedeemAdditionalCode>(17, _omitFieldNames ? '' : 'redeemadditionalcode', subBuilder: ApplicationData_RedeemAdditionalCode.create)
..aOM<ApplicationData_RemoveAdditionalUser>(18, _omitFieldNames ? '' : 'removeadditionaluser', subBuilder: ApplicationData_RemoveAdditionalUser.create)
..aOM<ApplicationData_UpdatePlanOptions>(19, _omitFieldNames ? '' : 'updateplanoptions', subBuilder: ApplicationData_UpdatePlanOptions.create)
..aOM<ApplicationData_DownloadDone>(20, _omitFieldNames ? '' : 'downloaddone', subBuilder: ApplicationData_DownloadDone.create)
..aOM<ApplicationData_GetSignedPreKeyByUserId>(22, _omitFieldNames ? '' : 'getsignedprekeybyuserid', subBuilder: ApplicationData_GetSignedPreKeyByUserId.create)
..aOM<ApplicationData_UpdateSignedPreKey>(23, _omitFieldNames ? '' : 'updatesignedprekey', subBuilder: ApplicationData_UpdateSignedPreKey.create)
..aOM<ApplicationData_DeleteAccount>(24, _omitFieldNames ? '' : 'deleteaccount', subBuilder: ApplicationData_DeleteAccount.create)
..aOM<ApplicationData_ReportUser>(25, _omitFieldNames ? '' : 'reportuser', subBuilder: ApplicationData_ReportUser.create)
..oo(0, [1, 2, 3, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26])
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textMessage', protoName: 'textMessage', subBuilder: ApplicationData_TextMessage.create)
..aOM<ApplicationData_GetUserByUsername>(2, _omitFieldNames ? '' : 'getUserByUsername', protoName: 'getUserByUsername', subBuilder: ApplicationData_GetUserByUsername.create)
..aOM<ApplicationData_GetPrekeysByUserId>(3, _omitFieldNames ? '' : 'getPrekeysByUserId', protoName: 'getPrekeysByUserId', subBuilder: ApplicationData_GetPrekeysByUserId.create)
..aOM<ApplicationData_GetUserById>(6, _omitFieldNames ? '' : 'getUserById', protoName: 'getUserById', subBuilder: ApplicationData_GetUserById.create)
..aOM<ApplicationData_UpdateGoogleFcmToken>(8, _omitFieldNames ? '' : 'updateGoogleFcmToken', protoName: 'updateGoogleFcmToken', subBuilder: ApplicationData_UpdateGoogleFcmToken.create)
..aOM<ApplicationData_GetLocation>(9, _omitFieldNames ? '' : 'getLocation', protoName: 'getLocation', subBuilder: ApplicationData_GetLocation.create)
..aOM<ApplicationData_GetCurrentPlanInfos>(10, _omitFieldNames ? '' : 'getCurrentPlanInfos', protoName: 'getCurrentPlanInfos', subBuilder: ApplicationData_GetCurrentPlanInfos.create)
..aOM<ApplicationData_RedeemVoucher>(11, _omitFieldNames ? '' : 'redeemVoucher', protoName: 'redeemVoucher', subBuilder: ApplicationData_RedeemVoucher.create)
..aOM<ApplicationData_GetAvailablePlans>(12, _omitFieldNames ? '' : 'getAvailablePlans', protoName: 'getAvailablePlans', subBuilder: ApplicationData_GetAvailablePlans.create)
..aOM<ApplicationData_CreateVoucher>(13, _omitFieldNames ? '' : 'createVoucher', protoName: 'createVoucher', subBuilder: ApplicationData_CreateVoucher.create)
..aOM<ApplicationData_GetVouchers>(14, _omitFieldNames ? '' : 'getVouchers', protoName: 'getVouchers', subBuilder: ApplicationData_GetVouchers.create)
..aOM<ApplicationData_SwitchToPayedPlan>(15, _omitFieldNames ? '' : 'switchtoPayedPlan', protoName: 'switchtoPayedPlan', subBuilder: ApplicationData_SwitchToPayedPlan.create)
..aOM<ApplicationData_GetAddAccountsInvites>(16, _omitFieldNames ? '' : 'getAddaccountsInvites', protoName: 'getAddaccountsInvites', subBuilder: ApplicationData_GetAddAccountsInvites.create)
..aOM<ApplicationData_RedeemAdditionalCode>(17, _omitFieldNames ? '' : 'redeemAdditionalCode', protoName: 'redeemAdditionalCode', subBuilder: ApplicationData_RedeemAdditionalCode.create)
..aOM<ApplicationData_RemoveAdditionalUser>(18, _omitFieldNames ? '' : 'removeAdditionalUser', protoName: 'removeAdditionalUser', subBuilder: ApplicationData_RemoveAdditionalUser.create)
..aOM<ApplicationData_UpdatePlanOptions>(19, _omitFieldNames ? '' : 'updatePlanOptions', protoName: 'updatePlanOptions', subBuilder: ApplicationData_UpdatePlanOptions.create)
..aOM<ApplicationData_DownloadDone>(20, _omitFieldNames ? '' : 'downloadDone', protoName: 'downloadDone', subBuilder: ApplicationData_DownloadDone.create)
..aOM<ApplicationData_GetSignedPreKeyByUserId>(22, _omitFieldNames ? '' : 'getSignedPrekeyByUserid', protoName: 'getSignedPrekeyByUserid', subBuilder: ApplicationData_GetSignedPreKeyByUserId.create)
..aOM<ApplicationData_UpdateSignedPreKey>(23, _omitFieldNames ? '' : 'updateSignedPrekey', protoName: 'updateSignedPrekey', subBuilder: ApplicationData_UpdateSignedPreKey.create)
..aOM<ApplicationData_DeleteAccount>(24, _omitFieldNames ? '' : 'deleteAccount', protoName: 'deleteAccount', subBuilder: ApplicationData_DeleteAccount.create)
..aOM<ApplicationData_ReportUser>(25, _omitFieldNames ? '' : 'reportUser', protoName: 'reportUser', subBuilder: ApplicationData_ReportUser.create)
..aOM<ApplicationData_ChangeUsername>(26, _omitFieldNames ? '' : 'changeUsername', protoName: 'changeUsername', subBuilder: ApplicationData_ChangeUsername.create)
..hasRequiredFields = false
;
@ -1885,235 +2020,246 @@ class ApplicationData extends $pb.GeneratedMessage {
void clearApplicationData() => clearField($_whichOneof(0));
@$pb.TagNumber(1)
ApplicationData_TextMessage get textmessage => $_getN(0);
ApplicationData_TextMessage get textMessage => $_getN(0);
@$pb.TagNumber(1)
set textmessage(ApplicationData_TextMessage v) { setField(1, v); }
set textMessage(ApplicationData_TextMessage v) { setField(1, v); }
@$pb.TagNumber(1)
$core.bool hasTextmessage() => $_has(0);
$core.bool hasTextMessage() => $_has(0);
@$pb.TagNumber(1)
void clearTextmessage() => clearField(1);
void clearTextMessage() => clearField(1);
@$pb.TagNumber(1)
ApplicationData_TextMessage ensureTextmessage() => $_ensure(0);
ApplicationData_TextMessage ensureTextMessage() => $_ensure(0);
@$pb.TagNumber(2)
ApplicationData_GetUserByUsername get getuserbyusername => $_getN(1);
ApplicationData_GetUserByUsername get getUserByUsername => $_getN(1);
@$pb.TagNumber(2)
set getuserbyusername(ApplicationData_GetUserByUsername v) { setField(2, v); }
set getUserByUsername(ApplicationData_GetUserByUsername v) { setField(2, v); }
@$pb.TagNumber(2)
$core.bool hasGetuserbyusername() => $_has(1);
$core.bool hasGetUserByUsername() => $_has(1);
@$pb.TagNumber(2)
void clearGetuserbyusername() => clearField(2);
void clearGetUserByUsername() => clearField(2);
@$pb.TagNumber(2)
ApplicationData_GetUserByUsername ensureGetuserbyusername() => $_ensure(1);
ApplicationData_GetUserByUsername ensureGetUserByUsername() => $_ensure(1);
@$pb.TagNumber(3)
ApplicationData_GetPrekeysByUserId get getprekeysbyuserid => $_getN(2);
ApplicationData_GetPrekeysByUserId get getPrekeysByUserId => $_getN(2);
@$pb.TagNumber(3)
set getprekeysbyuserid(ApplicationData_GetPrekeysByUserId v) { setField(3, v); }
set getPrekeysByUserId(ApplicationData_GetPrekeysByUserId v) { setField(3, v); }
@$pb.TagNumber(3)
$core.bool hasGetprekeysbyuserid() => $_has(2);
$core.bool hasGetPrekeysByUserId() => $_has(2);
@$pb.TagNumber(3)
void clearGetprekeysbyuserid() => clearField(3);
void clearGetPrekeysByUserId() => clearField(3);
@$pb.TagNumber(3)
ApplicationData_GetPrekeysByUserId ensureGetprekeysbyuserid() => $_ensure(2);
ApplicationData_GetPrekeysByUserId ensureGetPrekeysByUserId() => $_ensure(2);
@$pb.TagNumber(6)
ApplicationData_GetUserById get getuserbyid => $_getN(3);
ApplicationData_GetUserById get getUserById => $_getN(3);
@$pb.TagNumber(6)
set getuserbyid(ApplicationData_GetUserById v) { setField(6, v); }
set getUserById(ApplicationData_GetUserById v) { setField(6, v); }
@$pb.TagNumber(6)
$core.bool hasGetuserbyid() => $_has(3);
$core.bool hasGetUserById() => $_has(3);
@$pb.TagNumber(6)
void clearGetuserbyid() => clearField(6);
void clearGetUserById() => clearField(6);
@$pb.TagNumber(6)
ApplicationData_GetUserById ensureGetuserbyid() => $_ensure(3);
ApplicationData_GetUserById ensureGetUserById() => $_ensure(3);
@$pb.TagNumber(8)
ApplicationData_UpdateGoogleFcmToken get updategooglefcmtoken => $_getN(4);
ApplicationData_UpdateGoogleFcmToken get updateGoogleFcmToken => $_getN(4);
@$pb.TagNumber(8)
set updategooglefcmtoken(ApplicationData_UpdateGoogleFcmToken v) { setField(8, v); }
set updateGoogleFcmToken(ApplicationData_UpdateGoogleFcmToken v) { setField(8, v); }
@$pb.TagNumber(8)
$core.bool hasUpdategooglefcmtoken() => $_has(4);
$core.bool hasUpdateGoogleFcmToken() => $_has(4);
@$pb.TagNumber(8)
void clearUpdategooglefcmtoken() => clearField(8);
void clearUpdateGoogleFcmToken() => clearField(8);
@$pb.TagNumber(8)
ApplicationData_UpdateGoogleFcmToken ensureUpdategooglefcmtoken() => $_ensure(4);
ApplicationData_UpdateGoogleFcmToken ensureUpdateGoogleFcmToken() => $_ensure(4);
@$pb.TagNumber(9)
ApplicationData_GetLocation get getlocation => $_getN(5);
ApplicationData_GetLocation get getLocation => $_getN(5);
@$pb.TagNumber(9)
set getlocation(ApplicationData_GetLocation v) { setField(9, v); }
set getLocation(ApplicationData_GetLocation v) { setField(9, v); }
@$pb.TagNumber(9)
$core.bool hasGetlocation() => $_has(5);
$core.bool hasGetLocation() => $_has(5);
@$pb.TagNumber(9)
void clearGetlocation() => clearField(9);
void clearGetLocation() => clearField(9);
@$pb.TagNumber(9)
ApplicationData_GetLocation ensureGetlocation() => $_ensure(5);
ApplicationData_GetLocation ensureGetLocation() => $_ensure(5);
@$pb.TagNumber(10)
ApplicationData_GetCurrentPlanInfos get getcurrentplaninfos => $_getN(6);
ApplicationData_GetCurrentPlanInfos get getCurrentPlanInfos => $_getN(6);
@$pb.TagNumber(10)
set getcurrentplaninfos(ApplicationData_GetCurrentPlanInfos v) { setField(10, v); }
set getCurrentPlanInfos(ApplicationData_GetCurrentPlanInfos v) { setField(10, v); }
@$pb.TagNumber(10)
$core.bool hasGetcurrentplaninfos() => $_has(6);
$core.bool hasGetCurrentPlanInfos() => $_has(6);
@$pb.TagNumber(10)
void clearGetcurrentplaninfos() => clearField(10);
void clearGetCurrentPlanInfos() => clearField(10);
@$pb.TagNumber(10)
ApplicationData_GetCurrentPlanInfos ensureGetcurrentplaninfos() => $_ensure(6);
ApplicationData_GetCurrentPlanInfos ensureGetCurrentPlanInfos() => $_ensure(6);
@$pb.TagNumber(11)
ApplicationData_RedeemVoucher get redeemvoucher => $_getN(7);
ApplicationData_RedeemVoucher get redeemVoucher => $_getN(7);
@$pb.TagNumber(11)
set redeemvoucher(ApplicationData_RedeemVoucher v) { setField(11, v); }
set redeemVoucher(ApplicationData_RedeemVoucher v) { setField(11, v); }
@$pb.TagNumber(11)
$core.bool hasRedeemvoucher() => $_has(7);
$core.bool hasRedeemVoucher() => $_has(7);
@$pb.TagNumber(11)
void clearRedeemvoucher() => clearField(11);
void clearRedeemVoucher() => clearField(11);
@$pb.TagNumber(11)
ApplicationData_RedeemVoucher ensureRedeemvoucher() => $_ensure(7);
ApplicationData_RedeemVoucher ensureRedeemVoucher() => $_ensure(7);
@$pb.TagNumber(12)
ApplicationData_GetAvailablePlans get getavailableplans => $_getN(8);
ApplicationData_GetAvailablePlans get getAvailablePlans => $_getN(8);
@$pb.TagNumber(12)
set getavailableplans(ApplicationData_GetAvailablePlans v) { setField(12, v); }
set getAvailablePlans(ApplicationData_GetAvailablePlans v) { setField(12, v); }
@$pb.TagNumber(12)
$core.bool hasGetavailableplans() => $_has(8);
$core.bool hasGetAvailablePlans() => $_has(8);
@$pb.TagNumber(12)
void clearGetavailableplans() => clearField(12);
void clearGetAvailablePlans() => clearField(12);
@$pb.TagNumber(12)
ApplicationData_GetAvailablePlans ensureGetavailableplans() => $_ensure(8);
ApplicationData_GetAvailablePlans ensureGetAvailablePlans() => $_ensure(8);
@$pb.TagNumber(13)
ApplicationData_CreateVoucher get createvoucher => $_getN(9);
ApplicationData_CreateVoucher get createVoucher => $_getN(9);
@$pb.TagNumber(13)
set createvoucher(ApplicationData_CreateVoucher v) { setField(13, v); }
set createVoucher(ApplicationData_CreateVoucher v) { setField(13, v); }
@$pb.TagNumber(13)
$core.bool hasCreatevoucher() => $_has(9);
$core.bool hasCreateVoucher() => $_has(9);
@$pb.TagNumber(13)
void clearCreatevoucher() => clearField(13);
void clearCreateVoucher() => clearField(13);
@$pb.TagNumber(13)
ApplicationData_CreateVoucher ensureCreatevoucher() => $_ensure(9);
ApplicationData_CreateVoucher ensureCreateVoucher() => $_ensure(9);
@$pb.TagNumber(14)
ApplicationData_GetVouchers get getvouchers => $_getN(10);
ApplicationData_GetVouchers get getVouchers => $_getN(10);
@$pb.TagNumber(14)
set getvouchers(ApplicationData_GetVouchers v) { setField(14, v); }
set getVouchers(ApplicationData_GetVouchers v) { setField(14, v); }
@$pb.TagNumber(14)
$core.bool hasGetvouchers() => $_has(10);
$core.bool hasGetVouchers() => $_has(10);
@$pb.TagNumber(14)
void clearGetvouchers() => clearField(14);
void clearGetVouchers() => clearField(14);
@$pb.TagNumber(14)
ApplicationData_GetVouchers ensureGetvouchers() => $_ensure(10);
ApplicationData_GetVouchers ensureGetVouchers() => $_ensure(10);
@$pb.TagNumber(15)
ApplicationData_SwitchToPayedPlan get switchtopayedplan => $_getN(11);
ApplicationData_SwitchToPayedPlan get switchtoPayedPlan => $_getN(11);
@$pb.TagNumber(15)
set switchtopayedplan(ApplicationData_SwitchToPayedPlan v) { setField(15, v); }
set switchtoPayedPlan(ApplicationData_SwitchToPayedPlan v) { setField(15, v); }
@$pb.TagNumber(15)
$core.bool hasSwitchtopayedplan() => $_has(11);
$core.bool hasSwitchtoPayedPlan() => $_has(11);
@$pb.TagNumber(15)
void clearSwitchtopayedplan() => clearField(15);
void clearSwitchtoPayedPlan() => clearField(15);
@$pb.TagNumber(15)
ApplicationData_SwitchToPayedPlan ensureSwitchtopayedplan() => $_ensure(11);
ApplicationData_SwitchToPayedPlan ensureSwitchtoPayedPlan() => $_ensure(11);
@$pb.TagNumber(16)
ApplicationData_GetAddAccountsInvites get getaddaccountsinvites => $_getN(12);
ApplicationData_GetAddAccountsInvites get getAddaccountsInvites => $_getN(12);
@$pb.TagNumber(16)
set getaddaccountsinvites(ApplicationData_GetAddAccountsInvites v) { setField(16, v); }
set getAddaccountsInvites(ApplicationData_GetAddAccountsInvites v) { setField(16, v); }
@$pb.TagNumber(16)
$core.bool hasGetaddaccountsinvites() => $_has(12);
$core.bool hasGetAddaccountsInvites() => $_has(12);
@$pb.TagNumber(16)
void clearGetaddaccountsinvites() => clearField(16);
void clearGetAddaccountsInvites() => clearField(16);
@$pb.TagNumber(16)
ApplicationData_GetAddAccountsInvites ensureGetaddaccountsinvites() => $_ensure(12);
ApplicationData_GetAddAccountsInvites ensureGetAddaccountsInvites() => $_ensure(12);
@$pb.TagNumber(17)
ApplicationData_RedeemAdditionalCode get redeemadditionalcode => $_getN(13);
ApplicationData_RedeemAdditionalCode get redeemAdditionalCode => $_getN(13);
@$pb.TagNumber(17)
set redeemadditionalcode(ApplicationData_RedeemAdditionalCode v) { setField(17, v); }
set redeemAdditionalCode(ApplicationData_RedeemAdditionalCode v) { setField(17, v); }
@$pb.TagNumber(17)
$core.bool hasRedeemadditionalcode() => $_has(13);
$core.bool hasRedeemAdditionalCode() => $_has(13);
@$pb.TagNumber(17)
void clearRedeemadditionalcode() => clearField(17);
void clearRedeemAdditionalCode() => clearField(17);
@$pb.TagNumber(17)
ApplicationData_RedeemAdditionalCode ensureRedeemadditionalcode() => $_ensure(13);
ApplicationData_RedeemAdditionalCode ensureRedeemAdditionalCode() => $_ensure(13);
@$pb.TagNumber(18)
ApplicationData_RemoveAdditionalUser get removeadditionaluser => $_getN(14);
ApplicationData_RemoveAdditionalUser get removeAdditionalUser => $_getN(14);
@$pb.TagNumber(18)
set removeadditionaluser(ApplicationData_RemoveAdditionalUser v) { setField(18, v); }
set removeAdditionalUser(ApplicationData_RemoveAdditionalUser v) { setField(18, v); }
@$pb.TagNumber(18)
$core.bool hasRemoveadditionaluser() => $_has(14);
$core.bool hasRemoveAdditionalUser() => $_has(14);
@$pb.TagNumber(18)
void clearRemoveadditionaluser() => clearField(18);
void clearRemoveAdditionalUser() => clearField(18);
@$pb.TagNumber(18)
ApplicationData_RemoveAdditionalUser ensureRemoveadditionaluser() => $_ensure(14);
ApplicationData_RemoveAdditionalUser ensureRemoveAdditionalUser() => $_ensure(14);
@$pb.TagNumber(19)
ApplicationData_UpdatePlanOptions get updateplanoptions => $_getN(15);
ApplicationData_UpdatePlanOptions get updatePlanOptions => $_getN(15);
@$pb.TagNumber(19)
set updateplanoptions(ApplicationData_UpdatePlanOptions v) { setField(19, v); }
set updatePlanOptions(ApplicationData_UpdatePlanOptions v) { setField(19, v); }
@$pb.TagNumber(19)
$core.bool hasUpdateplanoptions() => $_has(15);
$core.bool hasUpdatePlanOptions() => $_has(15);
@$pb.TagNumber(19)
void clearUpdateplanoptions() => clearField(19);
void clearUpdatePlanOptions() => clearField(19);
@$pb.TagNumber(19)
ApplicationData_UpdatePlanOptions ensureUpdateplanoptions() => $_ensure(15);
ApplicationData_UpdatePlanOptions ensureUpdatePlanOptions() => $_ensure(15);
@$pb.TagNumber(20)
ApplicationData_DownloadDone get downloaddone => $_getN(16);
ApplicationData_DownloadDone get downloadDone => $_getN(16);
@$pb.TagNumber(20)
set downloaddone(ApplicationData_DownloadDone v) { setField(20, v); }
set downloadDone(ApplicationData_DownloadDone v) { setField(20, v); }
@$pb.TagNumber(20)
$core.bool hasDownloaddone() => $_has(16);
$core.bool hasDownloadDone() => $_has(16);
@$pb.TagNumber(20)
void clearDownloaddone() => clearField(20);
void clearDownloadDone() => clearField(20);
@$pb.TagNumber(20)
ApplicationData_DownloadDone ensureDownloaddone() => $_ensure(16);
ApplicationData_DownloadDone ensureDownloadDone() => $_ensure(16);
@$pb.TagNumber(22)
ApplicationData_GetSignedPreKeyByUserId get getsignedprekeybyuserid => $_getN(17);
ApplicationData_GetSignedPreKeyByUserId get getSignedPrekeyByUserid => $_getN(17);
@$pb.TagNumber(22)
set getsignedprekeybyuserid(ApplicationData_GetSignedPreKeyByUserId v) { setField(22, v); }
set getSignedPrekeyByUserid(ApplicationData_GetSignedPreKeyByUserId v) { setField(22, v); }
@$pb.TagNumber(22)
$core.bool hasGetsignedprekeybyuserid() => $_has(17);
$core.bool hasGetSignedPrekeyByUserid() => $_has(17);
@$pb.TagNumber(22)
void clearGetsignedprekeybyuserid() => clearField(22);
void clearGetSignedPrekeyByUserid() => clearField(22);
@$pb.TagNumber(22)
ApplicationData_GetSignedPreKeyByUserId ensureGetsignedprekeybyuserid() => $_ensure(17);
ApplicationData_GetSignedPreKeyByUserId ensureGetSignedPrekeyByUserid() => $_ensure(17);
@$pb.TagNumber(23)
ApplicationData_UpdateSignedPreKey get updatesignedprekey => $_getN(18);
ApplicationData_UpdateSignedPreKey get updateSignedPrekey => $_getN(18);
@$pb.TagNumber(23)
set updatesignedprekey(ApplicationData_UpdateSignedPreKey v) { setField(23, v); }
set updateSignedPrekey(ApplicationData_UpdateSignedPreKey v) { setField(23, v); }
@$pb.TagNumber(23)
$core.bool hasUpdatesignedprekey() => $_has(18);
$core.bool hasUpdateSignedPrekey() => $_has(18);
@$pb.TagNumber(23)
void clearUpdatesignedprekey() => clearField(23);
void clearUpdateSignedPrekey() => clearField(23);
@$pb.TagNumber(23)
ApplicationData_UpdateSignedPreKey ensureUpdatesignedprekey() => $_ensure(18);
ApplicationData_UpdateSignedPreKey ensureUpdateSignedPrekey() => $_ensure(18);
@$pb.TagNumber(24)
ApplicationData_DeleteAccount get deleteaccount => $_getN(19);
ApplicationData_DeleteAccount get deleteAccount => $_getN(19);
@$pb.TagNumber(24)
set deleteaccount(ApplicationData_DeleteAccount v) { setField(24, v); }
set deleteAccount(ApplicationData_DeleteAccount v) { setField(24, v); }
@$pb.TagNumber(24)
$core.bool hasDeleteaccount() => $_has(19);
$core.bool hasDeleteAccount() => $_has(19);
@$pb.TagNumber(24)
void clearDeleteaccount() => clearField(24);
void clearDeleteAccount() => clearField(24);
@$pb.TagNumber(24)
ApplicationData_DeleteAccount ensureDeleteaccount() => $_ensure(19);
ApplicationData_DeleteAccount ensureDeleteAccount() => $_ensure(19);
@$pb.TagNumber(25)
ApplicationData_ReportUser get reportuser => $_getN(20);
ApplicationData_ReportUser get reportUser => $_getN(20);
@$pb.TagNumber(25)
set reportuser(ApplicationData_ReportUser v) { setField(25, v); }
set reportUser(ApplicationData_ReportUser v) { setField(25, v); }
@$pb.TagNumber(25)
$core.bool hasReportuser() => $_has(20);
$core.bool hasReportUser() => $_has(20);
@$pb.TagNumber(25)
void clearReportuser() => clearField(25);
void clearReportUser() => clearField(25);
@$pb.TagNumber(25)
ApplicationData_ReportUser ensureReportuser() => $_ensure(20);
ApplicationData_ReportUser ensureReportUser() => $_ensure(20);
@$pb.TagNumber(26)
ApplicationData_ChangeUsername get changeUsername => $_getN(21);
@$pb.TagNumber(26)
set changeUsername(ApplicationData_ChangeUsername v) { setField(26, v); }
@$pb.TagNumber(26)
$core.bool hasChangeUsername() => $_has(21);
@$pb.TagNumber(26)
void clearChangeUsername() => clearField(26);
@$pb.TagNumber(26)
ApplicationData_ChangeUsername ensureChangeUsername() => $_ensure(21);
}
class Response_PreKey extends $pb.GeneratedMessage {

View file

@ -56,16 +56,22 @@ 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': '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_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'},
],
};
@$core.Deprecated('Use handshakeDescriptor instead')
const Handshake_RequestPOW$json = {
'1': 'RequestPOW',
};
@$core.Deprecated('Use handshakeDescriptor instead')
const Handshake_Register$json = {
'1': 'Register',
@ -77,11 +83,12 @@ const Handshake_Register$json = {
{'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, '9': 1, '10': 'isIos', '17': true},
{'1': 'is_ios', '3': 8, '4': 1, '5': 8, '10': 'isIos'},
{'1': 'lang_code', '3': 9, '4': 1, '5': 9, '10': 'langCode'},
{'1': 'proof_of_work', '3': 10, '4': 1, '5': 3, '10': 'proofOfWork'},
],
'8': [
{'1': '_invite_code'},
{'1': '_is_ios'},
],
};
@ -117,51 +124,54 @@ const Handshake_Authenticate$json = {
/// Descriptor for `Handshake`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List handshakeDescriptor = $convert.base64Decode(
'CglIYW5kc2hha2USQgoIcmVnaXN0ZXIYASABKAsyJC5jbGllbnRfdG9fc2VydmVyLkhhbmRzaG'
'FrZS5SZWdpc3RlckgAUghyZWdpc3RlchJaChBnZXRhdXRoY2hhbGxlbmdlGAIgASgLMiwuY2xp'
'ZW50X3RvX3NlcnZlci5IYW5kc2hha2UuR2V0QXV0aENoYWxsZW5nZUgAUhBnZXRhdXRoY2hhbG'
'xlbmdlEk4KDGdldGF1dGh0b2tlbhgDIAEoCzIoLmNsaWVudF90b19zZXJ2ZXIuSGFuZHNoYWtl'
'LkdldEF1dGhUb2tlbkgAUgxnZXRhdXRodG9rZW4STgoMYXV0aGVudGljYXRlGAQgASgLMiguY2'
'xpZW50X3RvX3NlcnZlci5IYW5kc2hha2UuQXV0aGVudGljYXRlSABSDGF1dGhlbnRpY2F0ZRrj'
'AgoIUmVnaXN0ZXISGgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW1lEiQKC2ludml0ZV9jb2RlGA'
'IgASgJSABSCmludml0ZUNvZGWIAQESLgoTcHVibGljX2lkZW50aXR5X2tleRgDIAEoDFIRcHVi'
'bGljSWRlbnRpdHlLZXkSIwoNc2lnbmVkX3ByZWtleRgEIAEoDFIMc2lnbmVkUHJla2V5EjYKF3'
'NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAUgASgMUhVzaWduZWRQcmVrZXlTaWduYXR1cmUSKAoQ'
'c2lnbmVkX3ByZWtleV9pZBgGIAEoA1IOc2lnbmVkUHJla2V5SWQSJwoPcmVnaXN0cmF0aW9uX2'
'lkGAcgASgDUg5yZWdpc3RyYXRpb25JZBIaCgZpc19pb3MYCCABKAhIAVIFaXNJb3OIAQFCDgoM'
'X2ludml0ZV9jb2RlQgkKB19pc19pb3MaEgoQR2V0QXV0aENoYWxsZW5nZRpDCgxHZXRBdXRoVG'
'9rZW4SFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhoKCHJlc3BvbnNlGAIgASgMUghyZXNwb25z'
'ZRqsAQoMQXV0aGVudGljYXRlEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBIdCgphdXRoX3Rva2'
'VuGAIgASgMUglhdXRoVG9rZW4SJAoLYXBwX3ZlcnNpb24YAyABKAlIAFIKYXBwVmVyc2lvbogB'
'ARIgCglkZXZpY2VfaWQYBCABKANIAVIIZGV2aWNlSWSIAQFCDgoMX2FwcF92ZXJzaW9uQgwKCl'
'9kZXZpY2VfaWRCCwoJSGFuZHNoYWtl');
'FrZS5SZWdpc3RlckgAUghyZWdpc3RlchJaChBnZXRBdXRoQ2hhbGxlbmdlGAIgASgLMiwuY2xp'
'ZW50X3RvX3NlcnZlci5IYW5kc2hha2UuR2V0QXV0aENoYWxsZW5nZUgAUhBnZXRBdXRoQ2hhbG'
'xlbmdlEk4KDGdldEF1dGhUb2tlbhgDIAEoCzIoLmNsaWVudF90b19zZXJ2ZXIuSGFuZHNoYWtl'
'LkdldEF1dGhUb2tlbkgAUgxnZXRBdXRoVG9rZW4STgoMYXV0aGVudGljYXRlGAQgASgLMiguY2'
'xpZW50X3RvX3NlcnZlci5IYW5kc2hha2UuQXV0aGVudGljYXRlSABSDGF1dGhlbnRpY2F0ZRJI'
'CgpyZXF1ZXN0UE9XGAUgASgLMiYuY2xpZW50X3RvX3NlcnZlci5IYW5kc2hha2UuUmVxdWVzdF'
'BPV0gAUgpyZXF1ZXN0UE9XGgwKClJlcXVlc3RQT1calAMKCFJlZ2lzdGVyEhoKCHVzZXJuYW1l'
'GAEgASgJUgh1c2VybmFtZRIkCgtpbnZpdGVfY29kZRgCIAEoCUgAUgppbnZpdGVDb2RliAEBEi'
'4KE3B1YmxpY19pZGVudGl0eV9rZXkYAyABKAxSEXB1YmxpY0lkZW50aXR5S2V5EiMKDXNpZ25l'
'ZF9wcmVrZXkYBCABKAxSDHNpZ25lZFByZWtleRI2ChdzaWduZWRfcHJla2V5X3NpZ25hdHVyZR'
'gFIAEoDFIVc2lnbmVkUHJla2V5U2lnbmF0dXJlEigKEHNpZ25lZF9wcmVrZXlfaWQYBiABKANS'
'DnNpZ25lZFByZWtleUlkEicKD3JlZ2lzdHJhdGlvbl9pZBgHIAEoA1IOcmVnaXN0cmF0aW9uSW'
'QSFQoGaXNfaW9zGAggASgIUgVpc0lvcxIbCglsYW5nX2NvZGUYCSABKAlSCGxhbmdDb2RlEiIK'
'DXByb29mX29mX3dvcmsYCiABKANSC3Byb29mT2ZXb3JrQg4KDF9pbnZpdGVfY29kZRoSChBHZX'
'RBdXRoQ2hhbGxlbmdlGkMKDEdldEF1dGhUb2tlbhIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQS'
'GgoIcmVzcG9uc2UYAiABKAxSCHJlc3BvbnNlGqwBCgxBdXRoZW50aWNhdGUSFwoHdXNlcl9pZB'
'gBIAEoA1IGdXNlcklkEh0KCmF1dGhfdG9rZW4YAiABKAxSCWF1dGhUb2tlbhIkCgthcHBfdmVy'
'c2lvbhgDIAEoCUgAUgphcHBWZXJzaW9uiAEBEiAKCWRldmljZV9pZBgEIAEoA0gBUghkZXZpY2'
'VJZIgBAUIOCgxfYXBwX3ZlcnNpb25CDAoKX2RldmljZV9pZEILCglIYW5kc2hha2U=');
@$core.Deprecated('Use applicationDataDescriptor instead')
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': '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_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'},
],
@ -188,6 +198,14 @@ const ApplicationData_GetUserByUsername$json = {
],
};
@$core.Deprecated('Use applicationDataDescriptor instead')
const ApplicationData_ChangeUsername$json = {
'1': 'ChangeUsername',
'2': [
{'1': 'username', '3': 1, '4': 1, '5': 9, '10': 'username'},
],
};
@$core.Deprecated('Use applicationDataDescriptor instead')
const ApplicationData_UpdateGoogleFcmToken$json = {
'1': 'UpdateGoogleFcmToken',
@ -329,64 +347,67 @@ const ApplicationData_DeleteAccount$json = {
/// Descriptor for `ApplicationData`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dG1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm'
'VyLkFwcGxpY2F0aW9uRGF0YS5UZXh0TWVzc2FnZUgAUgt0ZXh0bWVzc2FnZRJjChFnZXR1c2Vy'
'Ynl1c2VybmFtZRgCIAEoCzIzLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldF'
'VzZXJCeVVzZXJuYW1lSABSEWdldHVzZXJieXVzZXJuYW1lEmYKEmdldHByZWtleXNieXVzZXJp'
'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dE1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm'
'VyLkFwcGxpY2F0aW9uRGF0YS5UZXh0TWVzc2FnZUgAUgt0ZXh0TWVzc2FnZRJjChFnZXRVc2Vy'
'QnlVc2VybmFtZRgCIAEoCzIzLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldF'
'VzZXJCeVVzZXJuYW1lSABSEWdldFVzZXJCeVVzZXJuYW1lEmYKEmdldFByZWtleXNCeVVzZXJJ'
'ZBgDIAEoCzI0LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldFByZWtleXNCeV'
'VzZXJJZEgAUhJnZXRwcmVrZXlzYnl1c2VyaWQSUQoLZ2V0dXNlcmJ5aWQYBiABKAsyLS5jbGll'
'bnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5HZXRVc2VyQnlJZEgAUgtnZXR1c2VyYnlpZB'
'JsChR1cGRhdGVnb29nbGVmY210b2tlbhgIIAEoCzI2LmNsaWVudF90b19zZXJ2ZXIuQXBwbGlj'
'YXRpb25EYXRhLlVwZGF0ZUdvb2dsZUZjbVRva2VuSABSFHVwZGF0ZWdvb2dsZWZjbXRva2VuEl'
'EKC2dldGxvY2F0aW9uGAkgASgLMi0uY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEu'
'R2V0TG9jYXRpb25IAFILZ2V0bG9jYXRpb24SaQoTZ2V0Y3VycmVudHBsYW5pbmZvcxgKIAEoCz'
'VzZXJJZEgAUhJnZXRQcmVrZXlzQnlVc2VySWQSUQoLZ2V0VXNlckJ5SWQYBiABKAsyLS5jbGll'
'bnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5HZXRVc2VyQnlJZEgAUgtnZXRVc2VyQnlJZB'
'JsChR1cGRhdGVHb29nbGVGY21Ub2tlbhgIIAEoCzI2LmNsaWVudF90b19zZXJ2ZXIuQXBwbGlj'
'YXRpb25EYXRhLlVwZGF0ZUdvb2dsZUZjbVRva2VuSABSFHVwZGF0ZUdvb2dsZUZjbVRva2VuEl'
'EKC2dldExvY2F0aW9uGAkgASgLMi0uY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEu'
'R2V0TG9jYXRpb25IAFILZ2V0TG9jYXRpb24SaQoTZ2V0Q3VycmVudFBsYW5JbmZvcxgKIAEoCz'
'I1LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldEN1cnJlbnRQbGFuSW5mb3NI'
'AFITZ2V0Y3VycmVudHBsYW5pbmZvcxJXCg1yZWRlZW12b3VjaGVyGAsgASgLMi8uY2xpZW50X3'
'RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVkZWVtVm91Y2hlckgAUg1yZWRlZW12b3VjaGVy'
'EmMKEWdldGF2YWlsYWJsZXBsYW5zGAwgASgLMjMuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdG'
'lvbkRhdGEuR2V0QXZhaWxhYmxlUGxhbnNIAFIRZ2V0YXZhaWxhYmxlcGxhbnMSVwoNY3JlYXRl'
'dm91Y2hlchgNIAEoCzIvLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkNyZWF0ZV'
'ZvdWNoZXJIAFINY3JlYXRldm91Y2hlchJRCgtnZXR2b3VjaGVycxgOIAEoCzItLmNsaWVudF90'
'b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldFZvdWNoZXJzSABSC2dldHZvdWNoZXJzEmMKEV'
'N3aXRjaHRvcGF5ZWRwbGFuGA8gASgLMjMuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRh'
'dGEuU3dpdGNoVG9QYXllZFBsYW5IAFIRU3dpdGNodG9wYXllZHBsYW4SbwoVZ2V0YWRkYWNjb3'
'VudHNpbnZpdGVzGBAgASgLMjcuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuR2V0'
'QWRkQWNjb3VudHNJbnZpdGVzSABSFWdldGFkZGFjY291bnRzaW52aXRlcxJsChRyZWRlZW1hZG'
'RpdGlvbmFsY29kZRgRIAEoCzI2LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLlJl'
'ZGVlbUFkZGl0aW9uYWxDb2RlSABSFHJlZGVlbWFkZGl0aW9uYWxjb2RlEmwKFHJlbW92ZWFkZG'
'l0aW9uYWx1c2VyGBIgASgLMjYuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVt'
'b3ZlQWRkaXRpb25hbFVzZXJIAFIUcmVtb3ZlYWRkaXRpb25hbHVzZXISYwoRdXBkYXRlcGxhbm'
'AFITZ2V0Q3VycmVudFBsYW5JbmZvcxJXCg1yZWRlZW1Wb3VjaGVyGAsgASgLMi8uY2xpZW50X3'
'RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVkZWVtVm91Y2hlckgAUg1yZWRlZW1Wb3VjaGVy'
'EmMKEWdldEF2YWlsYWJsZVBsYW5zGAwgASgLMjMuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdG'
'lvbkRhdGEuR2V0QXZhaWxhYmxlUGxhbnNIAFIRZ2V0QXZhaWxhYmxlUGxhbnMSVwoNY3JlYXRl'
'Vm91Y2hlchgNIAEoCzIvLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkNyZWF0ZV'
'ZvdWNoZXJIAFINY3JlYXRlVm91Y2hlchJRCgtnZXRWb3VjaGVycxgOIAEoCzItLmNsaWVudF90'
'b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLkdldFZvdWNoZXJzSABSC2dldFZvdWNoZXJzEmMKEX'
'N3aXRjaHRvUGF5ZWRQbGFuGA8gASgLMjMuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRh'
'dGEuU3dpdGNoVG9QYXllZFBsYW5IAFIRc3dpdGNodG9QYXllZFBsYW4SbwoVZ2V0QWRkYWNjb3'
'VudHNJbnZpdGVzGBAgASgLMjcuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuR2V0'
'QWRkQWNjb3VudHNJbnZpdGVzSABSFWdldEFkZGFjY291bnRzSW52aXRlcxJsChRyZWRlZW1BZG'
'RpdGlvbmFsQ29kZRgRIAEoCzI2LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLlJl'
'ZGVlbUFkZGl0aW9uYWxDb2RlSABSFHJlZGVlbUFkZGl0aW9uYWxDb2RlEmwKFHJlbW92ZUFkZG'
'l0aW9uYWxVc2VyGBIgASgLMjYuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVt'
'b3ZlQWRkaXRpb25hbFVzZXJIAFIUcmVtb3ZlQWRkaXRpb25hbFVzZXISYwoRdXBkYXRlUGxhbk'
'9wdGlvbnMYEyABKAsyMy5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5VcGRhdGVQ'
'bGFuT3B0aW9uc0gAUhF1cGRhdGVwbGFub3B0aW9ucxJUCgxkb3dubG9hZGRvbmUYFCABKAsyLi'
'bGFuT3B0aW9uc0gAUhF1cGRhdGVQbGFuT3B0aW9ucxJUCgxkb3dubG9hZERvbmUYFCABKAsyLi'
'5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5Eb3dubG9hZERvbmVIAFIMZG93bmxv'
'YWRkb25lEnUKF2dldHNpZ25lZHByZWtleWJ5dXNlcmlkGBYgASgLMjkuY2xpZW50X3RvX3Nlcn'
'Zlci5BcHBsaWNhdGlvbkRhdGEuR2V0U2lnbmVkUHJlS2V5QnlVc2VySWRIAFIXZ2V0c2lnbmVk'
'cHJla2V5Ynl1c2VyaWQSZgoSdXBkYXRlc2lnbmVkcHJla2V5GBcgASgLMjQuY2xpZW50X3RvX3'
'NlcnZlci5BcHBsaWNhdGlvbkRhdGEuVXBkYXRlU2lnbmVkUHJlS2V5SABSEnVwZGF0ZXNpZ25l'
'ZHByZWtleRJXCg1kZWxldGVhY2NvdW50GBggASgLMi8uY2xpZW50X3RvX3NlcnZlci5BcHBsaW'
'NhdGlvbkRhdGEuRGVsZXRlQWNjb3VudEgAUg1kZWxldGVhY2NvdW50Ek4KCnJlcG9ydHVzZXIY'
'YWREb25lEnUKF2dldFNpZ25lZFByZWtleUJ5VXNlcmlkGBYgASgLMjkuY2xpZW50X3RvX3Nlcn'
'Zlci5BcHBsaWNhdGlvbkRhdGEuR2V0U2lnbmVkUHJlS2V5QnlVc2VySWRIAFIXZ2V0U2lnbmVk'
'UHJla2V5QnlVc2VyaWQSZgoSdXBkYXRlU2lnbmVkUHJla2V5GBcgASgLMjQuY2xpZW50X3RvX3'
'NlcnZlci5BcHBsaWNhdGlvbkRhdGEuVXBkYXRlU2lnbmVkUHJlS2V5SABSEnVwZGF0ZVNpZ25l'
'ZFByZWtleRJXCg1kZWxldGVBY2NvdW50GBggASgLMi8uY2xpZW50X3RvX3NlcnZlci5BcHBsaW'
'NhdGlvbkRhdGEuRGVsZXRlQWNjb3VudEgAUg1kZWxldGVBY2NvdW50Ek4KCnJlcG9ydFVzZXIY'
'GSABKAsyLC5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5SZXBvcnRVc2VySABSCn'
'JlcG9ydHVzZXIaagoLVGV4dE1lc3NhZ2USFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhIKBGJv'
'ZHkYAyABKAxSBGJvZHkSIAoJcHVzaF9kYXRhGAQgASgMSABSCHB1c2hEYXRhiAEBQgwKCl9wdX'
'NoX2RhdGEaLwoRR2V0VXNlckJ5VXNlcm5hbWUSGgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW1l'
'GjUKFFVwZGF0ZUdvb2dsZUZjbVRva2VuEh0KCmdvb2dsZV9mY20YASABKAlSCWdvb2dsZUZjbR'
'omCgtHZXRVc2VyQnlJZBIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQaKQoNUmVkZWVtVm91Y2hl'
'chIYCgd2b3VjaGVyGAEgASgJUgd2b3VjaGVyGnAKEVN3aXRjaFRvUGF5ZWRQbGFuEhcKB3BsYW'
'5faWQYASABKAlSBnBsYW5JZBIfCgtwYXlfbW9udGhseRgCIAEoCFIKcGF5TW9udGhseRIhCgxh'
'dXRvX3JlbmV3YWwYAyABKAhSC2F1dG9SZW5ld2FsGjYKEVVwZGF0ZVBsYW5PcHRpb25zEiEKDG'
'F1dG9fcmVuZXdhbBgBIAEoCFILYXV0b1JlbmV3YWwaMAoNQ3JlYXRlVm91Y2hlchIfCgt2YWx1'
'ZV9jZW50cxgBIAEoDVIKdmFsdWVDZW50cxoNCgtHZXRMb2NhdGlvbhoNCgtHZXRWb3VjaGVycx'
'oTChFHZXRBdmFpbGFibGVQbGFucxoXChVHZXRBZGRBY2NvdW50c0ludml0ZXMaFQoTR2V0Q3Vy'
'cmVudFBsYW5JbmZvcxo3ChRSZWRlZW1BZGRpdGlvbmFsQ29kZRIfCgtpbnZpdGVfY29kZRgCIA'
'EoCVIKaW52aXRlQ29kZRovChRSZW1vdmVBZGRpdGlvbmFsVXNlchIXCgd1c2VyX2lkGAEgASgD'
'UgZ1c2VySWQaLQoSR2V0UHJla2V5c0J5VXNlcklkEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZB'
'oyChdHZXRTaWduZWRQcmVLZXlCeVVzZXJJZBIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQamwEK'
'ElVwZGF0ZVNpZ25lZFByZUtleRIoChBzaWduZWRfcHJla2V5X2lkGAEgASgDUg5zaWduZWRQcm'
'VrZXlJZBIjCg1zaWduZWRfcHJla2V5GAIgASgMUgxzaWduZWRQcmVrZXkSNgoXc2lnbmVkX3By'
'ZWtleV9zaWduYXR1cmUYAyABKAxSFXNpZ25lZFByZWtleVNpZ25hdHVyZRo1CgxEb3dubG9hZE'
'RvbmUSJQoOZG93bmxvYWRfdG9rZW4YASABKAxSDWRvd25sb2FkVG9rZW4aTgoKUmVwb3J0VXNl'
'chIoChByZXBvcnRlZF91c2VyX2lkGAEgASgDUg5yZXBvcnRlZFVzZXJJZBIWCgZyZWFzb24YAi'
'ABKAlSBnJlYXNvbhoPCg1EZWxldGVBY2NvdW50QhEKD0FwcGxpY2F0aW9uRGF0YQ==');
'JlcG9ydFVzZXISWgoOY2hhbmdlVXNlcm5hbWUYGiABKAsyMC5jbGllbnRfdG9fc2VydmVyLkFw'
'cGxpY2F0aW9uRGF0YS5DaGFuZ2VVc2VybmFtZUgAUg5jaGFuZ2VVc2VybmFtZRpqCgtUZXh0TW'
'Vzc2FnZRIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQSEgoEYm9keRgDIAEoDFIEYm9keRIgCglw'
'dXNoX2RhdGEYBCABKAxIAFIIcHVzaERhdGGIAQFCDAoKX3B1c2hfZGF0YRovChFHZXRVc2VyQn'
'lVc2VybmFtZRIaCgh1c2VybmFtZRgBIAEoCVIIdXNlcm5hbWUaLAoOQ2hhbmdlVXNlcm5hbWUS'
'GgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW1lGjUKFFVwZGF0ZUdvb2dsZUZjbVRva2VuEh0KCm'
'dvb2dsZV9mY20YASABKAlSCWdvb2dsZUZjbRomCgtHZXRVc2VyQnlJZBIXCgd1c2VyX2lkGAEg'
'ASgDUgZ1c2VySWQaKQoNUmVkZWVtVm91Y2hlchIYCgd2b3VjaGVyGAEgASgJUgd2b3VjaGVyGn'
'AKEVN3aXRjaFRvUGF5ZWRQbGFuEhcKB3BsYW5faWQYASABKAlSBnBsYW5JZBIfCgtwYXlfbW9u'
'dGhseRgCIAEoCFIKcGF5TW9udGhseRIhCgxhdXRvX3JlbmV3YWwYAyABKAhSC2F1dG9SZW5ld2'
'FsGjYKEVVwZGF0ZVBsYW5PcHRpb25zEiEKDGF1dG9fcmVuZXdhbBgBIAEoCFILYXV0b1JlbmV3'
'YWwaMAoNQ3JlYXRlVm91Y2hlchIfCgt2YWx1ZV9jZW50cxgBIAEoDVIKdmFsdWVDZW50cxoNCg'
'tHZXRMb2NhdGlvbhoNCgtHZXRWb3VjaGVycxoTChFHZXRBdmFpbGFibGVQbGFucxoXChVHZXRB'
'ZGRBY2NvdW50c0ludml0ZXMaFQoTR2V0Q3VycmVudFBsYW5JbmZvcxo3ChRSZWRlZW1BZGRpdG'
'lvbmFsQ29kZRIfCgtpbnZpdGVfY29kZRgCIAEoCVIKaW52aXRlQ29kZRovChRSZW1vdmVBZGRp'
'dGlvbmFsVXNlchIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQaLQoSR2V0UHJla2V5c0J5VXNlck'
'lkEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBoyChdHZXRTaWduZWRQcmVLZXlCeVVzZXJJZBIX'
'Cgd1c2VyX2lkGAEgASgDUgZ1c2VySWQamwEKElVwZGF0ZVNpZ25lZFByZUtleRIoChBzaWduZW'
'RfcHJla2V5X2lkGAEgASgDUg5zaWduZWRQcmVrZXlJZBIjCg1zaWduZWRfcHJla2V5GAIgASgM'
'UgxzaWduZWRQcmVrZXkSNgoXc2lnbmVkX3ByZWtleV9zaWduYXR1cmUYAyABKAxSFXNpZ25lZF'
'ByZWtleVNpZ25hdHVyZRo1CgxEb3dubG9hZERvbmUSJQoOZG93bmxvYWRfdG9rZW4YASABKAxS'
'DWRvd25sb2FkVG9rZW4aTgoKUmVwb3J0VXNlchIoChByZXBvcnRlZF91c2VyX2lkGAEgASgDUg'
'5yZXBvcnRlZFVzZXJJZBIWCgZyZWFzb24YAiABKAlSBnJlYXNvbhoPCg1EZWxldGVBY2NvdW50'
'QhEKD0FwcGxpY2F0aW9uRGF0YQ==');
@$core.Deprecated('Use responseDescriptor instead')
const Response$json = {

View file

@ -48,6 +48,8 @@ class ErrorCode extends $pb.ProtobufEnum {
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,
@ -84,6 +86,8 @@ class ErrorCode extends $pb.ProtobufEnum {
UserIdAlreadyTaken,
AppVersionOutdated,
NewDeviceRegistered,
InvalidProofOfWork,
RegistrationDisabled,
];
static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);

View file

@ -51,6 +51,8 @@ const ErrorCode$json = {
{'1': 'UserIdAlreadyTaken', '2': 1029},
{'1': 'AppVersionOutdated', '2': 1030},
{'1': 'NewDeviceRegistered', '2': 1031},
{'1': 'InvalidProofOfWork', '2': 1032},
{'1': 'RegistrationDisabled', '2': 1033},
],
};
@ -70,5 +72,6 @@ final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode(
'dlZBD+BxIVChBQbGFuTGltaXRSZWFjaGVkEP8HEhQKD05vdEVub3VnaENyZWRpdBCACBISCg1Q'
'bGFuRG93bmdyYWRlEIEIEhkKFFBsYW5VcGdyYWRlTm90WWVhcmx5EIIIEhgKE0ludmFsaWRTaW'
'duZWRQcmVLZXkQgwgSEwoOVXNlcklkTm90Rm91bmQQhAgSFwoSVXNlcklkQWxyZWFkeVRha2Vu'
'EIUIEhcKEkFwcFZlcnNpb25PdXRkYXRlZBCGCBIYChNOZXdEZXZpY2VSZWdpc3RlcmVkEIcI');
'EIUIEhcKEkFwcFZlcnNpb25PdXRkYXRlZBCGCBIYChNOZXdEZXZpY2VSZWdpc3RlcmVkEIcIEh'
'cKEkludmFsaWRQcm9vZk9mV29yaxCICBIZChRSZWdpc3RyYXRpb25EaXNhYmxlZBCJCA==');

View file

@ -1536,6 +1536,70 @@ class Response_DownloadTokens extends $pb.GeneratedMessage {
$core.List<$core.List<$core.int>> get downloadTokens => $_getList(0);
}
class Response_ProofOfWork extends $pb.GeneratedMessage {
factory Response_ProofOfWork({
$core.String? prefix,
$fixnum.Int64? difficulty,
}) {
final $result = create();
if (prefix != null) {
$result.prefix = prefix;
}
if (difficulty != null) {
$result.difficulty = difficulty;
}
return $result;
}
Response_ProofOfWork._() : super();
factory Response_ProofOfWork.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory Response_ProofOfWork.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response.ProofOfWork', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'prefix')
..aInt64(2, _omitFieldNames ? '' : 'difficulty')
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
Response_ProofOfWork clone() => Response_ProofOfWork()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
Response_ProofOfWork copyWith(void Function(Response_ProofOfWork) updates) => super.copyWith((message) => updates(message as Response_ProofOfWork)) as Response_ProofOfWork;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static Response_ProofOfWork create() => Response_ProofOfWork._();
Response_ProofOfWork createEmptyInstance() => create();
static $pb.PbList<Response_ProofOfWork> createRepeated() => $pb.PbList<Response_ProofOfWork>();
@$core.pragma('dart2js:noInline')
static Response_ProofOfWork getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Response_ProofOfWork>(create);
static Response_ProofOfWork? _defaultInstance;
@$pb.TagNumber(1)
$core.String get prefix => $_getSZ(0);
@$pb.TagNumber(1)
set prefix($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasPrefix() => $_has(0);
@$pb.TagNumber(1)
void clearPrefix() => clearField(1);
@$pb.TagNumber(2)
$fixnum.Int64 get difficulty => $_getI64(1);
@$pb.TagNumber(2)
set difficulty($fixnum.Int64 v) { $_setInt64(1, v); }
@$pb.TagNumber(2)
$core.bool hasDifficulty() => $_has(1);
@$pb.TagNumber(2)
void clearDifficulty() => clearField(2);
}
enum Response_Ok_Ok {
none,
userid,
@ -1551,6 +1615,7 @@ enum Response_Ok_Ok {
addaccountsinvites,
downloadtokens,
signedprekey,
proofOfWork,
notSet
}
@ -1570,6 +1635,7 @@ class Response_Ok extends $pb.GeneratedMessage {
Response_AddAccountsInvites? addaccountsinvites,
Response_DownloadTokens? downloadtokens,
Response_SignedPreKey? signedprekey,
Response_ProofOfWork? proofOfWork,
}) {
final $result = create();
if (none != null) {
@ -1614,6 +1680,9 @@ class Response_Ok extends $pb.GeneratedMessage {
if (signedprekey != null) {
$result.signedprekey = signedprekey;
}
if (proofOfWork != null) {
$result.proofOfWork = proofOfWork;
}
return $result;
}
Response_Ok._() : super();
@ -1635,10 +1704,11 @@ class Response_Ok extends $pb.GeneratedMessage {
12 : Response_Ok_Ok.addaccountsinvites,
13 : Response_Ok_Ok.downloadtokens,
14 : Response_Ok_Ok.signedprekey,
15 : Response_Ok_Ok.proofOfWork,
0 : Response_Ok_Ok.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response.Ok', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create)
..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
..aOB(1, _omitFieldNames ? '' : 'None', protoName: 'None')
..aInt64(2, _omitFieldNames ? '' : 'userid')
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'authchallenge', $pb.PbFieldType.OY)
@ -1653,6 +1723,7 @@ class Response_Ok extends $pb.GeneratedMessage {
..aOM<Response_AddAccountsInvites>(12, _omitFieldNames ? '' : 'addaccountsinvites', subBuilder: Response_AddAccountsInvites.create)
..aOM<Response_DownloadTokens>(13, _omitFieldNames ? '' : 'downloadtokens', subBuilder: Response_DownloadTokens.create)
..aOM<Response_SignedPreKey>(14, _omitFieldNames ? '' : 'signedprekey', subBuilder: Response_SignedPreKey.create)
..aOM<Response_ProofOfWork>(15, _omitFieldNames ? '' : 'proofOfWork', protoName: 'proofOfWork', subBuilder: Response_ProofOfWork.create)
..hasRequiredFields = false
;
@ -1825,6 +1896,17 @@ class Response_Ok extends $pb.GeneratedMessage {
void clearSignedprekey() => clearField(14);
@$pb.TagNumber(14)
Response_SignedPreKey ensureSignedprekey() => $_ensure(13);
@$pb.TagNumber(15)
Response_ProofOfWork get proofOfWork => $_getN(14);
@$pb.TagNumber(15)
set proofOfWork(Response_ProofOfWork v) { setField(15, v); }
@$pb.TagNumber(15)
$core.bool hasProofOfWork() => $_has(14);
@$pb.TagNumber(15)
void clearProofOfWork() => clearField(15);
@$pb.TagNumber(15)
Response_ProofOfWork ensureProofOfWork() => $_ensure(14);
}
enum Response_Response {

View file

@ -73,7 +73,7 @@ const Response$json = {
{'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_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'},
@ -257,6 +257,15 @@ const Response_DownloadTokens$json = {
],
};
@$core.Deprecated('Use responseDescriptor instead')
const Response_ProofOfWork$json = {
'1': 'ProofOfWork',
'2': [
{'1': 'prefix', '3': 1, '4': 1, '5': 9, '10': 'prefix'},
{'1': 'difficulty', '3': 2, '4': 1, '5': 3, '10': 'difficulty'},
],
};
@$core.Deprecated('Use responseDescriptor instead')
const Response_Ok$json = {
'1': 'Ok',
@ -275,6 +284,7 @@ const Response_Ok$json = {
{'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'},
@ -352,24 +362,26 @@ final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
'9zaWduZWRfcHJla2V5X2lkGlkKC1VwbG9hZFRva2VuEiEKDHVwbG9hZF90b2tlbhgBIAEoDFIL'
'dXBsb2FkVG9rZW4SJwoPZG93bmxvYWRfdG9rZW5zGAIgAygMUg5kb3dubG9hZFRva2Vucxo5Cg'
'5Eb3dubG9hZFRva2VucxInCg9kb3dubG9hZF90b2tlbnMYASADKAxSDmRvd25sb2FkVG9rZW5z'
'GvcGCgJPaxIUCgROb25lGAEgASgISABSBE5vbmUSGAoGdXNlcmlkGAIgASgDSABSBnVzZXJpZB'
'ImCg1hdXRoY2hhbGxlbmdlGAMgASgMSABSDWF1dGhjaGFsbGVuZ2USSgoLdXBsb2FkdG9rZW4Y'
'BCABKAsyJi5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlVwbG9hZFRva2VuSABSC3VwbG9hZH'
'Rva2VuEkEKCHVzZXJkYXRhGAUgASgLMiMuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5Vc2Vy'
'RGF0YUgAUgh1c2VyZGF0YRIeCglhdXRodG9rZW4YBiABKAxIAFIJYXV0aHRva2VuEkEKCGxvY2'
'F0aW9uGAcgASgLMiMuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5Mb2NhdGlvbkgAUghsb2Nh'
'dGlvbhJQCg1hdXRoZW50aWNhdGVkGAggASgLMiguc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS'
'5BdXRoZW50aWNhdGVkSABSDWF1dGhlbnRpY2F0ZWQSOAoFcGxhbnMYCSABKAsyIC5zZXJ2ZXJf'
'dG9fY2xpZW50LlJlc3BvbnNlLlBsYW5zSABSBXBsYW5zEk0KDHBsYW5iYWxsYW5jZRgKIAEoCz'
'InLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuUGxhbkJhbGxhbmNlSABSDHBsYW5iYWxsYW5j'
'ZRJBCgh2b3VjaGVycxgLIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVm91Y2hlcn'
'NIAFIIdm91Y2hlcnMSXwoSYWRkYWNjb3VudHNpbnZpdGVzGAwgASgLMi0uc2VydmVyX3RvX2Ns'
'aWVudC5SZXNwb25zZS5BZGRBY2NvdW50c0ludml0ZXNIAFISYWRkYWNjb3VudHNpbnZpdGVzEl'
'MKDmRvd25sb2FkdG9rZW5zGA0gASgLMikuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5Eb3du'
'bG9hZFRva2Vuc0gAUg5kb3dubG9hZHRva2VucxJNCgxzaWduZWRwcmVrZXkYDiABKAsyJy5zZX'
'J2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlNpZ25lZFByZUtleUgAUgxzaWduZWRwcmVrZXlCBAoC'
'T2silgEKEFRyYW5zYWN0aW9uVHlwZXMSCgoGUmVmdW5kEAASEwoPVm91Y2hlclJlZGVlbWVkEA'
'ESEgoOVm91Y2hlckNyZWF0ZWQQAhIICgRDYXNoEAMSDwoLUGxhblVwZ3JhZGUQBBILCgdVbmtu'
'b3duEAUSFAoQVGhhbmtzRm9yVGVzdGluZxAGEg8KC0F1dG9SZW5ld2FsEAdCCgoIUmVzcG9uc2'
'U=');
'GkUKC1Byb29mT2ZXb3JrEhYKBnByZWZpeBgBIAEoCVIGcHJlZml4Eh4KCmRpZmZpY3VsdHkYAi'
'ABKANSCmRpZmZpY3VsdHkawwcKAk9rEhQKBE5vbmUYASABKAhIAFIETm9uZRIYCgZ1c2VyaWQY'
'AiABKANIAFIGdXNlcmlkEiYKDWF1dGhjaGFsbGVuZ2UYAyABKAxIAFINYXV0aGNoYWxsZW5nZR'
'JKCgt1cGxvYWR0b2tlbhgEIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXBsb2Fk'
'VG9rZW5IAFILdXBsb2FkdG9rZW4SQQoIdXNlcmRhdGEYBSABKAsyIy5zZXJ2ZXJfdG9fY2xpZW'
'50LlJlc3BvbnNlLlVzZXJEYXRhSABSCHVzZXJkYXRhEh4KCWF1dGh0b2tlbhgGIAEoDEgAUglh'
'dXRodG9rZW4SQQoIbG9jYXRpb24YByABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLk'
'xvY2F0aW9uSABSCGxvY2F0aW9uElAKDWF1dGhlbnRpY2F0ZWQYCCABKAsyKC5zZXJ2ZXJfdG9f'
'Y2xpZW50LlJlc3BvbnNlLkF1dGhlbnRpY2F0ZWRIAFINYXV0aGVudGljYXRlZBI4CgVwbGFucx'
'gJIAEoCzIgLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuUGxhbnNIAFIFcGxhbnMSTQoMcGxh'
'bmJhbGxhbmNlGAogASgLMicuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QbGFuQmFsbGFuY2'
'VIAFIMcGxhbmJhbGxhbmNlEkEKCHZvdWNoZXJzGAsgASgLMiMuc2VydmVyX3RvX2NsaWVudC5S'
'ZXNwb25zZS5Wb3VjaGVyc0gAUgh2b3VjaGVycxJfChJhZGRhY2NvdW50c2ludml0ZXMYDCABKA'
'syLS5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkFkZEFjY291bnRzSW52aXRlc0gAUhJhZGRh'
'Y2NvdW50c2ludml0ZXMSUwoOZG93bmxvYWR0b2tlbnMYDSABKAsyKS5zZXJ2ZXJfdG9fY2xpZW'
'50LlJlc3BvbnNlLkRvd25sb2FkVG9rZW5zSABSDmRvd25sb2FkdG9rZW5zEk0KDHNpZ25lZHBy'
'ZWtleRgOIAEoCzInLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuU2lnbmVkUHJlS2V5SABSDH'
'NpZ25lZHByZWtleRJKCgtwcm9vZk9mV29yaxgPIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVz'
'cG9uc2UuUHJvb2ZPZldvcmtIAFILcHJvb2ZPZldvcmtCBAoCT2silgEKEFRyYW5zYWN0aW9uVH'
'lwZXMSCgoGUmVmdW5kEAASEwoPVm91Y2hlclJlZGVlbWVkEAESEgoOVm91Y2hlckNyZWF0ZWQQ'
'AhIICgRDYXNoEAMSDwoLUGxhblVwZ3JhZGUQBBILCgdVbmtub3duEAUSFAoQVGhhbmtzRm9yVG'
'VzdGluZxAGEg8KC0F1dG9SZW5ld2FsEAdCCgoIUmVzcG9uc2U=');

View file

@ -0,0 +1,246 @@
//
// Generated code. Do not modify.
// source: groups.proto
//
// @dart = 2.12
// 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
import 'dart:core' as $core;
import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:protobuf/protobuf.dart' as $pb;
import 'groups.pbenum.dart';
export 'groups.pbenum.dart';
/// Stored encrypted on the server in the members columns.
class EncryptedGroupState extends $pb.GeneratedMessage {
factory EncryptedGroupState({
$core.Iterable<$fixnum.Int64>? memberIds,
$core.Iterable<$fixnum.Int64>? adminIds,
$core.String? groupName,
$fixnum.Int64? deleteMessagesAfterMilliseconds,
$core.List<$core.int>? padding,
}) {
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;
}
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')
..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
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
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;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EncryptedGroupState create() => EncryptedGroupState._();
EncryptedGroupState createEmptyInstance() => create();
static $pb.PbList<EncryptedGroupState> createRepeated() => $pb.PbList<EncryptedGroupState>();
@$core.pragma('dart2js:noInline')
static EncryptedGroupState getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<EncryptedGroupState>(create);
static EncryptedGroupState? _defaultInstance;
@$pb.TagNumber(1)
$core.List<$fixnum.Int64> get memberIds => $_getList(0);
@$pb.TagNumber(2)
$core.List<$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); }
@$pb.TagNumber(3)
$core.bool hasGroupName() => $_has(2);
@$pb.TagNumber(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); }
@$pb.TagNumber(4)
$core.bool hasDeleteMessagesAfterMilliseconds() => $_has(3);
@$pb.TagNumber(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); }
@$pb.TagNumber(5)
$core.bool hasPadding() => $_has(4);
@$pb.TagNumber(5)
void clearPadding() => clearField(5);
}
class EncryptedAppendedGroupState extends $pb.GeneratedMessage {
factory EncryptedAppendedGroupState({
EncryptedAppendedGroupState_Type? type,
}) {
final $result = create();
if (type != null) {
$result.type = type;
}
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
;
@$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;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EncryptedAppendedGroupState create() => EncryptedAppendedGroupState._();
EncryptedAppendedGroupState createEmptyInstance() => create();
static $pb.PbList<EncryptedAppendedGroupState> createRepeated() => $pb.PbList<EncryptedAppendedGroupState>();
@$core.pragma('dart2js:noInline')
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); }
@$pb.TagNumber(1)
$core.bool hasType() => $_has(0);
@$pb.TagNumber(1)
void clearType() => clearField(1);
}
class EncryptedGroupStateEnvelop extends $pb.GeneratedMessage {
factory EncryptedGroupStateEnvelop({
$core.List<$core.int>? nonce,
$core.List<$core.int>? encryptedGroupState,
$core.List<$core.int>? mac,
}) {
final $result = create();
if (nonce != null) {
$result.nonce = nonce;
}
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
;
@$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;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static EncryptedGroupStateEnvelop create() => EncryptedGroupStateEnvelop._();
EncryptedGroupStateEnvelop createEmptyInstance() => create();
static $pb.PbList<EncryptedGroupStateEnvelop> createRepeated() => $pb.PbList<EncryptedGroupStateEnvelop>();
@$core.pragma('dart2js:noInline')
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); }
@$pb.TagNumber(1)
$core.bool hasNonce() => $_has(0);
@$pb.TagNumber(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); }
@$pb.TagNumber(2)
$core.bool hasEncryptedGroupState() => $_has(1);
@$pb.TagNumber(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); }
@$pb.TagNumber(3)
$core.bool hasMac() => $_has(2);
@$pb.TagNumber(3)
void clearMac() => clearField(3);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');

View file

@ -0,0 +1,30 @@
//
// Generated code. Do not modify.
// source: groups.proto
//
// @dart = 2.12
// 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
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 $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];
const EncryptedAppendedGroupState_Type._($core.int v, $core.String n) : super(v, n);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -0,0 +1,76 @@
//
// Generated code. Do not modify.
// source: groups.proto
//
// @dart = 2.12
// 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
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use encryptedGroupStateDescriptor instead')
const EncryptedGroupState$json = {
'1': 'EncryptedGroupState',
'2': [
{'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': 'padding', '3': 5, '4': 1, '5': 12, '10': 'padding'},
],
'8': [
{'1': '_deleteMessagesAfterMilliseconds'},
],
};
/// Descriptor for `EncryptedGroupState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List encryptedGroupStateDescriptor = $convert.base64Decode(
'ChNFbmNyeXB0ZWRHcm91cFN0YXRlEhwKCW1lbWJlcklkcxgBIAMoA1IJbWVtYmVySWRzEhoKCG'
'FkbWluSWRzGAIgAygDUghhZG1pbklkcxIcCglncm91cE5hbWUYAyABKAlSCWdyb3VwTmFtZRJN'
'Ch9kZWxldGVNZXNzYWdlc0FmdGVyTWlsbGlzZWNvbmRzGAQgASgDSABSH2RlbGV0ZU1lc3NhZ2'
'VzQWZ0ZXJNaWxsaXNlY29uZHOIAQESGAoHcGFkZGluZxgFIAEoDFIHcGFkZGluZ0IiCiBfZGVs'
'ZXRlTWVzc2FnZXNBZnRlck1pbGxpc2Vjb25kcw==');
@$core.Deprecated('Use encryptedAppendedGroupStateDescriptor instead')
const EncryptedAppendedGroupState$json = {
'1': 'EncryptedAppendedGroupState',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedAppendedGroupState.Type', '10': 'type'},
],
'4': [EncryptedAppendedGroupState_Type$json],
};
@$core.Deprecated('Use encryptedAppendedGroupStateDescriptor instead')
const EncryptedAppendedGroupState_Type$json = {
'1': 'Type',
'2': [
{'1': 'LEFT_GROUP', '2': 0},
],
};
/// Descriptor for `EncryptedAppendedGroupState`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List encryptedAppendedGroupStateDescriptor = $convert.base64Decode(
'ChtFbmNyeXB0ZWRBcHBlbmRlZEdyb3VwU3RhdGUSNQoEdHlwZRgBIAEoDjIhLkVuY3J5cHRlZE'
'FwcGVuZGVkR3JvdXBTdGF0ZS5UeXBlUgR0eXBlIhYKBFR5cGUSDgoKTEVGVF9HUk9VUBAA');
@$core.Deprecated('Use encryptedGroupStateEnvelopDescriptor instead')
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': '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(
'ChpFbmNyeXB0ZWRHcm91cFN0YXRlRW52ZWxvcBIUCgVub25jZRgBIAEoDFIFbm9uY2USMAoTZW'
'5jcnlwdGVkR3JvdXBTdGF0ZRgCIAEoDFITZW5jcnlwdGVkR3JvdXBTdGF0ZRIQCgNtYWMYAyAB'
'KAxSA21hYw==');

View file

@ -0,0 +1,14 @@
//
// Generated code. Do not modify.
// source: groups.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
export 'groups.pb.dart';

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,155 @@
//
// Generated code. Do not modify.
// source: messages.proto
//
// @dart = 2.12
// 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
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 $core.List<Message_Type> values = <Message_Type> [
SENDER_DELIVERY_RECEIPT,
PLAINTEXT_CONTENT,
CIPHERTEXT,
PREKEY_BUNDLE,
TEST_NOTIFICATION,
];
static final $core.Map<$core.int, Message_Type> _byValue = $pb.ProtobufEnum.initByValue(values);
static Message_Type? valueOf($core.int value) => _byValue[value];
const Message_Type._($core.int v, $core.String n) : super(v, n);
}
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 $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];
const PlaintextContent_DecryptionErrorMessage_Type._($core.int v, $core.String n) : super(v, n);
}
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 $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];
const EncryptedContent_MessageUpdate_Type._($core.int v, $core.String n) : super(v, n);
}
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 $core.List<EncryptedContent_Media_Type> values = <EncryptedContent_Media_Type> [
REUPLOAD,
IMAGE,
VIDEO,
GIF,
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];
const EncryptedContent_Media_Type._($core.int v, $core.String n) : super(v, n);
}
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 $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];
const EncryptedContent_MediaUpdate_Type._($core.int v, $core.String n) : super(v, n);
}
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 $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];
const EncryptedContent_ContactRequest_Type._($core.int v, $core.String n) : super(v, n);
}
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 $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];
const EncryptedContent_ContactUpdate_Type._($core.int v, $core.String n) : super(v, n);
}
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 $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];
const EncryptedContent_PushKeys_Type._($core.int v, $core.String n) : super(v, n);
}
const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names');

View file

@ -0,0 +1,448 @@
//
// Generated code. Do not modify.
// source: messages.proto
//
// @dart = 2.12
// 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
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use messageDescriptor instead')
const Message$json = {
'1': 'Message',
'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},
],
'4': [Message_Type$json],
'8': [
{'1': '_encryptedContent'},
{'1': '_plaintextContent'},
],
};
@$core.Deprecated('Use messageDescriptor instead')
const Message_Type$json = {
'1': 'Type',
'2': [
{'1': 'SENDER_DELIVERY_RECEIPT', '2': 0},
{'1': 'PLAINTEXT_CONTENT', '2': 1},
{'1': 'CIPHERTEXT', '2': 2},
{'1': 'PREKEY_BUNDLE', '2': 3},
{'1': 'TEST_NOTIFICATION', '2': 4},
],
};
/// Descriptor for `Message`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List messageDescriptor = $convert.base64Decode(
'CgdNZXNzYWdlEiEKBHR5cGUYASABKA4yDS5NZXNzYWdlLlR5cGVSBHR5cGUSHAoJcmVjZWlwdE'
'lkGAIgASgJUglyZWNlaXB0SWQSLwoQZW5jcnlwdGVkQ29udGVudBgDIAEoDEgAUhBlbmNyeXB0'
'ZWRDb250ZW50iAEBEkIKEHBsYWludGV4dENvbnRlbnQYBCABKAsyES5QbGFpbnRleHRDb250ZW'
'50SAFSEHBsYWludGV4dENvbnRlbnSIAQEidAoEVHlwZRIbChdTRU5ERVJfREVMSVZFUllfUkVD'
'RUlQVBAAEhUKEVBMQUlOVEVYVF9DT05URU5UEAESDgoKQ0lQSEVSVEVYVBACEhEKDVBSRUtFWV'
'9CVU5ETEUQAxIVChFURVNUX05PVElGSUNBVElPThAEQhMKEV9lbmNyeXB0ZWRDb250ZW50QhMK'
'EV9wbGFpbnRleHRDb250ZW50');
@$core.Deprecated('Use plaintextContentDescriptor instead')
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},
],
'3': [PlaintextContent_RetryErrorMessage$json, PlaintextContent_DecryptionErrorMessage$json],
'8': [
{'1': '_decryptionErrorMessage'},
{'1': '_retryControlError'},
],
};
@$core.Deprecated('Use plaintextContentDescriptor instead')
const PlaintextContent_RetryErrorMessage$json = {
'1': 'RetryErrorMessage',
};
@$core.Deprecated('Use plaintextContentDescriptor instead')
const PlaintextContent_DecryptionErrorMessage$json = {
'1': 'DecryptionErrorMessage',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.PlaintextContent.DecryptionErrorMessage.Type', '10': 'type'},
],
'4': [PlaintextContent_DecryptionErrorMessage_Type$json],
};
@$core.Deprecated('Use plaintextContentDescriptor instead')
const PlaintextContent_DecryptionErrorMessage_Type$json = {
'1': 'Type',
'2': [
{'1': 'UNKNOWN', '2': 0},
{'1': 'PREKEY_UNKNOWN', '2': 1},
],
};
/// Descriptor for `PlaintextContent`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List plaintextContentDescriptor = $convert.base64Decode(
'ChBQbGFpbnRleHRDb250ZW50EmUKFmRlY3J5cHRpb25FcnJvck1lc3NhZ2UYASABKAsyKC5QbG'
'FpbnRleHRDb250ZW50LkRlY3J5cHRpb25FcnJvck1lc3NhZ2VIAFIWZGVjcnlwdGlvbkVycm9y'
'TWVzc2FnZYgBARJWChFyZXRyeUNvbnRyb2xFcnJvchgCIAEoCzIjLlBsYWludGV4dENvbnRlbn'
'QuUmV0cnlFcnJvck1lc3NhZ2VIAVIRcmV0cnlDb250cm9sRXJyb3KIAQEaEwoRUmV0cnlFcnJv'
'ck1lc3NhZ2UahAEKFkRlY3J5cHRpb25FcnJvck1lc3NhZ2USQQoEdHlwZRgBIAEoDjItLlBsYW'
'ludGV4dENvbnRlbnQuRGVjcnlwdGlvbkVycm9yTWVzc2FnZS5UeXBlUgR0eXBlIicKBFR5cGUS'
'CwoHVU5LTk9XThAAEhIKDlBSRUtFWV9VTktOT1dOEAFCGQoXX2RlY3J5cHRpb25FcnJvck1lc3'
'NhZ2VCFAoSX3JldHJ5Q29udHJvbEVycm9y');
@$core.Deprecated('Use encryptedContentDescriptor instead')
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},
],
'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'},
{'1': '_senderProfileCounter'},
{'1': '_messageUpdate'},
{'1': '_media'},
{'1': '_mediaUpdate'},
{'1': '_contactUpdate'},
{'1': '_contactRequest'},
{'1': '_flameSync'},
{'1': '_pushKeys'},
{'1': '_reaction'},
{'1': '_textMessage'},
{'1': '_groupCreate'},
{'1': '_groupJoin'},
{'1': '_groupUpdate'},
{'1': '_resendGroupPublicKey'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_GroupCreate$json = {
'1': 'GroupCreate',
'2': [
{'1': 'stateKey', '3': 3, '4': 1, '5': 12, '10': 'stateKey'},
{'1': 'groupPublicKey', '3': 4, '4': 1, '5': 12, '10': 'groupPublicKey'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_GroupJoin$json = {
'1': 'GroupJoin',
'2': [
{'1': 'groupPublicKey', '3': 1, '4': 1, '5': 12, '10': 'groupPublicKey'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_ResendGroupPublicKey$json = {
'1': 'ResendGroupPublicKey',
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
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},
],
'8': [
{'1': '_affectedContactId'},
{'1': '_newGroupName'},
{'1': '_newDeleteMessagesAfterMilliseconds'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_TextMessage$json = {
'1': 'TextMessage',
'2': [
{'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},
],
'8': [
{'1': '_quoteMessageId'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_Reaction$json = {
'1': 'Reaction',
'2': [
{'1': 'targetMessageId', '3': 1, '4': 1, '5': 9, '10': 'targetMessageId'},
{'1': 'emoji', '3': 2, '4': 1, '5': 9, '10': 'emoji'},
{'1': 'remove', '3': 3, '4': 1, '5': 8, '10': 'remove'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
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': 'text', '3': 4, '4': 1, '5': 9, '9': 1, '10': 'text', '17': true},
{'1': 'timestamp', '3': 5, '4': 1, '5': 3, '10': 'timestamp'},
],
'4': [EncryptedContent_MessageUpdate_Type$json],
'8': [
{'1': '_senderMessageId'},
{'1': '_text'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_MessageUpdate_Type$json = {
'1': 'Type',
'2': [
{'1': 'DELETE', '2': 0},
{'1': 'EDIT_TEXT', '2': 1},
{'1': 'OPENED', '2': 2},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
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': '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},
],
'4': [EncryptedContent_Media_Type$json],
'8': [
{'1': '_displayLimitInMilliseconds'},
{'1': '_quoteMessageId'},
{'1': '_downloadToken'},
{'1': '_encryptionKey'},
{'1': '_encryptionMac'},
{'1': '_encryptionNonce'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_Media_Type$json = {
'1': 'Type',
'2': [
{'1': 'REUPLOAD', '2': 0},
{'1': 'IMAGE', '2': 1},
{'1': 'VIDEO', '2': 2},
{'1': 'GIF', '2': 3},
{'1': 'AUDIO', '2': 4},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_MediaUpdate$json = {
'1': 'MediaUpdate',
'2': [
{'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],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_MediaUpdate_Type$json = {
'1': 'Type',
'2': [
{'1': 'REOPENED', '2': 0},
{'1': 'STORED', '2': 1},
{'1': 'DECRYPTION_ERROR', '2': 2},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_ContactRequest$json = {
'1': 'ContactRequest',
'2': [
{'1': 'type', '3': 1, '4': 1, '5': 14, '6': '.EncryptedContent.ContactRequest.Type', '10': 'type'},
],
'4': [EncryptedContent_ContactRequest_Type$json],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_ContactRequest_Type$json = {
'1': 'Type',
'2': [
{'1': 'REQUEST', '2': 0},
{'1': 'REJECT', '2': 1},
{'1': 'ACCEPT', '2': 2},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
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},
],
'4': [EncryptedContent_ContactUpdate_Type$json],
'8': [
{'1': '_avatarSvgCompressed'},
{'1': '_username'},
{'1': '_displayName'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_ContactUpdate_Type$json = {
'1': 'Type',
'2': [
{'1': 'REQUEST', '2': 0},
{'1': 'UPDATE', '2': 1},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_PushKeys$json = {
'1': 'PushKeys',
'2': [
{'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},
],
'4': [EncryptedContent_PushKeys_Type$json],
'8': [
{'1': '_keyId'},
{'1': '_key'},
{'1': '_createdAt'},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
const EncryptedContent_PushKeys_Type$json = {
'1': 'Type',
'2': [
{'1': 'REQUEST', '2': 0},
{'1': 'UPDATE', '2': 1},
],
};
@$core.Deprecated('Use encryptedContentDescriptor instead')
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': 'bestFriend', '3': 3, '4': 1, '5': 8, '10': 'bestFriend'},
{'1': 'forceUpdate', '3': 4, '4': 1, '5': 8, '10': 'forceUpdate'},
],
};
/// Descriptor for `EncryptedContent`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List encryptedContentDescriptor = $convert.base64Decode(
'ChBFbmNyeXB0ZWRDb250ZW50Eh0KB2dyb3VwSWQYAiABKAlIAFIHZ3JvdXBJZIgBARInCgxpc0'
'RpcmVjdENoYXQYAyABKAhIAVIMaXNEaXJlY3RDaGF0iAEBEjcKFHNlbmRlclByb2ZpbGVDb3Vu'
'dGVyGAQgASgDSAJSFHNlbmRlclByb2ZpbGVDb3VudGVyiAEBEkoKDW1lc3NhZ2VVcGRhdGUYBS'
'ABKAsyHy5FbmNyeXB0ZWRDb250ZW50Lk1lc3NhZ2VVcGRhdGVIA1INbWVzc2FnZVVwZGF0ZYgB'
'ARIyCgVtZWRpYRgGIAEoCzIXLkVuY3J5cHRlZENvbnRlbnQuTWVkaWFIBFIFbWVkaWGIAQESRA'
'oLbWVkaWFVcGRhdGUYByABKAsyHS5FbmNyeXB0ZWRDb250ZW50Lk1lZGlhVXBkYXRlSAVSC21l'
'ZGlhVXBkYXRliAEBEkoKDWNvbnRhY3RVcGRhdGUYCCABKAsyHy5FbmNyeXB0ZWRDb250ZW50Lk'
'NvbnRhY3RVcGRhdGVIBlINY29udGFjdFVwZGF0ZYgBARJNCg5jb250YWN0UmVxdWVzdBgJIAEo'
'CzIgLkVuY3J5cHRlZENvbnRlbnQuQ29udGFjdFJlcXVlc3RIB1IOY29udGFjdFJlcXVlc3SIAQ'
'ESPgoJZmxhbWVTeW5jGAogASgLMhsuRW5jcnlwdGVkQ29udGVudC5GbGFtZVN5bmNICFIJZmxh'
'bWVTeW5jiAEBEjsKCHB1c2hLZXlzGAsgASgLMhouRW5jcnlwdGVkQ29udGVudC5QdXNoS2V5c0'
'gJUghwdXNoS2V5c4gBARI7CghyZWFjdGlvbhgMIAEoCzIaLkVuY3J5cHRlZENvbnRlbnQuUmVh'
'Y3Rpb25IClIIcmVhY3Rpb26IAQESRAoLdGV4dE1lc3NhZ2UYDSABKAsyHS5FbmNyeXB0ZWRDb2'
'50ZW50LlRleHRNZXNzYWdlSAtSC3RleHRNZXNzYWdliAEBEkQKC2dyb3VwQ3JlYXRlGA4gASgL'
'Mh0uRW5jcnlwdGVkQ29udGVudC5Hcm91cENyZWF0ZUgMUgtncm91cENyZWF0ZYgBARI+Cglncm'
'91cEpvaW4YDyABKAsyGy5FbmNyeXB0ZWRDb250ZW50Lkdyb3VwSm9pbkgNUglncm91cEpvaW6I'
'AQESRAoLZ3JvdXBVcGRhdGUYECABKAsyHS5FbmNyeXB0ZWRDb250ZW50Lkdyb3VwVXBkYXRlSA'
'5SC2dyb3VwVXBkYXRliAEBEl8KFHJlc2VuZEdyb3VwUHVibGljS2V5GBEgASgLMiYuRW5jcnlw'
'dGVkQ29udGVudC5SZXNlbmRHcm91cFB1YmxpY0tleUgPUhRyZXNlbmRHcm91cFB1YmxpY0tleY'
'gBARpRCgtHcm91cENyZWF0ZRIaCghzdGF0ZUtleRgDIAEoDFIIc3RhdGVLZXkSJgoOZ3JvdXBQ'
'dWJsaWNLZXkYBCABKAxSDmdyb3VwUHVibGljS2V5GjMKCUdyb3VwSm9pbhImCg5ncm91cFB1Ym'
'xpY0tleRgBIAEoDFIOZ3JvdXBQdWJsaWNLZXkaFgoUUmVzZW5kR3JvdXBQdWJsaWNLZXkatgIK'
'C0dyb3VwVXBkYXRlEigKD2dyb3VwQWN0aW9uVHlwZRgBIAEoCVIPZ3JvdXBBY3Rpb25UeXBlEj'
'EKEWFmZmVjdGVkQ29udGFjdElkGAIgASgDSABSEWFmZmVjdGVkQ29udGFjdElkiAEBEicKDG5l'
'd0dyb3VwTmFtZRgDIAEoCUgBUgxuZXdHcm91cE5hbWWIAQESUwoibmV3RGVsZXRlTWVzc2FnZX'
'NBZnRlck1pbGxpc2Vjb25kcxgEIAEoA0gCUiJuZXdEZWxldGVNZXNzYWdlc0FmdGVyTWlsbGlz'
'ZWNvbmRziAEBQhQKEl9hZmZlY3RlZENvbnRhY3RJZEIPCg1fbmV3R3JvdXBOYW1lQiUKI19uZX'
'dEZWxldGVNZXNzYWdlc0FmdGVyTWlsbGlzZWNvbmRzGqkBCgtUZXh0TWVzc2FnZRIoCg9zZW5k'
'ZXJNZXNzYWdlSWQYASABKAlSD3NlbmRlck1lc3NhZ2VJZBISCgR0ZXh0GAIgASgJUgR0ZXh0Eh'
'wKCXRpbWVzdGFtcBgDIAEoA1IJdGltZXN0YW1wEisKDnF1b3RlTWVzc2FnZUlkGAQgASgJSABS'
'DnF1b3RlTWVzc2FnZUlkiAEBQhEKD19xdW90ZU1lc3NhZ2VJZBpiCghSZWFjdGlvbhIoCg90YX'
'JnZXRNZXNzYWdlSWQYASABKAlSD3RhcmdldE1lc3NhZ2VJZBIUCgVlbW9qaRgCIAEoCVIFZW1v'
'amkSFgoGcmVtb3ZlGAMgASgIUgZyZW1vdmUatwIKDU1lc3NhZ2VVcGRhdGUSOAoEdHlwZRgBIA'
'EoDjIkLkVuY3J5cHRlZENvbnRlbnQuTWVzc2FnZVVwZGF0ZS5UeXBlUgR0eXBlEi0KD3NlbmRl'
'ck1lc3NhZ2VJZBgCIAEoCUgAUg9zZW5kZXJNZXNzYWdlSWSIAQESOgoYbXVsdGlwbGVUYXJnZX'
'RNZXNzYWdlSWRzGAMgAygJUhhtdWx0aXBsZVRhcmdldE1lc3NhZ2VJZHMSFwoEdGV4dBgEIAEo'
'CUgBUgR0ZXh0iAEBEhwKCXRpbWVzdGFtcBgFIAEoA1IJdGltZXN0YW1wIi0KBFR5cGUSCgoGRE'
'VMRVRFEAASDQoJRURJVF9URVhUEAESCgoGT1BFTkVEEAJCEgoQX3NlbmRlck1lc3NhZ2VJZEIH'
'CgVfdGV4dBqXBQoFTWVkaWESKAoPc2VuZGVyTWVzc2FnZUlkGAEgASgJUg9zZW5kZXJNZXNzYW'
'dlSWQSMAoEdHlwZRgCIAEoDjIcLkVuY3J5cHRlZENvbnRlbnQuTWVkaWEuVHlwZVIEdHlwZRJD'
'ChpkaXNwbGF5TGltaXRJbk1pbGxpc2Vjb25kcxgDIAEoA0gAUhpkaXNwbGF5TGltaXRJbk1pbG'
'xpc2Vjb25kc4gBARI2ChZyZXF1aXJlc0F1dGhlbnRpY2F0aW9uGAQgASgIUhZyZXF1aXJlc0F1'
'dGhlbnRpY2F0aW9uEhwKCXRpbWVzdGFtcBgFIAEoA1IJdGltZXN0YW1wEisKDnF1b3RlTWVzc2'
'FnZUlkGAYgASgJSAFSDnF1b3RlTWVzc2FnZUlkiAEBEikKDWRvd25sb2FkVG9rZW4YByABKAxI'
'AlINZG93bmxvYWRUb2tlbogBARIpCg1lbmNyeXB0aW9uS2V5GAggASgMSANSDWVuY3J5cHRpb2'
'5LZXmIAQESKQoNZW5jcnlwdGlvbk1hYxgJIAEoDEgEUg1lbmNyeXB0aW9uTWFjiAEBEi0KD2Vu'
'Y3J5cHRpb25Ob25jZRgKIAEoDEgFUg9lbmNyeXB0aW9uTm9uY2WIAQEiPgoEVHlwZRIMCghSRV'
'VQTE9BRBAAEgkKBUlNQUdFEAESCQoFVklERU8QAhIHCgNHSUYQAxIJCgVBVURJTxAEQh0KG19k'
'aXNwbGF5TGltaXRJbk1pbGxpc2Vjb25kc0IRCg9fcXVvdGVNZXNzYWdlSWRCEAoOX2Rvd25sb2'
'FkVG9rZW5CEAoOX2VuY3J5cHRpb25LZXlCEAoOX2VuY3J5cHRpb25NYWNCEgoQX2VuY3J5cHRp'
'b25Ob25jZRqnAQoLTWVkaWFVcGRhdGUSNgoEdHlwZRgBIAEoDjIiLkVuY3J5cHRlZENvbnRlbn'
'QuTWVkaWFVcGRhdGUuVHlwZVIEdHlwZRIoCg90YXJnZXRNZXNzYWdlSWQYAiABKAlSD3Rhcmdl'
'dE1lc3NhZ2VJZCI2CgRUeXBlEgwKCFJFT1BFTkVEEAASCgoGU1RPUkVEEAESFAoQREVDUllQVE'
'lPTl9FUlJPUhACGngKDkNvbnRhY3RSZXF1ZXN0EjkKBHR5cGUYASABKA4yJS5FbmNyeXB0ZWRD'
'b250ZW50LkNvbnRhY3RSZXF1ZXN0LlR5cGVSBHR5cGUiKwoEVHlwZRILCgdSRVFVRVNUEAASCg'
'oGUkVKRUNUEAESCgoGQUNDRVBUEAIangIKDUNvbnRhY3RVcGRhdGUSOAoEdHlwZRgBIAEoDjIk'
'LkVuY3J5cHRlZENvbnRlbnQuQ29udGFjdFVwZGF0ZS5UeXBlUgR0eXBlEjUKE2F2YXRhclN2Z0'
'NvbXByZXNzZWQYAiABKAxIAFITYXZhdGFyU3ZnQ29tcHJlc3NlZIgBARIfCgh1c2VybmFtZRgD'
'IAEoCUgBUgh1c2VybmFtZYgBARIlCgtkaXNwbGF5TmFtZRgEIAEoCUgCUgtkaXNwbGF5TmFtZY'
'gBASIfCgRUeXBlEgsKB1JFUVVFU1QQABIKCgZVUERBVEUQAUIWChRfYXZhdGFyU3ZnQ29tcHJl'
'c3NlZEILCglfdXNlcm5hbWVCDgoMX2Rpc3BsYXlOYW1lGtUBCghQdXNoS2V5cxIzCgR0eXBlGA'
'EgASgOMh8uRW5jcnlwdGVkQ29udGVudC5QdXNoS2V5cy5UeXBlUgR0eXBlEhkKBWtleUlkGAIg'
'ASgDSABSBWtleUlkiAEBEhUKA2tleRgDIAEoDEgBUgNrZXmIAQESIQoJY3JlYXRlZEF0GAQgAS'
'gDSAJSCWNyZWF0ZWRBdIgBASIfCgRUeXBlEgsKB1JFUVVFU1QQABIKCgZVUERBVEUQAUIICgZf'
'a2V5SWRCBgoEX2tleUIMCgpfY3JlYXRlZEF0GqkBCglGbGFtZVN5bmMSIgoMZmxhbWVDb3VudG'
'VyGAEgASgDUgxmbGFtZUNvdW50ZXISNgoWbGFzdEZsYW1lQ291bnRlckNoYW5nZRgCIAEoA1IW'
'bGFzdEZsYW1lQ291bnRlckNoYW5nZRIeCgpiZXN0RnJpZW5kGAMgASgIUgpiZXN0RnJpZW5kEi'
'AKC2ZvcmNlVXBkYXRlGAQgASgIUgtmb3JjZVVwZGF0ZUIKCghfZ3JvdXBJZEIPCg1faXNEaXJl'
'Y3RDaGF0QhcKFV9zZW5kZXJQcm9maWxlQ291bnRlckIQCg5fbWVzc2FnZVVwZGF0ZUIICgZfbW'
'VkaWFCDgoMX21lZGlhVXBkYXRlQhAKDl9jb250YWN0VXBkYXRlQhEKD19jb250YWN0UmVxdWVz'
'dEIMCgpfZmxhbWVTeW5jQgsKCV9wdXNoS2V5c0ILCglfcmVhY3Rpb25CDgoMX3RleHRNZXNzYW'
'dlQg4KDF9ncm91cENyZWF0ZUIMCgpfZ3JvdXBKb2luQg4KDF9ncm91cFVwZGF0ZUIXChVfcmVz'
'ZW5kR3JvdXBQdWJsaWNLZXk=');

View file

@ -0,0 +1,14 @@
//
// Generated code. Do not modify.
// source: messages.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names
// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
export 'messages.pb.dart';

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