Add default feed mode, explore feed sort, and comment sort options

This commit is contained in:
John Wesley 2024-01-26 10:42:15 -05:00
parent e15c4e862f
commit 6e16a3ac1d
10 changed files with 316 additions and 142 deletions

35
lib/src/api/comment.dart Normal file
View File

@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:interstellar/src/widgets/selection_menu.dart';
enum CommentSort { newest, top, hot, active, oldest }
const SelectionMenu<CommentSort> commentSortSelect = SelectionMenu(
'Sort Comments',
[
SelectionMenuItem(
value: CommentSort.hot,
title: 'Hot',
icon: Icons.local_fire_department,
),
SelectionMenuItem(
value: CommentSort.top,
title: 'Top',
icon: Icons.trending_up,
),
SelectionMenuItem(
value: CommentSort.newest,
title: 'Newest',
icon: Icons.auto_awesome_rounded,
),
SelectionMenuItem(
value: CommentSort.active,
title: 'Active',
icon: Icons.rocket_launch,
),
SelectionMenuItem(
value: CommentSort.oldest,
title: 'Oldest',
icon: Icons.access_time_outlined,
),
],
);

View File

@ -1,17 +1,16 @@
import 'dart:convert'; import 'dart:convert';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:interstellar/src/api/comment.dart';
import 'package:interstellar/src/models/entry_comment.dart'; import 'package:interstellar/src/models/entry_comment.dart';
import 'package:interstellar/src/utils/utils.dart'; import 'package:interstellar/src/utils/utils.dart';
enum CommentsSort { newest, top, hot, active, oldest }
Future<EntryCommentListModel> fetchComments( Future<EntryCommentListModel> fetchComments(
http.Client client, http.Client client,
String instanceHost, String instanceHost,
int entryId, { int entryId, {
int? page, int? page,
CommentsSort? sort, CommentSort? sort,
}) async { }) async {
final response = await client.get(Uri.https( final response = await client.get(Uri.https(
instanceHost, instanceHost,

View File

@ -1,17 +1,16 @@
import 'dart:convert'; import 'dart:convert';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:interstellar/src/api/comment.dart';
import 'package:interstellar/src/models/post_comment.dart'; import 'package:interstellar/src/models/post_comment.dart';
import 'package:interstellar/src/utils/utils.dart'; import 'package:interstellar/src/utils/utils.dart';
enum CommentsSort { newest, top, hot, active, oldest }
Future<PostCommentListModel> fetchComments( Future<PostCommentListModel> fetchComments(
http.Client client, http.Client client,
String instanceHost, String instanceHost,
int postId, { int postId, {
int? page, int? page,
CommentsSort? sort, CommentSort? sort,
}) async { }) async {
final response = await client.get(Uri.https( final response = await client.get(Uri.https(
instanceHost, instanceHost,

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:interstellar/src/api/comments.dart' as api_comments; import 'package:interstellar/src/api/entry_comments.dart' as api_comments;
import 'package:interstellar/src/models/entry_comment.dart'; import 'package:interstellar/src/models/entry_comment.dart';
import 'package:interstellar/src/screens/entries/entry_comment_screen.dart'; import 'package:interstellar/src/screens/entries/entry_comment_screen.dart';
import 'package:interstellar/src/screens/settings/settings_controller.dart'; import 'package:interstellar/src/screens/settings/settings_controller.dart';
@ -134,8 +134,10 @@ class _EntryCommentState extends State<EntryComment> {
TextButton( TextButton(
onPressed: () => Navigator.of(context).push( onPressed: () => Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => builder: (context) => EntryCommentScreen(
EntryCommentScreen(widget.comment.commentId, opUserId: widget.opUserId), widget.comment.commentId,
opUserId: widget.opUserId,
),
), ),
), ),
child: Text( child: Text(

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:interstellar/src/api/comments.dart'; import 'package:interstellar/src/api/entry_comments.dart';
import 'package:interstellar/src/models/entry_comment.dart'; import 'package:interstellar/src/models/entry_comment.dart';
import 'package:interstellar/src/screens/entries/entry_comment.dart'; import 'package:interstellar/src/screens/entries/entry_comment.dart';
import 'package:interstellar/src/screens/settings/settings_controller.dart'; import 'package:interstellar/src/screens/settings/settings_controller.dart';
@ -49,11 +49,11 @@ class _EntryCommentScreenState extends State<EntryCommentScreen> {
vertical: 4, vertical: 4,
), ),
child: EntryComment( child: EntryComment(
_comment!, _comment!,
(newComment) => setState(() { (newComment) => setState(() {
_comment = newComment; _comment = newComment;
}), opUserId: widget.opUserId }),
), opUserId: widget.opUserId),
) )
], ],
) )

View File

@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:interstellar/src/api/comments.dart' as api_comments; import 'package:interstellar/src/api/comment.dart';
import 'package:interstellar/src/api/entries.dart' as api_entries; import 'package:interstellar/src/api/entries.dart' as api_entries;
import 'package:interstellar/src/api/entry_comments.dart' as api_comments;
import 'package:interstellar/src/models/entry.dart'; import 'package:interstellar/src/models/entry.dart';
import 'package:interstellar/src/models/entry_comment.dart'; import 'package:interstellar/src/models/entry_comment.dart';
import 'package:interstellar/src/screens/entries/entry_comment.dart'; import 'package:interstellar/src/screens/entries/entry_comment.dart';
@ -27,7 +28,7 @@ class EntryPage extends StatefulWidget {
class _EntryPageState extends State<EntryPage> { class _EntryPageState extends State<EntryPage> {
EntryModel? _data; EntryModel? _data;
api_comments.CommentsSort commentsSort = api_comments.CommentsSort.hot; CommentSort commentSort = CommentSort.hot;
final PagingController<int, EntryCommentModel> _pagingController = final PagingController<int, EntryCommentModel> _pagingController =
PagingController(firstPageKey: 1); PagingController(firstPageKey: 1);
@ -37,6 +38,7 @@ class _EntryPageState extends State<EntryPage> {
super.initState(); super.initState();
_data = widget.initData; _data = widget.initData;
commentSort = context.read<SettingsController>().defaultCommentSort;
_pagingController.addPageRequestListener(_fetchPage); _pagingController.addPageRequestListener(_fetchPage);
} }
@ -55,7 +57,7 @@ class _EntryPageState extends State<EntryPage> {
context.read<SettingsController>().instanceHost, context.read<SettingsController>().instanceHost,
_data!.entryId, _data!.entryId,
page: pageKey, page: pageKey,
sort: commentsSort, sort: commentSort,
); );
// Check BuildContext // Check BuildContext
@ -88,6 +90,25 @@ class _EntryPageState extends State<EntryPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(_data?.title ?? ''), title: Text(_data?.title ?? ''),
actions: [
Padding(
padding: const EdgeInsets.only(right: 8),
child: IconButton(
onPressed: () async {
final newSort = await commentSortSelect.inquireSelection(
context, commentSort);
if (newSort != null && newSort != commentSort) {
setState(() {
commentSort = newSort;
_pagingController.refresh();
});
}
},
icon: const Icon(Icons.sort),
),
),
],
), ),
body: RefreshIndicator( body: RefreshIndicator(
onRefresh: () => Future.sync( onRefresh: () => Future.sync(
@ -153,48 +174,6 @@ class _EntryPageState extends State<EntryPage> {
: null, : null,
), ),
), ),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
DropdownButton<api_comments.CommentsSort>(
value: commentsSort,
onChanged: (newSort) {
if (newSort != null) {
setState(() {
commentsSort = newSort;
_pagingController.refresh();
});
}
},
items: const [
DropdownMenuItem(
value: api_comments.CommentsSort.hot,
child: Text('Hot'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.top,
child: Text('Top'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.newest,
child: Text('Newest'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.active,
child: Text('Active'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.oldest,
child: Text('Oldest'),
),
],
),
],
),
),
),
PagedSliverList<int, EntryCommentModel>( PagedSliverList<int, EntryCommentModel>(
pagingController: _pagingController, pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<EntryCommentModel>( builderDelegate: PagedChildBuilderDelegate<EntryCommentModel>(

View File

@ -35,14 +35,19 @@ class FeedScreen extends StatefulWidget {
enum FeedMode { entries, posts } enum FeedMode { entries, posts }
class _FeedScreenState extends State<FeedScreen> { class _FeedScreenState extends State<FeedScreen> {
FeedMode _feedMode = FeedMode.entries; FeedMode _mode = FeedMode.entries;
FeedSort _sort = FeedSort.hot; FeedSort _sort = FeedSort.hot;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_sort = context.read<SettingsController>().defaultFeedSort; _mode = (widget.source ?? const FeedSourceAll()).getPostsPath() != null
? context.read<SettingsController>().defaultFeedMode
: FeedMode.entries;
_sort = widget.source == null
? context.read<SettingsController>().defaultFeedSort
: context.read<SettingsController>().defaultExploreFeedSort;
} }
@override @override
@ -76,10 +81,10 @@ class _FeedScreenState extends State<FeedScreen> {
tapTargetSize: MaterialTapTargetSize.shrinkWrap, tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: VisualDensity(horizontal: -3, vertical: -3), visualDensity: VisualDensity(horizontal: -3, vertical: -3),
), ),
selected: <FeedMode>{_feedMode}, selected: <FeedMode>{_mode},
onSelectionChanged: (Set<FeedMode> newSelection) { onSelectionChanged: (Set<FeedMode> newSelection) {
setState(() { setState(() {
_feedMode = newSelection.first; _mode = newSelection.first;
}); });
}, },
), ),
@ -99,7 +104,7 @@ class _FeedScreenState extends State<FeedScreen> {
}, },
icon: const Icon(Icons.sort), icon: const Icon(Icons.sort),
), ),
) ),
], ],
bottom: widget.source == null bottom: widget.source == null
? whenLoggedIn( ? whenLoggedIn(
@ -129,7 +134,7 @@ class _FeedScreenState extends State<FeedScreen> {
? FeedScreenBody( ? FeedScreenBody(
source: widget.source!, source: widget.source!,
sort: _sort, sort: _sort,
mode: _feedMode, mode: _mode,
details: widget.details, details: widget.details,
) )
: whenLoggedIn( : whenLoggedIn(
@ -139,25 +144,25 @@ class _FeedScreenState extends State<FeedScreen> {
FeedScreenBody( FeedScreenBody(
source: const FeedSourceSub(), source: const FeedSourceSub(),
sort: _sort, sort: _sort,
mode: _feedMode, mode: _mode,
details: widget.details, details: widget.details,
), ),
FeedScreenBody( FeedScreenBody(
source: const FeedSourceMod(), source: const FeedSourceMod(),
sort: _sort, sort: _sort,
mode: _feedMode, mode: _mode,
details: widget.details, details: widget.details,
), ),
FeedScreenBody( FeedScreenBody(
source: const FeedSourceFav(), source: const FeedSourceFav(),
sort: _sort, sort: _sort,
mode: _feedMode, mode: _mode,
details: widget.details, details: widget.details,
), ),
FeedScreenBody( FeedScreenBody(
source: const FeedSourceAll(), source: const FeedSourceAll(),
sort: _sort, sort: _sort,
mode: _feedMode, mode: _mode,
details: widget.details, details: widget.details,
), ),
], ],
@ -165,7 +170,7 @@ class _FeedScreenState extends State<FeedScreen> {
otherwise: FeedScreenBody( otherwise: FeedScreenBody(
source: const FeedSourceAll(), source: const FeedSourceAll(),
sort: _sort, sort: _sort,
mode: _feedMode, mode: _mode,
details: widget.details, details: widget.details,
), ),
), ),

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:interstellar/src/api/comment.dart';
import 'package:interstellar/src/api/post_comments.dart' as api_comments; import 'package:interstellar/src/api/post_comments.dart' as api_comments;
import 'package:interstellar/src/api/posts.dart' as api_posts; import 'package:interstellar/src/api/posts.dart' as api_posts;
import 'package:interstellar/src/models/post.dart'; import 'package:interstellar/src/models/post.dart';
@ -27,7 +28,7 @@ class PostPage extends StatefulWidget {
class _PostPageState extends State<PostPage> { class _PostPageState extends State<PostPage> {
PostModel? _data; PostModel? _data;
api_comments.CommentsSort commentsSort = api_comments.CommentsSort.hot; CommentSort commentSort = CommentSort.hot;
final PagingController<int, PostCommentModel> _pagingController = final PagingController<int, PostCommentModel> _pagingController =
PagingController(firstPageKey: 1); PagingController(firstPageKey: 1);
@ -37,6 +38,7 @@ class _PostPageState extends State<PostPage> {
super.initState(); super.initState();
_data = widget.initData; _data = widget.initData;
commentSort = context.read<SettingsController>().defaultCommentSort;
_pagingController.addPageRequestListener(_fetchPage); _pagingController.addPageRequestListener(_fetchPage);
} }
@ -55,7 +57,7 @@ class _PostPageState extends State<PostPage> {
context.read<SettingsController>().instanceHost, context.read<SettingsController>().instanceHost,
_data!.postId, _data!.postId,
page: pageKey, page: pageKey,
sort: commentsSort, sort: commentSort,
); );
// Check BuildContext // Check BuildContext
@ -86,6 +88,25 @@ class _PostPageState extends State<PostPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(_data?.user.username ?? ''), title: Text(_data?.user.username ?? ''),
actions: [
Padding(
padding: const EdgeInsets.only(right: 8),
child: IconButton(
onPressed: () async {
final newSort = await commentSortSelect.inquireSelection(
context, commentSort);
if (newSort != null && newSort != commentSort) {
setState(() {
commentSort = newSort;
_pagingController.refresh();
});
}
},
icon: const Icon(Icons.sort),
),
),
],
), ),
body: RefreshIndicator( body: RefreshIndicator(
onRefresh: () => Future.sync( onRefresh: () => Future.sync(
@ -149,48 +170,6 @@ class _PostPageState extends State<PostPage> {
: null, : null,
), ),
), ),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
DropdownButton<api_comments.CommentsSort>(
value: commentsSort,
onChanged: (newSort) {
if (newSort != null) {
setState(() {
commentsSort = newSort;
_pagingController.refresh();
});
}
},
items: const [
DropdownMenuItem(
value: api_comments.CommentsSort.hot,
child: Text('Hot'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.top,
child: Text('Top'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.newest,
child: Text('Newest'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.active,
child: Text('Active'),
),
DropdownMenuItem(
value: api_comments.CommentsSort.oldest,
child: Text('Oldest'),
),
],
),
],
),
),
),
PagedSliverList<int, PostCommentModel>( PagedSliverList<int, PostCommentModel>(
pagingController: _pagingController, pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<PostCommentModel>( builderDelegate: PagedChildBuilderDelegate<PostCommentModel>(

View File

@ -2,16 +2,24 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:interstellar/src/api/comment.dart';
import 'package:interstellar/src/api/feed_source.dart'; import 'package:interstellar/src/api/feed_source.dart';
import 'package:interstellar/src/api/oauth.dart'; import 'package:interstellar/src/api/oauth.dart';
import 'package:interstellar/src/screens/feed_screen.dart';
import 'package:oauth2/oauth2.dart' as oauth2; import 'package:oauth2/oauth2.dart' as oauth2;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
class SettingsController with ChangeNotifier { class SettingsController with ChangeNotifier {
late ThemeMode _themeMode; late ThemeMode _themeMode;
ThemeMode get themeMode => _themeMode; ThemeMode get themeMode => _themeMode;
late FeedMode _defaultFeedMode;
FeedMode get defaultFeedMode => _defaultFeedMode;
late FeedSort _defaultFeedSort; late FeedSort _defaultFeedSort;
FeedSort get defaultFeedSort => _defaultFeedSort; FeedSort get defaultFeedSort => _defaultFeedSort;
late FeedSort _defaultExploreFeedSort;
FeedSort get defaultExploreFeedSort => _defaultExploreFeedSort;
late CommentSort _defaultCommentSort;
CommentSort get defaultCommentSort => _defaultCommentSort;
late Map<String, String> _oauthIdentifiers; late Map<String, String> _oauthIdentifiers;
late Map<String, oauth2.Credentials?> _oauthCredentials; late Map<String, oauth2.Credentials?> _oauthCredentials;
@ -31,9 +39,18 @@ class SettingsController with ChangeNotifier {
_themeMode = prefs.getString('themeMode') != null _themeMode = prefs.getString('themeMode') != null
? ThemeMode.values.byName(prefs.getString("themeMode")!) ? ThemeMode.values.byName(prefs.getString("themeMode")!)
: ThemeMode.system; : ThemeMode.system;
_defaultFeedMode = prefs.getString('defaultFeedMode') != null
? FeedMode.values.byName(prefs.getString("defaultFeedMode")!)
: FeedMode.entries;
_defaultFeedSort = prefs.getString('defaultFeedSort') != null _defaultFeedSort = prefs.getString('defaultFeedSort') != null
? FeedSort.values.byName(prefs.getString("defaultFeedSort")!) ? FeedSort.values.byName(prefs.getString("defaultFeedSort")!)
: FeedSort.hot; : FeedSort.hot;
_defaultExploreFeedSort = prefs.getString('defaultExploreFeedSort') != null
? FeedSort.values.byName(prefs.getString("defaultExploreFeedSort")!)
: FeedSort.newest;
_defaultCommentSort = prefs.getString('defaultCommentSort') != null
? CommentSort.values.byName(prefs.getString("defaultCommentSort")!)
: CommentSort.hot;
_oauthIdentifiers = (jsonDecode(prefs.getString('oauthIdentifiers') ?? '{}') _oauthIdentifiers = (jsonDecode(prefs.getString('oauthIdentifiers') ?? '{}')
as Map<String, dynamic>) as Map<String, dynamic>)
@ -62,6 +79,19 @@ class SettingsController with ChangeNotifier {
await prefs.setString('themeMode', newThemeMode.name); await prefs.setString('themeMode', newThemeMode.name);
} }
Future<void> updateDefaultFeedMode(FeedMode? newDefaultFeedMode) async {
if (newDefaultFeedMode == null) return;
if (newDefaultFeedMode == _defaultFeedMode) return;
_defaultFeedMode = newDefaultFeedMode;
notifyListeners();
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('defaultFeedMode', newDefaultFeedMode.name);
}
Future<void> updateDefaultFeedSort(FeedSort? newDefaultFeedSort) async { Future<void> updateDefaultFeedSort(FeedSort? newDefaultFeedSort) async {
if (newDefaultFeedSort == null) return; if (newDefaultFeedSort == null) return;
@ -75,6 +105,37 @@ class SettingsController with ChangeNotifier {
await prefs.setString('defaultFeedSort', newDefaultFeedSort.name); await prefs.setString('defaultFeedSort', newDefaultFeedSort.name);
} }
Future<void> updateDefaultExploreFeedSort(
FeedSort? newDefaultExploreFeedSort,
) async {
if (newDefaultExploreFeedSort == null) return;
if (newDefaultExploreFeedSort == _defaultExploreFeedSort) return;
_defaultExploreFeedSort = newDefaultExploreFeedSort;
notifyListeners();
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(
'defaultExploreFeedSort', newDefaultExploreFeedSort.name);
}
Future<void> updateDefaultCommentSort(
CommentSort? newDefaultCommentSort,
) async {
if (newDefaultCommentSort == null) return;
if (newDefaultCommentSort == _defaultCommentSort) return;
_defaultCommentSort = newDefaultCommentSort;
notifyListeners();
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('defaultCommentSort', newDefaultCommentSort.name);
}
Future<String> getOAuthIdentifier(String instanceHost) async { Future<String> getOAuthIdentifier(String instanceHost) async {
if (_oauthIdentifiers.containsKey(instanceHost)) { if (_oauthIdentifiers.containsKey(instanceHost)) {
return _oauthIdentifiers[instanceHost]!; return _oauthIdentifiers[instanceHost]!;

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:interstellar/src/api/comment.dart';
import 'package:interstellar/src/screens/feed_screen.dart'; import 'package:interstellar/src/screens/feed_screen.dart';
import 'package:interstellar/src/screens/settings/login.dart'; import 'package:interstellar/src/screens/settings/login.dart';
import 'package:interstellar/src/widgets/selection_menu.dart';
import 'settings_controller.dart'; import 'settings_controller.dart';
@ -11,9 +13,21 @@ class SettingsScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final currentThemeMode = themeModeSelect.options.firstWhere(
(option) => option.value == controller.themeMode,
);
final currentDefaultFeedMode = feedModeSelect.options.firstWhere(
(option) => option.value == controller.defaultFeedMode,
);
final currentDefaultFeedSort = feedSortSelect.options.firstWhere( final currentDefaultFeedSort = feedSortSelect.options.firstWhere(
(option) => option.value == controller.defaultFeedSort, (option) => option.value == controller.defaultFeedSort,
); );
final currentDefaultExploreFeedSort = feedSortSelect.options.firstWhere(
(option) => option.value == controller.defaultExploreFeedSort,
);
final currentDefaultCommentSort = commentSortSelect.options.firstWhere(
(option) => option.value == controller.defaultCommentSort,
);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@ -27,28 +41,50 @@ class SettingsScreen extends StatelessWidget {
child: child:
Text('Theme', style: Theme.of(context).textTheme.titleMedium), Text('Theme', style: Theme.of(context).textTheme.titleMedium),
), ),
DropdownButton<ThemeMode>( ListTile(
value: controller.themeMode, title: const Text('Theme Mode'),
onChanged: controller.updateThemeMode, leading: const Icon(Icons.palette),
items: const [ onTap: () async {
DropdownMenuItem( controller.updateThemeMode(
value: ThemeMode.system, await themeModeSelect.inquireSelection(
child: Text('System Theme'), context,
), currentThemeMode.value,
DropdownMenuItem( ),
value: ThemeMode.light, );
child: Text('Light Theme'), },
), trailing: Row(
DropdownMenuItem( mainAxisSize: MainAxisSize.min,
value: ThemeMode.dark, children: [
child: Text('Dark Theme'), Icon(currentThemeMode.icon),
) const SizedBox(width: 4),
], Text(currentThemeMode.title),
],
),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 8),
child: Text('Feed', style: Theme.of(context).textTheme.titleMedium), child: Text('Feed', style: Theme.of(context).textTheme.titleMedium),
), ),
ListTile(
title: const Text('Default Feed Mode'),
leading: const Icon(Icons.tab),
onTap: () async {
controller.updateDefaultFeedMode(
await feedModeSelect.inquireSelection(
context,
currentDefaultFeedMode.value,
),
);
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(currentDefaultFeedMode.icon),
const SizedBox(width: 4),
Text(currentDefaultFeedMode.title),
],
),
),
ListTile( ListTile(
title: const Text('Default Feed Sort'), title: const Text('Default Feed Sort'),
leading: const Icon(Icons.sort), leading: const Icon(Icons.sort),
@ -69,6 +105,46 @@ class SettingsScreen extends StatelessWidget {
], ],
), ),
), ),
ListTile(
title: const Text('Default Explore Feed Sort'),
leading: const Icon(Icons.sort),
onTap: () async {
controller.updateDefaultExploreFeedSort(
await feedSortSelect.inquireSelection(
context,
currentDefaultExploreFeedSort.value,
),
);
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(currentDefaultExploreFeedSort.icon),
const SizedBox(width: 4),
Text(currentDefaultExploreFeedSort.title),
],
),
),
ListTile(
title: const Text('Default Comment Sort'),
leading: const Icon(Icons.comment),
onTap: () async {
controller.updateDefaultCommentSort(
await commentSortSelect.inquireSelection(
context,
currentDefaultCommentSort.value,
),
);
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(currentDefaultCommentSort.icon),
const SizedBox(width: 4),
Text(currentDefaultCommentSort.title),
],
),
),
Padding( Padding(
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 8),
child: Text('Accounts', child: Text('Accounts',
@ -110,19 +186,58 @@ class SettingsScreen extends StatelessWidget {
}, },
icon: const Icon(Icons.delete_outline)), icon: const Icon(Icons.delete_outline)),
)), )),
const SizedBox(height: 8), Padding(
OutlinedButton( padding: const EdgeInsets.all(8.0),
onPressed: () { child: OutlinedButton(
Navigator.of(context).push( onPressed: () {
MaterialPageRoute( Navigator.of(context).push(
builder: (context) => const LoginScreen(), MaterialPageRoute(
), builder: (context) => const LoginScreen(),
); ),
}, );
child: const Text('Add Account'), },
child: const Text('Add Account'),
),
) )
], ],
), ),
); );
} }
} }
const SelectionMenu<ThemeMode> themeModeSelect = SelectionMenu(
'Theme Mode',
[
SelectionMenuItem(
value: ThemeMode.system,
title: 'System',
icon: Icons.auto_mode,
),
SelectionMenuItem(
value: ThemeMode.light,
title: 'Light',
icon: Icons.light_mode,
),
SelectionMenuItem(
value: ThemeMode.dark,
title: 'Dark',
icon: Icons.dark_mode,
),
],
);
const SelectionMenu<FeedMode> feedModeSelect = SelectionMenu(
'Feed Mode',
[
SelectionMenuItem(
value: FeedMode.entries,
title: 'Threads',
icon: Icons.feed,
),
SelectionMenuItem(
value: FeedMode.posts,
title: 'Posts',
icon: Icons.chat,
),
],
);