Skip to content

Commit b84c5dd

Browse files
committed
Merge branch 'patches' into main
2 parents 22cd273 + aa266ce commit b84c5dd

File tree

10 files changed

+192
-69
lines changed

10 files changed

+192
-69
lines changed

docs/ChangeLog.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Bug Fixes
22
- fixed longpress in termform to edit term name
33
- fixed bookdetails refresh
4+
- Android pill navigation now no longer scrolls to the bottom of the page.
5+
- term glow only affects the word tapped now
46

5-
# New Feature - Terms Screen
6-
7+
# New Feature
78

89
# Other Changes
910
- Add status colors to termsscreen stats
11+
- Swipe navigation toggle

docs/stuff.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55

66
# Statistics Screen
77

8+
- When multiple languages are selected it should show a line for each language in the line graphs and a bar for each language in the bar graph.
9+
- Use Hive-ce on the backend.
10+
811
# Terms Screen
912

10-
Add the Status highlights to the status labels in the term statistics card and add the language name to the right of the term statitics label.
1113

1214
# Reader
1315

1416
fixed? Some users are reporting that tooltips aren't showing. They work perfectly in my testing. Lets look into how to solve this. Maybe with retry logic of sometype? I think this is an issue with a slow server. All of our testing servers are really fast but some users may have slow servers
15-
- how hard to add elsewhere?
16-
17-
- Glow highlights make all terms with that termid glow, make it so only the clicked one glows.
17+
- right now we wait to show the tooltip ontap until the doubletap timeout ends. Can we also add a flag to wait until the data is actually fetched? with a 2 second timeout
1818

1919
# TTS
2020
- Future: add a selector in language settings to apply TTS voices based on languages.

lib/features/reader/widgets/reader_screen.dart

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import '../models/page_data.dart';
1010
import '../providers/reader_provider.dart';
1111
import '../providers/audio_player_provider.dart';
1212
import '../widgets/term_tooltip.dart';
13-
import '../models/sentence_translation.dart';
1413
import 'text_display.dart';
1514
import 'term_form.dart';
1615
import 'sentence_translation.dart';
@@ -143,7 +142,10 @@ class ReaderScreenState extends ConsumerState<ReaderScreen>
143142
Timer? _hideUiTimer;
144143
Timer? _glowTimer;
145144
int? _highlightedWordId;
145+
int? _highlightedParagraphId;
146+
int? _highlightedOrder;
146147
int? _originalWordId;
148+
TextItem? _originalTextItem;
147149
ScrollController _scrollController = ScrollController();
148150
double _lastScrollPosition = 0.0;
149151
DateTime? _lastMarkPageTime;
@@ -697,13 +699,15 @@ class ReaderScreenState extends ConsumerState<ReaderScreen>
697699
final textSettings = ref.watch(textFormattingSettingsProvider);
698700
final settings = ref.watch(settingsProvider);
699701

702+
final hasGestureNav = MediaQuery.of(context).systemGestureInsets.bottom > 0;
700703
final textDisplay = TextDisplay(
701704
key: _pageKey,
702705
paragraphs: pageData!.paragraphs,
703706
scrollController: _scrollController,
704707
topPadding: textSettings.fullscreenMode && !_isUiVisible
705708
? MediaQuery.of(context).padding.top
706709
: 0.0,
710+
bottomPadding: hasGestureNav ? 128 : 0,
707711
bottomControlWidget: _buildPageControls(context, pageData),
708712
onTap: (item, position) {
709713
_handleTap(item, position);
@@ -720,42 +724,80 @@ class ReaderScreenState extends ConsumerState<ReaderScreen>
720724
fontWeight: textSettings.fontWeight,
721725
isItalic: textSettings.isItalic,
722726
highlightedWordId: _highlightedWordId,
727+
highlightedParagraphId: _highlightedParagraphId,
728+
highlightedOrder: _highlightedOrder,
723729
);
724730

725-
return GestureDetector(
726-
onTapDown: (_) => TermTooltipClass.close(),
727-
onTap: () {
728-
if (textSettings.fullscreenMode && !_isUiVisible) {
729-
_showUi();
730-
}
731-
},
732-
onHorizontalDragEnd: (details) async {
733-
if (pageData!.pageCount <= 1) return;
734-
735-
final velocity = details.primaryVelocity ?? 0;
736-
if (velocity > 0) {
737-
if (pageData!.currentPage > 1) {
738-
_loadPageWithoutMarkingRead(pageData!.currentPage - 1);
739-
}
740-
} else if (velocity < 0) {
741-
if (pageData!.currentPage < pageData!.pageCount) {
731+
return Stack(
732+
children: [
733+
GestureDetector(
734+
onTapDown: (_) => TermTooltipClass.close(),
735+
onTap: () {
736+
if (textSettings.fullscreenMode && !_isUiVisible) {
737+
_showUi();
738+
}
739+
},
740+
onHorizontalDragEnd: (details) async {
741+
if (pageData!.pageCount <= 1) return;
742+
742743
final currentTextSettings = ref.read(
743744
textFormattingSettingsProvider,
744745
);
745746

746-
if (currentTextSettings.swipeMarksRead) {
747-
ref
748-
.read(readerProvider.notifier)
749-
.markPageRead(pageData!.bookId, pageData!.currentPage);
750-
}
747+
if (!currentTextSettings.swipeNavigationEnabled) return;
751748

752-
_loadPageWithoutMarkingRead(pageData!.currentPage + 1);
753-
}
754-
}
755-
},
756-
child: settings.pageTurnAnimations
757-
? _PageTransition(isForward: _isNavigatingForward, child: textDisplay)
758-
: textDisplay,
749+
final velocity = details.primaryVelocity ?? 0;
750+
const minSwipeVelocity = 300.0;
751+
752+
if (velocity.abs() < minSwipeVelocity) return;
753+
754+
if (velocity > 0) {
755+
if (pageData!.currentPage > 1) {
756+
_loadPageWithoutMarkingRead(pageData!.currentPage - 1);
757+
}
758+
} else if (velocity < 0) {
759+
if (pageData!.currentPage < pageData!.pageCount) {
760+
final currentTextSettings = ref.read(
761+
textFormattingSettingsProvider,
762+
);
763+
764+
if (currentTextSettings.swipeMarksRead) {
765+
ref
766+
.read(readerProvider.notifier)
767+
.markPageRead(pageData!.bookId, pageData!.currentPage);
768+
}
769+
770+
_loadPageWithoutMarkingRead(pageData!.currentPage + 1);
771+
}
772+
}
773+
},
774+
child: settings.pageTurnAnimations
775+
? _PageTransition(
776+
isForward: _isNavigatingForward,
777+
child: textDisplay,
778+
)
779+
: textDisplay,
780+
),
781+
if (hasGestureNav)
782+
Positioned(
783+
left: 0,
784+
right: 0,
785+
bottom: 0,
786+
height: 48,
787+
child: GestureDetector(
788+
behavior: HitTestBehavior.translucent,
789+
onVerticalDragStart: (_) {},
790+
onVerticalDragUpdate: (_) {},
791+
onVerticalDragEnd: (_) {},
792+
onTap: () {
793+
if (textSettings.fullscreenMode && !_isUiVisible) {
794+
_showUi();
795+
}
796+
},
797+
child: const SizedBox.shrink(),
798+
),
799+
),
800+
],
759801
);
760802
}
761803

@@ -783,9 +825,12 @@ class ReaderScreenState extends ConsumerState<ReaderScreen>
783825
if (item.wordId == null) return;
784826
if (item.langId == null) return;
785827

786-
// Store original word ID before opening term form
828+
// Store original identifiers before opening term form
787829
_originalWordId = item.wordId;
830+
_originalTextItem = item;
788831
_highlightedWordId = null;
832+
_highlightedParagraphId = null;
833+
_highlightedOrder = null;
789834

790835
print(
791836
'_handleDoubleTap: text="${item.text}", wordId=${item.wordId}, langId=${item.langId}',
@@ -810,22 +855,26 @@ class ReaderScreenState extends ConsumerState<ReaderScreen>
810855
void _triggerWordGlow() {
811856
final settings = ref.read(termFormSettingsProvider);
812857

813-
// Only trigger if enabled and we have an original word ID
814-
if (!settings.wordGlowEnabled || _originalWordId == null) return;
858+
// Only trigger if enabled and we have an original text item
859+
if (!settings.wordGlowEnabled || _originalTextItem == null) return;
815860

816861
// Cancel any existing timer
817862
_glowTimer?.cancel();
818863

819-
// Set highlight
864+
// Set highlight for this specific instance
820865
setState(() {
821-
_highlightedWordId = _originalWordId;
866+
_highlightedWordId = _originalTextItem!.wordId;
867+
_highlightedParagraphId = _originalTextItem!.paragraphId;
868+
_highlightedOrder = _originalTextItem!.order;
822869
});
823870

824-
// Auto-dismiss after 100ms
871+
// Auto-dismiss after 150ms
825872
_glowTimer = Timer(const Duration(milliseconds: 150), () {
826873
if (mounted) {
827874
setState(() {
828875
_highlightedWordId = null;
876+
_highlightedParagraphId = null;
877+
_highlightedOrder = null;
829878
});
830879
}
831880
});

lib/features/reader/widgets/sentence_reader_screen.dart

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,14 @@ class SentenceReaderScreenState extends ConsumerState<SentenceReaderScreen>
529529
return GestureDetector(
530530
onTapDown: (_) => TermTooltipClass.close(),
531531
onHorizontalDragEnd: (details) async {
532+
final textSettings = ref.read(textFormattingSettingsProvider);
533+
if (!textSettings.swipeNavigationEnabled) return;
534+
532535
final velocity = details.primaryVelocity ?? 0;
536+
const minSwipeVelocity = 300.0;
537+
538+
if (velocity.abs() < minSwipeVelocity) return;
539+
533540
final sentenceReaderNotifier = ref.read(
534541
sentenceReaderProvider.notifier,
535542
);
@@ -558,7 +565,12 @@ class SentenceReaderScreenState extends ConsumerState<SentenceReaderScreen>
558565
},
559566
child: SingleChildScrollView(
560567
child: Padding(
561-
padding: const EdgeInsets.all(24),
568+
padding: EdgeInsets.only(
569+
left: 24,
570+
right: 24,
571+
top: 24,
572+
bottom: 24 + MediaQuery.of(context).systemGestureInsets.bottom,
573+
),
562574
child: SentenceReaderDisplay(
563575
sentence: currentSentence,
564576
onTap: (item, position) => _handleTap(item, position),
@@ -582,7 +594,14 @@ class SentenceReaderScreenState extends ConsumerState<SentenceReaderScreen>
582594

583595
return GestureDetector(
584596
onHorizontalDragEnd: (details) async {
597+
final textSettings = ref.read(textFormattingSettingsProvider);
598+
if (!textSettings.swipeNavigationEnabled) return;
599+
585600
final velocity = details.primaryVelocity ?? 0;
601+
const minSwipeVelocity = 300.0;
602+
603+
if (velocity.abs() < minSwipeVelocity) return;
604+
586605
final sentenceReaderNotifier = ref.read(
587606
sentenceReaderProvider.notifier,
588607
);

lib/features/reader/widgets/term_list_display.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,12 @@ class TermListDisplay extends StatelessWidget {
8282
}
8383

8484
return ListView.builder(
85-
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
85+
padding: EdgeInsets.only(
86+
left: 12,
87+
right: 12,
88+
top: 8,
89+
bottom: 8 + MediaQuery.of(context).systemGestureInsets.bottom,
90+
),
8691
itemCount: uniqueTerms.length,
8792
itemBuilder: (context, index) {
8893
final term = uniqueTerms[index];

lib/features/reader/widgets/text_display.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ class TextDisplay extends StatefulWidget {
1717
final bool isItalic;
1818
final ScrollController? scrollController;
1919
final double topPadding;
20+
final double bottomPadding;
2021
final Widget? bottomControlWidget;
2122
final int? highlightedWordId;
23+
final int? highlightedParagraphId;
24+
final int? highlightedOrder;
2225

2326
const TextDisplay({
2427
super.key,
@@ -33,8 +36,11 @@ class TextDisplay extends StatefulWidget {
3336
this.isItalic = false,
3437
this.scrollController,
3538
this.topPadding = 0.0,
39+
this.bottomPadding = 0.0,
3640
this.bottomControlWidget,
3741
this.highlightedWordId,
42+
this.highlightedParagraphId,
43+
this.highlightedOrder,
3844
});
3945

4046
static Widget buildInteractiveWord(
@@ -49,6 +55,8 @@ class TextDisplay extends StatefulWidget {
4955
void Function(TextItem)? onDoubleTap,
5056
void Function(TextItem)? onLongPress,
5157
int? highlightedWordId,
58+
int? highlightedParagraphId,
59+
int? highlightedOrder,
5260
}) {
5361
if (item.isSpace) {
5462
return Text(
@@ -77,7 +85,10 @@ class TextDisplay extends StatefulWidget {
7785
}
7886

7987
final isHighlighted =
80-
highlightedWordId != null && highlightedWordId == item.wordId;
88+
highlightedWordId != null &&
89+
highlightedWordId == item.wordId &&
90+
highlightedParagraphId == item.paragraphId &&
91+
highlightedOrder == item.order;
8192

8293
final glowEffect = isHighlighted
8394
? BoxShadow(
@@ -182,7 +193,7 @@ class _TextDisplayState extends State<TextDisplay> {
182193
top: 16 + widget.topPadding,
183194
left: 16,
184195
right: 16,
185-
bottom: 16,
196+
bottom: 16 + widget.bottomPadding,
186197
),
187198
child: Column(
188199
crossAxisAlignment: CrossAxisAlignment.start,
@@ -227,6 +238,8 @@ class _TextDisplayState extends State<TextDisplay> {
227238
onDoubleTap: (item) => widget.onDoubleTap?.call(item),
228239
onLongPress: (item) => widget.onLongPress?.call(item),
229240
highlightedWordId: widget.highlightedWordId,
241+
highlightedParagraphId: widget.highlightedParagraphId,
242+
highlightedOrder: widget.highlightedOrder,
230243
);
231244
}
232245
}

0 commit comments

Comments
 (0)