add option to disable auto-scroll. (#225)

This commit is contained in:
Jiaqi Feng
2023-06-05 18:23:29 -07:00
committed by GitHub
parent e33ff417fb
commit 8d238744c7
14 changed files with 159 additions and 153 deletions

BIN
assets/hacki-github.xcf Normal file

Binary file not shown.

BIN
assets/hacki.xcf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 KiB

View File

@ -68,6 +68,8 @@ class PreferenceState extends Equatable {
bool get swipeGestureEnabled => _isOn<SwipeGesturePreference>();
bool get autoScrollEnabled => _isOn<AutoScrollModePreference>();
List<StoryType> get tabs {
final String result =
preferences.singleWhereType<TabOrderPreference>().val.toString();

View File

@ -48,3 +48,11 @@ class SearchState extends Equatable {
params,
];
}
extension SearchStateExtension on SearchState {
bool get showDateRangeShortcutChips {
return hasDateFilter &&
dateFilter?.startTime != null &&
dateFilter?.endTime != null;
}
}

View File

@ -30,6 +30,7 @@ abstract class Preference<T> extends Equatable with SettingsDisplayable {
const StoryUrlModePreference(),
const NotificationModePreference(),
const SwipeGesturePreference(),
const AutoScrollModePreference(),
const CollapseModePreference(),
const ReaderModePreference(),
const MarkReadStoriesModePreference(),
@ -54,12 +55,13 @@ const bool _notificationModeDefaultValue = true;
const bool _swipeGestureModeDefaultValue = false;
const bool _displayModeDefaultValue = true;
const bool _eyeCandyModeDefaultValue = false;
const bool _trueDarkModeDefaultValue = false;
const bool _trueDarkModeDefaultValue = true;
const bool _readerModeDefaultValue = true;
const bool _markReadStoriesModeDefaultValue = true;
const bool _metadataModeDefaultValue = true;
const bool _storyUrlModeDefaultValue = true;
const bool _collapseModeDefaultValue = true;
const bool _autoScrollModeDefaultValue = true;
final int _fetchModeDefaultValue = FetchMode.eager.index;
final int _commentsOrderDefaultValue = CommentsOrder.natural.index;
final int _fontSizeDefaultValue = FontSize.regular.index;
@ -127,6 +129,26 @@ class CollapseModePreference extends BooleanPreference {
'''if disabled, tap on the top of comment tile to collapse.''';
}
class AutoScrollModePreference extends BooleanPreference {
const AutoScrollModePreference({bool? val})
: super(val: val ?? _autoScrollModeDefaultValue);
@override
AutoScrollModePreference copyWith({required bool? val}) {
return AutoScrollModePreference(val: val);
}
@override
String get key => 'autoScrollMode';
@override
String get title => 'Auto-scroll on collapsing';
@override
String get subtitle =>
'''Automatically scroll to next comment when you collapse a comment.''';
}
/// The value deciding whether or not the story
/// tile should display link preview. Defaults to true.
class DisplayModePreference extends BooleanPreference {

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_fadein/flutter_fadein.dart';
import 'package:hacki/config/constants.dart';
@ -32,31 +31,9 @@ class _SearchScreenState extends State<SearchScreen> {
final RefreshController refreshController = RefreshController();
final ScrollController scrollController = ScrollController();
final Debouncer debouncer = Debouncer(delay: Durations.oneSecond);
bool showChips = true;
bool shouldOffStageChips = false;
static const Duration chipsAnimationDuration = Durations.ms300;
@override
void initState() {
super.initState();
scrollController.addListener(() {
if (scrollController.position.userScrollDirection ==
ScrollDirection.reverse &&
showChips) {
setState(() {
showChips = false;
});
} else if (scrollController.position.userScrollDirection ==
ScrollDirection.forward &&
!showChips) {
setState(() {
showChips = true;
});
}
});
}
@override
void dispose() {
refreshController.dispose();
@ -108,16 +85,13 @@ class _SearchScreenState extends State<SearchScreen> {
),
AnimatedCrossFade(
duration: chipsAnimationDuration,
crossFadeState: showChips
crossFadeState: state.showDateRangeShortcutChips
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
firstChild: SizedBox.fromSize(),
secondChild: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (state.hasDateFilter &&
state.dateFilter?.startTime != null &&
state.dateFilter?.endTime != null)
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
@ -129,8 +103,8 @@ class _SearchScreenState extends State<SearchScreen> {
onDateTimeRangeUpdated: context
.read<SearchCubit>()
.onDateTimeRangeUpdated,
startDate: state.dateFilter!.startTime!,
endDate: state.dateFilter!.endTime!,
startDate: state.dateFilter?.startTime,
endDate: state.dateFilter?.endTime,
),
const SizedBox(
width: Dimens.pt8,
@ -139,8 +113,8 @@ class _SearchScreenState extends State<SearchScreen> {
onDateTimeRangeUpdated: context
.read<SearchCubit>()
.onDateTimeRangeUpdated,
startDate: state.dateFilter!.startTime!,
endDate: state.dateFilter!.endTime!,
startDate: state.dateFilter?.startTime,
endDate: state.dateFilter?.endTime,
),
const SizedBox(
width: Dimens.pt8,
@ -149,8 +123,8 @@ class _SearchScreenState extends State<SearchScreen> {
onDateTimeRangeUpdated: context
.read<SearchCubit>()
.onDateTimeRangeUpdated,
startDate: state.dateFilter!.startTime!,
endDate: state.dateFilter!.endTime!,
startDate: state.dateFilter?.startTime,
endDate: state.dateFilter?.endTime,
),
const SizedBox(
width: Dimens.pt8,
@ -159,8 +133,8 @@ class _SearchScreenState extends State<SearchScreen> {
onDateTimeRangeUpdated: context
.read<SearchCubit>()
.onDateTimeRangeUpdated,
startDate: state.dateFilter!.startTime!,
endDate: state.dateFilter!.endTime!,
startDate: state.dateFilter?.startTime,
endDate: state.dateFilter?.endTime,
),
const SizedBox(
width: Dimens.pt8,
@ -169,8 +143,8 @@ class _SearchScreenState extends State<SearchScreen> {
onDateTimeRangeUpdated: context
.read<SearchCubit>()
.onDateTimeRangeUpdated,
startDate: state.dateFilter!.startTime!,
endDate: state.dateFilter!.endTime!,
startDate: state.dateFilter?.startTime,
endDate: state.dateFilter?.endTime,
),
const SizedBox(
width: Dimens.pt8,
@ -179,8 +153,11 @@ class _SearchScreenState extends State<SearchScreen> {
onDateTimeRangeUpdated: context
.read<SearchCubit>()
.onDateTimeRangeUpdated,
startDate: state.dateFilter!.startTime!,
endDate: state.dateFilter!.endTime!,
startDate: state.dateFilter?.startTime,
endDate: state.dateFilter?.endTime,
),
],
),
),
],
),
@ -208,9 +185,8 @@ class _SearchScreenState extends State<SearchScreen> {
),
PostedByFilterChip(
filter: state.params.get<PostedByFilter>(),
onChanged: context
.read<SearchCubit>()
.onPostedByChanged,
onChanged:
context.read<SearchCubit>().onPostedByChanged,
),
const SizedBox(
width: Dimens.pt8,
@ -249,9 +225,8 @@ class _SearchScreenState extends State<SearchScreen> {
width: Dimens.pt8,
),
CustomChip(
onSelected: (_) => context
.read<SearchCubit>()
.onToggled(filter),
onSelected: (_) =>
context.read<SearchCubit>().onToggled(filter),
selected: context
.read<SearchCubit>()
.state
@ -264,9 +239,6 @@ class _SearchScreenState extends State<SearchScreen> {
],
),
),
],
),
),
if (state.status == SearchStatus.loading &&
state.results.isEmpty) ...<Widget>[
const SizedBox(

View File

@ -68,8 +68,8 @@ class DateTimeShortcutChip extends StatelessWidget {
_calculator = ((DateTime date) => date.add(const Duration(days: 30)));
final void Function(DateTime, DateTime) onDateTimeRangeUpdated;
final DateTime startDate;
final DateTime endDate;
final DateTime? startDate;
final DateTime? endDate;
final String label;
final Calculator _calculator;
@ -77,8 +77,9 @@ class DateTimeShortcutChip extends StatelessWidget {
Widget build(BuildContext context) {
return CustomChip(
onSelected: (bool value) {
final DateTime updatedStartDate = _calculator(startDate);
final DateTime updatedEndDate = _calculator(endDate);
if (startDate == null || endDate == null) return;
final DateTime updatedStartDate = _calculator(startDate!);
final DateTime updatedEndDate = _calculator(endDate!);
onDateTimeRangeUpdated(updatedStartDate, updatedEndDate);
},
selected: false,

View File

@ -349,7 +349,8 @@ class CommentTile extends StatelessWidget {
void _collapse(BuildContext context) {
HapticFeedbackUtil.selection();
context.read<CollapseCubit>().collapse();
if (context.read<CollapseCubit>().state.collapsed) {
if (context.read<CollapseCubit>().state.collapsed &&
context.read<PreferenceCubit>().state.autoScrollEnabled) {
Future<void>.delayed(
Durations.ms300,
() {

View File

@ -237,7 +237,7 @@ class LinkView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: isUsingSerifFont! ? Dimens.pt2 : Dimens.pt4,
height: isUsingSerifFont! ? Dimens.zero : Dimens.pt4,
),
Text(
title,

View File

@ -1,6 +1,6 @@
name: hacki
description: A Hacker News reader.
version: 1.7.1+112
version: 1.7.2+113
publish_to: none
environment: