refactor: rename internal Fai* design system + fai_ helpers to chain
Some checks failed
Security / Security check (push) Failing after 2s
Some checks failed
Security / Security check (push) Failing after 2s
The Studio design system, widgets and helpers carried a Fai* / fai_ prefix (FaiSpace, FaiColors, FaiTheme, FaiLog, 17 fai_*.dart files, the faiBinary* l10n keys). Studio is the Ch∆In product, so rename them to Chain* / chain_ — carefully preserving English fail/failure/failed. Also fix stale references: the 'fai' binary in l10n strings -> 'chain', FAI_* env vars (FAI_BIN/DATA_DIR/MODULES_DIR/TODAY/BOOTSTRAP_TOKEN) -> CHAIN_*, fai_platform -> fai_chain, fai_hub -> chain_hub. Vendor security-hook tooling (FAI_BANNED_TERMS_FILE) + the .fai bundle ext left. flutter analyze + test: clean (20 passed). Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
68d23ab7dd
commit
891acd2ba2
52 changed files with 1225 additions and 1225 deletions
173
lib/widgets/chain_delta_mark.dart
Normal file
173
lib/widgets/chain_delta_mark.dart
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// ChainDeltaMark — the Ch∆In signature element. A precise triangle
|
||||
// (∆) drawn from primitives, not a font glyph. Three states:
|
||||
//
|
||||
// - idle: static, accent colour, soft glow
|
||||
// - live: gentle pulse, like a heartbeat
|
||||
// - busy: rotates slowly, used while a long operation runs
|
||||
//
|
||||
// Sized small. Lives in the navigation rail header so it's
|
||||
// always visible and identifies the brand without screaming.
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum ChainDeltaMode { idle, live, busy }
|
||||
|
||||
class ChainDeltaMark extends StatefulWidget {
|
||||
final ChainDeltaMode mode;
|
||||
final double size;
|
||||
final Color color;
|
||||
|
||||
const ChainDeltaMark({
|
||||
super.key,
|
||||
required this.color,
|
||||
this.mode = ChainDeltaMode.idle,
|
||||
this.size = 36,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ChainDeltaMark> createState() => _FaiDeltaMarkState();
|
||||
}
|
||||
|
||||
class _FaiDeltaMarkState extends State<ChainDeltaMark>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final AnimationController _ctrl;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_ctrl = AnimationController(
|
||||
vsync: this,
|
||||
duration: _durationFor(widget.mode),
|
||||
);
|
||||
_restart();
|
||||
}
|
||||
|
||||
Duration _durationFor(ChainDeltaMode m) {
|
||||
switch (m) {
|
||||
case ChainDeltaMode.idle:
|
||||
return const Duration(seconds: 1);
|
||||
case ChainDeltaMode.live:
|
||||
return const Duration(milliseconds: 1600);
|
||||
case ChainDeltaMode.busy:
|
||||
return const Duration(seconds: 4);
|
||||
}
|
||||
}
|
||||
|
||||
void _restart() {
|
||||
_ctrl.duration = _durationFor(widget.mode);
|
||||
switch (widget.mode) {
|
||||
case ChainDeltaMode.idle:
|
||||
_ctrl.stop();
|
||||
_ctrl.value = 0;
|
||||
break;
|
||||
case ChainDeltaMode.live:
|
||||
_ctrl.repeat(reverse: true);
|
||||
break;
|
||||
case ChainDeltaMode.busy:
|
||||
_ctrl.repeat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant ChainDeltaMark old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (old.mode != widget.mode) _restart();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_ctrl.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _ctrl,
|
||||
builder: (_, _) {
|
||||
return CustomPaint(
|
||||
size: Size.square(widget.size),
|
||||
painter: _DeltaPainter(
|
||||
color: widget.color,
|
||||
mode: widget.mode,
|
||||
t: _ctrl.value,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DeltaPainter extends CustomPainter {
|
||||
final Color color;
|
||||
final ChainDeltaMode mode;
|
||||
final double t;
|
||||
|
||||
_DeltaPainter({required this.color, required this.mode, required this.t});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final cx = size.width / 2;
|
||||
final cy = size.height / 2;
|
||||
|
||||
// In live mode: scale the whole mark between 0.85 and 1.15
|
||||
// so the pulse is visible without staring. Idle stays at 1.0.
|
||||
final scale = mode == ChainDeltaMode.live ? 0.85 + 0.30 * t : 1.0;
|
||||
final r = size.width * 0.36 * scale;
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(cx, cy);
|
||||
if (mode == ChainDeltaMode.busy) {
|
||||
canvas.rotate(t * 2 * pi);
|
||||
}
|
||||
|
||||
// Outer triangle path.
|
||||
final path = Path()
|
||||
..moveTo(0, -r)
|
||||
..lineTo(r * cos(pi / 6), r * sin(pi / 6))
|
||||
..lineTo(-r * cos(pi / 6), r * sin(pi / 6))
|
||||
..close();
|
||||
|
||||
// Glow halo. In live mode the glow ring grows with the pulse
|
||||
// and the alpha breathes harder.
|
||||
if (mode != ChainDeltaMode.idle) {
|
||||
final pulseStrength = mode == ChainDeltaMode.live ? t : 1.0;
|
||||
final glow = Paint()
|
||||
..color = color.withValues(alpha: 0.30 + 0.40 * pulseStrength)
|
||||
..maskFilter = MaskFilter.blur(BlurStyle.normal, 8 + 14 * pulseStrength)
|
||||
..style = PaintingStyle.fill;
|
||||
canvas.drawPath(path, glow);
|
||||
}
|
||||
|
||||
// Filled triangle, brighter on the up-beat for live mode.
|
||||
final fillAlpha = mode == ChainDeltaMode.live ? 0.15 + 0.20 * t : 0.18;
|
||||
final fill = Paint()
|
||||
..color = color.withValues(alpha: fillAlpha)
|
||||
..style = PaintingStyle.fill;
|
||||
canvas.drawPath(path, fill);
|
||||
|
||||
// Outline stroke.
|
||||
final stroke = Paint()
|
||||
..color = color
|
||||
..strokeWidth = 2.2
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeJoin = StrokeJoin.round;
|
||||
canvas.drawPath(path, stroke);
|
||||
|
||||
// Inner accent dot.
|
||||
final dotAlpha = mode == ChainDeltaMode.live ? 0.55 + 0.45 * t : 1.0;
|
||||
final dot = Paint()
|
||||
..color = color.withValues(alpha: dotAlpha)
|
||||
..style = PaintingStyle.fill;
|
||||
canvas.drawCircle(Offset(0, r * 0.18), r * 0.16, dot);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant _DeltaPainter old) =>
|
||||
old.t != t || old.mode != mode || old.color != color;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue