feat(ui): add pointer cursors to clickable controls

close #1068
This commit is contained in:
edde746
2026-05-18 15:56:41 +02:00
parent 324d145292
commit 5a68711f7b
24 changed files with 772 additions and 649 deletions
+61 -58
View File
@@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
import '../../focus/key_event_utils.dart';
import '../../media/library_first_character.dart';
import '../../widgets/clickable_cursor.dart';
import 'alpha_jump_helper.dart';
/// Vertical strip of letters for jumping through sorted library items.
@@ -209,72 +210,74 @@ class _AlphaJumpBarState extends State<AlphaJumpBar> {
final currentLetter = _nearestDisplayed(widget.currentLetter);
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (details) {
final idx = _letterIndexFromDy(details.localPosition.dy, constraints.maxHeight);
setState(() => _highlightedIndex = idx);
_jumpToLetter(_displayed[idx]);
},
onVerticalDragUpdate: (details) {
final idx = _letterIndexFromDy(details.localPosition.dy, constraints.maxHeight);
if (idx != _highlightedIndex) {
return ClickableCursor(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (details) {
final idx = _letterIndexFromDy(details.localPosition.dy, constraints.maxHeight);
setState(() => _highlightedIndex = idx);
_jumpToLetter(_displayed[idx]);
}
},
child: Container(
width: 28,
decoration: BoxDecoration(
color: colorScheme.surface.withValues(alpha: 0.7),
borderRadius: const BorderRadius.all(Radius.circular(14)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(_displayed.length, (i) {
final letter = _displayed[i];
final isCurrent = letter == currentLetter && !_hasFocus;
final isHighlighted = _hasFocus && i == _highlightedIndex;
},
onVerticalDragUpdate: (details) {
final idx = _letterIndexFromDy(details.localPosition.dy, constraints.maxHeight);
if (idx != _highlightedIndex) {
setState(() => _highlightedIndex = idx);
_jumpToLetter(_displayed[idx]);
}
},
child: Container(
width: 28,
decoration: BoxDecoration(
color: colorScheme.surface.withValues(alpha: 0.7),
borderRadius: const BorderRadius.all(Radius.circular(14)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(_displayed.length, (i) {
final letter = _displayed[i];
final isCurrent = letter == currentLetter && !_hasFocus;
final isHighlighted = _hasFocus && i == _highlightedIndex;
BoxDecoration? decoration;
if (isHighlighted) {
decoration = BoxDecoration(color: colorScheme.primary, shape: BoxShape.circle);
} else if (isCurrent) {
decoration = BoxDecoration(
color: colorScheme.primary.withValues(alpha: 0.3),
shape: BoxShape.circle,
);
}
BoxDecoration? decoration;
if (isHighlighted) {
decoration = BoxDecoration(color: colorScheme.primary, shape: BoxShape.circle);
} else if (isCurrent) {
decoration = BoxDecoration(
color: colorScheme.primary.withValues(alpha: 0.3),
shape: BoxShape.circle,
);
}
Color letterColor;
if (isHighlighted) {
letterColor = colorScheme.onPrimary;
} else if (isCurrent) {
letterColor = colorScheme.primary;
} else {
letterColor = colorScheme.onSurface;
}
Color letterColor;
if (isHighlighted) {
letterColor = colorScheme.onPrimary;
} else if (isCurrent) {
letterColor = colorScheme.primary;
} else {
letterColor = colorScheme.onSurface;
}
return SizedBox(
height: constraints.maxHeight / _displayed.length,
child: Center(
child: Container(
width: 22,
height: 22,
decoration: decoration,
alignment: Alignment.center,
child: Text(
letter,
style: TextStyle(
fontSize: 10,
fontWeight: (isCurrent || isHighlighted) ? FontWeight.bold : FontWeight.normal,
color: letterColor,
return SizedBox(
height: constraints.maxHeight / _displayed.length,
child: Center(
child: Container(
width: 22,
height: 22,
decoration: decoration,
alignment: Alignment.center,
child: Text(
letter,
style: TextStyle(
fontSize: 10,
fontWeight: (isCurrent || isHighlighted) ? FontWeight.bold : FontWeight.normal,
color: letterColor,
),
),
),
),
),
);
}),
);
}),
),
),
),
);
+20 -17
View File
@@ -176,23 +176,26 @@ class _AlphaScrollHandleState extends State<AlphaScrollHandle> with SingleTicker
Positioned(
right: 0,
top: handleTop - _touchTargetVerticalPadding,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onVerticalDragStart: _onDragStart,
onVerticalDragUpdate: _onDragUpdate,
onVerticalDragEnd: _onDragEnd,
child: SizedBox(
width: _touchTargetWidth,
height: _handleHeight + _touchTargetVerticalPadding * 2,
child: Align(
alignment: Alignment.centerRight,
child: Container(
margin: const EdgeInsets.only(right: 2),
width: _handleWidth,
height: _handleHeight,
decoration: BoxDecoration(
color: colorScheme.onSurface.withValues(alpha: 0.5),
borderRadius: const BorderRadius.all(Radius.circular(_handleRadius)),
child: MouseRegion(
cursor: SystemMouseCursors.resizeUpDown,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onVerticalDragStart: _onDragStart,
onVerticalDragUpdate: _onDragUpdate,
onVerticalDragEnd: _onDragEnd,
child: SizedBox(
width: _touchTargetWidth,
height: _handleHeight + _touchTargetVerticalPadding * 2,
child: Align(
alignment: Alignment.centerRight,
child: Container(
margin: const EdgeInsets.only(right: 2),
width: _handleWidth,
height: _handleHeight,
decoration: BoxDecoration(
color: colorScheme.onSurface.withValues(alpha: 0.5),
borderRadius: const BorderRadius.all(Radius.circular(_handleRadius)),
),
),
),
),