Implement FCM [WIP]

This commit is contained in:
2024-05-31 15:22:27 +02:00
parent 0ad82bb248
commit dfcee5dfc7
33 changed files with 665 additions and 337 deletions

View File

@@ -138,6 +138,37 @@ class APIClient {
);
}
static Future<Client> addClient(KeyTokenAuth? auth, String fcmToken, String agentModel, String agentVersion, String clientType) async {
return await _request(
name: 'addClient',
method: 'POST',
relURL: 'users/${auth!.userId}/clients',
jsonBody: {
'fcm_token': fcmToken,
'agent_model': agentModel,
'agent_version': agentVersion,
'client_type': clientType,
},
fn: Client.fromJson,
auth: auth,
);
}
static Future<Client> updateClient(KeyTokenAuth? auth, String clientID, String fcmToken, String agentModel, String agentVersion) async {
return await _request(
name: 'updateClient',
method: 'PUT',
relURL: 'users/${auth!.userId}/clients/$clientID',
jsonBody: {
'fcm_token': fcmToken,
'agent_model': agentModel,
'agent_version': agentVersion,
},
fn: Client.fromJson,
auth: auth,
);
}
static Future<List<ChannelWithSubscription>> getChannelList(KeyTokenAuth auth, ChannelSelector sel) async {
return await _request(
name: 'getChannelList',

View File

@@ -0,0 +1,94 @@
// 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) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
return macos;
case TargetPlatform.windows:
return windows;
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 web = FirebaseOptions(
apiKey: 'AIzaSyCbA3VPKlkfJXw27L_J1x5VbfxeqmjdR5o',
appId: '1:232728961679:web:e53211fff778ab61b446fa',
messagingSenderId: '232728961679',
projectId: 'simplecloudnotifier-ea7ef',
authDomain: 'simplecloudnotifier-ea7ef.firebaseapp.com',
databaseURL: 'https://simplecloudnotifier-ea7ef.firebaseio.com',
storageBucket: 'simplecloudnotifier-ea7ef.appspot.com',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyBasR6JLAjM5Ut0rPb0euE_9DdDoTkcvKQ',
appId: '1:232728961679:android:23c75317f79601c9',
messagingSenderId: '232728961679',
projectId: 'simplecloudnotifier-ea7ef',
databaseURL: 'https://simplecloudnotifier-ea7ef.firebaseio.com',
storageBucket: 'simplecloudnotifier-ea7ef.appspot.com',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyCJpUsV4ApJfQPcSDpPj2CkzNyS8093A8s',
appId: '1:232728961679:ios:85155ba52c4f3311b446fa',
messagingSenderId: '232728961679',
projectId: 'simplecloudnotifier-ea7ef',
databaseURL: 'https://simplecloudnotifier-ea7ef.firebaseio.com',
storageBucket: 'simplecloudnotifier-ea7ef.appspot.com',
androidClientId: '232728961679-o7gig6f684mp1l1ok7719v3jf3csejc1.apps.googleusercontent.com',
iosBundleId: 'com.blackforestbytes.simplecloudnotifier',
);
static const FirebaseOptions macos = FirebaseOptions(
apiKey: 'AIzaSyCJpUsV4ApJfQPcSDpPj2CkzNyS8093A8s',
appId: '1:232728961679:ios:85155ba52c4f3311b446fa',
messagingSenderId: '232728961679',
projectId: 'simplecloudnotifier-ea7ef',
databaseURL: 'https://simplecloudnotifier-ea7ef.firebaseio.com',
storageBucket: 'simplecloudnotifier-ea7ef.appspot.com',
androidClientId: '232728961679-o7gig6f684mp1l1ok7719v3jf3csejc1.apps.googleusercontent.com',
iosBundleId: 'com.blackforestbytes.simplecloudnotifier',
);
static const FirebaseOptions windows = FirebaseOptions(
apiKey: 'AIzaSyCbA3VPKlkfJXw27L_J1x5VbfxeqmjdR5o',
appId: '1:232728961679:web:6e8235651da6241eb446fa',
messagingSenderId: '232728961679',
projectId: 'simplecloudnotifier-ea7ef',
authDomain: 'simplecloudnotifier-ea7ef.firebaseapp.com',
databaseURL: 'https://simplecloudnotifier-ea7ef.firebaseio.com',
storageBucket: 'simplecloudnotifier-ea7ef.appspot.com',
);
}

View File

@@ -1,13 +1,17 @@
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:fl_toast/fl_toast.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:simplecloudnotifier/api/api_client.dart';
import 'package:simplecloudnotifier/nav_layout.dart';
import 'package:simplecloudnotifier/state/app_theme.dart';
import 'package:simplecloudnotifier/state/application_log.dart';
import 'package:simplecloudnotifier/state/globals.dart';
import 'package:simplecloudnotifier/state/request_log.dart';
import 'package:simplecloudnotifier/state/user_account.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -35,6 +39,22 @@ void main() async {
ApplicationLog.error('Failed to open Hive-Box: scn-logs: ' + exc.toString(), trace: trace);
}
UserAccount(); // ensure UserAccount is loaded
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);
FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) {
try {
setFirebaseToken(fcmToken);
} catch (exc, trace) {
ApplicationLog.error('Failed to set firebase token: ' + exc.toString(), trace: trace);
}
}).onError((dynamic err) {
ApplicationLog.error('Failed to listen to token refresh events: ' + (err?.toString() ?? ''));
});
ApplicationLog.debug('Application started');
runApp(
@@ -48,13 +68,25 @@ void main() async {
);
}
void setFirebaseToken(String fcmToken) async {
ApplicationLog.info('New firebase token: $fcmToken');
final acc = UserAccount();
if (acc.auth != null) {
if (acc.client == null) {
final client = await APIClient.addClient(acc.auth, fcmToken, Globals().platform, Globals().version, Globals().clientType);
acc.setClient(client);
} else {
final client = await APIClient.updateClient(acc.auth, acc.client!.clientID, fcmToken, Globals().platform, Globals().version);
acc.setClient(client);
}
}
}
class SCNApp extends StatelessWidget {
const SCNApp({super.key});
@override
Widget build(BuildContext context) {
Provider.of<UserAccount>(context); // ensure UserAccount is loaded (unneccessary if lazy: false is set in MultiProvider ??)
return Consumer<AppTheme>(
builder: (context, appTheme, child) => MaterialApp(
title: 'SimpleCloudNotifier',

View File

@@ -1,5 +1,6 @@
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -18,6 +19,8 @@ class Globals {
String buildNumber = '';
String platform = '';
String hostname = '';
String clientType = '';
String deviceModel = '';
late SharedPreferences sharedPrefs;
@@ -31,6 +34,25 @@ class Globals {
this.platform = Platform.operatingSystem;
this.hostname = Platform.localHostname;
if (Platform.isAndroid) {
this.clientType = 'ANDROID';
this.deviceModel = (await DeviceInfoPlugin().androidInfo).model;
} else if (Platform.isIOS) {
this.clientType = 'IOS';
this.deviceModel = (await DeviceInfoPlugin().iosInfo).model;
} else if (Platform.isLinux) {
this.clientType = 'LINUX';
this.deviceModel = (await DeviceInfoPlugin().linuxInfo).prettyName;
} else if (Platform.isWindows) {
this.clientType = 'WINDOWS';
this.deviceModel = (await DeviceInfoPlugin().windowsInfo).productName;
} else if (Platform.isMacOS) {
this.clientType = 'MACOS';
this.deviceModel = (await DeviceInfoPlugin().macOsInfo).model;
} else {
this.clientType = '?';
}
this.sharedPrefs = await SharedPreferences.getInstance();
}
}

View File

@@ -1,6 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:simplecloudnotifier/api/api_client.dart';
import 'package:simplecloudnotifier/models/client.dart';
import 'package:simplecloudnotifier/models/key_token_auth.dart';
import 'package:simplecloudnotifier/models/user.dart';
import 'package:simplecloudnotifier/state/globals.dart';
@@ -9,10 +10,19 @@ class UserAccount extends ChangeNotifier {
User? _user;
User? get user => _user;
Client? _client;
Client? get client => _client;
KeyTokenAuth? _auth;
KeyTokenAuth? get auth => _auth;
UserAccount() {
static UserAccount? _singleton = UserAccount._internal();
factory UserAccount() {
return _singleton ?? (_singleton = UserAccount._internal());
}
UserAccount._internal() {
load();
}
@@ -38,6 +48,16 @@ class UserAccount extends ChangeNotifier {
notifyListeners();
}
void setClient(Client client) {
_client = client;
notifyListeners();
}
void clearClient() {
_client = null;
notifyListeners();
}
void load() {
final uid = Globals().sharedPrefs.getString('auth.userid');
final tok = Globals().sharedPrefs.getString('auth.token');