Skip to content

Commit 6325944

Browse files
authored
Merge pull request #87 from mediocre9/development
implemented feedback feature and bug fixes
2 parents 0a0a1a5 + 4164af3 commit 6325944

23 files changed

+615
-206
lines changed

lib/config/router/route_generator.dart

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import 'package:flutter/cupertino.dart';
1+
import 'package:cloud_firestore/cloud_firestore.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter_bloc/flutter_bloc.dart';
44
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
55
import 'package:smart_link/config/router/index.dart';
66
import 'package:smart_link/screens/authentication_screen/cubit/authentication_screen_cubit.dart';
7+
import 'package:smart_link/screens/feedback_screen/cubit/feedback_cubit.dart';
8+
import 'package:smart_link/screens/feedback_screen/feedback_screen.dart';
79
import 'package:smart_link/services/auth_service.dart';
810
import 'package:smart_link/services/bluetooth_service.dart';
11+
import 'package:smart_link/services/feedback_service.dart';
912
import 'package:smart_link/services/permission_service.dart';
1013
import '../../screens/wifi_home_screen/cubit/wifi_home_cubit.dart';
1114

@@ -31,8 +34,8 @@ class RouteGenerator {
3134
BlocProvider(
3235
lazy: false,
3336
create: (_) => BluetoothHomeCubit(
34-
BluetoothPermissionService(),
35-
BluetoothService(FlutterBluetoothSerial.instance),
37+
permission: BluetoothPermissionService(),
38+
bluetooth: BluetoothService(FlutterBluetoothSerial.instance),
3639
),
3740
child: const BluetoothHomeScreen(),
3841
),
@@ -65,6 +68,17 @@ class RouteGenerator {
6568
),
6669
);
6770

71+
case Routes.feedback:
72+
return _pageTransition(
73+
BlocProvider(
74+
create: (_) => FeedbackCubit(
75+
feedbackService: FeedbackService(firestore: FirebaseFirestore.instance),
76+
service: AuthenticationService(),
77+
),
78+
child: const FeedbackScreen(),
79+
),
80+
);
81+
6882
case Routes.biometric:
6983
return _pageTransition(const BiometricScreen());
7084

@@ -73,7 +87,7 @@ class RouteGenerator {
7387
}
7488
}
7589

76-
static _pageTransition(Widget route) => CupertinoPageRoute(builder: (_) => route);
90+
static _pageTransition(Widget route) => MaterialPageRoute(builder: (_) => route);
7791

7892
static _defaultRoute() {
7993
return const Scaffold(

lib/config/router/routes.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
class Routes {
22
Routes._();
3+
34
static const String auth = '/';
5+
46
static const String bluetoothHome = '/bluetoothHome';
7+
58
static const String bluetoothRemote = '/bluetoothRemote';
9+
610
static const String wifiHome = '/wifiHome';
11+
712
static const String wifiRemote = '/wifiRemote';
13+
814
static const String biometric = '/biometric';
15+
16+
static const String feedback = '/feedback';
917
}

lib/config/strings/strings.dart

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,53 @@
11
class Strings {
22
Strings._();
33

4-
static const String appName = 'Smart Link';
5-
static const String appVersion = 'v0.5.2';
6-
static const String appDescription = 'IoT Remote Control';
7-
static const String appLogo = 'assets/images/logo.png';
8-
static const String bluetoothOnHomeDescription = 'Scan for bluetooth devices';
9-
static const String bluetoothDiscoveryDescription = 'This may take a few moments to discover nearby devices. Please be patient!';
10-
static const String gettingPairedDevices = 'Getting paired devices . . .';
11-
static const String pairUnsuccessful = "";
12-
static const String noInternet = 'No Internet Connection!';
13-
static const String bluetoothOff = 'Bluetooth service is off.';
14-
static const String devicesNotInRange = 'No nearby device(s) available. Try Again!';
15-
static const String copyright = '(c) Copyright 2023 CUSIT IT & Robotics Engineering Society. All rights reserved.';
4+
static const String appName = "Smart Link";
5+
6+
static const String appVersion = "v0.6.1";
7+
8+
static const String appDescription = "IoT Remote Control";
9+
10+
static const String appLogo = "assets/images/logo.png";
11+
12+
static const String copyright = "(c) Copyright 2023 CUSIT IT & Robotics Society. All rights reserved.";
13+
14+
static const String permissionInfo = "Allow Smart Link to access Bluetooth and Location permissions on this device?";
15+
16+
static const String noInternet = "Unable to connect to the internet.";
17+
18+
static const String bluetoothOnHomeDescription = "Scan for bluetooth devices";
19+
20+
static const String bluetoothDiscoveryDescription = "This may take a few moments to discover nearby devices. Please be patient!";
21+
22+
static const String gettingPairedDevices = "Getting paired devices . . .";
23+
24+
static const String bluetoothOff = "Bluetooth is disabled!";
25+
26+
static const String bluetoothConnected = "Connected!";
27+
28+
static const String bluetoothDisconnected = "Disconnected!";
29+
30+
static const String endDeviceNotResponding = "End device not responding!";
31+
32+
static const String devicesNotInRange = "No nearby devices are available. Try Again!";
33+
34+
static const String feedbackPosted = "Thank you for your valuable feedback!";
1635

1736
static const String biometricLock = "Locked out due to too many attempts!";
37+
1838
static const String biometricPermanent = "Locked out permanently due to too many attempts!";
39+
1940
static const String biometricEnrollment = "Please register your fingerprint from your device settings!";
41+
2042
static const String biometricNotSupported = "Your device does not have fingerprint support!";
43+
2144
static const String microControllerIp = "192.168.4.1";
2245

23-
static const String userBlocked = 'Your account has been blocked.';
24-
static const String googleLogoPath = 'assets/images/google_logo.png';
25-
static const String radarAnimationPath = 'assets/animations/radar.json';
26-
static const String signinButtonText = 'Sign in with Google';
46+
static const String userBlocked = "Account access revoked. Contact support.";
47+
48+
static const String googleLogoPath = "assets/images/google_logo.png";
49+
50+
static const String radarAnimationPath = "assets/animations/radar.json";
51+
52+
static const String signinButtonText = "Sign in with Google";
2753
}

lib/main.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ class SmartLinkApp extends StatelessWidget {
3232
return MaterialApp(
3333
title: Strings.appName,
3434
color: AppColors.primary,
35-
initialRoute: kDebugMode ? Routes.bluetoothHome : Routes.auth,
35+
theme: AppTheme.darkTheme(),
3636
onGenerateRoute: RouteGenerator.generate,
37+
initialRoute: kDebugMode ? Routes.bluetoothHome : Routes.auth,
3738
debugShowCheckedModeBanner: kDebugMode ? true : false,
38-
theme: AppTheme.darkTheme(),
3939
);
4040
}
4141
}

lib/models/model.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
abstract class Model {
2+
final String? id;
3+
4+
Model({required this.id});
5+
}

lib/models/user_feedback_model.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import 'package:smart_link/models/model.dart';
2+
3+
final class UserFeedback extends Model {
4+
final String email;
5+
final String username;
6+
final String subject;
7+
final String body;
8+
final DateTime submittedDate;
9+
10+
UserFeedback({
11+
required super.id,
12+
required this.email,
13+
required this.username,
14+
required this.subject,
15+
required this.body,
16+
required this.submittedDate,
17+
});
18+
19+
factory UserFeedback.fromJSON(Map<String, dynamic> data) {
20+
return UserFeedback(
21+
id: data["userId"],
22+
email: data["email"],
23+
username: data["username"],
24+
subject: data["subject"],
25+
body: data["body"],
26+
submittedDate: data["submittedDate"],
27+
);
28+
}
29+
30+
Map<String, dynamic> toJSON() {
31+
return {
32+
"userId": id,
33+
"username": username,
34+
"submittedDate": submittedDate,
35+
"email": email,
36+
"subject": subject,
37+
"body": body,
38+
};
39+
}
40+
}

lib/screens/authentication_screen/cubit/authentication_screen_cubit.dart

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,28 @@ class AuthenticationScreenCubit extends Cubit<AuthenticationScreenState> {
2626
if (!await _isInternetAvailable()) {
2727
emit(NoInternet(message: Strings.noInternet));
2828
emit(Initial());
29-
} else {
30-
emit(Loading());
31-
32-
SignInState state = await authService.signIn();
33-
34-
switch (state) {
35-
case SignInState.disabled:
36-
emit(UserBlocked(message: Strings.userBlocked));
37-
emit(Initial());
38-
break;
39-
default:
40-
emit(Authenticated(
41-
user: authService.getCurrentUser!,
42-
message: 'Signed in as ${authService.getCurrentUser!.email}',
43-
));
44-
}
29+
return;
30+
}
31+
32+
emit(Loading());
33+
34+
SignInState state = await authService.signIn();
35+
36+
switch (state) {
37+
case SignInState.disabled:
38+
emit(UserBlocked(message: Strings.userBlocked));
39+
emit(Initial());
40+
break;
41+
42+
case SignInState.authenticated:
43+
emit(Authenticated(
44+
user: authService.getCurrentUser!,
45+
message: 'Signed in as ${authService.getCurrentUser!.email}',
46+
));
47+
break;
48+
49+
default:
50+
emit(Initial());
4551
}
4652
}
4753
}

lib/screens/biometric_screen/fingerprint_screen.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
55
import 'package:flutter/services.dart';
66
import 'package:local_auth/local_auth.dart';
77
import 'package:smart_link/config/colors/app_colors.dart';
8+
import 'package:smart_link/config/router/routes.dart';
89
import 'package:smart_link/config/strings/strings.dart';
910
import 'package:smart_link/widgets/common.dart';
1011
import '../../widgets/app_drawer.dart';
@@ -95,9 +96,13 @@ class _BiometricScreenState extends State<BiometricScreen> with StandardAppWidge
9596
title: const Text("Fingerprint"),
9697
actions: [
9798
IconButton(
98-
onPressed: () => showAboutDialogWidget(context),
99+
icon: const Icon(Icons.bug_report_rounded),
100+
onPressed: () => Navigator.pushNamed(context, Routes.feedback),
101+
),
102+
IconButton(
99103
icon: const Icon(Icons.info_outline_rounded),
100-
)
104+
onPressed: () => showAboutDialogWidget(context),
105+
),
101106
],
102107
),
103108
drawer: AppDrawer(),

lib/screens/bluetooth_home_screen/bluetooth_home_screen.dart

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@ import 'cubit/bluetooth_home_cubit.dart';
1010

1111
class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
1212
const BluetoothHomeScreen({super.key});
13-
1413
@override
1514
Widget build(BuildContext context) {
1615
return Scaffold(
1716
appBar: AppBar(
1817
title: const Text("Bluetooth Home"),
1918
actions: [
19+
IconButton(
20+
icon: const Icon(Icons.bug_report_rounded),
21+
onPressed: () => Navigator.pushNamed(context, Routes.feedback),
22+
),
2023
IconButton(
2124
icon: const Icon(Icons.info_outline_rounded),
2225
onPressed: () => showAboutDialogWidget(context),
23-
)
26+
),
2427
],
2528
),
2629
drawer: AppDrawer(),
@@ -57,7 +60,7 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
5760
},
5861
);
5962

60-
case DiscoverDevices():
63+
case ScanAnimation():
6164
return FloatingActionButton(
6265
child: const Icon(Icons.pause),
6366
onPressed: () {
@@ -72,6 +75,31 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
7275

7376
void _blocListeners(BuildContext context, BluetoothHomeState state) {
7477
switch (state) {
78+
case GrantPermissions():
79+
showDialog(
80+
context: context,
81+
builder: (_) {
82+
return AlertDialog(
83+
title: const Text("Permission Access"),
84+
content: Text(state.message),
85+
actions: [
86+
TextButton(
87+
child: const Text("Deny"),
88+
onPressed: () => Navigator.pop(context),
89+
),
90+
TextButton(
91+
child: const Text("Allow"),
92+
onPressed: () {
93+
context.read<BluetoothHomeCubit>().openSettings();
94+
Navigator.pop(context);
95+
},
96+
),
97+
],
98+
);
99+
},
100+
);
101+
break;
102+
75103
case BluetoothDisabled():
76104
showSnackBarWidget(context, state.message);
77105
break;
@@ -118,9 +146,11 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
118146

119147
case ShowPairedDevices():
120148
return DevicesListView(devices: state.devices);
149+
121150
case ShowDiscoveredDevices():
122151
return DevicesListView(devices: state.devices);
123-
case DiscoverDevices():
152+
153+
case ScanAnimation():
124154
return RadarAnimation(text: state.text);
125155

126156
case PairDevice():
@@ -137,6 +167,7 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
137167
],
138168
),
139169
);
170+
140171
default:
141172
return Container();
142173
}

0 commit comments

Comments
 (0)