Skip to content

Commit

Permalink
Merge pull request #87 from mediocre9/development
Browse files Browse the repository at this point in the history
implemented feedback feature and bug fixes
  • Loading branch information
mediocre9 authored Oct 24, 2023
2 parents 0a0a1a5 + 4164af3 commit 6325944
Show file tree
Hide file tree
Showing 23 changed files with 615 additions and 206 deletions.
22 changes: 18 additions & 4 deletions lib/config/router/route_generator.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import 'package:flutter/cupertino.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:smart_link/config/router/index.dart';
import 'package:smart_link/screens/authentication_screen/cubit/authentication_screen_cubit.dart';
import 'package:smart_link/screens/feedback_screen/cubit/feedback_cubit.dart';
import 'package:smart_link/screens/feedback_screen/feedback_screen.dart';
import 'package:smart_link/services/auth_service.dart';
import 'package:smart_link/services/bluetooth_service.dart';
import 'package:smart_link/services/feedback_service.dart';
import 'package:smart_link/services/permission_service.dart';
import '../../screens/wifi_home_screen/cubit/wifi_home_cubit.dart';

Expand All @@ -31,8 +34,8 @@ class RouteGenerator {
BlocProvider(
lazy: false,
create: (_) => BluetoothHomeCubit(
BluetoothPermissionService(),
BluetoothService(FlutterBluetoothSerial.instance),
permission: BluetoothPermissionService(),
bluetooth: BluetoothService(FlutterBluetoothSerial.instance),
),
child: const BluetoothHomeScreen(),
),
Expand Down Expand Up @@ -65,6 +68,17 @@ class RouteGenerator {
),
);

case Routes.feedback:
return _pageTransition(
BlocProvider(
create: (_) => FeedbackCubit(
feedbackService: FeedbackService(firestore: FirebaseFirestore.instance),
service: AuthenticationService(),
),
child: const FeedbackScreen(),
),
);

case Routes.biometric:
return _pageTransition(const BiometricScreen());

Expand All @@ -73,7 +87,7 @@ class RouteGenerator {
}
}

static _pageTransition(Widget route) => CupertinoPageRoute(builder: (_) => route);
static _pageTransition(Widget route) => MaterialPageRoute(builder: (_) => route);

static _defaultRoute() {
return const Scaffold(
Expand Down
8 changes: 8 additions & 0 deletions lib/config/router/routes.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
class Routes {
Routes._();

static const String auth = '/';

static const String bluetoothHome = '/bluetoothHome';

static const String bluetoothRemote = '/bluetoothRemote';

static const String wifiHome = '/wifiHome';

static const String wifiRemote = '/wifiRemote';

static const String biometric = '/biometric';

static const String feedback = '/feedback';
}
58 changes: 42 additions & 16 deletions lib/config/strings/strings.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,53 @@
class Strings {
Strings._();

static const String appName = 'Smart Link';
static const String appVersion = 'v0.5.2';
static const String appDescription = 'IoT Remote Control';
static const String appLogo = 'assets/images/logo.png';
static const String bluetoothOnHomeDescription = 'Scan for bluetooth devices';
static const String bluetoothDiscoveryDescription = 'This may take a few moments to discover nearby devices. Please be patient!';
static const String gettingPairedDevices = 'Getting paired devices . . .';
static const String pairUnsuccessful = "";
static const String noInternet = 'No Internet Connection!';
static const String bluetoothOff = 'Bluetooth service is off.';
static const String devicesNotInRange = 'No nearby device(s) available. Try Again!';
static const String copyright = '(c) Copyright 2023 CUSIT IT & Robotics Engineering Society. All rights reserved.';
static const String appName = "Smart Link";

static const String appVersion = "v0.6.1";

static const String appDescription = "IoT Remote Control";

static const String appLogo = "assets/images/logo.png";

static const String copyright = "(c) Copyright 2023 CUSIT IT & Robotics Society. All rights reserved.";

static const String permissionInfo = "Allow Smart Link to access Bluetooth and Location permissions on this device?";

static const String noInternet = "Unable to connect to the internet.";

static const String bluetoothOnHomeDescription = "Scan for bluetooth devices";

static const String bluetoothDiscoveryDescription = "This may take a few moments to discover nearby devices. Please be patient!";

static const String gettingPairedDevices = "Getting paired devices . . .";

static const String bluetoothOff = "Bluetooth is disabled!";

static const String bluetoothConnected = "Connected!";

static const String bluetoothDisconnected = "Disconnected!";

static const String endDeviceNotResponding = "End device not responding!";

static const String devicesNotInRange = "No nearby devices are available. Try Again!";

static const String feedbackPosted = "Thank you for your valuable feedback!";

static const String biometricLock = "Locked out due to too many attempts!";

static const String biometricPermanent = "Locked out permanently due to too many attempts!";

static const String biometricEnrollment = "Please register your fingerprint from your device settings!";

static const String biometricNotSupported = "Your device does not have fingerprint support!";

static const String microControllerIp = "192.168.4.1";

static const String userBlocked = 'Your account has been blocked.';
static const String googleLogoPath = 'assets/images/google_logo.png';
static const String radarAnimationPath = 'assets/animations/radar.json';
static const String signinButtonText = 'Sign in with Google';
static const String userBlocked = "Account access revoked. Contact support.";

static const String googleLogoPath = "assets/images/google_logo.png";

static const String radarAnimationPath = "assets/animations/radar.json";

static const String signinButtonText = "Sign in with Google";
}
4 changes: 2 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ class SmartLinkApp extends StatelessWidget {
return MaterialApp(
title: Strings.appName,
color: AppColors.primary,
initialRoute: kDebugMode ? Routes.bluetoothHome : Routes.auth,
theme: AppTheme.darkTheme(),
onGenerateRoute: RouteGenerator.generate,
initialRoute: kDebugMode ? Routes.bluetoothHome : Routes.auth,
debugShowCheckedModeBanner: kDebugMode ? true : false,
theme: AppTheme.darkTheme(),
);
}
}
5 changes: 5 additions & 0 deletions lib/models/model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
abstract class Model {
final String? id;

Model({required this.id});
}
40 changes: 40 additions & 0 deletions lib/models/user_feedback_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:smart_link/models/model.dart';

final class UserFeedback extends Model {
final String email;
final String username;
final String subject;
final String body;
final DateTime submittedDate;

UserFeedback({
required super.id,
required this.email,
required this.username,
required this.subject,
required this.body,
required this.submittedDate,
});

factory UserFeedback.fromJSON(Map<String, dynamic> data) {
return UserFeedback(
id: data["userId"],
email: data["email"],
username: data["username"],
subject: data["subject"],
body: data["body"],
submittedDate: data["submittedDate"],
);
}

Map<String, dynamic> toJSON() {
return {
"userId": id,
"username": username,
"submittedDate": submittedDate,
"email": email,
"subject": subject,
"body": body,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,28 @@ class AuthenticationScreenCubit extends Cubit<AuthenticationScreenState> {
if (!await _isInternetAvailable()) {
emit(NoInternet(message: Strings.noInternet));
emit(Initial());
} else {
emit(Loading());

SignInState state = await authService.signIn();

switch (state) {
case SignInState.disabled:
emit(UserBlocked(message: Strings.userBlocked));
emit(Initial());
break;
default:
emit(Authenticated(
user: authService.getCurrentUser!,
message: 'Signed in as ${authService.getCurrentUser!.email}',
));
}
return;
}

emit(Loading());

SignInState state = await authService.signIn();

switch (state) {
case SignInState.disabled:
emit(UserBlocked(message: Strings.userBlocked));
emit(Initial());
break;

case SignInState.authenticated:
emit(Authenticated(
user: authService.getCurrentUser!,
message: 'Signed in as ${authService.getCurrentUser!.email}',
));
break;

default:
emit(Initial());
}
}
}
9 changes: 7 additions & 2 deletions lib/screens/biometric_screen/fingerprint_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:local_auth/local_auth.dart';
import 'package:smart_link/config/colors/app_colors.dart';
import 'package:smart_link/config/router/routes.dart';
import 'package:smart_link/config/strings/strings.dart';
import 'package:smart_link/widgets/common.dart';
import '../../widgets/app_drawer.dart';
Expand Down Expand Up @@ -95,9 +96,13 @@ class _BiometricScreenState extends State<BiometricScreen> with StandardAppWidge
title: const Text("Fingerprint"),
actions: [
IconButton(
onPressed: () => showAboutDialogWidget(context),
icon: const Icon(Icons.bug_report_rounded),
onPressed: () => Navigator.pushNamed(context, Routes.feedback),
),
IconButton(
icon: const Icon(Icons.info_outline_rounded),
)
onPressed: () => showAboutDialogWidget(context),
),
],
),
drawer: AppDrawer(),
Expand Down
39 changes: 35 additions & 4 deletions lib/screens/bluetooth_home_screen/bluetooth_home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ import 'cubit/bluetooth_home_cubit.dart';

class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
const BluetoothHomeScreen({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Bluetooth Home"),
actions: [
IconButton(
icon: const Icon(Icons.bug_report_rounded),
onPressed: () => Navigator.pushNamed(context, Routes.feedback),
),
IconButton(
icon: const Icon(Icons.info_outline_rounded),
onPressed: () => showAboutDialogWidget(context),
)
),
],
),
drawer: AppDrawer(),
Expand Down Expand Up @@ -57,7 +60,7 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
},
);

case DiscoverDevices():
case ScanAnimation():
return FloatingActionButton(
child: const Icon(Icons.pause),
onPressed: () {
Expand All @@ -72,6 +75,31 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {

void _blocListeners(BuildContext context, BluetoothHomeState state) {
switch (state) {
case GrantPermissions():
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: const Text("Permission Access"),
content: Text(state.message),
actions: [
TextButton(
child: const Text("Deny"),
onPressed: () => Navigator.pop(context),
),
TextButton(
child: const Text("Allow"),
onPressed: () {
context.read<BluetoothHomeCubit>().openSettings();
Navigator.pop(context);
},
),
],
);
},
);
break;

case BluetoothDisabled():
showSnackBarWidget(context, state.message);
break;
Expand Down Expand Up @@ -118,9 +146,11 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {

case ShowPairedDevices():
return DevicesListView(devices: state.devices);

case ShowDiscoveredDevices():
return DevicesListView(devices: state.devices);
case DiscoverDevices():

case ScanAnimation():
return RadarAnimation(text: state.text);

case PairDevice():
Expand All @@ -137,6 +167,7 @@ class BluetoothHomeScreen extends StatelessWidget with StandardAppWidgets {
],
),
);

default:
return Container();
}
Expand Down
Loading

0 comments on commit 6325944

Please sign in to comment.