Compare commits

..

No commits in common. "a20c2598fcb773c3f5959b85c79c5b4edbab75e2" and "46919dec31beeeeb05baf86c8348b361d23def81" have entirely different histories.

12 changed files with 116 additions and 152 deletions

View File

@ -532,7 +532,7 @@
"aboutScreenContactUsTitle": "联系我们", "aboutScreenContactUsTitle": "联系我们",
"aboutScreenLicenseTitle": "许可证", "aboutScreenLicenseTitle": "许可证",
"aboutScreenLicenseContent": "GNU Affero General Public License v3.0", "aboutScreenLicenseContent": "GNU Affero General Public License v3.0",
"aboutScreenCopyright": "版权所有 © 索尔辛茨 {}", "aboutScreenCopyright": "版权所有 © Solsynth {}",
"aboutScreenMadeWith": "由 Solar Network Team 用 ❤︎️ 制作", "aboutScreenMadeWith": "由 Solar Network Team 用 ❤︎️ 制作",
"aboutScreenFailedToLoadPackageInfo": "加载包信息失败:{error}", "aboutScreenFailedToLoadPackageInfo": "加载包信息失败:{error}",
"copiedToClipboard": "已复制到剪贴板", "copiedToClipboard": "已复制到剪贴板",

View File

@ -221,7 +221,7 @@ class IslandApp extends HookConsumerWidget {
Future(() { Future(() {
userNotifier.fetchUser().then((_) { userNotifier.fetchUser().then((_) {
final user = ref.watch(userInfoProvider); final user = ref.watch(userInfoProvider);
if (user.value != null) { if (user.hasValue) {
final apiClient = ref.read(apiClientProvider); final apiClient = ref.read(apiClientProvider);
subscribePushNotification(apiClient); subscribePushNotification(apiClient);
final wsNotifier = ref.read(websocketStateProvider.notifier); final wsNotifier = ref.read(websocketStateProvider.notifier);

View File

@ -18,13 +18,8 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
final user = SnAccount.fromJson(response.data); final user = SnAccount.fromJson(response.data);
state = AsyncValue.data(user); state = AsyncValue.data(user);
} catch (error, stackTrace) { } catch (error, stackTrace) {
log( log("[UserInfo] Failed to fetch user info: $error");
"[UserInfo] Failed to fetch user info...", state = AsyncValue.error(error, stackTrace);
name: 'UserInfoNotifier',
error: error,
stackTrace: stackTrace,
);
state = AsyncValue.data(null);
} }
} }

View File

@ -59,7 +59,7 @@ class AccountScreen extends HookConsumerWidget {
notificationUnreadCountNotifierProvider, notificationUnreadCountNotifierProvider,
); );
if (user.value == null || user.value == null) { if (!user.hasValue || user.value == null) {
return _UnauthorizedAccountScreen(); return _UnauthorizedAccountScreen();
} }
@ -367,23 +367,12 @@ class _UnauthorizedAccountScreen extends StatelessWidget {
), ),
), ),
const Gap(8), const Gap(8),
Row( TextButton(
mainAxisAlignment: MainAxisAlignment.center, onPressed: () {
children: [ context.push('/settings');
TextButton( },
onPressed: () { child: Text('appSettings').tr(),
context.push('/about'); ).center(),
},
child: Text('about').tr(),
),
TextButton(
onPressed: () {
context.push('/settings');
},
child: Text('appSettings').tr(),
),
],
),
], ],
), ),
).center(), ).center(),

View File

@ -82,7 +82,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.value != null) if (name != 'me' && user.hasValue)
AccountNameplate(name: name), AccountNameplate(name: name),
], ],
), ),
@ -106,7 +106,7 @@ class EventCalanderScreen extends HookConsumerWidget {
).padding(horizontal: 8, vertical: 4), ).padding(horizontal: 8, vertical: 4),
// Show user profile if viewing someone else's calendar // Show user profile if viewing someone else's calendar
if (name != 'me' && user.value != null) if (name != 'me' && user.hasValue)
AccountNameplate(name: name), AccountNameplate(name: name),
Gap(MediaQuery.of(context).padding.bottom + 16), Gap(MediaQuery.of(context).padding.bottom + 16),
], ],

View File

@ -72,8 +72,6 @@ Future<Color?> accountAppbarForcegroundColor(Ref ref, String uname) async {
@riverpod @riverpod
Future<SnChatRoom?> accountDirectChat(Ref ref, String uname) async { Future<SnChatRoom?> accountDirectChat(Ref ref, String uname) async {
final userInfo = ref.watch(userInfoProvider);
if (userInfo.value == null) return null;
final account = await ref.watch(accountProvider(uname).future); final account = await ref.watch(accountProvider(uname).future);
final apiClient = ref.watch(apiClientProvider); final apiClient = ref.watch(apiClientProvider);
try { try {
@ -89,8 +87,6 @@ Future<SnChatRoom?> accountDirectChat(Ref ref, String uname) async {
@riverpod @riverpod
Future<SnRelationship?> accountRelationship(Ref ref, String uname) async { Future<SnRelationship?> accountRelationship(Ref ref, String uname) async {
final userInfo = ref.watch(userInfoProvider);
if (userInfo.value == null) return null;
final account = await ref.watch(accountProvider(uname).future); final account = await ref.watch(accountProvider(uname).future);
final apiClient = ref.watch(apiClientProvider); final apiClient = ref.watch(apiClientProvider);
try { try {
@ -223,8 +219,6 @@ class AccountProfileScreen extends HookConsumerWidget {
]; ];
} }
final user = ref.watch(userInfoProvider);
return account.when( return account.when(
data: data:
(data) => AppScaffold( (data) => AppScaffold(
@ -385,60 +379,56 @@ class AccountProfileScreen extends HookConsumerWidget {
).padding(horizontal: 24), ).padding(horizontal: 24),
), ),
if (user.value != null) SliverToBoxAdapter(
SliverToBoxAdapter( child: const Divider(height: 1).padding(top: 24, bottom: 12),
child: const Divider( ),
height: 1, SliverToBoxAdapter(
).padding(top: 24, bottom: 12), child: Row(
), spacing: 8,
if (user.value != null) children: [
SliverToBoxAdapter( Expanded(
child: Row( child: FilledButton.icon(
spacing: 8, style: ButtonStyle(
children: [ backgroundColor: WidgetStatePropertyAll(
Expanded( accountRelationship.value == null
child: FilledButton.icon( ? null
style: ButtonStyle( : Theme.of(context).colorScheme.secondary,
backgroundColor: WidgetStatePropertyAll(
accountRelationship.value == null
? null
: Theme.of(context).colorScheme.secondary,
),
foregroundColor: WidgetStatePropertyAll(
accountRelationship.value == null
? null
: Theme.of(context).colorScheme.onSecondary,
),
), ),
onPressed: relationshipAction, foregroundColor: WidgetStatePropertyAll(
label: accountRelationship.value == null
Text( ? null
accountRelationship.value == null : Theme.of(context).colorScheme.onSecondary,
? 'addFriendShort' ),
: 'added', ),
).tr(), onPressed: relationshipAction,
icon: label:
Text(
accountRelationship.value == null accountRelationship.value == null
? const Icon(Symbols.person_add) ? 'addFriendShort'
: const Icon(Symbols.person_check), : 'added',
), ).tr(),
icon:
accountRelationship.value == null
? const Icon(Symbols.person_add)
: const Icon(Symbols.person_check),
), ),
Expanded( ),
child: FilledButton.icon( Expanded(
onPressed: directMessageAction, child: FilledButton.icon(
icon: const Icon(Symbols.message), onPressed: directMessageAction,
label: icon: const Icon(Symbols.message),
Text( label:
accountChat.value == null Text(
? 'createDirectMessage' accountChat.value == null
: 'gotoDirectMessage', ? 'createDirectMessage'
maxLines: 1, : 'gotoDirectMessage',
).tr(), maxLines: 1,
), ).tr(),
), ),
], ),
).padding(horizontal: 16), ],
), ).padding(horizontal: 16),
),
SliverToBoxAdapter( SliverToBoxAdapter(
child: const Divider(height: 1).padding(top: 12), child: const Divider(height: 1).padding(top: 12),
), ),

View File

@ -51,59 +51,54 @@ class _ArticleDetailContent extends HookConsumerWidget {
); );
return SingleChildScrollView( return SingleChildScrollView(
child: Center( child: Column(
child: ConstrainedBox( crossAxisAlignment: CrossAxisAlignment.stretch,
constraints: const BoxConstraints(maxWidth: 560), children: [
child: Column( if (article.preview?.imageUrl != null)
crossAxisAlignment: CrossAxisAlignment.stretch, Image.network(
children: [ article.preview!.imageUrl!,
if (article.preview?.imageUrl != null) width: double.infinity,
Image.network( height: 200,
article.preview!.imageUrl!, fit: BoxFit.cover,
width: double.infinity, ),
height: 200, Padding(
fit: BoxFit.cover, padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
article.title,
style: Theme.of(context).textTheme.headlineSmall,
), ),
Padding( const SizedBox(height: 8),
padding: const EdgeInsets.all(16.0), if (article.feed?.title != null)
child: Column( Text(
crossAxisAlignment: CrossAxisAlignment.start, article.feed!.title,
children: [ style: Theme.of(context).textTheme.bodyMedium?.copyWith(
Text( color: Theme.of(context).colorScheme.onSurfaceVariant,
article.title,
style: Theme.of(context).textTheme.headlineSmall,
), ),
const SizedBox(height: 8), ),
if (article.feed?.title != null) const Divider(height: 32),
Text( if (article.content != null)
article.feed!.title, ...MarkdownTextContent.buildGenerator(
style: Theme.of(context).textTheme.bodyMedium?.copyWith( isDark: Theme.of(context).brightness == Brightness.dark,
color: Theme.of(context).colorScheme.onSurfaceVariant, ).buildWidgets(markdownContent)
), else if (article.preview?.description != null)
Text(article.preview!.description!),
const Gap(24),
FilledButton(
onPressed:
() => launchUrlString(
article.url,
mode: LaunchMode.externalApplication,
), ),
const Divider(height: 32), child: const Text('Read Full Article'),
if (article.content != null)
...MarkdownTextContent.buildGenerator(
isDark: Theme.of(context).brightness == Brightness.dark,
).buildWidgets(markdownContent)
else if (article.preview?.description != null)
Text(article.preview!.description!),
const Gap(24),
FilledButton(
onPressed:
() => launchUrlString(
article.url,
mode: LaunchMode.externalApplication,
),
child: const Text('Read Full Article'),
),
Gap(MediaQuery.of(context).padding.bottom),
],
), ),
), Gap(MediaQuery.of(context).padding.bottom),
], ],
),
), ),
), ],
), ),
); );
} }

View File

@ -126,21 +126,16 @@ class ArticlesScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text(title ?? 'Articles')), appBar: AppBar(title: Text(title ?? 'Articles')),
body: Center( body: CustomScrollView(
child: ConstrainedBox( slivers: [
constraints: const BoxConstraints(maxWidth: 560), SliverPadding(
child: CustomScrollView( padding: const EdgeInsets.only(top: 8, left: 8, right: 8),
slivers: [ sliver: SliverArticlesList(
SliverPadding( feedId: feedId,
padding: const EdgeInsets.only(top: 8, left: 8, right: 8), publisherId: publisherId,
sliver: SliverArticlesList( ),
feedId: feedId,
publisherId: publisherId,
),
),
],
), ),
), ],
), ),
); );
} }

View File

@ -307,7 +307,7 @@ class _ActivityListView extends HookConsumerWidget {
return CustomScrollView( return CustomScrollView(
slivers: [ slivers: [
if (user.value != null && !contentOnly) if (user.hasValue && !contentOnly)
SliverToBoxAdapter(child: CheckInWidget()), SliverToBoxAdapter(child: CheckInWidget()),
SliverList.builder( SliverList.builder(
itemCount: widgetCount, itemCount: widgetCount,

View File

@ -59,7 +59,7 @@ class AccountStatusCreationSheet extends HookConsumerWidget {
}, },
options: Options(method: initialStatus == null ? 'POST' : 'PATCH'), options: Options(method: initialStatus == null ? 'POST' : 'PATCH'),
); );
if (user.value != null) { if (user.hasValue) {
ref.invalidate(accountStatusProvider(user.value!.name)); ref.invalidate(accountStatusProvider(user.value!.name));
} }
if (!context.mounted) return; if (!context.mounted) return;

View File

@ -350,7 +350,7 @@ class _WebSocketIndicator extends HookConsumerWidget {
return AnimatedPositioned( return AnimatedPositioned(
duration: Duration(milliseconds: 1850), duration: Duration(milliseconds: 1850),
top: top:
user.value == null || !user.hasValue ||
user.value == null || user.value == null ||
websocketState == WebSocketState.connected() websocketState == WebSocketState.connected()
? -indicatorHeight ? -indicatorHeight
@ -362,7 +362,7 @@ class _WebSocketIndicator extends HookConsumerWidget {
child: IgnorePointer( child: IgnorePointer(
child: Material( child: Material(
elevation: elevation:
user.value == null || websocketState == WebSocketState.connected() !user.hasValue || websocketState == WebSocketState.connected()
? 0 ? 0
: 4, : 4,
child: AnimatedContainer( child: AnimatedContainer(

View File

@ -56,7 +56,7 @@ class PostItem extends HookConsumerWidget {
final user = ref.watch(userInfoProvider); final user = ref.watch(userInfoProvider);
final isAuthor = useMemoized( final isAuthor = useMemoized(
() => user.value != null && user.value?.id == item.publisher.accountId, () => user.hasValue && user.value?.id == item.publisher.accountId,
[user], [user],
); );