-
Notifications
You must be signed in to change notification settings - Fork 13
feat: added customizable templates #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Reviewer's GuideThis PR implements a customizable template workflow by letting users select from predefined card templates (employee ID and price tag), fill out form fields with live previews, and preload the resulting LayerSpec entries into the MovableBackgroundImage editor for further adjustment or export. Sequence diagram for template selection and layer preloadingsequenceDiagram
actor User
participant ImageEditor as ImageEditorView
participant TemplateView as CardTemplateSelectionView
participant Form as TemplateForm (EmployeeIdForm/PriceTagForm)
participant Editor as MovableBackgroundImageExample
User->>ImageEditor: Tap 'Templates' action
ImageEditor->>TemplateView: Open CardTemplateSelectionView
User->>TemplateView: Selects a template
TemplateView->>Form: Open corresponding form
User->>Form: Fill out form fields, see live preview
User->>Form: Submit form
Form->>Editor: Open MovableBackgroundImageExample with initialLayers
Editor->>User: Show editor with preloaded layers
User->>Editor: Optionally edit layers
User->>ImageEditor: Save/export final image
Class diagram for new and updated template-related modelsclassDiagram
class LayerSpec {
+Widget? widget
+String? text
+TextStyle? textStyle
+Color? textColor
+Color? backgroundColor
+TextAlign? textAlign
+Offset offset
+double scale
+double rotation
+LayerSpec.text(...)
+LayerSpec.widget(...)
}
class EmployeeIdModel {
+String companyName
+String name
+String idNumber
+String division
+String position
+String qrData
+File? profileImage
}
class PriceTagModel {
+String productName
+String price
+String currency
+String quantity
+String barcodeData
+File? productImage
}
Class diagram for new template form and widget classesclassDiagram
class EmployeeIdForm {
+int width
+int height
+EmployeeIdForm(...)
}
class EmployeeIdCardWidget {
+EmployeeIdModel data
+EmployeeIdCardWidget(...)
}
class PriceTagForm {
+int width
+int height
+PriceTagForm(...)
}
class PriceTagCardWidget {
+PriceTagModel data
+PriceTagCardWidget(...)
}
class CardTemplateSelectionView {
+int width
+int height
+CardTemplateSelectionView(...)
}
EmployeeIdForm --> EmployeeIdCardWidget : uses
PriceTagForm --> PriceTagCardWidget : uses
CardTemplateSelectionView --> EmployeeIdForm : opens
CardTemplateSelectionView --> PriceTagForm : opens
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @Vishveshwara - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `lib/card_templates/employee_id_card_widget.dart:61` </location>
<code_context>
+ ),
+ const SizedBox(height: 4),
+ // Name
+ if (data.name.isNotEmpty)
+ Text(
+ 'Name: ${data.name}',
+ style:
</code_context>
<issue_to_address>
Name is displayed twice in the card widget.
Remove one of the duplicate name fields to prevent redundancy in the card display.
</issue_to_address>
### Comment 2
<location> `lib/card_templates/employee_id_form.dart:113` </location>
<code_context>
+ ));
+ }
+
+ // Profile Image Layer
+ if (_profileImage != null) {
+ layers.add(LayerSpec(
+ widget: ClipRRect(
+ borderRadius: BorderRadius.circular(8.0),
+ child: Image.file(_profileImage!,
+ width: 200, height: 200, fit: BoxFit.cover),
+ ),
+ offset: const Offset(0, -205),
+ scale: 10,
+ ));
+ }
+
</code_context>
<issue_to_address>
Profile image and company name layers have overlapping offsets.
Adjust the offsets to prevent visual overlap between the profile image and company name layers.
Suggested implementation:
```
widget: Text(
_employeeData.companyName,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
),
offset: const Offset(0, -240), // Moved company name higher
scale: 10,
));
}
```
```
// Profile Image Layer
if (_profileImage != null) {
layers.add(LayerSpec(
widget: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.file(_profileImage!,
width: 200, height: 200, fit: BoxFit.cover),
),
offset: const Offset(0, -180), // Moved profile image lower
scale: 10,
));
}
```
</issue_to_address>
### Comment 3
<location> `lib/card_templates/employee_id_form.dart:180` </location>
<code_context>
+ ));
+
+ // QR Code Layer (bottom, only if qrData is not empty)
+ if (_employeeData.qrData.isNotEmpty) {
+ layers.add(LayerSpec(
+ widget: BarcodeWidget(
+ barcode: Barcode.qrCode(),
+ data: _employeeData.qrData,
+ width: 60,
+ height: 60,
+ ),
+ offset: const Offset(0, 170),
+ scale: 8,
+ ));
+ }
+
</code_context>
<issue_to_address>
No error handling for invalid QR data.
Validate the QR data or add exception handling to avoid runtime errors if the data is invalid.
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
const SizedBox(height: 8), | ||
// Company Name | ||
if (data.companyName.isNotEmpty) | ||
Text( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: Name is displayed twice in the card widget.
Remove one of the duplicate name fields to prevent redundancy in the card display.
), | ||
offset: const Offset(0, -210), | ||
scale: 10, | ||
)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Profile image and company name layers have overlapping offsets.
Adjust the offsets to prevent visual overlap between the profile image and company name layers.
Suggested implementation:
widget: Text(
_employeeData.companyName,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
),
offset: const Offset(0, -240), // Moved company name higher
scale: 10,
));
}
// Profile Image Layer
if (_profileImage != null) {
layers.add(LayerSpec(
widget: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.file(_profileImage!,
width: 200, height: 200, fit: BoxFit.cover),
),
offset: const Offset(0, -180), // Moved profile image lower
scale: 10,
));
}
), | ||
offset: const Offset(0, -210), | ||
scale: 10, | ||
)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): No error handling for invalid QR data.
Validate the QR data or add exception handling to avoid runtime errors if the data is invalid.
emp.mp4 |
@Vishveshwara how far are you with this draft PR? |
@hpdang , actually I can finish implementing this in the same way i have done for the employee id , but there is a method to adjust the fonts in the editor , but i am getting an error when using the text layer in the pro_image_editor package , I am going to create a discussion in their github repository , so that we can change the fonts in the editor. |
@hpdang , Added shopping price tag and text layer to adjust fonts or modify the text in the editor itself. price.tag.vid.mp4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @Vishveshwara - I've reviewed your changes - here's some feedback:
- You’re adding initial layers inside the build callback, which risks duplication on rebuilds—consider moving that logic to initState (or a post‐frame callback) so layers are only applied once.
- The two form widgets (EmployeeIdForm and PriceTagForm) share a lot of boilerplate for controller setup, preview updates and layer generation—consider extracting a common base or helper to reduce duplication.
- Please remove the commented-out "code testing" snippets once you’ve verified functionality to keep the code clean and maintainable.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- You’re adding initial layers inside the build callback, which risks duplication on rebuilds—consider moving that logic to initState (or a post‐frame callback) so layers are only applied once.
- The two form widgets (EmployeeIdForm and PriceTagForm) share a lot of boilerplate for controller setup, preview updates and layer generation—consider extracting a common base or helper to reduce duplication.
- Please remove the commented-out "code testing" snippets once you’ve verified functionality to keep the code clean and maintainable.
## Individual Comments
### Comment 1
<location> `lib/pro_image_editor/features/movable_background_image.dart:456` </location>
<code_context>
);
+
+ // Add initial layers from widget parameter
+ if (widget.initialLayers != null) {
+ addInitialLayers(widget.initialLayers!);
+ }
+ //code testing
+ //editorKey.currentState!.openTextEditor(initialText: "Hello World");
</code_context>
<issue_to_address>
Adding initial layers inside the build method can lead to unexpected behavior.
The build method may be called multiple times, causing duplicate layers. Move this logic to an initialization phase to prevent repeated additions.
</issue_to_address>
### Comment 2
<location> `lib/util/template_util.dart:4` </location>
<code_context>
+class LayerSpec {
</code_context>
<issue_to_address>
LayerSpec allows both widget and text to be set, which could lead to ambiguous layer definitions.
The main constructor currently permits both fields to be set, which may introduce ambiguity. Making it private and using only named constructors would enforce clearer usage.
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
class LayerSpec { | ||
final Widget? widget; | ||
final String? text; | ||
final TextStyle? textStyle; | ||
final Color? textColor; | ||
final Color? backgroundColor; | ||
final TextAlign? textAlign; | ||
final Offset offset; | ||
final double scale; | ||
final double rotation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): LayerSpec allows both widget and text to be set, which could lead to ambiguous layer definitions.
The main constructor currently permits both fields to be set, which may introduce ambiguity. Making it private and using only named constructors would enforce clearer usage.
Build StatusBuild successful. APKs to test: https://github.com/fossasia/magic-epaper-app/actions/runs/16676154107/artifacts/3667471538. |
@Vishveshwara please see screenshot below, why there is a line of text covering the bottom menu? |
@Vishveshwara please fix error and resolve conflicts |
Tested. The bottom text is not there anymore. It showed debug label on the top though, is it intended? @Vishveshwara |
@hpdang |
|
@hpdang this is not an issue, this is just a debug build version of the app which is used for testing and quick debugging, the release version of the app will remove the debug label. |
Fixes #86
Changes
Screenshots / Recordings
Checklist:
constants.dart
without hard coding any value.Summary by Sourcery
Introduce customizable card templates by adding template selection, form screens for employee IDs and price tags, layer specification utilities, and integration with the pro_image_editor to generate template-based images
New Features:
Enhancements:
Build: