Skip to content

Commit

Permalink
Support new sort types controversial and scaled (#829)
Browse files Browse the repository at this point in the history
* Support new sort types

* Update API package

* Remove unnecessary strings

* Invert logic for less nesting

* Invert if to reduce nesting

* Simplify feature version checking
  • Loading branch information
micahmo authored Oct 20, 2023
1 parent e57228a commit 2e220d6
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 72 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Introduced support for reporting comments. - contribution from @ggichure
- Added ability to create post from home feed - contribution from @micahmo
- Added option to enter reader mode when tapping on a link in iOS
- Support new scaled and controversial sort types - contribution from @micahmo
- Added support to open Lemmy links in app. Android only. - contribution from @ggichure

### Changed
Expand Down
62 changes: 62 additions & 0 deletions lib/core/singletons/lemmy_client.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'package:lemmy_api_client/v3.dart';
import 'package:thunder/account/models/account.dart';
import 'package:thunder/core/auth/helpers/fetch_account.dart';
import 'package:version/version.dart';

class LemmyClient {
LemmyApiV3 lemmyApiV3 = const LemmyApiV3('');
Expand All @@ -7,9 +10,68 @@ class LemmyClient {

void changeBaseUrl(String baseUrl) {
lemmyApiV3 = LemmyApiV3(baseUrl);
_populateSiteInfo(); // Do NOT await this. Let it populate in the background.
}

static final LemmyClient _instance = LemmyClient._initialize();

static LemmyClient get instance => _instance;

Future<void> _populateSiteInfo() async {
if (_lemmySites.containsKey(instance.lemmyApiV3.host)) return;

// Retrieve the site so we can look up metadata about it later
Account? account = await fetchActiveProfileAccount();

_lemmySites[instance.lemmyApiV3.host] = await instance.lemmyApiV3.run(
GetSite(
auth: account?.jwt,
),
);
}

bool supportsFeature(LemmyFeature feature) {
if (!_lemmySites.containsKey(instance.lemmyApiV3.host)) return false;

// Parse the version
FullSiteView site = _lemmySites[instance.lemmyApiV3.host]!;
Version instanceVersion;
try {
instanceVersion = Version.parse(site.version);
} catch (e) {
return false;
}

// Check the feature and return whether it's supported in this version
return instanceVersion > feature.minSupportedVersion;
}

static final Map<String, FullSiteView> _lemmySites = <String, FullSiteView>{};
}

enum LemmyFeature {
sortTypeControversial(0, 19, 0, preRelease: ["rc", "1"]),
sortTypeScaled(0, 19, 0, preRelease: ["rc", "1"]),
commentSortTypeControversial(0, 19, 0, preRelease: ["rc", "1"]);

final int major;
final int minor;
final int patch;
final List<String> preRelease;

const LemmyFeature(this.major, this.minor, this.patch, {this.preRelease = const []});

Version get minSupportedVersion => Version(
major,
minor,
patch,
// The Version package attempts to modify this list, so give them a non-final copy.
preRelease: List.from(preRelease),
);
}

enum IncludeVersionSpecificFeature {
never,
ifSupported,
always,
}
1 change: 1 addition & 0 deletions lib/feed/widgets/feed_fab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ class FeedFAB extends StatelessWidget {
showModalBottomSheet<void>(
showDragHandle: true,
context: context,
isScrollControlled: true,
builder: (builderContext) => SortPicker(
title: l10n.sortOptions,
onSelect: (selected) => context.read<FeedBloc>().add(FeedChangeSortTypeEvent(selected.payload)),
Expand Down
1 change: 1 addition & 0 deletions lib/feed/widgets/feed_page_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class FeedPageAppBar extends StatelessWidget {
showModalBottomSheet<void>(
showDragHandle: true,
context: context,
isScrollControlled: true,
builder: (builderContext) => SortPicker(
title: l10n.sortOptions,
onSelect: (selected) => feedBloc.add(FeedChangeSortTypeEvent(selected.payload)),
Expand Down
2 changes: 2 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@
"@upvote": {},
"downvote": "Downvote",
"@downvote": {},
"scaled": "Scaled",
"controversial": "Controversial",
"edit": "Edit",
"@edit": {},
"restore": "Restore",
Expand Down
4 changes: 3 additions & 1 deletion lib/post/pages/post_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:thunder/core/auth/bloc/auth_bloc.dart';
import 'package:thunder/core/enums/fab_action.dart';
import 'package:thunder/core/enums/local_settings.dart';
import 'package:thunder/core/models/post_view_media.dart';
import 'package:thunder/core/singletons/lemmy_client.dart';
import 'package:thunder/core/singletons/preferences.dart';
import 'package:thunder/post/bloc/post_bloc.dart';
import 'package:thunder/post/pages/post_page_success.dart';
Expand Down Expand Up @@ -121,7 +122,8 @@ class _PostPageState extends State<PostPage> {
if (previousState.sortType != currentState.sortType) {
setState(() {
sortType = currentState.sortType;
final sortTypeItem = commentSortTypeItems.firstWhere((sortTypeItem) => sortTypeItem.payload == currentState.sortType);
final sortTypeItem = CommentSortPicker.getCommentSortTypeItems(includeVersionSpecificFeature: IncludeVersionSpecificFeature.always)
.firstWhere((sortTypeItem) => sortTypeItem.payload == currentState.sortType);
sortTypeIcon = sortTypeItem.icon;
sortTypeLabel = sortTypeItem.label;
});
Expand Down
17 changes: 13 additions & 4 deletions lib/settings/pages/general_settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:permission_handler/permission_handler.dart';

import 'package:thunder/core/enums/local_settings.dart';
import 'package:thunder/core/enums/nested_comment_indicator.dart';
import 'package:thunder/core/singletons/lemmy_client.dart';
import 'package:thunder/core/singletons/preferences.dart';
import 'package:thunder/settings/widgets/list_option.dart';
import 'package:thunder/settings/widgets/settings_list_tile.dart';
Expand Down Expand Up @@ -416,11 +417,12 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> with SingleTi
ListOption(
description: LocalSettings.defaultFeedSortType.label,
value: ListPickerItem(label: defaultSortType.value, icon: Icons.local_fire_department_rounded, payload: defaultSortType),
options: allSortTypeItems,
options: [...SortPicker.getDefaultSortTypeItems(includeVersionSpecificFeature: IncludeVersionSpecificFeature.never), ...topSortTypeItems],
icon: Icons.sort_rounded,
onChanged: (_) {},
isBottomModalScrollControlled: true,
customListPicker: SortPicker(
includeVersionSpecificFeature: IncludeVersionSpecificFeature.never,
title: LocalSettings.defaultFeedSortType.label,
onSelect: (value) {
setPreferences(LocalSettings.defaultFeedSortType, value.payload.name);
Expand Down Expand Up @@ -627,10 +629,11 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> with SingleTi
ListOption(
description: LocalSettings.defaultCommentSortType.label,
value: ListPickerItem(label: defaultCommentSortType.value, icon: Icons.local_fire_department_rounded, payload: defaultCommentSortType),
options: commentSortTypeItems,
options: CommentSortPicker.getCommentSortTypeItems(includeVersionSpecificFeature: IncludeVersionSpecificFeature.never),
icon: Icons.comment_bank_rounded,
onChanged: (_) {},
customListPicker: CommentSortPicker(
includeVersionSpecificFeature: IncludeVersionSpecificFeature.never,
title: l10n.commentSortType,
onSelect: (value) {
setPreferences(LocalSettings.defaultCommentSortType, value.payload.name);
Expand All @@ -639,10 +642,16 @@ class _GeneralSettingsPageState extends State<GeneralSettingsPage> with SingleTi
),
valueDisplay: Row(
children: [
Icon(commentSortTypeItems.firstWhere((sortTypeItem) => sortTypeItem.payload == defaultCommentSortType).icon, size: 13),
Icon(
CommentSortPicker.getCommentSortTypeItems(includeVersionSpecificFeature: IncludeVersionSpecificFeature.always)
.firstWhere((sortTypeItem) => sortTypeItem.payload == defaultCommentSortType)
.icon,
size: 13),
const SizedBox(width: 4),
Text(
commentSortTypeItems.firstWhere((sortTypeItem) => sortTypeItem.payload == defaultCommentSortType).label,
CommentSortPicker.getCommentSortTypeItems(includeVersionSpecificFeature: IncludeVersionSpecificFeature.always)
.firstWhere((sortTypeItem) => sortTypeItem.payload == defaultCommentSortType)
.label,
style: theme.textTheme.titleSmall,
),
],
Expand Down
79 changes: 48 additions & 31 deletions lib/shared/comment_sort_picker.dart
Original file line number Diff line number Diff line change
@@ -1,41 +1,58 @@
import 'package:flutter/material.dart';
import 'package:lemmy_api_client/v3.dart';
import 'package:thunder/core/singletons/lemmy_client.dart';
import 'package:thunder/shared/picker_item.dart';
import 'package:thunder/utils/bottom_sheet_list_picker.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/utils/global_context.dart';

List<ListPickerItem<CommentSortType>> commentSortTypeItems = [
ListPickerItem(
payload: CommentSortType.top,
icon: Icons.military_tech,
label: AppLocalizations.of(GlobalContext.context)!.top,
),
ListPickerItem(
payload: CommentSortType.old,
icon: Icons.access_time_outlined,
label: AppLocalizations.of(GlobalContext.context)!.old,
),
ListPickerItem(
payload: CommentSortType.new_,
icon: Icons.auto_awesome_rounded,
label: AppLocalizations.of(GlobalContext.context)!.new_,
),
ListPickerItem(
payload: CommentSortType.hot,
icon: Icons.local_fire_department,
label: AppLocalizations.of(GlobalContext.context)!.hot,
),
//
// ListPickerItem(
// payload: CommentSortType.chat,
// icon: Icons.chat,
// label: 'Chat',
// ),
];

class CommentSortPicker extends BottomSheetListPicker<CommentSortType> {
CommentSortPicker({super.key, required super.onSelect, required super.title, List<ListPickerItem<CommentSortType>>? items, super.previouslySelected}) : super(items: items ?? commentSortTypeItems);
final IncludeVersionSpecificFeature includeVersionSpecificFeature;

static List<ListPickerItem<CommentSortType>> getCommentSortTypeItems({IncludeVersionSpecificFeature includeVersionSpecificFeature = IncludeVersionSpecificFeature.ifSupported}) => [
ListPickerItem(
payload: CommentSortType.top,
icon: Icons.military_tech,
label: AppLocalizations.of(GlobalContext.context)!.top,
),
ListPickerItem(
payload: CommentSortType.old,
icon: Icons.access_time_outlined,
label: AppLocalizations.of(GlobalContext.context)!.old,
),
if (includeVersionSpecificFeature == IncludeVersionSpecificFeature.always ||
(includeVersionSpecificFeature == IncludeVersionSpecificFeature.ifSupported && LemmyClient.instance.supportsFeature(LemmyFeature.commentSortTypeControversial)))
ListPickerItem(
payload: CommentSortType.controversial,
icon: Icons.warning_rounded,
label: AppLocalizations.of(GlobalContext.context)!.controversial,
),
ListPickerItem(
payload: CommentSortType.new_,
icon: Icons.auto_awesome_rounded,
label: AppLocalizations.of(GlobalContext.context)!.new_,
),
ListPickerItem(
payload: CommentSortType.hot,
icon: Icons.local_fire_department,
label: AppLocalizations.of(GlobalContext.context)!.hot,
),
//
// ListPickerItem(
// payload: CommentSortType.chat,
// icon: Icons.chat,
// label: 'Chat',
// ),
];

CommentSortPicker(
{super.key,
required super.onSelect,
required super.title,
List<ListPickerItem<CommentSortType>>? items,
super.previouslySelected,
this.includeVersionSpecificFeature = IncludeVersionSpecificFeature.ifSupported})
: super(items: items ?? CommentSortPicker.getCommentSortTypeItems(includeVersionSpecificFeature: includeVersionSpecificFeature));

@override
State<StatefulWidget> createState() => _SortPickerState();
Expand Down Expand Up @@ -79,7 +96,7 @@ class _SortPickerState extends State<CommentSortPicker> {
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
children: [
..._generateList(commentSortTypeItems, theme),
..._generateList(CommentSortPicker.getCommentSortTypeItems(includeVersionSpecificFeature: widget.includeVersionSpecificFeature), theme),
],
),
const SizedBox(height: 16.0),
Expand Down
Loading

0 comments on commit 2e220d6

Please sign in to comment.