Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:hjiangsu/thunder into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
hjiangsu committed Jul 11, 2023
2 parents 83d6b51 + 6fb32ab commit c209136
Show file tree
Hide file tree
Showing 16 changed files with 369 additions and 70 deletions.
67 changes: 53 additions & 14 deletions lib/account/pages/login_page.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import 'dart:async';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';

import 'package:thunder/core/auth/bloc/auth_bloc.dart';
import 'package:thunder/utils/instance.dart';
import 'package:thunder/utils/text_input_formatter.dart';

class LoginPage extends StatefulWidget {
Expand All @@ -24,6 +28,9 @@ class _LoginPageState extends State<LoginPage> {

bool showPassword = false;
bool fieldsFilledIn = false;
String? instanceIcon;
String? currentInstance;
Timer? instanceTextDebounceTimer;

@override
void initState() {
Expand All @@ -49,12 +56,30 @@ class _LoginPageState extends State<LoginPage> {
}
});

_instanceTextEditingController.addListener(() {
_instanceTextEditingController.addListener(() async {
if (currentInstance != _instanceTextEditingController.text) {
setState(() => instanceIcon = null);
currentInstance = _instanceTextEditingController.text;
}

if (_usernameTextEditingController.text.isNotEmpty && _passwordTextEditingController.text.isNotEmpty && _instanceTextEditingController.text.isNotEmpty) {
setState(() => fieldsFilledIn = true);
} else {
setState(() => fieldsFilledIn = false);
}

// Debounce
if (instanceTextDebounceTimer?.isActive == true) {
instanceTextDebounceTimer!.cancel();
}
instanceTextDebounceTimer = Timer(const Duration(milliseconds: 500), () async {
await getInstanceIcon(_instanceTextEditingController.text).then((value) {
// Make sure the icon we looked up still matches the text
if (currentInstance == _instanceTextEditingController.text) {
setState(() => instanceIcon = value);
}
});
});
});
}

Expand Down Expand Up @@ -82,8 +107,34 @@ class _LoginPageState extends State<LoginPage> {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset('assets/logo.png', width: 196.0, height: 196.0),
AnimatedCrossFade(
duration: const Duration(milliseconds: 500),
crossFadeState: instanceIcon == null
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
firstChild: Image.asset('assets/logo.png', width: 80.0, height: 80.0),
secondChild: instanceIcon == null
? Container()
: CircleAvatar(
foregroundImage: CachedNetworkImageProvider(instanceIcon!),
backgroundColor: Colors.transparent,
maxRadius: 40,
),
),
const SizedBox(height: 12.0),
TextField(
autocorrect: false,
controller: _instanceTextEditingController,
inputFormatters: [LowerCaseTextFormatter()],
decoration: const InputDecoration(
isDense: true,
border: OutlineInputBorder(),
labelText: 'Instance',
hintText: 'e.g., lemmy.ml, lemmy.world, etc.',
),
enableSuggestions: false,
),
const SizedBox(height: 35.0),
AutofillGroup(
child: Column(
children: <Widget>[
Expand Down Expand Up @@ -145,18 +196,6 @@ class _LoginPageState extends State<LoginPage> {
enableSuggestions: false,
),
const SizedBox(height: 12.0),
TextField(
autocorrect: false,
controller: _instanceTextEditingController,
inputFormatters: [LowerCaseTextFormatter()],
decoration: const InputDecoration(
isDense: true,
border: OutlineInputBorder(),
labelText: 'Instance',
hintText: 'lemmy.ml',
),
enableSuggestions: false,
),
const SizedBox(height: 32.0),
ElevatedButton(
style: ElevatedButton.styleFrom(
Expand Down
47 changes: 35 additions & 12 deletions lib/account/widgets/profile_modal_body.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';

import 'package:flutter_bloc/flutter_bloc.dart';
Expand All @@ -7,6 +8,7 @@ import 'package:thunder/account/models/account.dart';
import 'package:thunder/account/pages/login_page.dart';
import 'package:thunder/core/auth/bloc/auth_bloc.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/utils/instance.dart';

class ProfileModalBody extends StatelessWidget {
const ProfileModalBody({super.key});
Expand Down Expand Up @@ -79,22 +81,28 @@ class ProfileSelect extends StatelessWidget {
);
} else {
return ListTile(
leading: Icon(
Icons.person,
color: currentAccountId == snapshot.data![index].id ? Colors.amber : null,
),
leading: snapshot.data![index].instanceIcon == null
? const Icon(
Icons.person,
)
: CircleAvatar(
backgroundColor: Colors.transparent,
foregroundImage: snapshot.data![index].instanceIcon == null
? null
: CachedNetworkImageProvider(snapshot.data![index].instanceIcon!),
),
title: Text(
snapshot.data![index].username ?? 'N/A',
snapshot.data![index].account.username ?? 'N/A',
style: theme.textTheme.titleMedium?.copyWith(),
),
subtitle: Text(snapshot.data![index].instance?.replaceAll('https://', '') ?? 'N/A'),
onTap: (currentAccountId == snapshot.data![index].id)
subtitle: Text(snapshot.data![index].account.instance?.replaceAll('https://', '') ?? 'N/A'),
onTap: (currentAccountId == snapshot.data![index].account.id)
? null
: () {
context.read<AuthBloc>().add(SwitchAccount(accountId: snapshot.data![index].id));
context.read<AuthBloc>().add(SwitchAccount(accountId: snapshot.data![index].account.id));
context.pop();
},
trailing: (currentAccountId == snapshot.data![index].id)
trailing: (currentAccountId == snapshot.data![index].account.id)
? const InputChip(
label: Text('Active'),
visualDensity: VisualDensity.compact,
Expand All @@ -105,7 +113,7 @@ class ProfileSelect extends StatelessWidget {
semanticLabel: 'Remove Account',
),
onPressed: () {
context.read<AuthBloc>().add(RemoveAccount(accountId: snapshot.data![index].id));
context.read<AuthBloc>().add(RemoveAccount(accountId: snapshot.data![index].account.id));
context.pop();
}),
);
Expand All @@ -120,8 +128,23 @@ class ProfileSelect extends StatelessWidget {
);
}

Future<List<Account>> fetchAccounts() async {
List<Account> accounts = await Account.accounts();
Future<List<AccountExtended>> fetchAccounts() async {
List<AccountExtended> accounts = await Future.wait((await Account.accounts()).map((account) async {
final instanceIcon = await getInstanceIcon(account.instance);
return AccountExtended(account: account, instanceIcon: instanceIcon);
}).toList());

return accounts;
}
}

/// Wrapper class around Account with support for instance icon
class AccountExtended {
final Account account;
final String? instanceIcon;

const AccountExtended({
required this.account,
this.instanceIcon
});
}
7 changes: 3 additions & 4 deletions lib/community/widgets/community_header.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ class CommunityHeader extends StatelessWidget {
style: theme.textTheme.headlineSmall?.copyWith(fontWeight: FontWeight.w600),
),
Text(
fetchInstanceNameFromUrl(communityInfo?.communityView.community.actorId) ?? 'N/A',
style: theme.textTheme.titleSmall,
'${communityInfo?.communityView.community.name ?? 'N/A'}@${fetchInstanceNameFromUrl(communityInfo?.communityView.community.actorId) ?? 'N/A'}'
),
const SizedBox(height: 8.0),
Row(
Expand All @@ -74,8 +73,8 @@ class CommunityHeader extends StatelessWidget {
),
const SizedBox(width: 8.0),
IconText(
icon: const Icon(Icons.sensors_rounded),
text: (communityInfo?.online != null) ? '${communityInfo?.online}' : '-',
icon: const Icon(Icons.calendar_month_rounded ),
text: formatNumberToK(communityInfo?.communityView.counts.usersActiveMonth ?? 0),
),
],
),
Expand Down
42 changes: 35 additions & 7 deletions lib/community/widgets/post_card_metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import 'package:thunder/utils/numbers.dart';
class PostCardMetaData extends StatelessWidget {
final int score;
final VoteType voteType;
final int unreadComments;
final int comments;
final bool hasBeenEdited;
final DateTime published;
final bool saved;
final bool distinguised;
Expand All @@ -21,7 +23,9 @@ class PostCardMetaData extends StatelessWidget {
super.key,
required this.score,
required this.voteType,
required this.unreadComments,
required this.comments,
required this.hasBeenEdited,
required this.published,
required this.saved,
required this.distinguised,
Expand Down Expand Up @@ -53,7 +57,7 @@ class PostCardMetaData extends StatelessWidget {
: voteType == VoteType.down
? downVoteColor
: theme.textTheme.titleSmall?.color?.withOpacity(0.9),
icon: Icon( voteType == VoteType.down ? Icons.arrow_downward : Icons.arrow_upward,
icon: Icon( voteType == VoteType.up ? Icons.arrow_upward : (voteType == VoteType.down ? Icons.arrow_downward : (score < 0 ? Icons.arrow_downward : Icons.arrow_upward)),
size: 18.0,
color: voteType == VoteType.up
? upVoteColor
Expand All @@ -67,19 +71,19 @@ class PostCardMetaData extends StatelessWidget {
IconText(
textScaleFactor: state.contentFontSizeScale.textScaleFactor,
icon: Icon(
Icons.chat,
/*unreadComments != 0 && unreadComments != comments ? Icons.mark_unread_chat_alt_rounded :*/ Icons.chat,
size: 17.0,
color: theme.textTheme.titleSmall?.color?.withOpacity(0.75),
color: /*unreadComments != 0 && unreadComments != comments ? theme.primaryColor :*/ theme.textTheme.titleSmall?.color?.withOpacity(0.75),
),
text: formatNumberToK(comments),
textColor: theme.textTheme.titleSmall?.color?.withOpacity(0.9),
text: /*unreadComments != 0 && unreadComments != comments ? '+${formatNumberToK(unreadComments)}' :*/ formatNumberToK(comments),
textColor: /*unreadComments != 0 && unreadComments != comments ? theme.primaryColor :*/ theme.textTheme.titleSmall?.color?.withOpacity(0.9),
padding: 5.0,
),
const SizedBox(width: 10.0),
IconText(
textScaleFactor: state.contentFontSizeScale.textScaleFactor,
icon: Icon(
Icons.history_rounded,
hasBeenEdited ? Icons.refresh_rounded : Icons.history_rounded,
size: 19.0,
color: theme.textTheme.titleSmall?.color?.withOpacity(0.75),
),
Expand Down Expand Up @@ -110,13 +114,17 @@ class PostCardMetaData extends StatelessWidget {
}

class PostViewMetaData extends StatelessWidget {
final int unreadComments;
final int comments;
final bool hasBeenEdited;
final DateTime published;
final bool saved;

const PostViewMetaData({
super.key,
required this.unreadComments,
required this.comments,
required this.hasBeenEdited,
required this.published,
required this.saved,
});
Expand All @@ -137,6 +145,24 @@ class PostViewMetaData extends StatelessWidget {
Row(
mainAxisSize: MainAxisSize.min,
children: [
/*Container(
child: unreadComments != 0 && unreadComments != comments ? Row(
children: [
IconText(
textScaleFactor: state.contentFontSizeScale.textScaleFactor,
icon: Icon(
Icons.mark_unread_chat_alt_rounded,
size: 17.0,
color: theme.primaryColor,
),
text: '+${formatNumberToK(unreadComments)}',
textColor: theme.primaryColor,
padding: 5.0,
),
const SizedBox(width: 10.0),
],
) : null,
),*/
IconText(
textScaleFactor: state.contentFontSizeScale.textScaleFactor,
icon: Icon(
Expand All @@ -145,17 +171,19 @@ class PostViewMetaData extends StatelessWidget {
color: theme.textTheme.titleSmall?.color?.withOpacity(0.75),
),
text: formatNumberToK(comments),
textColor: theme.textTheme.titleSmall?.color?.withOpacity(0.9),
padding: 5.0,
),
const SizedBox(width: 10.0),
IconText(
textScaleFactor: state.contentFontSizeScale.textScaleFactor,
icon: Icon(
Icons.history_rounded,
hasBeenEdited ? Icons.refresh_rounded : Icons.history_rounded,
size: 19.0,
color: theme.textTheme.titleSmall?.color?.withOpacity(0.75),
),
text: formatTimeToString(dateTime: published.toIso8601String()),
textColor: theme.textTheme.titleSmall?.color?.withOpacity(0.9),
),
],
),
Expand Down
4 changes: 3 additions & 1 deletion lib/community/widgets/post_card_view_comfortable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ class PostCardViewComfortable extends StatelessWidget {
score: postViewMedia.postView.counts.score,
voteType: postViewMedia.postView.myVote ?? VoteType.none,
comments: postViewMedia.postView.counts.comments,
published: postViewMedia.postView.post.published,
unreadComments: postViewMedia.postView.unreadComments,
hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false,
published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published,
saved: postViewMedia.postView.saved,
distinguised: postViewMedia.postView.post.featuredCommunity,
)
Expand Down
4 changes: 3 additions & 1 deletion lib/community/widgets/post_card_view_compact.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ class PostCardViewCompact extends StatelessWidget {
score: postViewMedia.postView.counts.score,
voteType: postViewMedia.postView.myVote ?? VoteType.none,
comments: postViewMedia.postView.counts.comments,
published: postViewMedia.postView.post.published,
unreadComments: postViewMedia.postView.unreadComments,
hasBeenEdited: postViewMedia.postView.post.updated != null ? true : false,
published: postViewMedia.postView.post.updated != null ? postViewMedia.postView.post.updated! : postViewMedia.postView.post.published,
saved: postViewMedia.postView.saved,
distinguised: postViewMedia.postView.post.featuredCommunity,
)
Expand Down
Loading

0 comments on commit c209136

Please sign in to comment.