claude refactorings, flutter best practices, platform dependent changes, general cleanup
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum BubbleNip { leftTop, rightBottom, none }
|
||||
|
||||
class BubbleEdges {
|
||||
const BubbleEdges.only({this.top = 0, this.bottom = 0, this.left = 0, this.right = 0});
|
||||
const BubbleEdges.all(double value)
|
||||
: top = value,
|
||||
bottom = value,
|
||||
left = value,
|
||||
right = value;
|
||||
|
||||
final double top;
|
||||
final double bottom;
|
||||
final double left;
|
||||
final double right;
|
||||
|
||||
EdgeInsets toEdgeInsets() => EdgeInsets.fromLTRB(left, top, right, bottom);
|
||||
}
|
||||
|
||||
class BubbleStyle {
|
||||
const BubbleStyle({
|
||||
this.color,
|
||||
this.borderWidth = 0,
|
||||
this.elevation = 0,
|
||||
this.margin = const BubbleEdges.only(),
|
||||
this.padding = const BubbleEdges.all(8),
|
||||
this.alignment = Alignment.centerLeft,
|
||||
this.nip = BubbleNip.none,
|
||||
this.borderRadius = 12,
|
||||
});
|
||||
|
||||
final Color? color;
|
||||
final double borderWidth;
|
||||
final double elevation;
|
||||
final BubbleEdges margin;
|
||||
final BubbleEdges padding;
|
||||
final Alignment alignment;
|
||||
final BubbleNip nip;
|
||||
final double borderRadius;
|
||||
}
|
||||
|
||||
/// Lightweight chat bubble. Replaces the abandoned `bubble` package: renders a
|
||||
/// rounded container with optional shadow / border. The nip is conveyed by
|
||||
/// flattening one corner so the bubble visually anchors to the speaker side.
|
||||
class Bubble extends StatelessWidget {
|
||||
const Bubble({required this.child, required this.style, super.key});
|
||||
|
||||
final Widget child;
|
||||
final BubbleStyle style;
|
||||
|
||||
BorderRadius _radius() {
|
||||
final r = Radius.circular(style.borderRadius);
|
||||
final flat = Radius.zero;
|
||||
switch (style.nip) {
|
||||
case BubbleNip.leftTop:
|
||||
return BorderRadius.only(topLeft: flat, topRight: r, bottomLeft: r, bottomRight: r);
|
||||
case BubbleNip.rightBottom:
|
||||
return BorderRadius.only(topLeft: r, topRight: r, bottomLeft: r, bottomRight: flat);
|
||||
case BubbleNip.none:
|
||||
return BorderRadius.all(r);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final radius = _radius();
|
||||
return Align(
|
||||
alignment: style.alignment,
|
||||
child: Container(
|
||||
margin: style.margin.toEdgeInsets(),
|
||||
decoration: BoxDecoration(
|
||||
color: style.color,
|
||||
borderRadius: radius,
|
||||
border: style.borderWidth > 0
|
||||
? Border.all(color: Theme.of(context).dividerColor, width: style.borderWidth)
|
||||
: null,
|
||||
boxShadow: style.elevation > 0
|
||||
? [BoxShadow(color: Colors.black26, blurRadius: style.elevation * 2, offset: Offset(0, style.elevation))]
|
||||
: null,
|
||||
),
|
||||
padding: style.padding.toEdgeInsets(),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user