add tag color

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2023-08-13 18:13:06 +08:00
parent ae640dda56
commit a5bba37cae
3 changed files with 139 additions and 18 deletions

View File

@ -1074,6 +1074,30 @@ Color str2color(String str, [alpha = 0xFF]) {
return Color((hash & 0xFF7FFF) | (alpha << 24));
}
Color str2color2(String str, [alpha = 0xFF]) {
List<Color> colorList = [
Colors.red,
Colors.green,
Colors.blue,
Colors.orange,
Colors.yellow,
Colors.purple,
Colors.grey,
Colors.cyan,
Colors.lime,
Colors.teal,
Colors.pink,
Colors.indigo,
Colors.brown,
];
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash += str.codeUnitAt(i);
}
hash = hash % colorList.length;
return colorList[hash].withAlpha(alpha);
}
const K = 1024;
const M = K * K;
const G = M * K;

View File

@ -449,26 +449,43 @@ class AddressBookTag extends StatelessWidget {
pos = RelativeRect.fromLTRB(x, y, x, y);
}
const double radius = 8;
return GestureDetector(
onTap: onTap,
onTapDown: showActionMenu ? setPosition : null,
onSecondaryTapDown: showActionMenu ? setPosition : null,
onSecondaryTap: showActionMenu ? () => _showMenu(context, pos) : null,
onLongPress: showActionMenu ? () => _showMenu(context, pos) : null,
child: Obx(
() => Container(
decoration: BoxDecoration(
color: tags.contains(name)
? Colors.blue
: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(6)),
margin: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 8.0),
padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 8.0),
child: Text(name,
style:
TextStyle(color: tags.contains(name) ? Colors.white : null)),
),
),
child: Obx(() => Container(
decoration: BoxDecoration(
color: tags.contains(name)
? str2color2(name, 0xFF)
: Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(4)),
margin: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 4.0),
padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 6.0),
child: IntrinsicWidth(
child: Row(
children: [
Container(
width: radius,
height: radius,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: tags.contains(name)
? Colors.white
: str2color2(name)),
).marginOnly(right: radius / 2),
Expanded(
child: Text(name,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: tags.contains(name) ? Colors.white : null)),
),
],
),
),
)),
);
}

View File

@ -14,6 +14,7 @@ import '../../models/peer_model.dart';
import '../../models/platform_model.dart';
import '../../desktop/widgets/material_mod_popup_menu.dart' as mod_menu;
import '../../desktop/widgets/popup_menu.dart';
import 'dart:math' as math;
typedef PopupMenuEntryBuilder = Future<List<mod_menu.PopupMenuEntry<String>>>
Function(BuildContext);
@ -159,7 +160,7 @@ class _PeerCardState extends State<_PeerCard>
fontSize: 11,
color: Theme.of(context).textTheme.titleLarge?.color?.withOpacity(0.6));
final alias = bind.mainGetPeerOptionSync(id: peer.id, key: 'alias');
return Obx(
final child = Obx(
() => Container(
foregroundDecoration: deco.value,
child: Row(
@ -199,7 +200,7 @@ class _PeerCardState extends State<_PeerCard>
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.titleSmall,
)),
]).marginOnly(bottom: 2),
]).marginOnly(bottom: 0, top: 2),
Align(
alignment: Alignment.centerLeft,
child: Text(
@ -221,13 +222,29 @@ class _PeerCardState extends State<_PeerCard>
),
),
);
final colors = _frontN(peer.tags, 25).map((e) => str2color2(e)).toList();
return Tooltip(
message: peer.tags.isNotEmpty
? '${translate('Tags')}: ${peer.tags.join(', ')}'
: '',
child: Stack(children: [
child,
Positioned(
top: 2,
right: 10,
child: CustomPaint(
painter: TagPainter(radius: 3, colors: colors),
),
)
]),
);
}
Widget _buildPeerCard(
BuildContext context, Peer peer, Rx<BoxDecoration?> deco) {
final name =
'${peer.username}${peer.username.isNotEmpty && peer.hostname.isNotEmpty ? '@' : ''}${peer.hostname}';
return Card(
final child = Card(
color: Colors.transparent,
elevation: 0,
margin: EdgeInsets.zero,
@ -253,7 +270,7 @@ class _PeerCardState extends State<_PeerCard>
padding: const EdgeInsets.all(6),
child:
getPlatformImage(peer.platform, size: 60),
),
).marginOnly(top: 4),
Row(
children: [
Expanded(
@ -304,6 +321,31 @@ class _PeerCardState extends State<_PeerCard>
),
),
);
final colors = _frontN(peer.tags, 25).map((e) => str2color2(e)).toList();
return Tooltip(
message: peer.tags.isNotEmpty
? '${translate('Tags')}: ${peer.tags.join(', ')}'
: '',
child: Stack(children: [
child,
Positioned(
top: 4,
right: 12,
child: CustomPaint(
painter: TagPainter(radius: 4, colors: colors),
),
)
]),
);
}
List _frontN<T>(List list, int n) {
if (list.length <= n) {
return list;
} else {
return list.sublist(0, n);
}
}
Widget checkBoxOrActionMoreMobile(Peer peer) {
@ -1193,3 +1235,41 @@ Widget build_more(BuildContext context, {bool invert = false}) {
?.color
?.withOpacity(0.5)))));
}
class TagPainter extends CustomPainter {
final double radius;
late final List<Color> colors;
TagPainter({required this.radius, required List<Color> colors}) {
this.colors = colors.reversed.toList();
}
@override
void paint(Canvas canvas, Size size) {
double x = 0;
double y = radius;
for (int i = 0; i < colors.length; i++) {
Paint paint = Paint();
paint.color = colors[i];
x -= radius + 1;
if (i == colors.length - 1) {
canvas.drawCircle(Offset(x, y), radius, paint);
} else {
Path path = Path();
path.addArc(Rect.fromCircle(center: Offset(x, y), radius: radius),
math.pi * 4 / 3, math.pi * 4 / 3);
path.addArc(
Rect.fromCircle(center: Offset(x - radius, y), radius: radius),
math.pi * 5 / 3,
math.pi * 2 / 3);
path.fillType = PathFillType.evenOdd;
canvas.drawPath(path, paint);
}
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}