mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 10:38:41 +00:00
switch to google fcm fix #14
This commit is contained in:
parent
7a8e14c3be
commit
1b1da8c481
24 changed files with 558 additions and 65 deletions
25
.vscode/launch.json
vendored
25
.vscode/launch.json
vendored
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
|
||||
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
|
||||
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Connect-App",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
},
|
||||
{
|
||||
"name": "Connect-App (profile mode)",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "profile"
|
||||
},
|
||||
{
|
||||
"name": "Connect-App (release mode)",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "release"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"thounthends"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,10 +1,19 @@
|
|||
plugins {
|
||||
id "com.android.application"
|
||||
// START: FlutterFire Configuration
|
||||
id 'com.google.gms.google-services'
|
||||
// END: FlutterFire Configuration
|
||||
id "kotlin-android"
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.connect"
|
||||
// compileSdk = flutter.compileSdkVersion
|
||||
|
|
@ -33,13 +42,19 @@ android {
|
|||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||
storePassword keystoreProperties['storePassword']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.debug
|
||||
}
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
48
android/app/google-services.json
Normal file
48
android/app/google-services.json
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "650346093942",
|
||||
"project_id": "twonly-ff605",
|
||||
"storage_bucket": "twonly-ff605.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:650346093942:android:040816fb819b1bfb81ae57",
|
||||
"android_client_info": {
|
||||
"package_name": "eu.twonly"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA4d5ORP11WpuVgmoYtWmOcMzZYWLPVtBk"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:650346093942:android:706cb87c3131dabe81ae57",
|
||||
"android_client_info": {
|
||||
"package_name": "eu.twonly.testing"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA4d5ORP11WpuVgmoYtWmOcMzZYWLPVtBk"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
|
|
@ -19,6 +19,9 @@ pluginManagement {
|
|||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "8.3.2" apply false
|
||||
// START: FlutterFire Configuration
|
||||
id "com.google.gms.google-services" version "4.3.15" apply false
|
||||
// END: FlutterFire Configuration
|
||||
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
|
||||
}
|
||||
|
||||
|
|
|
|||
1
firebase.json
Normal file
1
firebase.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"flutter":{"platforms":{"android":{"default":{"projectId":"twonly-ff605","appId":"1:650346093942:android:706cb87c3131dabe81ae57","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"twonly-ff605","appId":"1:650346093942:ios:e80075ff3de823c581ae57","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"twonly-ff605","configurations":{"android":"1:650346093942:android:706cb87c3131dabe81ae57","ios":"1:650346093942:ios:e80075ff3de823c581ae57"}}}}}}
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
F3C66D726A2EB28484DF0B10 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
/* Begin PBXFileReference section */
|
||||
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>"; };
|
||||
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>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
|
|
@ -94,6 +96,7 @@
|
|||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
16FBC6F5B58E1C6646F5D447 /* GoogleService-Info.plist */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -216,6 +219,7 @@
|
|||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
F3C66D726A2EB28484DF0B10 /* GoogleService-Info.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
30
ios/Runner/GoogleService-Info.plist
Normal file
30
ios/Runner/GoogleService-Info.plist
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?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>API_KEY</key>
|
||||
<string>AIzaSyDr7MEoz2XvrYxU0kYvZVVjej53q0gANnE</string>
|
||||
<key>GCM_SENDER_ID</key>
|
||||
<string>650346093942</string>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>com.example.connect</string>
|
||||
<key>PROJECT_ID</key>
|
||||
<string>twonly-ff605</string>
|
||||
<key>STORAGE_BUCKET</key>
|
||||
<string>twonly-ff605.firebasestorage.app</string>
|
||||
<key>IS_ADS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_ANALYTICS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_APPINVITE_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_GCM_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_SIGNIN_ENABLED</key>
|
||||
<true></true>
|
||||
<key>GOOGLE_APP_ID</key>
|
||||
<string>1:650346093942:ios:e80075ff3de823c581ae57</string>
|
||||
</dict>
|
||||
</plist>
|
||||
68
lib/firebase_options.dart
Normal file
68
lib/firebase_options.dart
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
// File generated by FlutterFire CLI.
|
||||
// ignore_for_file: type=lint
|
||||
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
|
||||
import 'package:flutter/foundation.dart'
|
||||
show defaultTargetPlatform, kIsWeb, TargetPlatform;
|
||||
|
||||
/// Default [FirebaseOptions] for use with your Firebase apps.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// import 'firebase_options.dart';
|
||||
/// // ...
|
||||
/// await Firebase.initializeApp(
|
||||
/// options: DefaultFirebaseOptions.currentPlatform,
|
||||
/// );
|
||||
/// ```
|
||||
class DefaultFirebaseOptions {
|
||||
static FirebaseOptions get currentPlatform {
|
||||
if (kIsWeb) {
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for web - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
}
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return android;
|
||||
case TargetPlatform.iOS:
|
||||
return ios;
|
||||
case TargetPlatform.macOS:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for macos - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
case TargetPlatform.windows:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for windows - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
case TargetPlatform.linux:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for linux - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
default:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions are not supported for this platform.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static const FirebaseOptions android = FirebaseOptions(
|
||||
apiKey: 'AIzaSyA4d5ORP11WpuVgmoYtWmOcMzZYWLPVtBk',
|
||||
appId: '1:650346093942:android:706cb87c3131dabe81ae57',
|
||||
messagingSenderId: '650346093942',
|
||||
projectId: 'twonly-ff605',
|
||||
storageBucket: 'twonly-ff605.firebasestorage.app',
|
||||
);
|
||||
|
||||
static const FirebaseOptions ios = FirebaseOptions(
|
||||
apiKey: 'AIzaSyDr7MEoz2XvrYxU0kYvZVVjej53q0gANnE',
|
||||
appId: '1:650346093942:ios:e80075ff3de823c581ae57',
|
||||
messagingSenderId: '650346093942',
|
||||
projectId: 'twonly-ff605',
|
||||
storageBucket: 'twonly-ff605.firebasestorage.app',
|
||||
iosBundleId: 'com.example.connect',
|
||||
);
|
||||
}
|
||||
|
|
@ -12,7 +12,9 @@ import 'package:twonly/src/providers/messages_change_provider.dart';
|
|||
import 'package:twonly/src/providers/contacts_change_provider.dart';
|
||||
import 'package:twonly/src/providers/send_next_media_to.dart';
|
||||
import 'package:twonly/src/providers/settings_change_provider.dart';
|
||||
import 'package:twonly/src/services/fcm_service.dart';
|
||||
import 'package:twonly/src/services/notification_service.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'src/app.dart';
|
||||
|
||||
void main() async {
|
||||
|
|
@ -26,16 +28,16 @@ void main() async {
|
|||
|
||||
Logger.root.level = kReleaseMode ? Level.INFO : Level.ALL;
|
||||
Logger.root.onRecord.listen((record) {
|
||||
// if (kReleaseMode) {
|
||||
// writeLogToFile(record);
|
||||
// } else {
|
||||
print(
|
||||
'${record.level.name}: twonly:${record.loggerName}: ${record.message}');
|
||||
// }
|
||||
writeLogToFile(record);
|
||||
if (kDebugMode) {
|
||||
print(
|
||||
'${record.level.name}: twonly:${record.loggerName}: ${record.message}');
|
||||
}
|
||||
});
|
||||
|
||||
await setupPushNotification();
|
||||
await initMediaStorage();
|
||||
await initFCMService();
|
||||
|
||||
dbProvider = DbProvider();
|
||||
await dbProvider.ready;
|
||||
|
|
|
|||
|
|
@ -73,17 +73,17 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||
.updateLastMessageFor(userId, messageId);
|
||||
};
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_requestPermissions();
|
||||
_initService();
|
||||
});
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// _requestPermissions();
|
||||
// _initService();
|
||||
// });
|
||||
initAsync();
|
||||
}
|
||||
|
||||
Future initAsync() async {
|
||||
// make sure the front end service will be killed
|
||||
FlutterForegroundTask.sendDataToTask("");
|
||||
await FlutterForegroundTask.stopService();
|
||||
// FlutterForegroundTask.sendDataToTask("");
|
||||
// await FlutterForegroundTask.stopService();
|
||||
// connect async to the backend api
|
||||
apiProvider.connect();
|
||||
}
|
||||
|
|
@ -177,13 +177,15 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
|||
if (state == AppLifecycleState.resumed) {
|
||||
if (wasPaused) {
|
||||
globalIsAppInBackground = false;
|
||||
_stopService();
|
||||
apiProvider.connect();
|
||||
// _stopService();
|
||||
}
|
||||
} else if (state == AppLifecycleState.paused) {
|
||||
wasPaused = true;
|
||||
globalIsAppInBackground = true;
|
||||
apiProvider.close(() {
|
||||
_startService();
|
||||
// use this only when uploading an image
|
||||
// _startService();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
"settingsNotification": "Benachrichtigung",
|
||||
"settingsHelp": "Hilfe",
|
||||
"settingsHelpSupport": "Support-Center",
|
||||
"settingsHelpDiagnostics": "Diagnoseprotokoll",
|
||||
"settingsHelpVersion": "Version",
|
||||
"settingsHelpLicenses": "Lizenzen",
|
||||
"settingsHelpLegal": "Nutzungsbedingungen & Datenschutzrichtlinie",
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
"settingsPrivacyBlockUsersCount": "{len} contact(s)",
|
||||
"settingsNotification": "Notification",
|
||||
"settingsHelp": "Help",
|
||||
"settingsHelpDiagnostics": "Diagnostic protocol",
|
||||
"settingsHelpSupport": "Support Center",
|
||||
"settingsHelpVersion": "Version",
|
||||
"settingsHelpLicenses": "Licenses",
|
||||
|
|
|
|||
|
|
@ -641,6 +641,56 @@ class ApplicationData_GetUserByUsername extends $pb.GeneratedMessage {
|
|||
void clearUsername() => clearField(1);
|
||||
}
|
||||
|
||||
class ApplicationData_UpdateGoogleFcmToken extends $pb.GeneratedMessage {
|
||||
factory ApplicationData_UpdateGoogleFcmToken({
|
||||
$core.String? googleFcm,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (googleFcm != null) {
|
||||
$result.googleFcm = googleFcm;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
ApplicationData_UpdateGoogleFcmToken._() : super();
|
||||
factory ApplicationData_UpdateGoogleFcmToken.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory ApplicationData_UpdateGoogleFcmToken.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.UpdateGoogleFcmToken', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'googleFcm')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
ApplicationData_UpdateGoogleFcmToken clone() => ApplicationData_UpdateGoogleFcmToken()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
ApplicationData_UpdateGoogleFcmToken copyWith(void Function(ApplicationData_UpdateGoogleFcmToken) updates) => super.copyWith((message) => updates(message as ApplicationData_UpdateGoogleFcmToken)) as ApplicationData_UpdateGoogleFcmToken;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_UpdateGoogleFcmToken create() => ApplicationData_UpdateGoogleFcmToken._();
|
||||
ApplicationData_UpdateGoogleFcmToken createEmptyInstance() => create();
|
||||
static $pb.PbList<ApplicationData_UpdateGoogleFcmToken> createRepeated() => $pb.PbList<ApplicationData_UpdateGoogleFcmToken>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_UpdateGoogleFcmToken getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ApplicationData_UpdateGoogleFcmToken>(create);
|
||||
static ApplicationData_UpdateGoogleFcmToken? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get googleFcm => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set googleFcm($core.String v) { $_setString(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasGoogleFcm() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearGoogleFcm() => clearField(1);
|
||||
}
|
||||
|
||||
class ApplicationData_GetUserById extends $pb.GeneratedMessage {
|
||||
factory ApplicationData_GetUserById({
|
||||
$fixnum.Int64? userId,
|
||||
|
|
@ -923,6 +973,7 @@ enum ApplicationData_ApplicationData {
|
|||
uploaddata,
|
||||
getuserbyid,
|
||||
downloaddata,
|
||||
updategooglefcmtoken,
|
||||
notSet
|
||||
}
|
||||
|
||||
|
|
@ -935,6 +986,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
ApplicationData_UploadData? uploaddata,
|
||||
ApplicationData_GetUserById? getuserbyid,
|
||||
ApplicationData_DownloadData? downloaddata,
|
||||
ApplicationData_UpdateGoogleFcmToken? updategooglefcmtoken,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (textmessage != null) {
|
||||
|
|
@ -958,6 +1010,9 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
if (downloaddata != null) {
|
||||
$result.downloaddata = downloaddata;
|
||||
}
|
||||
if (updategooglefcmtoken != null) {
|
||||
$result.updategooglefcmtoken = updategooglefcmtoken;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
ApplicationData._() : super();
|
||||
|
|
@ -972,10 +1027,11 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
5 : ApplicationData_ApplicationData.uploaddata,
|
||||
6 : ApplicationData_ApplicationData.getuserbyid,
|
||||
7 : ApplicationData_ApplicationData.downloaddata,
|
||||
8 : ApplicationData_ApplicationData.updategooglefcmtoken,
|
||||
0 : ApplicationData_ApplicationData.notSet
|
||||
};
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
||||
..oo(0, [1, 2, 3, 4, 5, 6, 7])
|
||||
..oo(0, [1, 2, 3, 4, 5, 6, 7, 8])
|
||||
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textmessage', subBuilder: ApplicationData_TextMessage.create)
|
||||
..aOM<ApplicationData_GetUserByUsername>(2, _omitFieldNames ? '' : 'getuserbyusername', subBuilder: ApplicationData_GetUserByUsername.create)
|
||||
..aOM<ApplicationData_GetPrekeysByUserId>(3, _omitFieldNames ? '' : 'getprekeysbyuserid', subBuilder: ApplicationData_GetPrekeysByUserId.create)
|
||||
|
|
@ -983,6 +1039,7 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
..aOM<ApplicationData_UploadData>(5, _omitFieldNames ? '' : 'uploaddata', subBuilder: ApplicationData_UploadData.create)
|
||||
..aOM<ApplicationData_GetUserById>(6, _omitFieldNames ? '' : 'getuserbyid', subBuilder: ApplicationData_GetUserById.create)
|
||||
..aOM<ApplicationData_DownloadData>(7, _omitFieldNames ? '' : 'downloaddata', subBuilder: ApplicationData_DownloadData.create)
|
||||
..aOM<ApplicationData_UpdateGoogleFcmToken>(8, _omitFieldNames ? '' : 'updategooglefcmtoken', subBuilder: ApplicationData_UpdateGoogleFcmToken.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
|
|
@ -1086,6 +1143,17 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
void clearDownloaddata() => clearField(7);
|
||||
@$pb.TagNumber(7)
|
||||
ApplicationData_DownloadData ensureDownloaddata() => $_ensure(6);
|
||||
|
||||
@$pb.TagNumber(8)
|
||||
ApplicationData_UpdateGoogleFcmToken get updategooglefcmtoken => $_getN(7);
|
||||
@$pb.TagNumber(8)
|
||||
set updategooglefcmtoken(ApplicationData_UpdateGoogleFcmToken v) { setField(8, v); }
|
||||
@$pb.TagNumber(8)
|
||||
$core.bool hasUpdategooglefcmtoken() => $_has(7);
|
||||
@$pb.TagNumber(8)
|
||||
void clearUpdategooglefcmtoken() => clearField(8);
|
||||
@$pb.TagNumber(8)
|
||||
ApplicationData_UpdateGoogleFcmToken ensureUpdategooglefcmtoken() => $_ensure(7);
|
||||
}
|
||||
|
||||
class Response_PreKey extends $pb.GeneratedMessage {
|
||||
|
|
|
|||
|
|
@ -122,8 +122,9 @@ const ApplicationData$json = {
|
|||
{'1': 'uploaddata', '3': 5, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UploadData', '9': 0, '10': 'uploaddata'},
|
||||
{'1': 'getuserbyid', '3': 6, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetUserById', '9': 0, '10': 'getuserbyid'},
|
||||
{'1': 'downloaddata', '3': 7, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.DownloadData', '9': 0, '10': 'downloaddata'},
|
||||
{'1': 'updategooglefcmtoken', '3': 8, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UpdateGoogleFcmToken', '9': 0, '10': 'updategooglefcmtoken'},
|
||||
],
|
||||
'3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_GetUserById$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json, ApplicationData_DownloadData$json],
|
||||
'3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_UpdateGoogleFcmToken$json, ApplicationData_GetUserById$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json, ApplicationData_DownloadData$json],
|
||||
'8': [
|
||||
{'1': 'ApplicationData'},
|
||||
],
|
||||
|
|
@ -146,6 +147,14 @@ const ApplicationData_GetUserByUsername$json = {
|
|||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||
const ApplicationData_UpdateGoogleFcmToken$json = {
|
||||
'1': 'UpdateGoogleFcmToken',
|
||||
'2': [
|
||||
{'1': 'google_fcm', '3': 1, '4': 1, '5': 9, '10': 'googleFcm'},
|
||||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||
const ApplicationData_GetUserById$json = {
|
||||
'1': 'GetUserById',
|
||||
|
|
@ -199,14 +208,17 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
|||
'dGlvbkRhdGEuVXBsb2FkRGF0YUgAUgp1cGxvYWRkYXRhElEKC2dldHVzZXJieWlkGAYgASgLMi'
|
||||
'0uY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuR2V0VXNlckJ5SWRIAFILZ2V0dXNl'
|
||||
'cmJ5aWQSVAoMZG93bmxvYWRkYXRhGAcgASgLMi4uY2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdG'
|
||||
'lvbkRhdGEuRG93bmxvYWREYXRhSABSDGRvd25sb2FkZGF0YRo6CgtUZXh0TWVzc2FnZRIXCgd1'
|
||||
'c2VyX2lkGAEgASgDUgZ1c2VySWQSEgoEYm9keRgDIAEoDFIEYm9keRovChFHZXRVc2VyQnlVc2'
|
||||
'VybmFtZRIaCgh1c2VybmFtZRgBIAEoCVIIdXNlcm5hbWUaJgoLR2V0VXNlckJ5SWQSFwoHdXNl'
|
||||
'cl9pZBgBIAEoA1IGdXNlcklkGi0KEkdldFByZWtleXNCeVVzZXJJZBIXCgd1c2VyX2lkGAEgAS'
|
||||
'gDUgZ1c2VySWQaEAoOR2V0VXBsb2FkVG9rZW4aWwoKVXBsb2FkRGF0YRIhCgx1cGxvYWRfdG9r'
|
||||
'ZW4YASABKAxSC3VwbG9hZFRva2VuEhYKBm9mZnNldBgCIAEoDVIGb2Zmc2V0EhIKBGRhdGEYAy'
|
||||
'ABKAxSBGRhdGEaSQoMRG93bmxvYWREYXRhEiEKDHVwbG9hZF90b2tlbhgBIAEoDFILdXBsb2Fk'
|
||||
'VG9rZW4SFgoGb2Zmc2V0GAIgASgNUgZvZmZzZXRCEQoPQXBwbGljYXRpb25EYXRh');
|
||||
'lvbkRhdGEuRG93bmxvYWREYXRhSABSDGRvd25sb2FkZGF0YRJsChR1cGRhdGVnb29nbGVmY210'
|
||||
'b2tlbhgIIAEoCzI2LmNsaWVudF90b19zZXJ2ZXIuQXBwbGljYXRpb25EYXRhLlVwZGF0ZUdvb2'
|
||||
'dsZUZjbVRva2VuSABSFHVwZGF0ZWdvb2dsZWZjbXRva2VuGjoKC1RleHRNZXNzYWdlEhcKB3Vz'
|
||||
'ZXJfaWQYASABKANSBnVzZXJJZBISCgRib2R5GAMgASgMUgRib2R5Gi8KEUdldFVzZXJCeVVzZX'
|
||||
'JuYW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2VybmFtZRo1ChRVcGRhdGVHb29nbGVGY21Ub2tl'
|
||||
'bhIdCgpnb29nbGVfZmNtGAEgASgJUglnb29nbGVGY20aJgoLR2V0VXNlckJ5SWQSFwoHdXNlcl'
|
||||
'9pZBgBIAEoA1IGdXNlcklkGi0KEkdldFByZWtleXNCeVVzZXJJZBIXCgd1c2VyX2lkGAEgASgD'
|
||||
'UgZ1c2VySWQaEAoOR2V0VXBsb2FkVG9rZW4aWwoKVXBsb2FkRGF0YRIhCgx1cGxvYWRfdG9rZW'
|
||||
'4YASABKAxSC3VwbG9hZFRva2VuEhYKBm9mZnNldBgCIAEoDVIGb2Zmc2V0EhIKBGRhdGEYAyAB'
|
||||
'KAxSBGRhdGEaSQoMRG93bmxvYWREYXRhEiEKDHVwbG9hZF90b2tlbhgBIAEoDFILdXBsb2FkVG'
|
||||
'9rZW4SFgoGb2Zmc2V0GAIgASgNUgZvZmZzZXRCEQoPQXBwbGljYXRpb25EYXRh');
|
||||
|
||||
@$core.Deprecated('Use responseDescriptor instead')
|
||||
const Response$json = {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class ErrorCode extends $pb.ProtobufEnum {
|
|||
static const ErrorCode UploadLimitReached = ErrorCode._(1011, _omitEnumNames ? '' : 'UploadLimitReached');
|
||||
static const ErrorCode InvalidUpdateToken = ErrorCode._(1012, _omitEnumNames ? '' : 'InvalidUpdateToken');
|
||||
static const ErrorCode InvalidOffset = ErrorCode._(1013, _omitEnumNames ? '' : 'InvalidOffset');
|
||||
static const ErrorCode InvalidGoogleFcmToken = ErrorCode._(1014, _omitEnumNames ? '' : 'InvalidGoogleFcmToken');
|
||||
|
||||
static const $core.List<ErrorCode> values = <ErrorCode> [
|
||||
Unknown,
|
||||
|
|
@ -48,6 +49,7 @@ class ErrorCode extends $pb.ProtobufEnum {
|
|||
UploadLimitReached,
|
||||
InvalidUpdateToken,
|
||||
InvalidOffset,
|
||||
InvalidGoogleFcmToken,
|
||||
];
|
||||
|
||||
static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const ErrorCode$json = {
|
|||
{'1': 'UploadLimitReached', '2': 1011},
|
||||
{'1': 'InvalidUpdateToken', '2': 1012},
|
||||
{'1': 'InvalidOffset', '2': 1013},
|
||||
{'1': 'InvalidGoogleFcmToken', '2': 1014},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
@ -45,5 +46,5 @@ final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode(
|
|||
'bGljS2V5EO8HEiAKG1Nlc3Npb25BbHJlYWR5QXV0aGVudGljYXRlZBDwBxIcChdTZXNzaW9uTm'
|
||||
'90QXV0aGVudGljYXRlZBDxBxIaChVPbmx5T25lU2Vzc2lvbkFsbG93ZWQQ8gcSFwoSVXBsb2Fk'
|
||||
'TGltaXRSZWFjaGVkEPMHEhcKEkludmFsaWRVcGRhdGVUb2tlbhD0BxISCg1JbnZhbGlkT2Zmc2'
|
||||
'V0EPUH');
|
||||
'V0EPUHEhoKFUludmFsaWRHb29nbGVGY21Ub2tlbhD2Bw==');
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import 'package:twonly/src/proto/api/server_to_client.pb.dart' as server;
|
|||
import 'package:twonly/src/providers/api/api.dart';
|
||||
import 'package:twonly/src/providers/api/api_utils.dart';
|
||||
import 'package:twonly/src/providers/api/server_messages.dart';
|
||||
import 'package:twonly/src/services/fcm_service.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/utils/storage.dart';
|
||||
// ignore: library_prefixes
|
||||
|
|
@ -59,6 +60,11 @@ class ApiProvider {
|
|||
}
|
||||
}
|
||||
|
||||
// Function is called after the user is authenticated at the server
|
||||
Future onAuthenticated() async {
|
||||
initFCMAfterAuthenticated();
|
||||
}
|
||||
|
||||
Future onConnected() async {
|
||||
await authenticate();
|
||||
globalCallbackConnectionState(true);
|
||||
|
|
@ -212,7 +218,6 @@ class ApiProvider {
|
|||
}
|
||||
|
||||
Future authenticate() async {
|
||||
print("try authenticate $isAuthenticated");
|
||||
if (isAuthenticated) return;
|
||||
if (await SignalHelper.getSignalIdentity() == null) {
|
||||
return;
|
||||
|
|
@ -221,7 +226,6 @@ class ApiProvider {
|
|||
var handshake = Handshake()..getchallenge = Handshake_GetChallenge();
|
||||
var req = createClientToServerFromHandshake(handshake);
|
||||
|
||||
print("try authenticate send to server");
|
||||
final result = await _sendRequestV0(req, authenticated: false);
|
||||
if (result.isError) {
|
||||
log.shout("Error auth", result);
|
||||
|
|
@ -253,6 +257,7 @@ class ApiProvider {
|
|||
}
|
||||
|
||||
log.info("Authenticated!");
|
||||
onAuthenticated();
|
||||
isAuthenticated = true;
|
||||
}
|
||||
|
||||
|
|
@ -329,6 +334,13 @@ class ApiProvider {
|
|||
return await _sendRequestV0(req);
|
||||
}
|
||||
|
||||
Future<Result> updateFCMToken(String googleFcm) async {
|
||||
var get = ApplicationData_UpdateGoogleFcmToken()..googleFcm = googleFcm;
|
||||
var appData = ApplicationData()..updategooglefcmtoken = get;
|
||||
var req = createClientToServerFromApplicationData(appData);
|
||||
return await _sendRequestV0(req);
|
||||
}
|
||||
|
||||
Future<Result> sendTextMessage(Int64 target, Uint8List msg) async {
|
||||
var testMessage = ApplicationData_TextMessage()
|
||||
..userId = target
|
||||
|
|
|
|||
100
lib/src/services/fcm_service.dart
Normal file
100
lib/src/services/fcm_service.dart
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/app.dart';
|
||||
import 'package:twonly/src/providers/api_provider.dart';
|
||||
import 'package:twonly/src/providers/db_provider.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
|
||||
import '../../firebase_options.dart';
|
||||
|
||||
// see more here: https://firebase.google.com/docs/cloud-messaging/flutter/receive?hl=de
|
||||
|
||||
Future initFCMAfterAuthenticated() async {
|
||||
if (globalIsAppInBackground) return;
|
||||
|
||||
final storage = getSecureStorage();
|
||||
|
||||
String? storedToken = await storage.read(key: "google_fcm");
|
||||
|
||||
final fcmToken = await FirebaseMessaging.instance.getToken();
|
||||
if (fcmToken == null) {
|
||||
Logger("init_fcm_service").shout("Error getting fcmToken");
|
||||
return;
|
||||
}
|
||||
|
||||
if (storedToken == null || fcmToken != storedToken) {
|
||||
await apiProvider.updateFCMToken(fcmToken);
|
||||
await storage.write(key: "google_fcm", value: fcmToken);
|
||||
}
|
||||
|
||||
FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) async {
|
||||
await apiProvider.updateFCMToken(fcmToken);
|
||||
await storage.write(key: "google_fcm", value: fcmToken);
|
||||
}).onError((err) {
|
||||
// Logger("init_fcm_service").shout("Error getting fcmToken");
|
||||
});
|
||||
}
|
||||
|
||||
Future initFCMService() async {
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
);
|
||||
|
||||
// You may set the permission requests to "provisional" which allows the user to choose what type
|
||||
// of notifications they would like to receive once the user receives a notification.
|
||||
// final notificationSettings =
|
||||
await FirebaseMessaging.instance.requestPermission(provisional: true);
|
||||
|
||||
// For apple platforms, ensure the APNS token is available before making any FCM plugin API calls
|
||||
// final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
|
||||
// if (apnsToken != null) {
|
||||
// APNS token is available, make FCM plugin API requests...
|
||||
// }
|
||||
|
||||
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
||||
|
||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||
print('Got a message whilst in the foreground!');
|
||||
print('Message data: ${message.data}');
|
||||
|
||||
if (message.notification != null) {
|
||||
print('Message also contained a notification: ${message.notification}');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
// If you're going to use other Firebase services in the background, such as Firestore,
|
||||
// make sure you call `initializeApp` before using other Firebase services.
|
||||
|
||||
// Wenn Tasks länger als 30 Sekunden ausgeführt werden, wird der Prozess möglicherweise automatisch vom Gerät beendet.
|
||||
// -> offer backend via http?
|
||||
|
||||
print("Handling a background message: ${message.messageId}");
|
||||
|
||||
bool gotMessage = false;
|
||||
|
||||
globalCallBackOnMessageChange = (a, b) async {
|
||||
gotMessage = true;
|
||||
print("Got message can exit");
|
||||
};
|
||||
|
||||
dbProvider = DbProvider();
|
||||
await dbProvider.ready;
|
||||
apiProvider = ApiProvider();
|
||||
await apiProvider.connect();
|
||||
|
||||
final stopwatch = Stopwatch()..start();
|
||||
while (!gotMessage) {
|
||||
print("gotMessage: $gotMessage");
|
||||
if (stopwatch.elapsed >= Duration(seconds: 20)) {
|
||||
Logger("firebase-background").shout('Timeout reached. Exiting the loop.');
|
||||
break; // Exit the loop if the timeout is reached.
|
||||
}
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
}
|
||||
await apiProvider.close(() {});
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ Future<void> writeLogToFile(LogRecord record) async {
|
|||
|
||||
// Prepare the log message
|
||||
final logMessage =
|
||||
'${record.level.name}: ${record.loggerName}: ${record.message}\n';
|
||||
'${DateTime.now()}: ${record.level.name}: ${record.loggerName}: ${record.message}\n';
|
||||
|
||||
// Append the log message to the file
|
||||
await logFile.writeAsString(logMessage, mode: FileMode.append);
|
||||
|
|
|
|||
88
lib/src/views/settings/diagnostics_view.dart
Normal file
88
lib/src/views/settings/diagnostics_view.dart
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'dart:io';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class DiagnosticsView extends StatelessWidget {
|
||||
const DiagnosticsView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<String>(
|
||||
future: _loadLogFile(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (snapshot.hasError) {
|
||||
return Center(child: Text('Error: ${snapshot.error}'));
|
||||
} else {
|
||||
final logText = snapshot.data ?? '';
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Diagnostics')),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(logText),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: logText));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Log copied to clipboard!')),
|
||||
);
|
||||
},
|
||||
child: const Text('Copy All Text'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final directory =
|
||||
await getApplicationDocumentsDirectory();
|
||||
final logFile = File('${directory.path}/app.log');
|
||||
|
||||
if (await logFile.exists()) {
|
||||
await logFile.delete();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Log file deleted!')),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Log file does not exist.')),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('Delete Log File'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> _loadLogFile() async {
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
final logFile = File('${directory.path}/app.log');
|
||||
|
||||
if (await logFile.exists()) {
|
||||
return await logFile.readAsString();
|
||||
} else {
|
||||
return 'Log file does not exist.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/views/settings/diagnostics_view.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class HelpView extends StatelessWidget {
|
||||
|
|
@ -43,9 +44,15 @@ class HelpView extends StatelessWidget {
|
|||
showLicensePage(context: context);
|
||||
},
|
||||
),
|
||||
|
||||
// Diagnoseprotokoll
|
||||
|
||||
ListTile(
|
||||
title: Text(context.lang.settingsHelpDiagnostics),
|
||||
onTap: () async {
|
||||
await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return DiagnosticsView();
|
||||
}));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(context.lang.settingsHelpLegal),
|
||||
onTap: () {
|
||||
|
|
|
|||
56
pubspec.lock
56
pubspec.lock
|
|
@ -9,6 +9,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "80.0.0"
|
||||
_flutterfire_internals:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _flutterfire_internals
|
||||
sha256: e051259913915ea5bc8fe18664596bea08592fd123930605d562969cd7315fcd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.51"
|
||||
adaptive_number:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -305,6 +313,54 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
firebase_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_core
|
||||
sha256: "93dc4dd12f9b02c5767f235307f609e61ed9211047132d07f9e02c668f0bfc33"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.11.0"
|
||||
firebase_core_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_platform_interface
|
||||
sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.0"
|
||||
firebase_core_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_core_web
|
||||
sha256: "0e13c80f0de8acaa5d0519cbe23c8b4cc138a2d5d508b5755c861bdfc9762678"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.20.0"
|
||||
firebase_messaging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: firebase_messaging
|
||||
sha256: "3dee3b0cbfe719e64773cb7d1cad57c58b2235a8c136f5715fe733a54058c783"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.2.2"
|
||||
firebase_messaging_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_messaging_platform_interface
|
||||
sha256: e9ea726b9bb864fc6223bb66422bd9877b9973ae51967754a769b0d01e201c1e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.6.2"
|
||||
firebase_messaging_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_messaging_web
|
||||
sha256: "5f7b40e8bf861a37f8b8196e347d8a919750421a45f0b45d1bb74e98fa72726e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.10.2"
|
||||
fixnum:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ dependencies:
|
|||
connectivity_plus: ^6.1.2
|
||||
cv: ^1.1.3
|
||||
exif: ^3.3.0
|
||||
firebase_core: ^3.11.0
|
||||
firebase_messaging: ^15.2.2
|
||||
fixnum: ^1.1.1
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
|
|
|||
Loading…
Reference in a new issue