💄 Optimized publisher profile & personal profile
This commit is contained in:
parent
6e74cf3a93
commit
30416f7ca0
@ -314,7 +314,7 @@
|
|||||||
"accountSettingsHelpContent": "This page allows you to manage your account security, privacy, and other settings. If you need assistance, please contact support.",
|
"accountSettingsHelpContent": "This page allows you to manage your account security, privacy, and other settings. If you need assistance, please contact support.",
|
||||||
"unauthorized": "Unauthorized",
|
"unauthorized": "Unauthorized",
|
||||||
"unauthorizedHint": "You're not signed in or session expired, please sign in again.",
|
"unauthorizedHint": "You're not signed in or session expired, please sign in again.",
|
||||||
"publisherVisitAccountPage": "Visit the profile of {}",
|
"publisherBelongsTo": "Belongs to {}",
|
||||||
"postVisibility": "Visibility",
|
"postVisibility": "Visibility",
|
||||||
"postVisibilityPublic": "Public",
|
"postVisibilityPublic": "Public",
|
||||||
"postVisibilityFriends": "Friends Only",
|
"postVisibilityFriends": "Friends Only",
|
||||||
@ -424,5 +424,6 @@
|
|||||||
"checkInResultT1": "Poor",
|
"checkInResultT1": "Poor",
|
||||||
"checkInResultT2": "Mid",
|
"checkInResultT2": "Mid",
|
||||||
"checkInResultT3": "Good",
|
"checkInResultT3": "Good",
|
||||||
"checkInResultT4": "Best"
|
"checkInResultT4": "Best",
|
||||||
|
"accountProfileView": "View Profile"
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import 'package:flutter/material.dart' as _i28;
|
|||||||
import 'package:island/models/post.dart' as _i30;
|
import 'package:island/models/post.dart' as _i30;
|
||||||
import 'package:island/route.dart' as _i31;
|
import 'package:island/route.dart' as _i31;
|
||||||
import 'package:island/screens/account.dart' as _i2;
|
import 'package:island/screens/account.dart' as _i2;
|
||||||
import 'package:island/screens/account/me/event_calendar.dart' as _i14;
|
import 'package:island/screens/account/event_calendar.dart' as _i14;
|
||||||
import 'package:island/screens/account/me/settings.dart' as _i3;
|
import 'package:island/screens/account/me/settings.dart' as _i3;
|
||||||
import 'package:island/screens/account/me/update.dart' as _i25;
|
import 'package:island/screens/account/me/update.dart' as _i25;
|
||||||
import 'package:island/screens/account/profile.dart' as _i1;
|
import 'package:island/screens/account/profile.dart' as _i1;
|
||||||
|
@ -6,6 +6,7 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/pods/event_calendar.dart';
|
import 'package:island/pods/event_calendar.dart';
|
||||||
import 'package:island/screens/account/profile.dart';
|
import 'package:island/screens/account/profile.dart';
|
||||||
|
import 'package:island/widgets/account/account_nameplate.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/account/event_calendar.dart';
|
import 'package:island/widgets/account/event_calendar.dart';
|
||||||
@ -86,29 +87,7 @@ class EventCalanderScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Show user profile if viewing someone else's calendar
|
// Show user profile if viewing someone else's calendar
|
||||||
if (name != 'me' && user.hasValue)
|
if (name != 'me' && user.hasValue)
|
||||||
Container(
|
AccountNameplate(name: name),
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
width:
|
|
||||||
1 / MediaQuery.of(context).devicePixelRatio,
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
|
||||||
),
|
|
||||||
margin: EdgeInsets.all(16),
|
|
||||||
child: Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
elevation: 0,
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: ListTile(
|
|
||||||
leading: ProfilePictureWidget(
|
|
||||||
fileId: user.value!.profile.picture?.id,
|
|
||||||
),
|
|
||||||
title: Text(user.value!.nick).bold(),
|
|
||||||
subtitle: Text('@${user.value!.name}'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
).center()
|
).center()
|
||||||
@ -132,28 +111,8 @@ class EventCalanderScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Show user profile if viewing someone else's calendar
|
// Show user profile if viewing someone else's calendar
|
||||||
if (name != 'me' && user.hasValue)
|
if (name != 'me' && user.hasValue)
|
||||||
Container(
|
AccountNameplate(name: name),
|
||||||
decoration: BoxDecoration(
|
Gap(MediaQuery.of(context).padding.bottom + 16),
|
||||||
border: Border.all(
|
|
||||||
width: 1 / MediaQuery.of(context).devicePixelRatio,
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
|
||||||
),
|
|
||||||
margin: EdgeInsets.all(16),
|
|
||||||
child: Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
elevation: 0,
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: ListTile(
|
|
||||||
leading: ProfilePictureWidget(
|
|
||||||
fileId: user.value!.profile.picture?.id,
|
|
||||||
),
|
|
||||||
title: Text(user.value!.nick).bold(),
|
|
||||||
subtitle: Text('@${user.value!.name}'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
@ -5,11 +5,13 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/user.dart';
|
import 'package:island/models/user.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
|
import 'package:island/pods/event_calendar.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/services/color.dart';
|
import 'package:island/services/color.dart';
|
||||||
import 'package:island/widgets/account/account_name.dart';
|
import 'package:island/widgets/account/account_name.dart';
|
||||||
import 'package:island/widgets/account/badge.dart';
|
import 'package:island/widgets/account/badge.dart';
|
||||||
|
import 'package:island/widgets/account/fortune_graph.dart';
|
||||||
import 'package:island/widgets/account/leveling_progress.dart';
|
import 'package:island/widgets/account/leveling_progress.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@ -67,7 +69,14 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
|
||||||
final account = ref.watch(accountProvider(name));
|
final account = ref.watch(accountProvider(name));
|
||||||
|
final accountEvents = ref.watch(
|
||||||
|
eventCalendarProvider(
|
||||||
|
EventCalendarQuery(uname: name, year: now.year, month: now.month),
|
||||||
|
),
|
||||||
|
);
|
||||||
final appbarColor = ref.watch(accountAppbarForcegroundColorProvider(name));
|
final appbarColor = ref.watch(accountAppbarForcegroundColorProvider(name));
|
||||||
|
|
||||||
final appbarShadow = Shadow(
|
final appbarShadow = Shadow(
|
||||||
@ -173,22 +182,39 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
mark: data.profile.verification!,
|
mark: data.profile.verification!,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 20, bottom: 24),
|
).padding(horizontal: 20),
|
||||||
),
|
),
|
||||||
|
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: const Divider(height: 1).padding(bottom: 24),
|
child: const Divider(height: 1).padding(vertical: 24),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text('bio').tr().bold(),
|
||||||
|
Text(
|
||||||
|
data.profile.bio.isEmpty
|
||||||
|
? 'descriptionNone'.tr()
|
||||||
|
: data.profile.bio,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24),
|
||||||
|
),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: const Divider(height: 1).padding(top: 24),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
FortuneGraphWidget(
|
||||||
|
events: accountEvents,
|
||||||
|
eventCalanderUser: data.name,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(all: 8),
|
||||||
),
|
),
|
||||||
if (data.profile.bio.isNotEmpty)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text('bio').tr().bold(),
|
|
||||||
Text(data.profile.bio),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 24),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -385,6 +385,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
if (['messages.read'].contains(pkt.type)) return;
|
if (['messages.read'].contains(pkt.type)) return;
|
||||||
|
|
||||||
if (pkt.type == 'messages.typing' && pkt.data?['sender'] != null) {
|
if (pkt.type == 'messages.typing' && pkt.data?['sender'] != null) {
|
||||||
|
if (pkt.data?['room_id'] != chatRoom.value?.id) return;
|
||||||
if (pkt.data?['sender_id'] == chatIdentity.value?.id) return;
|
if (pkt.data?['sender_id'] == chatIdentity.value?.id) return;
|
||||||
|
|
||||||
final sender = SnChatMember.fromJson(
|
final sender = SnChatMember.fromJson(
|
||||||
|
@ -17,6 +17,7 @@ import 'package:island/widgets/alert.dart';
|
|||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/post/post_list.dart';
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
@ -210,65 +211,85 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Text(data.nick).fontSize(20),
|
Text(data.nick).fontSize(20),
|
||||||
|
if (data.verification != null)
|
||||||
|
VerificationMark(mark: data.verification!),
|
||||||
Text(
|
Text(
|
||||||
'@${data.name}',
|
'@${data.name}',
|
||||||
).fontSize(14).opacity(0.85),
|
).fontSize(14).opacity(0.85),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (data.type == 0 && data.account != null)
|
if (data.type == 0 && data.account != null)
|
||||||
InkWell(
|
Row(
|
||||||
onTap: () {
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
context.router.pushPath(
|
spacing: 6,
|
||||||
'/account/${data.account!.name}',
|
children: [
|
||||||
);
|
Icon(
|
||||||
},
|
data.type == 0
|
||||||
child: Row(
|
? Symbols.person
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
: Symbols.workspaces,
|
||||||
spacing: 4,
|
fill: 1,
|
||||||
children: [
|
size: 17,
|
||||||
Text(
|
),
|
||||||
'publisherVisitAccountPage'.tr(
|
Text(
|
||||||
args: ['@${data.account!.name}'],
|
'publisherBelongsTo'.tr(
|
||||||
),
|
args: ['@${data.account!.name}'],
|
||||||
).fontSize(14),
|
),
|
||||||
Icon(Icons.launch, size: 14),
|
).fontSize(14),
|
||||||
],
|
],
|
||||||
).opacity(0.85),
|
).opacity(0.85).padding(bottom: 6),
|
||||||
).padding(bottom: 6),
|
|
||||||
if (data.type == 0 && data.account != null)
|
if (data.type == 0 && data.account != null)
|
||||||
AccountStatusWidget(
|
AccountStatusWidget(
|
||||||
uname: data.account!.name,
|
uname: data.account!.name,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
|
OutlinedButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
context.router.pushPath(
|
||||||
|
'/account/${data.name}',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.launch),
|
||||||
|
label: Text('accountProfileView').tr(),
|
||||||
|
style: ButtonStyle(
|
||||||
|
visualDensity: VisualDensity(vertical: -2),
|
||||||
|
),
|
||||||
|
).padding(top: 8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, top: 24, bottom: 24),
|
).padding(horizontal: 24, top: 24),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: Column(
|
||||||
spacing: 24,
|
|
||||||
children: [
|
children: [
|
||||||
if (badges.value?.isNotEmpty ?? false)
|
if (badges.value?.isNotEmpty ?? false)
|
||||||
BadgeList(badges: badges.value!),
|
BadgeList(badges: badges.value!).padding(top: 16),
|
||||||
if (data.verification != null)
|
if (data.verification != null)
|
||||||
VerificationStatusCard(mark: data.verification!),
|
VerificationStatusCard(
|
||||||
|
mark: data.verification!,
|
||||||
|
).padding(top: 16),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, bottom: 24),
|
).padding(horizontal: 24),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: const Divider(height: 1).padding(vertical: 24),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text('bio').tr().bold(),
|
||||||
|
Text(
|
||||||
|
data.bio.isEmpty ? 'descriptionNone'.tr() : data.bio,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: const Divider(height: 1).padding(top: 24),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(child: const Divider(height: 1)),
|
|
||||||
if (data.bio.isNotEmpty)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [Text('bio').tr().bold(), Text(data.bio)],
|
|
||||||
).padding(horizontal: 24, top: 24),
|
|
||||||
),
|
|
||||||
if (data.bio.isNotEmpty)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: const Divider(height: 1).padding(top: 24),
|
|
||||||
),
|
|
||||||
SliverPostList(pubName: name),
|
SliverPostList(pubName: name),
|
||||||
SliverGap(MediaQuery.of(context).padding.bottom + 16),
|
SliverGap(MediaQuery.of(context).padding.bottom + 16),
|
||||||
],
|
],
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:relative_time/relative_time.dart';
|
||||||
|
|
||||||
extension DurationFormatter on Duration {
|
extension DurationFormatter on Duration {
|
||||||
String formatDuration() {
|
String formatDuration() {
|
||||||
final isNegative = inMicroseconds < 0;
|
final isNegative = inMicroseconds < 0;
|
||||||
@ -16,3 +20,21 @@ extension DurationFormatter on Duration {
|
|||||||
return '${isNegative ? '-' : ''}$hours:$minutes:$seconds';
|
return '${isNegative ? '-' : ''}$hours:$minutes:$seconds';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension DateTimeFormatter on DateTime {
|
||||||
|
String formatSystem() {
|
||||||
|
return DateFormat.yMd().add_jm().format(toLocal());
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatCustom(String pattern) {
|
||||||
|
return DateFormat(pattern).format(toLocal());
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatWithLocale(String locale) {
|
||||||
|
return DateFormat.yMd().add_jm().format(toLocal()).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatRelative(BuildContext context) {
|
||||||
|
return RelativeTime(context).format(toLocal());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
51
lib/widgets/account/account_nameplate.dart
Normal file
51
lib/widgets/account/account_nameplate.dart
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/screens/account/profile.dart';
|
||||||
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
class AccountNameplate extends HookConsumerWidget {
|
||||||
|
final String name;
|
||||||
|
const AccountNameplate({super.key, required this.name});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final user = ref.watch(accountProvider(name));
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
width: 1 / MediaQuery.of(context).devicePixelRatio,
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
margin: EdgeInsets.all(16),
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
elevation: 0,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: user.when(
|
||||||
|
data: (account) => ListTile(
|
||||||
|
leading: ProfilePictureWidget(
|
||||||
|
fileId: account.profile.picture?.id,
|
||||||
|
),
|
||||||
|
title: Text(account.nick).bold(),
|
||||||
|
subtitle: Text('@${account.name}'),
|
||||||
|
),
|
||||||
|
loading: () => ListTile(
|
||||||
|
leading: const CircularProgressIndicator(),
|
||||||
|
title: const Text('loading').bold().tr(),
|
||||||
|
subtitle: const Text('...'),
|
||||||
|
),
|
||||||
|
error: (error, stackTrace) => ListTile(
|
||||||
|
leading: Icon(Icons.error_outline, color: Colors.red),
|
||||||
|
title: Text('somethingWentWrong').bold().tr(),
|
||||||
|
subtitle: Text(error.toString()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_popup_card/flutter_popup_card.dart';
|
import 'package:flutter_popup_card/flutter_popup_card.dart';
|
||||||
@ -12,6 +13,7 @@ import 'package:island/widgets/account/leveling_progress.dart';
|
|||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/response.dart';
|
import 'package:island/widgets/response.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
class AccountProfileCard extends HookConsumerWidget {
|
class AccountProfileCard extends HookConsumerWidget {
|
||||||
@ -34,17 +36,18 @@ class AccountProfileCard extends HookConsumerWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
if (data.profile.background != null)
|
||||||
borderRadius: const BorderRadius.vertical(
|
ClipRRect(
|
||||||
top: Radius.circular(12),
|
borderRadius: const BorderRadius.vertical(
|
||||||
|
top: Radius.circular(12),
|
||||||
|
),
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 16 / 9,
|
||||||
|
child: CloudImageWidget(file: data.profile.background),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 16 / 9,
|
|
||||||
child: CloudImageWidget(file: data.profile.background),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
@ -76,6 +79,14 @@ class AccountProfileCard extends HookConsumerWidget {
|
|||||||
experience: data.profile.experience,
|
experience: data.profile.experience,
|
||||||
progress: data.profile.levelingProgress,
|
progress: data.profile.levelingProgress,
|
||||||
).padding(top: 12),
|
).padding(top: 12),
|
||||||
|
FilledButton.tonalIcon(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
context.router.pushPath('/account/${data.name}');
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.launch),
|
||||||
|
label: Text('accountProfileView').tr(),
|
||||||
|
).padding(top: 12, horizontal: 2),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, vertical: 16),
|
).padding(horizontal: 24, vertical: 16),
|
||||||
],
|
],
|
||||||
@ -86,9 +97,14 @@ class AccountProfileCard extends HookConsumerWidget {
|
|||||||
onRetry: () => ref.invalidate(accountProvider(uname)),
|
onRetry: () => ref.invalidate(accountProvider(uname)),
|
||||||
),
|
),
|
||||||
loading:
|
loading:
|
||||||
() => Padding(
|
() => SizedBox(
|
||||||
padding: const EdgeInsets.all(24),
|
width: width,
|
||||||
child: CircularProgressIndicator(),
|
height: width,
|
||||||
|
child:
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
).center(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -23,6 +24,8 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
/// Callback when a point is selected
|
/// Callback when a point is selected
|
||||||
final void Function(DateTime)? onPointSelected;
|
final void Function(DateTime)? onPointSelected;
|
||||||
|
|
||||||
|
final String? eventCalanderUser;
|
||||||
|
|
||||||
const FortuneGraphWidget({
|
const FortuneGraphWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.events,
|
required this.events,
|
||||||
@ -30,6 +33,7 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
this.maxWidth = double.infinity,
|
this.maxWidth = double.infinity,
|
||||||
this.height = 180,
|
this.height = 180,
|
||||||
this.onPointSelected,
|
this.onPointSelected,
|
||||||
|
this.eventCalanderUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -48,9 +52,27 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
final content = Column(
|
final content = Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Row(
|
||||||
'fortuneGraph',
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
).tr().fontSize(18).bold().padding(all: 16, bottom: 24),
|
children: [
|
||||||
|
Text('fortuneGraph').tr().fontSize(18).bold(),
|
||||||
|
if (eventCalanderUser != null)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.calendar_month, size: 20),
|
||||||
|
visualDensity: const VisualDensity(
|
||||||
|
horizontal: -4,
|
||||||
|
vertical: -4,
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
onPressed: () {
|
||||||
|
context.router.pushNamed(
|
||||||
|
'/account/$eventCalanderUser/calendar',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(all: 16, bottom: 24),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: height,
|
height: height,
|
||||||
child: filteredEvents.when(
|
child: filteredEvents.when(
|
||||||
@ -75,7 +97,7 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
final maxDate = data.last.date;
|
final maxDate = data.last.date;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 24),
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 0),
|
||||||
child: LineChart(
|
child: LineChart(
|
||||||
LineChartData(
|
LineChartData(
|
||||||
gridData: FlGridData(
|
gridData: FlGridData(
|
||||||
|
@ -4,6 +4,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/user.dart';
|
import 'package:island/models/user.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/screens/account/profile.dart';
|
||||||
|
import 'package:island/services/time.dart';
|
||||||
import 'package:island/widgets/account/status_creation.dart';
|
import 'package:island/widgets/account/status_creation.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
@ -104,14 +106,15 @@ class AccountStatusWidget extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final userStatus = ref.watch(accountStatusProvider(uname));
|
final status = ref.watch(accountStatusProvider(uname));
|
||||||
|
final account = ref.watch(accountProvider(uname));
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: padding ?? EdgeInsets.symmetric(horizontal: 27, vertical: 4),
|
padding: padding ?? EdgeInsets.symmetric(horizontal: 27, vertical: 4),
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
if (userStatus.value?.isOnline ?? false)
|
if (status.value?.isOnline ?? false)
|
||||||
Icon(
|
Icon(
|
||||||
Symbols.circle,
|
Symbols.circle,
|
||||||
fill: 1,
|
fill: 1,
|
||||||
@ -119,13 +122,24 @@ class AccountStatusWidget extends HookConsumerWidget {
|
|||||||
size: 16,
|
size: 16,
|
||||||
).padding(right: 4)
|
).padding(right: 4)
|
||||||
else
|
else
|
||||||
Icon(Symbols.circle, color: Colors.grey, size: 16).padding(all: 4),
|
Icon(
|
||||||
if (userStatus.value?.isCustomized ?? false)
|
Symbols.circle,
|
||||||
Text(userStatus.value?.label ?? 'unknown'.tr())
|
color: Colors.grey,
|
||||||
|
size: 16,
|
||||||
|
).padding(right: 4),
|
||||||
|
if (status.value?.isCustomized ?? false)
|
||||||
|
Text(status.value?.label ?? 'unknown'.tr())
|
||||||
else
|
else
|
||||||
Text((userStatus.value?.label ?? 'offline').toLowerCase()).tr(),
|
Text((status.value?.label ?? 'offline').toLowerCase()).tr(),
|
||||||
|
if (!(status.value?.isOnline ?? false) &&
|
||||||
|
account.value?.profile.lastSeenAt != null)
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
account.value!.profile.lastSeenAt!.formatRelative(context),
|
||||||
|
).opacity(0.75),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
).opacity((userStatus.value?.isCustomized ?? false) ? 1 : 0.85);
|
).opacity((status.value?.isCustomized ?? false) ? 1 : 0.85);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user