Skip to content

Commit

Permalink
Bug fixes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
venkatbalajim committed Mar 7, 2024
1 parent a6cc1e7 commit 64b90b3
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 52 deletions.
15 changes: 15 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'utils/imports.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
ChangeNotifierProvider(
create: (_) => ThemeProvider(),
Expand All @@ -14,6 +15,8 @@ class MyApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
_requestPermissions();

return MaterialApp(
title: 'QR Hub',
debugShowCheckedModeBanner: false,
Expand All @@ -30,4 +33,16 @@ class MyApp extends StatelessWidget {
home: const HomePage(),
);
}

Future<void> _requestPermissions() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.camera,
Permission.storage,
].request();

if (statuses[Permission.camera] != PermissionStatus.granted ||
statuses[Permission.storage] != PermissionStatus.granted) {

}
}
}
8 changes: 5 additions & 3 deletions lib/pages/generator_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class _GeneratorPageState extends State<GeneratorPage> {
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Empty Data'),
title: Text('Empty Data', style: Theme.of(context).textTheme.headlineMedium),
content: const Text('Kindly enter important data to generate QR Code.'),
actions: [
TextButton(
Expand Down Expand Up @@ -376,7 +376,9 @@ END:VEVENT
value: selectedEncryption,
onChanged: (String? newValue) {
if (newValue != null) {
selectedEncryption = newValue;
setState(() {
selectedEncryption = newValue;
});
}
},
items: wifiEncryptionOptions.map((String option) {
Expand All @@ -395,7 +397,7 @@ END:VEVENT
child: CustomTextButton(
buttonName: 'Generate QR Code',
onPressed: () {
if (qrDataController.text.isEmpty || subjectController.text.isEmpty) {
if (qrDataController.text.isEmpty) {
showEmptyDataDialog(context);
} else {
setState(() {
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/history_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ ${data.qrCodeData}
context: context,
builder: (context) {
return AlertDialog(
title: Text("${data.dataType} QR Code"),
title: Text("${data.dataType} QR Code", style: Theme.of(context).textTheme.headlineMedium,),
content: Text(contentData),
actions: [
Row(
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class _HomePageState extends State<HomePage> {
Text(
"QR Hub",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium,
style: Theme.of(context).textTheme.headlineLarge,
),
const SizedBox(height: 20),
Text(
Expand Down
17 changes: 11 additions & 6 deletions lib/pages/result_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import '../utils/imports.dart';
class ResultPage extends StatefulWidget {
final Barcode value;
final Uint8List? image;
final MobileScannerController controller;
final Function()? screenClose;
final String? scannedDate;
final String? scannedTime;
Expand All @@ -12,7 +13,8 @@ class ResultPage extends StatefulWidget {
super.key,
required this.value, this.screenClose,
this.scannedDate, this.scannedTime,
this.dataType, required this.image
this.dataType, this.image,
required this.controller
});

@override
Expand All @@ -35,6 +37,8 @@ class _ResultPageState extends State<ResultPage> {
}

void parseData() {
ValueNotifier<TorchState> torchStatus = widget.controller.torchState;
if (torchStatus.value == TorchState.on) widget.controller.toggleTorch();
Barcode fetchData = widget.value;
value = fetchData;
result = value.rawValue;
Expand Down Expand Up @@ -116,11 +120,12 @@ class _ResultPageState extends State<ResultPage> {
const SizedBox(height: 20),
ResultContainer(data: value),
const SizedBox(height: 20),
SizedBox(
width: 250,
height: 250,
child: Image.memory(widget.image!),
)
if (widget.image != null)
SizedBox(
width: 250,
height: 250,
child: Image.memory(widget.image!),
)
],
),
)
Expand Down
1 change: 1 addition & 0 deletions lib/pages/scanner_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class _ScannerPageState extends State<ScannerPage> {

Navigator.push(context, MaterialPageRoute(
builder: (context) => ResultPage(
controller: cameraController,
value: code.barcodes.first,
screenClose: screenClosed,
image: image,
Expand Down
33 changes: 21 additions & 12 deletions lib/utils/download.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,26 @@ Future<void> downloadQRCode(
Uint8List? image = await screenshotController.capture();

if (image != null) {
String downloadDir = (await DownloadsPath.downloadsDirectory())!.path;
String appFolderName = "QR Hub";
String downloadFolder = "QR Codes";
String fileName = DateFormat('yyyyMMddTHHmmss').format(DateTime.now());
Directory directory = Directory('$downloadDir/$appFolderName/$downloadFolder');
if (!directory.existsSync()) {
directory.createSync();
if (await Permission.storage.isGranted) {
String downloadDir = (await DownloadsPath.downloadsDirectory())!.path;
String appFolderName = "QR Hub";
String downloadFolder = "QR Codes";
String fileName = DateFormat('yyyyMMddTHHmmss').format(DateTime.now());
Directory directory = Directory('$downloadDir/$appFolderName/$downloadFolder');
if (!directory.existsSync()) {
directory.createSync(recursive: true);
}
String filePath = "${directory.path}/$fileName.jpg";
await File(filePath).writeAsBytes(image)
.then((value) => SnackBarWidget(context, 'File downloaded successfully.\nFile directory: Download/QR Hub/QR Codes'));
} else if (await Permission.storage.isDenied) {
await Permission.storage.request();
if (await Permission.storage.isGranted) {
SnackBarWidget(context, 'Permission granted. Click the download button again.');
}
} else if (await Permission.storage.isPermanentlyDenied) {
SnackBarWidget(context, 'Storage Permission Denied. So, unable to download the history.');
}
String filePath = "${directory.path}/$fileName.jpg";
await File(filePath).writeAsBytes(image)
.then((value) => SnackBarWidget(context, 'File downloaded successfully.\nFile directory: Download/QR Hub/QR Codes'));
} else {
SnackBarWidget(context, 'Sorry, cannot able to fetch QR code image.');
}
Expand All @@ -46,7 +55,7 @@ Future<void> downloadHistory(BuildContext context, List<QRCodeData> historyList)
String appFolderName = "QR Hub";
Directory directory = Directory('$downloadDir/$appFolderName/History');
if (!directory.existsSync()) {
directory.createSync();
directory.createSync(recursive: true);
}
String fileName = DateFormat('yyyyMMddTHHmmss').format(DateTime.now());
String filePath = "${directory.path}/$fileName.txt";
Expand All @@ -60,7 +69,7 @@ Future<void> downloadHistory(BuildContext context, List<QRCodeData> historyList)
} else if (await Permission.storage.isDenied) {
await Permission.storage.request();
if (await Permission.storage.isGranted) {
SnackBarWidget(context, 'Permission granted. Click the download button again');
SnackBarWidget(context, 'Permission granted. Click the download button again.');
}
} else if (await Permission.storage.isPermanentlyDenied) {
SnackBarWidget(context, 'Storage Permission Denied. So, unable to download the history.');
Expand Down
45 changes: 19 additions & 26 deletions lib/utils/history.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class QRCodeData {
String scannedDate;
String scannedTime;
String dataType;
String qrCodeData;
String qrCodeData;

QRCodeData({
required this.scannedDate,
Expand All @@ -13,21 +13,21 @@ class QRCodeData {
required this.qrCodeData,
});

Map<String, dynamic> toJson() {
return {
'scan_date': scannedDate,
'scan_time': scannedTime,
'qr_code_type': dataType,
'qr_code_data': qrCodeData,
};
List<dynamic> toList() {
return [
scannedDate,
scannedTime,
dataType,
qrCodeData,
];
}

factory QRCodeData.fromJson(Map<String, dynamic> json) {
factory QRCodeData.fromList(List<dynamic> list) {
return QRCodeData(
scannedDate: json['scan_date'] ?? '',
scannedTime: json['scan_time'] ?? '',
dataType: json['qr_code_type'] ?? '',
qrCodeData: json['qr_code_data'] ?? '',
scannedDate: list[0] ?? '',
scannedTime: list[1] ?? '',
dataType: list[2] ?? '',
qrCodeData: list[3] ?? const Barcode(),
);
}
}
Expand All @@ -39,15 +39,10 @@ class QRCodeHistoryManager {
SharedPreferences prefs = await SharedPreferences.getInstance();
final historyJson = prefs.getString(_key);
if (historyJson != null) {
final List<Map<String, dynamic>> historyList =
(json.decode(historyJson) as List).cast<Map<String, dynamic>>();
final List<Map<String, dynamic>> castedHistoryList =
historyList.map((item) {
return item.cast<String, dynamic>();
}).toList(growable: false);

return castedHistoryList
.map((item) => QRCodeData.fromJson(item))
final List<List<dynamic>> historyList =
(json.decode(historyJson) as List).cast<List<dynamic>>();
return historyList
.map((item) => QRCodeData.fromList(item))
.toList(growable: true);
}
return [];
Expand All @@ -57,15 +52,13 @@ class QRCodeHistoryManager {
SharedPreferences prefs = await SharedPreferences.getInstance();
final history = await getHistory();
history.add(data);
final historyJson =
json.encode(history.map((item) => item.toJson()).toList());
final historyJson = json.encode(history.map((item) => item.toList()).toList());
prefs.setString(_key, historyJson);
}

Future<void> saveHistory(List<QRCodeData> history) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final historyJson =
json.encode(history.map((item) => item.toJson()).toList());
final historyJson = json.encode(history.map((item) => item.toList()).toList());
prefs.setString(_key, historyJson);
}
}
2 changes: 2 additions & 0 deletions lib/utils/imports.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ import 'package:flutter/material.dart';
export 'package:flutter/material.dart';
import 'package:flutter/services.dart';
export 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
export 'package:flutter/cupertino.dart' hide RefreshCallback;

// QR Generator Package
import 'package:qr_flutter/qr_flutter.dart';
Expand Down
10 changes: 7 additions & 3 deletions lib/utils/themes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ ThemeData lightTheme = ThemeData(
brightness: Brightness.light,
useMaterial3: true,
textTheme: TextTheme(
headlineMedium: TextStyle(fontSize: 50, color: Colors.blue[900]),
headlineLarge: TextStyle(fontSize: 50, color: Colors.blue[900]),
headlineMedium: const TextStyle(fontSize: 25, color: Colors.black),
headlineSmall: TextStyle(fontSize: 17, color: Colors.grey[600]),
labelSmall: TextStyle(
fontSize: 15, color: Colors.blue[900], fontWeight: FontWeight.w400
Expand Down Expand Up @@ -47,6 +48,7 @@ ThemeData lightTheme = ThemeData(
fixedSize: MaterialStateProperty.all(const Size(40, 25)),
backgroundColor: MaterialStateProperty.all(Colors.transparent),
),
headerHeadlineStyle: const TextStyle(fontSize: 35)
),
timePickerTheme: TimePickerThemeData(
cancelButtonStyle: ButtonStyle(
Expand All @@ -66,7 +68,8 @@ ThemeData lightTheme = ThemeData(
ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
textTheme: TextTheme(
headlineMedium: const TextStyle(fontSize: 50, color: Colors.cyan),
headlineLarge: const TextStyle(fontSize: 50, color: Colors.cyan),
headlineMedium: const TextStyle(fontSize: 25, color: Colors.white),
headlineSmall: TextStyle(fontSize: 17, color: Colors.grey[500]),
labelSmall: TextStyle(
fontSize: 15, color: Colors.grey[500], fontWeight: FontWeight.w400
Expand Down Expand Up @@ -108,7 +111,8 @@ ThemeData darkTheme = ThemeData(
shape: MaterialStateProperty.all(LinearBorder.none),
fixedSize: MaterialStateProperty.all(const Size(40, 25)),
backgroundColor: MaterialStateProperty.all(Colors.transparent),
)
),
headerHeadlineStyle: const TextStyle(fontSize: 35)
),
timePickerTheme: TimePickerThemeData(
backgroundColor: Colors.grey[900],
Expand Down
24 changes: 24 additions & 0 deletions lib/widgets/generator_page/text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ class _CustomTextFieldState extends State<CustomTextField> {
_focusNode.unfocus();
},
child: TextField(
contextMenuBuilder: (context, editableTextState) {
return AdaptiveTextSelectionToolbar(
anchors: editableTextState.contextMenuAnchors,
children: editableTextState.contextMenuButtonItems
.map((ContextMenuButtonItem buttonItem) {
return CupertinoButton(
minSize: 50,
borderRadius: const BorderRadius.all(Radius.circular(0)),
color: Colors.grey[800],
onPressed: buttonItem.onPressed,
padding: const EdgeInsets.all(10.0),
pressedOpacity: 0.7,
child: SizedBox(
width: 80,
child: Text(
CupertinoTextSelectionToolbarButton.getButtonLabel(context, buttonItem),
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.white),
),
),
);
}).toList(),
);
},
cursorColor: Theme.of(context).colorScheme.primary,
controller: widget.textController,
onChanged: (data) {
Expand Down

0 comments on commit 64b90b3

Please sign in to comment.