Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
vmeeting
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Inomjon
vmeeting
Commits
3103d00c
Commit
3103d00c
authored
Dec 01, 2023
by
Inomjon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update chiqarish
parent
7831c56e
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
8 additions
and
1082 deletions
+8
-1082
login_screen.dart
lib/srcchat/login_screen.dart
+0
-544
push_notifications_manager.dart
lib/srcchat/managers/push_notifications_manager.dart
+0
-287
phone_auth_flow.dart
lib/srcchat/phone_auth_flow.dart
+0
-111
settings_screen.dart
lib/srcchat/settings_screen.dart
+4
-4
api_utils.dart
lib/srcchat/utils/api_utils.dart
+4
-8
pref_util.dart
lib/srcchat/utils/pref_util.dart
+0
-128
No files found.
lib/srcchat/login_screen.dart
deleted
100644 → 0
View file @
7831c56e
import
'dart:convert'
;
import
'package:firebase_auth/firebase_auth.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_local_notifications/flutter_local_notifications.dart'
;
import
'package:fluttertoast/fluttertoast.dart'
;
import
'package:connectycube_sdk/connectycube_sdk.dart'
;
import
'../firebase_options.dart'
;
import
'managers/push_notifications_manager.dart'
;
import
'phone_auth_flow.dart'
;
import
'utils/api_utils.dart'
;
import
'utils/consts.dart'
;
import
'utils/platform_utils.dart'
as
platformUtils
;
import
'utils/pref_util.dart'
;
class
LoginScreen
extends
StatelessWidget
{
static
const
String
TAG
=
"LoginScreen"
;
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
// appBar: AppBar(automaticallyImplyLeading: false, title: Text('Chat')),
body:
LoginPage
(),
);
}
}
class
LoginPage
extends
StatefulWidget
{
@override
State
<
StatefulWidget
>
createState
()
=>
new
LoginPageState
();
}
// Used for controlling whether the user is loggin or creating an account
enum
FormType
{
login
,
register
}
class
LoginPageState
extends
State
<
LoginPage
>
{
static
const
String
TAG
=
"_LoginPageState"
;
final
TextEditingController
_loginFilter
=
new
TextEditingController
();
final
TextEditingController
_passwordFilter
=
new
TextEditingController
();
String
_login
=
""
;
String
_password
=
""
;
FormType
_form
=
FormType
.
login
;
// our default setting is to login, and we should switch to creating an account when the user chooses to
bool
_isLoginContinues
=
false
;
List
<
bool
>
loginEmailSelection
=
[
true
,
false
];
bool
isEmailSelected
=
false
;
LoginPageState
()
{
_loginFilter
.
addListener
(
_loginListen
);
_passwordFilter
.
addListener
(
_passwordListen
);
}
void
_loginListen
()
{
if
(
_loginFilter
.
text
.
isEmpty
)
{
_login
=
""
;
}
else
{
_login
=
_loginFilter
.
text
;
}
}
void
_passwordListen
()
{
if
(
_passwordFilter
.
text
.
isEmpty
)
{
_password
=
""
;
}
else
{
_password
=
_passwordFilter
.
text
;
}
}
// Swap in between our two forms, registering and logging in
void
_formChange
()
async
{
setState
(()
{
if
(
_form
==
FormType
.
register
)
{
_form
=
FormType
.
login
;
}
else
{
_form
=
FormType
.
register
;
}
});
}
@override
void
initState
()
{
super
.
initState
();
loginEmailSelection
=
[
true
,
false
];
isEmailSelected
=
loginEmailSelection
[
1
];
}
@override
Widget
build
(
BuildContext
context
)
{
return
new
Scaffold
(
body:
Center
(
child:
SingleChildScrollView
(
child:
new
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
16.0
),
child:
new
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
mainAxisSize:
MainAxisSize
.
max
,
mainAxisAlignment:
MainAxisAlignment
.
end
,
children:
<
Widget
>[
_buildLogoField
(),
_initLoginWidgets
()],
),
),
),
),
);
}
Widget
_buildLogoField
()
{
// return Image.asset('assets/images/splash.png');
return
Container
(
child:
Align
(
alignment:
FractionalOffset
.
center
,
child:
Column
(
children:
[
ConstrainedBox
(
constraints:
BoxConstraints
(
maxWidth:
350
),
child:
Image
.
asset
(
'assets/images/splash.png'
),
),
Container
(
margin:
EdgeInsets
.
only
(
left:
8
),
height:
18
,
width:
18
,
child:
Visibility
(
visible:
_isLoginContinues
,
child:
CircularProgressIndicator
(
strokeWidth:
2
,
),
),
),
],
),
),
);
}
_initLoginWidgets
()
{
return
FutureBuilder
<
Widget
>(
future:
getFilterChipsWidgets
(),
builder:
(
BuildContext
context
,
AsyncSnapshot
<
Widget
>
snapshot
)
{
if
(
snapshot
.
hasData
)
{
return
snapshot
.
data
!;
}
return
SizedBox
.
shrink
();
});
}
Future
<
Widget
>
getFilterChipsWidgets
()
async
{
if
(
_isLoginContinues
)
return
SizedBox
.
shrink
();
SharedPrefs
sharedPrefs
=
await
SharedPrefs
.
instance
.
init
();
var
loginType
=
sharedPrefs
.
getLoginType
();
var
user
=
sharedPrefs
.
getUser
();
if
((
user
!=
null
&&
loginType
==
null
)
||
loginType
!=
null
)
{
_loginToCCWithSavedUser
(
context
,
loginType
??
LoginType
.
login
);
return
SizedBox
.
shrink
();
}
else
return
new
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
mainAxisSize:
MainAxisSize
.
max
,
mainAxisAlignment:
MainAxisAlignment
.
end
,
children:
<
Widget
>[
_buildTextFields
(),
_buildButtons
()],
);
}
Widget
_buildTextFields
()
{
return
ConstrainedBox
(
constraints:
BoxConstraints
(
maxWidth:
400
),
child:
Container
(
child:
Column
(
children:
<
Widget
>[
Align
(
alignment:
Alignment
.
centerRight
,
child:
ToggleButtons
(
constraints:
BoxConstraints
(
maxHeight:
38
),
borderColor:
Colors
.
green
,
fillColor:
Colors
.
green
.
shade400
,
borderWidth:
1
,
selectedBorderColor:
Colors
.
green
,
selectedColor:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
28
),
children:
<
Widget
>[
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
4
,
horizontal:
6.0
),
child:
Text
(
'By Login'
,
style:
TextStyle
(
color:
isEmailSelected
?
Colors
.
green
:
Colors
.
white
),
),
),
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
4
,
horizontal:
6.0
),
child:
Text
(
'By E-mail'
,
style:
TextStyle
(
color:
isEmailSelected
?
Colors
.
white
:
Colors
.
green
),
),
),
],
onPressed:
(
int
index
)
{
setState
(()
{
for
(
int
i
=
0
;
i
<
loginEmailSelection
.
length
;
i
++)
{
loginEmailSelection
[
i
]
=
i
==
index
;
}
isEmailSelected
=
loginEmailSelection
[
1
];
});
},
isSelected:
loginEmailSelection
,
),
),
Container
(
child:
TextField
(
keyboardType:
isEmailSelected
?
TextInputType
.
emailAddress
:
TextInputType
.
text
,
controller:
_loginFilter
,
decoration:
InputDecoration
(
labelText:
isEmailSelected
?
'E-mail'
:
'Login'
),
),
),
Container
(
child:
TextField
(
keyboardType:
TextInputType
.
visiblePassword
,
controller:
_passwordFilter
,
decoration:
InputDecoration
(
labelText:
'Password'
),
obscureText:
true
,
enableSuggestions:
false
,
autocorrect:
false
,
onSubmitted:
(
_
)
{
_form
==
FormType
.
login
?
_loginPressed
()
:
_createAccountPressed
();
},
),
)
],
),
),
);
}
Widget
_buildButtons
()
{
return
ConstrainedBox
(
constraints:
BoxConstraints
(
maxWidth:
400
),
child:
_form
==
FormType
.
login
?
Container
(
margin:
EdgeInsets
.
only
(
top:
8
),
child:
Column
(
children:
<
Widget
>[
ElevatedButton
(
child:
new
Text
(
'Login'
),
onPressed:
_loginPressed
,
),
TextButton
(
child:
new
Text
(
'Don
\'
t have an account? Tap here to register.'
),
onPressed:
_formChange
,
),
...
createCIPButtons
(),
],
),
)
:
Container
(
margin:
EdgeInsets
.
only
(
top:
8
),
child:
Column
(
children:
<
Widget
>[
ElevatedButton
(
child:
new
Text
(
'Create an Account'
),
onPressed:
_createAccountPressed
,
),
TextButton
(
child:
new
Text
(
'Have an account? Click here to login.'
),
onPressed:
_formChange
,
),
...
createCIPButtons
(),
],
),
),
);
}
List
<
Widget
>
createCIPButtons
()
{
return
[
Visibility
(
visible:
platformUtils
.
isPhoneAuthSupported
,
child:
OutlinedButton
.
icon
(
style:
OutlinedButton
.
styleFrom
(
minimumSize:
Size
(
190
,
36
),
),
icon:
Icon
(
Icons
.
dialpad
,
),
label:
Text
(
'By Phone number'
),
onPressed:
()
{
platformUtils
.
showModal
(
context:
context
,
child:
VerifyPhoneNumber
());
},
),
),
SizedBox
(
height:
6
,
),
OutlinedButton
.
icon
(
style:
OutlinedButton
.
styleFrom
(
foregroundColor:
Colors
.
blue
,
minimumSize:
Size
(
190
,
36
),
),
icon:
Icon
(
Icons
.
facebook
,
color:
Colors
.
blue
.
shade700
,
),
label:
Text
(
'By Facebook'
,
style:
TextStyle
(
color:
Colors
.
blue
.
shade700
),
),
onPressed:
()
{
Fluttertoast
.
showToast
(
msg:
'Coming soon'
,
gravity:
ToastGravity
.
BOTTOM
);
},
),
];
}
void
_loginPressed
()
{
print
(
'login with
$_login
and
$_password
'
);
var
userToLogin
=
CubeUser
();
if
(
isEmailSelected
)
{
userToLogin
.
email
=
_login
;
}
else
{
userToLogin
.
login
=
_login
;
}
userToLogin
.
password
=
_password
;
_loginToCC
(
context
,
userToLogin
,
saveUser:
true
);
}
void
_createAccountPressed
()
{
print
(
'create an user with
$_login
and
$_password
'
);
var
userToSignUp
=
CubeUser
();
if
(
isEmailSelected
)
{
userToSignUp
.
email
=
_login
;
}
else
{
userToSignUp
.
login
=
_login
;
}
userToSignUp
.
password
=
_password
;
userToSignUp
.
fullName
=
_login
;
_signInCC
(
context
,
userToSignUp
);
}
_signInCC
(
BuildContext
context
,
CubeUser
user
)
async
{
if
(
_isLoginContinues
)
return
;
setState
(()
{
_isLoginContinues
=
true
;
});
if
(!
CubeSessionManager
.
instance
.
isActiveSessionValid
())
{
try
{
await
createSession
();
}
catch
(
error
)
{
_processLoginError
(
error
);
}
}
signUp
(
user
).
then
((
newUser
)
{
print
(
"signUp newUser
$newUser
"
);
user
.
id
=
newUser
.
id
;
SharedPrefs
.
instance
.
saveNewUser
(
user
,
isEmailSelected
?
LoginType
.
email
:
LoginType
.
login
);
signIn
(
user
).
then
((
result
)
{
PushNotificationsManager
.
instance
.
init
();
_loginToCubeChat
(
context
,
user
);
});
}).
catchError
((
exception
)
{
_processLoginError
(
exception
);
});
}
_loginToCC
(
BuildContext
context
,
CubeUser
user
,
{
bool
saveUser
=
false
})
{
print
(
"_loginToCC user:
$user
"
);
if
(
_isLoginContinues
)
return
;
setState
(()
{
_isLoginContinues
=
true
;
});
createSession
(
user
).
then
((
cubeSession
)
async
{
print
(
"createSession cubeSession:
$cubeSession
"
);
var
tempUser
=
user
;
user
=
cubeSession
.
user
!..
password
=
tempUser
.
password
;
if
(
saveUser
)
SharedPrefs
.
instance
.
init
().
then
((
sharedPrefs
)
{
sharedPrefs
.
saveNewUser
(
user
,
isEmailSelected
?
LoginType
.
email
:
LoginType
.
login
);
});
PushNotificationsManager
.
instance
.
init
();
_loginToCubeChat
(
context
,
user
);
}).
catchError
((
error
)
{
_processLoginError
(
error
);
});
}
_loginToCCWithSavedUser
(
BuildContext
context
,
LoginType
loginType
)
async
{
log
(
"[_loginToCCWithSavedUser] user:
$loginType
"
);
if
(
_isLoginContinues
)
return
;
setState
(()
{
_isLoginContinues
=
true
;
});
Future
<
CubeUser
>?
signInFuture
;
if
(
loginType
==
LoginType
.
phone
)
{
var
phoneAuthToken
=
await
FirebaseAuth
.
instance
.
currentUser
?.
getIdToken
();
if
(
phoneAuthToken
==
null
)
{
setState
(()
{
_isLoginContinues
=
false
;
});
showDialog
(
context:
context
,
builder:
(
BuildContext
context
)
{
return
AlertDialog
(
title:
Text
(
'Error'
),
content:
Text
(
'Your Phone authentication session was expired, please refresh it by second login using your phone number'
),
actions:
<
Widget
>[
TextButton
(
child:
Text
(
"OK"
),
onPressed:
()
=>
Navigator
.
of
(
context
).
pop
(),
)
],
);
});
return
;
}
signInFuture
=
createSession
().
then
((
cubeSession
)
{
return
signInUsingFirebase
(
DefaultFirebaseOptions
.
currentPlatform
.
projectId
,
phoneAuthToken
)
.
then
((
cubeUser
)
{
return
SharedPrefs
.
instance
.
init
().
then
((
sharedPrefs
)
{
sharedPrefs
.
saveNewUser
(
cubeUser
,
LoginType
.
phone
);
return
cubeUser
..
password
=
CubeSessionManager
.
instance
.
activeSession
?.
token
;
});
});
});
}
else
if
(
loginType
==
LoginType
.
login
||
loginType
==
LoginType
.
email
)
{
signInFuture
=
SharedPrefs
.
instance
.
init
().
then
((
sharedPrefs
)
{
var
savedUser
=
sharedPrefs
.
getUser
();
return
createSession
(
savedUser
).
then
((
value
)
{
return
savedUser
!;
});
});
}
signInFuture
?.
then
((
cubeUser
)
{
PushNotificationsManager
.
instance
.
init
();
_loginToCubeChat
(
context
,
cubeUser
);
}).
catchError
((
error
)
{
_processLoginError
(
error
);
});
}
_loginToCubeChat
(
BuildContext
context
,
CubeUser
user
)
{
log
(
"_loginToCubeChat user
$user
"
);
CubeChatConnectionSettings
.
instance
.
totalReconnections
=
0
;
CubeChatConnection
.
instance
.
login
(
user
).
then
((
cubeUser
)
{
_isLoginContinues
=
false
;
_goDialogScreen
(
context
,
cubeUser
);
}).
catchError
((
error
)
{
_processLoginError
(
error
);
});
}
void
_processLoginError
(
exception
)
{
log
(
"Login error
$exception
"
,
TAG
);
setState
(()
{
_isLoginContinues
=
false
;
});
showDialogError
(
exception
,
context
);
}
void
_goDialogScreen
(
BuildContext
context
,
CubeUser
cubeUser
)
async
{
log
(
"_goDialogScreen"
);
FlutterLocalNotificationsPlugin
()
.
getNotificationAppLaunchDetails
()
.
then
((
details
)
{
log
(
"getNotificationAppLaunchDetails"
);
String
?
payload
=
details
!.
notificationResponse
?.
payload
;
log
(
"getNotificationAppLaunchDetails, payload:
$payload
"
);
var
dialogId
;
if
(
payload
==
null
)
{
dialogId
=
SharedPrefs
.
instance
.
getSelectedDialogId
();
log
(
"getNotificationAppLaunchDetails, selectedDialogId:
$dialogId
"
);
}
else
{
Map
<
String
,
dynamic
>
payloadObject
=
jsonDecode
(
payload
);
dialogId
=
payloadObject
[
'dialog_id'
];
}
if
(
dialogId
!=
null
&&
dialogId
.
isNotEmpty
)
{
getDialogs
({
'id'
:
dialogId
}).
then
((
dialogs
)
{
if
(
dialogs
?.
items
!=
null
&&
dialogs
!.
items
.
isNotEmpty
)
{
CubeDialog
dialog
=
dialogs
.
items
.
first
;
navigateToNextScreen
(
cubeUser
,
dialog
);
}
else
{
navigateToNextScreen
(
cubeUser
,
null
);
}
}).
catchError
((
onError
)
{
navigateToNextScreen
(
cubeUser
,
null
);
});
}
else
{
navigateToNextScreen
(
cubeUser
,
null
);
}
}).
catchError
((
onError
)
{
log
(
"getNotificationAppLaunchDetails ERROR"
);
navigateToNextScreen
(
cubeUser
,
null
);
});
}
void
navigateToNextScreen
(
CubeUser
cubeUser
,
CubeDialog
?
dialog
)
{
SharedPrefs
.
instance
.
saveSelectedDialogId
(
''
);
Navigator
.
pushReplacementNamed
(
context
,
'select_dialog'
,
arguments:
{
USER_ARG_NAME:
cubeUser
,
DIALOG_ARG_NAME:
dialog
},
);
if
(
dialog
!=
null
&&
!
platformUtils
.
isDesktop
())
{
Navigator
.
pushNamed
(
context
,
'chat_dialog'
,
arguments:
{
USER_ARG_NAME:
cubeUser
,
DIALOG_ARG_NAME:
dialog
});
}
}
}
lib/srcchat/managers/push_notifications_manager.dart
deleted
100644 → 0
View file @
7831c56e
import
'dart:async'
;
import
'dart:convert'
;
import
'package:device_info_plus/device_info_plus.dart'
;
import
'package:firebase_messaging/firebase_messaging.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_local_notifications/flutter_local_notifications.dart'
;
import
'package:package_info_plus/package_info_plus.dart'
;
import
'package:universal_io/io.dart'
;
import
'package:uuid/uuid.dart'
;
import
'package:connectycube_sdk/connectycube_sdk.dart'
;
import
'../utils/consts.dart'
;
import
'../utils/platform_utils.dart'
;
import
'../utils/pref_util.dart'
;
class
PushNotificationsManager
{
static
const
TAG
=
"PushNotificationsManager"
;
static
final
PushNotificationsManager
_instance
=
PushNotificationsManager
.
_internal
();
late
FlutterLocalNotificationsPlugin
flutterLocalNotificationsPlugin
;
PushNotificationsManager
.
_internal
()
{
flutterLocalNotificationsPlugin
=
FlutterLocalNotificationsPlugin
();
}
BuildContext
?
applicationContext
;
static
PushNotificationsManager
get
instance
=>
_instance
;
Future
<
dynamic
>
Function
(
String
?
payload
)?
onNotificationClicked
;
init
()
async
{
log
(
'[init]'
,
TAG
);
FirebaseMessaging
firebaseMessaging
=
FirebaseMessaging
.
instance
;
await
firebaseMessaging
.
requestPermission
(
alert:
true
,
badge:
true
,
sound:
true
);
const
AndroidInitializationSettings
initializationSettingsAndroid
=
AndroidInitializationSettings
(
'ic_launcher_foreground'
);
final
DarwinInitializationSettings
initializationSettingsIOS
=
DarwinInitializationSettings
(
requestSoundPermission:
true
,
requestBadgePermission:
true
,
requestAlertPermission:
true
,
onDidReceiveLocalNotification:
onDidReceiveLocalNotification
,
);
final
InitializationSettings
initializationSettings
=
InitializationSettings
(
android:
initializationSettingsAndroid
,
iOS:
initializationSettingsIOS
,
macOS:
DarwinInitializationSettings
());
await
flutterLocalNotificationsPlugin
.
initialize
(
initializationSettings
,
onDidReceiveNotificationResponse:
(
NotificationResponse
notificationResponse
)
{
log
(
'[onDidReceiveNotificationResponse] payload:
${notificationResponse.payload}
'
,
TAG
);
var
data
=
notificationResponse
.
payload
;
if
(
data
!=
null
)
{
if
(
onNotificationClicked
!=
null
)
{
onNotificationClicked
?.
call
(
data
);
}
else
{
String
?
dialogId
=
jsonDecode
(
data
)[
'dialog_id'
];
SharedPrefs
.
instance
.
saveSelectedDialogId
(
dialogId
??
''
);
}
}
},
onDidReceiveBackgroundNotificationResponse:
notificationTapBackground
,
);
String
?
token
;
if
(
Platform
.
isAndroid
||
kIsWeb
||
Platform
.
isIOS
||
Platform
.
isMacOS
)
{
firebaseMessaging
.
getToken
().
then
((
token
)
{
log
(
'[getToken] token:
$token
'
,
TAG
);
subscribe
(
token
);
}).
catchError
((
onError
)
{
log
(
'[getToken] onError:
$onError
'
,
TAG
);
});
}
if
(!
isEmpty
(
token
))
{
subscribe
(
token
);
}
firebaseMessaging
.
onTokenRefresh
.
listen
((
newToken
)
{
subscribe
(
newToken
);
});
FirebaseMessaging
.
onMessage
.
listen
((
remoteMessage
)
{
log
(
'[onMessage] message:
${remoteMessage.data}
'
,
TAG
);
showNotification
(
remoteMessage
);
});
// TODO test after fix https://github.com/FirebaseExtended/flutterfire/issues/4898
FirebaseMessaging
.
onMessageOpenedApp
.
listen
((
remoteMessage
)
{
log
(
'[onMessageOpenedApp] remoteMessage:
$remoteMessage
'
,
TAG
);
onNotificationClicked
?.
call
(
jsonEncode
(
remoteMessage
.
data
));
});
}
subscribe
(
String
?
token
)
async
{
log
(
'[subscribe] token:
$token
'
,
PushNotificationsManager
.
TAG
);
SharedPrefs
sharedPrefs
=
await
SharedPrefs
.
instance
.
init
();
if
(
sharedPrefs
.
getSubscriptionToken
()
==
token
)
{
log
(
'[subscribe] skip subscription for same token'
,
PushNotificationsManager
.
TAG
);
return
;
}
CreateSubscriptionParameters
parameters
=
CreateSubscriptionParameters
();
parameters
.
pushToken
=
token
;
bool
isProduction
=
kIsWeb
?
true
:
bool
.
fromEnvironment
(
'dart.vm.product'
);
parameters
.
environment
=
isProduction
?
CubeEnvironment
.
PRODUCTION
:
CubeEnvironment
.
DEVELOPMENT
;
if
(
Platform
.
isAndroid
||
kIsWeb
||
Platform
.
isIOS
||
Platform
.
isMacOS
)
{
parameters
.
channel
=
NotificationsChannels
.
GCM
;
parameters
.
platform
=
CubePlatform
.
ANDROID
;
}
var
deviceInfoPlugin
=
DeviceInfoPlugin
();
var
deviceId
;
if
(
kIsWeb
)
{
var
webBrowserInfo
=
await
deviceInfoPlugin
.
webBrowserInfo
;
deviceId
=
base64Encode
(
utf8
.
encode
(
webBrowserInfo
.
userAgent
??
''
));
}
else
if
(
Platform
.
isAndroid
)
{
var
androidInfo
=
await
deviceInfoPlugin
.
androidInfo
;
deviceId
=
androidInfo
.
id
;
}
else
if
(
Platform
.
isIOS
)
{
var
iosInfo
=
await
deviceInfoPlugin
.
iosInfo
;
deviceId
=
iosInfo
.
identifierForVendor
;
}
else
if
(
Platform
.
isMacOS
)
{
var
macOsInfo
=
await
deviceInfoPlugin
.
macOsInfo
;
deviceId
=
macOsInfo
.
computerName
;
}
parameters
.
udid
=
deviceId
??
Uuid
().
v4
;
var
packageInfo
=
await
PackageInfo
.
fromPlatform
();
parameters
.
bundleIdentifier
=
packageInfo
.
packageName
;
createSubscription
(
parameters
.
getRequestParameters
())
.
then
((
cubeSubscription
)
{
log
(
'[subscribe] subscription SUCCESS'
,
PushNotificationsManager
.
TAG
);
sharedPrefs
.
saveSubscriptionToken
(
token
!);
cubeSubscription
.
forEach
((
subscription
)
{
if
(
subscription
.
clientIdentificationSequence
==
token
)
{
sharedPrefs
.
saveSubscriptionId
(
subscription
.
id
!);
}
});
}).
catchError
((
error
)
{
log
(
'[subscribe] subscription ERROR:
$error
'
,
PushNotificationsManager
.
TAG
);
});
}
Future
<
void
>
unsubscribe
()
{
return
SharedPrefs
.
instance
.
init
().
then
((
sharedPrefs
)
{
int
subscriptionId
=
sharedPrefs
.
getSubscriptionId
();
if
(
subscriptionId
!=
0
)
{
return
deleteSubscription
(
subscriptionId
).
then
((
voidResult
)
{
FirebaseMessaging
.
instance
.
deleteToken
();
sharedPrefs
.
saveSubscriptionId
(
0
);
});
}
return
Future
.
value
();
}).
catchError
((
onError
)
{
log
(
'[unsubscribe] ERROR:
$onError
'
,
PushNotificationsManager
.
TAG
);
});
}
Future
<
dynamic
>
onDidReceiveLocalNotification
(
int
id
,
String
?
title
,
String
?
body
,
String
?
payload
)
{
log
(
'[onDidReceiveLocalNotification] id:
$id
, title:
$title
, body:
$body
, payload:
$payload
'
,
PushNotificationsManager
.
TAG
);
return
Future
.
value
();
}
Future
<
dynamic
>
onSelectNotification
(
String
?
payload
)
{
log
(
'[onSelectNotification] payload:
$payload
'
,
PushNotificationsManager
.
TAG
);
onNotificationClicked
?.
call
(
payload
);
return
Future
.
value
();
}
}
showNotification
(
RemoteMessage
message
)
{
log
(
'[showNotification] message:
${message.data}
'
,
PushNotificationsManager
.
TAG
);
Map
<
String
,
dynamic
>
data
=
message
.
data
;
NotificationDetails
buildNotificationDetails
(
int
?
badge
,
String
threadIdentifier
,
)
{
final
DarwinNotificationDetails
darwinNotificationDetails
=
DarwinNotificationDetails
(
badgeNumber:
badge
,
threadIdentifier:
threadIdentifier
,
);
final
AndroidNotificationDetails
androidPlatformChannelSpecifics
=
AndroidNotificationDetails
(
'messages_channel_id'
,
'Chat messages'
,
channelDescription:
'Chat messages will be received here'
,
importance:
Importance
.
max
,
priority:
Priority
.
high
,
showWhen:
true
,
color:
Colors
.
green
,
);
return
NotificationDetails
(
android:
androidPlatformChannelSpecifics
,
iOS:
darwinNotificationDetails
,
macOS:
darwinNotificationDetails
);
}
var
badge
=
int
.
tryParse
(
data
[
'badge'
].
toString
());
var
threadId
=
data
[
'ios_thread_id'
]
??
data
[
'dialog_id'
]
??
'ios_thread_id'
;
FlutterLocalNotificationsPlugin
().
show
(
6543
,
"Chat sample"
,
data
[
'message'
].
toString
(),
buildNotificationDetails
(
badge
,
threadId
),
payload:
jsonEncode
(
data
),
);
}
@pragma
(
'vm:entry-point'
)
Future
<
void
>
onBackgroundMessage
(
RemoteMessage
message
)
async
{
log
(
'[onBackgroundMessage] message:
${message.data}
'
,
PushNotificationsManager
.
TAG
);
showNotification
(
message
);
if
(!
Platform
.
isIOS
)
{
updateBadgeCount
(
int
.
tryParse
(
message
.
data
[
'badge'
].
toString
()));
}
return
Future
.
value
();
}
Future
<
dynamic
>
onNotificationSelected
(
String
?
payload
,
BuildContext
?
context
)
{
log
(
'[onSelectNotification] payload:
$payload
'
,
PushNotificationsManager
.
TAG
);
if
(
context
==
null
)
return
Future
.
value
();
log
(
'[onSelectNotification] context != null'
,
PushNotificationsManager
.
TAG
);
if
(
payload
!=
null
)
{
return
SharedPrefs
.
instance
.
init
().
then
((
sharedPrefs
)
{
CubeUser
?
user
=
sharedPrefs
.
getUser
();
Map
<
String
,
dynamic
>
payloadObject
=
jsonDecode
(
payload
);
String
?
dialogId
=
payloadObject
[
'dialog_id'
];
log
(
"[onSelectNotification] dialog_id:
$dialogId
"
,
PushNotificationsManager
.
TAG
);
getDialogs
({
'id'
:
dialogId
}).
then
((
dialogs
)
{
if
(
dialogs
?.
items
!=
null
&&
dialogs
!.
items
.
isNotEmpty
)
{
CubeDialog
dialog
=
dialogs
.
items
.
first
;
Navigator
.
pushNamed
(
context
,
'chat_dialog'
,
arguments:
{
USER_ARG_NAME:
user
,
DIALOG_ARG_NAME:
dialog
});
}
});
});
}
else
{
return
Future
.
value
();
}
}
@pragma
(
'vm:entry-point'
)
void
notificationTapBackground
(
NotificationResponse
notificationResponse
)
{
log
(
'[notificationTapBackground] payload:
${notificationResponse.payload}
'
);
}
lib/srcchat/phone_auth_flow.dart
deleted
100644 → 0
View file @
7831c56e
import
'package:firebase_ui_auth/firebase_ui_auth.dart'
;
import
'package:flutter/material.dart'
;
import
'package:universal_io/io.dart'
;
import
'package:connectycube_sdk/connectycube_sdk.dart'
;
import
'utils/consts.dart'
;
import
'utils/pref_util.dart'
;
import
'utils/route_utils.dart'
;
const
String
PHONE_INPUT_ROUTE_NAME
=
'PhoneInputScreen'
;
const
String
SMS_CODE_INPUT_ROUTE_NAME
=
'SMSCodeInputScreen'
;
class
VerifyPhoneNumber
extends
StatelessWidget
{
@override
Widget
build
(
BuildContext
context
)
{
return
Navigator
(
observers:
[
PhoneAuthRouteObserver
(
context
)],
key:
Navigation
.
verifyPhoneNavigation
,
onGenerateRoute:
(
RouteSettings
settings
)
{
return
PageRouteBuilder
(
reverseTransitionDuration:
Duration
(
milliseconds:
Platform
.
isIOS
?
1000
:
300
),
transitionsBuilder:
(
context
,
animation
,
secondaryAnimation
,
child
)
{
const
begin
=
Offset
(
0.0
,
1.0
);
const
end
=
Offset
.
zero
;
const
curve
=
Curves
.
ease
;
var
tween
=
Tween
(
begin:
begin
,
end:
end
).
chain
(
CurveTween
(
curve:
curve
));
return
SlideTransition
(
position:
animation
.
drive
(
tween
),
child:
child
,
);
},
settings:
RouteSettings
(
name:
PHONE_INPUT_ROUTE_NAME
),
pageBuilder:
(
context
,
animation
,
secondaryAnimation
)
=>
PhoneInputScreen
(
actions:
[
SMSCodeRequestedAction
((
ctx1
,
action
,
flowKey
,
phoneNumber
)
{
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
settings:
RouteSettings
(
name:
SMS_CODE_INPUT_ROUTE_NAME
),
builder:
(
ctx2
)
=>
SMSCodeInputScreen
(
flowKey:
flowKey
,
actions:
[
AuthStateChangeAction
<
SignedIn
>((
ctx3
,
state
)
{
log
(
'[AuthStateChangeAction] SignedIn'
);
state
.
user
?.
getIdToken
().
then
((
idToken
)
{
SharedPrefs
.
instance
.
saveLoginType
(
LoginType
.
phone
);
Navigator
.
of
(
ctx3
,
rootNavigator:
true
)
.
pushNamedAndRemoveUntil
(
'login'
,
(
route
)
=>
false
);
});
}),
AuthStateChangeAction
<
CredentialLinked
>((
ctx3
,
state
)
{
log
(
'[AuthStateChangeAction] CredentialLinked'
);
state
.
user
.
getIdToken
().
then
((
idToken
)
{
SharedPrefs
.
instance
.
saveLoginType
(
LoginType
.
phone
);
Navigator
.
of
(
ctx3
,
rootNavigator:
true
)
.
pushNamedAndRemoveUntil
(
'login'
,
(
route
)
=>
false
);
});
}),
AuthStateChangeAction
<
Uninitialized
>((
ctx3
,
state
)
{
log
(
'[AuthStateChangeAction] Uninitialized'
);
}),
AuthStateChangeAction
<
CredentialReceived
>(
(
ctx3
,
state
)
{
log
(
'[AuthStateChangeAction] CredentialReceived'
);
}),
AuthStateChangeAction
<
AuthFailed
>((
ctx3
,
state
)
{
log
(
'[AuthStateChangeAction] AuthFailed'
);
}),
AuthStateChangeAction
<
UserCreated
>((
ctx3
,
state
)
{
log
(
'[AuthStateChangeAction] UserCreated'
);
state
.
credential
.
user
?.
getIdToken
().
then
((
idToken
)
{
SharedPrefs
.
instance
.
saveLoginType
(
LoginType
.
phone
);
Navigator
.
of
(
ctx3
,
rootNavigator:
true
)
.
pushNamedAndRemoveUntil
(
'login'
,
(
route
)
=>
false
);
});
}),
],
),
),
);
}),
],
),
);
},
);
}
}
class
PhoneAuthRouteObserver
extends
RouteObserver
{
final
BuildContext
context
;
PhoneAuthRouteObserver
(
this
.
context
);
@override
void
didPop
(
Route
route
,
Route
?
previousRoute
)
{
super
.
didPop
(
route
,
previousRoute
);
if
(
route
.
settings
.
name
==
PHONE_INPUT_ROUTE_NAME
)
{
Navigator
.
of
(
context
,
rootNavigator:
true
).
pop
();
}
}
}
lib/srcchat/settings_screen.dart
View file @
3103d00c
...
...
@@ -7,13 +7,13 @@ import 'package:vmeeting/service/routes/routes_name.dart';
import
'package:vmeeting/src/extension/context_extensions.dart'
;
import
'../app_models/app_users_model/app_users_model.dart'
;
import
'../src/constants/colors_const.dart'
;
import
'../src/managers/push_notifications_manager.dart'
;
import
'../src/utils/app_utils.dart'
;
import
'../src/utils/pref_util.dart'
;
import
'../src/widgets/image_avatar.dart'
;
import
'../src/widgets/textfiled_widgets/auth_text_fild.dart'
;
import
'managers/push_notifications_manager.dart'
;
import
'utils/api_utils.dart'
;
import
'utils/consts.dart'
;
import
'utils/pref_util.dart'
;
class
SettingsScreen
extends
StatelessWidget
{
final
CubeUser
currentUser
;
...
...
@@ -339,7 +339,7 @@ class _BodyLayoutState extends State<BodyLayout> {
CubeChatConnection
.
instance
.
destroy
();
PushNotificationsManager
.
instance
.
unsubscribe
();
FirebaseAuth
.
instance
.
currentUser
?.
unlink
(
PhoneAuthProvider
.
PROVIDER_ID
);
SharedPrefs
.
instance
.
deleteUser
();
SharedPrefs
.
deleteUserData
();
Navigator
.
pop
(
context
);
// cancel current screen
_navigateToLoginScreen
(
context
);
});
...
...
@@ -394,7 +394,7 @@ class _BodyLayoutState extends State<BodyLayout> {
}
_navigateToLoginScreen
(
BuildContext
context
)
{
SharedPrefs
.
instance
.
deleteUser
();
SharedPrefs
.
deleteUserData
();
Navigator
.
pushReplacementNamed
(
context
,
MainRoutes
.
sign_in_page
);
}
...
...
lib/srcchat/utils/api_utils.dart
View file @
3103d00c
import
'dart:async'
;
import
'dart:collection'
;
import
'package:connectycube_sdk/connectycube_chat.dart'
;
import
'package:connectycube_sdk/connectycube_sdk.dart'
;
import
'package:file_picker/file_picker.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:universal_io/io.dart'
;
import
'../managers/push_notifications_manager.dart'
;
import
'platform_utils.dart'
;
void
showDialogError
(
exception
,
context
)
{
...
...
@@ -16,11 +13,11 @@ void showDialogError(exception, context) {
context:
context
,
builder:
(
BuildContext
context
)
{
return
AlertDialog
(
title:
Text
(
"Error"
),
title:
const
Text
(
"Error"
),
content:
Text
(
"Something went wrong
$exception
"
),
actions:
<
Widget
>[
TextButton
(
child:
Text
(
"OK"
),
child:
const
Text
(
"OK"
),
onPressed:
()
=>
Navigator
.
of
(
context
).
pop
(),
)
],
...
...
@@ -33,11 +30,11 @@ void showDialogMsg(msg, context) {
context:
context
,
builder:
(
BuildContext
context
)
{
return
AlertDialog
(
title:
Text
(
"Alert"
),
title:
const
Text
(
"Alert"
),
content:
Text
(
msg
),
actions:
<
Widget
>[
TextButton
(
child:
Text
(
"OK"
),
child:
const
Text
(
"OK"
),
onPressed:
()
=>
Navigator
.
of
(
context
).
pop
(),
)
],
...
...
@@ -68,7 +65,6 @@ Future<Map<int, CubeUser>> getUsersByIds(Set<int> ids) async {
Future
<
CubeFile
>
getUploadingImageFuture
(
FilePickerResult
result
)
async
{
// there possible to upload the file as an array of bytes, but here showed two ways just as an example
if
(
kIsWeb
){
return
uploadRawFile
(
result
.
files
.
single
.
bytes
!,
result
.
files
.
single
.
name
,
isPublic:
true
,
onProgress:
(
progress
)
{
log
(
"uploadImageFile progress=
$progress
"
);
...
...
lib/srcchat/utils/pref_util.dart
deleted
100644 → 0
View file @
7831c56e
import
'dart:async'
;
import
'package:collection/collection.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:shared_preferences/shared_preferences.dart'
;
import
'package:connectycube_sdk/connectycube_chat.dart'
;
import
'consts.dart'
;
const
String
prefLoginType
=
"pref_login_type"
;
const
String
prefUserLogin
=
"pref_user_login"
;
const
String
prefUserEmail
=
"pref_user_email"
;
const
String
prefUserPhone
=
"pref_user_phone"
;
const
String
prefUserPsw
=
"pref_user_psw"
;
const
String
prefUserName
=
"pref_user_name"
;
const
String
prefUserId
=
"pref_user_id"
;
const
String
prefUserAvatar
=
"pref_user_avatar"
;
const
String
prefSubscriptionToken
=
"pref_subscription_token"
;
const
String
prefSubscriptionId
=
"pref_subscription_id"
;
const
String
prefSelectedDialogId
=
"pref_selected_dialog_id"
;
class
SharedPrefs
{
static
final
SharedPrefs
_instance
=
SharedPrefs
.
_internal
();
late
SharedPreferences
prefs
;
SharedPrefs
.
_internal
();
bool
inited
=
false
;
static
SharedPrefs
get
instance
=>
_instance
;
Future
<
SharedPrefs
>
init
()
async
{
Completer
<
SharedPrefs
>
completer
=
Completer
();
if
(
inited
)
{
completer
.
complete
(
_instance
);
}
else
{
prefs
=
await
SharedPreferences
.
getInstance
();
inited
=
true
;
completer
.
complete
(
_instance
);
}
return
completer
.
future
;
}
saveNewUser
(
CubeUser
cubeUser
,
LoginType
loginType
)
{
prefs
.
clear
();
prefs
.
setString
(
prefLoginType
,
describeEnum
(
loginType
));
if
(
cubeUser
.
login
!=
null
)
prefs
.
setString
(
prefUserLogin
,
cubeUser
.
login
!);
if
(
cubeUser
.
email
!=
null
)
prefs
.
setString
(
prefUserEmail
,
cubeUser
.
email
!);
if
(
cubeUser
.
phone
!=
null
)
prefs
.
setString
(
prefUserPhone
,
cubeUser
.
phone
!);
if
(
cubeUser
.
password
!=
null
)
prefs
.
setString
(
prefUserPsw
,
cubeUser
.
password
!);
if
(
cubeUser
.
fullName
!=
null
)
prefs
.
setString
(
prefUserName
,
cubeUser
.
fullName
!);
prefs
.
setInt
(
prefUserId
,
cubeUser
.
id
!);
if
(
cubeUser
.
avatar
!=
null
)
prefs
.
setString
(
prefUserAvatar
,
cubeUser
.
avatar
!);
}
updateUser
(
CubeUser
cubeUser
)
{
if
(
cubeUser
.
password
!=
null
)
prefs
.
setString
(
prefUserPsw
,
cubeUser
.
password
!);
if
(
cubeUser
.
login
!=
null
)
prefs
.
setString
(
prefUserLogin
,
cubeUser
.
login
!);
if
(
cubeUser
.
email
!=
null
)
prefs
.
setString
(
prefUserEmail
,
cubeUser
.
email
!);
if
(
cubeUser
.
phone
!=
null
)
prefs
.
setString
(
prefUserPhone
,
cubeUser
.
phone
!);
if
(
cubeUser
.
fullName
!=
null
)
prefs
.
setString
(
prefUserName
,
cubeUser
.
fullName
!);
if
(
cubeUser
.
avatar
!=
null
)
prefs
.
setString
(
prefUserAvatar
,
cubeUser
.
avatar
!);
}
CubeUser
?
getUser
()
{
if
(
prefs
.
getString
(
prefUserLogin
)
==
null
&&
prefs
.
getString
(
prefUserEmail
)
==
null
)
return
null
;
var
user
=
CubeUser
();
user
.
login
=
prefs
.
getString
(
prefUserLogin
);
user
.
email
=
prefs
.
getString
(
prefUserEmail
);
user
.
phone
=
prefs
.
getString
(
prefUserPhone
);
user
.
password
=
prefs
.
getString
(
prefUserPsw
);
user
.
fullName
=
prefs
.
getString
(
prefUserName
);
user
.
id
=
prefs
.
getInt
(
prefUserId
);
user
.
avatar
=
prefs
.
getString
(
prefUserAvatar
);
return
user
;
}
LoginType
?
getLoginType
()
{
var
savedLoginType
=
prefs
.
getString
(
prefLoginType
);
if
(
savedLoginType
==
null
)
return
null
;
var
loginType
=
LoginType
.
values
.
firstWhereOrNull
((
e
)
=>
describeEnum
(
e
)
==
savedLoginType
);
return
loginType
;
}
saveLoginType
(
LoginType
loginType
)
{
prefs
.
setString
(
prefLoginType
,
describeEnum
(
loginType
));
}
Future
<
bool
>
deleteUser
()
{
return
prefs
.
clear
();
}
saveSubscriptionToken
(
String
token
)
{
prefs
.
setString
(
prefSubscriptionToken
,
token
);
}
String
getSubscriptionToken
()
{
return
prefs
.
getString
(
prefSubscriptionToken
)
??
""
;
}
saveSubscriptionId
(
int
id
)
{
prefs
.
setInt
(
prefSubscriptionId
,
id
);
}
int
getSubscriptionId
()
{
return
prefs
.
getInt
(
prefSubscriptionId
)
??
0
;
}
saveSelectedDialogId
(
String
dialogId
)
{
prefs
.
setString
(
prefSelectedDialogId
,
dialogId
);
}
String
?
getSelectedDialogId
()
{
return
prefs
.
getString
(
prefSelectedDialogId
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment