Files
Client/lib/view/pages/talk/widgets/bubble.dart
T

87 lines
2.4 KiB
Dart

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;
}
/// The "nip" is faked by flattening one corner so the bubble 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,
),
);
}
}