Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle TokenConfig reconnection for PushNotifications #102

Merged
merged 3 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import 'package:telnyx_webrtc/telnyx_client.dart';
import 'package:telnyx_webrtc/model/telnyx_message.dart';
import 'package:telnyx_webrtc/model/socket_method.dart';
import 'package:telnyx_flutter_webrtc/utils/theme.dart';
import 'package:telnyx_webrtc/config/telnyx_config.dart';

final logger = Logger();
final txClientViewModel = TelnyxClientViewModel();
Expand Down Expand Up @@ -227,11 +228,11 @@ Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async {

logger.i('iOS notification token :: $token');
}
final credentialConfig = await txClientViewModel.getCredentialConfig();
final config = await txClientViewModel.getConfig();
telnyxClient.handlePushNotification(
pushMetaData,
credentialConfig,
null,
config is CredentialConfig ? config : null,
config is TokenConfig ? config : null,
);
break;
case Event.actionDidUpdateDevicePushTokenVoip:
Expand Down Expand Up @@ -276,7 +277,7 @@ Future<void> main() async {
await AppInitializer().initialize();
}

final credentialConfig = await txClientViewModel.getCredentialConfig();
final config = await txClientViewModel.getConfig();
runApp(
BackgroundDetector(
onLifecycleEvent: (AppLifecycleState state) => {
Expand All @@ -286,7 +287,14 @@ Future<void> main() async {
// Check if we are from push, if we are do nothing, reconnection will happen there in handlePush. Otherwise connect
if (!txClientViewModel.callFromPush)
{
txClientViewModel.login(credentialConfig),
if (config != null && config is CredentialConfig)
{
txClientViewModel.login(config),
}
else if (config != null && config is TokenConfig)
{
txClientViewModel.loginWithToken(config),
},
},
}
else if (state == AppLifecycleState.paused)
Expand Down Expand Up @@ -319,9 +327,13 @@ Future<void> handlePush(Map<dynamic, dynamic> data) async {
pushMetaData = PushMetaData.fromJson(data);
logger.i('iOS notification token :: $token');
}
final credentialConfig = await txClientViewModel.getCredentialConfig();
final config = await txClientViewModel.getConfig();
txClientViewModel
..handlePushNotification(pushMetaData!, credentialConfig, null)
..handlePushNotification(
pushMetaData!,
config is CredentialConfig ? config : null,
config is TokenConfig ? config : null,
)
..observeResponses();
logger.i('actionCallIncoming :: Received Incoming Call! Handle Push');
}
Expand Down
30 changes: 28 additions & 2 deletions lib/model/profile_model.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import 'dart:io';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
import 'package:telnyx_webrtc/config/telnyx_config.dart';

class Profile {
Expand All @@ -7,6 +13,7 @@ class Profile {
final String sipPassword;
final String sipCallerIDName;
final String sipCallerIDNumber;
final String? notificationToken;

Profile({
required this.isTokenLogin,
Expand All @@ -15,6 +22,7 @@ class Profile {
this.sipPassword = '',
this.sipCallerIDName = '',
this.sipCallerIDNumber = '',
this.notificationToken = '',
});

factory Profile.fromJson(Map<String, dynamic> json) {
Expand All @@ -25,6 +33,7 @@ class Profile {
sipPassword: json['sipPassword'] as String? ?? '',
sipCallerIDName: json['sipCallerIDName'] as String? ?? '',
sipCallerIDNumber: json['sipCallerIDNumber'] as String? ?? '',
notificationToken: json['notificationToken'] as String? ?? '',
);
}

Expand All @@ -36,15 +45,31 @@ class Profile {
'sipPassword': sipPassword,
'sipCallerIDName': sipCallerIDName,
'sipCallerIDNumber': sipCallerIDNumber,
'notificationToken': notificationToken,
};
}

Config toTelnyxConfig() {
Future<String?> getNotificationTokenForPlatform() async {
var token;
if (defaultTargetPlatform == TargetPlatform.android) {
// If no apps are initialized, initialize one now.
if (Firebase.apps.isEmpty) {
await Firebase.initializeApp();
}
token = (await FirebaseMessaging.instance.getToken())!;
} else if (Platform.isIOS) {
token = await FlutterCallkitIncoming.getDevicePushTokenVoIP();
}
return token;
}

Future<Config> toTelnyxConfig() async {
if (isTokenLogin) {
return TokenConfig(
sipToken: token,
sipCallerIDName: sipCallerIDName,
sipCallerIDNumber: sipCallerIDNumber,
notificationToken: await getNotificationTokenForPlatform() ?? '',
debug: false,
);
} else {
Expand All @@ -53,8 +78,9 @@ class Profile {
sipPassword: sipPassword,
sipCallerIDName: sipCallerIDName,
sipCallerIDNumber: sipCallerIDNumber,
notificationToken: await getNotificationTokenForPlatform() ?? '',
debug: false,
);
}
}
}
}
36 changes: 30 additions & 6 deletions lib/view/telnyx_client_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -353,12 +353,22 @@ class TelnyxClientViewModel with ChangeNotifier {

bool waitingForInvite = false;

Future<CredentialConfig> getCredentialConfig() async {
Future<Config?> getConfig() async {
final config = await _getCredentialConfig();
if (config != null) {
return config;
} else {
return await _getTokenConfig();
}
}

Future<CredentialConfig?> _getCredentialConfig() async {
final prefs = await SharedPreferences.getInstance();
final sipUser = prefs.getString('sipUser');
final sipPassword = prefs.getString('sipPassword');
final sipName = prefs.getString('sipName');
final sipNumber = prefs.getString('sipNumber');
final notificationToken = prefs.getString('notificationToken');
if (sipUser != null &&
sipPassword != null &&
sipName != null &&
Expand All @@ -368,16 +378,30 @@ class TelnyxClientViewModel with ChangeNotifier {
sipCallerIDNumber: sipNumber,
sipUser: sipUser,
sipPassword: sipPassword,
notificationToken: notificationToken,
debug: true,
);
} else {
return CredentialConfig(
sipCallerIDName: 'Flutter Voice',
sipCallerIDNumber: '',
sipUser: MOCK_USER,
sipPassword: MOCK_PASSWORD,
return null;
}
}

Future<TokenConfig?> _getTokenConfig() async {
final prefs = await SharedPreferences.getInstance();
final token = prefs.getString('token');
final sipName = prefs.getString('sipName');
final sipNumber = prefs.getString('sipNumber');
final notificationToken = prefs.getString('notificationToken');
if (token != null && sipName != null && sipNumber != null) {
return TokenConfig(
sipCallerIDName: sipName,
sipCallerIDNumber: sipNumber,
sipToken: token,
notificationToken: notificationToken,
debug: true,
);
} else {
return null;
}
}

Expand Down
15 changes: 6 additions & 9 deletions lib/view/widgets/login/login_controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,13 @@ class _LoginControlsState extends State<LoginControls> {
width: double.infinity,
child: ElevatedButton(
onPressed: selectedProfile != null
? () {
? () async {
final viewModel = context.read<TelnyxClientViewModel>();
if (selectedProfile.isTokenLogin) {
viewModel.loginWithToken(
selectedProfile.toTelnyxConfig() as TokenConfig,
);
} else {
viewModel.login(
selectedProfile.toTelnyxConfig() as CredentialConfig,
);
final config = await selectedProfile.toTelnyxConfig();
if (config is TokenConfig) {
viewModel.loginWithToken(config);
} else if (config is CredentialConfig) {
viewModel.login(config);
}
}
: null,
Expand Down
Loading