-
Notifications
You must be signed in to change notification settings - Fork 68
/
Copy pathpopup_controller.dart
90 lines (76 loc) · 2.75 KB
/
popup_controller.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
class PopupController extends ChangeNotifier {
late List<String> suggestions;
int _selectedIndex = 0;
bool shouldShow = false;
bool enabled = true;
ItemScrollController itemScrollController = ItemScrollController();
final ItemPositionsListener itemPositionsListener =
ItemPositionsListener.create();
/// Should be called when an active list item is selected to be inserted into the text
late final void Function() onCompletionSelected;
PopupController({required this.onCompletionSelected}) : super();
set selectedIndex(int value) {
_selectedIndex = value;
notifyListeners();
}
int get selectedIndex => _selectedIndex;
void reset() {
itemScrollController = ItemScrollController();
}
void show(List<String> suggestions) {
if (enabled == false) {
return;
}
this.suggestions = suggestions;
_selectedIndex = 0;
shouldShow = true;
WidgetsBinding.instance.addPostFrameCallback((_) {
if (itemScrollController.isAttached) {
itemScrollController.jumpTo(index: 0);
}
});
notifyListeners();
}
void hide() {
shouldShow = false;
notifyListeners();
}
/// Changes the selected item and scrolls through the list of completions on keyboard arrows pressed
void scrollByArrow(ScrollDirection direction) {
final previousSelectedIndex = selectedIndex;
if (direction == ScrollDirection.up) {
selectedIndex =
(selectedIndex - 1 + suggestions.length) % suggestions.length;
} else {
selectedIndex = (selectedIndex + 1) % suggestions.length;
}
final visiblePositions = itemPositionsListener.itemPositions.value
.where((item) {
final bool isTopVisible = item.itemLeadingEdge >= 0;
final bool isBottomVisible = item.itemTrailingEdge <= 1;
return isTopVisible && isBottomVisible;
})
.map((e) => e.index)
.toList();
// List offset will be changed only if new selected item is not visible
if (!visiblePositions.contains(selectedIndex)) {
// If previously selected item was at the bottom of the visible part of the list,
// on 'down' arrow the new one will appear at the bottom as well
final isStepDown = selectedIndex - previousSelectedIndex == 1;
if (isStepDown && selectedIndex < suggestions.length - 1) {
itemScrollController.jumpTo(index: selectedIndex + 1, alignment: 1);
} else {
itemScrollController.jumpTo(index: selectedIndex);
}
}
notifyListeners();
}
String getSelectedWord() => suggestions[selectedIndex];
}
/// Possible directions of completions list navigation
enum ScrollDirection {
up,
down,
}