mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 22:08:40 +00:00
Compare commits
47 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
944fc1eb6c | ||
|
|
b1802111f5 | ||
|
|
52952babfc | ||
|
|
085702c0bb | ||
|
|
285859cee6 | ||
|
|
2249c63c2f | ||
|
|
772ec8aff1 | ||
|
|
e9fcfbefd9 | ||
|
|
5b2e91964f | ||
|
|
70fbf6abbb | ||
|
|
e9c5d49938 | ||
|
|
13f62934b7 | ||
|
|
36e309d58a | ||
|
|
d2b881e281 | ||
|
|
585f577f89 | ||
|
|
ad0ef841cc | ||
|
|
e97f0a910f | ||
|
|
6b353d8a66 | ||
|
|
24f45ce9bd | ||
|
|
1f8bdaa32d | ||
|
|
d067a3c931 | ||
|
|
b3c25dd160 | ||
|
|
3899c8e6e4 | ||
|
|
87187843fa | ||
|
|
ebf53a5ab4 | ||
|
|
6a104e9468 | ||
|
|
ea68dcaf1c | ||
|
|
4b5a4387d1 | ||
|
|
85d6bdfcc9 | ||
|
|
41dfd54e81 | ||
|
|
20a2d61751 | ||
|
|
57c73a86ac | ||
|
|
230809290a | ||
|
|
0984eaf347 | ||
|
|
b093a7acdb | ||
|
|
6dc9aa10bc | ||
|
|
11aa4c4202 | ||
|
|
987a55dc65 | ||
|
|
910f5f79fa | ||
|
|
27483bccd6 | ||
|
|
abd689f1fa | ||
|
|
027871290d | ||
|
|
82f4c9af9f | ||
|
|
7007e7b063 | ||
|
|
333f033993 | ||
|
|
e17e39ef41 | ||
|
|
b9bb074ba6 |
158 changed files with 12815 additions and 2457 deletions
4
.gitmodules
vendored
4
.gitmodules
vendored
|
|
@ -2,3 +2,7 @@
|
||||||
[submodule "dependencies"]
|
[submodule "dependencies"]
|
||||||
path = dependencies
|
path = dependencies
|
||||||
url = https://github.com/twonlyapp/twonly-app-dependencies.git
|
url = https://github.com/twonlyapp/twonly-app-dependencies.git
|
||||||
|
[submodule "lib/src/localization/translations"]
|
||||||
|
path = lib/src/localization/translations
|
||||||
|
# url = ssh://git@git.twonly.eu:22222/twonly/twonly-translations.git
|
||||||
|
url = https://git.twonly.eu/twonly/twonly-translations
|
||||||
|
|
|
||||||
25
CHANGELOG.md
25
CHANGELOG.md
|
|
@ -1,5 +1,30 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.0.83
|
||||||
|
|
||||||
|
- Improved view of the diagnostic log
|
||||||
|
- Several bug fixes
|
||||||
|
|
||||||
|
## 0.0.82
|
||||||
|
|
||||||
|
- Added an option in the settings to automatically save all sent images
|
||||||
|
- Hides duplicate images in the memory
|
||||||
|
- Fixes a bug where messages were not being received
|
||||||
|
- Several other minor improvements
|
||||||
|
|
||||||
|
## 0.0.81
|
||||||
|
|
||||||
|
- Fixes the issue where black/blank images were sometimes received
|
||||||
|
- Fixes an issue in the image editor
|
||||||
|
|
||||||
|
## 0.0.80
|
||||||
|
|
||||||
|
- Share images/videos directly from other applications
|
||||||
|
- More customization options in the appearance settings
|
||||||
|
- Improved UI for changing the display time of images
|
||||||
|
- Several minor UI improvements
|
||||||
|
- Several bug fixes
|
||||||
|
|
||||||
## 0.0.74
|
## 0.0.74
|
||||||
|
|
||||||
- Improving uploading speed
|
- Improving uploading speed
|
||||||
|
|
|
||||||
24
README.md
24
README.md
|
|
@ -4,20 +4,35 @@
|
||||||
|
|
||||||
This repository contains the complete source code of the [twonly](https://twonly.eu) apps.
|
This repository contains the complete source code of the [twonly](https://twonly.eu) apps.
|
||||||
|
|
||||||
<a href="https://testflight.apple.com/join/U9B3v2rk" >
|
<!-- <a href="https://testflight.apple.com/join/U9B3v2rk" >
|
||||||
<img alt="Get it on Testflight button" src="https://twonly.eu/assets/buttons/get-it-on-testflight.png"
|
<img alt="Get it on Testflight button" src="https://twonly.eu/assets/buttons/get-it-on-testflight.png"
|
||||||
width="100px" />
|
width="100px" />
|
||||||
|
</a> -->
|
||||||
|
<div class="my-5 space-x-4">
|
||||||
|
<div class="flex gap-5 items-center justify-center">
|
||||||
|
<a href="https://apps.apple.com/de/app/twonly/id6743774441">
|
||||||
|
<img alt="Get it on App Store button" src="https://twonly.eu/assets/buttons/download-on-the-app-store.svg"
|
||||||
|
width="100px" />
|
||||||
|
</a>
|
||||||
|
<a href="https://play.google.com/store/apps/details?id=eu.twonly">
|
||||||
|
<img alt="Get it on Google-Play button" src="https://twonly.eu/assets/buttons/get-it-in-google-play.webp"
|
||||||
|
width="110px" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/twonlyapp/twonly-app/releases">
|
||||||
|
<img alt="Get it on Github button" src="https://twonly.eu/assets/buttons/get-it-on-github.webp" width="110px" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://releases.twonly.eu/fdroid/repo/">
|
<a href="https://releases.twonly.eu/fdroid/repo/">
|
||||||
<img alt="Get it on F-Droid button" src="https://twonly.eu/assets/buttons/get-it-on-f-droid.webp" width="100px" />
|
<img alt="Get it on F-Droid button" src="https://twonly.eu/assets/buttons/get-it-on-f-droid.webp" width="105px" />
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Offer a Snapchat™ like experience
|
- Offer a Snapchat™ like experience
|
||||||
- End-to-End encryption using the [Signal Protocol](https://de.wikipedia.org/wiki/Signal-Protokoll)
|
- 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
|
- 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
|
- No email or phone number required to register
|
||||||
- Privacy friendly - Everything is stored on the device
|
- Privacy friendly - Everything is stored on the device
|
||||||
- The backend is hosted exclusively in Europe
|
- The backend is hosted exclusively in Europe
|
||||||
|
|
@ -29,6 +44,7 @@ This repository contains the complete source code of the [twonly](https://twonly
|
||||||
- Implementing [Sealed Sender](https://signal.org/blog/sealed-sender/) to minimize metadata
|
- Implementing [Sealed Sender](https://signal.org/blog/sealed-sender/) to minimize metadata
|
||||||
|
|
||||||
## Security Issues
|
## Security Issues
|
||||||
|
|
||||||
If you discover a security issue in twonly, please adhere to the coordinated vulnerability disclosure model. Please send
|
If you discover a security issue in twonly, please adhere to the coordinated vulnerability disclosure model. Please send
|
||||||
us your report to security@twonly.eu. We also offer for critical security issues a small bug bounties, but we can not
|
us your report to security@twonly.eu. We also offer for critical security issues a small bug bounties, but we can not
|
||||||
guarantee a bounty currently :/
|
guarantee a bounty currently :/
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,16 @@
|
||||||
<data android:scheme="http" android:host="me.twonly.eu" />
|
<data android:scheme="http" android:host="me.twonly.eu" />
|
||||||
<data android:scheme="https" />
|
<data android:scheme="https" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="image/*" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="video/*" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
|
@ -46,19 +56,11 @@
|
||||||
android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
|
android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
|
||||||
tools:node="remove">
|
tools:node="remove">
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- <service
|
|
||||||
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
|
|
||||||
android:foregroundServiceType="dataSync|remoteMessaging"
|
|
||||||
android:exported="false" /> -->
|
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="eu.twonly.service.TWONLY_LOGO"
|
android:name="eu.twonly.service.TWONLY_LOGO"
|
||||||
android:resource="@drawable/ic_launcher_foreground" />
|
android:resource="@drawable/ic_launcher_foreground" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
|
|
|
||||||
1
assets/animated_icons/alarm-clock.json
Normal file
1
assets/animated_icons/alarm-clock.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/ant.json
Normal file
1
assets/animated_icons/ant.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/automobile.json
Normal file
1
assets/animated_icons/automobile.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/beating-heart.json
Normal file
1
assets/animated_icons/beating-heart.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/bee.json
Normal file
1
assets/animated_icons/bee.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/burrito.json
Normal file
1
assets/animated_icons/burrito.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/cockroach.json
Normal file
1
assets/animated_icons/cockroach.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/crocodile.json
Normal file
1
assets/animated_icons/crocodile.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/crying-cat-face.json
Normal file
1
assets/animated_icons/crying-cat-face.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/fly.json
Normal file
1
assets/animated_icons/fly.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/guide-dog.json
Normal file
1
assets/animated_icons/guide-dog.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/heart-eyes-cat.json
Normal file
1
assets/animated_icons/heart-eyes-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/heart-grow.json
Normal file
1
assets/animated_icons/heart-grow.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/joy-cat.json
Normal file
1
assets/animated_icons/joy-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/kissing-cat.json
Normal file
1
assets/animated_icons/kissing-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/kissing-smiling-eyes.json
Normal file
1
assets/animated_icons/kissing-smiling-eyes.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/lady-bug.json
Normal file
1
assets/animated_icons/lady-bug.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/leg-mechanical.json
Normal file
1
assets/animated_icons/leg-mechanical.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/leg.json
Normal file
1
assets/animated_icons/leg.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/lizard.json
Normal file
1
assets/animated_icons/lizard.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/lobster.json
Normal file
1
assets/animated_icons/lobster.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/monkey.json
Normal file
1
assets/animated_icons/monkey.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/neutral-face.json
Normal file
1
assets/animated_icons/neutral-face.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/palms-up.json
Normal file
1
assets/animated_icons/palms-up.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/peacock.json
Normal file
1
assets/animated_icons/peacock.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/pouting-cat.json
Normal file
1
assets/animated_icons/pouting-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/rainbow.json
Normal file
1
assets/animated_icons/rainbow.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/revolving-hearts.json
Normal file
1
assets/animated_icons/revolving-hearts.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/scorpion.json
Normal file
1
assets/animated_icons/scorpion.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/scream-cat.json
Normal file
1
assets/animated_icons/scream-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/seal.json
Normal file
1
assets/animated_icons/seal.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/shark.json
Normal file
1
assets/animated_icons/shark.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/smile-cat.json
Normal file
1
assets/animated_icons/smile-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/smiley-cat.json
Normal file
1
assets/animated_icons/smiley-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/smirk-cat.json
Normal file
1
assets/animated_icons/smirk-cat.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/taxi.json
Normal file
1
assets/animated_icons/taxi.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/tiger.json
Normal file
1
assets/animated_icons/tiger.json
Normal file
File diff suppressed because one or more lines are too long
1
assets/animated_icons/volcano.json
Normal file
1
assets/animated_icons/volcano.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
||||||
Subproject commit fb66274bf729cde6f7184ec6f7f9ea89f12450fd
|
Subproject commit 7930d9727019344238297d810661bc3e8f724c37
|
||||||
|
|
@ -43,6 +43,13 @@ target 'Runner' do
|
||||||
target 'RunnerTests' do
|
target 'RunnerTests' do
|
||||||
inherit! :search_paths
|
inherit! :search_paths
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Share Extension is name of Extension which you created which is in this case 'Share Extension'
|
||||||
|
target 'ShareExtension' do
|
||||||
|
inherit! :search_paths
|
||||||
|
# flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,8 @@ PODS:
|
||||||
- flutter_secure_storage_darwin (10.0.0):
|
- flutter_secure_storage_darwin (10.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- flutter_sharing_intent (1.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_volume_controller (0.0.1):
|
- flutter_volume_controller (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
|
|
@ -260,7 +262,7 @@ PODS:
|
||||||
- nanopb/encode (= 3.30910.0)
|
- nanopb/encode (= 3.30910.0)
|
||||||
- nanopb/decode (3.30910.0)
|
- nanopb/decode (3.30910.0)
|
||||||
- nanopb/encode (3.30910.0)
|
- nanopb/encode (3.30910.0)
|
||||||
- "no_screenshot (0.0.1+4)":
|
- no_screenshot (0.3.2-beta.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
- ScreenProtectorKit (~> 1.3.1)
|
- ScreenProtectorKit (~> 1.3.1)
|
||||||
- objective_c (0.0.1):
|
- objective_c (0.0.1):
|
||||||
|
|
@ -350,6 +352,7 @@ DEPENDENCIES:
|
||||||
- flutter_keyboard_visibility_temp_fork (from `.symlinks/plugins/flutter_keyboard_visibility_temp_fork/ios`)
|
- 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_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
||||||
|
- flutter_sharing_intent (from `.symlinks/plugins/flutter_sharing_intent/ios`)
|
||||||
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
||||||
- gal (from `.symlinks/plugins/gal/darwin`)
|
- gal (from `.symlinks/plugins/gal/darwin`)
|
||||||
- google_mlkit_barcode_scanning (from `.symlinks/plugins/google_mlkit_barcode_scanning/ios`)
|
- google_mlkit_barcode_scanning (from `.symlinks/plugins/google_mlkit_barcode_scanning/ios`)
|
||||||
|
|
@ -441,6 +444,8 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
flutter_secure_storage_darwin:
|
flutter_secure_storage_darwin:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
||||||
|
flutter_sharing_intent:
|
||||||
|
:path: ".symlinks/plugins/flutter_sharing_intent/ios"
|
||||||
flutter_volume_controller:
|
flutter_volume_controller:
|
||||||
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
||||||
gal:
|
gal:
|
||||||
|
|
@ -507,7 +512,8 @@ SPEC CHECKSUMS:
|
||||||
flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1
|
flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1
|
||||||
flutter_keyboard_visibility_temp_fork: 95b2d534bacf6ac62e7fcbe5c2a9e2c2a17ce06f
|
flutter_keyboard_visibility_temp_fork: 95b2d534bacf6ac62e7fcbe5c2a9e2c2a17ce06f
|
||||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||||
flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468
|
flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23
|
||||||
|
flutter_sharing_intent: 0c1e53949f09fa8df8ac2268505687bde8ff264c
|
||||||
flutter_volume_controller: c2be490cb0487e8b88d0d9fc2b7e1c139a4ebccb
|
flutter_volume_controller: c2be490cb0487e8b88d0d9fc2b7e1c139a4ebccb
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
google_mlkit_barcode_scanning: 8f5987f244a43fe1167689c548342a5174108159
|
google_mlkit_barcode_scanning: 8f5987f244a43fe1167689c548342a5174108159
|
||||||
|
|
@ -529,7 +535,7 @@ SPEC CHECKSUMS:
|
||||||
MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d
|
MLKitCommon: 07c2c33ae5640e5380beaaa6e4b9c249a205542d
|
||||||
MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e
|
MLKitVision: 45e79d68845a2de77e2dd4d7f07947f0ed157b0e
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
no_screenshot: 6d183496405a3ab709a67a54e5cd0f639e94729e
|
no_screenshot: 89e778ede9f1e39cc3fb9404d782a42712f2a0b2
|
||||||
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||||
|
|
@ -551,6 +557,6 @@ SPEC CHECKSUMS:
|
||||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
||||||
|
|
||||||
PODFILE CHECKSUM: c0c524475498435108850efecde62ba98e081c25
|
PODFILE CHECKSUM: ae041999f13ba7b2285ff9ad9bc688ed647bbcb7
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
05CF222065FC24670B05B6D0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */; };
|
05CF222065FC24670B05B6D0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */; };
|
||||||
06AA21445BEAF2C45DC9DCDF /* Pods_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */; };
|
06AA21445BEAF2C45DC9DCDF /* Pods_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */; };
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
30EBDD0F93DC44E774F3B785 /* Pods_ShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E190E82D9973B318A389650B /* Pods_ShareExtension.framework */; };
|
||||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
|
@ -19,6 +20,7 @@
|
||||||
CA4FDF5DD8F229C30DE512AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */; };
|
CA4FDF5DD8F229C30DE512AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */; };
|
||||||
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D21FCEA42D9F2B750088701D /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D21FCEA42D9F2B750088701D /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
D25D4D1E2EF626E30029F805 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D25D4D1D2EF626E30029F805 /* StoreKit.framework */; };
|
D25D4D1E2EF626E30029F805 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D25D4D1D2EF626E30029F805 /* StoreKit.framework */; };
|
||||||
|
D25D4D7A2EFF41DB0029F805 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D25D4D702EFF41DB0029F805 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
F3C66D726A2EB28484DF0B10 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */; };
|
F3C66D726A2EB28484DF0B10 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
|
@ -37,6 +39,13 @@
|
||||||
remoteGlobalIDString = D21FCEA32D9F2B750088701D;
|
remoteGlobalIDString = D21FCEA32D9F2B750088701D;
|
||||||
remoteInfo = NotificationService;
|
remoteInfo = NotificationService;
|
||||||
};
|
};
|
||||||
|
D25D4D782EFF41DB0029F805 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = D25D4D6F2EFF41DB0029F805;
|
||||||
|
remoteInfo = ShareExtension;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
|
@ -56,6 +65,7 @@
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
|
D25D4D7A2EFF41DB0029F805 /* ShareExtension.appex in Embed Foundation Extensions */,
|
||||||
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */,
|
D21FCEAB2D9F2B750088701D /* NotificationService.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
name = "Embed Foundation Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
|
|
@ -67,10 +77,12 @@
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
1581CC44342D555EFB889768 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
1581CC44342D555EFB889768 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
15CEF849B61A620CFB2DC5F1 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
39FB86A38393489D58A01B0B /* Pods-ShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
6EB462F87F0A23758713308F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
6EB462F87F0A23758713308F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
|
@ -87,11 +99,15 @@
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
A22BD564F16069E5FCB60767 /* Pods-ShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.release.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
B3B27B7FBEEA31DB7793A0C2 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
B3B27B7FBEEA31DB7793A0C2 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
D21FCEA42D9F2B750088701D /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
D21FCEA42D9F2B750088701D /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D2265DD42D920142000D99BB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
D2265DD42D920142000D99BB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
D25D4D1D2EF626E30029F805 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
D25D4D1D2EF626E30029F805 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
|
||||||
|
D25D4D702EFF41DB0029F805 /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
D25D4D802EFF437F0029F805 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = "<group>"; };
|
||||||
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
E190E82D9973B318A389650B /* Pods_ShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
E96A5ACA32A7118204F050A5 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
E96A5ACA32A7118204F050A5 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.profile.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.profile.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
|
@ -105,6 +121,13 @@
|
||||||
);
|
);
|
||||||
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
||||||
};
|
};
|
||||||
|
D25D4D7E2EFF41DB0029F805 /* Exceptions for "ShareExtension" folder in "ShareExtension" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = D25D4D6F2EFF41DB0029F805 /* ShareExtension */;
|
||||||
|
};
|
||||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
@ -116,6 +139,14 @@
|
||||||
path = NotificationService;
|
path = NotificationService;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D25D4D712EFF41DB0029F805 /* ShareExtension */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
D25D4D7E2EFF41DB0029F805 /* Exceptions for "ShareExtension" folder in "ShareExtension" target */,
|
||||||
|
);
|
||||||
|
path = ShareExtension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -144,6 +175,14 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D25D4D6D2EFF41DB0029F805 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
30EBDD0F93DC44E774F3B785 /* Pods_ShareExtension.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
|
@ -172,6 +211,7 @@
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
D21FCEA52D9F2B750088701D /* NotificationService */,
|
D21FCEA52D9F2B750088701D /* NotificationService */,
|
||||||
|
D25D4D712EFF41DB0029F805 /* ShareExtension */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */,
|
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */,
|
||||||
|
|
@ -186,6 +226,7 @@
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||||
D21FCEA42D9F2B750088701D /* NotificationService.appex */,
|
D21FCEA42D9F2B750088701D /* NotificationService.appex */,
|
||||||
|
D25D4D702EFF41DB0029F805 /* ShareExtension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -193,6 +234,7 @@
|
||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D25D4D802EFF437F0029F805 /* RunnerDebug.entitlements */,
|
||||||
D2265DD42D920142000D99BB /* Runner.entitlements */,
|
D2265DD42D920142000D99BB /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
|
|
@ -213,6 +255,7 @@
|
||||||
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */,
|
A198C9B5D90584C4F96206B2 /* Pods_NotificationService.framework */,
|
||||||
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */,
|
EE2CCFEE4ABECF33852F7735 /* Pods_Runner.framework */,
|
||||||
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */,
|
DC1EE71614E1B4F84D6FDC2D /* Pods_RunnerTests.framework */,
|
||||||
|
E190E82D9973B318A389650B /* Pods_ShareExtension.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -229,6 +272,9 @@
|
||||||
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */,
|
4D78471482626812FE2468E9 /* Pods-NotificationService.debug.xcconfig */,
|
||||||
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */,
|
35366FD433E0EFC6EF19A452 /* Pods-NotificationService.release.xcconfig */,
|
||||||
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */,
|
F02F7A1D63544AA9F23A1085 /* Pods-NotificationService.profile.xcconfig */,
|
||||||
|
15CEF849B61A620CFB2DC5F1 /* Pods-ShareExtension.debug.xcconfig */,
|
||||||
|
A22BD564F16069E5FCB60767 /* Pods-ShareExtension.release.xcconfig */,
|
||||||
|
39FB86A38393489D58A01B0B /* Pods-ShareExtension.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -274,6 +320,7 @@
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
D21FCEAA2D9F2B750088701D /* PBXTargetDependency */,
|
D21FCEAA2D9F2B750088701D /* PBXTargetDependency */,
|
||||||
|
D25D4D792EFF41DB0029F805 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Runner;
|
name = Runner;
|
||||||
productName = Runner;
|
productName = Runner;
|
||||||
|
|
@ -301,6 +348,27 @@
|
||||||
productReference = D21FCEA42D9F2B750088701D /* NotificationService.appex */;
|
productReference = D21FCEA42D9F2B750088701D /* NotificationService.appex */;
|
||||||
productType = "com.apple.product-type.app-extension";
|
productType = "com.apple.product-type.app-extension";
|
||||||
};
|
};
|
||||||
|
D25D4D6F2EFF41DB0029F805 /* ShareExtension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = D25D4D7F2EFF41DB0029F805 /* Build configuration list for PBXNativeTarget "ShareExtension" */;
|
||||||
|
buildPhases = (
|
||||||
|
627F39EA1643E08048D23996 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
D25D4D6C2EFF41DB0029F805 /* Sources */,
|
||||||
|
D25D4D6D2EFF41DB0029F805 /* Frameworks */,
|
||||||
|
D25D4D6E2EFF41DB0029F805 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
D25D4D712EFF41DB0029F805 /* ShareExtension */,
|
||||||
|
);
|
||||||
|
name = ShareExtension;
|
||||||
|
productName = ShareExtension;
|
||||||
|
productReference = D25D4D702EFF41DB0029F805 /* ShareExtension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
|
|
@ -308,7 +376,7 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = YES;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
LastSwiftUpdateCheck = 1620;
|
LastSwiftUpdateCheck = 2610;
|
||||||
LastUpgradeCheck = 1510;
|
LastUpgradeCheck = 1510;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
|
@ -323,6 +391,9 @@
|
||||||
D21FCEA32D9F2B750088701D = {
|
D21FCEA32D9F2B750088701D = {
|
||||||
CreatedOnToolsVersion = 16.2;
|
CreatedOnToolsVersion = 16.2;
|
||||||
};
|
};
|
||||||
|
D25D4D6F2EFF41DB0029F805 = {
|
||||||
|
CreatedOnToolsVersion = 26.1.1;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||||
|
|
@ -341,6 +412,7 @@
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||||
D21FCEA32D9F2B750088701D /* NotificationService */,
|
D21FCEA32D9F2B750088701D /* NotificationService */,
|
||||||
|
D25D4D6F2EFF41DB0029F805 /* ShareExtension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
@ -372,6 +444,13 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D25D4D6E2EFF41DB0029F805 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
|
@ -452,6 +531,28 @@
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
|
||||||
};
|
};
|
||||||
|
627F39EA1643E08048D23996 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-ShareExtension-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
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;
|
||||||
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
|
|
@ -533,6 +634,13 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D25D4D6C2EFF41DB0029F805 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
|
@ -546,6 +654,11 @@
|
||||||
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
target = D21FCEA32D9F2B750088701D /* NotificationService */;
|
||||||
targetProxy = D21FCEA92D9F2B750088701D /* PBXContainerItemProxy */;
|
targetProxy = D21FCEA92D9F2B750088701D /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
D25D4D792EFF41DB0029F805 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = D25D4D6F2EFF41DB0029F805 /* ShareExtension */;
|
||||||
|
targetProxy = D25D4D782EFF41DB0029F805 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
|
@ -631,6 +744,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
DEVELOPMENT_TEAM = CN332ZUGRP;
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -827,8 +941,9 @@
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
DEVELOPMENT_TEAM = CN332ZUGRP;
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -863,6 +978,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
DEVELOPMENT_TEAM = CN332ZUGRP;
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|
@ -1004,6 +1120,133 @@
|
||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
D25D4D7B2EFF41DB0029F805 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 15CEF849B61A620CFB2DC5F1 /* Pods-ShareExtension.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtensionDebug.entitlements;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 26.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = eu.twonly.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
D25D4D7C2EFF41DB0029F805 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A22BD564F16069E5FCB60767 /* Pods-ShareExtension.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 26.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = eu.twonly.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
D25D4D7D2EFF41DB0029F805 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 39FB86A38393489D58A01B0B /* Pods-ShareExtension.profile.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
CUSTOM_GROUP_ID = group.eu.twonly.shareIntent;
|
||||||
|
DEVELOPMENT_TEAM = CN332ZUGRP;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 26.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = eu.twonly.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
|
@ -1047,6 +1290,16 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
D25D4D7F2EFF41DB0029F805 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
D25D4D7B2EFF41DB0029F805 /* Debug */,
|
||||||
|
D25D4D7C2EFF41DB0029F805 /* Release */,
|
||||||
|
D25D4D7D2EFF41DB0029F805 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import Flutter
|
||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import UserNotifications
|
import UserNotifications
|
||||||
|
import flutter_sharing_intent
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
||||||
|
|
@ -14,6 +15,17 @@ import UserNotifications
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
||||||
|
|
||||||
|
let sharingIntent = SwiftFlutterSharingIntentPlugin.instance
|
||||||
|
if sharingIntent.hasSameSchemePrefix(url: url) {
|
||||||
|
return sharingIntent.application(app, open: url, options: options)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed url handling for other Flutter libraries like app_links
|
||||||
|
return super.application(app, open: url, options:options)
|
||||||
|
}
|
||||||
|
|
||||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,21 @@
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<!--Disable Firebase Telemetry-->
|
|
||||||
<key>firebase_performance_collection_deactivated</key>
|
<key>firebase_performance_collection_deactivated</key>
|
||||||
<true/>
|
<true/>
|
||||||
<!--...-->
|
|
||||||
|
<key>AppGroupId</key>
|
||||||
|
<string>$(CUSTOM_GROUP_ID)</string>
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>SharingMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
20
ios/Runner/RunnerDebug.entitlements
Normal file
20
ios/Runner/RunnerDebug.entitlements
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>development</string>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:me.twonly.eu</string>
|
||||||
|
</array>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.eu.twonly.shareIntent</string>
|
||||||
|
</array>
|
||||||
|
<key>keychain-access-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>$(AppIdentifierPrefix)eu.twonly.shared</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
24
ios/ShareExtension/Base.lproj/MainInterface.storyboard
Normal file
24
ios/ShareExtension/Base.lproj/MainInterface.storyboard
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Share View Controller-->
|
||||||
|
<scene sceneID="ceB-am-kn3">
|
||||||
|
<objects>
|
||||||
|
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
553
ios/ShareExtension/FSIShareViewController.swift
Normal file
553
ios/ShareExtension/FSIShareViewController.swift
Normal file
|
|
@ -0,0 +1,553 @@
|
||||||
|
// SOURCE: https://github.com/bhagat-techind/flutter_sharing_intent/blob/main/example/ios/Share%20Extension/FSIShareViewController.swift
|
||||||
|
|
||||||
|
// FSIShareViewController.swift
|
||||||
|
// Merged, optimized controller: uses RSI architecture with all FSI features preserved
|
||||||
|
// Uses model name `SharingFile` (same fields as SharedMediaFile) where `value` = path
|
||||||
|
|
||||||
|
import AVFoundation
|
||||||
|
import MobileCoreServices
|
||||||
|
import Social
|
||||||
|
import UIKit
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
|
public let kSchemePrefix = "SharingMedia"
|
||||||
|
public let kUserDefaultsKey = "SharingKey"
|
||||||
|
public let kUserDefaultsMessageKey = "SharingMessageKey"
|
||||||
|
public let kAppGroupIdKey = "AppGroupId"
|
||||||
|
public let kAppChannel = "flutter_sharing_intent"
|
||||||
|
|
||||||
|
@available(swift, introduced: 5.0)
|
||||||
|
open class FSIShareViewController: SLComposeServiceViewController {
|
||||||
|
// MARK: - Config
|
||||||
|
private(set) var hostAppBundleIdentifier: String = ""
|
||||||
|
private(set) var appGroupId: String = ""
|
||||||
|
|
||||||
|
// Results
|
||||||
|
private var sharedMedia: [SharingFile] = []
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
private let debugLogs = false
|
||||||
|
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
open override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
loadIds()
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func isContentValid() -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func didSelectPost() {
|
||||||
|
if self.sharedMedia.isEmpty {
|
||||||
|
if let text = self.contentText, !text.isEmpty {
|
||||||
|
self.sharedMedia.append(
|
||||||
|
SharingFile(value: text, thumbnail: nil, duration: nil, type: .text)
|
||||||
|
)
|
||||||
|
self.saveAndRedirect(message: text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.completeAndExit()
|
||||||
|
} else {
|
||||||
|
self.saveAndRedirect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
// Process attachments automatically on appear like original FSI
|
||||||
|
processAttachments()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Load Ids
|
||||||
|
private func loadIds() {
|
||||||
|
let shareExtId = Bundle.main.bundleIdentifier ?? ""
|
||||||
|
if let idx = shareExtId.lastIndex(of: ".") {
|
||||||
|
hostAppBundleIdentifier = String(shareExtId[..<idx])
|
||||||
|
} else {
|
||||||
|
hostAppBundleIdentifier = shareExtId
|
||||||
|
}
|
||||||
|
let custom = Bundle.main.object(forInfoDictionaryKey: kAppGroupIdKey) as? String
|
||||||
|
appGroupId = custom ?? "group.\(hostAppBundleIdentifier)"
|
||||||
|
log("loaded host=\(hostAppBundleIdentifier) group=\(appGroupId)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Attachment processing (clean RSI style, preserve FSI features)
|
||||||
|
private func processAttachments() {
|
||||||
|
guard let content = extensionContext?.inputItems.first as? NSExtensionItem else {
|
||||||
|
completeAndExit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let attachments = content.attachments, !attachments.isEmpty else {
|
||||||
|
completeAndExit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use DispatchGroup to wait for async loads
|
||||||
|
let group = DispatchGroup()
|
||||||
|
for (index, provider) in attachments.enumerated() {
|
||||||
|
group.enter()
|
||||||
|
// Try all SharedMediaType options similar to RSI but preserve explicit FSI order
|
||||||
|
if provider.isImage {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.image, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleImageItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isMovie {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.movie, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleVideoItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isFile {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.fileURL, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleFileItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isURL {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.url, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleUrlItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isText {
|
||||||
|
let id = provider.hasItemConformingToTypeIdentifier(UType.plainText)
|
||||||
|
? UType.plainText
|
||||||
|
: UType.text
|
||||||
|
provider.loadItem(forTypeIdentifier: id, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleTextItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isData {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.data, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleFileItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.isItem {
|
||||||
|
provider.loadItem(forTypeIdentifier: UType.item, options: nil) { [weak self] data, error in
|
||||||
|
defer { group.leave() }
|
||||||
|
guard let self = self, error == nil else { self?.dismissWithError(); return }
|
||||||
|
self.handleFileItem(data: data, index: index, total: attachments.count)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log("Unknown provider type: \(provider.registeredTypeIdentifiers)")
|
||||||
|
|
||||||
|
// Unknown type: just leave
|
||||||
|
group.leave()
|
||||||
|
}
|
||||||
|
|
||||||
|
group.notify(queue: .main) { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
// if we have media -> media, else fallback to complete
|
||||||
|
if !self.sharedMedia.isEmpty {
|
||||||
|
self.saveAndRedirect()
|
||||||
|
} else {
|
||||||
|
print("FSIShare: No shared media → stopping.")
|
||||||
|
self.completeAndExit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Individual handlers (preserve FSI behavior)
|
||||||
|
private func handleTextItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let s = data as? String {
|
||||||
|
sharedMedia.append(SharingFile(value: s, thumbnail: nil, duration: nil, type: .text))
|
||||||
|
} else if let url = data as? URL {
|
||||||
|
sharedMedia.append(SharingFile(value: url.absoluteString, thumbnail: nil, duration: nil, type: .url))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleUrlItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let url = data as? URL {
|
||||||
|
sharedMedia.append(SharingFile(value: url.absoluteString, thumbnail: nil, duration: nil, type: .url))
|
||||||
|
} else if let s = data as? String {
|
||||||
|
sharedMedia.append(SharingFile(value: s, thumbnail: nil, duration: nil, type: .text))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleImageItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
// data can be URL, UIImage, or Data
|
||||||
|
if let url = data as? URL {
|
||||||
|
let filename = getFileName(from: url, type: .image)
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
if copyFile(at: url, to: dst) {
|
||||||
|
sharedMedia.append(SharingFile(value: dst.absoluteString, mimeType: url.mimeType(), thumbnail: nil, duration: nil, type: .image))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let img = data as? UIImage {
|
||||||
|
if let saved = writeTempImage(img) {
|
||||||
|
sharedMedia.append(saved)
|
||||||
|
}
|
||||||
|
} else if let raw = data as? Data, let img = UIImage(data: raw) {
|
||||||
|
if let saved = writeTempImage(img) {
|
||||||
|
sharedMedia.append(saved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleVideoItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let url = data as? URL {
|
||||||
|
let filename = getFileName(from: url, type: .video)
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
if copyFile(at: url, to: dst) {
|
||||||
|
if let m = getSharedMediaFile(forVideo: dst) {
|
||||||
|
sharedMedia.append(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleFileItem(data: NSSecureCoding?, index: Int, total: Int) {
|
||||||
|
if let url = data as? URL {
|
||||||
|
let filename = getFileName(from: url, type: .file)
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
if copyFile(at: url, to: dst) {
|
||||||
|
sharedMedia.append(SharingFile(value: dst.absoluteString, mimeType: url.mimeType(), thumbnail: nil, duration: nil, type: .file))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if let raw = data as? Data {
|
||||||
|
let filename = "File_\(UUID().uuidString)"
|
||||||
|
if let dst = containerURL()?.appendingPathComponent(filename) {
|
||||||
|
do {
|
||||||
|
try raw.write(to: dst)
|
||||||
|
sharedMedia.append(SharingFile(value: dst.absoluteString, mimeType: "application/octet-stream", thumbnail: nil, duration: nil, type: .file))
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers: write temp image
|
||||||
|
private func writeTempImage(_ image: UIImage) -> SharingFile? {
|
||||||
|
guard let container = containerURL() else { return nil }
|
||||||
|
let tempName = "TempImage_\(UUID().uuidString).png"
|
||||||
|
let dst = container.appendingPathComponent(tempName)
|
||||||
|
do {
|
||||||
|
if let d = image.pngData() {
|
||||||
|
try d.write(to: dst)
|
||||||
|
let decoded = dst.absoluteString.removingPercentEncoding ?? dst.absoluteString
|
||||||
|
return SharingFile(value: decoded, mimeType: "image/png", thumbnail: nil, duration: nil, type: .image)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
log("writeTempImage error: \(error)")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func saveAndRedirect(message: String? = nil) {
|
||||||
|
let ud = UserDefaults(suiteName: appGroupId)
|
||||||
|
if !sharedMedia.isEmpty {
|
||||||
|
if let data = try? JSONEncoder().encode(sharedMedia) {
|
||||||
|
ud?.set(data, forKey: kUserDefaultsKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ud?.set(message, forKey: kUserDefaultsMessageKey)
|
||||||
|
ud?.synchronize()
|
||||||
|
redirectToHostApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func redirectToHostApp() {
|
||||||
|
// kept for compatibility (RSI style)
|
||||||
|
loadIds()
|
||||||
|
// let raw = "\(kSchemePrefix)-\(hostAppBundleIdentifier):share"
|
||||||
|
let raw = "\(kSchemePrefix)-\(hostAppBundleIdentifier)://dataUrl=\(kUserDefaultsKey)"
|
||||||
|
guard let url = URL(string: raw.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? raw) else { completeAndExit(); return }
|
||||||
|
|
||||||
|
var responder: UIResponder? = self
|
||||||
|
if #available(iOS 18.0, *) {
|
||||||
|
while responder != nil {
|
||||||
|
if let app = responder as? UIApplication { app.open(url, options: [:], completionHandler: nil) }
|
||||||
|
responder = responder?.next
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let sel = sel_registerName("openURL:")
|
||||||
|
while responder != nil {
|
||||||
|
if responder?.responds(to: sel) ?? false { _ = responder?.perform(sel, with: url) }
|
||||||
|
responder = responder?.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - File / thumbnail / metadata helpers
|
||||||
|
func getExtension(from url: URL, type: SharingFileType) -> String {
|
||||||
|
let parts = url.lastPathComponent.components(separatedBy: ".")
|
||||||
|
var ex: String? = nil
|
||||||
|
if parts.count > 1 { ex = parts.last }
|
||||||
|
if ex == nil {
|
||||||
|
switch type {
|
||||||
|
case .image: ex = "png"
|
||||||
|
case .video: ex = "mp4"
|
||||||
|
case .file: ex = "txt"
|
||||||
|
case .text: ex = "txt"
|
||||||
|
case .url: ex = "txt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ex ?? "bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileName(from url: URL, type: SharingFileType) -> String {
|
||||||
|
var name = url.lastPathComponent
|
||||||
|
if name.isEmpty { name = UUID().uuidString + "." + getExtension(from: url, type: type) }
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFile(at srcURL: URL, to dstURL: URL) -> Bool {
|
||||||
|
do {
|
||||||
|
if FileManager.default.fileExists(atPath: dstURL.path) { try FileManager.default.removeItem(at: dstURL) }
|
||||||
|
try FileManager.default.copyItem(at: srcURL, to: dstURL)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
log("copyFile error: \(error)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getSharedMediaFile(forVideo: URL) -> SharingFile? {
|
||||||
|
let asset = AVAsset(url: forVideo)
|
||||||
|
let duration = (CMTimeGetSeconds(asset.duration) * 1000).rounded()
|
||||||
|
let thumbnailPath = getThumbnailPath(for: forVideo)
|
||||||
|
|
||||||
|
if FileManager.default.fileExists(atPath: thumbnailPath.path) {
|
||||||
|
return SharingFile(value: forVideo.absoluteString, mimeType: forVideo.mimeType(), thumbnail: thumbnailPath.absoluteString, duration: Int(duration), type: .video)
|
||||||
|
}
|
||||||
|
|
||||||
|
let gen = AVAssetImageGenerator(asset: asset)
|
||||||
|
gen.appliesPreferredTrackTransform = true
|
||||||
|
gen.maximumSize = CGSize(width: 360, height: 360)
|
||||||
|
|
||||||
|
// Use first second or zero
|
||||||
|
let time = CMTime(seconds: min(1.0, CMTimeGetSeconds(asset.duration)), preferredTimescale: 600)
|
||||||
|
do {
|
||||||
|
let cg = try gen.copyCGImage(at: time, actualTime: nil)
|
||||||
|
if let data = UIImage(cgImage: cg).jpegData(compressionQuality: 0.8) {
|
||||||
|
try data.write(to: thumbnailPath)
|
||||||
|
return SharingFile(value: forVideo.absoluteString, mimeType: forVideo.mimeType(), thumbnail: thumbnailPath.absoluteString, duration: Int(duration), type: .video)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
log("getSharedMediaFile thumbnail error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
return SharingFile(value: forVideo.absoluteString, mimeType: forVideo.mimeType(), thumbnail: nil, duration: Int(duration), type: .video)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getThumbnailPath(for url: URL) -> URL {
|
||||||
|
guard let container = containerURL() else { fatalError("App group not configured or missing") }
|
||||||
|
let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "=", with: "")
|
||||||
|
return container.appendingPathComponent("\(fileName).jpg")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func containerURL() -> URL? {
|
||||||
|
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func completeAndExit() {
|
||||||
|
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func dismissWithError() {
|
||||||
|
log("[ERROR] Error loading data!")
|
||||||
|
let alert = UIAlertController(title: "Error", message: "Error loading data", preferredStyle: .alert)
|
||||||
|
alert.addAction(UIAlertAction(title: "OK", style: .cancel) { _ in self.dismiss(animated: true, completion: nil) })
|
||||||
|
present(alert, animated: true, completion: nil)
|
||||||
|
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func writeTempFile(_ image: UIImage, to dstURL: URL) -> Bool {
|
||||||
|
do {
|
||||||
|
if FileManager.default.fileExists(atPath: dstURL.path) { try FileManager.default.removeItem(at: dstURL) }
|
||||||
|
let pngData = image.pngData()
|
||||||
|
try pngData?.write(to: dstURL)
|
||||||
|
return true
|
||||||
|
} catch (let error) {
|
||||||
|
log("writeTempFile error: \(error)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func saveToUserDefaults(data: [SharingFile]) {
|
||||||
|
let ud = UserDefaults(suiteName: appGroupId)
|
||||||
|
if let enc = try? JSONEncoder().encode(data) { ud?.set(enc, forKey: kUserDefaultsKey); ud?.synchronize() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Logging
|
||||||
|
private func log(_ s: String) { if debugLogs { print("[FSIShareVC] \(s)") } }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Extensions
|
||||||
|
extension URL {
|
||||||
|
func mimeType() -> String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
if let ut = UTType(filenameExtension: self.pathExtension), let m = ut.preferredMIMEType { return m }
|
||||||
|
} else {
|
||||||
|
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, self.pathExtension as NSString, nil)?.takeRetainedValue() {
|
||||||
|
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() { return mimetype as String }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "application/octet-stream"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NSItemProvider {
|
||||||
|
var isImage: Bool { return hasItemConformingToTypeIdentifier(UType.image) }
|
||||||
|
var isMovie: Bool { return hasItemConformingToTypeIdentifier(UType.movie) }
|
||||||
|
var isText: Bool {
|
||||||
|
hasItemConformingToTypeIdentifier(UType.plainText) || hasItemConformingToTypeIdentifier(UType.text)
|
||||||
|
}
|
||||||
|
var isURL: Bool { return hasItemConformingToTypeIdentifier(UType.url) }
|
||||||
|
var isFile: Bool { return hasItemConformingToTypeIdentifier(UType.fileURL) }
|
||||||
|
var isData:Bool { return hasItemConformingToTypeIdentifier(UType.data) }
|
||||||
|
var isItem: Bool { hasItemConformingToTypeIdentifier(UType.item) }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Array {
|
||||||
|
subscript(safe index: UInt) -> Element? { return Int(index) < count ? self[Int(index)] : nil }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SharingFile: Codable {
|
||||||
|
var value: String
|
||||||
|
var mimeType: String?
|
||||||
|
var thumbnail: String?; // video thumbnail
|
||||||
|
var duration: Int?; // video duration in milliseconds
|
||||||
|
var type: SharingFileType;
|
||||||
|
var message: String? // post message
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case value
|
||||||
|
case mimeType
|
||||||
|
case thumbnail
|
||||||
|
case duration
|
||||||
|
case type
|
||||||
|
case message
|
||||||
|
}
|
||||||
|
|
||||||
|
init(value: String, mimeType: String? = nil, thumbnail: String?, duration: Int?,
|
||||||
|
type: SharingFileType, message: String?=nil) {
|
||||||
|
self.value = value
|
||||||
|
self.mimeType = mimeType
|
||||||
|
self.thumbnail = thumbnail
|
||||||
|
self.duration = duration
|
||||||
|
self.type = type
|
||||||
|
self.message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug method to print out SharedMediaFile details in the console
|
||||||
|
func toString() {
|
||||||
|
print("[SharingFile] \n\tvalue: \(self.value)\n\tthumbnail: \(self.thumbnail ?? "--" )\n\tduration: \(self.duration ?? 0)\n\ttype: \(self.type)\n\tmimeType: \(String(describing: self.mimeType))\n\tmessage: \(String(describing: self.message))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum SharingFileType: Int, Codable {
|
||||||
|
case text
|
||||||
|
case url
|
||||||
|
case image
|
||||||
|
case video
|
||||||
|
case file
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unified UTType → works on iOS 11–18
|
||||||
|
enum UType {
|
||||||
|
static var image: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.image.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeImage as String // old API
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var movie: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.movie.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeMovie as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static var url: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.url.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeURL as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var fileURL: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.fileURL.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeFileURL as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var text: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.text.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeText as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var plainText: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.plainText.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypePlainText as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var data: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.data.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeData as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static var item: String {
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
return UTType.item.identifier
|
||||||
|
} else {
|
||||||
|
return kUTTypeItem as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
ios/ShareExtension/Info.plist
Normal file
35
ios/ShareExtension/Info.plist
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>AppGroupId</key>
|
||||||
|
<string>$(CUSTOM_GROUP_ID)</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionMainStoryboard</key>
|
||||||
|
<string>MainInterface</string>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.share-services</string>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>PHSupportedMediaTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>Video</string>
|
||||||
|
<string>Image</string>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<key>NSExtensionActivationRule</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
10
ios/ShareExtension/ShareExtensionDebug.entitlements
Normal file
10
ios/ShareExtension/ShareExtensionDebug.entitlements
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.eu.twonly.shareIntent</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
3
ios/ShareExtension/ShareViewController.swift
Normal file
3
ios/ShareExtension/ShareViewController.swift
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
class ShareViewController: FSIShareViewController {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
arb-dir: lib/src/localization
|
arb-dir: lib/src/localization/translations
|
||||||
template-arb-file: app_en.arb
|
template-arb-file: en.arb
|
||||||
output-localization-file: app_localizations.dart
|
output-localization-file: app_localizations.dart
|
||||||
untranslated-messages-file: build/l10n.log
|
untranslated-messages-file: build/l10n.log
|
||||||
output-dir: lib/src/localization/generated
|
output-dir: lib/src/localization/generated
|
||||||
|
|
|
||||||
11
lib/app.dart
11
lib/app.dart
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
@ -93,6 +94,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
||||||
listenable: context.watch<SettingsChangeProvider>(),
|
listenable: context.watch<SettingsChangeProvider>(),
|
||||||
builder: (BuildContext context, Widget? child) {
|
builder: (BuildContext context, Widget? child) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
scaffoldMessengerKey: globalRootScaffoldMessengerKey,
|
||||||
restorationScopeId: 'app',
|
restorationScopeId: 'app',
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
AppLocalizations.delegate,
|
AppLocalizations.delegate,
|
||||||
|
|
@ -157,11 +159,13 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
bool _showOnboarding = true;
|
bool _showOnboarding = true;
|
||||||
bool _isLoaded = false;
|
bool _isLoaded = false;
|
||||||
bool _skipBackup = false;
|
bool _skipBackup = false;
|
||||||
|
int _initialPage = 0;
|
||||||
|
|
||||||
(Future<int>?, bool) _proofOfWork = (null, false);
|
(Future<int>?, bool) _proofOfWork = (null, false);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
_initialPage = widget.initialPage;
|
||||||
initAsync();
|
initAsync();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
@ -173,6 +177,9 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
if (gUser.appVersion < 62) {
|
if (gUser.appVersion < 62) {
|
||||||
_showDatabaseMigration = true;
|
_showDatabaseMigration = true;
|
||||||
}
|
}
|
||||||
|
if (!gUser.startWithCameraOpen) {
|
||||||
|
_initialPage = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_isUserCreated && !_showDatabaseMigration) {
|
if (!_isUserCreated && !_showDatabaseMigration) {
|
||||||
|
|
@ -205,7 +212,7 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
if (_showDatabaseMigration) {
|
if (_showDatabaseMigration) {
|
||||||
child = const DatabaseMigrationView();
|
child = const DatabaseMigrationView();
|
||||||
} else if (_isUserCreated) {
|
} else if (_isUserCreated) {
|
||||||
if (gUser.twonlySafeBackup == null && !_skipBackup) {
|
if (gUser.twonlySafeBackup == null && !_skipBackup && kReleaseMode) {
|
||||||
child = TwonlyIdentityBackupView(
|
child = TwonlyIdentityBackupView(
|
||||||
callBack: () {
|
callBack: () {
|
||||||
_skipBackup = true;
|
_skipBackup = true;
|
||||||
|
|
@ -214,7 +221,7 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
child = HomeView(
|
child = HomeView(
|
||||||
initialPage: widget.initialPage,
|
initialPage: _initialPage,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (_showOnboarding) {
|
} else if (_showOnboarding) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/json/userdata.dart';
|
import 'package:twonly/src/model/json/userdata.dart';
|
||||||
import 'package:twonly/src/services/api.service.dart';
|
import 'package:twonly/src/services/api.service.dart';
|
||||||
|
|
@ -37,3 +36,6 @@ bool globalAllowErrorTrackingViaSentry = false;
|
||||||
|
|
||||||
late String globalApplicationCacheDirectory;
|
late String globalApplicationCacheDirectory;
|
||||||
late String globalApplicationSupportDirectory;
|
late String globalApplicationSupportDirectory;
|
||||||
|
|
||||||
|
final GlobalKey<ScaffoldMessengerState> globalRootScaffoldMessengerKey =
|
||||||
|
GlobalKey<ScaffoldMessengerState>();
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ class ContactsDao extends DatabaseAccessor<TwonlyDB> with _$ContactsDaoMixin {
|
||||||
.watchSingleOrNull();
|
.watchSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Contact>> getAllNotBlockedContacts() {
|
Future<List<Contact>> getAllContacts() {
|
||||||
return select(contacts).get();
|
return select(contacts).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:hashlib/random.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/tables/groups.table.dart';
|
import 'package:twonly/src/database/tables/groups.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/flame.service.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
|
|
@ -278,89 +279,6 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
||||||
return query.map((row) => row.readTable(groups)).getSingleOrNull();
|
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 + 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 >= maxFlameCounter ||
|
|
||||||
maxFlameCounterFrom == null ||
|
|
||||||
maxFlameCounterFrom
|
|
||||||
.isBefore(DateTime.now().subtract(const Duration(days: 5)))) {
|
|
||||||
maxFlameCounter = flameCounter;
|
|
||||||
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() {
|
Stream<int> watchSumTotalMediaCounter() {
|
||||||
final query = selectOnly(groups)
|
final query = selectOnly(groups)
|
||||||
..addColumns([groups.totalMediaCounter.sum()]);
|
..addColumns([groups.totalMediaCounter.sum()]);
|
||||||
|
|
@ -383,23 +301,3 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
|
||||||
.write(GroupsCompanion(lastMessageExchange: Value(newLastMessage)));
|
.write(GroupsCompanion(lastMessageExchange: Value(newLastMessage)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getFlameCounterFromGroup(Group? group) {
|
|
||||||
if (group == null) return 0;
|
|
||||||
if (group.lastMessageSend == null ||
|
|
||||||
group.lastMessageReceived == null ||
|
|
||||||
group.lastFlameCounterChange == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
final now = DateTime.now();
|
|
||||||
final startOfToday = DateTime(now.year, now.month, now.day);
|
|
||||||
final twoDaysAgo = startOfToday.subtract(const Duration(days: 2));
|
|
||||||
final oneDayAgo = startOfToday.subtract(const Duration(days: 1));
|
|
||||||
if (group.lastMessageSend!.isAfter(twoDaysAgo) &&
|
|
||||||
group.lastMessageReceived!.isAfter(twoDaysAgo) ||
|
|
||||||
group.lastFlameCounterChange!.isAfter(oneDayAgo)) {
|
|
||||||
return group.flameCounter + 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,14 @@ class MediaFilesDao extends DatabaseAccessor<TwonlyDB>
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<MediaFile>> getAllNonHashedStoredMediaFiles() async {
|
||||||
|
return (select(mediaFiles)
|
||||||
|
..where(
|
||||||
|
(t) => t.stored.equals(true) & t.storedFileHash.isNull(),
|
||||||
|
))
|
||||||
|
.get();
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<MediaFile>> getAllMediaFilesPendingUpload() async {
|
Future<List<MediaFile>> getAllMediaFilesPendingUpload() async {
|
||||||
return (select(mediaFiles)
|
return (select(mediaFiles)
|
||||||
..where(
|
..where(
|
||||||
|
|
@ -111,7 +119,10 @@ class MediaFilesDao extends DatabaseAccessor<TwonlyDB>
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<List<MediaFile>> watchAllStoredMediaFiles() {
|
Stream<List<MediaFile>> watchAllStoredMediaFiles() {
|
||||||
return (select(mediaFiles)..where((t) => t.stored.equals(true))).watch();
|
final query = (select(mediaFiles)..where((t) => t.stored.equals(true)))
|
||||||
|
.join([])
|
||||||
|
..groupBy([mediaFiles.storedFileHash]);
|
||||||
|
return query.map((row) => row.readTable(mediaFiles)).watch();
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<List<MediaFile>> watchNewestMediaFiles() {
|
Stream<List<MediaFile>> watchNewestMediaFiles() {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:hashlib/random.dart';
|
import 'package:hashlib/random.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
|
@ -110,7 +111,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
final allGroups = await select(groups).get();
|
final allGroups = await select(groups).get();
|
||||||
|
|
||||||
for (final group in allGroups) {
|
for (final group in allGroups) {
|
||||||
final deletionTime = DateTime.now().subtract(
|
final deletionTime = clock.now().subtract(
|
||||||
Duration(
|
Duration(
|
||||||
milliseconds: group.deleteMessagesAfterMilliseconds,
|
milliseconds: group.deleteMessagesAfterMilliseconds,
|
||||||
),
|
),
|
||||||
|
|
@ -150,7 +151,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
// t.messageOtherId.isNull() &
|
// t.messageOtherId.isNull() &
|
||||||
// t.errorWhileSending.equals(false) &
|
// t.errorWhileSending.equals(false) &
|
||||||
// t.sendAt.isBiggerThanValue(
|
// t.sendAt.isBiggerThanValue(
|
||||||
// DateTime.now().subtract(const Duration(minutes: 10)),
|
// clock.now().subtract(const Duration(minutes: 10)),
|
||||||
// ),
|
// ),
|
||||||
// ))
|
// ))
|
||||||
// .get();
|
// .get();
|
||||||
|
|
@ -178,7 +179,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Future<void> openedAllTextMessages(String groupId) {
|
Future<void> openedAllTextMessages(String groupId) {
|
||||||
final updates = MessagesCompanion(openedAt: Value(DateTime.now()));
|
final updates = MessagesCompanion(openedAt: Value(clock.now()));
|
||||||
return (update(messages)
|
return (update(messages)
|
||||||
..where(
|
..where(
|
||||||
(t) =>
|
(t) =>
|
||||||
|
|
@ -272,12 +273,12 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
// Directly show as message opened as soon as one person has opened it
|
// Directly show as message opened as soon as one person has opened it
|
||||||
final openedByAll =
|
final openedByAll =
|
||||||
await haveAllMembers(messageId, MessageActionType.openedAt)
|
await haveAllMembers(messageId, MessageActionType.openedAt)
|
||||||
? DateTime.now()
|
? clock.now()
|
||||||
: null;
|
: null;
|
||||||
await twonlyDB.messagesDao.updateMessageId(
|
await twonlyDB.messagesDao.updateMessageId(
|
||||||
messageId,
|
messageId,
|
||||||
MessagesCompanion(
|
MessagesCompanion(
|
||||||
openedAt: Value(DateTime.now()),
|
openedAt: Value(clock.now()),
|
||||||
openedByAll: Value(openedByAll),
|
openedByAll: Value(openedByAll),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -298,7 +299,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
);
|
);
|
||||||
await twonlyDB.messagesDao.updateMessageId(
|
await twonlyDB.messagesDao.updateMessageId(
|
||||||
messageId,
|
messageId,
|
||||||
MessagesCompanion(ackByServer: Value(DateTime.now())),
|
MessagesCompanion(ackByServer: Value(clock.now())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -378,7 +379,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
await twonlyDB.groupsDao.updateGroup(
|
await twonlyDB.groupsDao.updateGroup(
|
||||||
message.groupId.value,
|
message.groupId.value,
|
||||||
GroupsCompanion(
|
GroupsCompanion(
|
||||||
lastMessageExchange: Value(DateTime.now()),
|
lastMessageExchange: Value(clock.now()),
|
||||||
archived: const Value(false),
|
archived: const Value(false),
|
||||||
deletedContent: const Value(false),
|
deletedContent: const Value(false),
|
||||||
),
|
),
|
||||||
|
|
@ -389,7 +390,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
message.groupId.value,
|
message.groupId.value,
|
||||||
message.senderId.value!,
|
message.senderId.value!,
|
||||||
GroupMembersCompanion(
|
GroupMembersCompanion(
|
||||||
lastMessage: Value(DateTime.now()),
|
lastMessage: Value(clock.now()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:hashlib/random.dart';
|
import 'package:hashlib/random.dart';
|
||||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
|
|
@ -80,10 +81,18 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Receipt>> getReceiptsNotAckByServer() async {
|
Future<List<Receipt>> getReceiptsForRetransmission() async {
|
||||||
|
final markedRetriesTime = clock.now().subtract(
|
||||||
|
const Duration(
|
||||||
|
// give the server time to transmit all messages to the client
|
||||||
|
seconds: 20,
|
||||||
|
),
|
||||||
|
);
|
||||||
return (select(receipts)
|
return (select(receipts)
|
||||||
..where(
|
..where(
|
||||||
(t) => t.ackByServerAt.isNull(),
|
(t) =>
|
||||||
|
t.ackByServerAt.isNull() |
|
||||||
|
t.markForRetry.isSmallerThanValue(markedRetriesTime),
|
||||||
))
|
))
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
@ -100,6 +109,14 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
|
||||||
.write(updates);
|
.write(updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> markMessagesForRetry(int contactId) async {
|
||||||
|
await (update(receipts)..where((c) => c.contactId.equals(contactId))).write(
|
||||||
|
ReceiptsCompanion(
|
||||||
|
markForRetry: Value(clock.now()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> isDuplicated(String receiptId) async {
|
Future<bool> isDuplicated(String receiptId) async {
|
||||||
return await (select(receivedReceipts)
|
return await (select(receivedReceipts)
|
||||||
..where((t) => t.receiptId.equals(receiptId)))
|
..where((t) => t.receiptId.equals(receiptId)))
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/globals.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_prekey.table.dart';
|
||||||
|
|
@ -107,7 +108,7 @@ class SignalDao extends DatabaseAccessor<TwonlyDB> with _$SignalDaoMixin {
|
||||||
await (delete(signalContactPreKeys)
|
await (delete(signalContactPreKeys)
|
||||||
..where(
|
..where(
|
||||||
(t) => (t.createdAt.isSmallerThanValue(
|
(t) => (t.createdAt.isSmallerThanValue(
|
||||||
DateTime.now().subtract(
|
clock.now().subtract(
|
||||||
const Duration(days: 100),
|
const Duration(days: 100),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|
@ -117,7 +118,7 @@ class SignalDao extends DatabaseAccessor<TwonlyDB> with _$SignalDaoMixin {
|
||||||
await (delete(twonlyDB.signalPreKeyStores)
|
await (delete(twonlyDB.signalPreKeyStores)
|
||||||
..where(
|
..where(
|
||||||
(t) => (t.createdAt.isSmallerThanValue(
|
(t) => (t.createdAt.isSmallerThanValue(
|
||||||
DateTime.now().subtract(
|
clock.now().subtract(
|
||||||
const Duration(days: 365),
|
const Duration(days: 365),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|
|
||||||
1
lib/src/database/schemas/twonly_db/drift_schema_v5.json
Normal file
1
lib/src/database/schemas/twonly_db/drift_schema_v5.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -59,6 +59,8 @@ class MediaFiles extends Table {
|
||||||
BlobColumn get encryptionMac => blob().nullable()();
|
BlobColumn get encryptionMac => blob().nullable()();
|
||||||
BlobColumn get encryptionNonce => blob().nullable()();
|
BlobColumn get encryptionNonce => blob().nullable()();
|
||||||
|
|
||||||
|
BlobColumn get storedFileHash => blob().nullable()();
|
||||||
|
|
||||||
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ class Receipts extends Table {
|
||||||
BoolColumn get contactWillSendsReceipt =>
|
BoolColumn get contactWillSendsReceipt =>
|
||||||
boolean().withDefault(const Constant(true))();
|
boolean().withDefault(const Constant(true))();
|
||||||
|
|
||||||
|
DateTimeColumn get markForRetry => dateTime().nullable()();
|
||||||
|
|
||||||
DateTimeColumn get ackByServerAt => dateTime().nullable()();
|
DateTimeColumn get ackByServerAt => dateTime().nullable()();
|
||||||
|
|
||||||
IntColumn get retryCount => integer().withDefault(const Constant(0))();
|
IntColumn get retryCount => integer().withDefault(const Constant(0))();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:drift_flutter/drift_flutter.dart'
|
import 'package:drift_flutter/drift_flutter.dart'
|
||||||
show DriftNativeOptions, driftDatabase;
|
show DriftNativeOptions, driftDatabase;
|
||||||
|
|
@ -67,7 +68,7 @@ class TwonlyDB extends _$TwonlyDB {
|
||||||
TwonlyDB.forTesting(DatabaseConnection super.connection);
|
TwonlyDB.forTesting(DatabaseConnection super.connection);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 4;
|
int get schemaVersion => 5;
|
||||||
|
|
||||||
static QueryExecutor _openConnection() {
|
static QueryExecutor _openConnection() {
|
||||||
return driftDatabase(
|
return driftDatabase(
|
||||||
|
|
@ -103,6 +104,13 @@ class TwonlyDB extends _$TwonlyDB {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
from4To5: (m, schema) async {
|
||||||
|
await m.addColumn(schema.receipts, schema.receipts.markForRetry);
|
||||||
|
await m.addColumn(
|
||||||
|
schema.mediaFiles,
|
||||||
|
schema.mediaFiles.storedFileHash,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +161,7 @@ class TwonlyDB extends _$TwonlyDB {
|
||||||
await (delete(signalPreKeyStores)
|
await (delete(signalPreKeyStores)
|
||||||
..where(
|
..where(
|
||||||
(t) => (t.createdAt.isSmallerThanValue(
|
(t) => (t.createdAt.isSmallerThanValue(
|
||||||
DateTime.now().subtract(
|
clock.now().subtract(
|
||||||
const Duration(days: 25),
|
const Duration(days: 25),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|
|
||||||
|
|
@ -1996,6 +1996,12 @@ class $MediaFilesTable extends MediaFiles
|
||||||
late final GeneratedColumn<Uint8List> encryptionNonce =
|
late final GeneratedColumn<Uint8List> encryptionNonce =
|
||||||
GeneratedColumn<Uint8List>('encryption_nonce', aliasedName, true,
|
GeneratedColumn<Uint8List>('encryption_nonce', aliasedName, true,
|
||||||
type: DriftSqlType.blob, requiredDuringInsert: false);
|
type: DriftSqlType.blob, requiredDuringInsert: false);
|
||||||
|
static const VerificationMeta _storedFileHashMeta =
|
||||||
|
const VerificationMeta('storedFileHash');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<Uint8List> storedFileHash =
|
||||||
|
GeneratedColumn<Uint8List>('stored_file_hash', aliasedName, true,
|
||||||
|
type: DriftSqlType.blob, requiredDuringInsert: false);
|
||||||
static const VerificationMeta _createdAtMeta =
|
static const VerificationMeta _createdAtMeta =
|
||||||
const VerificationMeta('createdAt');
|
const VerificationMeta('createdAt');
|
||||||
@override
|
@override
|
||||||
|
|
@ -2020,6 +2026,7 @@ class $MediaFilesTable extends MediaFiles
|
||||||
encryptionKey,
|
encryptionKey,
|
||||||
encryptionMac,
|
encryptionMac,
|
||||||
encryptionNonce,
|
encryptionNonce,
|
||||||
|
storedFileHash,
|
||||||
createdAt
|
createdAt
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
|
|
@ -2091,6 +2098,12 @@ class $MediaFilesTable extends MediaFiles
|
||||||
encryptionNonce.isAcceptableOrUnknown(
|
encryptionNonce.isAcceptableOrUnknown(
|
||||||
data['encryption_nonce']!, _encryptionNonceMeta));
|
data['encryption_nonce']!, _encryptionNonceMeta));
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('stored_file_hash')) {
|
||||||
|
context.handle(
|
||||||
|
_storedFileHashMeta,
|
||||||
|
storedFileHash.isAcceptableOrUnknown(
|
||||||
|
data['stored_file_hash']!, _storedFileHashMeta));
|
||||||
|
}
|
||||||
if (data.containsKey('created_at')) {
|
if (data.containsKey('created_at')) {
|
||||||
context.handle(_createdAtMeta,
|
context.handle(_createdAtMeta,
|
||||||
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
||||||
|
|
@ -2137,6 +2150,8 @@ class $MediaFilesTable extends MediaFiles
|
||||||
.read(DriftSqlType.blob, data['${effectivePrefix}encryption_mac']),
|
.read(DriftSqlType.blob, data['${effectivePrefix}encryption_mac']),
|
||||||
encryptionNonce: attachedDatabase.typeMapping
|
encryptionNonce: attachedDatabase.typeMapping
|
||||||
.read(DriftSqlType.blob, data['${effectivePrefix}encryption_nonce']),
|
.read(DriftSqlType.blob, data['${effectivePrefix}encryption_nonce']),
|
||||||
|
storedFileHash: attachedDatabase.typeMapping
|
||||||
|
.read(DriftSqlType.blob, data['${effectivePrefix}stored_file_hash']),
|
||||||
createdAt: attachedDatabase.typeMapping
|
createdAt: attachedDatabase.typeMapping
|
||||||
.read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!,
|
.read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!,
|
||||||
);
|
);
|
||||||
|
|
@ -2181,6 +2196,7 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
final Uint8List? encryptionKey;
|
final Uint8List? encryptionKey;
|
||||||
final Uint8List? encryptionMac;
|
final Uint8List? encryptionMac;
|
||||||
final Uint8List? encryptionNonce;
|
final Uint8List? encryptionNonce;
|
||||||
|
final Uint8List? storedFileHash;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
const MediaFile(
|
const MediaFile(
|
||||||
{required this.mediaId,
|
{required this.mediaId,
|
||||||
|
|
@ -2197,6 +2213,7 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
this.encryptionKey,
|
this.encryptionKey,
|
||||||
this.encryptionMac,
|
this.encryptionMac,
|
||||||
this.encryptionNonce,
|
this.encryptionNonce,
|
||||||
|
this.storedFileHash,
|
||||||
required this.createdAt});
|
required this.createdAt});
|
||||||
@override
|
@override
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
|
|
@ -2241,6 +2258,9 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
if (!nullToAbsent || encryptionNonce != null) {
|
if (!nullToAbsent || encryptionNonce != null) {
|
||||||
map['encryption_nonce'] = Variable<Uint8List>(encryptionNonce);
|
map['encryption_nonce'] = Variable<Uint8List>(encryptionNonce);
|
||||||
}
|
}
|
||||||
|
if (!nullToAbsent || storedFileHash != null) {
|
||||||
|
map['stored_file_hash'] = Variable<Uint8List>(storedFileHash);
|
||||||
|
}
|
||||||
map['created_at'] = Variable<DateTime>(createdAt);
|
map['created_at'] = Variable<DateTime>(createdAt);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
@ -2280,6 +2300,9 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
encryptionNonce: encryptionNonce == null && nullToAbsent
|
encryptionNonce: encryptionNonce == null && nullToAbsent
|
||||||
? const Value.absent()
|
? const Value.absent()
|
||||||
: Value(encryptionNonce),
|
: Value(encryptionNonce),
|
||||||
|
storedFileHash: storedFileHash == null && nullToAbsent
|
||||||
|
? const Value.absent()
|
||||||
|
: Value(storedFileHash),
|
||||||
createdAt: Value(createdAt),
|
createdAt: Value(createdAt),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2308,6 +2331,7 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
encryptionKey: serializer.fromJson<Uint8List?>(json['encryptionKey']),
|
encryptionKey: serializer.fromJson<Uint8List?>(json['encryptionKey']),
|
||||||
encryptionMac: serializer.fromJson<Uint8List?>(json['encryptionMac']),
|
encryptionMac: serializer.fromJson<Uint8List?>(json['encryptionMac']),
|
||||||
encryptionNonce: serializer.fromJson<Uint8List?>(json['encryptionNonce']),
|
encryptionNonce: serializer.fromJson<Uint8List?>(json['encryptionNonce']),
|
||||||
|
storedFileHash: serializer.fromJson<Uint8List?>(json['storedFileHash']),
|
||||||
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2333,6 +2357,7 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
'encryptionKey': serializer.toJson<Uint8List?>(encryptionKey),
|
'encryptionKey': serializer.toJson<Uint8List?>(encryptionKey),
|
||||||
'encryptionMac': serializer.toJson<Uint8List?>(encryptionMac),
|
'encryptionMac': serializer.toJson<Uint8List?>(encryptionMac),
|
||||||
'encryptionNonce': serializer.toJson<Uint8List?>(encryptionNonce),
|
'encryptionNonce': serializer.toJson<Uint8List?>(encryptionNonce),
|
||||||
|
'storedFileHash': serializer.toJson<Uint8List?>(storedFileHash),
|
||||||
'createdAt': serializer.toJson<DateTime>(createdAt),
|
'createdAt': serializer.toJson<DateTime>(createdAt),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -2352,6 +2377,7 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
Value<Uint8List?> encryptionKey = const Value.absent(),
|
Value<Uint8List?> encryptionKey = const Value.absent(),
|
||||||
Value<Uint8List?> encryptionMac = const Value.absent(),
|
Value<Uint8List?> encryptionMac = const Value.absent(),
|
||||||
Value<Uint8List?> encryptionNonce = const Value.absent(),
|
Value<Uint8List?> encryptionNonce = const Value.absent(),
|
||||||
|
Value<Uint8List?> storedFileHash = const Value.absent(),
|
||||||
DateTime? createdAt}) =>
|
DateTime? createdAt}) =>
|
||||||
MediaFile(
|
MediaFile(
|
||||||
mediaId: mediaId ?? this.mediaId,
|
mediaId: mediaId ?? this.mediaId,
|
||||||
|
|
@ -2379,6 +2405,8 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
encryptionNonce: encryptionNonce.present
|
encryptionNonce: encryptionNonce.present
|
||||||
? encryptionNonce.value
|
? encryptionNonce.value
|
||||||
: this.encryptionNonce,
|
: this.encryptionNonce,
|
||||||
|
storedFileHash:
|
||||||
|
storedFileHash.present ? storedFileHash.value : this.storedFileHash,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
);
|
);
|
||||||
MediaFile copyWithCompanion(MediaFilesCompanion data) {
|
MediaFile copyWithCompanion(MediaFilesCompanion data) {
|
||||||
|
|
@ -2417,6 +2445,9 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
encryptionNonce: data.encryptionNonce.present
|
encryptionNonce: data.encryptionNonce.present
|
||||||
? data.encryptionNonce.value
|
? data.encryptionNonce.value
|
||||||
: this.encryptionNonce,
|
: this.encryptionNonce,
|
||||||
|
storedFileHash: data.storedFileHash.present
|
||||||
|
? data.storedFileHash.value
|
||||||
|
: this.storedFileHash,
|
||||||
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2438,6 +2469,7 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
..write('encryptionKey: $encryptionKey, ')
|
..write('encryptionKey: $encryptionKey, ')
|
||||||
..write('encryptionMac: $encryptionMac, ')
|
..write('encryptionMac: $encryptionMac, ')
|
||||||
..write('encryptionNonce: $encryptionNonce, ')
|
..write('encryptionNonce: $encryptionNonce, ')
|
||||||
|
..write('storedFileHash: $storedFileHash, ')
|
||||||
..write('createdAt: $createdAt')
|
..write('createdAt: $createdAt')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
|
|
@ -2459,6 +2491,7 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
$driftBlobEquality.hash(encryptionKey),
|
$driftBlobEquality.hash(encryptionKey),
|
||||||
$driftBlobEquality.hash(encryptionMac),
|
$driftBlobEquality.hash(encryptionMac),
|
||||||
$driftBlobEquality.hash(encryptionNonce),
|
$driftBlobEquality.hash(encryptionNonce),
|
||||||
|
$driftBlobEquality.hash(storedFileHash),
|
||||||
createdAt);
|
createdAt);
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
|
|
@ -2479,6 +2512,8 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
|
||||||
$driftBlobEquality.equals(other.encryptionMac, this.encryptionMac) &&
|
$driftBlobEquality.equals(other.encryptionMac, this.encryptionMac) &&
|
||||||
$driftBlobEquality.equals(
|
$driftBlobEquality.equals(
|
||||||
other.encryptionNonce, this.encryptionNonce) &&
|
other.encryptionNonce, this.encryptionNonce) &&
|
||||||
|
$driftBlobEquality.equals(
|
||||||
|
other.storedFileHash, this.storedFileHash) &&
|
||||||
other.createdAt == this.createdAt);
|
other.createdAt == this.createdAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2497,6 +2532,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
final Value<Uint8List?> encryptionKey;
|
final Value<Uint8List?> encryptionKey;
|
||||||
final Value<Uint8List?> encryptionMac;
|
final Value<Uint8List?> encryptionMac;
|
||||||
final Value<Uint8List?> encryptionNonce;
|
final Value<Uint8List?> encryptionNonce;
|
||||||
|
final Value<Uint8List?> storedFileHash;
|
||||||
final Value<DateTime> createdAt;
|
final Value<DateTime> createdAt;
|
||||||
final Value<int> rowid;
|
final Value<int> rowid;
|
||||||
const MediaFilesCompanion({
|
const MediaFilesCompanion({
|
||||||
|
|
@ -2514,6 +2550,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
this.encryptionKey = const Value.absent(),
|
this.encryptionKey = const Value.absent(),
|
||||||
this.encryptionMac = const Value.absent(),
|
this.encryptionMac = const Value.absent(),
|
||||||
this.encryptionNonce = const Value.absent(),
|
this.encryptionNonce = const Value.absent(),
|
||||||
|
this.storedFileHash = const Value.absent(),
|
||||||
this.createdAt = const Value.absent(),
|
this.createdAt = const Value.absent(),
|
||||||
this.rowid = const Value.absent(),
|
this.rowid = const Value.absent(),
|
||||||
});
|
});
|
||||||
|
|
@ -2532,6 +2569,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
this.encryptionKey = const Value.absent(),
|
this.encryptionKey = const Value.absent(),
|
||||||
this.encryptionMac = const Value.absent(),
|
this.encryptionMac = const Value.absent(),
|
||||||
this.encryptionNonce = const Value.absent(),
|
this.encryptionNonce = const Value.absent(),
|
||||||
|
this.storedFileHash = const Value.absent(),
|
||||||
this.createdAt = const Value.absent(),
|
this.createdAt = const Value.absent(),
|
||||||
this.rowid = const Value.absent(),
|
this.rowid = const Value.absent(),
|
||||||
}) : mediaId = Value(mediaId),
|
}) : mediaId = Value(mediaId),
|
||||||
|
|
@ -2551,6 +2589,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
Expression<Uint8List>? encryptionKey,
|
Expression<Uint8List>? encryptionKey,
|
||||||
Expression<Uint8List>? encryptionMac,
|
Expression<Uint8List>? encryptionMac,
|
||||||
Expression<Uint8List>? encryptionNonce,
|
Expression<Uint8List>? encryptionNonce,
|
||||||
|
Expression<Uint8List>? storedFileHash,
|
||||||
Expression<DateTime>? createdAt,
|
Expression<DateTime>? createdAt,
|
||||||
Expression<int>? rowid,
|
Expression<int>? rowid,
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -2572,6 +2611,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
if (encryptionKey != null) 'encryption_key': encryptionKey,
|
if (encryptionKey != null) 'encryption_key': encryptionKey,
|
||||||
if (encryptionMac != null) 'encryption_mac': encryptionMac,
|
if (encryptionMac != null) 'encryption_mac': encryptionMac,
|
||||||
if (encryptionNonce != null) 'encryption_nonce': encryptionNonce,
|
if (encryptionNonce != null) 'encryption_nonce': encryptionNonce,
|
||||||
|
if (storedFileHash != null) 'stored_file_hash': storedFileHash,
|
||||||
if (createdAt != null) 'created_at': createdAt,
|
if (createdAt != null) 'created_at': createdAt,
|
||||||
if (rowid != null) 'rowid': rowid,
|
if (rowid != null) 'rowid': rowid,
|
||||||
});
|
});
|
||||||
|
|
@ -2592,6 +2632,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
Value<Uint8List?>? encryptionKey,
|
Value<Uint8List?>? encryptionKey,
|
||||||
Value<Uint8List?>? encryptionMac,
|
Value<Uint8List?>? encryptionMac,
|
||||||
Value<Uint8List?>? encryptionNonce,
|
Value<Uint8List?>? encryptionNonce,
|
||||||
|
Value<Uint8List?>? storedFileHash,
|
||||||
Value<DateTime>? createdAt,
|
Value<DateTime>? createdAt,
|
||||||
Value<int>? rowid}) {
|
Value<int>? rowid}) {
|
||||||
return MediaFilesCompanion(
|
return MediaFilesCompanion(
|
||||||
|
|
@ -2611,6 +2652,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
encryptionKey: encryptionKey ?? this.encryptionKey,
|
encryptionKey: encryptionKey ?? this.encryptionKey,
|
||||||
encryptionMac: encryptionMac ?? this.encryptionMac,
|
encryptionMac: encryptionMac ?? this.encryptionMac,
|
||||||
encryptionNonce: encryptionNonce ?? this.encryptionNonce,
|
encryptionNonce: encryptionNonce ?? this.encryptionNonce,
|
||||||
|
storedFileHash: storedFileHash ?? this.storedFileHash,
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
rowid: rowid ?? this.rowid,
|
rowid: rowid ?? this.rowid,
|
||||||
);
|
);
|
||||||
|
|
@ -2668,6 +2710,9 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
if (encryptionNonce.present) {
|
if (encryptionNonce.present) {
|
||||||
map['encryption_nonce'] = Variable<Uint8List>(encryptionNonce.value);
|
map['encryption_nonce'] = Variable<Uint8List>(encryptionNonce.value);
|
||||||
}
|
}
|
||||||
|
if (storedFileHash.present) {
|
||||||
|
map['stored_file_hash'] = Variable<Uint8List>(storedFileHash.value);
|
||||||
|
}
|
||||||
if (createdAt.present) {
|
if (createdAt.present) {
|
||||||
map['created_at'] = Variable<DateTime>(createdAt.value);
|
map['created_at'] = Variable<DateTime>(createdAt.value);
|
||||||
}
|
}
|
||||||
|
|
@ -2694,6 +2739,7 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
|
||||||
..write('encryptionKey: $encryptionKey, ')
|
..write('encryptionKey: $encryptionKey, ')
|
||||||
..write('encryptionMac: $encryptionMac, ')
|
..write('encryptionMac: $encryptionMac, ')
|
||||||
..write('encryptionNonce: $encryptionNonce, ')
|
..write('encryptionNonce: $encryptionNonce, ')
|
||||||
|
..write('storedFileHash: $storedFileHash, ')
|
||||||
..write('createdAt: $createdAt, ')
|
..write('createdAt: $createdAt, ')
|
||||||
..write('rowid: $rowid')
|
..write('rowid: $rowid')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
|
|
@ -4546,6 +4592,12 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
|
||||||
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
'CHECK ("contact_will_sends_receipt" IN (0, 1))'),
|
'CHECK ("contact_will_sends_receipt" IN (0, 1))'),
|
||||||
defaultValue: const Constant(true));
|
defaultValue: const Constant(true));
|
||||||
|
static const VerificationMeta _markForRetryMeta =
|
||||||
|
const VerificationMeta('markForRetry');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<DateTime> markForRetry = GeneratedColumn<DateTime>(
|
||||||
|
'mark_for_retry', aliasedName, true,
|
||||||
|
type: DriftSqlType.dateTime, requiredDuringInsert: false);
|
||||||
static const VerificationMeta _ackByServerAtMeta =
|
static const VerificationMeta _ackByServerAtMeta =
|
||||||
const VerificationMeta('ackByServerAt');
|
const VerificationMeta('ackByServerAt');
|
||||||
@override
|
@override
|
||||||
|
|
@ -4581,6 +4633,7 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
|
||||||
messageId,
|
messageId,
|
||||||
message,
|
message,
|
||||||
contactWillSendsReceipt,
|
contactWillSendsReceipt,
|
||||||
|
markForRetry,
|
||||||
ackByServerAt,
|
ackByServerAt,
|
||||||
retryCount,
|
retryCount,
|
||||||
lastRetry,
|
lastRetry,
|
||||||
|
|
@ -4625,6 +4678,12 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
|
||||||
data['contact_will_sends_receipt']!,
|
data['contact_will_sends_receipt']!,
|
||||||
_contactWillSendsReceiptMeta));
|
_contactWillSendsReceiptMeta));
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('mark_for_retry')) {
|
||||||
|
context.handle(
|
||||||
|
_markForRetryMeta,
|
||||||
|
markForRetry.isAcceptableOrUnknown(
|
||||||
|
data['mark_for_retry']!, _markForRetryMeta));
|
||||||
|
}
|
||||||
if (data.containsKey('ack_by_server_at')) {
|
if (data.containsKey('ack_by_server_at')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_ackByServerAtMeta,
|
_ackByServerAtMeta,
|
||||||
|
|
@ -4665,6 +4724,8 @@ class $ReceiptsTable extends Receipts with TableInfo<$ReceiptsTable, Receipt> {
|
||||||
contactWillSendsReceipt: attachedDatabase.typeMapping.read(
|
contactWillSendsReceipt: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.bool,
|
DriftSqlType.bool,
|
||||||
data['${effectivePrefix}contact_will_sends_receipt'])!,
|
data['${effectivePrefix}contact_will_sends_receipt'])!,
|
||||||
|
markForRetry: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.dateTime, data['${effectivePrefix}mark_for_retry']),
|
||||||
ackByServerAt: attachedDatabase.typeMapping.read(
|
ackByServerAt: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.dateTime, data['${effectivePrefix}ack_by_server_at']),
|
DriftSqlType.dateTime, data['${effectivePrefix}ack_by_server_at']),
|
||||||
retryCount: attachedDatabase.typeMapping
|
retryCount: attachedDatabase.typeMapping
|
||||||
|
|
@ -4690,6 +4751,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
/// This is the protobuf 'Message'
|
/// This is the protobuf 'Message'
|
||||||
final Uint8List message;
|
final Uint8List message;
|
||||||
final bool contactWillSendsReceipt;
|
final bool contactWillSendsReceipt;
|
||||||
|
final DateTime? markForRetry;
|
||||||
final DateTime? ackByServerAt;
|
final DateTime? ackByServerAt;
|
||||||
final int retryCount;
|
final int retryCount;
|
||||||
final DateTime? lastRetry;
|
final DateTime? lastRetry;
|
||||||
|
|
@ -4700,6 +4762,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
this.messageId,
|
this.messageId,
|
||||||
required this.message,
|
required this.message,
|
||||||
required this.contactWillSendsReceipt,
|
required this.contactWillSendsReceipt,
|
||||||
|
this.markForRetry,
|
||||||
this.ackByServerAt,
|
this.ackByServerAt,
|
||||||
required this.retryCount,
|
required this.retryCount,
|
||||||
this.lastRetry,
|
this.lastRetry,
|
||||||
|
|
@ -4714,6 +4777,9 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
}
|
}
|
||||||
map['message'] = Variable<Uint8List>(message);
|
map['message'] = Variable<Uint8List>(message);
|
||||||
map['contact_will_sends_receipt'] = Variable<bool>(contactWillSendsReceipt);
|
map['contact_will_sends_receipt'] = Variable<bool>(contactWillSendsReceipt);
|
||||||
|
if (!nullToAbsent || markForRetry != null) {
|
||||||
|
map['mark_for_retry'] = Variable<DateTime>(markForRetry);
|
||||||
|
}
|
||||||
if (!nullToAbsent || ackByServerAt != null) {
|
if (!nullToAbsent || ackByServerAt != null) {
|
||||||
map['ack_by_server_at'] = Variable<DateTime>(ackByServerAt);
|
map['ack_by_server_at'] = Variable<DateTime>(ackByServerAt);
|
||||||
}
|
}
|
||||||
|
|
@ -4734,6 +4800,9 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
: Value(messageId),
|
: Value(messageId),
|
||||||
message: Value(message),
|
message: Value(message),
|
||||||
contactWillSendsReceipt: Value(contactWillSendsReceipt),
|
contactWillSendsReceipt: Value(contactWillSendsReceipt),
|
||||||
|
markForRetry: markForRetry == null && nullToAbsent
|
||||||
|
? const Value.absent()
|
||||||
|
: Value(markForRetry),
|
||||||
ackByServerAt: ackByServerAt == null && nullToAbsent
|
ackByServerAt: ackByServerAt == null && nullToAbsent
|
||||||
? const Value.absent()
|
? const Value.absent()
|
||||||
: Value(ackByServerAt),
|
: Value(ackByServerAt),
|
||||||
|
|
@ -4755,6 +4824,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
message: serializer.fromJson<Uint8List>(json['message']),
|
message: serializer.fromJson<Uint8List>(json['message']),
|
||||||
contactWillSendsReceipt:
|
contactWillSendsReceipt:
|
||||||
serializer.fromJson<bool>(json['contactWillSendsReceipt']),
|
serializer.fromJson<bool>(json['contactWillSendsReceipt']),
|
||||||
|
markForRetry: serializer.fromJson<DateTime?>(json['markForRetry']),
|
||||||
ackByServerAt: serializer.fromJson<DateTime?>(json['ackByServerAt']),
|
ackByServerAt: serializer.fromJson<DateTime?>(json['ackByServerAt']),
|
||||||
retryCount: serializer.fromJson<int>(json['retryCount']),
|
retryCount: serializer.fromJson<int>(json['retryCount']),
|
||||||
lastRetry: serializer.fromJson<DateTime?>(json['lastRetry']),
|
lastRetry: serializer.fromJson<DateTime?>(json['lastRetry']),
|
||||||
|
|
@ -4771,6 +4841,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
'message': serializer.toJson<Uint8List>(message),
|
'message': serializer.toJson<Uint8List>(message),
|
||||||
'contactWillSendsReceipt':
|
'contactWillSendsReceipt':
|
||||||
serializer.toJson<bool>(contactWillSendsReceipt),
|
serializer.toJson<bool>(contactWillSendsReceipt),
|
||||||
|
'markForRetry': serializer.toJson<DateTime?>(markForRetry),
|
||||||
'ackByServerAt': serializer.toJson<DateTime?>(ackByServerAt),
|
'ackByServerAt': serializer.toJson<DateTime?>(ackByServerAt),
|
||||||
'retryCount': serializer.toJson<int>(retryCount),
|
'retryCount': serializer.toJson<int>(retryCount),
|
||||||
'lastRetry': serializer.toJson<DateTime?>(lastRetry),
|
'lastRetry': serializer.toJson<DateTime?>(lastRetry),
|
||||||
|
|
@ -4784,6 +4855,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
Value<String?> messageId = const Value.absent(),
|
Value<String?> messageId = const Value.absent(),
|
||||||
Uint8List? message,
|
Uint8List? message,
|
||||||
bool? contactWillSendsReceipt,
|
bool? contactWillSendsReceipt,
|
||||||
|
Value<DateTime?> markForRetry = const Value.absent(),
|
||||||
Value<DateTime?> ackByServerAt = const Value.absent(),
|
Value<DateTime?> ackByServerAt = const Value.absent(),
|
||||||
int? retryCount,
|
int? retryCount,
|
||||||
Value<DateTime?> lastRetry = const Value.absent(),
|
Value<DateTime?> lastRetry = const Value.absent(),
|
||||||
|
|
@ -4795,6 +4867,8 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
message: message ?? this.message,
|
message: message ?? this.message,
|
||||||
contactWillSendsReceipt:
|
contactWillSendsReceipt:
|
||||||
contactWillSendsReceipt ?? this.contactWillSendsReceipt,
|
contactWillSendsReceipt ?? this.contactWillSendsReceipt,
|
||||||
|
markForRetry:
|
||||||
|
markForRetry.present ? markForRetry.value : this.markForRetry,
|
||||||
ackByServerAt:
|
ackByServerAt:
|
||||||
ackByServerAt.present ? ackByServerAt.value : this.ackByServerAt,
|
ackByServerAt.present ? ackByServerAt.value : this.ackByServerAt,
|
||||||
retryCount: retryCount ?? this.retryCount,
|
retryCount: retryCount ?? this.retryCount,
|
||||||
|
|
@ -4810,6 +4884,9 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
contactWillSendsReceipt: data.contactWillSendsReceipt.present
|
contactWillSendsReceipt: data.contactWillSendsReceipt.present
|
||||||
? data.contactWillSendsReceipt.value
|
? data.contactWillSendsReceipt.value
|
||||||
: this.contactWillSendsReceipt,
|
: this.contactWillSendsReceipt,
|
||||||
|
markForRetry: data.markForRetry.present
|
||||||
|
? data.markForRetry.value
|
||||||
|
: this.markForRetry,
|
||||||
ackByServerAt: data.ackByServerAt.present
|
ackByServerAt: data.ackByServerAt.present
|
||||||
? data.ackByServerAt.value
|
? data.ackByServerAt.value
|
||||||
: this.ackByServerAt,
|
: this.ackByServerAt,
|
||||||
|
|
@ -4828,6 +4905,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
..write('messageId: $messageId, ')
|
..write('messageId: $messageId, ')
|
||||||
..write('message: $message, ')
|
..write('message: $message, ')
|
||||||
..write('contactWillSendsReceipt: $contactWillSendsReceipt, ')
|
..write('contactWillSendsReceipt: $contactWillSendsReceipt, ')
|
||||||
|
..write('markForRetry: $markForRetry, ')
|
||||||
..write('ackByServerAt: $ackByServerAt, ')
|
..write('ackByServerAt: $ackByServerAt, ')
|
||||||
..write('retryCount: $retryCount, ')
|
..write('retryCount: $retryCount, ')
|
||||||
..write('lastRetry: $lastRetry, ')
|
..write('lastRetry: $lastRetry, ')
|
||||||
|
|
@ -4843,6 +4921,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
messageId,
|
messageId,
|
||||||
$driftBlobEquality.hash(message),
|
$driftBlobEquality.hash(message),
|
||||||
contactWillSendsReceipt,
|
contactWillSendsReceipt,
|
||||||
|
markForRetry,
|
||||||
ackByServerAt,
|
ackByServerAt,
|
||||||
retryCount,
|
retryCount,
|
||||||
lastRetry,
|
lastRetry,
|
||||||
|
|
@ -4856,6 +4935,7 @@ class Receipt extends DataClass implements Insertable<Receipt> {
|
||||||
other.messageId == this.messageId &&
|
other.messageId == this.messageId &&
|
||||||
$driftBlobEquality.equals(other.message, this.message) &&
|
$driftBlobEquality.equals(other.message, this.message) &&
|
||||||
other.contactWillSendsReceipt == this.contactWillSendsReceipt &&
|
other.contactWillSendsReceipt == this.contactWillSendsReceipt &&
|
||||||
|
other.markForRetry == this.markForRetry &&
|
||||||
other.ackByServerAt == this.ackByServerAt &&
|
other.ackByServerAt == this.ackByServerAt &&
|
||||||
other.retryCount == this.retryCount &&
|
other.retryCount == this.retryCount &&
|
||||||
other.lastRetry == this.lastRetry &&
|
other.lastRetry == this.lastRetry &&
|
||||||
|
|
@ -4868,6 +4948,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
final Value<String?> messageId;
|
final Value<String?> messageId;
|
||||||
final Value<Uint8List> message;
|
final Value<Uint8List> message;
|
||||||
final Value<bool> contactWillSendsReceipt;
|
final Value<bool> contactWillSendsReceipt;
|
||||||
|
final Value<DateTime?> markForRetry;
|
||||||
final Value<DateTime?> ackByServerAt;
|
final Value<DateTime?> ackByServerAt;
|
||||||
final Value<int> retryCount;
|
final Value<int> retryCount;
|
||||||
final Value<DateTime?> lastRetry;
|
final Value<DateTime?> lastRetry;
|
||||||
|
|
@ -4879,6 +4960,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
this.messageId = const Value.absent(),
|
this.messageId = const Value.absent(),
|
||||||
this.message = const Value.absent(),
|
this.message = const Value.absent(),
|
||||||
this.contactWillSendsReceipt = const Value.absent(),
|
this.contactWillSendsReceipt = const Value.absent(),
|
||||||
|
this.markForRetry = const Value.absent(),
|
||||||
this.ackByServerAt = const Value.absent(),
|
this.ackByServerAt = const Value.absent(),
|
||||||
this.retryCount = const Value.absent(),
|
this.retryCount = const Value.absent(),
|
||||||
this.lastRetry = const Value.absent(),
|
this.lastRetry = const Value.absent(),
|
||||||
|
|
@ -4891,6 +4973,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
this.messageId = const Value.absent(),
|
this.messageId = const Value.absent(),
|
||||||
required Uint8List message,
|
required Uint8List message,
|
||||||
this.contactWillSendsReceipt = const Value.absent(),
|
this.contactWillSendsReceipt = const Value.absent(),
|
||||||
|
this.markForRetry = const Value.absent(),
|
||||||
this.ackByServerAt = const Value.absent(),
|
this.ackByServerAt = const Value.absent(),
|
||||||
this.retryCount = const Value.absent(),
|
this.retryCount = const Value.absent(),
|
||||||
this.lastRetry = const Value.absent(),
|
this.lastRetry = const Value.absent(),
|
||||||
|
|
@ -4905,6 +4988,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
Expression<String>? messageId,
|
Expression<String>? messageId,
|
||||||
Expression<Uint8List>? message,
|
Expression<Uint8List>? message,
|
||||||
Expression<bool>? contactWillSendsReceipt,
|
Expression<bool>? contactWillSendsReceipt,
|
||||||
|
Expression<DateTime>? markForRetry,
|
||||||
Expression<DateTime>? ackByServerAt,
|
Expression<DateTime>? ackByServerAt,
|
||||||
Expression<int>? retryCount,
|
Expression<int>? retryCount,
|
||||||
Expression<DateTime>? lastRetry,
|
Expression<DateTime>? lastRetry,
|
||||||
|
|
@ -4918,6 +5002,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
if (message != null) 'message': message,
|
if (message != null) 'message': message,
|
||||||
if (contactWillSendsReceipt != null)
|
if (contactWillSendsReceipt != null)
|
||||||
'contact_will_sends_receipt': contactWillSendsReceipt,
|
'contact_will_sends_receipt': contactWillSendsReceipt,
|
||||||
|
if (markForRetry != null) 'mark_for_retry': markForRetry,
|
||||||
if (ackByServerAt != null) 'ack_by_server_at': ackByServerAt,
|
if (ackByServerAt != null) 'ack_by_server_at': ackByServerAt,
|
||||||
if (retryCount != null) 'retry_count': retryCount,
|
if (retryCount != null) 'retry_count': retryCount,
|
||||||
if (lastRetry != null) 'last_retry': lastRetry,
|
if (lastRetry != null) 'last_retry': lastRetry,
|
||||||
|
|
@ -4932,6 +5017,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
Value<String?>? messageId,
|
Value<String?>? messageId,
|
||||||
Value<Uint8List>? message,
|
Value<Uint8List>? message,
|
||||||
Value<bool>? contactWillSendsReceipt,
|
Value<bool>? contactWillSendsReceipt,
|
||||||
|
Value<DateTime?>? markForRetry,
|
||||||
Value<DateTime?>? ackByServerAt,
|
Value<DateTime?>? ackByServerAt,
|
||||||
Value<int>? retryCount,
|
Value<int>? retryCount,
|
||||||
Value<DateTime?>? lastRetry,
|
Value<DateTime?>? lastRetry,
|
||||||
|
|
@ -4944,6 +5030,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
message: message ?? this.message,
|
message: message ?? this.message,
|
||||||
contactWillSendsReceipt:
|
contactWillSendsReceipt:
|
||||||
contactWillSendsReceipt ?? this.contactWillSendsReceipt,
|
contactWillSendsReceipt ?? this.contactWillSendsReceipt,
|
||||||
|
markForRetry: markForRetry ?? this.markForRetry,
|
||||||
ackByServerAt: ackByServerAt ?? this.ackByServerAt,
|
ackByServerAt: ackByServerAt ?? this.ackByServerAt,
|
||||||
retryCount: retryCount ?? this.retryCount,
|
retryCount: retryCount ?? this.retryCount,
|
||||||
lastRetry: lastRetry ?? this.lastRetry,
|
lastRetry: lastRetry ?? this.lastRetry,
|
||||||
|
|
@ -4971,6 +5058,9 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
map['contact_will_sends_receipt'] =
|
map['contact_will_sends_receipt'] =
|
||||||
Variable<bool>(contactWillSendsReceipt.value);
|
Variable<bool>(contactWillSendsReceipt.value);
|
||||||
}
|
}
|
||||||
|
if (markForRetry.present) {
|
||||||
|
map['mark_for_retry'] = Variable<DateTime>(markForRetry.value);
|
||||||
|
}
|
||||||
if (ackByServerAt.present) {
|
if (ackByServerAt.present) {
|
||||||
map['ack_by_server_at'] = Variable<DateTime>(ackByServerAt.value);
|
map['ack_by_server_at'] = Variable<DateTime>(ackByServerAt.value);
|
||||||
}
|
}
|
||||||
|
|
@ -4997,6 +5087,7 @@ class ReceiptsCompanion extends UpdateCompanion<Receipt> {
|
||||||
..write('messageId: $messageId, ')
|
..write('messageId: $messageId, ')
|
||||||
..write('message: $message, ')
|
..write('message: $message, ')
|
||||||
..write('contactWillSendsReceipt: $contactWillSendsReceipt, ')
|
..write('contactWillSendsReceipt: $contactWillSendsReceipt, ')
|
||||||
|
..write('markForRetry: $markForRetry, ')
|
||||||
..write('ackByServerAt: $ackByServerAt, ')
|
..write('ackByServerAt: $ackByServerAt, ')
|
||||||
..write('retryCount: $retryCount, ')
|
..write('retryCount: $retryCount, ')
|
||||||
..write('lastRetry: $lastRetry, ')
|
..write('lastRetry: $lastRetry, ')
|
||||||
|
|
@ -7111,10 +7202,7 @@ class $GroupHistoriesTable extends GroupHistories
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<int> affectedContactId = GeneratedColumn<int>(
|
late final GeneratedColumn<int> affectedContactId = GeneratedColumn<int>(
|
||||||
'affected_contact_id', aliasedName, true,
|
'affected_contact_id', aliasedName, true,
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int, requiredDuringInsert: false);
|
||||||
requiredDuringInsert: false,
|
|
||||||
defaultConstraints:
|
|
||||||
GeneratedColumn.constraintIsAlways('REFERENCES contacts (user_id)'));
|
|
||||||
static const VerificationMeta _oldGroupNameMeta =
|
static const VerificationMeta _oldGroupNameMeta =
|
||||||
const VerificationMeta('oldGroupName');
|
const VerificationMeta('oldGroupName');
|
||||||
@override
|
@override
|
||||||
|
|
@ -7896,6 +7984,22 @@ final class $$ContactsTableReferences
|
||||||
return ProcessedTableManager(
|
return ProcessedTableManager(
|
||||||
manager.$state.copyWith(prefetchedData: cache));
|
manager.$state.copyWith(prefetchedData: cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MultiTypedResultKey<$GroupHistoriesTable, List<GroupHistory>>
|
||||||
|
_groupHistoriesRefsTable(_$TwonlyDB db) =>
|
||||||
|
MultiTypedResultKey.fromTable(db.groupHistories,
|
||||||
|
aliasName: $_aliasNameGenerator(
|
||||||
|
db.contacts.userId, db.groupHistories.contactId));
|
||||||
|
|
||||||
|
$$GroupHistoriesTableProcessedTableManager get groupHistoriesRefs {
|
||||||
|
final manager = $$GroupHistoriesTableTableManager($_db, $_db.groupHistories)
|
||||||
|
.filter(
|
||||||
|
(f) => f.contactId.userId.sqlEquals($_itemColumn<int>('user_id')!));
|
||||||
|
|
||||||
|
final cache = $_typedResult.readTableOrNull(_groupHistoriesRefsTable($_db));
|
||||||
|
return ProcessedTableManager(
|
||||||
|
manager.$state.copyWith(prefetchedData: cache));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$ContactsTableFilterComposer
|
class $$ContactsTableFilterComposer
|
||||||
|
|
@ -8078,6 +8182,27 @@ class $$ContactsTableFilterComposer
|
||||||
));
|
));
|
||||||
return f(composer);
|
return f(composer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression<bool> groupHistoriesRefs(
|
||||||
|
Expression<bool> Function($$GroupHistoriesTableFilterComposer f) f) {
|
||||||
|
final $$GroupHistoriesTableFilterComposer composer = $composerBuilder(
|
||||||
|
composer: this,
|
||||||
|
getCurrentColumn: (t) => t.userId,
|
||||||
|
referencedTable: $db.groupHistories,
|
||||||
|
getReferencedColumn: (t) => t.contactId,
|
||||||
|
builder: (joinBuilder,
|
||||||
|
{$addJoinBuilderToRootComposer,
|
||||||
|
$removeJoinBuilderFromRootComposer}) =>
|
||||||
|
$$GroupHistoriesTableFilterComposer(
|
||||||
|
$db: $db,
|
||||||
|
$table: $db.groupHistories,
|
||||||
|
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||||
|
joinBuilder: joinBuilder,
|
||||||
|
$removeJoinBuilderFromRootComposer:
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
));
|
||||||
|
return f(composer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$ContactsTableOrderingComposer
|
class $$ContactsTableOrderingComposer
|
||||||
|
|
@ -8311,6 +8436,27 @@ class $$ContactsTableAnnotationComposer
|
||||||
));
|
));
|
||||||
return f(composer);
|
return f(composer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression<T> groupHistoriesRefs<T extends Object>(
|
||||||
|
Expression<T> Function($$GroupHistoriesTableAnnotationComposer a) f) {
|
||||||
|
final $$GroupHistoriesTableAnnotationComposer composer = $composerBuilder(
|
||||||
|
composer: this,
|
||||||
|
getCurrentColumn: (t) => t.userId,
|
||||||
|
referencedTable: $db.groupHistories,
|
||||||
|
getReferencedColumn: (t) => t.contactId,
|
||||||
|
builder: (joinBuilder,
|
||||||
|
{$addJoinBuilderToRootComposer,
|
||||||
|
$removeJoinBuilderFromRootComposer}) =>
|
||||||
|
$$GroupHistoriesTableAnnotationComposer(
|
||||||
|
$db: $db,
|
||||||
|
$table: $db.groupHistories,
|
||||||
|
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||||
|
joinBuilder: joinBuilder,
|
||||||
|
$removeJoinBuilderFromRootComposer:
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
));
|
||||||
|
return f(composer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$ContactsTableTableManager extends RootTableManager<
|
class $$ContactsTableTableManager extends RootTableManager<
|
||||||
|
|
@ -8330,7 +8476,8 @@ class $$ContactsTableTableManager extends RootTableManager<
|
||||||
bool groupMembersRefs,
|
bool groupMembersRefs,
|
||||||
bool receiptsRefs,
|
bool receiptsRefs,
|
||||||
bool signalContactPreKeysRefs,
|
bool signalContactPreKeysRefs,
|
||||||
bool signalContactSignedPreKeysRefs})> {
|
bool signalContactSignedPreKeysRefs,
|
||||||
|
bool groupHistoriesRefs})> {
|
||||||
$$ContactsTableTableManager(_$TwonlyDB db, $ContactsTable table)
|
$$ContactsTableTableManager(_$TwonlyDB db, $ContactsTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
|
|
@ -8411,7 +8558,8 @@ class $$ContactsTableTableManager extends RootTableManager<
|
||||||
groupMembersRefs = false,
|
groupMembersRefs = false,
|
||||||
receiptsRefs = false,
|
receiptsRefs = false,
|
||||||
signalContactPreKeysRefs = false,
|
signalContactPreKeysRefs = false,
|
||||||
signalContactSignedPreKeysRefs = false}) {
|
signalContactSignedPreKeysRefs = false,
|
||||||
|
groupHistoriesRefs = false}) {
|
||||||
return PrefetchHooks(
|
return PrefetchHooks(
|
||||||
db: db,
|
db: db,
|
||||||
explicitlyWatchedTables: [
|
explicitlyWatchedTables: [
|
||||||
|
|
@ -8421,7 +8569,8 @@ class $$ContactsTableTableManager extends RootTableManager<
|
||||||
if (receiptsRefs) db.receipts,
|
if (receiptsRefs) db.receipts,
|
||||||
if (signalContactPreKeysRefs) db.signalContactPreKeys,
|
if (signalContactPreKeysRefs) db.signalContactPreKeys,
|
||||||
if (signalContactSignedPreKeysRefs)
|
if (signalContactSignedPreKeysRefs)
|
||||||
db.signalContactSignedPreKeys
|
db.signalContactSignedPreKeys,
|
||||||
|
if (groupHistoriesRefs) db.groupHistories
|
||||||
],
|
],
|
||||||
addJoins: null,
|
addJoins: null,
|
||||||
getPrefetchedDataCallback: (items) async {
|
getPrefetchedDataCallback: (items) async {
|
||||||
|
|
@ -8501,6 +8650,19 @@ class $$ContactsTableTableManager extends RootTableManager<
|
||||||
referencedItemsForCurrentItem:
|
referencedItemsForCurrentItem:
|
||||||
(item, referencedItems) => referencedItems
|
(item, referencedItems) => referencedItems
|
||||||
.where((e) => e.contactId == item.userId),
|
.where((e) => e.contactId == item.userId),
|
||||||
|
typedResults: items),
|
||||||
|
if (groupHistoriesRefs)
|
||||||
|
await $_getPrefetchedData<Contact, $ContactsTable,
|
||||||
|
GroupHistory>(
|
||||||
|
currentTable: table,
|
||||||
|
referencedTable: $$ContactsTableReferences
|
||||||
|
._groupHistoriesRefsTable(db),
|
||||||
|
managerFromTypedResult: (p0) =>
|
||||||
|
$$ContactsTableReferences(db, table, p0)
|
||||||
|
.groupHistoriesRefs,
|
||||||
|
referencedItemsForCurrentItem:
|
||||||
|
(item, referencedItems) => referencedItems
|
||||||
|
.where((e) => e.contactId == item.userId),
|
||||||
typedResults: items)
|
typedResults: items)
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|
@ -8526,7 +8688,8 @@ typedef $$ContactsTableProcessedTableManager = ProcessedTableManager<
|
||||||
bool groupMembersRefs,
|
bool groupMembersRefs,
|
||||||
bool receiptsRefs,
|
bool receiptsRefs,
|
||||||
bool signalContactPreKeysRefs,
|
bool signalContactPreKeysRefs,
|
||||||
bool signalContactSignedPreKeysRefs})>;
|
bool signalContactSignedPreKeysRefs,
|
||||||
|
bool groupHistoriesRefs})>;
|
||||||
typedef $$GroupsTableCreateCompanionBuilder = GroupsCompanion Function({
|
typedef $$GroupsTableCreateCompanionBuilder = GroupsCompanion Function({
|
||||||
required String groupId,
|
required String groupId,
|
||||||
Value<bool> isGroupAdmin,
|
Value<bool> isGroupAdmin,
|
||||||
|
|
@ -9273,6 +9436,7 @@ typedef $$MediaFilesTableCreateCompanionBuilder = MediaFilesCompanion Function({
|
||||||
Value<Uint8List?> encryptionKey,
|
Value<Uint8List?> encryptionKey,
|
||||||
Value<Uint8List?> encryptionMac,
|
Value<Uint8List?> encryptionMac,
|
||||||
Value<Uint8List?> encryptionNonce,
|
Value<Uint8List?> encryptionNonce,
|
||||||
|
Value<Uint8List?> storedFileHash,
|
||||||
Value<DateTime> createdAt,
|
Value<DateTime> createdAt,
|
||||||
Value<int> rowid,
|
Value<int> rowid,
|
||||||
});
|
});
|
||||||
|
|
@ -9291,6 +9455,7 @@ typedef $$MediaFilesTableUpdateCompanionBuilder = MediaFilesCompanion Function({
|
||||||
Value<Uint8List?> encryptionKey,
|
Value<Uint8List?> encryptionKey,
|
||||||
Value<Uint8List?> encryptionMac,
|
Value<Uint8List?> encryptionMac,
|
||||||
Value<Uint8List?> encryptionNonce,
|
Value<Uint8List?> encryptionNonce,
|
||||||
|
Value<Uint8List?> storedFileHash,
|
||||||
Value<DateTime> createdAt,
|
Value<DateTime> createdAt,
|
||||||
Value<int> rowid,
|
Value<int> rowid,
|
||||||
});
|
});
|
||||||
|
|
@ -9377,6 +9542,10 @@ class $$MediaFilesTableFilterComposer
|
||||||
column: $table.encryptionNonce,
|
column: $table.encryptionNonce,
|
||||||
builder: (column) => ColumnFilters(column));
|
builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
|
ColumnFilters<Uint8List> get storedFileHash => $composableBuilder(
|
||||||
|
column: $table.storedFileHash,
|
||||||
|
builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
ColumnFilters<DateTime> get createdAt => $composableBuilder(
|
ColumnFilters<DateTime> get createdAt => $composableBuilder(
|
||||||
column: $table.createdAt, builder: (column) => ColumnFilters(column));
|
column: $table.createdAt, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
|
|
@ -9462,6 +9631,10 @@ class $$MediaFilesTableOrderingComposer
|
||||||
column: $table.encryptionNonce,
|
column: $table.encryptionNonce,
|
||||||
builder: (column) => ColumnOrderings(column));
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
|
ColumnOrderings<Uint8List> get storedFileHash => $composableBuilder(
|
||||||
|
column: $table.storedFileHash,
|
||||||
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<DateTime> get createdAt => $composableBuilder(
|
ColumnOrderings<DateTime> get createdAt => $composableBuilder(
|
||||||
column: $table.createdAt, builder: (column) => ColumnOrderings(column));
|
column: $table.createdAt, builder: (column) => ColumnOrderings(column));
|
||||||
}
|
}
|
||||||
|
|
@ -9520,6 +9693,9 @@ class $$MediaFilesTableAnnotationComposer
|
||||||
GeneratedColumn<Uint8List> get encryptionNonce => $composableBuilder(
|
GeneratedColumn<Uint8List> get encryptionNonce => $composableBuilder(
|
||||||
column: $table.encryptionNonce, builder: (column) => column);
|
column: $table.encryptionNonce, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<Uint8List> get storedFileHash => $composableBuilder(
|
||||||
|
column: $table.storedFileHash, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<DateTime> get createdAt =>
|
GeneratedColumn<DateTime> get createdAt =>
|
||||||
$composableBuilder(column: $table.createdAt, builder: (column) => column);
|
$composableBuilder(column: $table.createdAt, builder: (column) => column);
|
||||||
|
|
||||||
|
|
@ -9582,6 +9758,7 @@ class $$MediaFilesTableTableManager extends RootTableManager<
|
||||||
Value<Uint8List?> encryptionKey = const Value.absent(),
|
Value<Uint8List?> encryptionKey = const Value.absent(),
|
||||||
Value<Uint8List?> encryptionMac = const Value.absent(),
|
Value<Uint8List?> encryptionMac = const Value.absent(),
|
||||||
Value<Uint8List?> encryptionNonce = const Value.absent(),
|
Value<Uint8List?> encryptionNonce = const Value.absent(),
|
||||||
|
Value<Uint8List?> storedFileHash = const Value.absent(),
|
||||||
Value<DateTime> createdAt = const Value.absent(),
|
Value<DateTime> createdAt = const Value.absent(),
|
||||||
Value<int> rowid = const Value.absent(),
|
Value<int> rowid = const Value.absent(),
|
||||||
}) =>
|
}) =>
|
||||||
|
|
@ -9600,6 +9777,7 @@ class $$MediaFilesTableTableManager extends RootTableManager<
|
||||||
encryptionKey: encryptionKey,
|
encryptionKey: encryptionKey,
|
||||||
encryptionMac: encryptionMac,
|
encryptionMac: encryptionMac,
|
||||||
encryptionNonce: encryptionNonce,
|
encryptionNonce: encryptionNonce,
|
||||||
|
storedFileHash: storedFileHash,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
rowid: rowid,
|
rowid: rowid,
|
||||||
),
|
),
|
||||||
|
|
@ -9618,6 +9796,7 @@ class $$MediaFilesTableTableManager extends RootTableManager<
|
||||||
Value<Uint8List?> encryptionKey = const Value.absent(),
|
Value<Uint8List?> encryptionKey = const Value.absent(),
|
||||||
Value<Uint8List?> encryptionMac = const Value.absent(),
|
Value<Uint8List?> encryptionMac = const Value.absent(),
|
||||||
Value<Uint8List?> encryptionNonce = const Value.absent(),
|
Value<Uint8List?> encryptionNonce = const Value.absent(),
|
||||||
|
Value<Uint8List?> storedFileHash = const Value.absent(),
|
||||||
Value<DateTime> createdAt = const Value.absent(),
|
Value<DateTime> createdAt = const Value.absent(),
|
||||||
Value<int> rowid = const Value.absent(),
|
Value<int> rowid = const Value.absent(),
|
||||||
}) =>
|
}) =>
|
||||||
|
|
@ -9636,6 +9815,7 @@ class $$MediaFilesTableTableManager extends RootTableManager<
|
||||||
encryptionKey: encryptionKey,
|
encryptionKey: encryptionKey,
|
||||||
encryptionMac: encryptionMac,
|
encryptionMac: encryptionMac,
|
||||||
encryptionNonce: encryptionNonce,
|
encryptionNonce: encryptionNonce,
|
||||||
|
storedFileHash: storedFileHash,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
rowid: rowid,
|
rowid: rowid,
|
||||||
),
|
),
|
||||||
|
|
@ -11590,6 +11770,7 @@ typedef $$ReceiptsTableCreateCompanionBuilder = ReceiptsCompanion Function({
|
||||||
Value<String?> messageId,
|
Value<String?> messageId,
|
||||||
required Uint8List message,
|
required Uint8List message,
|
||||||
Value<bool> contactWillSendsReceipt,
|
Value<bool> contactWillSendsReceipt,
|
||||||
|
Value<DateTime?> markForRetry,
|
||||||
Value<DateTime?> ackByServerAt,
|
Value<DateTime?> ackByServerAt,
|
||||||
Value<int> retryCount,
|
Value<int> retryCount,
|
||||||
Value<DateTime?> lastRetry,
|
Value<DateTime?> lastRetry,
|
||||||
|
|
@ -11602,6 +11783,7 @@ typedef $$ReceiptsTableUpdateCompanionBuilder = ReceiptsCompanion Function({
|
||||||
Value<String?> messageId,
|
Value<String?> messageId,
|
||||||
Value<Uint8List> message,
|
Value<Uint8List> message,
|
||||||
Value<bool> contactWillSendsReceipt,
|
Value<bool> contactWillSendsReceipt,
|
||||||
|
Value<DateTime?> markForRetry,
|
||||||
Value<DateTime?> ackByServerAt,
|
Value<DateTime?> ackByServerAt,
|
||||||
Value<int> retryCount,
|
Value<int> retryCount,
|
||||||
Value<DateTime?> lastRetry,
|
Value<DateTime?> lastRetry,
|
||||||
|
|
@ -11663,6 +11845,9 @@ class $$ReceiptsTableFilterComposer
|
||||||
column: $table.contactWillSendsReceipt,
|
column: $table.contactWillSendsReceipt,
|
||||||
builder: (column) => ColumnFilters(column));
|
builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
|
ColumnFilters<DateTime> get markForRetry => $composableBuilder(
|
||||||
|
column: $table.markForRetry, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
ColumnFilters<DateTime> get ackByServerAt => $composableBuilder(
|
ColumnFilters<DateTime> get ackByServerAt => $composableBuilder(
|
||||||
column: $table.ackByServerAt, builder: (column) => ColumnFilters(column));
|
column: $table.ackByServerAt, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
|
|
@ -11735,6 +11920,10 @@ class $$ReceiptsTableOrderingComposer
|
||||||
column: $table.contactWillSendsReceipt,
|
column: $table.contactWillSendsReceipt,
|
||||||
builder: (column) => ColumnOrderings(column));
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
|
ColumnOrderings<DateTime> get markForRetry => $composableBuilder(
|
||||||
|
column: $table.markForRetry,
|
||||||
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<DateTime> get ackByServerAt => $composableBuilder(
|
ColumnOrderings<DateTime> get ackByServerAt => $composableBuilder(
|
||||||
column: $table.ackByServerAt,
|
column: $table.ackByServerAt,
|
||||||
builder: (column) => ColumnOrderings(column));
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
@ -11807,6 +11996,9 @@ class $$ReceiptsTableAnnotationComposer
|
||||||
GeneratedColumn<bool> get contactWillSendsReceipt => $composableBuilder(
|
GeneratedColumn<bool> get contactWillSendsReceipt => $composableBuilder(
|
||||||
column: $table.contactWillSendsReceipt, builder: (column) => column);
|
column: $table.contactWillSendsReceipt, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<DateTime> get markForRetry => $composableBuilder(
|
||||||
|
column: $table.markForRetry, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<DateTime> get ackByServerAt => $composableBuilder(
|
GeneratedColumn<DateTime> get ackByServerAt => $composableBuilder(
|
||||||
column: $table.ackByServerAt, builder: (column) => column);
|
column: $table.ackByServerAt, builder: (column) => column);
|
||||||
|
|
||||||
|
|
@ -11888,6 +12080,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
|
||||||
Value<String?> messageId = const Value.absent(),
|
Value<String?> messageId = const Value.absent(),
|
||||||
Value<Uint8List> message = const Value.absent(),
|
Value<Uint8List> message = const Value.absent(),
|
||||||
Value<bool> contactWillSendsReceipt = const Value.absent(),
|
Value<bool> contactWillSendsReceipt = const Value.absent(),
|
||||||
|
Value<DateTime?> markForRetry = const Value.absent(),
|
||||||
Value<DateTime?> ackByServerAt = const Value.absent(),
|
Value<DateTime?> ackByServerAt = const Value.absent(),
|
||||||
Value<int> retryCount = const Value.absent(),
|
Value<int> retryCount = const Value.absent(),
|
||||||
Value<DateTime?> lastRetry = const Value.absent(),
|
Value<DateTime?> lastRetry = const Value.absent(),
|
||||||
|
|
@ -11900,6 +12093,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
|
||||||
messageId: messageId,
|
messageId: messageId,
|
||||||
message: message,
|
message: message,
|
||||||
contactWillSendsReceipt: contactWillSendsReceipt,
|
contactWillSendsReceipt: contactWillSendsReceipt,
|
||||||
|
markForRetry: markForRetry,
|
||||||
ackByServerAt: ackByServerAt,
|
ackByServerAt: ackByServerAt,
|
||||||
retryCount: retryCount,
|
retryCount: retryCount,
|
||||||
lastRetry: lastRetry,
|
lastRetry: lastRetry,
|
||||||
|
|
@ -11912,6 +12106,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
|
||||||
Value<String?> messageId = const Value.absent(),
|
Value<String?> messageId = const Value.absent(),
|
||||||
required Uint8List message,
|
required Uint8List message,
|
||||||
Value<bool> contactWillSendsReceipt = const Value.absent(),
|
Value<bool> contactWillSendsReceipt = const Value.absent(),
|
||||||
|
Value<DateTime?> markForRetry = const Value.absent(),
|
||||||
Value<DateTime?> ackByServerAt = const Value.absent(),
|
Value<DateTime?> ackByServerAt = const Value.absent(),
|
||||||
Value<int> retryCount = const Value.absent(),
|
Value<int> retryCount = const Value.absent(),
|
||||||
Value<DateTime?> lastRetry = const Value.absent(),
|
Value<DateTime?> lastRetry = const Value.absent(),
|
||||||
|
|
@ -11924,6 +12119,7 @@ class $$ReceiptsTableTableManager extends RootTableManager<
|
||||||
messageId: messageId,
|
messageId: messageId,
|
||||||
message: message,
|
message: message,
|
||||||
contactWillSendsReceipt: contactWillSendsReceipt,
|
contactWillSendsReceipt: contactWillSendsReceipt,
|
||||||
|
markForRetry: markForRetry,
|
||||||
ackByServerAt: ackByServerAt,
|
ackByServerAt: ackByServerAt,
|
||||||
retryCount: retryCount,
|
retryCount: retryCount,
|
||||||
lastRetry: lastRetry,
|
lastRetry: lastRetry,
|
||||||
|
|
@ -13600,21 +13796,6 @@ final class $$GroupHistoriesTableReferences
|
||||||
return ProcessedTableManager(
|
return ProcessedTableManager(
|
||||||
manager.$state.copyWith(prefetchedData: [item]));
|
manager.$state.copyWith(prefetchedData: [item]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static $ContactsTable _affectedContactIdTable(_$TwonlyDB db) =>
|
|
||||||
db.contacts.createAlias($_aliasNameGenerator(
|
|
||||||
db.groupHistories.affectedContactId, db.contacts.userId));
|
|
||||||
|
|
||||||
$$ContactsTableProcessedTableManager? get affectedContactId {
|
|
||||||
final $_column = $_itemColumn<int>('affected_contact_id');
|
|
||||||
if ($_column == null) return null;
|
|
||||||
final manager = $$ContactsTableTableManager($_db, $_db.contacts)
|
|
||||||
.filter((f) => f.userId.sqlEquals($_column));
|
|
||||||
final item = $_typedResult.readTableOrNull(_affectedContactIdTable($_db));
|
|
||||||
if (item == null) return manager;
|
|
||||||
return ProcessedTableManager(
|
|
||||||
manager.$state.copyWith(prefetchedData: [item]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$GroupHistoriesTableFilterComposer
|
class $$GroupHistoriesTableFilterComposer
|
||||||
|
|
@ -13630,6 +13811,10 @@ class $$GroupHistoriesTableFilterComposer
|
||||||
column: $table.groupHistoryId,
|
column: $table.groupHistoryId,
|
||||||
builder: (column) => ColumnFilters(column));
|
builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
|
ColumnFilters<int> get affectedContactId => $composableBuilder(
|
||||||
|
column: $table.affectedContactId,
|
||||||
|
builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
ColumnFilters<String> get oldGroupName => $composableBuilder(
|
ColumnFilters<String> get oldGroupName => $composableBuilder(
|
||||||
column: $table.oldGroupName, builder: (column) => ColumnFilters(column));
|
column: $table.oldGroupName, builder: (column) => ColumnFilters(column));
|
||||||
|
|
||||||
|
|
@ -13688,26 +13873,6 @@ class $$GroupHistoriesTableFilterComposer
|
||||||
));
|
));
|
||||||
return composer;
|
return composer;
|
||||||
}
|
}
|
||||||
|
|
||||||
$$ContactsTableFilterComposer get affectedContactId {
|
|
||||||
final $$ContactsTableFilterComposer composer = $composerBuilder(
|
|
||||||
composer: this,
|
|
||||||
getCurrentColumn: (t) => t.affectedContactId,
|
|
||||||
referencedTable: $db.contacts,
|
|
||||||
getReferencedColumn: (t) => t.userId,
|
|
||||||
builder: (joinBuilder,
|
|
||||||
{$addJoinBuilderToRootComposer,
|
|
||||||
$removeJoinBuilderFromRootComposer}) =>
|
|
||||||
$$ContactsTableFilterComposer(
|
|
||||||
$db: $db,
|
|
||||||
$table: $db.contacts,
|
|
||||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
|
||||||
joinBuilder: joinBuilder,
|
|
||||||
$removeJoinBuilderFromRootComposer:
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
));
|
|
||||||
return composer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$GroupHistoriesTableOrderingComposer
|
class $$GroupHistoriesTableOrderingComposer
|
||||||
|
|
@ -13723,6 +13888,10 @@ class $$GroupHistoriesTableOrderingComposer
|
||||||
column: $table.groupHistoryId,
|
column: $table.groupHistoryId,
|
||||||
builder: (column) => ColumnOrderings(column));
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
|
ColumnOrderings<int> get affectedContactId => $composableBuilder(
|
||||||
|
column: $table.affectedContactId,
|
||||||
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
||||||
ColumnOrderings<String> get oldGroupName => $composableBuilder(
|
ColumnOrderings<String> get oldGroupName => $composableBuilder(
|
||||||
column: $table.oldGroupName,
|
column: $table.oldGroupName,
|
||||||
builder: (column) => ColumnOrderings(column));
|
builder: (column) => ColumnOrderings(column));
|
||||||
|
|
@ -13781,26 +13950,6 @@ class $$GroupHistoriesTableOrderingComposer
|
||||||
));
|
));
|
||||||
return composer;
|
return composer;
|
||||||
}
|
}
|
||||||
|
|
||||||
$$ContactsTableOrderingComposer get affectedContactId {
|
|
||||||
final $$ContactsTableOrderingComposer composer = $composerBuilder(
|
|
||||||
composer: this,
|
|
||||||
getCurrentColumn: (t) => t.affectedContactId,
|
|
||||||
referencedTable: $db.contacts,
|
|
||||||
getReferencedColumn: (t) => t.userId,
|
|
||||||
builder: (joinBuilder,
|
|
||||||
{$addJoinBuilderToRootComposer,
|
|
||||||
$removeJoinBuilderFromRootComposer}) =>
|
|
||||||
$$ContactsTableOrderingComposer(
|
|
||||||
$db: $db,
|
|
||||||
$table: $db.contacts,
|
|
||||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
|
||||||
joinBuilder: joinBuilder,
|
|
||||||
$removeJoinBuilderFromRootComposer:
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
));
|
|
||||||
return composer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$GroupHistoriesTableAnnotationComposer
|
class $$GroupHistoriesTableAnnotationComposer
|
||||||
|
|
@ -13815,6 +13964,9 @@ class $$GroupHistoriesTableAnnotationComposer
|
||||||
GeneratedColumn<String> get groupHistoryId => $composableBuilder(
|
GeneratedColumn<String> get groupHistoryId => $composableBuilder(
|
||||||
column: $table.groupHistoryId, builder: (column) => column);
|
column: $table.groupHistoryId, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<int> get affectedContactId => $composableBuilder(
|
||||||
|
column: $table.affectedContactId, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<String> get oldGroupName => $composableBuilder(
|
GeneratedColumn<String> get oldGroupName => $composableBuilder(
|
||||||
column: $table.oldGroupName, builder: (column) => column);
|
column: $table.oldGroupName, builder: (column) => column);
|
||||||
|
|
||||||
|
|
@ -13871,26 +14023,6 @@ class $$GroupHistoriesTableAnnotationComposer
|
||||||
));
|
));
|
||||||
return composer;
|
return composer;
|
||||||
}
|
}
|
||||||
|
|
||||||
$$ContactsTableAnnotationComposer get affectedContactId {
|
|
||||||
final $$ContactsTableAnnotationComposer composer = $composerBuilder(
|
|
||||||
composer: this,
|
|
||||||
getCurrentColumn: (t) => t.affectedContactId,
|
|
||||||
referencedTable: $db.contacts,
|
|
||||||
getReferencedColumn: (t) => t.userId,
|
|
||||||
builder: (joinBuilder,
|
|
||||||
{$addJoinBuilderToRootComposer,
|
|
||||||
$removeJoinBuilderFromRootComposer}) =>
|
|
||||||
$$ContactsTableAnnotationComposer(
|
|
||||||
$db: $db,
|
|
||||||
$table: $db.contacts,
|
|
||||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
|
||||||
joinBuilder: joinBuilder,
|
|
||||||
$removeJoinBuilderFromRootComposer:
|
|
||||||
$removeJoinBuilderFromRootComposer,
|
|
||||||
));
|
|
||||||
return composer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$GroupHistoriesTableTableManager extends RootTableManager<
|
class $$GroupHistoriesTableTableManager extends RootTableManager<
|
||||||
|
|
@ -13904,8 +14036,7 @@ class $$GroupHistoriesTableTableManager extends RootTableManager<
|
||||||
$$GroupHistoriesTableUpdateCompanionBuilder,
|
$$GroupHistoriesTableUpdateCompanionBuilder,
|
||||||
(GroupHistory, $$GroupHistoriesTableReferences),
|
(GroupHistory, $$GroupHistoriesTableReferences),
|
||||||
GroupHistory,
|
GroupHistory,
|
||||||
PrefetchHooks Function(
|
PrefetchHooks Function({bool groupId, bool contactId})> {
|
||||||
{bool groupId, bool contactId, bool affectedContactId})> {
|
|
||||||
$$GroupHistoriesTableTableManager(_$TwonlyDB db, $GroupHistoriesTable table)
|
$$GroupHistoriesTableTableManager(_$TwonlyDB db, $GroupHistoriesTable table)
|
||||||
: super(TableManagerState(
|
: super(TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
|
|
@ -13974,8 +14105,7 @@ class $$GroupHistoriesTableTableManager extends RootTableManager<
|
||||||
$$GroupHistoriesTableReferences(db, table, e)
|
$$GroupHistoriesTableReferences(db, table, e)
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
prefetchHooksCallback: (
|
prefetchHooksCallback: ({groupId = false, contactId = false}) {
|
||||||
{groupId = false, contactId = false, affectedContactId = false}) {
|
|
||||||
return PrefetchHooks(
|
return PrefetchHooks(
|
||||||
db: db,
|
db: db,
|
||||||
explicitlyWatchedTables: [],
|
explicitlyWatchedTables: [],
|
||||||
|
|
@ -14014,17 +14144,6 @@ class $$GroupHistoriesTableTableManager extends RootTableManager<
|
||||||
.userId,
|
.userId,
|
||||||
) as T;
|
) as T;
|
||||||
}
|
}
|
||||||
if (affectedContactId) {
|
|
||||||
state = state.withJoin(
|
|
||||||
currentTable: table,
|
|
||||||
currentColumn: table.affectedContactId,
|
|
||||||
referencedTable: $$GroupHistoriesTableReferences
|
|
||||||
._affectedContactIdTable(db),
|
|
||||||
referencedColumn: $$GroupHistoriesTableReferences
|
|
||||||
._affectedContactIdTable(db)
|
|
||||||
.userId,
|
|
||||||
) as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
},
|
},
|
||||||
|
|
@ -14047,8 +14166,7 @@ typedef $$GroupHistoriesTableProcessedTableManager = ProcessedTableManager<
|
||||||
$$GroupHistoriesTableUpdateCompanionBuilder,
|
$$GroupHistoriesTableUpdateCompanionBuilder,
|
||||||
(GroupHistory, $$GroupHistoriesTableReferences),
|
(GroupHistory, $$GroupHistoriesTableReferences),
|
||||||
GroupHistory,
|
GroupHistory,
|
||||||
PrefetchHooks Function(
|
PrefetchHooks Function({bool groupId, bool contactId})>;
|
||||||
{bool groupId, bool contactId, bool affectedContactId})>;
|
|
||||||
|
|
||||||
class $TwonlyDBManager {
|
class $TwonlyDBManager {
|
||||||
final _$TwonlyDB _db;
|
final _$TwonlyDB _db;
|
||||||
|
|
|
||||||
|
|
@ -1946,10 +1946,458 @@ final class Schema4 extends i0.VersionedSchema {
|
||||||
i1.GeneratedColumn<int> _column_101(String aliasedName) =>
|
i1.GeneratedColumn<int> _column_101(String aliasedName) =>
|
||||||
i1.GeneratedColumn<int>('affected_contact_id', aliasedName, true,
|
i1.GeneratedColumn<int>('affected_contact_id', aliasedName, true,
|
||||||
type: i1.DriftSqlType.int);
|
type: i1.DriftSqlType.int);
|
||||||
|
|
||||||
|
final class Schema5 extends i0.VersionedSchema {
|
||||||
|
Schema5({required super.database}) : super(version: 5);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
contacts,
|
||||||
|
groups,
|
||||||
|
mediaFiles,
|
||||||
|
messages,
|
||||||
|
messageHistories,
|
||||||
|
reactions,
|
||||||
|
groupMembers,
|
||||||
|
receipts,
|
||||||
|
receivedReceipts,
|
||||||
|
signalIdentityKeyStores,
|
||||||
|
signalPreKeyStores,
|
||||||
|
signalSenderKeyStores,
|
||||||
|
signalSessionStores,
|
||||||
|
signalContactPreKeys,
|
||||||
|
signalContactSignedPreKeys,
|
||||||
|
messageActions,
|
||||||
|
groupHistories,
|
||||||
|
];
|
||||||
|
late final Shape0 contacts = Shape0(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'contacts',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(user_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
_column_6,
|
||||||
|
_column_7,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape17 groups = Shape17(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'groups',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(group_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_13,
|
||||||
|
_column_14,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_17,
|
||||||
|
_column_18,
|
||||||
|
_column_19,
|
||||||
|
_column_20,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_23,
|
||||||
|
_column_24,
|
||||||
|
_column_100,
|
||||||
|
_column_25,
|
||||||
|
_column_26,
|
||||||
|
_column_27,
|
||||||
|
_column_12,
|
||||||
|
_column_28,
|
||||||
|
_column_29,
|
||||||
|
_column_30,
|
||||||
|
_column_31,
|
||||||
|
_column_32,
|
||||||
|
_column_33,
|
||||||
|
_column_34,
|
||||||
|
_column_35,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape18 mediaFiles = Shape18(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'media_files',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(media_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_36,
|
||||||
|
_column_37,
|
||||||
|
_column_38,
|
||||||
|
_column_39,
|
||||||
|
_column_40,
|
||||||
|
_column_41,
|
||||||
|
_column_42,
|
||||||
|
_column_43,
|
||||||
|
_column_44,
|
||||||
|
_column_45,
|
||||||
|
_column_46,
|
||||||
|
_column_47,
|
||||||
|
_column_48,
|
||||||
|
_column_49,
|
||||||
|
_column_102,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape3 messages = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'messages',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(message_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_50,
|
||||||
|
_column_51,
|
||||||
|
_column_52,
|
||||||
|
_column_37,
|
||||||
|
_column_53,
|
||||||
|
_column_54,
|
||||||
|
_column_55,
|
||||||
|
_column_56,
|
||||||
|
_column_46,
|
||||||
|
_column_57,
|
||||||
|
_column_58,
|
||||||
|
_column_59,
|
||||||
|
_column_60,
|
||||||
|
_column_12,
|
||||||
|
_column_61,
|
||||||
|
_column_62,
|
||||||
|
_column_63,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape4 messageHistories = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'message_histories',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_64,
|
||||||
|
_column_65,
|
||||||
|
_column_66,
|
||||||
|
_column_53,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape5 reactions = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'reactions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(message_id, sender_id, emoji)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_65,
|
||||||
|
_column_67,
|
||||||
|
_column_68,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape6 groupMembers = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'group_members',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(group_id, contact_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_50,
|
||||||
|
_column_69,
|
||||||
|
_column_70,
|
||||||
|
_column_71,
|
||||||
|
_column_72,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape19 receipts = Shape19(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'receipts',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(receipt_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_73,
|
||||||
|
_column_74,
|
||||||
|
_column_75,
|
||||||
|
_column_76,
|
||||||
|
_column_77,
|
||||||
|
_column_103,
|
||||||
|
_column_78,
|
||||||
|
_column_79,
|
||||||
|
_column_80,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape8 receivedReceipts = Shape8(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'received_receipts',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(receipt_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_73,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape9 signalIdentityKeyStores = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_identity_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(device_id, name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_81,
|
||||||
|
_column_82,
|
||||||
|
_column_83,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape10 signalPreKeyStores = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_pre_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(pre_key_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_84,
|
||||||
|
_column_85,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape11 signalSenderKeyStores = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_sender_key_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(sender_key_name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_86,
|
||||||
|
_column_87,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape12 signalSessionStores = Shape12(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_session_stores',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(device_id, name)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_81,
|
||||||
|
_column_82,
|
||||||
|
_column_88,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape13 signalContactPreKeys = Shape13(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_contact_pre_keys',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(contact_id, pre_key_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_74,
|
||||||
|
_column_84,
|
||||||
|
_column_85,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape14 signalContactSignedPreKeys = Shape14(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'signal_contact_signed_pre_keys',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(contact_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_74,
|
||||||
|
_column_89,
|
||||||
|
_column_90,
|
||||||
|
_column_91,
|
||||||
|
_column_12,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape15 messageActions = Shape15(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'message_actions',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(message_id, contact_id, type)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_65,
|
||||||
|
_column_92,
|
||||||
|
_column_37,
|
||||||
|
_column_93,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
late final Shape16 groupHistories = Shape16(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'group_histories',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [
|
||||||
|
'PRIMARY KEY(group_history_id)',
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
_column_94,
|
||||||
|
_column_50,
|
||||||
|
_column_95,
|
||||||
|
_column_101,
|
||||||
|
_column_97,
|
||||||
|
_column_98,
|
||||||
|
_column_99,
|
||||||
|
_column_37,
|
||||||
|
_column_93,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape18 extends i0.VersionedTable {
|
||||||
|
Shape18({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get mediaId =>
|
||||||
|
columnsByName['media_id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get type =>
|
||||||
|
columnsByName['type']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get uploadState =>
|
||||||
|
columnsByName['upload_state']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get downloadState =>
|
||||||
|
columnsByName['download_state']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<bool> get requiresAuthentication =>
|
||||||
|
columnsByName['requires_authentication']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<bool> get stored =>
|
||||||
|
columnsByName['stored']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<bool> get isDraftMedia =>
|
||||||
|
columnsByName['is_draft_media']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<String> get reuploadRequestedBy =>
|
||||||
|
columnsByName['reupload_requested_by']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<int> get displayLimitInMilliseconds =>
|
||||||
|
columnsByName['display_limit_in_milliseconds']!
|
||||||
|
as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<bool> get removeAudio =>
|
||||||
|
columnsByName['remove_audio']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get downloadToken =>
|
||||||
|
columnsByName['download_token']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get encryptionKey =>
|
||||||
|
columnsByName['encryption_key']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get encryptionMac =>
|
||||||
|
columnsByName['encryption_mac']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get encryptionNonce =>
|
||||||
|
columnsByName['encryption_nonce']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get storedFileHash =>
|
||||||
|
columnsByName['stored_file_hash']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> _column_102(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<i2.Uint8List>('stored_file_hash', aliasedName, true,
|
||||||
|
type: i1.DriftSqlType.blob);
|
||||||
|
|
||||||
|
class Shape19 extends i0.VersionedTable {
|
||||||
|
Shape19({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get receiptId =>
|
||||||
|
columnsByName['receipt_id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<int> get contactId =>
|
||||||
|
columnsByName['contact_id']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get messageId =>
|
||||||
|
columnsByName['message_id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<i2.Uint8List> get message =>
|
||||||
|
columnsByName['message']! as i1.GeneratedColumn<i2.Uint8List>;
|
||||||
|
i1.GeneratedColumn<bool> get contactWillSendsReceipt =>
|
||||||
|
columnsByName['contact_will_sends_receipt']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<DateTime> get markForRetry =>
|
||||||
|
columnsByName['mark_for_retry']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<DateTime> get ackByServerAt =>
|
||||||
|
columnsByName['ack_by_server_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<int> get retryCount =>
|
||||||
|
columnsByName['retry_count']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<DateTime> get lastRetry =>
|
||||||
|
columnsByName['last_retry']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<DateTime> _column_103(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<DateTime>('mark_for_retry', aliasedName, true,
|
||||||
|
type: i1.DriftSqlType.dateTime);
|
||||||
i0.MigrationStepWithVersion migrationSteps({
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
|
||||||
}) {
|
}) {
|
||||||
return (currentVersion, database) async {
|
return (currentVersion, database) async {
|
||||||
switch (currentVersion) {
|
switch (currentVersion) {
|
||||||
|
|
@ -1968,6 +2416,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||||
final migrator = i1.Migrator(database, schema);
|
final migrator = i1.Migrator(database, schema);
|
||||||
await from3To4(migrator, schema);
|
await from3To4(migrator, schema);
|
||||||
return 4;
|
return 4;
|
||||||
|
case 4:
|
||||||
|
final schema = Schema5(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from4To5(migrator, schema);
|
||||||
|
return 5;
|
||||||
default:
|
default:
|
||||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
}
|
}
|
||||||
|
|
@ -1978,10 +2431,12 @@ i1.OnUpgrade stepByStep({
|
||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema5 schema) from4To5,
|
||||||
}) =>
|
}) =>
|
||||||
i0.VersionedSchema.stepByStepHelper(
|
i0.VersionedSchema.stepByStepHelper(
|
||||||
step: migrationSteps(
|
step: migrationSteps(
|
||||||
from1To2: from1To2,
|
from1To2: from1To2,
|
||||||
from2To3: from2To3,
|
from2To3: from2To3,
|
||||||
from3To4: from3To4,
|
from3To4: from3To4,
|
||||||
|
from4To5: from4To5,
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:drift_flutter/drift_flutter.dart'
|
import 'package:drift_flutter/drift_flutter.dart'
|
||||||
show DriftNativeOptions, driftDatabase;
|
show DriftNativeOptions, driftDatabase;
|
||||||
|
|
@ -191,7 +192,7 @@ class TwonlyDatabaseOld extends _$TwonlyDatabaseOld {
|
||||||
await (delete(signalPreKeyStores)
|
await (delete(signalPreKeyStores)
|
||||||
..where(
|
..where(
|
||||||
(t) => (t.createdAt.isSmallerThanValue(
|
(t) => (t.createdAt.isSmallerThanValue(
|
||||||
DateTime.now().subtract(
|
clock.now().subtract(
|
||||||
const Duration(days: 25),
|
const Duration(days: 25),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|
|
||||||
|
|
@ -1,459 +0,0 @@
|
||||||
{
|
|
||||||
"@@locale": "de",
|
|
||||||
"registerTitle": "Willkommen bei twonly!",
|
|
||||||
"registerSlogan": "twonly, eine private und sichere Möglichkeit um mit Freunden in Kontakt zu bleiben.",
|
|
||||||
"onboardingWelcomeTitle": "Willkommen bei twonly!",
|
|
||||||
"onboardingWelcomeBody": "Erlebe eine private und sichere Möglichkeit mit Freunden in Kontakt zu bleiben, indem du spontane Bilder teilst.",
|
|
||||||
"onboardingE2eTitle": "Unbekümmert teilen",
|
|
||||||
"onboardingE2eBody": "Genieße durch die Ende-zu-Ende-Verschlüsselung die Gewissheit, dass nur du und deine Freunde die geteilten Momente sehen können.",
|
|
||||||
"onboardingFocusTitle": "Fokussiere dich auf das Teilen von Momenten",
|
|
||||||
"onboardingFocusBody": "Verabschiede dich von süchtig machenden Funktionen! twonly wurde für das Teilen von Momenten ohne nutzlose Ablenkungen oder Werbung entwickelt.",
|
|
||||||
"onboardingSendTwonliesTitle": "twonlies senden",
|
|
||||||
"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!",
|
|
||||||
"onboardingNotProductTitle": "Du bist nicht das Produkt!",
|
|
||||||
"onboardingNotProductBody": "twonly wird durch Spenden und ein optionales Abonnement finanziert. Deine Daten werden niemals verkauft.",
|
|
||||||
"onboardingBuyOneGetTwoTitle": "Kaufe eins, bekomme zwei",
|
|
||||||
"onboardingBuyOneGetTwoBody": "twonly benötigt immer mindestens zwei Personen, daher erhältst du beim Kauf eine zweite kostenlose Lizenz für deinen twonly-Partner.",
|
|
||||||
"onboardingGetStartedTitle": "Auf geht's",
|
|
||||||
"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.",
|
|
||||||
"onboardingTryForFree": "Jetzt registrieren",
|
|
||||||
"registerUsernameSlogan": "Bitte wähle einen Benutzernamen, damit dich andere finden können!",
|
|
||||||
"registerUsernameDecoration": "Benutzername",
|
|
||||||
"registerUsernameLimits": "Der Benutzername muss mindestens 3 Zeichen lang sein.",
|
|
||||||
"registerSubmitButton": "Jetzt registrieren!",
|
|
||||||
"registerTwonlyCodeText": "Hast du einen twonly-Code erhalten? Dann löse ihn entweder direkt hier oder später ein!",
|
|
||||||
"registerTwonlyCodeLabel": "twonly-Code",
|
|
||||||
"newMessageTitle": "Neue Nachricht",
|
|
||||||
"chatsTapToSend": "Klicke, um dein erstes Bild zu teilen.",
|
|
||||||
"cameraPreviewSendTo": "Senden an",
|
|
||||||
"shareImageTitle": "Teilen mit",
|
|
||||||
"shareImageBestFriends": "Beste Freunde",
|
|
||||||
"shareImagePinnedContacts": "Angeheftet",
|
|
||||||
"shareImagedEditorSendImage": "Senden",
|
|
||||||
"shareImagedEditorShareWith": "Teilen mit",
|
|
||||||
"shareImagedEditorSaveImage": "Speichern",
|
|
||||||
"shareImagedEditorSavedImage": "Gespeichert",
|
|
||||||
"shareImagedSelectAll": "Alle auswählen",
|
|
||||||
"shareImageAllUsers": "Alle Kontakte",
|
|
||||||
"shareImageAllTwonlyWarning": "twonlies können nur an verifizierte Kontakte gesendet werden!",
|
|
||||||
"shareImageSearchAllContacts": "Alle Kontakte durchsuchen",
|
|
||||||
"shareImageUserNotVerified": "Benutzer ist nicht verifiziert",
|
|
||||||
"shareImageUserNotVerifiedDesc": "twonlies können nur an verifizierte Nutzer gesendet werden. Um einen Nutzer zu verifizieren, gehe auf sein Profil und auf „Sicherheitsnummer verifizieren“.",
|
|
||||||
"shareImageShowArchived": "Archivierte Benutzer anzeigen",
|
|
||||||
"startNewChatSearchHint": "Name, Benutzername oder Gruppenname",
|
|
||||||
"searchUsernameInput": "Benutzername",
|
|
||||||
"searchUsernameTitle": "Benutzernamen suchen",
|
|
||||||
"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!",
|
|
||||||
"selectSubscription": "Abo auswählen",
|
|
||||||
"searchUsernameNotFound": "Benutzername nicht gefunden",
|
|
||||||
"searchUsernameNotFoundBody": "Es wurde kein Benutzer mit dem Benutzernamen \"{username}\" gefunden.",
|
|
||||||
"searchUsernameNewFollowerTitle": "Folgeanfragen",
|
|
||||||
"searchUsernameQrCodeBtn": "QR-Code scannen",
|
|
||||||
"searchUserNamePending": "Ausstehend",
|
|
||||||
"searchUserNameBlockUserTooltip": "Benutzer ohne Benachrichtigung blockieren.",
|
|
||||||
"searchUserNameRejectUserTooltip": "Die Anfrage ablehnen und den Anfragenden informieren.",
|
|
||||||
"searchUserNameArchiveUserTooltip": "Benutzer archivieren. Du wirst informiert sobald er deine Anfrage akzeptiert.",
|
|
||||||
"userFound": "{username} gefunden",
|
|
||||||
"userFoundBody": "Möchtest du eine Folgeanfrage stellen?",
|
|
||||||
"chatListViewSearchUserNameBtn": "Füge deinen ersten twonly-Kontakt hinzu!",
|
|
||||||
"chatListViewSendFirstTwonly": "Sende dein erstes twonly!",
|
|
||||||
"chatListDetailInput": "Nachricht eingeben",
|
|
||||||
"userDeletedAccount": "Der Nutzer hat sein Konto gelöscht.",
|
|
||||||
"contextMenuUserProfile": "Userprofil",
|
|
||||||
"contextMenuVerifyUser": "Verifizieren",
|
|
||||||
"contextMenuArchiveUser": "Archivieren",
|
|
||||||
"contextMenuUndoArchiveUser": "Archivierung aufheben",
|
|
||||||
"startNewChatTitle": "Kontakt wählen",
|
|
||||||
"startNewChatNewContact": "Neuer Kontakt",
|
|
||||||
"startNewChatYourContacts": "Deine Kontakte",
|
|
||||||
"contextMenuOpenChat": "Chat",
|
|
||||||
"contextMenuPin": "Anheften",
|
|
||||||
"contextMenuUnpin": "Lösen",
|
|
||||||
"mediaViewerAuthReason": "Bitte authentifiziere dich, um diesen twonly zu sehen!",
|
|
||||||
"mediaViewerTwonlyTapToOpen": "Tippe um den twonly zu öffnen!",
|
|
||||||
"messageSendState_Received": "Empfangen",
|
|
||||||
"messageSendState_Opened": "Geöffnet",
|
|
||||||
"messageSendState_Send": "Gesendet",
|
|
||||||
"messageSendState_Sending": "Wird gesendet",
|
|
||||||
"messageSendState_TapToLoad": "Tippe zum Laden",
|
|
||||||
"messageSendState_Loading": "Herunterladen",
|
|
||||||
"messageStoredInGallery": "Gespeichert",
|
|
||||||
"messageReopened": "Erneut geöffnet",
|
|
||||||
"imageEditorDrawOk": "Zeichnung machen",
|
|
||||||
"settingsTitle": "Einstellungen",
|
|
||||||
"settingsChats": "Chats",
|
|
||||||
"settingsStorageData": "Daten und Speicher",
|
|
||||||
"settingsStorageDataStoreInGTitle": "In der Galerie speichern",
|
|
||||||
"settingsStorageDataStoreInGSubtitle": "Speichere Bilder zusätzlich in der Systemgalerie.",
|
|
||||||
"settingsStorageDataMediaAutoDownload": "Automatischer Mediendownload",
|
|
||||||
"settingsStorageDataAutoDownMobile": "Bei Nutzung mobiler Daten",
|
|
||||||
"settingsStorageDataAutoDownWifi": "Bei Nutzung von WLAN",
|
|
||||||
"settingsPreSelectedReactions": "Vorgewählte Reaktions-Emojis",
|
|
||||||
"settingsPreSelectedReactionsError": "Es können maximal 12 Reaktionen ausgewählt werden.",
|
|
||||||
"settingsProfile": "Profil",
|
|
||||||
"settingsProfileCustomizeAvatar": "Avatar anpassen",
|
|
||||||
"settingsProfileEditDisplayName": "Anzeigename",
|
|
||||||
"settingsProfileEditDisplayNameNew": "Neuer Anzeigename",
|
|
||||||
"settingsAccount": "Konto",
|
|
||||||
"settingsSubscription": "Abonnement",
|
|
||||||
"settingsAppearance": "Erscheinungsbild",
|
|
||||||
"settingsPrivacy": "Datenschutz",
|
|
||||||
"settingsPrivacyBlockUsers": "Benutzer blockieren",
|
|
||||||
"settingsPrivacyBlockUsersDesc": "Blockierte Benutzer können nicht mit dir kommunizieren. Du kannst einen blockierten Benutzer jederzeit wieder entsperren.",
|
|
||||||
"settingsPrivacyBlockUsersCount": "{len} Kontakt(e)",
|
|
||||||
"settingsNotification": "Benachrichtigung",
|
|
||||||
"settingsNotifyTroubleshooting": "Fehlersuche",
|
|
||||||
"settingsNotifyTroubleshootingDesc": "Hier klicken, wenn Probleme beim Empfang von Push-Benachrichtigungen auftreten.",
|
|
||||||
"settingsNotifyTroubleshootingNoProblem": "Kein Problem festgestellt",
|
|
||||||
"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.",
|
|
||||||
"settingsHelp": "Hilfe",
|
|
||||||
"settingsHelpFAQ": "FAQ",
|
|
||||||
"feedbackTooltip": "Feedback zur Verbesserung von twonly geben.",
|
|
||||||
"settingsHelpContactUs": "Kontaktiere uns",
|
|
||||||
"contactUsFaq": "FAQ schon gelesen?",
|
|
||||||
"contactUsEmojis": "Wie fühlst du dich? (optional)",
|
|
||||||
"contactUsSelectOption": "Bitte wähle eine Option",
|
|
||||||
"contactUsReason": "Sag uns, warum du uns kontaktierst",
|
|
||||||
"contactUsMessage": "Wenn du eine Antwort erhalten möchtest, füge bitte deine E-Mail-Adresse hinzu, damit wir dich kontaktieren können.",
|
|
||||||
"contactUsYourMessage": "Deine Nachricht",
|
|
||||||
"contactUsMessageTitle": "Erzähl uns, was los ist",
|
|
||||||
"contactUsReasonNotWorking": "Etwas funktioniert nicht",
|
|
||||||
"contactUsReasonFeatureRequest": "Funktionsanfrage",
|
|
||||||
"contactUsReasonQuestion": "Frage",
|
|
||||||
"contactUsReasonFeedback": "Feedback",
|
|
||||||
"contactUsReasonOther": "Sonstiges",
|
|
||||||
"contactUsIncludeLog": "Debug-Protokoll anhängen.",
|
|
||||||
"contactUsWhatsThat": "Was ist das?",
|
|
||||||
"contactUsLastWarning": "Dies sind die Informationen, die an uns gesendet werden. Bitte prüfen Sie sie und klicke dann auf „Abschicken“.",
|
|
||||||
"contactUsSuccess": "Feedback erfolgreich übermittelt!",
|
|
||||||
"contactUsShortcut": "Feedback-Symbol ausblenden",
|
|
||||||
"settingsHelpDiagnostics": "Diagnoseprotokoll",
|
|
||||||
"settingsHelpVersion": "Version",
|
|
||||||
"settingsHelpLicenses": "Lizenzen (Source-Code)",
|
|
||||||
"settingsHelpCredits": "Lizenzen (Bilder)",
|
|
||||||
"settingsHelpImprint": "Impressum & Datenschutzrichtlinie",
|
|
||||||
"settingsHelpTerms": "Nutzungsbedingungen",
|
|
||||||
"settingsAppearanceTheme": "Theme",
|
|
||||||
"settingsAccountDeleteAccount": "Konto löschen",
|
|
||||||
"settingsAccountDeleteAccountWithBallance": "Im nächsten Schritt kannst du auswählen, was du mit dem Restguthaben ({credit}) machen willst.",
|
|
||||||
"settingsAccountDeleteAccountNoInternet": "Zum Löschen deines Accounts ist eine Internetverbindung erforderlich.",
|
|
||||||
"settingsAccountDeleteAccountNoBallance": "Wenn du dein Konto gelöscht hast, gibt es keinen Weg zurück.",
|
|
||||||
"settingsAccountDeleteModalTitle": "Bist du sicher?",
|
|
||||||
"settingsAccountDeleteModalBody": "Dein Konto wird gelöscht. Es gibt keine Möglichkeit, es wiederherzustellen.",
|
|
||||||
"contactVerifyNumberTitle": "Sicherheitsnummer verifizieren",
|
|
||||||
"contactVerifyNumberTapToScan": "Zum Scannen tippen",
|
|
||||||
"contactVerifyNumberMarkAsVerified": "Als verifiziert markieren",
|
|
||||||
"contactVerifyNumberClearVerification": "Verifizierung aufheben",
|
|
||||||
"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.",
|
|
||||||
"contactNickname": "Spitzname",
|
|
||||||
"contactNicknameNew": "Neuer Spitzname",
|
|
||||||
"contactBlock": "Blockieren",
|
|
||||||
"contactRemove": "Benutzer löschen",
|
|
||||||
"contactRemoveTitle": "{username} löschen?",
|
|
||||||
"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.",
|
|
||||||
"deleteAllContactMessages": "Textnachrichten löschen",
|
|
||||||
"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!",
|
|
||||||
"contactBlockTitle": "Blockiere {username}",
|
|
||||||
"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.",
|
|
||||||
"undo": "Rückgängig",
|
|
||||||
"redo": "Wiederholen",
|
|
||||||
"next": "Weiter",
|
|
||||||
"submit": "Abschicken",
|
|
||||||
"close": "Schließen",
|
|
||||||
"cancel": "Abbrechen",
|
|
||||||
"edit": "Bearbeiten",
|
|
||||||
"ok": "Ok",
|
|
||||||
"now": "Jetzt",
|
|
||||||
"you": "Du",
|
|
||||||
"minutesShort": "Min.",
|
|
||||||
"image": "Bild",
|
|
||||||
"video": "Video",
|
|
||||||
"react": "Reagieren",
|
|
||||||
"reply": "Antworten",
|
|
||||||
"copy": "Kopieren",
|
|
||||||
"delete": "Löschen",
|
|
||||||
"info": "Info",
|
|
||||||
"disable": "Deaktiviern",
|
|
||||||
"enable": "Aktivieren",
|
|
||||||
"switchFrontAndBackCamera": "Zwischen Front- und Rückkamera wechseln.",
|
|
||||||
"addTextItem": "Text",
|
|
||||||
"protectAsARealTwonly": "Als echtes twonly senden!",
|
|
||||||
"addDrawing": "Zeichnung",
|
|
||||||
"addEmoji": "Emoji",
|
|
||||||
"toggleFlashLight": "Taschenlampe umschalten",
|
|
||||||
"toggleHighQuality": "Bessere Auflösung umschalten",
|
|
||||||
"searchUsernameNotFoundLong": "\"{username}\" ist kein twonly-Benutzer. Bitte überprüfe den Benutzernamen und versuche es erneut.",
|
|
||||||
"errorUnknown": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuche es später erneut.",
|
|
||||||
"errorBadRequest": "Die Anfrage konnte vom Server aufgrund einer fehlerhaften Syntax nicht verstanden werden. Bitte überprüfe deine Eingabe und versuche es erneut.",
|
|
||||||
"errorTooManyRequests": "Du hast in kurzer Zeit zu viele Anfragen gestellt. Bitte warte einen Moment, bevor du es erneut versuchst.",
|
|
||||||
"errorInternalError": "Der Server ist derzeit nicht verfügbar. Bitte versuche es später erneut.",
|
|
||||||
"errorInvalidInvitationCode": "Der von dir angegebene Einladungscode ist ungültig. Bitte überprüfe den Code und versuche es erneut.",
|
|
||||||
"errorUsernameAlreadyTaken": "Der Benutzername ist bereits vergeben.",
|
|
||||||
"errorSignatureNotValid": "Die bereitgestellte Signatur ist nicht gültig. Bitte überprüfe deine Anmeldeinformationen und versuche es erneut.",
|
|
||||||
"errorUsernameNotFound": "Der eingegebene Benutzername existiert nicht. Bitte überprüfe die Schreibweise oder erstelle ein neues Konto.",
|
|
||||||
"errorUsernameNotValid": "Der von dir angegebene Benutzername entspricht nicht den erforderlichen Kriterien. Bitte wähle einen gültigen Benutzernamen.",
|
|
||||||
"errorInvalidPublicKey": "Der von dir angegebene öffentliche Schlüssel ist ungültig. Bitte überprüfe den Schlüssel und versuche es erneut.",
|
|
||||||
"errorSessionAlreadyAuthenticated": "Du bist bereits angemeldet. Bitte melde dich ab, wenn du dich mit einem anderen Konto anmelden möchtest.",
|
|
||||||
"errorSessionNotAuthenticated": "Deine Sitzung ist nicht authentifiziert. Bitte melde dich an, um fortzufahren.",
|
|
||||||
"errorOnlyOneSessionAllowed": "Es ist nur eine aktive Sitzung pro Benutzer erlaubt. Bitte melde dich von anderen Geräten ab, um fortzufahren.",
|
|
||||||
"upgradeToPaidPlan": "Upgrade auf einen kostenpflichtigen Plan.",
|
|
||||||
"upgradeToPaidPlanButton": "Auf {planId} upgraden{sufix}",
|
|
||||||
"partOfPaidPlanOf": "Du bist Teil des bezahlten Plans von {username}!",
|
|
||||||
"errorNotEnoughCredit": "Du hast nicht genügend twonly-Guthaben.",
|
|
||||||
"errorPlanLimitReached": "Du hast das Limit deines Plans erreicht. Bitte upgrade deinen Plan.",
|
|
||||||
"errorPlanNotAllowed": "Dieses Feature ist in deinem aktuellen Plan nicht verfügbar.",
|
|
||||||
"errorVoucherInvalid": "Der eingegebene Gutschein-Code ist nicht gültig.",
|
|
||||||
"errorPlanUpgradeNotYearly": "Das Upgrade des Plans muss jährlich bezahlt werden, da der aktuelle Plan ebenfalls jährlich abgerechnet wird.",
|
|
||||||
"proFeature1": "✓ Unbegrenzte Medien-Datei-Uploads",
|
|
||||||
"proFeature2": "✓ 1 zusätzlicher Plus Benutzer",
|
|
||||||
"proFeature3": "✓ Flammen wiederherstellen",
|
|
||||||
"proFeature4": "✓ twonly unterstützen",
|
|
||||||
"year": "Jahr",
|
|
||||||
"month": "Monat",
|
|
||||||
"yearly": "Jährlich",
|
|
||||||
"monthly": "Monatlich",
|
|
||||||
"familyFeature1": "✓ Unbegrenzte Medien-Datei-Uploads",
|
|
||||||
"familyFeature2": "✓ 4 zusätzliche Plus Benutzer",
|
|
||||||
"familyFeature3": "✓ Flammen wiederherstellen",
|
|
||||||
"familyFeature4": "✓ twonly unterstützen",
|
|
||||||
"redeemUserInviteCode": "Oder löse einen twonly-Code ein.",
|
|
||||||
"freeFeature1": "✓ 10 Medien-Datei-Uploads pro Tag",
|
|
||||||
"plusFeature1": "✓ Unbegrenzte Medien-Datei-Uploads",
|
|
||||||
"plusFeature2": "✓ Zusatzfunktionen (coming-soon)",
|
|
||||||
"transactionHistory": "Transaktionshistorie",
|
|
||||||
"currentBalance": "Dein Guthaben",
|
|
||||||
"manageAdditionalUsers": "Zusätzliche Benutzer verwalten",
|
|
||||||
"manageSubscription": "Abonnement verwalten",
|
|
||||||
"nextPayment": "Nächste Zahlung",
|
|
||||||
"open": "Offene",
|
|
||||||
"buy": "Kaufen",
|
|
||||||
"createOrRedeemVoucher": "Gutschein erstellen oder einlösen",
|
|
||||||
"subscriptionRefund": "Wenn du ein Upgrade durchführst, erhältst du eine Rückerstattung von {refund} für dein aktuelles Abonnement.",
|
|
||||||
"createVoucher": "Gutschein kaufen",
|
|
||||||
"createVoucherDesc": "Wähle den Wert des Gutscheins. Der Wert des Gutschein wird von deinem twonly-Guthaben abgezogen.",
|
|
||||||
"redeemVoucher": "Gutschein einlösen",
|
|
||||||
"redeemUserInviteCodeTitle": "twonly-Code einlösen",
|
|
||||||
"redeemUserInviteCodeSuccess": "Dein Plan wurde erfolgreich angepasst.",
|
|
||||||
"voucherCreated": "Gutschein wurde erstellt",
|
|
||||||
"openVouchers": "Offene Gutscheine",
|
|
||||||
"enterVoucherCode": "Gutschein Code eingeben",
|
|
||||||
"voucherRedeemed": "Gutschein eingelöst",
|
|
||||||
"requestedVouchers": "Beantragte Gutscheine",
|
|
||||||
"redeemedVouchers": "Eingelöste Gutscheine",
|
|
||||||
"transactionCash": "Bargeldtransaktion",
|
|
||||||
"transactionPlanUpgrade": "Planupgrade",
|
|
||||||
"transactionRefund": "Rückerstattung",
|
|
||||||
"transactionAutoRenewal": "Automatische Verlängerung",
|
|
||||||
"refund": "Rückerstattung",
|
|
||||||
"transactionThanksForTesting": "Danke fürs Testen",
|
|
||||||
"transactionUnknown": "Unbekannte Transaktion",
|
|
||||||
"transactionVoucherCreated": "Gutschein erstellt",
|
|
||||||
"transactionVoucherRedeemed": "Gutschein eingelöst",
|
|
||||||
"checkoutOptions": "Optionen",
|
|
||||||
"checkoutPayYearly": "Jährlich bezahlen",
|
|
||||||
"checkoutTotal": "Gesamt",
|
|
||||||
"selectPaymentMethod": "Zahlungsmethode auswählen",
|
|
||||||
"twonlyCredit": "twonly-Guthaben",
|
|
||||||
"notEnoughCredit": "Du hast nicht genügend Guthaben!",
|
|
||||||
"chargeCredit": "Guthaben aufladen",
|
|
||||||
"autoRenewal": "Automatische Verlängerung",
|
|
||||||
"autoRenewalDesc": "Du kannst dies jederzeit ändern.",
|
|
||||||
"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.",
|
|
||||||
"planSuccessUpgraded": "Dein Plan wurde erfolgreich aktualisiert.",
|
|
||||||
"checkoutSubmit": "Kostenpflichtig bestellen",
|
|
||||||
"additionalUsersList": "Ihre zusätzlichen Benutzer",
|
|
||||||
"additionalUsersPlusTokens": "twonly-Codes für \"Plus\"-Benutzer",
|
|
||||||
"additionalUsersFreeTokens": "twonly-Codes für \"Free\"-Benutzer",
|
|
||||||
"planNotAllowed": "In deinem aktuellen Plan kannst du keine Mediendateien versenden. Aktualisiere deinen Plan jetzt, um die Mediendatei zu senden.",
|
|
||||||
"planLimitReached": "Du hast dein Planlimit für heute erreicht. Aktualisiere deinen Plan jetzt, um die Mediendatei zu senden.",
|
|
||||||
"galleryDelete": "Datei löschen",
|
|
||||||
"galleryExport": "In Galerie exportieren",
|
|
||||||
"galleryExportSuccess": "Erfolgreich in der Gallery gespeichert.",
|
|
||||||
"galleryDetails": "Details anzeigen",
|
|
||||||
"settingsResetTutorials": "Tutorials erneut anzeigen",
|
|
||||||
"settingsResetTutorialsDesc": "Klicke hier, um bereits angezeigte Tutorials erneut anzuzeigen.",
|
|
||||||
"settingsResetTutorialsSuccess": "Tutorials werden erneut angezeigt.",
|
|
||||||
"tutorialChatListSearchUsersTitle": "Freunde finden und Freundschaftsanfragen verwalten",
|
|
||||||
"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.",
|
|
||||||
"tutorialChatListContextMenuTitle": "Klicke lange auf den Kontakt, um das Kontextmenü zu öffnen.",
|
|
||||||
"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.",
|
|
||||||
"tutorialChatMessagesVerifyShieldTitle": "Verifiziere deine Kontakte!",
|
|
||||||
"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.",
|
|
||||||
"tutorialChatMessagesReopenMessageTitle": "Bilder und Videos erneut öffnen",
|
|
||||||
"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.",
|
|
||||||
"memoriesEmpty": "Sobald du Bilder oder Videos speicherst, landen sie hier in deinen Erinnerungen.",
|
|
||||||
"deleteTitle": "Bist du dir sicher?",
|
|
||||||
"deleteOkBtnForAll": "Für alle löschen",
|
|
||||||
"deleteOkBtnForMe": "Für mich löschen",
|
|
||||||
"deleteImageTitle": "Bist du dir sicher?",
|
|
||||||
"deleteImageBody": "Das Bild wird unwiderruflich gelöscht.",
|
|
||||||
"backupNoticeTitle": "Kein Backup konfiguriert",
|
|
||||||
"backupNoticeDesc": "Wenn du dein Gerät wechselst oder verlierst, kann ohne Backup niemand dein Account wiederherstellen. Sichere deshalb deine Daten.",
|
|
||||||
"backupNoticeLater": "Später erinnern",
|
|
||||||
"backupNoticeOpenBackup": "Backup erstellen",
|
|
||||||
"backupPending": "Ausstehend",
|
|
||||||
"backupFailed": "Fehlgeschlagen",
|
|
||||||
"backupSuccess": "Erfolgreich",
|
|
||||||
"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.",
|
|
||||||
"backupServer": "Server",
|
|
||||||
"backupMaxBackupSize": "max. Backup-Größe",
|
|
||||||
"backupStorageRetention": "Speicheraufbewahrung",
|
|
||||||
"backupLastBackupDate": "Letztes Backup",
|
|
||||||
"backupLastBackupSize": "Backup-Größe",
|
|
||||||
"backupLastBackupResult": "Ergebnis",
|
|
||||||
"deleteBackupTitle": "Bist du sicher?",
|
|
||||||
"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.",
|
|
||||||
"deleteBackupBody": "Ohne ein Backup kannst du dein Benutzerkonto nicht wiederherstellen.",
|
|
||||||
"backupData": "Daten-Backup",
|
|
||||||
"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.",
|
|
||||||
"backupInsecurePassword": "Unsicheres Passwort",
|
|
||||||
"backupInsecurePasswordDesc": "Das gewählte Passwort ist sehr unsicher und kann daher leicht von Angreifern erraten werden. Bitte wähle ein sicheres Passwort.",
|
|
||||||
"backupInsecurePasswordOk": "Trotzdem fortfahren",
|
|
||||||
"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 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.",
|
|
||||||
"backupSelectStrongPassword": "Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Backup wiederherstellen möchtest.",
|
|
||||||
"password": "Passwort",
|
|
||||||
"passwordRepeated": "Passwort wiederholen",
|
|
||||||
"passwordRepeatedNotEqual": "Passwörter stimmen nicht überein.",
|
|
||||||
"backupPasswordRequirement": "Das Passwort muss mindestens 8 Zeichen lang sein.",
|
|
||||||
"backupExpertSettings": "Experteneinstellungen",
|
|
||||||
"backupEnableBackup": "Automatische Sicherung aktivieren",
|
|
||||||
"backupOwnServerDesc": "Speichere dein twonly Backup auf einem Server deiner Wahl.",
|
|
||||||
"backupUseOwnServer": "Server verwenden",
|
|
||||||
"backupResetServer": "Standardserver verwenden",
|
|
||||||
"backupTwonlySaveNow": "Jetzt speichern",
|
|
||||||
"backupChangePassword": "Password ändern",
|
|
||||||
"inviteFriends": "Freunde einladen",
|
|
||||||
"inviteFriendsShareBtn": "Teilen",
|
|
||||||
"inviteFriendsShareText": "Wechseln wir zu twonly: {url}",
|
|
||||||
"appOutdated": "Deine Version von twonly ist veraltet.",
|
|
||||||
"appOutdatedBtn": "Jetzt aktualisieren.",
|
|
||||||
"doubleClickToReopen": "Doppelklicken zum\nerneuten Öffnen.",
|
|
||||||
"uploadLimitReached": "Das Upload-Limit wurde\nerreicht. Upgrade auf Pro\noder warte bis morgen.",
|
|
||||||
"retransmissionRequested": "Wird erneut versucht.",
|
|
||||||
"testPaymentMethod": "Vielen Dank für dein Interesse an einem kostenpflichtigen Tarif. Die kostenpflichtigen Pläne sind derzeit noch deaktiviert. Sie werden aber bald aktiviert!",
|
|
||||||
"openChangeLog": "Changelog automatisch öffnen",
|
|
||||||
"reportUserTitle": "Melde {username}",
|
|
||||||
"reportUserReason": "Meldegrund",
|
|
||||||
"reportUser": "Benutzer melden",
|
|
||||||
"newDeviceRegistered": "Du hast dich auf einem anderen Gerät angemeldet. Daher wurdest du hier abgemeldet.",
|
|
||||||
"tabToRemoveEmoji": "Tippen um zu entfernen",
|
|
||||||
"quotedMessageWasDeleted": "Die zitierte Nachricht wurde gelöscht.",
|
|
||||||
"messageWasDeleted": "Nachricht wurde gelöscht.",
|
|
||||||
"messageWasDeletedShort": "Gelöscht",
|
|
||||||
"sent": "Versendet",
|
|
||||||
"sentTo": "Zugestellt an",
|
|
||||||
"received": "Empfangen",
|
|
||||||
"opened": "Geöffnet",
|
|
||||||
"waitingForInternet": "Warten auf Internet",
|
|
||||||
"editHistory": "Bearbeitungshistorie",
|
|
||||||
"archivedChats": "Archivierte Chats",
|
|
||||||
"durationShortSecond": "Sek.",
|
|
||||||
"durationShortMinute": "Min.",
|
|
||||||
"durationShortHour": "Std.",
|
|
||||||
"durationShortDays": "{count, plural, =1{1 Tag} other{{count} Tage}}",
|
|
||||||
"contacts": "Kontakte",
|
|
||||||
"groups": "Gruppen",
|
|
||||||
"newGroup": "Neue Gruppe",
|
|
||||||
"selectMembers": "Mitglieder auswählen",
|
|
||||||
"selectGroupName": "Gruppennamen wählen",
|
|
||||||
"groupNameInput": "Gruppennamen",
|
|
||||||
"groupMembers": "Mitglieder",
|
|
||||||
"createGroup": "Gruppe erstellen",
|
|
||||||
"addMember": "Mitglied hinzufügen",
|
|
||||||
"leaveGroup": "Gruppe verlassen",
|
|
||||||
"createContactRequest": "Kontaktanfrage erstellen",
|
|
||||||
"contactRequestSend": "Kontakanfrage gesendet",
|
|
||||||
"makeAdmin": "Zum Admin machen",
|
|
||||||
"removeAdmin": "Als Admin entfernen",
|
|
||||||
"removeFromGroup": "Aus Gruppe entfernen",
|
|
||||||
"admin": "Admin",
|
|
||||||
"revokeAdminRightsTitle": "Adminrechte von {username} entfernen?",
|
|
||||||
"revokeAdminRightsOkBtn": "Als Admin entfernen",
|
|
||||||
"makeAdminRightsTitle": "{username} zum Admin machen?",
|
|
||||||
"makeAdminRightsBody": "{username} wird diese Gruppe und ihre Mitglieder bearbeiten können.",
|
|
||||||
"makeAdminRightsOkBtn": "Zum Admin machen",
|
|
||||||
"updateGroup": "Gruppe aktualisieren",
|
|
||||||
"alreadyInGroup": "Bereits Mitglied",
|
|
||||||
"removeContactFromGroupTitle": "{username} aus dieser Gruppe entfernen?",
|
|
||||||
"youChangedGroupName": "Du hast den Gruppennamen zu „{newGroupName}“ geändert.",
|
|
||||||
"makerChangedGroupName": "{maker} hat den Gruppennamen zu „{newGroupName}“ geändert.",
|
|
||||||
"youCreatedGroup": "Du hast die Gruppe erstellt.",
|
|
||||||
"makerCreatedGroup": "{maker} hat die Gruppe erstellt.",
|
|
||||||
"youRemovedMember": "Du hast {affected} aus der Gruppe entfernt.",
|
|
||||||
"makerRemovedMember": "{maker} hat {affected} aus der Gruppe entfernt.",
|
|
||||||
"youAddedMember": "Du hast {affected} zur Gruppe hinzugefügt.",
|
|
||||||
"makerAddedMember": "{maker} hat {affected} zur Gruppe hinzugefügt.",
|
|
||||||
"youMadeAdmin": "Du hast {affected} zum Administrator gemacht.",
|
|
||||||
"makerMadeAdmin": "{maker} hat {affected} zum Administrator gemacht.",
|
|
||||||
"youRevokedAdminRights": "Du hast {affectedR} die Administratorrechte entzogen.",
|
|
||||||
"makerRevokedAdminRights": "{maker} hat {affectedR} die Administratorrechte entzogen.",
|
|
||||||
"youLeftGroup": "Du hast die Gruppe verlassen.",
|
|
||||||
"makerLeftGroup": "{maker} hat die Gruppe verlassen.",
|
|
||||||
"groupActionYou": "dich",
|
|
||||||
"groupActionYour": "deine",
|
|
||||||
"settingsBackup": "Backup",
|
|
||||||
"twonlySafeRecoverTitle": "Recovery",
|
|
||||||
"twonlySafeRecoverDesc": "Wenn du ein Backup mit twonly Backup erstellt hast, kannst du es hier wiederherstellen.",
|
|
||||||
"twonlySafeRecoverBtn": "Backup wiederherstellen",
|
|
||||||
"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": "[Unbekannt]",
|
|
||||||
"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.",
|
|
||||||
"dialogAskDeleteMediaFilePopTitle": "Bist du sicher, dass du dein Meisterwerk löschen möchtest?",
|
|
||||||
"dialogAskDeleteMediaFilePopDelete": "Löschen",
|
|
||||||
"allowErrorTracking": "Fehler und Crashes mit uns teilen",
|
|
||||||
"allowErrorTrackingSubtitle": "Wenn twonly abstürzt oder Fehler auftreten, werden diese automatisch an unsere selbst gehostete Glitchtip-Instanz gemeldet. Persönliche Daten wie Nachrichten oder Bilder werden niemals hochgeladen.",
|
|
||||||
"avatarSaveChanges": "Möchtest du die Änderungen speichern?",
|
|
||||||
"avatarSaveChangesStore": "Speichern",
|
|
||||||
"avatarSaveChangesDiscard": "Verwerfen",
|
|
||||||
"inProcess": "Wird verarbeitet",
|
|
||||||
"draftMessage": "Entwurf",
|
|
||||||
"exportMemories": "Memories exportieren (Beta)",
|
|
||||||
"importMemories": "Memories importieren (Beta)",
|
|
||||||
"voiceMessageSlideToCancel": "Zum Abbrechen ziehen",
|
|
||||||
"voiceMessageCancel": "Abbrechen",
|
|
||||||
"shareYourProfile": "Teile dein Profil",
|
|
||||||
"scanOtherProfile": "Scanne ein anderes Profil",
|
|
||||||
"skipForNow": "Vorerst überspringen",
|
|
||||||
"linkFromUsername": "Ist der Link von {username}?",
|
|
||||||
"linkFromUsernameLong": "Wenn du den Link von der Person direkt erhalten hast, kannst du den Kontakt als verifiziert markieren, da der öffentliche Schlüssel im Link mit dem bereits für diesen Benutzer gespeicherten öffentlichen Schlüssel übereinstimmt.",
|
|
||||||
"gotLinkFromFriend": "Ja, der Link kommt direkt von der Person.",
|
|
||||||
"couldNotVerifyUsername": "{username} konnte nicht verifiziert werden",
|
|
||||||
"linkPubkeyDoesNotMatch": "Der öffentliche Schlüssel im Link stimmt nicht mit dem für diesen Kontakt gespeicherten öffentlichen Schlüssel überein. Triff die Person persönlich und scanne den QR-Code direkt!"
|
|
||||||
}
|
|
||||||
|
|
@ -1,489 +0,0 @@
|
||||||
{
|
|
||||||
"@@locale": "en",
|
|
||||||
"registerTitle": "Welcome to twonly!",
|
|
||||||
"registerSlogan": "twonly, a privacy friendly way to connect with friends through secure, spontaneous image sharing",
|
|
||||||
"onboardingWelcomeTitle": "Welcome to twonly!",
|
|
||||||
"onboardingWelcomeBody": "Experience a private and secure way to stay in touch with friends by sharing instant pictures.",
|
|
||||||
"onboardingE2eTitle": "Carefree sharing",
|
|
||||||
"onboardingE2eBody": "With end-to-end encryption, enjoy the peace of mind that only you and your friends can see the moments you share.",
|
|
||||||
"onboardingFocusTitle": "Focus on sharing moments",
|
|
||||||
"onboardingFocusBody": "Say goodbye to addictive features! twonly was created for sharing moments, free from useless distractions or ads.",
|
|
||||||
"onboardingSendTwonliesTitle": "Send twonlies",
|
|
||||||
"onboardingSendTwonliesBody": "Share moments securely with your partner. twonly ensures that only your partner can open it, keeping your moments with your partner a two(o)nly thing!",
|
|
||||||
"onboardingNotProductTitle": "You are not the product!",
|
|
||||||
"onboardingNotProductBody": "twonly is financed by donations and an optional subscription. Your data will never be sold.",
|
|
||||||
"onboardingBuyOneGetTwoTitle": "Buy one get two",
|
|
||||||
"onboardingBuyOneGetTwoBody": "twonly always requires at least two people, which is why you receive a second free license for your twonly partner with your purchase.",
|
|
||||||
"onboardingGetStartedTitle": "Let's go!",
|
|
||||||
"onboardingGetStartedBody": "You can test twonly free of charge in preview mode. In this mode you can be found by others and receive pictures or videos but you cannot send any yourself.",
|
|
||||||
"onboardingTryForFree": "Try for free",
|
|
||||||
"registerUsernameSlogan": "Please select a username so others can find you!",
|
|
||||||
"registerUsernameDecoration": "Username",
|
|
||||||
"registerUsernameLimits": "Your username must be at least 3 characters long.",
|
|
||||||
"registerSubmitButton": "Register now!",
|
|
||||||
"registerTwonlyCodeText": "Have you received a twonly code? Then redeem it either directly here or later!",
|
|
||||||
"registerTwonlyCodeLabel": "twonly-Code",
|
|
||||||
"newMessageTitle": "New message",
|
|
||||||
"chatsTapToSend": "Click to send your first image",
|
|
||||||
"cameraPreviewSendTo": "Send to",
|
|
||||||
"shareImageTitle": "Share with",
|
|
||||||
"shareImageBestFriends": "Best friends",
|
|
||||||
"shareImagePinnedContacts": "Pinnded",
|
|
||||||
"shareImagedEditorSendImage": "Send",
|
|
||||||
"shareImagedEditorShareWith": "Share with",
|
|
||||||
"shareImagedEditorSaveImage": "Save",
|
|
||||||
"shareImagedEditorSavedImage": "Saved",
|
|
||||||
"shareImageSearchAllContacts": "Search all contacts",
|
|
||||||
"startNewChatSearchHint": "Name, username or groupname",
|
|
||||||
"shareImagedSelectAll": "Select all",
|
|
||||||
"startNewChatTitle": "Select Contact",
|
|
||||||
"startNewChatNewContact": "New Contact",
|
|
||||||
"startNewChatYourContacts": "Your Contacts",
|
|
||||||
"shareImageAllUsers": "All contacts",
|
|
||||||
"shareImageAllTwonlyWarning": "twonlies can only be send to verified contacts!",
|
|
||||||
"shareImageUserNotVerified": "User is not verified",
|
|
||||||
"shareImageUserNotVerifiedDesc": "twonlies can only be sent to verified users. To verify a user, go to their profile and to verify security number.",
|
|
||||||
"shareImageShowArchived": "Show archived users",
|
|
||||||
"searchUsernameInput": "Username",
|
|
||||||
"searchUsernameTitle": "Search username",
|
|
||||||
"searchUserNamePreview": "To protect you and other twonly users from spam and abuse, it is not possible to search for other people in preview mode. Other users can find you and their requests will be displayed here!",
|
|
||||||
"selectSubscription": "Select subscription",
|
|
||||||
"searchUserNamePending": "Pending",
|
|
||||||
"searchUserNameBlockUserTooltip": "Block the user without informing.",
|
|
||||||
"searchUserNameRejectUserTooltip": "Reject the request and let the requester know.",
|
|
||||||
"searchUserNameArchiveUserTooltip": "Archive the user. He will appear again as soon as he accepts your request.",
|
|
||||||
"searchUsernameNotFound": "Username not found",
|
|
||||||
"searchUsernameNotFoundBody": "There is no user with the username \"{username}\" registered",
|
|
||||||
"@searchUsernameNotFoundBody": {
|
|
||||||
"placeholders": {
|
|
||||||
"username": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"searchUsernameNewFollowerTitle": "Follow requests",
|
|
||||||
"searchUsernameQrCodeBtn": "Scan QR code",
|
|
||||||
"chatListViewSearchUserNameBtn": "Add your first twonly contact!",
|
|
||||||
"chatListViewSendFirstTwonly": "Send your first twonly!",
|
|
||||||
"chatListDetailInput": "Type a message",
|
|
||||||
"userDeletedAccount": "The user has deleted its account.",
|
|
||||||
"contextMenuUserProfile": "User profile",
|
|
||||||
"contextMenuVerifyUser": "Verify",
|
|
||||||
"contextMenuArchiveUser": "Archive",
|
|
||||||
"contextMenuUndoArchiveUser": "Undo archiving",
|
|
||||||
"contextMenuOpenChat": "Open chat",
|
|
||||||
"contextMenuPin": "Pin",
|
|
||||||
"contextMenuUnpin": "Unpin",
|
|
||||||
"mediaViewerAuthReason": "Please authenticate to see this twonly!",
|
|
||||||
"mediaViewerTwonlyTapToOpen": "Tap to open your twonly!",
|
|
||||||
"messageSendState_Received": "Received",
|
|
||||||
"messageSendState_Opened": "Opened",
|
|
||||||
"messageSendState_Send": "Sent",
|
|
||||||
"messageSendState_Sending": "Sending",
|
|
||||||
"messageSendState_TapToLoad": "Tap to load",
|
|
||||||
"messageSendState_Loading": "Downloading",
|
|
||||||
"messageStoredInGallery": "Stored in gallery",
|
|
||||||
"messageReopened": "Re-opened",
|
|
||||||
"imageEditorDrawOk": "Take drawing",
|
|
||||||
"settingsTitle": "Settings",
|
|
||||||
"settingsChats": "Chats",
|
|
||||||
"settingsPreSelectedReactions": "Preselected reaction emojis",
|
|
||||||
"settingsPreSelectedReactionsError": "A maximum of 12 reactions can be selected.",
|
|
||||||
"settingsProfile": "Profile",
|
|
||||||
"settingsStorageData": "Data and storage",
|
|
||||||
"settingsStorageDataStoreInGTitle": "Store in Gallery",
|
|
||||||
"settingsStorageDataStoreInGSubtitle": "Store saved images additional in the systems gallery.",
|
|
||||||
"settingsStorageDataMediaAutoDownload": "Media auto-download",
|
|
||||||
"settingsStorageDataAutoDownMobile": "When using mobile data",
|
|
||||||
"settingsStorageDataAutoDownWifi": "When using WI-FI",
|
|
||||||
"settingsProfileCustomizeAvatar": "Customize your avatar",
|
|
||||||
"settingsProfileEditDisplayName": "Displayname",
|
|
||||||
"settingsProfileEditDisplayNameNew": "New Displayname",
|
|
||||||
"settingsAccount": "Konto",
|
|
||||||
"settingsSubscription": "Subscription",
|
|
||||||
"settingsAppearance": "Appearance",
|
|
||||||
"settingsPrivacy": "Privacy",
|
|
||||||
"settingsPrivacyBlockUsers": "Block users",
|
|
||||||
"settingsPrivacyBlockUsersDesc": "Blocked users will not be able to communicate with you. You can unblock a blocked user at any time.",
|
|
||||||
"settingsPrivacyBlockUsersCount": "{len} contact(s)",
|
|
||||||
"@settingsPrivacyBlockUsersCount": {
|
|
||||||
"placeholders": {
|
|
||||||
"len": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"settingsNotification": "Notification",
|
|
||||||
"settingsNotifyTroubleshooting": "Troubleshooting",
|
|
||||||
"settingsNotifyTroubleshootingDesc": "Click here if you have problems receiving push notifications.",
|
|
||||||
"settingsNotifyTroubleshootingNoProblem": "No problem detected",
|
|
||||||
"settingsNotifyTroubleshootingNoProblemDesc": "Press OK to receive a test notification. When you receive no message even after waiting for 10 minutes, please send us your debug log in Settings > Help > Debug log, so we can look at that issue.",
|
|
||||||
"settingsHelp": "Help",
|
|
||||||
"settingsHelpDiagnostics": "Diagnostic protocol",
|
|
||||||
"settingsHelpFAQ": "FAQ",
|
|
||||||
"feedbackTooltip": "Give Feedback to improve twonly.",
|
|
||||||
"settingsHelpContactUs": "Contact us",
|
|
||||||
"settingsHelpVersion": "Version",
|
|
||||||
"settingsHelpLicenses": "Licenses (Source-Code)",
|
|
||||||
"settingsHelpCredits": "Licenses (Images)",
|
|
||||||
"settingsHelpImprint": "Imprint & Privacy Policy",
|
|
||||||
"contactUsFaq": "Have you read our FAQ yet?",
|
|
||||||
"contactUsEmojis": "How do you feel? (optional)",
|
|
||||||
"contactUsSelectOption": "Please select an option",
|
|
||||||
"contactUsReason": "Tell us why you're reaching out",
|
|
||||||
"contactUsMessage": "If you want to receive an answer, please add your e-mail address so we can contact you.",
|
|
||||||
"contactUsYourMessage": "Your message",
|
|
||||||
"contactUsMessageTitle": "Tell us what's going on",
|
|
||||||
"contactUsReasonNotWorking": "Something's not working",
|
|
||||||
"contactUsReasonFeatureRequest": "Feature request",
|
|
||||||
"contactUsReasonQuestion": "Question",
|
|
||||||
"contactUsReasonFeedback": "Feedback",
|
|
||||||
"contactUsReasonOther": "Other",
|
|
||||||
"contactUsIncludeLog": "Include debug log",
|
|
||||||
"contactUsWhatsThat": "What's that?",
|
|
||||||
"contactUsLastWarning": "This are the information's which will be send to us. Please verify them and then press submit.",
|
|
||||||
"contactUsSuccess": "Feedback submitted successfully!",
|
|
||||||
"contactUsShortcut": "Hide Feedback Icon",
|
|
||||||
"settingsHelpTerms": "Terms of Service",
|
|
||||||
"settingsAppearanceTheme": "Theme",
|
|
||||||
"settingsAccountDeleteAccount": "Delete account",
|
|
||||||
"settingsAccountDeleteAccountWithBallance": "In the next step, you can select what you want to to with the remaining credit ({credit}).",
|
|
||||||
"settingsAccountDeleteAccountNoBallance": "Once you delete your account, there is no going back.",
|
|
||||||
"settingsAccountDeleteAccountNoInternet": "An Internet connection is required to delete your account.",
|
|
||||||
"settingsAccountDeleteModalTitle": "Are you sure?",
|
|
||||||
"settingsAccountDeleteModalBody": "Your account will be deleted. There is no change to restore it.",
|
|
||||||
"contactVerifyNumberTitle": "Verify safety number",
|
|
||||||
"contactVerifyNumberTapToScan": "Tap to scan",
|
|
||||||
"contactVerifyNumberMarkAsVerified": "Mark as verified",
|
|
||||||
"contactVerifyNumberClearVerification": "Clear verification",
|
|
||||||
"contactVerifyNumberLongDesc": "To verify the end-to-end encryption with {username}, compare the numbers with their device. The person can also scan your code with their device.",
|
|
||||||
"@contactVerifyNumberLongDesc": {
|
|
||||||
"placeholders": {
|
|
||||||
"username": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"contactNickname": "Nickname",
|
|
||||||
"contactNicknameNew": "New nickname",
|
|
||||||
"deleteAllContactMessages": "Delete all text-messages",
|
|
||||||
"deleteAllContactMessagesBody": "This will remove all messages, except stored media files, in your chat with {username}. This will NOT delete the messages stored at {username}s device!",
|
|
||||||
"@deleteAllContactMessagesBody": {
|
|
||||||
"placeholders": {
|
|
||||||
"username": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"contactBlock": "Block",
|
|
||||||
"contactBlockTitle": "Block {username}",
|
|
||||||
"@contactBlockTitle": {
|
|
||||||
"placeholders": {
|
|
||||||
"username": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"contactBlockBody": "A blocked user will no longer be able to send you messages and their profile will be hidden from view. To unblock a user, simply navigate to Settings > Privacy > Blocked Users.",
|
|
||||||
"contactRemove": "Remove user",
|
|
||||||
"contactRemoveTitle": "Remove {username}",
|
|
||||||
"contactRemoveBody": "Remove the user and permanently delete the chat and all associated media files. This will also delete YOUR ACCOUNT FROM YOUR CONTACT'S PHONE.",
|
|
||||||
"undo": "Undo",
|
|
||||||
"redo": "Redo",
|
|
||||||
"next": "Next",
|
|
||||||
"submit": "Submit",
|
|
||||||
"close": "Close",
|
|
||||||
"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",
|
|
||||||
"switchFrontAndBackCamera": "Switch between front and back camera.",
|
|
||||||
"addTextItem": "Text",
|
|
||||||
"protectAsARealTwonly": "Send as real twonly!",
|
|
||||||
"addDrawing": "Drawing",
|
|
||||||
"addEmoji": "Emoji",
|
|
||||||
"toggleFlashLight": "Toggle the flash light",
|
|
||||||
"toggleHighQuality": "Toggle better resolution",
|
|
||||||
"userFound": "{username} found",
|
|
||||||
"userFoundBody": "Do you want to create a follow request?",
|
|
||||||
"searchUsernameNotFoundLong": "\"{username}\" is not a twonly user. Please check the username and try again.",
|
|
||||||
"@searchUsernameNotFoundLong": {
|
|
||||||
"placeholders": {
|
|
||||||
"username": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"errorUnknown": "An unexpected error has occurred. Please try again later.",
|
|
||||||
"errorBadRequest": "The request could not be understood by the server due to malformed syntax. Please check your input and try again.",
|
|
||||||
"errorTooManyRequests": "You have made too many requests in a short period. Please wait a moment before trying again.",
|
|
||||||
"errorInternalError": "The server is currently not available. Please try again later.",
|
|
||||||
"errorInvalidInvitationCode": "The invitation code you provided is invalid. Please check the code and try again.",
|
|
||||||
"errorUsernameAlreadyTaken": "The username is already taken.",
|
|
||||||
"errorSignatureNotValid": "The provided signature is not valid. Please check your credentials and try again.",
|
|
||||||
"errorUsernameNotFound": "The username you entered does not exist. Please check the spelling or create a new account.",
|
|
||||||
"errorUsernameNotValid": "The username you provided does not meet the required criteria. Please choose a valid username.",
|
|
||||||
"errorInvalidPublicKey": "The public key you provided is invalid. Please check the key and try again.",
|
|
||||||
"errorSessionAlreadyAuthenticated": "You are already logged in. Please log out if you want to log in with a different account.",
|
|
||||||
"errorSessionNotAuthenticated": "Your session is not authenticated. Please log in to continue.",
|
|
||||||
"errorOnlyOneSessionAllowed": "Only one active session is allowed per user. Please log out from other devices to continue.",
|
|
||||||
"errorNotEnoughCredit": "You do not have enough twonly-credit.",
|
|
||||||
"errorVoucherInvalid": "The voucher code you entered is not valid.",
|
|
||||||
"errorPlanLimitReached": "You have reached your plans limit. Please upgrade your plan.",
|
|
||||||
"errorPlanNotAllowed": "This feature is not available in your current plan.",
|
|
||||||
"errorPlanUpgradeNotYearly": "The plan upgrade must be paid for annually, as the current plan is also billed annually.",
|
|
||||||
"upgradeToPaidPlan": "Upgrade to a paid plan.",
|
|
||||||
"upgradeToPaidPlanButton": "Upgrade to {planId}{sufix}",
|
|
||||||
"partOfPaidPlanOf": "You are part of the paid plan of {username}!",
|
|
||||||
"year": "year",
|
|
||||||
"yearly": "Yearly",
|
|
||||||
"month": "month",
|
|
||||||
"monthly": "Monthly",
|
|
||||||
"proFeature1": "✓ Unlimited media file uploads",
|
|
||||||
"proFeature2": "✓ 1 additional Plus user",
|
|
||||||
"proFeature3": "✓ Restore flames",
|
|
||||||
"proFeature4": "✓ Support twonly",
|
|
||||||
"familyFeature1": "✓ Unlimited media file uploads",
|
|
||||||
"familyFeature2": "✓ 4 additional Plus user",
|
|
||||||
"familyFeature3": "✓ Restore flames",
|
|
||||||
"familyFeature4": "✓ Support twonly",
|
|
||||||
"redeemUserInviteCode": "Or redeem a twonly-Code.",
|
|
||||||
"redeemUserInviteCodeTitle": "Redeem twonly-Code",
|
|
||||||
"redeemUserInviteCodeSuccess": "Your plan has been successfully adjusted.",
|
|
||||||
"freeFeature1": "✓ 10 Media file uploads per day",
|
|
||||||
"plusFeature1": "✓ Unlimited media file uploads",
|
|
||||||
"plusFeature2": "✓ Additional features (coming-soon)",
|
|
||||||
"transactionHistory": "Your transaction history",
|
|
||||||
"manageSubscription": "Manage your subscription",
|
|
||||||
"nextPayment": "Next payment",
|
|
||||||
"currentBalance": "Current balance",
|
|
||||||
"manageAdditionalUsers": "Manage additional users",
|
|
||||||
"open": "Open",
|
|
||||||
"createOrRedeemVoucher": "Buy or redeem voucher",
|
|
||||||
"createVoucher": "Buy voucher",
|
|
||||||
"createVoucherDesc": "Choose the value of the voucher. The value of the voucher will be deducted from your twonly balance.",
|
|
||||||
"redeemVoucher": "Redeem voucher",
|
|
||||||
"openVouchers": "Open vouchers",
|
|
||||||
"voucherCreated": "Voucher created",
|
|
||||||
"voucherRedeemed": "Voucher redeemed",
|
|
||||||
"enterVoucherCode": "Enter Voucher Code",
|
|
||||||
"requestedVouchers": "Requested vouchers",
|
|
||||||
"redeemedVouchers": "Redeemed vouchers",
|
|
||||||
"buy": "Buy",
|
|
||||||
"subscriptionRefund": "When you upgrade, you will receive a refund of {refund} for your current subscription.",
|
|
||||||
"transactionCash": "Cash transaction",
|
|
||||||
"transactionPlanUpgrade": "Plan upgrade",
|
|
||||||
"transactionRefund": "Refund transaction",
|
|
||||||
"transactionThanksForTesting": "Thank you for testing",
|
|
||||||
"transactionUnknown": "Unknown transaction",
|
|
||||||
"transactionVoucherCreated": "Voucher created",
|
|
||||||
"transactionVoucherRedeemed": "Voucher redeemed",
|
|
||||||
"transactionAutoRenewal": "Automatic renewal",
|
|
||||||
"checkoutOptions": "Options",
|
|
||||||
"refund": "Refund",
|
|
||||||
"checkoutPayYearly": "Pay yearly",
|
|
||||||
"checkoutTotal": "Total",
|
|
||||||
"selectPaymentMethod": "Select Payment Method",
|
|
||||||
"twonlyCredit": "twonly-Credit",
|
|
||||||
"notEnoughCredit": "You do not have enough credit!",
|
|
||||||
"chargeCredit": "Charge credit",
|
|
||||||
"autoRenewal": "Auto renewal",
|
|
||||||
"autoRenewalDesc": "You can change this at any time.",
|
|
||||||
"autoRenewalLongDesc": "When your subscription expires, you will automatically be downgraded to the Preview plan. If you activate the automatic renewal, please make sure that you have enough credit for the automatic renewal. We will notify you in good time before the automatic renewal.",
|
|
||||||
"planSuccessUpgraded": "Successfully upgraded your plan.",
|
|
||||||
"checkoutSubmit": "Order with a fee.",
|
|
||||||
"additionalUsersList": "Your additional users",
|
|
||||||
"additionalUsersPlusTokens": "twonly-Codes für \"Plus\" user",
|
|
||||||
"additionalUsersFreeTokens": "twonly-Codes für \"Free\" user",
|
|
||||||
"planLimitReached": "You have reached your plan limit for today. Upgrade your plan now to send the media file.",
|
|
||||||
"planNotAllowed": "You cannot send media files with your current tariff. Upgrade your plan now to send the media file.",
|
|
||||||
"galleryDelete": "Delete file",
|
|
||||||
"galleryDetails": "Show details",
|
|
||||||
"galleryExport": "Export to gallery",
|
|
||||||
"galleryExportSuccess": "Successfully saved in the Gallery.",
|
|
||||||
"settingsResetTutorials": "Show tutorials again",
|
|
||||||
"settingsResetTutorialsDesc": "Click here to show already displayed tutorials again.",
|
|
||||||
"settingsResetTutorialsSuccess": "Tutorials will be displayed again.",
|
|
||||||
"tutorialChatListSearchUsersTitle": "Find Friends and Manage Friend Requests",
|
|
||||||
"tutorialChatListSearchUsersDesc": "If you know your friends' usernames, you can search for them here and send a friend request. You will also see all requests from other users that you can accept or block.",
|
|
||||||
"tutorialChatListContextMenuTitle": "Long press on the contact to open the context menu.",
|
|
||||||
"tutorialChatListContextMenuDesc": "With the context menu, you can pin, archive, and perform various actions on your contacts. Simply long press the contact and then move your finger to the desired option or tap directly on it.",
|
|
||||||
"tutorialChatMessagesVerifyShieldTitle": "Verify your contacts!",
|
|
||||||
"tutorialChatMessagesVerifyShieldDesc": "twonly uses the Signal protocol for secure end-to-end encryption. When you first contact someone, their public identity key is downloaded. To ensure that this key has not been tampered with by third parties, you should compare it with your friend when you meet in person. Once you have verified the user, you can also enable the twonly mode when sending images and videos.",
|
|
||||||
"tutorialChatMessagesReopenMessageTitle": "Reopen Images and Videos",
|
|
||||||
"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?",
|
|
||||||
"deleteOkBtnForAll": "Delete for all",
|
|
||||||
"deleteOkBtnForMe": "Delete for me",
|
|
||||||
"deleteImageTitle": "Are you sure?",
|
|
||||||
"deleteImageBody": "The image will be irrevocably deleted.",
|
|
||||||
"settingsBackup": "Backup",
|
|
||||||
"backupNoticeTitle": "No backup configured",
|
|
||||||
"backupNoticeDesc": "If you change or lose your device, no one can restore your account without a backup. Therefore, back up your data.",
|
|
||||||
"backupNoticeLater": "Remind later",
|
|
||||||
"backupNoticeOpenBackup": "Create backup",
|
|
||||||
"backupPending": "Pending",
|
|
||||||
"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",
|
|
||||||
"backupLastBackupDate": "Last backup",
|
|
||||||
"backupLastBackupSize": "Backup size",
|
|
||||||
"backupLastBackupResult": "Result",
|
|
||||||
"deleteBackupTitle": "Are you sure?",
|
|
||||||
"deleteBackupBody": "Without an backup, you can not restore your user account.",
|
|
||||||
"backupData": "Data-Backup",
|
|
||||||
"backupDataDesc": "This backup contains besides of your twonly-Identity also all of your media files. This backup will is also encrypted but stored locally. You then have to ensure to manually copy it onto your laptop or device of your choice.",
|
|
||||||
"backupInsecurePassword": "Insecure password",
|
|
||||||
"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 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 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 Backup, you can restore it here.",
|
|
||||||
"twonlySafeRecoverBtn": "Restore backup",
|
|
||||||
"inviteFriends": "Invite your friends",
|
|
||||||
"inviteFriendsShareBtn": "Share",
|
|
||||||
"inviteFriendsShareText": "Let's switch to twonly: {url}",
|
|
||||||
"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.",
|
|
||||||
"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 an 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": "[Unknown]",
|
|
||||||
"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.",
|
|
||||||
"dialogAskDeleteMediaFilePopTitle": "Are you sure you want to delete your masterpiece?",
|
|
||||||
"dialogAskDeleteMediaFilePopDelete": "Delete",
|
|
||||||
"allowErrorTracking": "Share errors and crashes with us",
|
|
||||||
"allowErrorTrackingSubtitle": "If twonly crashes or errors occur, these are automatically reported to our self-hosted Glitchtip instance. Personal data such as messages or images are never uploaded.",
|
|
||||||
"avatarSaveChanges": "Would you like to save the changes?",
|
|
||||||
"avatarSaveChangesStore": "Save",
|
|
||||||
"avatarSaveChangesDiscard": "Discard",
|
|
||||||
"inProcess": "In process",
|
|
||||||
"draftMessage": "Draft",
|
|
||||||
"exportMemories": "Export memories (Beta)",
|
|
||||||
"importMemories": "Import memories (Beta)",
|
|
||||||
"voiceMessageSlideToCancel": "Slide to cancel",
|
|
||||||
"voiceMessageCancel": "Cancel",
|
|
||||||
"shareYourProfile": "Share your profile",
|
|
||||||
"scanOtherProfile": "Scan other profile",
|
|
||||||
"skipForNow": "Skip for now",
|
|
||||||
"linkFromUsername": "Is the link from {username}?",
|
|
||||||
"linkFromUsernameLong": "If you received the link from your friend, you can mark the user as verified, as the public key in the link matches the public key already stored for that user?",
|
|
||||||
"gotLinkFromFriend": "Yes, I got the link from my friend!",
|
|
||||||
"couldNotVerifyUsername": "Could not verify {username}",
|
|
||||||
"linkPubkeyDoesNotMatch": "The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!"
|
|
||||||
}
|
|
||||||
|
|
@ -7,6 +7,7 @@ import 'package:intl/intl.dart' as intl;
|
||||||
|
|
||||||
import 'app_localizations_de.dart';
|
import 'app_localizations_de.dart';
|
||||||
import 'app_localizations_en.dart';
|
import 'app_localizations_en.dart';
|
||||||
|
import 'app_localizations_sv.dart';
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
|
|
||||||
|
|
@ -95,7 +96,8 @@ abstract class AppLocalizations {
|
||||||
/// A list of this localizations delegate's supported locales.
|
/// A list of this localizations delegate's supported locales.
|
||||||
static const List<Locale> supportedLocales = <Locale>[
|
static const List<Locale> supportedLocales = <Locale>[
|
||||||
Locale('de'),
|
Locale('de'),
|
||||||
Locale('en')
|
Locale('en'),
|
||||||
|
Locale('sv')
|
||||||
];
|
];
|
||||||
|
|
||||||
/// No description provided for @registerTitle.
|
/// No description provided for @registerTitle.
|
||||||
|
|
@ -218,6 +220,12 @@ abstract class AppLocalizations {
|
||||||
/// **'Your username must be at least 3 characters long.'**
|
/// **'Your username must be at least 3 characters long.'**
|
||||||
String get registerUsernameLimits;
|
String get registerUsernameLimits;
|
||||||
|
|
||||||
|
/// No description provided for @registerProofOfWorkFailed.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'There was an issue with the captcha test. Please try again.'**
|
||||||
|
String get registerProofOfWorkFailed;
|
||||||
|
|
||||||
/// No description provided for @registerSubmitButton.
|
/// No description provided for @registerSubmitButton.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -1394,24 +1402,6 @@ abstract class AppLocalizations {
|
||||||
/// **'✓ Support twonly'**
|
/// **'✓ Support twonly'**
|
||||||
String get familyFeature4;
|
String get familyFeature4;
|
||||||
|
|
||||||
/// No description provided for @redeemUserInviteCode.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Or redeem a twonly-Code.'**
|
|
||||||
String get redeemUserInviteCode;
|
|
||||||
|
|
||||||
/// No description provided for @redeemUserInviteCodeTitle.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Redeem twonly-Code'**
|
|
||||||
String get redeemUserInviteCodeTitle;
|
|
||||||
|
|
||||||
/// No description provided for @redeemUserInviteCodeSuccess.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Your plan has been successfully adjusted.'**
|
|
||||||
String get redeemUserInviteCodeSuccess;
|
|
||||||
|
|
||||||
/// No description provided for @freeFeature1.
|
/// No description provided for @freeFeature1.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -1439,7 +1429,7 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @manageSubscription.
|
/// No description provided for @manageSubscription.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Manage your subscription'**
|
/// **'Manage subscription'**
|
||||||
String get manageSubscription;
|
String get manageSubscription;
|
||||||
|
|
||||||
/// No description provided for @nextPayment.
|
/// No description provided for @nextPayment.
|
||||||
|
|
@ -2099,7 +2089,7 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @uploadLimitReached.
|
/// No description provided for @uploadLimitReached.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'The upload limit has\been reached. Upgrade to Pro\nor wait until tomorrow.'**
|
/// **'The upload limit has\nbeen reached. Upgrade to Pro\nor wait until tomorrow.'**
|
||||||
String get uploadLimitReached;
|
String get uploadLimitReached;
|
||||||
|
|
||||||
/// No description provided for @retransmissionRequested.
|
/// No description provided for @retransmissionRequested.
|
||||||
|
|
@ -2833,6 +2823,108 @@ abstract class AppLocalizations {
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!'**
|
/// **'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!'**
|
||||||
String get linkPubkeyDoesNotMatch;
|
String get linkPubkeyDoesNotMatch;
|
||||||
|
|
||||||
|
/// No description provided for @startWithCameraOpen.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Start with camera open'**
|
||||||
|
String get startWithCameraOpen;
|
||||||
|
|
||||||
|
/// No description provided for @showImagePreviewWhenSending.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Display image preview when selecting recipients'**
|
||||||
|
String get showImagePreviewWhenSending;
|
||||||
|
|
||||||
|
/// No description provided for @verifiedPublicKey.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'The public key of {username} has been verified and is valid.'**
|
||||||
|
String verifiedPublicKey(Object username);
|
||||||
|
|
||||||
|
/// No description provided for @memoriesAYearAgo.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'One year ago'**
|
||||||
|
String get memoriesAYearAgo;
|
||||||
|
|
||||||
|
/// No description provided for @memoriesXYearsAgo.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'{years} years ago'**
|
||||||
|
String memoriesXYearsAgo(Object years);
|
||||||
|
|
||||||
|
/// No description provided for @migrationOfMemories.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Migration of media files: {open} still to be processed.'**
|
||||||
|
String migrationOfMemories(Object open);
|
||||||
|
|
||||||
|
/// No description provided for @autoStoreAllSendUnlimitedMediaFiles.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Save all sent media'**
|
||||||
|
String get autoStoreAllSendUnlimitedMediaFiles;
|
||||||
|
|
||||||
|
/// No description provided for @autoStoreAllSendUnlimitedMediaFilesSubtitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'If you enable this option, all images you send will be saved as long as they were sent with an infinite countdown and not in twonly mode.'**
|
||||||
|
String get autoStoreAllSendUnlimitedMediaFilesSubtitle;
|
||||||
|
|
||||||
|
/// No description provided for @termsOfService.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Terms of service'**
|
||||||
|
String get termsOfService;
|
||||||
|
|
||||||
|
/// No description provided for @privacyPolicy.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Privacy policy'**
|
||||||
|
String get privacyPolicy;
|
||||||
|
|
||||||
|
/// No description provided for @additionalUserAddError.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Could not add additional user. Try again later.'**
|
||||||
|
String get additionalUserAddError;
|
||||||
|
|
||||||
|
/// No description provided for @additionalUserAddButton.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Add additional user ({used}/{limit})'**
|
||||||
|
String additionalUserAddButton(Object limit, Object used);
|
||||||
|
|
||||||
|
/// No description provided for @additionalUserRemoveTitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Remove this additional user'**
|
||||||
|
String get additionalUserRemoveTitle;
|
||||||
|
|
||||||
|
/// No description provided for @additionalUserRemoveDesc.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'After removal, the additional user will automatically be downgraded to the free plan, and you can add another person.'**
|
||||||
|
String get additionalUserRemoveDesc;
|
||||||
|
|
||||||
|
/// No description provided for @additionalUserSelectTitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Select additional users'**
|
||||||
|
String get additionalUserSelectTitle;
|
||||||
|
|
||||||
|
/// No description provided for @additionalUserSelectButton.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Select users ({used}/{limit})'**
|
||||||
|
String additionalUserSelectButton(Object limit, Object used);
|
||||||
|
|
||||||
|
/// No description provided for @storeAsDefault.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Store as default'**
|
||||||
|
String get storeAsDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate
|
class _AppLocalizationsDelegate
|
||||||
|
|
@ -2846,7 +2938,7 @@ class _AppLocalizationsDelegate
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isSupported(Locale locale) =>
|
bool isSupported(Locale locale) =>
|
||||||
<String>['de', 'en'].contains(locale.languageCode);
|
<String>['de', 'en', 'sv'].contains(locale.languageCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||||
|
|
@ -2859,6 +2951,8 @@ AppLocalizations lookupAppLocalizations(Locale locale) {
|
||||||
return AppLocalizationsDe();
|
return AppLocalizationsDe();
|
||||||
case 'en':
|
case 'en':
|
||||||
return AppLocalizationsEn();
|
return AppLocalizationsEn();
|
||||||
|
case 'sv':
|
||||||
|
return AppLocalizationsSv();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw FlutterError(
|
throw FlutterError(
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,10 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
String get registerUsernameLimits =>
|
String get registerUsernameLimits =>
|
||||||
'Der Benutzername muss mindestens 3 Zeichen lang sein.';
|
'Der Benutzername muss mindestens 3 Zeichen lang sein.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get registerProofOfWorkFailed =>
|
||||||
|
'Beim Captcha-Test gab es ein Problem. Bitte versuche es erneut.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get registerSubmitButton => 'Jetzt registrieren!';
|
String get registerSubmitButton => 'Jetzt registrieren!';
|
||||||
|
|
||||||
|
|
@ -730,16 +734,6 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get familyFeature4 => '✓ twonly unterstützen';
|
String get familyFeature4 => '✓ twonly unterstützen';
|
||||||
|
|
||||||
@override
|
|
||||||
String get redeemUserInviteCode => 'Oder löse einen twonly-Code ein.';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get redeemUserInviteCodeTitle => 'twonly-Code einlösen';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get redeemUserInviteCodeSuccess =>
|
|
||||||
'Dein Plan wurde erfolgreich angepasst.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get freeFeature1 => '✓ 10 Medien-Datei-Uploads pro Tag';
|
String get freeFeature1 => '✓ 10 Medien-Datei-Uploads pro Tag';
|
||||||
|
|
||||||
|
|
@ -871,7 +865,7 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
String get checkoutSubmit => 'Kostenpflichtig bestellen';
|
String get checkoutSubmit => 'Kostenpflichtig bestellen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get additionalUsersList => 'Ihre zusätzlichen Benutzer';
|
String get additionalUsersList => 'Deine zusätzlichen Benutzer';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get additionalUsersPlusTokens => 'twonly-Codes für \"Plus\"-Benutzer';
|
String get additionalUsersPlusTokens => 'twonly-Codes für \"Plus\"-Benutzer';
|
||||||
|
|
@ -1566,4 +1560,71 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get linkPubkeyDoesNotMatch =>
|
String get linkPubkeyDoesNotMatch =>
|
||||||
'Der öffentliche Schlüssel im Link stimmt nicht mit dem für diesen Kontakt gespeicherten öffentlichen Schlüssel überein. Triff die Person persönlich und scanne den QR-Code direkt!';
|
'Der öffentliche Schlüssel im Link stimmt nicht mit dem für diesen Kontakt gespeicherten öffentlichen Schlüssel überein. Triff die Person persönlich und scanne den QR-Code direkt!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startWithCameraOpen => 'Mit geöffneter Kamera starten';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get showImagePreviewWhenSending =>
|
||||||
|
'Bildvorschau bei der Auswahl von Empfängern anzeigen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String verifiedPublicKey(Object username) {
|
||||||
|
return 'Der öffentliche Schlüssel von $username wurde überprüft und ist gültig.';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get memoriesAYearAgo => 'Vor einem Jahr';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String memoriesXYearsAgo(Object years) {
|
||||||
|
return 'Vor $years Jahren';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String migrationOfMemories(Object open) {
|
||||||
|
return 'Migration von Mediendateien: $open noch offen.';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get autoStoreAllSendUnlimitedMediaFiles =>
|
||||||
|
'Alle gesendeten Medien speichern';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get autoStoreAllSendUnlimitedMediaFilesSubtitle =>
|
||||||
|
'Wenn du diese Option aktivierst, werden alle Bilder, die du sendest, gespeichert, sofern sie mit einem unendlichen Countdown und nicht im twonly-Modus gesendet wurden.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get termsOfService => 'Allgemeine Geschäftsbedingungen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get privacyPolicy => 'Datenschutzerklärung';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserAddError =>
|
||||||
|
'Es konnte kein zusätzlicher Nutzer hinzugefügt werden. Versuche es später noch einmal.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String additionalUserAddButton(Object limit, Object used) {
|
||||||
|
return 'Zusätzlichen Benutzer hinzufügen ($used/$limit)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserRemoveTitle =>
|
||||||
|
'Diesen zusätzlichen Benutzer entfernen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserRemoveDesc =>
|
||||||
|
'Der zusätzliche Nutzer wird nach der Entfernung automatisch auf den kostenlosen Tarif zurückgestuft und du kannst eine andere Person hinzufügen.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserSelectTitle => 'Zusätzliche Benutzer auswählen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String additionalUserSelectButton(Object limit, Object used) {
|
||||||
|
return 'Benutzer auswählen ($used/$limit)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeAsDefault => 'Als Standard speichern';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,10 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
String get registerUsernameLimits =>
|
String get registerUsernameLimits =>
|
||||||
'Your username must be at least 3 characters long.';
|
'Your username must be at least 3 characters long.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get registerProofOfWorkFailed =>
|
||||||
|
'There was an issue with the captcha test. Please try again.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get registerSubmitButton => 'Register now!';
|
String get registerSubmitButton => 'Register now!';
|
||||||
|
|
||||||
|
|
@ -724,16 +728,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get familyFeature4 => '✓ Support twonly';
|
String get familyFeature4 => '✓ Support twonly';
|
||||||
|
|
||||||
@override
|
|
||||||
String get redeemUserInviteCode => 'Or redeem a twonly-Code.';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get redeemUserInviteCodeTitle => 'Redeem twonly-Code';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get redeemUserInviteCodeSuccess =>
|
|
||||||
'Your plan has been successfully adjusted.';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get freeFeature1 => '✓ 10 Media file uploads per day';
|
String get freeFeature1 => '✓ 10 Media file uploads per day';
|
||||||
|
|
||||||
|
|
@ -747,7 +741,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
String get transactionHistory => 'Your transaction history';
|
String get transactionHistory => 'Your transaction history';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get manageSubscription => 'Manage your subscription';
|
String get manageSubscription => 'Manage subscription';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get nextPayment => 'Next payment';
|
String get nextPayment => 'Next payment';
|
||||||
|
|
@ -1107,7 +1101,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get uploadLimitReached =>
|
String get uploadLimitReached =>
|
||||||
'The upload limit has\been reached. Upgrade to Pro\nor wait until tomorrow.';
|
'The upload limit has\nbeen reached. Upgrade to Pro\nor wait until tomorrow.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get retransmissionRequested => 'Retransmission requested';
|
String get retransmissionRequested => 'Retransmission requested';
|
||||||
|
|
@ -1556,4 +1550,69 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get linkPubkeyDoesNotMatch =>
|
String get linkPubkeyDoesNotMatch =>
|
||||||
'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!';
|
'The public key in the link does not match the public key stored for this contact. Try to meet your friend in person and scan the QR code directly!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startWithCameraOpen => 'Start with camera open';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get showImagePreviewWhenSending =>
|
||||||
|
'Display image preview when selecting recipients';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String verifiedPublicKey(Object username) {
|
||||||
|
return 'The public key of $username has been verified and is valid.';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get memoriesAYearAgo => 'One year ago';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String memoriesXYearsAgo(Object years) {
|
||||||
|
return '$years years ago';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String migrationOfMemories(Object open) {
|
||||||
|
return 'Migration of media files: $open still to be processed.';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get autoStoreAllSendUnlimitedMediaFiles => 'Save all sent media';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get autoStoreAllSendUnlimitedMediaFilesSubtitle =>
|
||||||
|
'If you enable this option, all images you send will be saved as long as they were sent with an infinite countdown and not in twonly mode.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get termsOfService => 'Terms of service';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get privacyPolicy => 'Privacy policy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserAddError =>
|
||||||
|
'Could not add additional user. Try again later.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String additionalUserAddButton(Object limit, Object used) {
|
||||||
|
return 'Add additional user ($used/$limit)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserRemoveTitle => 'Remove this additional user';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserRemoveDesc =>
|
||||||
|
'After removal, the additional user will automatically be downgraded to the free plan, and you can add another person.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get additionalUserSelectTitle => 'Select additional users';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String additionalUserSelectButton(Object limit, Object used) {
|
||||||
|
return 'Select users ($used/$limit)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeAsDefault => 'Store as default';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1618
lib/src/localization/generated/app_localizations_sv.dart
Normal file
1618
lib/src/localization/generated/app_localizations_sv.dart
Normal file
File diff suppressed because it is too large
Load diff
1
lib/src/localization/translations
Submodule
1
lib/src/localization/translations
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 775c0ffd9523177478681ecff4e8c4613bf57ee3
|
||||||
|
|
@ -59,6 +59,12 @@ class UserData {
|
||||||
@JsonKey(defaultValue: true)
|
@JsonKey(defaultValue: true)
|
||||||
bool showFeedbackShortcut = true;
|
bool showFeedbackShortcut = true;
|
||||||
|
|
||||||
|
@JsonKey(defaultValue: false)
|
||||||
|
bool showShowImagePreviewWhenSending = false;
|
||||||
|
|
||||||
|
@JsonKey(defaultValue: true)
|
||||||
|
bool startWithCameraOpen = true;
|
||||||
|
|
||||||
List<String>? preSelectedEmojies;
|
List<String>? preSelectedEmojies;
|
||||||
|
|
||||||
Map<String, List<String>>? autoDownloadOptions;
|
Map<String, List<String>>? autoDownloadOptions;
|
||||||
|
|
@ -66,6 +72,9 @@ class UserData {
|
||||||
@JsonKey(defaultValue: false)
|
@JsonKey(defaultValue: false)
|
||||||
bool storeMediaFilesInGallery = false;
|
bool storeMediaFilesInGallery = false;
|
||||||
|
|
||||||
|
@JsonKey(defaultValue: false)
|
||||||
|
bool autoStoreAllSendUnlimitedMediaFiles = false;
|
||||||
|
|
||||||
String? lastPlanBallance;
|
String? lastPlanBallance;
|
||||||
String? additionalUserInvites;
|
String? additionalUserInvites;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
||||||
..requestedAudioPermission =
|
..requestedAudioPermission =
|
||||||
json['requestedAudioPermission'] as bool? ?? false
|
json['requestedAudioPermission'] as bool? ?? false
|
||||||
..showFeedbackShortcut = json['showFeedbackShortcut'] as bool? ?? true
|
..showFeedbackShortcut = json['showFeedbackShortcut'] as bool? ?? true
|
||||||
|
..showShowImagePreviewWhenSending =
|
||||||
|
json['showShowImagePreviewWhenSending'] as bool? ?? false
|
||||||
|
..startWithCameraOpen = json['startWithCameraOpen'] as bool? ?? true
|
||||||
..preSelectedEmojies = (json['preSelectedEmojies'] as List<dynamic>?)
|
..preSelectedEmojies = (json['preSelectedEmojies'] as List<dynamic>?)
|
||||||
?.map((e) => e as String)
|
?.map((e) => e as String)
|
||||||
.toList()
|
.toList()
|
||||||
|
|
@ -42,6 +45,8 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
||||||
)
|
)
|
||||||
..storeMediaFilesInGallery =
|
..storeMediaFilesInGallery =
|
||||||
json['storeMediaFilesInGallery'] as bool? ?? false
|
json['storeMediaFilesInGallery'] as bool? ?? false
|
||||||
|
..autoStoreAllSendUnlimitedMediaFiles =
|
||||||
|
json['autoStoreAllSendUnlimitedMediaFiles'] as bool? ?? false
|
||||||
..lastPlanBallance = json['lastPlanBallance'] as String?
|
..lastPlanBallance = json['lastPlanBallance'] as String?
|
||||||
..additionalUserInvites = json['additionalUserInvites'] as String?
|
..additionalUserInvites = json['additionalUserInvites'] as String?
|
||||||
..tutorialDisplayed = (json['tutorialDisplayed'] as List<dynamic>?)
|
..tutorialDisplayed = (json['tutorialDisplayed'] as List<dynamic>?)
|
||||||
|
|
@ -61,7 +66,7 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) => UserData(
|
||||||
..lastChangeLogHash = (json['lastChangeLogHash'] as List<dynamic>?)
|
..lastChangeLogHash = (json['lastChangeLogHash'] as List<dynamic>?)
|
||||||
?.map((e) => (e as num).toInt())
|
?.map((e) => (e as num).toInt())
|
||||||
.toList()
|
.toList()
|
||||||
..hideChangeLog = json['hideChangeLog'] as bool? ?? false
|
..hideChangeLog = json['hideChangeLog'] as bool? ?? true
|
||||||
..updateFCMToken = json['updateFCMToken'] as bool? ?? true
|
..updateFCMToken = json['updateFCMToken'] as bool? ?? true
|
||||||
..nextTimeToShowBackupNotice = json['nextTimeToShowBackupNotice'] == null
|
..nextTimeToShowBackupNotice = json['nextTimeToShowBackupNotice'] == null
|
||||||
? null
|
? null
|
||||||
|
|
@ -93,9 +98,14 @@ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
|
||||||
'defaultShowTime': instance.defaultShowTime,
|
'defaultShowTime': instance.defaultShowTime,
|
||||||
'requestedAudioPermission': instance.requestedAudioPermission,
|
'requestedAudioPermission': instance.requestedAudioPermission,
|
||||||
'showFeedbackShortcut': instance.showFeedbackShortcut,
|
'showFeedbackShortcut': instance.showFeedbackShortcut,
|
||||||
|
'showShowImagePreviewWhenSending':
|
||||||
|
instance.showShowImagePreviewWhenSending,
|
||||||
|
'startWithCameraOpen': instance.startWithCameraOpen,
|
||||||
'preSelectedEmojies': instance.preSelectedEmojies,
|
'preSelectedEmojies': instance.preSelectedEmojies,
|
||||||
'autoDownloadOptions': instance.autoDownloadOptions,
|
'autoDownloadOptions': instance.autoDownloadOptions,
|
||||||
'storeMediaFilesInGallery': instance.storeMediaFilesInGallery,
|
'storeMediaFilesInGallery': instance.storeMediaFilesInGallery,
|
||||||
|
'autoStoreAllSendUnlimitedMediaFiles':
|
||||||
|
instance.autoStoreAllSendUnlimitedMediaFiles,
|
||||||
'lastPlanBallance': instance.lastPlanBallance,
|
'lastPlanBallance': instance.lastPlanBallance,
|
||||||
'additionalUserInvites': instance.additionalUserInvites,
|
'additionalUserInvites': instance.additionalUserInvites,
|
||||||
'tutorialDisplayed': instance.tutorialDisplayed,
|
'tutorialDisplayed': instance.tutorialDisplayed,
|
||||||
|
|
|
||||||
|
|
@ -2260,6 +2260,69 @@ class ApplicationData_DeleteAccount extends $pb.GeneratedMessage {
|
||||||
static ApplicationData_DeleteAccount? _defaultInstance;
|
static ApplicationData_DeleteAccount? _defaultInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ApplicationData_AddAdditionalUser extends $pb.GeneratedMessage {
|
||||||
|
factory ApplicationData_AddAdditionalUser({
|
||||||
|
$fixnum.Int64? userId,
|
||||||
|
}) {
|
||||||
|
final result = create();
|
||||||
|
if (userId != null) result.userId = userId;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationData_AddAdditionalUser._();
|
||||||
|
|
||||||
|
factory ApplicationData_AddAdditionalUser.fromBuffer(
|
||||||
|
$core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory ApplicationData_AddAdditionalUser.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'ApplicationData.AddAdditionalUser',
|
||||||
|
package:
|
||||||
|
const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'),
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..aInt64(1, _omitFieldNames ? '' : 'userId')
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
ApplicationData_AddAdditionalUser clone() =>
|
||||||
|
ApplicationData_AddAdditionalUser()..mergeFromMessage(this);
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
ApplicationData_AddAdditionalUser copyWith(
|
||||||
|
void Function(ApplicationData_AddAdditionalUser) updates) =>
|
||||||
|
super.copyWith((message) =>
|
||||||
|
updates(message as ApplicationData_AddAdditionalUser))
|
||||||
|
as ApplicationData_AddAdditionalUser;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static ApplicationData_AddAdditionalUser create() =>
|
||||||
|
ApplicationData_AddAdditionalUser._();
|
||||||
|
@$core.override
|
||||||
|
ApplicationData_AddAdditionalUser createEmptyInstance() => create();
|
||||||
|
static $pb.PbList<ApplicationData_AddAdditionalUser> createRepeated() =>
|
||||||
|
$pb.PbList<ApplicationData_AddAdditionalUser>();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static ApplicationData_AddAdditionalUser getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<ApplicationData_AddAdditionalUser>(
|
||||||
|
create);
|
||||||
|
static ApplicationData_AddAdditionalUser? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$fixnum.Int64 get userId => $_getI64(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set userId($fixnum.Int64 value) => $_setInt64(0, value);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasUserId() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearUserId() => $_clearField(1);
|
||||||
|
}
|
||||||
|
|
||||||
enum ApplicationData_ApplicationData {
|
enum ApplicationData_ApplicationData {
|
||||||
textMessage,
|
textMessage,
|
||||||
getUserByUsername,
|
getUserByUsername,
|
||||||
|
|
@ -2285,6 +2348,7 @@ enum ApplicationData_ApplicationData {
|
||||||
changeUsername,
|
changeUsername,
|
||||||
ipaPurchase,
|
ipaPurchase,
|
||||||
ipaForceCheck,
|
ipaForceCheck,
|
||||||
|
addAdditionalUser,
|
||||||
notSet
|
notSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2314,6 +2378,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
ApplicationData_ChangeUsername? changeUsername,
|
ApplicationData_ChangeUsername? changeUsername,
|
||||||
ApplicationData_IPAPurchase? ipaPurchase,
|
ApplicationData_IPAPurchase? ipaPurchase,
|
||||||
ApplicationData_IPAForceCheck? ipaForceCheck,
|
ApplicationData_IPAForceCheck? ipaForceCheck,
|
||||||
|
ApplicationData_AddAdditionalUser? addAdditionalUser,
|
||||||
}) {
|
}) {
|
||||||
final result = create();
|
final result = create();
|
||||||
if (textMessage != null) result.textMessage = textMessage;
|
if (textMessage != null) result.textMessage = textMessage;
|
||||||
|
|
@ -2348,6 +2413,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
if (changeUsername != null) result.changeUsername = changeUsername;
|
if (changeUsername != null) result.changeUsername = changeUsername;
|
||||||
if (ipaPurchase != null) result.ipaPurchase = ipaPurchase;
|
if (ipaPurchase != null) result.ipaPurchase = ipaPurchase;
|
||||||
if (ipaForceCheck != null) result.ipaForceCheck = ipaForceCheck;
|
if (ipaForceCheck != null) result.ipaForceCheck = ipaForceCheck;
|
||||||
|
if (addAdditionalUser != null) result.addAdditionalUser = addAdditionalUser;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2386,6 +2452,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
26: ApplicationData_ApplicationData.changeUsername,
|
26: ApplicationData_ApplicationData.changeUsername,
|
||||||
27: ApplicationData_ApplicationData.ipaPurchase,
|
27: ApplicationData_ApplicationData.ipaPurchase,
|
||||||
28: ApplicationData_ApplicationData.ipaForceCheck,
|
28: ApplicationData_ApplicationData.ipaForceCheck,
|
||||||
|
29: ApplicationData_ApplicationData.addAdditionalUser,
|
||||||
0: ApplicationData_ApplicationData.notSet
|
0: ApplicationData_ApplicationData.notSet
|
||||||
};
|
};
|
||||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
|
@ -2417,7 +2484,8 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
25,
|
25,
|
||||||
26,
|
26,
|
||||||
27,
|
27,
|
||||||
28
|
28,
|
||||||
|
29
|
||||||
])
|
])
|
||||||
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textMessage',
|
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textMessage',
|
||||||
protoName: 'textMessage',
|
protoName: 'textMessage',
|
||||||
|
|
@ -2508,6 +2576,10 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
28, _omitFieldNames ? '' : 'ipaForceCheck',
|
28, _omitFieldNames ? '' : 'ipaForceCheck',
|
||||||
protoName: 'ipaForceCheck',
|
protoName: 'ipaForceCheck',
|
||||||
subBuilder: ApplicationData_IPAForceCheck.create)
|
subBuilder: ApplicationData_IPAForceCheck.create)
|
||||||
|
..aOM<ApplicationData_AddAdditionalUser>(
|
||||||
|
29, _omitFieldNames ? '' : 'addAdditionalUser',
|
||||||
|
protoName: 'addAdditionalUser',
|
||||||
|
subBuilder: ApplicationData_AddAdditionalUser.create)
|
||||||
..hasRequiredFields = false;
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
|
@ -2822,6 +2894,18 @@ class ApplicationData extends $pb.GeneratedMessage {
|
||||||
void clearIpaForceCheck() => $_clearField(28);
|
void clearIpaForceCheck() => $_clearField(28);
|
||||||
@$pb.TagNumber(28)
|
@$pb.TagNumber(28)
|
||||||
ApplicationData_IPAForceCheck ensureIpaForceCheck() => $_ensure(23);
|
ApplicationData_IPAForceCheck ensureIpaForceCheck() => $_ensure(23);
|
||||||
|
|
||||||
|
@$pb.TagNumber(29)
|
||||||
|
ApplicationData_AddAdditionalUser get addAdditionalUser => $_getN(24);
|
||||||
|
@$pb.TagNumber(29)
|
||||||
|
set addAdditionalUser(ApplicationData_AddAdditionalUser value) =>
|
||||||
|
$_setField(29, value);
|
||||||
|
@$pb.TagNumber(29)
|
||||||
|
$core.bool hasAddAdditionalUser() => $_has(24);
|
||||||
|
@$pb.TagNumber(29)
|
||||||
|
void clearAddAdditionalUser() => $_clearField(29);
|
||||||
|
@$pb.TagNumber(29)
|
||||||
|
ApplicationData_AddAdditionalUser ensureAddAdditionalUser() => $_ensure(24);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Response_PreKey extends $pb.GeneratedMessage {
|
class Response_PreKey extends $pb.GeneratedMessage {
|
||||||
|
|
|
||||||
|
|
@ -389,15 +389,6 @@ const ApplicationData$json = {
|
||||||
'9': 0,
|
'9': 0,
|
||||||
'10': 'redeemAdditionalCode'
|
'10': 'redeemAdditionalCode'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'1': 'removeAdditionalUser',
|
|
||||||
'3': 18,
|
|
||||||
'4': 1,
|
|
||||||
'5': 11,
|
|
||||||
'6': '.client_to_server.ApplicationData.RemoveAdditionalUser',
|
|
||||||
'9': 0,
|
|
||||||
'10': 'removeAdditionalUser'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
'1': 'updatePlanOptions',
|
'1': 'updatePlanOptions',
|
||||||
'3': 19,
|
'3': 19,
|
||||||
|
|
@ -479,6 +470,24 @@ const ApplicationData$json = {
|
||||||
'9': 0,
|
'9': 0,
|
||||||
'10': 'ipaForceCheck'
|
'10': 'ipaForceCheck'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'1': 'removeAdditionalUser',
|
||||||
|
'3': 18,
|
||||||
|
'4': 1,
|
||||||
|
'5': 11,
|
||||||
|
'6': '.client_to_server.ApplicationData.RemoveAdditionalUser',
|
||||||
|
'9': 0,
|
||||||
|
'10': 'removeAdditionalUser'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'1': 'addAdditionalUser',
|
||||||
|
'3': 29,
|
||||||
|
'4': 1,
|
||||||
|
'5': 11,
|
||||||
|
'6': '.client_to_server.ApplicationData.AddAdditionalUser',
|
||||||
|
'9': 0,
|
||||||
|
'10': 'addAdditionalUser'
|
||||||
|
},
|
||||||
],
|
],
|
||||||
'3': [
|
'3': [
|
||||||
ApplicationData_TextMessage$json,
|
ApplicationData_TextMessage$json,
|
||||||
|
|
@ -504,7 +513,8 @@ const ApplicationData$json = {
|
||||||
ApplicationData_ReportUser$json,
|
ApplicationData_ReportUser$json,
|
||||||
ApplicationData_IPAPurchase$json,
|
ApplicationData_IPAPurchase$json,
|
||||||
ApplicationData_IPAForceCheck$json,
|
ApplicationData_IPAForceCheck$json,
|
||||||
ApplicationData_DeleteAccount$json
|
ApplicationData_DeleteAccount$json,
|
||||||
|
ApplicationData_AddAdditionalUser$json
|
||||||
],
|
],
|
||||||
'8': [
|
'8': [
|
||||||
{'1': 'ApplicationData'},
|
{'1': 'ApplicationData'},
|
||||||
|
|
@ -714,6 +724,14 @@ const ApplicationData_DeleteAccount$json = {
|
||||||
'1': 'DeleteAccount',
|
'1': 'DeleteAccount',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||||
|
const ApplicationData_AddAdditionalUser$json = {
|
||||||
|
'1': 'AddAdditionalUser',
|
||||||
|
'2': [
|
||||||
|
{'1': 'user_id', '3': 1, '4': 1, '5': 3, '10': 'userId'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
/// Descriptor for `ApplicationData`. Decode as a `google.protobuf.DescriptorProto`.
|
/// Descriptor for `ApplicationData`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
||||||
'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dE1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm'
|
'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dE1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm'
|
||||||
|
|
@ -740,48 +758,51 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
||||||
'VudHNJbnZpdGVzGBAgASgLMjcuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuR2V0'
|
'VudHNJbnZpdGVzGBAgASgLMjcuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuR2V0'
|
||||||
'QWRkQWNjb3VudHNJbnZpdGVzSABSFWdldEFkZGFjY291bnRzSW52aXRlcxJsChRyZWRlZW1BZG'
|
'QWRkQWNjb3VudHNJbnZpdGVzSABSFWdldEFkZGFjY291bnRzSW52aXRlcxJsChRyZWRlZW1BZG'
|
||||||
'RpdGlvbmFsQ29kZRgRIAEoCzI2LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLlJl'
|
'RpdGlvbmFsQ29kZRgRIAEoCzI2LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLlJl'
|
||||||
'ZGVlbUFkZGl0aW9uYWxDb2RlSABSFHJlZGVlbUFkZGl0aW9uYWxDb2RlEmwKFHJlbW92ZUFkZG'
|
'ZGVlbUFkZGl0aW9uYWxDb2RlSABSFHJlZGVlbUFkZGl0aW9uYWxDb2RlEmMKEXVwZGF0ZVBsYW'
|
||||||
'l0aW9uYWxVc2VyGBIgASgLMjYuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVt'
|
'5PcHRpb25zGBMgASgLMjMuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuVXBkYXRl'
|
||||||
'b3ZlQWRkaXRpb25hbFVzZXJIAFIUcmVtb3ZlQWRkaXRpb25hbFVzZXISYwoRdXBkYXRlUGxhbk'
|
'UGxhbk9wdGlvbnNIAFIRdXBkYXRlUGxhbk9wdGlvbnMSVAoMZG93bmxvYWREb25lGBQgASgLMi'
|
||||||
'9wdGlvbnMYEyABKAsyMy5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5VcGRhdGVQ'
|
'4uY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuRG93bmxvYWREb25lSABSDGRvd25s'
|
||||||
'bGFuT3B0aW9uc0gAUhF1cGRhdGVQbGFuT3B0aW9ucxJUCgxkb3dubG9hZERvbmUYFCABKAsyLi'
|
'b2FkRG9uZRJ1ChdnZXRTaWduZWRQcmVrZXlCeVVzZXJpZBgWIAEoCzI5LmNsaWVudF90b19zZX'
|
||||||
'5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5Eb3dubG9hZERvbmVIAFIMZG93bmxv'
|
'J2ZXIuQXBwbGljYXRpb25EYXRhLkdldFNpZ25lZFByZUtleUJ5VXNlcklkSABSF2dldFNpZ25l'
|
||||||
'YWREb25lEnUKF2dldFNpZ25lZFByZWtleUJ5VXNlcmlkGBYgASgLMjkuY2xpZW50X3RvX3Nlcn'
|
'ZFByZWtleUJ5VXNlcmlkEmYKEnVwZGF0ZVNpZ25lZFByZWtleRgXIAEoCzI0LmNsaWVudF90b1'
|
||||||
'Zlci5BcHBsaWNhdGlvbkRhdGEuR2V0U2lnbmVkUHJlS2V5QnlVc2VySWRIAFIXZ2V0U2lnbmVk'
|
'9zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLlVwZGF0ZVNpZ25lZFByZUtleUgAUhJ1cGRhdGVTaWdu'
|
||||||
'UHJla2V5QnlVc2VyaWQSZgoSdXBkYXRlU2lnbmVkUHJla2V5GBcgASgLMjQuY2xpZW50X3RvX3'
|
'ZWRQcmVrZXkSVwoNZGVsZXRlQWNjb3VudBgYIAEoCzIvLmNsaWVudF90b19zZXJ2ZXIuQXBwbG'
|
||||||
'NlcnZlci5BcHBsaWNhdGlvbkRhdGEuVXBkYXRlU2lnbmVkUHJlS2V5SABSEnVwZGF0ZVNpZ25l'
|
'ljYXRpb25EYXRhLkRlbGV0ZUFjY291bnRIAFINZGVsZXRlQWNjb3VudBJOCgpyZXBvcnRVc2Vy'
|
||||||
'ZFByZWtleRJXCg1kZWxldGVBY2NvdW50GBggASgLMi8uY2xpZW50X3RvX3NlcnZlci5BcHBsaW'
|
'GBkgASgLMiwuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVwb3J0VXNlckgAUg'
|
||||||
'NhdGlvbkRhdGEuRGVsZXRlQWNjb3VudEgAUg1kZWxldGVBY2NvdW50Ek4KCnJlcG9ydFVzZXIY'
|
'pyZXBvcnRVc2VyEloKDmNoYW5nZVVzZXJuYW1lGBogASgLMjAuY2xpZW50X3RvX3NlcnZlci5B'
|
||||||
'GSABKAsyLC5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5SZXBvcnRVc2VySABSCn'
|
'cHBsaWNhdGlvbkRhdGEuQ2hhbmdlVXNlcm5hbWVIAFIOY2hhbmdlVXNlcm5hbWUSUQoLaXBhUH'
|
||||||
'JlcG9ydFVzZXISWgoOY2hhbmdlVXNlcm5hbWUYGiABKAsyMC5jbGllbnRfdG9fc2VydmVyLkFw'
|
'VyY2hhc2UYGyABKAsyLS5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5JUEFQdXJj'
|
||||||
'cGxpY2F0aW9uRGF0YS5DaGFuZ2VVc2VybmFtZUgAUg5jaGFuZ2VVc2VybmFtZRJRCgtpcGFQdX'
|
'aGFzZUgAUgtpcGFQdXJjaGFzZRJXCg1pcGFGb3JjZUNoZWNrGBwgASgLMi8uY2xpZW50X3RvX3'
|
||||||
'JjaGFzZRgbIAEoCzItLmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLklQQVB1cmNo'
|
'NlcnZlci5BcHBsaWNhdGlvbkRhdGEuSVBBRm9yY2VDaGVja0gAUg1pcGFGb3JjZUNoZWNrEmwK'
|
||||||
'YXNlSABSC2lwYVB1cmNoYXNlElcKDWlwYUZvcmNlQ2hlY2sYHCABKAsyLy5jbGllbnRfdG9fc2'
|
'FHJlbW92ZUFkZGl0aW9uYWxVc2VyGBIgASgLMjYuY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdG'
|
||||||
'VydmVyLkFwcGxpY2F0aW9uRGF0YS5JUEFGb3JjZUNoZWNrSABSDWlwYUZvcmNlQ2hlY2saagoL'
|
'lvbkRhdGEuUmVtb3ZlQWRkaXRpb25hbFVzZXJIAFIUcmVtb3ZlQWRkaXRpb25hbFVzZXISYwoR'
|
||||||
'VGV4dE1lc3NhZ2USFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhIKBGJvZHkYAyABKAxSBGJvZH'
|
'YWRkQWRkaXRpb25hbFVzZXIYHSABKAsyMy5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRG'
|
||||||
'kSIAoJcHVzaF9kYXRhGAQgASgMSABSCHB1c2hEYXRhiAEBQgwKCl9wdXNoX2RhdGEaLwoRR2V0'
|
'F0YS5BZGRBZGRpdGlvbmFsVXNlckgAUhFhZGRBZGRpdGlvbmFsVXNlchpqCgtUZXh0TWVzc2Fn'
|
||||||
'VXNlckJ5VXNlcm5hbWUSGgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW1lGiwKDkNoYW5nZVVzZX'
|
'ZRIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQSEgoEYm9keRgDIAEoDFIEYm9keRIgCglwdXNoX2'
|
||||||
'JuYW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRo1ChRVcGRhdGVHb29nbGVGY21Ub2tl'
|
'RhdGEYBCABKAxIAFIIcHVzaERhdGGIAQFCDAoKX3B1c2hfZGF0YRovChFHZXRVc2VyQnlVc2Vy'
|
||||||
'bhIdCgpnb29nbGVfZmNtGAEgASgJUglnb29nbGVGY20aJgoLR2V0VXNlckJ5SWQSFwoHdXNlcl'
|
'bmFtZRIaCgh1c2VybmFtZRgBIAEoCVIIdXNlcm5hbWUaLAoOQ2hhbmdlVXNlcm5hbWUSGgoIdX'
|
||||||
'9pZBgBIAEoA1IGdXNlcklkGikKDVJlZGVlbVZvdWNoZXISGAoHdm91Y2hlchgBIAEoCVIHdm91'
|
'Nlcm5hbWUYASABKAlSCHVzZXJuYW1lGjUKFFVwZGF0ZUdvb2dsZUZjbVRva2VuEh0KCmdvb2ds'
|
||||||
'Y2hlchpwChFTd2l0Y2hUb1BheWVkUGxhbhIXCgdwbGFuX2lkGAEgASgJUgZwbGFuSWQSHwoLcG'
|
'ZV9mY20YASABKAlSCWdvb2dsZUZjbRomCgtHZXRVc2VyQnlJZBIXCgd1c2VyX2lkGAEgASgDUg'
|
||||||
'F5X21vbnRobHkYAiABKAhSCnBheU1vbnRobHkSIQoMYXV0b19yZW5ld2FsGAMgASgIUgthdXRv'
|
'Z1c2VySWQaKQoNUmVkZWVtVm91Y2hlchIYCgd2b3VjaGVyGAEgASgJUgd2b3VjaGVyGnAKEVN3'
|
||||||
'UmVuZXdhbBo2ChFVcGRhdGVQbGFuT3B0aW9ucxIhCgxhdXRvX3JlbmV3YWwYASABKAhSC2F1dG'
|
'aXRjaFRvUGF5ZWRQbGFuEhcKB3BsYW5faWQYASABKAlSBnBsYW5JZBIfCgtwYXlfbW9udGhseR'
|
||||||
'9SZW5ld2FsGjAKDUNyZWF0ZVZvdWNoZXISHwoLdmFsdWVfY2VudHMYASABKA1SCnZhbHVlQ2Vu'
|
'gCIAEoCFIKcGF5TW9udGhseRIhCgxhdXRvX3JlbmV3YWwYAyABKAhSC2F1dG9SZW5ld2FsGjYK'
|
||||||
'dHMaDQoLR2V0TG9jYXRpb24aDQoLR2V0Vm91Y2hlcnMaEwoRR2V0QXZhaWxhYmxlUGxhbnMaFw'
|
'EVVwZGF0ZVBsYW5PcHRpb25zEiEKDGF1dG9fcmVuZXdhbBgBIAEoCFILYXV0b1JlbmV3YWwaMA'
|
||||||
'oVR2V0QWRkQWNjb3VudHNJbnZpdGVzGhUKE0dldEN1cnJlbnRQbGFuSW5mb3MaNwoUUmVkZWVt'
|
'oNQ3JlYXRlVm91Y2hlchIfCgt2YWx1ZV9jZW50cxgBIAEoDVIKdmFsdWVDZW50cxoNCgtHZXRM'
|
||||||
'QWRkaXRpb25hbENvZGUSHwoLaW52aXRlX2NvZGUYAiABKAlSCmludml0ZUNvZGUaLwoUUmVtb3'
|
'b2NhdGlvbhoNCgtHZXRWb3VjaGVycxoTChFHZXRBdmFpbGFibGVQbGFucxoXChVHZXRBZGRBY2'
|
||||||
'ZlQWRkaXRpb25hbFVzZXISFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkGi0KEkdldFByZWtleXNC'
|
'NvdW50c0ludml0ZXMaFQoTR2V0Q3VycmVudFBsYW5JbmZvcxo3ChRSZWRlZW1BZGRpdGlvbmFs'
|
||||||
'eVVzZXJJZBIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQaMgoXR2V0U2lnbmVkUHJlS2V5QnlVc2'
|
'Q29kZRIfCgtpbnZpdGVfY29kZRgCIAEoCVIKaW52aXRlQ29kZRovChRSZW1vdmVBZGRpdGlvbm'
|
||||||
'VySWQSFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkGpsBChJVcGRhdGVTaWduZWRQcmVLZXkSKAoQ'
|
'FsVXNlchIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQaLQoSR2V0UHJla2V5c0J5VXNlcklkEhcK'
|
||||||
'c2lnbmVkX3ByZWtleV9pZBgBIAEoA1IOc2lnbmVkUHJla2V5SWQSIwoNc2lnbmVkX3ByZWtleR'
|
'B3VzZXJfaWQYASABKANSBnVzZXJJZBoyChdHZXRTaWduZWRQcmVLZXlCeVVzZXJJZBIXCgd1c2'
|
||||||
'gCIAEoDFIMc2lnbmVkUHJla2V5EjYKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAMgASgMUhVz'
|
'VyX2lkGAEgASgDUgZ1c2VySWQamwEKElVwZGF0ZVNpZ25lZFByZUtleRIoChBzaWduZWRfcHJl'
|
||||||
'aWduZWRQcmVrZXlTaWduYXR1cmUaNQoMRG93bmxvYWREb25lEiUKDmRvd25sb2FkX3Rva2VuGA'
|
'a2V5X2lkGAEgASgDUg5zaWduZWRQcmVrZXlJZBIjCg1zaWduZWRfcHJla2V5GAIgASgMUgxzaW'
|
||||||
'EgASgMUg1kb3dubG9hZFRva2VuGk4KClJlcG9ydFVzZXISKAoQcmVwb3J0ZWRfdXNlcl9pZBgB'
|
'duZWRQcmVrZXkSNgoXc2lnbmVkX3ByZWtleV9zaWduYXR1cmUYAyABKAxSFXNpZ25lZFByZWtl'
|
||||||
'IAEoA1IOcmVwb3J0ZWRVc2VySWQSFgoGcmVhc29uGAIgASgJUgZyZWFzb24acQoLSVBBUHVyY2'
|
'eVNpZ25hdHVyZRo1CgxEb3dubG9hZERvbmUSJQoOZG93bmxvYWRfdG9rZW4YASABKAxSDWRvd2'
|
||||||
'hhc2USHQoKcHJvZHVjdF9pZBgBIAEoCVIJcHJvZHVjdElkEhYKBnNvdXJjZRgCIAEoCVIGc291'
|
'5sb2FkVG9rZW4aTgoKUmVwb3J0VXNlchIoChByZXBvcnRlZF91c2VyX2lkGAEgASgDUg5yZXBv'
|
||||||
'cmNlEisKEXZlcmlmaWNhdGlvbl9kYXRhGAMgASgJUhB2ZXJpZmljYXRpb25EYXRhGg8KDUlQQU'
|
'cnRlZFVzZXJJZBIWCgZyZWFzb24YAiABKAlSBnJlYXNvbhpxCgtJUEFQdXJjaGFzZRIdCgpwcm'
|
||||||
'ZvcmNlQ2hlY2saDwoNRGVsZXRlQWNjb3VudEIRCg9BcHBsaWNhdGlvbkRhdGE=');
|
'9kdWN0X2lkGAEgASgJUglwcm9kdWN0SWQSFgoGc291cmNlGAIgASgJUgZzb3VyY2USKwoRdmVy'
|
||||||
|
'aWZpY2F0aW9uX2RhdGEYAyABKAlSEHZlcmlmaWNhdGlvbkRhdGEaDwoNSVBBRm9yY2VDaGVjax'
|
||||||
|
'oPCg1EZWxldGVBY2NvdW50GiwKEUFkZEFkZGl0aW9uYWxVc2VyEhcKB3VzZXJfaWQYASABKANS'
|
||||||
|
'BnVzZXJJZEIRCg9BcHBsaWNhdGlvbkRhdGE=');
|
||||||
|
|
||||||
@$core.Deprecated('Use responseDescriptor instead')
|
@$core.Deprecated('Use responseDescriptor instead')
|
||||||
const Response$json = {
|
const Response$json = {
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,8 @@ class ErrorCode extends $pb.ProtobufEnum {
|
||||||
ErrorCode._(1033, _omitEnumNames ? '' : 'RegistrationDisabled');
|
ErrorCode._(1033, _omitEnumNames ? '' : 'RegistrationDisabled');
|
||||||
static const ErrorCode IPAPaymentExpired =
|
static const ErrorCode IPAPaymentExpired =
|
||||||
ErrorCode._(1034, _omitEnumNames ? '' : 'IPAPaymentExpired');
|
ErrorCode._(1034, _omitEnumNames ? '' : 'IPAPaymentExpired');
|
||||||
|
static const ErrorCode UserIsNotInFreePlan =
|
||||||
|
ErrorCode._(1035, _omitEnumNames ? '' : 'UserIsNotInFreePlan');
|
||||||
|
|
||||||
static const $core.List<ErrorCode> values = <ErrorCode>[
|
static const $core.List<ErrorCode> values = <ErrorCode>[
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
@ -128,6 +130,7 @@ class ErrorCode extends $pb.ProtobufEnum {
|
||||||
InvalidProofOfWork,
|
InvalidProofOfWork,
|
||||||
RegistrationDisabled,
|
RegistrationDisabled,
|
||||||
IPAPaymentExpired,
|
IPAPaymentExpired,
|
||||||
|
UserIsNotInFreePlan,
|
||||||
];
|
];
|
||||||
|
|
||||||
static final $core.Map<$core.int, ErrorCode> _byValue =
|
static final $core.Map<$core.int, ErrorCode> _byValue =
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ const ErrorCode$json = {
|
||||||
{'1': 'InvalidProofOfWork', '2': 1032},
|
{'1': 'InvalidProofOfWork', '2': 1032},
|
||||||
{'1': 'RegistrationDisabled', '2': 1033},
|
{'1': 'RegistrationDisabled', '2': 1033},
|
||||||
{'1': 'IPAPaymentExpired', '2': 1034},
|
{'1': 'IPAPaymentExpired', '2': 1034},
|
||||||
|
{'1': 'UserIsNotInFreePlan', '2': 1035},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -76,4 +77,4 @@ final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode(
|
||||||
'duZWRQcmVLZXkQgwgSEwoOVXNlcklkTm90Rm91bmQQhAgSFwoSVXNlcklkQWxyZWFkeVRha2Vu'
|
'duZWRQcmVLZXkQgwgSEwoOVXNlcklkTm90Rm91bmQQhAgSFwoSVXNlcklkQWxyZWFkeVRha2Vu'
|
||||||
'EIUIEhcKEkFwcFZlcnNpb25PdXRkYXRlZBCGCBIYChNOZXdEZXZpY2VSZWdpc3RlcmVkEIcIEh'
|
'EIUIEhcKEkFwcFZlcnNpb25PdXRkYXRlZBCGCBIYChNOZXdEZXZpY2VSZWdpc3RlcmVkEIcIEh'
|
||||||
'cKEkludmFsaWRQcm9vZk9mV29yaxCICBIZChRSZWdpc3RyYXRpb25EaXNhYmxlZBCJCBIWChFJ'
|
'cKEkludmFsaWRQcm9vZk9mV29yaxCICBIZChRSZWdpc3RyYXRpb25EaXNhYmxlZBCJCBIWChFJ'
|
||||||
'UEFQYXltZW50RXhwaXJlZBCKCA==');
|
'UEFQYXltZW50RXhwaXJlZBCKCBIYChNVc2VySXNOb3RJbkZyZWVQbGFuEIsI');
|
||||||
|
|
|
||||||
|
|
@ -428,7 +428,6 @@ class Response_Plan extends $pb.GeneratedMessage {
|
||||||
$fixnum.Int64? dailyMediaUploadLimit,
|
$fixnum.Int64? dailyMediaUploadLimit,
|
||||||
$fixnum.Int64? maximalUploadSizeOfSingleMediaSize,
|
$fixnum.Int64? maximalUploadSizeOfSingleMediaSize,
|
||||||
$fixnum.Int64? additionalPlusAccounts,
|
$fixnum.Int64? additionalPlusAccounts,
|
||||||
$fixnum.Int64? additionalFreeAccounts,
|
|
||||||
$fixnum.Int64? monthlyCostsCent,
|
$fixnum.Int64? monthlyCostsCent,
|
||||||
$fixnum.Int64? yearlyCostsCent,
|
$fixnum.Int64? yearlyCostsCent,
|
||||||
$core.bool? allowedToSendTextMessages,
|
$core.bool? allowedToSendTextMessages,
|
||||||
|
|
@ -444,8 +443,6 @@ class Response_Plan extends $pb.GeneratedMessage {
|
||||||
maximalUploadSizeOfSingleMediaSize;
|
maximalUploadSizeOfSingleMediaSize;
|
||||||
if (additionalPlusAccounts != null)
|
if (additionalPlusAccounts != null)
|
||||||
result.additionalPlusAccounts = additionalPlusAccounts;
|
result.additionalPlusAccounts = additionalPlusAccounts;
|
||||||
if (additionalFreeAccounts != null)
|
|
||||||
result.additionalFreeAccounts = additionalFreeAccounts;
|
|
||||||
if (monthlyCostsCent != null) result.monthlyCostsCent = monthlyCostsCent;
|
if (monthlyCostsCent != null) result.monthlyCostsCent = monthlyCostsCent;
|
||||||
if (yearlyCostsCent != null) result.yearlyCostsCent = yearlyCostsCent;
|
if (yearlyCostsCent != null) result.yearlyCostsCent = yearlyCostsCent;
|
||||||
if (allowedToSendTextMessages != null)
|
if (allowedToSendTextMessages != null)
|
||||||
|
|
@ -474,7 +471,6 @@ class Response_Plan extends $pb.GeneratedMessage {
|
||||||
..aInt64(3, _omitFieldNames ? '' : 'dailyMediaUploadLimit')
|
..aInt64(3, _omitFieldNames ? '' : 'dailyMediaUploadLimit')
|
||||||
..aInt64(4, _omitFieldNames ? '' : 'maximalUploadSizeOfSingleMediaSize')
|
..aInt64(4, _omitFieldNames ? '' : 'maximalUploadSizeOfSingleMediaSize')
|
||||||
..aInt64(5, _omitFieldNames ? '' : 'additionalPlusAccounts')
|
..aInt64(5, _omitFieldNames ? '' : 'additionalPlusAccounts')
|
||||||
..aInt64(6, _omitFieldNames ? '' : 'additionalFreeAccounts')
|
|
||||||
..aInt64(7, _omitFieldNames ? '' : 'monthlyCostsCent')
|
..aInt64(7, _omitFieldNames ? '' : 'monthlyCostsCent')
|
||||||
..aInt64(8, _omitFieldNames ? '' : 'yearlyCostsCent')
|
..aInt64(8, _omitFieldNames ? '' : 'yearlyCostsCent')
|
||||||
..aOB(9, _omitFieldNames ? '' : 'allowedToSendTextMessages')
|
..aOB(9, _omitFieldNames ? '' : 'allowedToSendTextMessages')
|
||||||
|
|
@ -548,48 +544,39 @@ class Response_Plan extends $pb.GeneratedMessage {
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
void clearAdditionalPlusAccounts() => $_clearField(5);
|
void clearAdditionalPlusAccounts() => $_clearField(5);
|
||||||
|
|
||||||
@$pb.TagNumber(6)
|
|
||||||
$fixnum.Int64 get additionalFreeAccounts => $_getI64(5);
|
|
||||||
@$pb.TagNumber(6)
|
|
||||||
set additionalFreeAccounts($fixnum.Int64 value) => $_setInt64(5, value);
|
|
||||||
@$pb.TagNumber(6)
|
|
||||||
$core.bool hasAdditionalFreeAccounts() => $_has(5);
|
|
||||||
@$pb.TagNumber(6)
|
|
||||||
void clearAdditionalFreeAccounts() => $_clearField(6);
|
|
||||||
|
|
||||||
@$pb.TagNumber(7)
|
@$pb.TagNumber(7)
|
||||||
$fixnum.Int64 get monthlyCostsCent => $_getI64(6);
|
$fixnum.Int64 get monthlyCostsCent => $_getI64(5);
|
||||||
@$pb.TagNumber(7)
|
@$pb.TagNumber(7)
|
||||||
set monthlyCostsCent($fixnum.Int64 value) => $_setInt64(6, value);
|
set monthlyCostsCent($fixnum.Int64 value) => $_setInt64(5, value);
|
||||||
@$pb.TagNumber(7)
|
@$pb.TagNumber(7)
|
||||||
$core.bool hasMonthlyCostsCent() => $_has(6);
|
$core.bool hasMonthlyCostsCent() => $_has(5);
|
||||||
@$pb.TagNumber(7)
|
@$pb.TagNumber(7)
|
||||||
void clearMonthlyCostsCent() => $_clearField(7);
|
void clearMonthlyCostsCent() => $_clearField(7);
|
||||||
|
|
||||||
@$pb.TagNumber(8)
|
@$pb.TagNumber(8)
|
||||||
$fixnum.Int64 get yearlyCostsCent => $_getI64(7);
|
$fixnum.Int64 get yearlyCostsCent => $_getI64(6);
|
||||||
@$pb.TagNumber(8)
|
@$pb.TagNumber(8)
|
||||||
set yearlyCostsCent($fixnum.Int64 value) => $_setInt64(7, value);
|
set yearlyCostsCent($fixnum.Int64 value) => $_setInt64(6, value);
|
||||||
@$pb.TagNumber(8)
|
@$pb.TagNumber(8)
|
||||||
$core.bool hasYearlyCostsCent() => $_has(7);
|
$core.bool hasYearlyCostsCent() => $_has(6);
|
||||||
@$pb.TagNumber(8)
|
@$pb.TagNumber(8)
|
||||||
void clearYearlyCostsCent() => $_clearField(8);
|
void clearYearlyCostsCent() => $_clearField(8);
|
||||||
|
|
||||||
@$pb.TagNumber(9)
|
@$pb.TagNumber(9)
|
||||||
$core.bool get allowedToSendTextMessages => $_getBF(8);
|
$core.bool get allowedToSendTextMessages => $_getBF(7);
|
||||||
@$pb.TagNumber(9)
|
@$pb.TagNumber(9)
|
||||||
set allowedToSendTextMessages($core.bool value) => $_setBool(8, value);
|
set allowedToSendTextMessages($core.bool value) => $_setBool(7, value);
|
||||||
@$pb.TagNumber(9)
|
@$pb.TagNumber(9)
|
||||||
$core.bool hasAllowedToSendTextMessages() => $_has(8);
|
$core.bool hasAllowedToSendTextMessages() => $_has(7);
|
||||||
@$pb.TagNumber(9)
|
@$pb.TagNumber(9)
|
||||||
void clearAllowedToSendTextMessages() => $_clearField(9);
|
void clearAllowedToSendTextMessages() => $_clearField(9);
|
||||||
|
|
||||||
@$pb.TagNumber(10)
|
@$pb.TagNumber(10)
|
||||||
$core.bool get isAdditionalAccount => $_getBF(9);
|
$core.bool get isAdditionalAccount => $_getBF(8);
|
||||||
@$pb.TagNumber(10)
|
@$pb.TagNumber(10)
|
||||||
set isAdditionalAccount($core.bool value) => $_setBool(9, value);
|
set isAdditionalAccount($core.bool value) => $_setBool(8, value);
|
||||||
@$pb.TagNumber(10)
|
@$pb.TagNumber(10)
|
||||||
$core.bool hasIsAdditionalAccount() => $_has(9);
|
$core.bool hasIsAdditionalAccount() => $_has(8);
|
||||||
@$pb.TagNumber(10)
|
@$pb.TagNumber(10)
|
||||||
void clearIsAdditionalAccount() => $_clearField(10);
|
void clearIsAdditionalAccount() => $_clearField(10);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -220,13 +220,6 @@ const Response_Plan$json = {
|
||||||
'5': 3,
|
'5': 3,
|
||||||
'10': 'additionalPlusAccounts'
|
'10': 'additionalPlusAccounts'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'1': 'additional_free_accounts',
|
|
||||||
'3': 6,
|
|
||||||
'4': 1,
|
|
||||||
'5': 3,
|
|
||||||
'10': 'additionalFreeAccounts'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
'1': 'monthly_costs_cent',
|
'1': 'monthly_costs_cent',
|
||||||
'3': 7,
|
'3': 7,
|
||||||
|
|
@ -713,78 +706,77 @@ const Response_TransactionTypes$json = {
|
||||||
final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
|
final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
|
||||||
'CghSZXNwb25zZRIvCgJvaxgBIAEoCzIdLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuT2tIAF'
|
'CghSZXNwb25zZRIvCgJvaxgBIAEoCzIdLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuT2tIAF'
|
||||||
'ICb2sSKAoFZXJyb3IYAiABKA4yEC5lcnJvci5FcnJvckNvZGVIAFIFZXJyb3IaIwoNQXV0aGVu'
|
'ICb2sSKAoFZXJyb3IYAiABKA4yEC5lcnJvci5FcnJvckNvZGVIAFIFZXJyb3IaIwoNQXV0aGVu'
|
||||||
'dGljYXRlZBISCgRwbGFuGAEgASgJUgRwbGFuGp4ECgRQbGFuEhcKB3BsYW5faWQYASABKAlSBn'
|
'dGljYXRlZBISCgRwbGFuGAEgASgJUgRwbGFuGuQDCgRQbGFuEhcKB3BsYW5faWQYASABKAlSBn'
|
||||||
'BsYW5JZBIqChF1cGxvYWRfc2l6ZV9saW1pdBgCIAEoA1IPdXBsb2FkU2l6ZUxpbWl0EjcKGGRh'
|
'BsYW5JZBIqChF1cGxvYWRfc2l6ZV9saW1pdBgCIAEoA1IPdXBsb2FkU2l6ZUxpbWl0EjcKGGRh'
|
||||||
'aWx5X21lZGlhX3VwbG9hZF9saW1pdBgDIAEoA1IVZGFpbHlNZWRpYVVwbG9hZExpbWl0ElQKKG'
|
'aWx5X21lZGlhX3VwbG9hZF9saW1pdBgDIAEoA1IVZGFpbHlNZWRpYVVwbG9hZExpbWl0ElQKKG'
|
||||||
'1heGltYWxfdXBsb2FkX3NpemVfb2Zfc2luZ2xlX21lZGlhX3NpemUYBCABKANSIm1heGltYWxV'
|
'1heGltYWxfdXBsb2FkX3NpemVfb2Zfc2luZ2xlX21lZGlhX3NpemUYBCABKANSIm1heGltYWxV'
|
||||||
'cGxvYWRTaXplT2ZTaW5nbGVNZWRpYVNpemUSOAoYYWRkaXRpb25hbF9wbHVzX2FjY291bnRzGA'
|
'cGxvYWRTaXplT2ZTaW5nbGVNZWRpYVNpemUSOAoYYWRkaXRpb25hbF9wbHVzX2FjY291bnRzGA'
|
||||||
'UgASgDUhZhZGRpdGlvbmFsUGx1c0FjY291bnRzEjgKGGFkZGl0aW9uYWxfZnJlZV9hY2NvdW50'
|
'UgASgDUhZhZGRpdGlvbmFsUGx1c0FjY291bnRzEiwKEm1vbnRobHlfY29zdHNfY2VudBgHIAEo'
|
||||||
'cxgGIAEoA1IWYWRkaXRpb25hbEZyZWVBY2NvdW50cxIsChJtb250aGx5X2Nvc3RzX2NlbnQYBy'
|
'A1IQbW9udGhseUNvc3RzQ2VudBIqChF5ZWFybHlfY29zdHNfY2VudBgIIAEoA1IPeWVhcmx5Q2'
|
||||||
'ABKANSEG1vbnRobHlDb3N0c0NlbnQSKgoReWVhcmx5X2Nvc3RzX2NlbnQYCCABKANSD3llYXJs'
|
'9zdHNDZW50EkAKHWFsbG93ZWRfdG9fc2VuZF90ZXh0X21lc3NhZ2VzGAkgASgIUhlhbGxvd2Vk'
|
||||||
'eUNvc3RzQ2VudBJACh1hbGxvd2VkX3RvX3NlbmRfdGV4dF9tZXNzYWdlcxgJIAEoCFIZYWxsb3'
|
'VG9TZW5kVGV4dE1lc3NhZ2VzEjIKFWlzX2FkZGl0aW9uYWxfYWNjb3VudBgKIAEoCFITaXNBZG'
|
||||||
'dlZFRvU2VuZFRleHRNZXNzYWdlcxIyChVpc19hZGRpdGlvbmFsX2FjY291bnQYCiABKAhSE2lz'
|
'RpdGlvbmFsQWNjb3VudBo+CgVQbGFucxI1CgVwbGFucxgBIAMoCzIfLnNlcnZlcl90b19jbGll'
|
||||||
'QWRkaXRpb25hbEFjY291bnQaPgoFUGxhbnMSNQoFcGxhbnMYASADKAsyHy5zZXJ2ZXJfdG9fY2'
|
'bnQuUmVzcG9uc2UuUGxhblIFcGxhbnMaTQoRQWRkQWNjb3VudHNJbnZpdGUSFwoHcGxhbl9pZB'
|
||||||
'xpZW50LlJlc3BvbnNlLlBsYW5SBXBsYW5zGk0KEUFkZEFjY291bnRzSW52aXRlEhcKB3BsYW5f'
|
'gBIAEoCVIGcGxhbklkEh8KC2ludml0ZV9jb2RlGAIgASgJUgppbnZpdGVDb2RlGlwKEkFkZEFj'
|
||||||
'aWQYASABKAlSBnBsYW5JZBIfCgtpbnZpdGVfY29kZRgCIAEoCVIKaW52aXRlQ29kZRpcChJBZG'
|
'Y291bnRzSW52aXRlcxJGCgdpbnZpdGVzGAEgAygLMiwuc2VydmVyX3RvX2NsaWVudC5SZXNwb2'
|
||||||
'RBY2NvdW50c0ludml0ZXMSRgoHaW52aXRlcxgBIAMoCzIsLnNlcnZlcl90b19jbGllbnQuUmVz'
|
'5zZS5BZGRBY2NvdW50c0ludml0ZVIHaW52aXRlcxrFAQoLVHJhbnNhY3Rpb24SIwoNZGVwb3Np'
|
||||||
'cG9uc2UuQWRkQWNjb3VudHNJbnZpdGVSB2ludml0ZXMaxQEKC1RyYW5zYWN0aW9uEiMKDWRlcG'
|
'dF9jZW50cxgBIAEoA1IMZGVwb3NpdENlbnRzElYKEHRyYW5zYWN0aW9uX3R5cGUYAiABKA4yKy'
|
||||||
'9zaXRfY2VudHMYASABKANSDGRlcG9zaXRDZW50cxJWChB0cmFuc2FjdGlvbl90eXBlGAIgASgO'
|
'5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlRyYW5zYWN0aW9uVHlwZXNSD3RyYW5zYWN0aW9u'
|
||||||
'Misuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5UcmFuc2FjdGlvblR5cGVzUg90cmFuc2FjdG'
|
'VHlwZRI5ChljcmVhdGVkX2F0X3VuaXhfdGltZXN0YW1wGAMgASgDUhZjcmVhdGVkQXRVbml4VG'
|
||||||
'lvblR5cGUSOQoZY3JlYXRlZF9hdF91bml4X3RpbWVzdGFtcBgDIAEoA1IWY3JlYXRlZEF0VW5p'
|
'ltZXN0YW1wGkUKEUFkZGl0aW9uYWxBY2NvdW50EhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBIX'
|
||||||
'eFRpbWVzdGFtcBpFChFBZGRpdGlvbmFsQWNjb3VudBIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySW'
|
'CgdwbGFuX2lkGAMgASgJUgZwbGFuSWQavgEKB1ZvdWNoZXISHQoKdm91Y2hlcl9pZBgBIAEoCV'
|
||||||
'QSFwoHcGxhbl9pZBgDIAEoCVIGcGxhbklkGr4BCgdWb3VjaGVyEh0KCnZvdWNoZXJfaWQYASAB'
|
'IJdm91Y2hlcklkEh8KC3ZhbHVlX2NlbnRzGAIgASgDUgp2YWx1ZUNlbnRzEhoKCHJlZGVlbWVk'
|
||||||
'KAlSCXZvdWNoZXJJZBIfCgt2YWx1ZV9jZW50cxgCIAEoA1IKdmFsdWVDZW50cxIaCghyZWRlZW'
|
'GAMgASgIUghyZWRlZW1lZBIcCglyZXF1ZXN0ZWQYBCABKAhSCXJlcXVlc3RlZBI5ChljcmVhdG'
|
||||||
'1lZBgDIAEoCFIIcmVkZWVtZWQSHAoJcmVxdWVzdGVkGAQgASgIUglyZXF1ZXN0ZWQSOQoZY3Jl'
|
'VkX2F0X3VuaXhfdGltZXN0YW1wGAUgASgDUhZjcmVhdGVkQXRVbml4VGltZXN0YW1wGkoKCFZv'
|
||||||
'YXRlZF9hdF91bml4X3RpbWVzdGFtcBgFIAEoA1IWY3JlYXRlZEF0VW5peFRpbWVzdGFtcBpKCg'
|
'dWNoZXJzEj4KCHZvdWNoZXJzGAEgAygLMiIuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5Wb3'
|
||||||
'hWb3VjaGVycxI+Cgh2b3VjaGVycxgBIAMoCzIiLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2Uu'
|
'VjaGVyUgh2b3VjaGVycxqXBQoMUGxhbkJhbGxhbmNlEkAKHXVzZWRfZGFpbHlfbWVkaWFfdXBs'
|
||||||
'Vm91Y2hlclIIdm91Y2hlcnMalwUKDFBsYW5CYWxsYW5jZRJACh11c2VkX2RhaWx5X21lZGlhX3'
|
'b2FkX2xpbWl0GAEgASgDUhl1c2VkRGFpbHlNZWRpYVVwbG9hZExpbWl0Ej4KHHVzZWRfdXBsb2'
|
||||||
'VwbG9hZF9saW1pdBgBIAEoA1IZdXNlZERhaWx5TWVkaWFVcGxvYWRMaW1pdBI+Chx1c2VkX3Vw'
|
'FkX21lZGlhX3NpemVfbGltaXQYAiABKANSGHVzZWRVcGxvYWRNZWRpYVNpemVMaW1pdBIzChNw'
|
||||||
'bG9hZF9tZWRpYV9zaXplX2xpbWl0GAIgASgDUhh1c2VkVXBsb2FkTWVkaWFTaXplTGltaXQSMw'
|
'YXltZW50X3BlcmlvZF9kYXlzGAMgASgDSABSEXBheW1lbnRQZXJpb2REYXlziAEBEksKIGxhc3'
|
||||||
'oTcGF5bWVudF9wZXJpb2RfZGF5cxgDIAEoA0gAUhFwYXltZW50UGVyaW9kRGF5c4gBARJLCiBs'
|
'RfcGF5bWVudF9kb25lX3VuaXhfdGltZXN0YW1wGAQgASgDSAFSHGxhc3RQYXltZW50RG9uZVVu'
|
||||||
'YXN0X3BheW1lbnRfZG9uZV91bml4X3RpbWVzdGFtcBgEIAEoA0gBUhxsYXN0UGF5bWVudERvbm'
|
'aXhUaW1lc3RhbXCIAQESSgoMdHJhbnNhY3Rpb25zGAUgAygLMiYuc2VydmVyX3RvX2NsaWVudC'
|
||||||
'VVbml4VGltZXN0YW1wiAEBEkoKDHRyYW5zYWN0aW9ucxgFIAMoCzImLnNlcnZlcl90b19jbGll'
|
'5SZXNwb25zZS5UcmFuc2FjdGlvblIMdHJhbnNhY3Rpb25zEl0KE2FkZGl0aW9uYWxfYWNjb3Vu'
|
||||||
'bnQuUmVzcG9uc2UuVHJhbnNhY3Rpb25SDHRyYW5zYWN0aW9ucxJdChNhZGRpdGlvbmFsX2FjY2'
|
'dHMYBiADKAsyLC5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkFkZGl0aW9uYWxBY2NvdW50Uh'
|
||||||
'91bnRzGAYgAygLMiwuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5BZGRpdGlvbmFsQWNjb3Vu'
|
'JhZGRpdGlvbmFsQWNjb3VudHMSJgoMYXV0b19yZW5ld2FsGAcgASgISAJSC2F1dG9SZW5ld2Fs'
|
||||||
'dFISYWRkaXRpb25hbEFjY291bnRzEiYKDGF1dG9fcmVuZXdhbBgHIAEoCEgCUgthdXRvUmVuZX'
|
'iAEBEkIKG2FkZGl0aW9uYWxfYWNjb3VudF9vd25lcl9pZBgIIAEoA0gDUhhhZGRpdGlvbmFsQW'
|
||||||
'dhbIgBARJCChthZGRpdGlvbmFsX2FjY291bnRfb3duZXJfaWQYCCABKANIA1IYYWRkaXRpb25h'
|
'Njb3VudE93bmVySWSIAQFCFgoUX3BheW1lbnRfcGVyaW9kX2RheXNCIwohX2xhc3RfcGF5bWVu'
|
||||||
'bEFjY291bnRPd25lcklkiAEBQhYKFF9wYXltZW50X3BlcmlvZF9kYXlzQiMKIV9sYXN0X3BheW'
|
'dF9kb25lX3VuaXhfdGltZXN0YW1wQg8KDV9hdXRvX3JlbmV3YWxCHgocX2FkZGl0aW9uYWxfYW'
|
||||||
'1lbnRfZG9uZV91bml4X3RpbWVzdGFtcEIPCg1fYXV0b19yZW5ld2FsQh4KHF9hZGRpdGlvbmFs'
|
'Njb3VudF9vd25lcl9pZBpOCghMb2NhdGlvbhIWCgZjb3VudHkYASABKAlSBmNvdW50eRIWCgZy'
|
||||||
'X2FjY291bnRfb3duZXJfaWQaTgoITG9jYXRpb24SFgoGY291bnR5GAEgASgJUgZjb3VudHkSFg'
|
'ZWdpb24YAiABKAlSBnJlZ2lvbhISCgRjaXR5GAMgASgJUgRjaXR5GjAKBlByZUtleRIOCgJpZB'
|
||||||
'oGcmVnaW9uGAIgASgJUgZyZWdpb24SEgoEY2l0eRgDIAEoCVIEY2l0eRowCgZQcmVLZXkSDgoC'
|
'gBIAEoA1ICaWQSFgoGcHJla2V5GAIgASgMUgZwcmVrZXkalQEKDFNpZ25lZFByZUtleRIoChBz'
|
||||||
'aWQYASABKANSAmlkEhYKBnByZWtleRgCIAEoDFIGcHJla2V5GpUBCgxTaWduZWRQcmVLZXkSKA'
|
'aWduZWRfcHJla2V5X2lkGAEgASgDUg5zaWduZWRQcmVrZXlJZBIjCg1zaWduZWRfcHJla2V5GA'
|
||||||
'oQc2lnbmVkX3ByZWtleV9pZBgBIAEoA1IOc2lnbmVkUHJla2V5SWQSIwoNc2lnbmVkX3ByZWtl'
|
'IgASgMUgxzaWduZWRQcmVrZXkSNgoXc2lnbmVkX3ByZWtleV9zaWduYXR1cmUYAyABKAxSFXNp'
|
||||||
'eRgCIAEoDFIMc2lnbmVkUHJla2V5EjYKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAMgASgMUh'
|
'Z25lZFByZWtleVNpZ25hdHVyZRr2AwoIVXNlckRhdGESFwoHdXNlcl9pZBgBIAEoA1IGdXNlck'
|
||||||
'VzaWduZWRQcmVrZXlTaWduYXR1cmUa9gMKCFVzZXJEYXRhEhcKB3VzZXJfaWQYASABKANSBnVz'
|
'lkEjsKB3ByZWtleXMYAiADKAsyIS5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlByZUtleVIH'
|
||||||
'ZXJJZBI7CgdwcmVrZXlzGAIgAygLMiEuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QcmVLZX'
|
'cHJla2V5cxIfCgh1c2VybmFtZRgHIAEoDEgAUgh1c2VybmFtZYgBARIzChNwdWJsaWNfaWRlbn'
|
||||||
'lSB3ByZWtleXMSHwoIdXNlcm5hbWUYByABKAxIAFIIdXNlcm5hbWWIAQESMwoTcHVibGljX2lk'
|
'RpdHlfa2V5GAMgASgMSAFSEXB1YmxpY0lkZW50aXR5S2V5iAEBEigKDXNpZ25lZF9wcmVrZXkY'
|
||||||
'ZW50aXR5X2tleRgDIAEoDEgBUhFwdWJsaWNJZGVudGl0eUtleYgBARIoCg1zaWduZWRfcHJla2'
|
'BCABKAxIAlIMc2lnbmVkUHJla2V5iAEBEjsKF3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlGAUgAS'
|
||||||
'V5GAQgASgMSAJSDHNpZ25lZFByZWtleYgBARI7ChdzaWduZWRfcHJla2V5X3NpZ25hdHVyZRgF'
|
'gMSANSFXNpZ25lZFByZWtleVNpZ25hdHVyZYgBARItChBzaWduZWRfcHJla2V5X2lkGAYgASgD'
|
||||||
'IAEoDEgDUhVzaWduZWRQcmVrZXlTaWduYXR1cmWIAQESLQoQc2lnbmVkX3ByZWtleV9pZBgGIA'
|
'SARSDnNpZ25lZFByZWtleUlkiAEBEiwKD3JlZ2lzdHJhdGlvbl9pZBgIIAEoA0gFUg5yZWdpc3'
|
||||||
'EoA0gEUg5zaWduZWRQcmVrZXlJZIgBARIsCg9yZWdpc3RyYXRpb25faWQYCCABKANIBVIOcmVn'
|
'RyYXRpb25JZIgBAUILCglfdXNlcm5hbWVCFgoUX3B1YmxpY19pZGVudGl0eV9rZXlCEAoOX3Np'
|
||||||
'aXN0cmF0aW9uSWSIAQFCCwoJX3VzZXJuYW1lQhYKFF9wdWJsaWNfaWRlbnRpdHlfa2V5QhAKDl'
|
'Z25lZF9wcmVrZXlCGgoYX3NpZ25lZF9wcmVrZXlfc2lnbmF0dXJlQhMKEV9zaWduZWRfcHJla2'
|
||||||
'9zaWduZWRfcHJla2V5QhoKGF9zaWduZWRfcHJla2V5X3NpZ25hdHVyZUITChFfc2lnbmVkX3By'
|
'V5X2lkQhIKEF9yZWdpc3RyYXRpb25faWQaWQoLVXBsb2FkVG9rZW4SIQoMdXBsb2FkX3Rva2Vu'
|
||||||
'ZWtleV9pZEISChBfcmVnaXN0cmF0aW9uX2lkGlkKC1VwbG9hZFRva2VuEiEKDHVwbG9hZF90b2'
|
'GAEgASgMUgt1cGxvYWRUb2tlbhInCg9kb3dubG9hZF90b2tlbnMYAiADKAxSDmRvd25sb2FkVG'
|
||||||
'tlbhgBIAEoDFILdXBsb2FkVG9rZW4SJwoPZG93bmxvYWRfdG9rZW5zGAIgAygMUg5kb3dubG9h'
|
'9rZW5zGjkKDkRvd25sb2FkVG9rZW5zEicKD2Rvd25sb2FkX3Rva2VucxgBIAMoDFIOZG93bmxv'
|
||||||
'ZFRva2Vucxo5Cg5Eb3dubG9hZFRva2VucxInCg9kb3dubG9hZF90b2tlbnMYASADKAxSDmRvd2'
|
'YWRUb2tlbnMaRQoLUHJvb2ZPZldvcmsSFgoGcHJlZml4GAEgASgJUgZwcmVmaXgSHgoKZGlmZm'
|
||||||
'5sb2FkVG9rZW5zGkUKC1Byb29mT2ZXb3JrEhYKBnByZWZpeBgBIAEoCVIGcHJlZml4Eh4KCmRp'
|
'ljdWx0eRgCIAEoA1IKZGlmZmljdWx0eRrDBwoCT2sSFAoETm9uZRgBIAEoCEgAUgROb25lEhgK'
|
||||||
'ZmZpY3VsdHkYAiABKANSCmRpZmZpY3VsdHkawwcKAk9rEhQKBE5vbmUYASABKAhIAFIETm9uZR'
|
'BnVzZXJpZBgCIAEoA0gAUgZ1c2VyaWQSJgoNYXV0aGNoYWxsZW5nZRgDIAEoDEgAUg1hdXRoY2'
|
||||||
'IYCgZ1c2VyaWQYAiABKANIAFIGdXNlcmlkEiYKDWF1dGhjaGFsbGVuZ2UYAyABKAxIAFINYXV0'
|
'hhbGxlbmdlEkoKC3VwbG9hZHRva2VuGAQgASgLMiYuc2VydmVyX3RvX2NsaWVudC5SZXNwb25z'
|
||||||
'aGNoYWxsZW5nZRJKCgt1cGxvYWR0b2tlbhgEIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVzcG'
|
'ZS5VcGxvYWRUb2tlbkgAUgt1cGxvYWR0b2tlbhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl'
|
||||||
'9uc2UuVXBsb2FkVG9rZW5IAFILdXBsb2FkdG9rZW4SQQoIdXNlcmRhdGEYBSABKAsyIy5zZXJ2'
|
'90b19jbGllbnQuUmVzcG9uc2UuVXNlckRhdGFIAFIIdXNlcmRhdGESHgoJYXV0aHRva2VuGAYg'
|
||||||
'ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlVzZXJEYXRhSABSCHVzZXJkYXRhEh4KCWF1dGh0b2tlbh'
|
'ASgMSABSCWF1dGh0b2tlbhJBCghsb2NhdGlvbhgHIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUm'
|
||||||
'gGIAEoDEgAUglhdXRodG9rZW4SQQoIbG9jYXRpb24YByABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50'
|
'VzcG9uc2UuTG9jYXRpb25IAFIIbG9jYXRpb24SUAoNYXV0aGVudGljYXRlZBgIIAEoCzIoLnNl'
|
||||||
'LlJlc3BvbnNlLkxvY2F0aW9uSABSCGxvY2F0aW9uElAKDWF1dGhlbnRpY2F0ZWQYCCABKAsyKC'
|
'cnZlcl90b19jbGllbnQuUmVzcG9uc2UuQXV0aGVudGljYXRlZEgAUg1hdXRoZW50aWNhdGVkEj'
|
||||||
'5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkF1dGhlbnRpY2F0ZWRIAFINYXV0aGVudGljYXRl'
|
'gKBXBsYW5zGAkgASgLMiAuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QbGFuc0gAUgVwbGFu'
|
||||||
'ZBI4CgVwbGFucxgJIAEoCzIgLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuUGxhbnNIAFIFcG'
|
'cxJNCgxwbGFuYmFsbGFuY2UYCiABKAsyJy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlBsYW'
|
||||||
'xhbnMSTQoMcGxhbmJhbGxhbmNlGAogASgLMicuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5Q'
|
'5CYWxsYW5jZUgAUgxwbGFuYmFsbGFuY2USQQoIdm91Y2hlcnMYCyABKAsyIy5zZXJ2ZXJfdG9f'
|
||||||
'bGFuQmFsbGFuY2VIAFIMcGxhbmJhbGxhbmNlEkEKCHZvdWNoZXJzGAsgASgLMiMuc2VydmVyX3'
|
'Y2xpZW50LlJlc3BvbnNlLlZvdWNoZXJzSABSCHZvdWNoZXJzEl8KEmFkZGFjY291bnRzaW52aX'
|
||||||
'RvX2NsaWVudC5SZXNwb25zZS5Wb3VjaGVyc0gAUgh2b3VjaGVycxJfChJhZGRhY2NvdW50c2lu'
|
'RlcxgMIAEoCzItLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuQWRkQWNjb3VudHNJbnZpdGVz'
|
||||||
'dml0ZXMYDCABKAsyLS5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkFkZEFjY291bnRzSW52aX'
|
'SABSEmFkZGFjY291bnRzaW52aXRlcxJTCg5kb3dubG9hZHRva2VucxgNIAEoCzIpLnNlcnZlcl'
|
||||||
'Rlc0gAUhJhZGRhY2NvdW50c2ludml0ZXMSUwoOZG93bmxvYWR0b2tlbnMYDSABKAsyKS5zZXJ2'
|
'90b19jbGllbnQuUmVzcG9uc2UuRG93bmxvYWRUb2tlbnNIAFIOZG93bmxvYWR0b2tlbnMSTQoM'
|
||||||
'ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkRvd25sb2FkVG9rZW5zSABSDmRvd25sb2FkdG9rZW5zEk'
|
'c2lnbmVkcHJla2V5GA4gASgLMicuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5TaWduZWRQcm'
|
||||||
'0KDHNpZ25lZHByZWtleRgOIAEoCzInLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuU2lnbmVk'
|
'VLZXlIAFIMc2lnbmVkcHJla2V5EkoKC3Byb29mT2ZXb3JrGA8gASgLMiYuc2VydmVyX3RvX2Ns'
|
||||||
'UHJlS2V5SABSDHNpZ25lZHByZWtleRJKCgtwcm9vZk9mV29yaxgPIAEoCzImLnNlcnZlcl90b1'
|
'aWVudC5SZXNwb25zZS5Qcm9vZk9mV29ya0gAUgtwcm9vZk9mV29ya0IECgJPayKWAQoQVHJhbn'
|
||||||
'9jbGllbnQuUmVzcG9uc2UuUHJvb2ZPZldvcmtIAFILcHJvb2ZPZldvcmtCBAoCT2silgEKEFRy'
|
'NhY3Rpb25UeXBlcxIKCgZSZWZ1bmQQABITCg9Wb3VjaGVyUmVkZWVtZWQQARISCg5Wb3VjaGVy'
|
||||||
'YW5zYWN0aW9uVHlwZXMSCgoGUmVmdW5kEAASEwoPVm91Y2hlclJlZGVlbWVkEAESEgoOVm91Y2'
|
'Q3JlYXRlZBACEggKBENhc2gQAxIPCgtQbGFuVXBncmFkZRAEEgsKB1Vua25vd24QBRIUChBUaG'
|
||||||
'hlckNyZWF0ZWQQAhIICgRDYXNoEAMSDwoLUGxhblVwZ3JhZGUQBBILCgdVbmtub3duEAUSFAoQ'
|
'Fua3NGb3JUZXN0aW5nEAYSDwoLQXV0b1JlbmV3YWwQB0IKCghSZXNwb25zZQ==');
|
||||||
'VGhhbmtzRm9yVGVzdGluZxAGEg8KC0F1dG9SZW5ld2FsEAdCCgoIUmVzcG9uc2U=');
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:in_app_purchase/in_app_purchase.dart';
|
import 'package:in_app_purchase/in_app_purchase.dart';
|
||||||
|
|
@ -120,15 +121,36 @@ class PurchasesProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) async {
|
Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) async {
|
||||||
|
Log.info('verifying _verifyPurchase');
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
try {
|
||||||
|
var b64Data = purchaseDetails.verificationData.serverVerificationData
|
||||||
|
.split('.')[1];
|
||||||
|
|
||||||
|
final paddingNeeded = (4 - (b64Data.length % 4)) % 4;
|
||||||
|
b64Data += '=' * paddingNeeded;
|
||||||
|
|
||||||
|
final jsonData = base64Decode(b64Data);
|
||||||
|
final data = jsonDecode(utf8.decode(jsonData)) as Map<String, dynamic>;
|
||||||
|
final expiresDate = data['expiresDate'] as int;
|
||||||
|
final dt =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(expiresDate, isUtc: true);
|
||||||
|
if (dt.isBefore(DateTime.now())) {
|
||||||
|
Log.warn('ExpiresDate is in the past: $dt');
|
||||||
|
if (_userTriggeredBuyButton && Platform.isIOS) {
|
||||||
|
await launchUrl(
|
||||||
|
Uri.parse('https://apps.apple.com/account/subscriptions'),
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
Log.info(purchaseDetails.productID);
|
Log.info(purchaseDetails.productID);
|
||||||
Log.info(purchaseDetails.verificationData.serverVerificationData);
|
|
||||||
// if (Platform.isIOS) {
|
|
||||||
// final data = purchaseDetails.verificationData.serverVerificationData;
|
|
||||||
// printWrapped(data);
|
|
||||||
// final datas = data.split('.')[1];
|
|
||||||
// printWrapped(datas);
|
|
||||||
// }
|
|
||||||
Log.info(purchaseDetails.verificationData.source);
|
Log.info(purchaseDetails.verificationData.source);
|
||||||
}
|
}
|
||||||
final res = await apiService.ipaPurchase(
|
final res = await apiService.ipaPurchase(
|
||||||
|
|
@ -163,7 +185,9 @@ class PurchasesProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
||||||
Log.info(
|
Log.info(
|
||||||
'_handlePurchase: ${purchaseDetails.productID}, ${purchaseDetails.status}',
|
'_handlePurchase: ${purchaseDetails.productID}, ${purchaseDetails.status}',
|
||||||
);
|
);
|
||||||
if (purchaseDetails.status == PurchaseStatus.purchased) {
|
if (purchaseDetails.status == PurchaseStatus.purchased ||
|
||||||
|
(purchaseDetails.status == PurchaseStatus.restored &&
|
||||||
|
_userTriggeredBuyButton)) {
|
||||||
await _verifyPurchase(purchaseDetails);
|
await _verifyPurchase(purchaseDetails);
|
||||||
}
|
}
|
||||||
if (purchaseDetails.status == PurchaseStatus.restored &&
|
if (purchaseDetails.status == PurchaseStatus.restored &&
|
||||||
|
|
@ -178,7 +202,8 @@ class PurchasesProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
||||||
for (var i = 0; i < 100; i++) {
|
for (var i = 0; i < 100; i++) {
|
||||||
if (apiService.isAuthenticated) {
|
if (apiService.isAuthenticated) {
|
||||||
Log.info(
|
Log.info(
|
||||||
'current user does not have a sub: ${purchaseDetails.productID}');
|
'current user does not have a sub: ${purchaseDetails.productID}',
|
||||||
|
);
|
||||||
await _verifyPurchase(purchaseDetails);
|
await _verifyPurchase(purchaseDetails);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
|
@ -182,6 +183,7 @@ class ApiService {
|
||||||
|
|
||||||
Future<void> _onDone() async {
|
Future<void> _onDone() async {
|
||||||
Log.info('websocket closed without error');
|
Log.info('websocket closed without error');
|
||||||
|
_reconnectionDelay = 60 * 2; // the server closed the connection...
|
||||||
await onClosed();
|
await onClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +207,7 @@ class ApiService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<server.ServerToClient?> _waitForResponse(Int64 seq) async {
|
Future<server.ServerToClient?> _waitForResponse(Int64 seq) async {
|
||||||
final startTime = DateTime.now();
|
final startTime = clock.now();
|
||||||
|
|
||||||
const timeout = Duration(seconds: 60);
|
const timeout = Duration(seconds: 60);
|
||||||
|
|
||||||
|
|
@ -215,7 +217,7 @@ class ApiService {
|
||||||
messagesV0.remove(seq);
|
messagesV0.remove(seq);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
if (DateTime.now().difference(startTime) > timeout) {
|
if (clock.now().difference(startTime) > timeout) {
|
||||||
Log.warn('Timeout for message $seq');
|
Log.warn('Timeout for message $seq');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -593,20 +595,6 @@ class ApiService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Response_AddAccountsInvite>?> getAdditionalUserInvites() async {
|
|
||||||
final get = ApplicationData_GetAddAccountsInvites();
|
|
||||||
final appData = ApplicationData()..getAddaccountsInvites = get;
|
|
||||||
final req = createClientToServerFromApplicationData(appData);
|
|
||||||
final res = await sendRequestSync(req);
|
|
||||||
if (res.isSuccess) {
|
|
||||||
final ok = res.value as server.Response_Ok;
|
|
||||||
if (ok.hasAddaccountsinvites()) {
|
|
||||||
return ok.addaccountsinvites.invites;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Result> updatePlanOptions(bool autoRenewal) async {
|
Future<Result> updatePlanOptions(bool autoRenewal) async {
|
||||||
final get = ApplicationData_UpdatePlanOptions()..autoRenewal = autoRenewal;
|
final get = ApplicationData_UpdatePlanOptions()..autoRenewal = autoRenewal;
|
||||||
final appData = ApplicationData()..updatePlanOptions = get;
|
final appData = ApplicationData()..updatePlanOptions = get;
|
||||||
|
|
@ -621,6 +609,13 @@ class ApiService {
|
||||||
return sendRequestSync(req, contactId: userId.toInt());
|
return sendRequestSync(req, contactId: userId.toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Result> addAdditionalUser(Int64 userId) async {
|
||||||
|
final get = ApplicationData_AddAdditionalUser()..userId = userId;
|
||||||
|
final appData = ApplicationData()..addAdditionalUser = get;
|
||||||
|
final req = createClientToServerFromApplicationData(appData);
|
||||||
|
return sendRequestSync(req, contactId: userId.toInt());
|
||||||
|
}
|
||||||
|
|
||||||
Future<Result> buyVoucher(int valueInCents) async {
|
Future<Result> buyVoucher(int valueInCents) async {
|
||||||
final get = ApplicationData_CreateVoucher()..valueCents = valueInCents;
|
final get = ApplicationData_CreateVoucher()..valueCents = valueInCents;
|
||||||
final appData = ApplicationData()..createVoucher = get;
|
final appData = ApplicationData()..createVoucher = get;
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ Future<void> handleContactUpdate(
|
||||||
switch (contactUpdate.type) {
|
switch (contactUpdate.type) {
|
||||||
case EncryptedContent_ContactUpdate_Type.REQUEST:
|
case EncryptedContent_ContactUpdate_Type.REQUEST:
|
||||||
Log.info('Got a contact update request from $fromUserId');
|
Log.info('Got a contact update request from $fromUserId');
|
||||||
await notifyContactsAboutProfileChange(onlyToContact: fromUserId);
|
await sendContactMyProfileData(fromUserId);
|
||||||
|
|
||||||
case EncryptedContent_ContactUpdate_Type.UPDATE:
|
case EncryptedContent_ContactUpdate_Type.UPDATE:
|
||||||
Log.info('Got a contact update $fromUserId');
|
Log.info('Got a contact update $fromUserId');
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/services/api/mediafiles/download.service.dart';
|
import 'package:twonly/src/services/api/mediafiles/download.service.dart';
|
||||||
import 'package:twonly/src/services/api/utils.dart';
|
import 'package:twonly/src/services/api/utils.dart';
|
||||||
|
import 'package:twonly/src/services/flame.service.dart';
|
||||||
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
|
|
@ -114,7 +115,7 @@ Future<void> handleMedia(
|
||||||
await twonlyDB.groupsDao
|
await twonlyDB.groupsDao
|
||||||
.increaseLastMessageExchange(groupId, fromTimestamp(media.timestamp));
|
.increaseLastMessageExchange(groupId, fromTimestamp(media.timestamp));
|
||||||
Log.info('Inserted a new media message with ID: ${message.messageId}');
|
Log.info('Inserted a new media message with ID: ${message.messageId}');
|
||||||
await twonlyDB.groupsDao.incFlameCounter(
|
await incFlameCounter(
|
||||||
message.groupId,
|
message.groupId,
|
||||||
true,
|
true,
|
||||||
fromTimestamp(media.timestamp),
|
fromTimestamp(media.timestamp),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
import 'package:twonly/src/services/notifications/pushkeys.notifications.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
||||||
DateTime lastPushKeyRequest = DateTime.now().subtract(const Duration(hours: 1));
|
DateTime lastPushKeyRequest = clock.now().subtract(const Duration(hours: 1));
|
||||||
|
|
||||||
Future<void> handlePushKey(
|
Future<void> handlePushKey(
|
||||||
int contactId,
|
int contactId,
|
||||||
|
|
@ -14,8 +15,8 @@ Future<void> handlePushKey(
|
||||||
case EncryptedContent_PushKeys_Type.REQUEST:
|
case EncryptedContent_PushKeys_Type.REQUEST:
|
||||||
Log.info('Got a pushkey request from $contactId');
|
Log.info('Got a pushkey request from $contactId');
|
||||||
if (lastPushKeyRequest
|
if (lastPushKeyRequest
|
||||||
.isBefore(DateTime.now().subtract(const Duration(seconds: 60)))) {
|
.isBefore(clock.now().subtract(const Duration(seconds: 60)))) {
|
||||||
lastPushKeyRequest = DateTime.now();
|
lastPushKeyRequest = clock.now();
|
||||||
unawaited(setupNotificationWithUsers(forceContact: contactId));
|
unawaited(setupNotificationWithUsers(forceContact: contactId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
|
@ -17,7 +18,6 @@ Future<void> handleReaction(
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!reaction.remove) {
|
if (!reaction.remove) {
|
||||||
await twonlyDB.groupsDao
|
await twonlyDB.groupsDao.increaseLastMessageExchange(groupId, clock.now());
|
||||||
.increaseLastMessageExchange(groupId, DateTime.now());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
|
|
@ -26,7 +27,7 @@ Future<void> handleTextMessage(
|
||||||
textMessage.hasQuoteMessageId() ? textMessage.quoteMessageId : null,
|
textMessage.hasQuoteMessageId() ? textMessage.quoteMessageId : null,
|
||||||
),
|
),
|
||||||
createdAt: Value(fromTimestamp(textMessage.timestamp)),
|
createdAt: Value(fromTimestamp(textMessage.timestamp)),
|
||||||
ackByServer: Value(DateTime.now()),
|
ackByServer: Value(clock.now()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
await twonlyDB.groupsDao.increaseLastMessageExchange(
|
await twonlyDB.groupsDao.increaseLastMessageExchange(
|
||||||
|
|
|
||||||
|
|
@ -57,28 +57,18 @@ Future<bool> isAllowedToDownload(MediaType type) async {
|
||||||
if (options[ConnectivityResult.mobile.name]!
|
if (options[ConnectivityResult.mobile.name]!
|
||||||
.contains(DownloadMediaTypes.video.name)) {
|
.contains(DownloadMediaTypes.video.name)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (type == MediaType.audio) {
|
|
||||||
if (options[ConnectivityResult.mobile.name]!
|
|
||||||
.contains(DownloadMediaTypes.audio.name)) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} else if (options[ConnectivityResult.mobile.name]!
|
} else if (options[ConnectivityResult.mobile.name]!
|
||||||
.contains(DownloadMediaTypes.image.name)) {
|
.contains(DownloadMediaTypes.image.name)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (connectivityResult.contains(ConnectivityResult.wifi)) {
|
if (connectivityResult.contains(ConnectivityResult.wifi)) {
|
||||||
if (type == MediaType.video) {
|
if (type == MediaType.video) {
|
||||||
if (options[ConnectivityResult.wifi.name]!
|
if (options[ConnectivityResult.wifi.name]!
|
||||||
.contains(DownloadMediaTypes.video.name)) {
|
.contains(DownloadMediaTypes.video.name)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (type == MediaType.audio) {
|
|
||||||
if (options[ConnectivityResult.wifi.name]!
|
|
||||||
.contains(DownloadMediaTypes.audio.name)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (options[ConnectivityResult.wifi.name]!
|
} else if (options[ConnectivityResult.wifi.name]!
|
||||||
.contains(DownloadMediaTypes.image.name)) {
|
.contains(DownloadMediaTypes.image.name)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -224,13 +214,9 @@ Future<void> downloadFileFast(
|
||||||
|
|
||||||
Future<void> requestMediaReupload(String mediaId) async {
|
Future<void> requestMediaReupload(String mediaId) async {
|
||||||
final messages = await twonlyDB.messagesDao.getMessagesByMediaId(mediaId);
|
final messages = await twonlyDB.messagesDao.getMessagesByMediaId(mediaId);
|
||||||
if (messages.length != 1 || messages.first.senderId == null) {
|
|
||||||
Log.error(
|
|
||||||
'Media file has none or more than one sender. That is not possible',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (final message in messages) {
|
||||||
|
if (message.openedAt != null) continue;
|
||||||
await sendCipherText(
|
await sendCipherText(
|
||||||
messages.first.senderId!,
|
messages.first.senderId!,
|
||||||
EncryptedContent(
|
EncryptedContent(
|
||||||
|
|
@ -240,7 +226,6 @@ Future<void> requestMediaReupload(String mediaId) async {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
await twonlyDB.mediaFilesDao.updateMedia(
|
await twonlyDB.mediaFilesDao.updateMedia(
|
||||||
mediaId,
|
mediaId,
|
||||||
const MediaFilesCompanion(
|
const MediaFilesCompanion(
|
||||||
|
|
@ -248,6 +233,7 @@ Future<void> requestMediaReupload(String mediaId) async {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> handleEncryptedFile(String mediaId) async {
|
Future<void> handleEncryptedFile(String mediaId) async {
|
||||||
final mediaService = await MediaFileService.fromMediaId(mediaId);
|
final mediaService = await MediaFileService.fromMediaId(mediaId);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:background_downloader/background_downloader.dart';
|
import 'package:background_downloader/background_downloader.dart';
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart' show Value;
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
|
@ -92,7 +93,7 @@ Future<void> handleUploadStatusUpdate(TaskStatusUpdate update) async {
|
||||||
await twonlyDB.messagesDao.handleMessageAckByServer(
|
await twonlyDB.messagesDao.handleMessageAckByServer(
|
||||||
contact.contactId,
|
contact.contactId,
|
||||||
message.messageId,
|
message.messageId,
|
||||||
DateTime.now(),
|
clock.now(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:background_downloader/background_downloader.dart';
|
import 'package:background_downloader/background_downloader.dart';
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:cryptography_flutter_plus/cryptography_flutter_plus.dart';
|
import 'package:cryptography_flutter_plus/cryptography_flutter_plus.dart';
|
||||||
import 'package:cryptography_plus/cryptography_plus.dart';
|
import 'package:cryptography_plus/cryptography_plus.dart';
|
||||||
|
|
@ -18,6 +19,7 @@ import 'package:twonly/src/model/protobuf/api/http/http_requests.pb.dart';
|
||||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/services/api/mediafiles/media_background.service.dart';
|
import 'package:twonly/src/services/api/mediafiles/media_background.service.dart';
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
|
import 'package:twonly/src/services/flame.service.dart';
|
||||||
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
||||||
import 'package:twonly/src/utils/log.dart';
|
import 'package:twonly/src/utils/log.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
@ -101,8 +103,7 @@ Future<void> insertMediaFileInMessagesTable(
|
||||||
type: const Value(MessageType.media),
|
type: const Value(MessageType.media),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
await twonlyDB.groupsDao
|
await twonlyDB.groupsDao.increaseLastMessageExchange(groupId, clock.now());
|
||||||
.increaseLastMessageExchange(groupId, DateTime.now());
|
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
// de-archive contact when sending a new message
|
// de-archive contact when sending a new message
|
||||||
await twonlyDB.groupsDao.updateGroup(
|
await twonlyDB.groupsDao.updateGroup(
|
||||||
|
|
@ -132,6 +133,15 @@ Future<void> startBackgroundMediaUpload(MediaFileService mediaService) async {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the user has enabled auto storing and the file
|
||||||
|
// was send with unlimited counter not in twonly-Mode then store the file
|
||||||
|
if (gUser.autoStoreAllSendUnlimitedMediaFiles &&
|
||||||
|
!mediaService.mediaFile.requiresAuthentication &&
|
||||||
|
!mediaService.storedPath.existsSync() &&
|
||||||
|
mediaService.mediaFile.displayLimitInMilliseconds == null) {
|
||||||
|
await mediaService.storeMediaFile();
|
||||||
|
}
|
||||||
|
|
||||||
if (!mediaService.encryptedPath.existsSync()) {
|
if (!mediaService.encryptedPath.existsSync()) {
|
||||||
await _encryptMediaFiles(mediaService);
|
await _encryptMediaFiles(mediaService);
|
||||||
if (!mediaService.encryptedPath.existsSync()) {
|
if (!mediaService.encryptedPath.existsSync()) {
|
||||||
|
|
@ -198,11 +208,7 @@ Future<void> _createUploadRequest(MediaFileService media) async {
|
||||||
await twonlyDB.groupsDao.getGroupNonLeftMembers(message.groupId);
|
await twonlyDB.groupsDao.getGroupNonLeftMembers(message.groupId);
|
||||||
|
|
||||||
if (media.mediaFile.reuploadRequestedBy == null) {
|
if (media.mediaFile.reuploadRequestedBy == null) {
|
||||||
await twonlyDB.groupsDao.incFlameCounter(
|
await incFlameCounter(message.groupId, false, message.createdAt);
|
||||||
message.groupId,
|
|
||||||
false,
|
|
||||||
message.createdAt,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final groupMember in groupMembers) {
|
for (final groupMember in groupMembers) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart';
|
||||||
|
|
@ -21,7 +22,7 @@ final lockRetransmission = Mutex();
|
||||||
|
|
||||||
Future<void> tryTransmitMessages() async {
|
Future<void> tryTransmitMessages() async {
|
||||||
return lockRetransmission.protect(() async {
|
return lockRetransmission.protect(() async {
|
||||||
final receipts = await twonlyDB.receiptsDao.getReceiptsNotAckByServer();
|
final receipts = await twonlyDB.receiptsDao.getReceiptsForRetransmission();
|
||||||
|
|
||||||
if (receipts.isEmpty) return;
|
if (receipts.isEmpty) return;
|
||||||
|
|
||||||
|
|
@ -50,8 +51,10 @@ Future<(Uint8List, Uint8List?)?> tryToSendCompleteMessage({
|
||||||
}
|
}
|
||||||
receiptId = receipt.receiptId;
|
receiptId = receipt.receiptId;
|
||||||
|
|
||||||
if (!onlyReturnEncryptedData && receipt.ackByServerAt != null) {
|
if (!onlyReturnEncryptedData &&
|
||||||
Log.error('message already uploaded!');
|
receipt.ackByServerAt != null &&
|
||||||
|
receipt.markForRetry == null) {
|
||||||
|
Log.error('Message already uploaded and mark for retry is not set!');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +132,7 @@ Future<(Uint8List, Uint8List?)?> tryToSendCompleteMessage({
|
||||||
await twonlyDB.messagesDao.handleMessageAckByServer(
|
await twonlyDB.messagesDao.handleMessageAckByServer(
|
||||||
receipt.contactId,
|
receipt.contactId,
|
||||||
receipt.messageId!,
|
receipt.messageId!,
|
||||||
DateTime.now(),
|
clock.now(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!receipt.contactWillSendsReceipt) {
|
if (!receipt.contactWillSendsReceipt) {
|
||||||
|
|
@ -138,9 +141,10 @@ Future<(Uint8List, Uint8List?)?> tryToSendCompleteMessage({
|
||||||
await twonlyDB.receiptsDao.updateReceipt(
|
await twonlyDB.receiptsDao.updateReceipt(
|
||||||
receiptId,
|
receiptId,
|
||||||
ReceiptsCompanion(
|
ReceiptsCompanion(
|
||||||
ackByServerAt: Value(DateTime.now()),
|
ackByServerAt: Value(clock.now()),
|
||||||
retryCount: Value(receipt.retryCount + 1),
|
retryCount: Value(receipt.retryCount + 1),
|
||||||
lastRetry: Value(DateTime.now()),
|
lastRetry: Value(clock.now()),
|
||||||
|
markForRetry: const Value(null),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +211,7 @@ Future<void> sendCipherTextToGroup(
|
||||||
}) async {
|
}) async {
|
||||||
final groupMembers = await twonlyDB.groupsDao.getGroupNonLeftMembers(groupId);
|
final groupMembers = await twonlyDB.groupsDao.getGroupNonLeftMembers(groupId);
|
||||||
|
|
||||||
await twonlyDB.groupsDao.increaseLastMessageExchange(groupId, DateTime.now());
|
await twonlyDB.groupsDao.increaseLastMessageExchange(groupId, clock.now());
|
||||||
|
|
||||||
encryptedContent.groupId = groupId;
|
encryptedContent.groupId = groupId;
|
||||||
|
|
||||||
|
|
@ -239,7 +243,7 @@ Future<(Uint8List, Uint8List?)?> sendCipherText(
|
||||||
contactId: Value(contactId),
|
contactId: Value(contactId),
|
||||||
message: Value(response.writeToBuffer()),
|
message: Value(response.writeToBuffer()),
|
||||||
messageId: Value(messageId),
|
messageId: Value(messageId),
|
||||||
ackByServerAt: Value(onlyReturnEncryptedData ? DateTime.now() : null),
|
ackByServerAt: Value(onlyReturnEncryptedData ? clock.now() : null),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -265,7 +269,7 @@ Future<void> notifyContactAboutOpeningMessage(
|
||||||
}
|
}
|
||||||
Log.info('Opened messages: $messageOtherIds');
|
Log.info('Opened messages: $messageOtherIds');
|
||||||
|
|
||||||
final actionAt = DateTime.now();
|
final actionAt = clock.now();
|
||||||
|
|
||||||
await sendCipherText(
|
await sendCipherText(
|
||||||
contactId,
|
contactId,
|
||||||
|
|
@ -289,26 +293,18 @@ Future<void> notifyContactAboutOpeningMessage(
|
||||||
await updateLastMessageId(contactId, biggestMessageId);
|
await updateLastMessageId(contactId, biggestMessageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> notifyContactsAboutProfileChange({int? onlyToContact}) async {
|
Future<void> sendContactMyProfileData(int contactId) async {
|
||||||
if (gUser.avatarSvg == null) return;
|
List<int>? avatarSvgCompressed;
|
||||||
|
if (gUser.avatarSvg != null) {
|
||||||
|
avatarSvgCompressed = gzip.encode(utf8.encode(gUser.avatarSvg!));
|
||||||
|
}
|
||||||
final encryptedContent = pb.EncryptedContent(
|
final encryptedContent = pb.EncryptedContent(
|
||||||
contactUpdate: pb.EncryptedContent_ContactUpdate(
|
contactUpdate: pb.EncryptedContent_ContactUpdate(
|
||||||
type: pb.EncryptedContent_ContactUpdate_Type.UPDATE,
|
type: pb.EncryptedContent_ContactUpdate_Type.UPDATE,
|
||||||
avatarSvgCompressed: gzip.encode(utf8.encode(gUser.avatarSvg!)),
|
avatarSvgCompressed: avatarSvgCompressed,
|
||||||
displayName: gUser.displayName,
|
displayName: gUser.displayName,
|
||||||
username: gUser.username,
|
username: gUser.username,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
await sendCipherText(contactId, encryptedContent);
|
||||||
if (onlyToContact != null) {
|
|
||||||
await sendCipherText(onlyToContact, encryptedContent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final contacts = await twonlyDB.contactsDao.getAllNotBlockedContacts();
|
|
||||||
|
|
||||||
for (final contact in contacts) {
|
|
||||||
await sendCipherText(contact.userId, encryptedContent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:hashlib/random.dart';
|
import 'package:hashlib/random.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
|
|
@ -40,7 +41,11 @@ Future<void> handleServerMessage(server.ServerToClient msg) async {
|
||||||
await handleClient2ClientMessage(msg.v0.newMessage);
|
await handleClient2ClientMessage(msg.v0.newMessage);
|
||||||
} else if (msg.v0.hasNewMessages()) {
|
} else if (msg.v0.hasNewMessages()) {
|
||||||
for (final newMessage in msg.v0.newMessages.newMessages) {
|
for (final newMessage in msg.v0.newMessages.newMessages) {
|
||||||
|
try {
|
||||||
await handleClient2ClientMessage(newMessage);
|
await handleClient2ClientMessage(newMessage);
|
||||||
|
} catch (e) {
|
||||||
|
Log.error(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.error('Unknown server message: $msg');
|
Log.error('Unknown server message: $msg');
|
||||||
|
|
@ -56,7 +61,7 @@ Future<void> handleServerMessage(server.ServerToClient msg) async {
|
||||||
await apiService.sendResponse(ClientToServer()..v0 = v0);
|
await apiService.sendResponse(ClientToServer()..v0 = v0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime lastPushKeyRequest = DateTime.now().subtract(const Duration(hours: 1));
|
DateTime lastPushKeyRequest = clock.now().subtract(const Duration(hours: 1));
|
||||||
|
|
||||||
Mutex protectReceiptCheck = Mutex();
|
Mutex protectReceiptCheck = Mutex();
|
||||||
|
|
||||||
|
|
@ -185,6 +190,15 @@ Future<PlaintextContent?> handleEncryptedMessage(
|
||||||
..type = decryptionErrorType!);
|
..type = decryptionErrorType!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We got a valid message fromUserId, so mark all messages which where
|
||||||
|
// send to the user but not yet ACK for retransmission. All marked messages
|
||||||
|
// will be either transmitted again after a new server connection (minimum 20 seconds).
|
||||||
|
// In case the server sends the ACK before they will be deleted.
|
||||||
|
// This ensures that 1. all messages will be received by the other person and
|
||||||
|
// that they will be retransmitted in case the server deleted them as they
|
||||||
|
// where not downloaded within the 40 days
|
||||||
|
await twonlyDB.receiptsDao.markMessagesForRetry(fromUserId);
|
||||||
|
|
||||||
final senderProfileCounter = await checkForProfileUpdate(fromUserId, content);
|
final senderProfileCounter = await checkForProfileUpdate(fromUserId, content);
|
||||||
|
|
||||||
if (content.hasContactRequest()) {
|
if (content.hasContactRequest()) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/database/daos/groups.dao.dart';
|
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
|
|
@ -32,10 +32,10 @@ Future<void> syncFlameCounters({String? forceForGroup}) async {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final flameCounter = getFlameCounterFromGroup(group) - 1;
|
final flameCounter = getFlameCounterFromGroup(group);
|
||||||
|
|
||||||
// only sync when flame counter is higher than three days or when they are bestFriends
|
// only sync when flame counter is higher three or when they are bestFriends
|
||||||
if (flameCounter < 1 && bestFriend.groupId != group.groupId) continue;
|
if (flameCounter <= 2 && bestFriend.groupId != group.groupId) continue;
|
||||||
|
|
||||||
final groupMembers =
|
final groupMembers =
|
||||||
await twonlyDB.groupsDao.getGroupNonLeftMembers(group.groupId);
|
await twonlyDB.groupsDao.getGroupNonLeftMembers(group.groupId);
|
||||||
|
|
@ -59,8 +59,125 @@ Future<void> syncFlameCounters({String? forceForGroup}) async {
|
||||||
await twonlyDB.groupsDao.updateGroup(
|
await twonlyDB.groupsDao.updateGroup(
|
||||||
group.groupId,
|
group.groupId,
|
||||||
GroupsCompanion(
|
GroupsCompanion(
|
||||||
lastFlameSync: Value(DateTime.now()),
|
lastFlameSync: Value(clock.now()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getFlameCounterFromGroup(Group? group) {
|
||||||
|
if (group == null) return 0;
|
||||||
|
if (group.lastMessageSend == null ||
|
||||||
|
group.lastMessageReceived == null ||
|
||||||
|
group.lastFlameCounterChange == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
final now = clock.now();
|
||||||
|
final startOfToday = DateTime(now.year, now.month, now.day);
|
||||||
|
final twoDaysAgo = startOfToday.subtract(const Duration(days: 2));
|
||||||
|
final oneDayAgo = startOfToday.subtract(const Duration(days: 1));
|
||||||
|
if (group.lastMessageSend!.isAfter(twoDaysAgo) &&
|
||||||
|
group.lastMessageReceived!.isAfter(twoDaysAgo) ||
|
||||||
|
group.lastFlameCounterChange!.isAfter(oneDayAgo)) {
|
||||||
|
return group.flameCounter;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> incFlameCounter(
|
||||||
|
String groupId,
|
||||||
|
bool received,
|
||||||
|
DateTime timestamp,
|
||||||
|
) async {
|
||||||
|
final group = await twonlyDB.groupsDao.getGroup(groupId);
|
||||||
|
if (group == null) return;
|
||||||
|
|
||||||
|
final totalMediaCounter = group.totalMediaCounter + 1;
|
||||||
|
var flameCounter = group.flameCounter;
|
||||||
|
var maxFlameCounter = group.maxFlameCounter;
|
||||||
|
var maxFlameCounterFrom = group.maxFlameCounterFrom;
|
||||||
|
|
||||||
|
if (group.lastMessageReceived != null && group.lastMessageSend != null) {
|
||||||
|
final now = clock.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();
|
||||||
|
|
||||||
|
final now = clock.now();
|
||||||
|
final startOfToday = DateTime(now.year, now.month, now.day);
|
||||||
|
|
||||||
|
if (group.lastFlameCounterChange == null ||
|
||||||
|
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;
|
||||||
|
if (group.lastFlameCounterChange == null ||
|
||||||
|
group.lastFlameCounterChange!.isBefore(timestamp)) {
|
||||||
|
// only update if the timestamp is newer
|
||||||
|
lastFlameCounterChange = Value(timestamp);
|
||||||
|
}
|
||||||
|
// Overwrite max flame counter either the current is bigger or the the max flame counter is older then 4 days
|
||||||
|
if (flameCounter >= maxFlameCounter ||
|
||||||
|
maxFlameCounterFrom == null ||
|
||||||
|
maxFlameCounterFrom
|
||||||
|
.isBefore(clock.now().subtract(const Duration(days: 5)))) {
|
||||||
|
maxFlameCounter = flameCounter;
|
||||||
|
maxFlameCounterFrom = clock.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (received) {
|
||||||
|
if (group.lastMessageReceived == null ||
|
||||||
|
group.lastMessageReceived!.isBefore(timestamp)) {
|
||||||
|
lastMessageReceived = Value(timestamp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (group.lastMessageSend == null ||
|
||||||
|
group.lastMessageSend!.isBefore(timestamp)) {
|
||||||
|
lastMessageSend = Value(timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await twonlyDB.groupsDao.updateGroup(
|
||||||
|
groupId,
|
||||||
|
GroupsCompanion(
|
||||||
|
totalMediaCounter: Value(totalMediaCounter),
|
||||||
|
lastFlameCounterChange: lastFlameCounterChange,
|
||||||
|
lastMessageReceived: lastMessageReceived,
|
||||||
|
lastMessageSend: lastMessageSend,
|
||||||
|
flameCounter: Value(flameCounter),
|
||||||
|
maxFlameCounter: Value(maxFlameCounter),
|
||||||
|
maxFlameCounterFrom: Value(maxFlameCounterFrom),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isItPossibleToRestoreFlames(Group group) {
|
||||||
|
final flameCounter = getFlameCounterFromGroup(group);
|
||||||
|
return group.maxFlameCounter > 2 &&
|
||||||
|
flameCounter < group.maxFlameCounter &&
|
||||||
|
group.maxFlameCounterFrom!
|
||||||
|
.isAfter(clock.now().subtract(const Duration(days: 5)));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'package:clock/clock.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:cryptography_flutter_plus/cryptography_flutter_plus.dart';
|
import 'package:cryptography_flutter_plus/cryptography_flutter_plus.dart';
|
||||||
import 'package:cryptography_plus/cryptography_plus.dart';
|
import 'package:cryptography_plus/cryptography_plus.dart';
|
||||||
|
|
@ -158,7 +159,7 @@ Future<void> fetchMissingGroupPublicKey() async {
|
||||||
if (member.lastMessage == null) continue;
|
if (member.lastMessage == null) continue;
|
||||||
// only request if the users has send a message in the last two days.
|
// only request if the users has send a message in the last two days.
|
||||||
if (member.lastMessage!
|
if (member.lastMessage!
|
||||||
.isAfter(DateTime.now().subtract(const Duration(days: 2)))) {
|
.isAfter(clock.now().subtract(const Duration(days: 2)))) {
|
||||||
await sendCipherText(
|
await sendCipherText(
|
||||||
member.contactId,
|
member.contactId,
|
||||||
EncryptedContent(
|
EncryptedContent(
|
||||||
|
|
|
||||||
180
lib/src/services/intent/links.intent.dart
Normal file
180
lib/src/services/intent/links.intent.dart
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
||||||
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/api/mediafiles/upload.service.dart';
|
||||||
|
import 'package:twonly/src/services/signal/session.signal.dart';
|
||||||
|
import 'package:twonly/src/utils/log.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/views/camera/share_image_editor_view.dart';
|
||||||
|
import 'package:twonly/src/views/chats/add_new_user.view.dart';
|
||||||
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
|
import 'package:twonly/src/views/contact/contact.view.dart';
|
||||||
|
import 'package:twonly/src/views/public_profile.view.dart';
|
||||||
|
|
||||||
|
Future<void> handleIntentUrl(BuildContext context, Uri uri) async {
|
||||||
|
if (!uri.scheme.startsWith('http')) return;
|
||||||
|
if (uri.host != 'me.twonly.eu') return;
|
||||||
|
if (uri.hasEmptyPath) return;
|
||||||
|
|
||||||
|
final publicKey = uri.hasFragment ? uri.fragment : null;
|
||||||
|
final userPaths = uri.path.split('/');
|
||||||
|
if (userPaths.length != 2) return;
|
||||||
|
final username = userPaths[1];
|
||||||
|
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
if (username == gUser.username) {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return const PublicProfileView();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info(
|
||||||
|
'Opened via deep link!: username = $username public_key = ${uri.fragment}',
|
||||||
|
);
|
||||||
|
final contacts = await twonlyDB.contactsDao.getContactsByUsername(username);
|
||||||
|
if (contacts.isEmpty) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
Uint8List? publicKeyBytes;
|
||||||
|
if (publicKey != null) {
|
||||||
|
publicKeyBytes = base64Url.decode(publicKey);
|
||||||
|
}
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return AddNewUserView(
|
||||||
|
username: username,
|
||||||
|
publicKey: publicKeyBytes,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (publicKey != null) {
|
||||||
|
try {
|
||||||
|
final contact = contacts.first;
|
||||||
|
final storedPublicKey = await getPublicKeyFromContact(contact.userId);
|
||||||
|
final receivedPublicKey = base64Url.decode(publicKey);
|
||||||
|
if (storedPublicKey == null ||
|
||||||
|
receivedPublicKey.isEmpty ||
|
||||||
|
!context.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (storedPublicKey.equals(receivedPublicKey)) {
|
||||||
|
if (!contact.verified) {
|
||||||
|
final markAsVerified = await showAlertDialog(
|
||||||
|
context,
|
||||||
|
context.lang.linkFromUsername(contact.username),
|
||||||
|
context.lang.linkFromUsernameLong,
|
||||||
|
customOk: context.lang.gotLinkFromFriend,
|
||||||
|
);
|
||||||
|
if (markAsVerified) {
|
||||||
|
await twonlyDB.contactsDao.updateContact(
|
||||||
|
contact.userId,
|
||||||
|
const ContactsCompanion(
|
||||||
|
verified: Value(true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return ContactView(contact.userId);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await showAlertDialog(
|
||||||
|
context,
|
||||||
|
context.lang.couldNotVerifyUsername(contact.username),
|
||||||
|
context.lang.linkPubkeyDoesNotMatch,
|
||||||
|
customCancel: '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Log.warn(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleIntentMediaFile(
|
||||||
|
BuildContext context,
|
||||||
|
String filePath,
|
||||||
|
MediaType type,
|
||||||
|
) async {
|
||||||
|
final file = File(filePath);
|
||||||
|
if (!file.existsSync()) {
|
||||||
|
Log.error('The shared intent file does not exits.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final newMediaService = await initializeMediaUpload(
|
||||||
|
type,
|
||||||
|
gUser.defaultShowTime,
|
||||||
|
);
|
||||||
|
if (newMediaService == null) {
|
||||||
|
Log.error('Could not create new media file for intent shared file');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.copySync(newMediaService.originalPath.path);
|
||||||
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => ShareImageEditorView(
|
||||||
|
mediaFileService: newMediaService,
|
||||||
|
sharedFromGallery: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleIntentSharedFile(
|
||||||
|
BuildContext context,
|
||||||
|
List<SharedFile> files,
|
||||||
|
) async {
|
||||||
|
for (final file in files) {
|
||||||
|
if (file.value == null) {
|
||||||
|
Log.error(
|
||||||
|
'Got shared media, but value is empty: getMediaStream ${file.mimeType}',
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log.info('got file via intent ${file.type} ${file.value}');
|
||||||
|
|
||||||
|
switch (file.type) {
|
||||||
|
case SharedMediaType.URL:
|
||||||
|
// await handleIntentUrl(context, Uri.parse(file.value!));
|
||||||
|
case SharedMediaType.IMAGE:
|
||||||
|
var type = MediaType.image;
|
||||||
|
if (file.value!.endsWith('.gif')) {
|
||||||
|
type = MediaType.gif;
|
||||||
|
}
|
||||||
|
await handleIntentMediaFile(context, file.value!, type);
|
||||||
|
case SharedMediaType.VIDEO:
|
||||||
|
await handleIntentMediaFile(context, file.value!, MediaType.video);
|
||||||
|
// ignore: no_default_cases
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
break; // only handle one file...
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue