Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 126 additions & 108 deletions lib/src/view/user/user_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import 'package:lichess_mobile/src/view/user/user_profile.dart';
import 'package:lichess_mobile/src/view/watch/tv_screen.dart';
import 'package:lichess_mobile/src/widgets/buttons.dart';
import 'package:lichess_mobile/src/widgets/feedback.dart';
import 'package:lichess_mobile/src/widgets/haptic_refresh_indicator.dart';
import 'package:lichess_mobile/src/widgets/list.dart';
import 'package:lichess_mobile/src/widgets/platform.dart';
import 'package:lichess_mobile/src/widgets/text_badge.dart';
Expand Down Expand Up @@ -111,7 +112,12 @@ class _UserScreenState extends ConsumerState<UserScreen> {
],
),
body: userScreenData.when(
data: (data) => _UserProfileListView(data, isLoading, setIsLoading),
data: (data) => _UserProfileListView(
data,
isLoading,
setIsLoading,
onRefresh: () => ref.refresh(_userScreenDataProvider(widget.user.id).future),
),
loading: () => const Center(child: CircularProgressIndicator.adaptive()),
error: (error, _) {
if (error is ClientException && error.message.contains('404')) {
Expand All @@ -133,12 +139,17 @@ class _UserScreenState extends ConsumerState<UserScreen> {
}

class _UserProfileListView extends ConsumerWidget {
const _UserProfileListView(this.data, this.isLoading, this.setIsLoading);
const _UserProfileListView(
this.data,
this.isLoading,
this.setIsLoading, {
required this.onRefresh,
});

final UserScreenData data;
final bool isLoading;

final void Function(bool value) setIsLoading;
final RefreshCallback onRefresh;

String _scoreDisplay(double score) {
final integerPart = score.truncate();
Expand Down Expand Up @@ -171,120 +182,127 @@ class _UserProfileListView extends ConsumerWidget {
}
}

return ListView(
children: [
UserProfileWidget(user: user),
PerfCards(user: user, isMe: false),
ListSection(
hasLeading: true,
children: [
if (authUser != null && crosstable != null && (crosstable.nbGames) > 0) ...[
() {
final crosstableData = crosstable;
final currentUserScore = crosstableData.users[authUser.user.id] ?? 0;
final otherUserScore = crosstableData.users[user.id] ?? 0;
return HapticRefreshIndicator(
edgeOffset: Theme.of(context).platform == TargetPlatform.iOS
? MediaQuery.paddingOf(context).top + kToolbarHeight
: 0.0,
onRefresh: onRefresh,
child: ListView(
children: [
UserProfileWidget(user: user),
PerfCards(user: user, isMe: false),
ListSection(
hasLeading: true,
children: [
if (authUser != null && crosstable != null && (crosstable.nbGames) > 0) ...[
() {
final crosstableData = crosstable;
final currentUserScore = crosstableData.users[authUser.user.id] ?? 0;
final otherUserScore = crosstableData.users[user.id] ?? 0;

return ListTile(
title: Text(
context.l10n.yourScore(
'${_scoreDisplay(currentUserScore)} - ${_scoreDisplay(otherUserScore)}',
return ListTile(
title: Text(
context.l10n.yourScore(
'${_scoreDisplay(currentUserScore)} - ${_scoreDisplay(otherUserScore)}',
),
),
leading: const Icon(Icons.scoreboard_outlined),
onTap: () {
Navigator.of(context).push(
GameHistoryScreen.buildRoute(
context,
user: authUser.user,
isOnline: connectivity.value?.isOnline == true,
gameFilter: GameFilterState(opponent: user),
),
);
},
);
}(),
],
ListTile(
title: Text(context.l10n.watchGames),
leading: const Icon(Icons.live_tv_outlined),
trailing: isPlayingLive == true ? const TextBadge(text: 'LIVE') : null,
onTap: () {
Navigator.of(
context,
rootNavigator: true,
).push(TvScreen.buildRoute(context, user: user.lightUser));
},
),
if (authUser != null) ...[
if (user.canChallenge == true)
ListTile(
title: Text(context.l10n.challengeChallengeToPlay),
leading: const Icon(LichessIcons.crossed_swords),
onTap: () => UserScreen.challengeUser(user, context: context, ref: ref),
),
leading: const Icon(Icons.scoreboard_outlined),
onTap: () {
Navigator.of(context).push(
GameHistoryScreen.buildRoute(
context,
user: authUser.user,
isOnline: connectivity.value?.isOnline == true,
gameFilter: GameFilterState(opponent: user),
),
);
},
);
}(),
],
ListTile(
title: Text(context.l10n.watchGames),
leading: const Icon(Icons.live_tv_outlined),
trailing: isPlayingLive == true ? const TextBadge(text: 'LIVE') : null,
onTap: () {
Navigator.of(
context,
rootNavigator: true,
).push(TvScreen.buildRoute(context, user: user.lightUser));
},
),
if (authUser != null) ...[
if (user.canChallenge == true)
ListTile(
title: Text(context.l10n.challengeChallengeToPlay),
leading: const Icon(LichessIcons.crossed_swords),
onTap: () => UserScreen.challengeUser(user, context: context, ref: ref),
),

if (user.blocking != true && !user.isBot && kidMode.value == false)
if (user.blocking != true && !user.isBot && kidMode.value == false)
ListTile(
leading: const Icon(Icons.chat_bubble_outline),
title: Text(context.l10n.composeMessage),
onTap: () {
Navigator.of(
context,
rootNavigator: true,
).push(ConversationScreen.buildRoute(context, user: user.lightUser));
},
),
if (user.followable == true && user.following != true)
ListTile(
leading: const Icon(Icons.person_add_outlined),
title: Text(context.l10n.follow),
onTap: isLoading
? null
: () => userAction((client) => RelationRepository(client).follow(user.id)),
)
else if (user.following == true)
ListTile(
leading: const Icon(Icons.person_remove_outlined),
title: Text(context.l10n.unfollow),
onTap: isLoading
? null
: () =>
userAction((client) => RelationRepository(client).unfollow(user.id)),
),
if (user.following != true && user.blocking != true)
ListTile(
leading: const Icon(Icons.block_outlined),
title: Text(context.l10n.block),
onTap: isLoading
? null
: () => userAction((client) => RelationRepository(client).block(user.id)),
)
else if (user.blocking == true)
ListTile(
leading: const Icon(Icons.block_outlined),
title: Text(context.l10n.unblock),
onTap: isLoading
? null
: () => userAction((client) => RelationRepository(client).unblock(user.id)),
),
ListTile(
leading: const Icon(Icons.chat_bubble_outline),
title: Text(context.l10n.composeMessage),
leading: const Icon(Icons.report_problem_outlined),
title: Text(context.l10n.reportXToModerators(user.username)),
onTap: () {
Navigator.of(
context,
rootNavigator: true,
).push(ConversationScreen.buildRoute(context, user: user.lightUser));
launchUrl(
lichessUri('/report', {'username': user.id, 'login': authUser.user.id}),
);
},
),
if (user.followable == true && user.following != true)
ListTile(
leading: const Icon(Icons.person_add_outlined),
title: Text(context.l10n.follow),
onTap: isLoading
? null
: () => userAction((client) => RelationRepository(client).follow(user.id)),
)
else if (user.following == true)
ListTile(
leading: const Icon(Icons.person_remove_outlined),
title: Text(context.l10n.unfollow),
onTap: isLoading
? null
: () => userAction((client) => RelationRepository(client).unfollow(user.id)),
),
if (user.following != true && user.blocking != true)
ListTile(
leading: const Icon(Icons.block_outlined),
title: Text(context.l10n.block),
onTap: isLoading
? null
: () => userAction((client) => RelationRepository(client).block(user.id)),
)
else if (user.blocking == true)
ListTile(
leading: const Icon(Icons.block_outlined),
title: Text(context.l10n.unblock),
onTap: isLoading
? null
: () => userAction((client) => RelationRepository(client).unblock(user.id)),
),
ListTile(
leading: const Icon(Icons.report_problem_outlined),
title: Text(context.l10n.reportXToModerators(user.username)),
onTap: () {
launchUrl(
lichessUri('/report', {'username': user.id, 'login': authUser.user.id}),
);
},
),
],
],
],
),
UserActivityWidget(activity: AsyncData(activity), user: user.lightUser),
RecentGamesWidget(
recentGames: AsyncData(recentGames),
nbOfGames: nbOfGames,
user: user.lightUser,
),
],
),
UserActivityWidget(activity: AsyncData(activity), user: user.lightUser),
RecentGamesWidget(
recentGames: AsyncData(recentGames),
nbOfGames: nbOfGames,
user: user.lightUser,
),
],
),
);
}
}