Skip to content

Commit

Permalink
Add new community stats (#1449)
Browse files Browse the repository at this point in the history
  • Loading branch information
micahmo authored Jun 21, 2024
1 parent 036e681 commit c9e5fa7
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 25 deletions.
64 changes: 45 additions & 19 deletions lib/community/widgets/community_sidebar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:lemmy_api_client/v3.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import 'package:thunder/community/bloc/community_bloc.dart';
import 'package:thunder/community/enums/community_action.dart';
Expand Down Expand Up @@ -43,6 +44,7 @@ class _CommunitySidebarState extends State<CommunitySidebar> {

@override
Widget build(BuildContext context) {
final AppLocalizations l10n = AppLocalizations.of(context)!;
final theme = Theme.of(context);
final bool isUserLoggedIn = context.read<AuthBloc>().state.isLoggedIn;

Expand Down Expand Up @@ -115,18 +117,18 @@ class _CommunitySidebarState extends State<CommunitySidebar> {
imageMaxWidth: (kSidebarWidthFactor - 0.1) * MediaQuery.of(context).size.width,
),
),
const SidebarSectionHeader(value: "Stats"),
SidebarSectionHeader(value: l10n.stats),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: CommunityStatsList(communityView: communityView),
),
const SidebarSectionHeader(value: "Moderators"),
SidebarSectionHeader(value: l10n.moderator(2)),
CommunityModeratorList(getCommunityResponse: widget.getCommunityResponse!),
Container(
child: widget.getCommunityResponse!.site != null
? Column(
children: [
const SidebarSectionHeader(value: "Host Instance"),
SidebarSectionHeader(value: l10n.hostInstance),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: InstanceView(
Expand Down Expand Up @@ -159,43 +161,63 @@ class CommunityStatsList extends StatelessWidget {

@override
Widget build(BuildContext context) {
final AppLocalizations l10n = AppLocalizations.of(context)!;

return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (communityView.community.visibility != null) ...[
SidebarStat(
icon: switch (communityView.community.visibility!) {
CommunityVisibility.public => Icons.language_rounded,
CommunityVisibility.localOnly => Icons.house_rounded,
},
value: l10n.visibility(switch (communityView.community.visibility!) {
CommunityVisibility.public => l10n.public,
CommunityVisibility.localOnly => l10n.localOnly,
}),
),
const SizedBox(height: 8.0),
],
// TODO Make this use device date format
SidebarStat(
icon: Icons.cake_rounded,
value: 'Created ${DateFormat.yMMMMd().format(communityView.community.published)} · ${formatTimeToString(dateTime: communityView.community.published.toIso8601String())} ago',
value: '${l10n.created(DateFormat.yMMMMd().format(communityView.community.published))} · ${l10n.ago(formatTimeToString(dateTime: communityView.community.published.toIso8601String()))}',
),
const SizedBox(height: 8.0),
SidebarStat(
icon: Icons.people_rounded,
value: '${NumberFormat("#,###,###,###").format(communityView.counts.subscribers)} Subscribers',
value: l10n.countSubscribers(NumberFormat("#,###,###,###").format(communityView.counts.subscribers)),
),
if (communityView.counts.subscribersLocal != null)
SidebarStat(
icon: Icons.people_rounded,
value: l10n.countLocalSubscribers(NumberFormat("#,###,###,###").format(communityView.counts.subscribersLocal)),
),
SidebarStat(
icon: Icons.wysiwyg_rounded,
value: '${NumberFormat("#,###,###,###").format(communityView.counts.posts)} Posts',
value: l10n.countPosts(NumberFormat("#,###,###,###").format(communityView.counts.posts)),
),
SidebarStat(
icon: Icons.chat_rounded,
value: '${NumberFormat("#,###,###,###").format(communityView.counts.comments)} Comments',
value: l10n.countComments(NumberFormat("#,###,###,###").format(communityView.counts.comments)),
),
const SizedBox(height: 8.0),
SidebarStat(
icon: Icons.calendar_month_rounded,
value: '${NumberFormat("#,###,###,###").format(communityView.counts.usersActiveHalfYear)} users/6 mo',
value: l10n.countUsersActiveHalfYear(NumberFormat("#,###,###,###").format(communityView.counts.usersActiveHalfYear)),
),
SidebarStat(
icon: Icons.calendar_view_month_rounded,
value: '${NumberFormat("#,###,###,###").format(communityView.counts.usersActiveMonth)} users/mo',
value: l10n.countUsersActiveMonth(NumberFormat("#,###,###,###").format(communityView.counts.usersActiveMonth)),
),
SidebarStat(
icon: Icons.calendar_view_week_rounded,
value: '${NumberFormat("#,###,###,###").format(communityView.counts.usersActiveWeek)} users/wk',
value: l10n.countUsersActiveWeek(NumberFormat("#,###,###,###").format(communityView.counts.usersActiveWeek)),
),
SidebarStat(
icon: Icons.calendar_view_day_rounded,
value: '${NumberFormat("#,###,###,###").format(communityView.counts.usersActiveDay)} users/day',
value: l10n.countUsersActiveDay(NumberFormat("#,###,###,###").format(communityView.counts.usersActiveDay)),
),
],
);
Expand Down Expand Up @@ -276,6 +298,8 @@ class BlockCommunityButton extends StatelessWidget {

@override
Widget build(BuildContext context) {
final AppLocalizations l10n = AppLocalizations.of(context)!;

return BlocBuilder<CommunityBloc, CommunityState>(
builder: (context, state) {
bool blocked = false;
Expand Down Expand Up @@ -305,7 +329,7 @@ class BlockCommunityButton extends StatelessWidget {
children: [
Icon(blocked ? Icons.undo_rounded : Icons.block_rounded),
const SizedBox(width: 4.0),
Text(blocked ? 'Unblock Community' : 'Block Community'),
Text(blocked ? l10n.unblockCommunity : l10n.blockCommunity),
],
),
),
Expand All @@ -323,6 +347,8 @@ class CommunityActions extends StatelessWidget {

@override
Widget build(BuildContext context) {
final AppLocalizations l10n = AppLocalizations.of(context)!;

CommunityView communityView = getCommunityResponse.communityView;

return Row(
Expand All @@ -342,12 +368,12 @@ class CommunityActions extends StatelessWidget {
),
child: Semantics(
focused: true,
child: const Row(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.library_books_rounded),
SizedBox(width: 4.0),
Text('New Post', style: TextStyle(color: null)),
const Icon(Icons.library_books_rounded),
const SizedBox(width: 4.0),
Text(l10n.newPost, style: const TextStyle(color: null)),
],
),
),
Expand Down Expand Up @@ -381,9 +407,9 @@ class CommunityActions extends StatelessWidget {
const SizedBox(width: 4.0),
Text(
switch (communityView.subscribed) {
SubscribedType.notSubscribed => 'Subscribe',
SubscribedType.pending => 'Pending...',
SubscribedType.subscribed => 'Unsubscribe',
SubscribedType.notSubscribed => l10n.subscribe,
SubscribedType.pending => '${l10n.pending}...',
SubscribedType.subscribed => l10n.unsubscribe,
},
),
],
Expand Down
70 changes: 66 additions & 4 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@
"@advanced": {
"description": "Heading for advanced settings"
},
"ago": "{time} ago",
"@ago": {
"description": "Represents a duration in the past"
},
"all": "All",
"@all": {},
"allPosts": "All Posts",
Expand Down Expand Up @@ -475,12 +479,42 @@
"@couldntFindPost": {
"description": "Error message for when we can't load a post."
},
"countSubscribers": "{count} subscribers",
"@countSubscribers": {},
"countComments": "{count} Comments",
"@countComments": {
"description": "Number of comments"
},
"countLocalSubscribers": "{count} Local Subscribers",
"@countLocalSubscribers": {
"description": "Number of local subscribers"
},
"countPosts": "{count} Posts",
"@countPosts": {
"description": "Number of posts"
},
"countSubscribers": "{count} Subscribers",
"@countSubscribers": {
"description": "Number of subscribers"
},
"countUsers": "{count} users",
"@countUsers": {
"description": "Describes a certain number of users"
},
"countUsersActiveDay": "{count} users/day",
"@countUsersActiveDay": {
"description": "Number of users active in the last day"
},
"countUsersActiveHalfYear": "{count} users/6 mo",
"@countUsersActiveHalfYear": {
"description": "Number of users active in the last half year"
},
"countUsersActiveMonth": "{count} users/mo",
"@countUsersActiveMonth": {
"description": "Number of users active in the last month"
},
"countUsersActiveWeek": "{count} users/wk",
"@countUsersActiveWeek": {
"description": "Number of users active in the last week"
},
"createAccount": "Create Account",
"@createAccount": {},
"createComment": "Create Comment",
Expand All @@ -489,6 +523,10 @@
"@createNewCrossPost": {},
"createPost": "Create Post",
"@createPost": {},
"created": "Created {date}",
"@created": {
"description": "The date that something was created"
},
"createdToday": "Created Today",
"@createdToday": {
"description": "An account descriptor for an account with a birthday today"
Expand Down Expand Up @@ -927,6 +965,10 @@
"@hideTopBarOnScroll": {
"description": "Settings toggle to hide the top bar on scroll"
},
"hostInstance": "Host Instance",
"@hostInstance": {
"description": "The instance hosting a community"
},
"hot": "Hot",
"@hot": {},
"image": "Image",
Expand Down Expand Up @@ -1103,6 +1145,10 @@
"@localNotifications": {
"description": "Describes the notification type for Local Notifications"
},
"localOnly": "Local Only",
"@localOnly": {
"description": "Local community visibility"
},
"localPosts": "Local Posts",
"@localPosts": {},
"lockPost": "Lock Post",
Expand Down Expand Up @@ -1217,7 +1263,7 @@
"@moderatedCommunities": {
"description": "Describes a list of communities that are moderated by the current user."
},
"moderator": "Moderator",
"moderator": "{count, plural, zero {Moderator} one {Moderator} other {Moderators}}",
"@moderator": {
"description": "Role name for moderator"
},
Expand Down Expand Up @@ -1543,6 +1589,10 @@
},
"profiles": "Profiles",
"@profiles": {},
"public": "Public",
"@public": {
"description": "Public community visibility"
},
"pureBlack": "Pure Black",
"@pureBlack": {
"description": "Describes using the pure black theme"
Expand Down Expand Up @@ -2071,6 +2121,10 @@
"@standard": {
"description": "Describes a standard visual density"
},
"stats": "Stats",
"@stats": {
"description": "Community statistics"
},
"status": "Status",
"@status": {
"description": "Status of the action"
Expand Down Expand Up @@ -2301,6 +2355,10 @@
"@unbannedUserFromCommunity": {
"description": "Short decription for moderator action to unban a user from a community"
},
"unblockCommunity": "Unblock Community",
"@unblockCommunity": {
"description": "Action to unblock a community"
},
"unblockInstance": "Unblock Instance",
"@unblockInstance": {
"description": "Tooltip for unblocking an instance"
Expand Down Expand Up @@ -2545,6 +2603,10 @@
"@viewingAll": {
"description": "Chip for viewing all possible search results"
},
"visibility": "Visibility: {visibility}",
"@visibility": {
"description": "Visibility heading for community"
},
"visitCommunity": "Visit Community",
"@visitCommunity": {},
"visitInstance": "Visit Instance",
Expand All @@ -2563,7 +2625,7 @@
},
"xUpvotes": "{x} upvotes",
"@xUpvotes": {},
"xYearsOld": "{count, plural, zero {{x} years old} one {{x} year old} other {{x} years old}}",
"xYearsOld": "{count, plural, zero {{x} year old} one {{x} year old} other {{x} years old}}",
"@xYearsOld": {
"description": "An account descriptor representing how old an account is"
},
Expand Down
2 changes: 1 addition & 1 deletion lib/modlog/view/modlog_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class _ModlogFeedViewState extends State<ModlogFeedView> {
case ModlogActionType.adminPurgePerson:
return l10n.admin;
default:
return l10n.moderator;
return l10n.moderator(1);
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/user/utils/user_groups.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ String fetchUserGroupDescriptor(List<UserType> userGroups, Person? person) {
if (userGroups.contains(UserType.op)) descriptors.add(l10n.originalPoster);
if (userGroups.contains(UserType.self)) descriptors.add(l10n.me);
if (userGroups.contains(UserType.admin)) descriptors.add(l10n.admin);
if (userGroups.contains(UserType.moderator)) descriptors.add(l10n.moderator);
if (userGroups.contains(UserType.moderator)) descriptors.add(l10n.moderator(1));
if (userGroups.contains(UserType.bot)) descriptors.add(l10n.bot);
if (descriptors.isNotEmpty) descriptor = ' (${descriptors.join(', ')})';

Expand Down

0 comments on commit c9e5fa7

Please sign in to comment.