Skip to content

Commit

Permalink
feat: Added the logic to display the user drawn clipart to the badge. (
Browse files Browse the repository at this point in the history
  • Loading branch information
Jhalakupadhyay authored Aug 17, 2024
1 parent e9b2418 commit 3ece383
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 31 deletions.
Binary file added assets/icons/postman collections.zip
Binary file not shown.
2 changes: 0 additions & 2 deletions lib/bademagic_module/bluetooth/base_ble_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ abstract class RetryBleState extends BleState {
attempt++;
if (attempt < _maxRetries) {
logger.d("Retrying ($attempt/$_maxRetries)...");
await Future.delayed(
const Duration(seconds: 2)); // Wait before retrying
} else {
logger.e("Max retries reached. Last exception: $lastException");
lastException =
Expand Down
25 changes: 19 additions & 6 deletions lib/bademagic_module/utils/converters.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:math';
import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart';
import 'package:badgemagic/bademagic_module/utils/data_to_bytearray_converter.dart';
import 'package:badgemagic/bademagic_module/utils/file_helper.dart';
import 'package:badgemagic/bademagic_module/utils/image_utils.dart';
import 'package:badgemagic/providers/imageprovider.dart';
import 'package:get_it/get_it.dart';
Expand All @@ -10,6 +11,7 @@ class Converters {
GetIt.instance.get<InlineImageProvider>();
DataToByteArrayConverter converter = DataToByteArrayConverter();
ImageUtils imageUtils = ImageUtils();
FileHelper fileHelper = FileHelper();

int controllerLength = 0;

Expand All @@ -18,10 +20,20 @@ class Converters {
for (int x = 0; x < message.length; x++) {
if (message[x] == '<' && message[min(x + 5, message.length - 1)] == '>') {
int index = int.parse(message[x + 2] + message[x + 3]);
List<String> hs =
await imageUtils.generateLedHex(controllerData.vectors[index]);
hexStrings.addAll(hs);
x += 5;
var key = controllerData.imageCache.keys.toList()[index];
if (key is List) {
String filename = key[0];
logger.d("Filename: $filename");
List<List<int>>? image = await fileHelper.readFromFile(filename);
logger.d("Image: $image");
hexStrings = convertBitmapToLEDHex(image!, true);
x += 5;
} else {
List<String> hs =
await imageUtils.generateLedHex(controllerData.vectors[index]);
hexStrings.addAll(hs);
x += 5;
}
} else {
if (converter.charCodes.containsKey(message[x])) {
hexStrings.add(converter.charCodes[message[x]]!);
Expand All @@ -33,7 +45,8 @@ class Converters {

//function to convert the bitmap to the LED hex format
//it takes the 2D list of pixels and converts it to the LED hex format
static List<String> convertBitmapToLEDHex(List<List<int>> image) {
static List<String> convertBitmapToLEDHex(
List<List<int>> image, bool isDrawn) {
// Determine the height and width of the image
int height = image.length;
int width = image.isNotEmpty ? image[0].length : 0;
Expand Down Expand Up @@ -132,7 +145,7 @@ class Converters {

allHexs.add(lineHex.toString()); // Store completed hexadecimal line
}

logger.d("All hexs: $allHexs");
return allHexs; // Return list of hexadecimal strings
}
}
48 changes: 33 additions & 15 deletions lib/bademagic_module/utils/file_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,14 @@ class FileHelper {
return File(path).writeAsString(data);
}

// static Future<String> _readFromFile(String filename) async {
// try {
// final path = await _getFilePath(filename);
// return await File(path).readAsString();
// } catch (e) {
// return ''; // Return an empty string if there's an error
// }
// }

static String _generateUniqueFilename() {
final String uniqueId = uuid.v4();
final String timestamp = DateTime.now().millisecondsSinceEpoch.toString();
return 'data_${timestamp}_$uniqueId.json';
}

// Add a new image to the cache
void addToCache(Uint8List imageData) {
void addToCache(Uint8List imageData, String filename) {
int key;
if (imageCacheProvider.availableKeys.isNotEmpty) {
// Reuse the lowest available key
Expand All @@ -57,7 +48,11 @@ class FileHelper {
key++;
}
}
imageCacheProvider.imageCache[key] = imageData;
//storing the user drawn clipart to the badge in the form of a list
//the first element of the list is the filename and the second element is the key
//while parsing the vector we can take the filename and generate the hex for that vector
//therefore transfering the vector to the physiacl badge will be easier.
imageCacheProvider.imageCache[[filename, key]] = imageData;
}

// Remove an image from the cache
Expand All @@ -70,13 +65,14 @@ class FileHelper {
}

// Generate a Uint8List from a 2D list (image data) and add it to the cache
Future<void> _addImageDataToCache(List<List<dynamic>> imageData) async {
Future<void> _addImageDataToCache(
List<List<dynamic>> imageData, String filename) async {
// Convert List<List<dynamic>> to List<List<int>>
List<List<int>> intImageData =
imageData.map((list) => list.cast<int>()).toList();
Uint8List imageBytes =
await imageUtils.convert2DListToUint8List(intImageData);
addToCache(imageBytes);
addToCache(imageBytes, filename);
}

// Read all files, parse the 2D lists, and add to cache
Expand All @@ -92,7 +88,7 @@ class FileHelper {
final List<dynamic> decodedData = jsonDecode(content);
final List<List<dynamic>> imageData =
decodedData.cast<List<dynamic>>();
await _addImageDataToCache(imageData);
await _addImageDataToCache(imageData, file.path.split('/').last);
}
}
}
Expand Down Expand Up @@ -126,6 +122,28 @@ class FileHelper {
logger.d('Image saved to file: $filename');

//Add the image to the image cache after saving it to a file
await _addImageDataToCache(image);
await _addImageDataToCache(image, filename);
}

Future<List<List<int>>?> readFromFile(String filename) async {
try {
final path = await _getFilePath(filename);
final file = File(path);
if (await file.exists()) {
final content = await file.readAsString();
final List<dynamic> decodedData = jsonDecode(content);
final List<List<dynamic>> image = decodedData.cast<List<dynamic>>();
//COnvert the List<list<Dynamic>> to List<List<int>>
List<List<int>> imageData =
image.map((list) => list.cast<int>()).toList();
return imageData;
} else {
logger.d('File not found: $filename');
return null;
}
} catch (e) {
logger.e('Error reading file: $e');
return null;
}
}
}
2 changes: 1 addition & 1 deletion lib/bademagic_module/utils/image_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,6 @@ class ImageUtils {
}
}
logger.d("Pixel Array generated = $pixelArray");
return Converters.convertBitmapToLEDHex(pixelArray);
return Converters.convertBitmapToLEDHex(pixelArray, false);
}
}
11 changes: 9 additions & 2 deletions lib/providers/imageprovider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class InlineImageProvider extends ChangeNotifier {
//Map to store the cache of the images generated
//Image caches are generated at the splash screen
//The cache generation time acts as a delay in the splash screen
Map<int, Uint8List?> imageCache = {};
Map<Object, Uint8List?> imageCache = {};

//function that generates the image cache
//it fills the map with the Unit8List(byte Array) of the images
Expand All @@ -71,7 +71,14 @@ class InlineImageProvider extends ChangeNotifier {
notifyListeners();
}

void insertInlineImage(int index) {
void insertInlineImage(Object key) {
int index = 0;
if (key is int) {
index = key;
} else if (key is List) {
index = key[1];
}
logger.d('Inserting image at index: $index');
String placeholder = index < 10 ? '<<0$index>>' : '<<$index>>';
int cursorPos =
message.selection.baseOffset == -1 ? 0 : message.selection.baseOffset;
Expand Down
7 changes: 6 additions & 1 deletion lib/view/special_text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ class InlineImageText extends SpecialText {
final String key = toString();

// Parse the index from the placeholder text
final int vectorIndex = int.parse(key.substring(2, key.length - 2));
final int index = int.parse(key.substring(2, key.length - 2));
Object vectorIndex = index;
var keyAt = textData.imageCache.keys.toList()[index];
if (keyAt is List) {
vectorIndex = keyAt;
}

return ImageSpan(MemoryImage(textData.imageCache[vectorIndex]!),
imageWidth: 25.w,
Expand Down
8 changes: 5 additions & 3 deletions lib/view/widgets/vectorview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class _VectorGridViewState extends State<VectorGridView> {
Widget build(BuildContext context) {
InlineImageProvider inlineImageProvider =
Provider.of<InlineImageProvider>(context);
List keys = inlineImageProvider.imageCache.keys.toList();
return GridView.builder(
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
Expand All @@ -24,7 +25,7 @@ class _VectorGridViewState extends State<VectorGridView> {
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
inlineImageProvider.insertInlineImage(index);
inlineImageProvider.insertInlineImage(keys[index]);
},
child: Card(
shape: RoundedRectangleBorder(
Expand All @@ -35,10 +36,11 @@ class _VectorGridViewState extends State<VectorGridView> {
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Image.memory(inlineImageProvider.imageCache[index]!)),
child: Image.memory(
inlineImageProvider.imageCache[keys[index]]!)),
));
},
itemCount: inlineImageProvider.imageCache.length,
itemCount: keys.length,
);
}
}
2 changes: 1 addition & 1 deletion test/converters_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ void main() {
[0, 1]
];

List<String> result = Converters.convertBitmapToLEDHex(image);
List<String> result = Converters.convertBitmapToLEDHex(image, false);

expect(result, ["1008"]);
});
Expand Down

0 comments on commit 3ece383

Please sign in to comment.