Files
SpotiFLAC-Mobile/lib/widgets/metadata_barcode.dart
T

142 lines
4.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:spotiflac_android/utils/retail_barcode.dart';
class MetadataBarcode extends StatelessWidget {
final String value;
final String label;
final VoidCallback? onCopy;
const MetadataBarcode({
super.key,
required this.value,
required this.label,
this.onCopy,
});
@override
Widget build(BuildContext context) {
final barcode = encodeRetailBarcode(value);
if (barcode == null) return const SizedBox.shrink();
final colorScheme = Theme.of(context).colorScheme;
return Semantics(
label: '$label ${barcode.value}',
button: onCopy != null,
child: Material(
color: colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(16),
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: onCopy,
child: Padding(
padding: const EdgeInsets.fromLTRB(14, 12, 14, 14),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.qr_code_2_rounded,
size: 18,
color: colorScheme.primary,
),
const SizedBox(width: 8),
Expanded(
child: Text(
label,
style: Theme.of(context).textTheme.labelLarge?.copyWith(
fontWeight: FontWeight.w600,
),
),
),
Text(
barcode.symbology,
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: colorScheme.onSurfaceVariant,
),
),
if (onCopy != null) ...[
const SizedBox(width: 8),
Icon(
Icons.copy_rounded,
size: 16,
color: colorScheme.onSurfaceVariant,
),
],
],
),
const SizedBox(height: 10),
Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(10, 12, 10, 9),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
RepaintBoundary(
child: SizedBox(
width: double.infinity,
height: 76,
child: CustomPaint(painter: _BarcodePainter(barcode)),
),
),
const SizedBox(height: 7),
Text(
barcode.value,
maxLines: 1,
overflow: TextOverflow.fade,
softWrap: false,
style: const TextStyle(
color: Colors.black,
fontFamily: 'monospace',
fontSize: 14,
fontWeight: FontWeight.w600,
letterSpacing: 2.2,
),
),
],
),
),
],
),
),
),
),
);
}
}
class _BarcodePainter extends CustomPainter {
final RetailBarcodeData barcode;
const _BarcodePainter(this.barcode);
@override
void paint(Canvas canvas, Size size) {
final totalModules =
barcode.modules.length + (barcode.quietZoneModules * 2);
final moduleWidth = size.width / totalModules;
final paint = Paint()
..color = Colors.black
..style = PaintingStyle.fill
..isAntiAlias = false;
for (var i = 0; i < barcode.modules.length; i++) {
if (barcode.modules.codeUnitAt(i) != 49) continue;
final left = (barcode.quietZoneModules + i) * moduleWidth;
canvas.drawRect(
Rect.fromLTWH(left, 0, moduleWidth + 0.01, size.height),
paint,
);
}
}
@override
bool shouldRepaint(covariant _BarcodePainter oldDelegate) {
return barcode.modules != oldDelegate.barcode.modules ||
barcode.quietZoneModules != oldDelegate.barcode.quietZoneModules;
}
}