Skip to content

Commit 8ea4dcd

Browse files
committed
Update animation UI as per textfield style
1 parent 9bce97c commit 8ea4dcd

9 files changed

Lines changed: 658 additions & 206 deletions

File tree

android/gradle.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
org.gradle.jvmargs=-Xmx4G
22
android.useAndroidX=true
33
android.enableJetifier=true
4+
# This builtInKotlin flag was added automatically by Flutter migrator
5+
android.builtInKotlin=false
6+
# This newDsl flag was added automatically by Flutter migrator
7+
android.newDsl=false

lib/bademagic_module/utils/converters.dart

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,14 @@ class Converters {
224224
segments.add(
225225
{'type': 'image', 'index': int.parse(text[i + 2] + text[i + 3])});
226226
i += 6;
227+
} else if (text[i] == '\f') {
228+
// Frame separator: flush current text then pad to next screen boundary.
229+
if (currentText.isNotEmpty) {
230+
segments.add({'type': 'text', 'content': currentText});
231+
currentText = '';
232+
}
233+
segments.add({'type': 'frame_break'});
234+
i++;
227235
} else {
228236
currentText += text[i];
229237
i++;
@@ -237,7 +245,9 @@ class Converters {
237245

238246
// Process each segment
239247
for (var segment in segments) {
240-
if (segment['type'] == 'text') {
248+
if (segment['type'] == 'frame_break') {
249+
_padMatrixToNextFrame(combinedMatrix);
250+
} else if (segment['type'] == 'text') {
241251
String text = segment['content'];
242252
for (int i = 0; i < text.length; i++) {
243253
String char = text[i];
@@ -325,6 +335,27 @@ class Converters {
325335
return hexStrings;
326336
}
327337

338+
/// Pads [combinedMatrix] with empty columns until its width is a multiple of
339+
/// [badgeScreenWidth] (default 44). Used to align frames at screen boundaries
340+
/// when the "Animation" (Splitting) transition is active.
341+
void _padMatrixToNextFrame(
342+
List<List<bool>> combinedMatrix, {
343+
int badgeScreenWidth = 44,
344+
}) {
345+
final currentWidth =
346+
combinedMatrix.isNotEmpty ? combinedMatrix[0].length : 0;
347+
if (currentWidth == 0) return;
348+
final remainder = currentWidth % badgeScreenWidth;
349+
if (remainder == 0) return; // already aligned
350+
final paddingNeeded = badgeScreenWidth - remainder;
351+
final emptyCol = List<bool>.filled(11, false);
352+
for (int p = 0; p < paddingNeeded; p++) {
353+
for (int row = 0; row < 11; row++) {
354+
combinedMatrix[row].add(emptyCol[row]);
355+
}
356+
}
357+
}
358+
328359
Future<List<String>> _processDefaultFont(String text) async {
329360
List<Map<String, dynamic>> segments = [];
330361
String currentText = '';
@@ -339,6 +370,15 @@ class Converters {
339370
segments.add(
340371
{'type': 'image', 'index': int.parse(text[i + 2] + text[i + 3])});
341372
i += 6;
373+
} else if (text[i] == '\f') {
374+
// Frame separator: flush current text segment then pad matrix to the
375+
// next 44-column screen boundary so the following frame starts fresh.
376+
if (currentText.isNotEmpty) {
377+
segments.add({'type': 'text', 'content': currentText});
378+
currentText = '';
379+
}
380+
segments.add({'type': 'frame_break'});
381+
i++;
342382
} else {
343383
currentText += text[i];
344384
i++;
@@ -351,7 +391,10 @@ class Converters {
351391
List<List<bool>> combinedMatrix = List.generate(11, (_) => []);
352392

353393
for (var segment in segments) {
354-
if (segment['type'] == 'text') {
394+
if (segment['type'] == 'frame_break') {
395+
// Pad to the next full badge screen (44 columns).
396+
_padMatrixToNextFrame(combinedMatrix);
397+
} else if (segment['type'] == 'text') {
355398
String segmentText = segment['content'];
356399
for (final char in segmentText.split('')) {
357400
if (!converter.charCodes.containsKey(char)) continue;

lib/l10n/app_en.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,5 +235,7 @@
235235
"shareQrImage": "Share QR image",
236236
"couldNotGenerateQrImage": "Could not generate QR image.",
237237
"couldNotShareQrImage": "Could not share QR image.",
238-
"qrShareInstruction": "Scan this code from another device, or tap share to send the QR image."
238+
"qrShareInstruction": "Scan this code from another device, or tap share to send the QR image.",
239+
"addFrame": "Add Frame",
240+
"frameHint": "Type text for this frame"
239241
}

lib/l10n/app_hi.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,7 @@
172172
"saveSettings": "सेटिंग्स सेव करें",
173173
"connectToAnyBadge": "किसी भी बैज से कनेक्ट करें",
174174
"badgeNameHint": "बैज का नाम",
175-
"pleaseSelectClipart": "सेव करने से पहले कृपया तस्वीर बनाएं या चुनें"
175+
"pleaseSelectClipart": "कृपया सेव करने से पहले कोई क्लिपआर्ट बनाएं या चुनें",
176+
"addFrame": "फ्रेम जोड़ें",
177+
"frameHint": "इस फ्रेम के लिए टेक्स्ट लिखें"
176178
}

lib/l10n/app_it.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,5 +215,7 @@
215215
"triangle": "Triangolo",
216216
"clipartSavedSuccessfully": "Clipart salvato con successo",
217217
"badgeScanMode": "Modalità Scansione Badge",
218-
"pleaseSelectClipart": "Si prega di disegnare o selezionare un clipart prima di salvare"
218+
"pleaseSelectClipart": "Si prega di disegnare o selezionare un clipart prima di salvare",
219+
"addFrame": "Aggiungi Fotogramma",
220+
"frameHint": "Scrivi il testo per questo fotogramma"
219221
}

lib/providers/imageprovider.dart

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@ class InlineImageProvider extends ChangeNotifier {
9393
//controller for the Textfield
9494
TextEditingController message = TextEditingController();
9595

96+
/// When the multi-frame input widget is active, this is set to the
97+
/// [TextEditingController] of the frame that is currently focused.
98+
/// Clipart will be inserted into this controller instead of [message].
99+
TextEditingController? activeFrameController;
100+
101+
/// Saves the full multi-frame text (with \f separators) when switching away
102+
/// from the Animation (Splitting) transition, so it can be restored.
103+
String? savedMultiFrameText;
104+
105+
/// Remembers which frame index was active when switching away from Splitting.
106+
int? savedActiveFrameIndex;
107+
96108
//getter for the textfield controller
97109
TextEditingController getController() => message;
98110

@@ -150,12 +162,15 @@ class InlineImageProvider extends ChangeNotifier {
150162
}
151163
logger.d('Inserting image at index: $index');
152164
String placeholder = index < 10 ? '<<0$index>>' : '<<$index>>';
165+
// Insert into the currently focused frame if available, otherwise the
166+
// main message controller.
167+
final target = activeFrameController ?? message;
153168
int cursorPos =
154-
message.selection.baseOffset == -1 ? 0 : message.selection.baseOffset;
155-
String beforeCursor = message.text.substring(0, cursorPos);
156-
String afterCursor = message.text.substring(cursorPos);
157-
message.text = beforeCursor + placeholder + afterCursor;
158-
message.selection = TextSelection.fromPosition(
169+
target.selection.baseOffset == -1 ? 0 : target.selection.baseOffset;
170+
String beforeCursor = target.text.substring(0, cursorPos);
171+
String afterCursor = target.text.substring(cursorPos);
172+
target.text = beforeCursor + placeholder + afterCursor;
173+
target.selection = TextSelection.fromPosition(
159174
TextPosition(offset: cursorPos + placeholder.length));
160175
}
161176
}

0 commit comments

Comments
 (0)