🎨 Optimized code structure, rename a lot of widgets

💄 Better large screen support in chat
This commit is contained in:
2024-05-03 13:39:52 +08:00
parent e080f49935
commit c0680a3134
48 changed files with 329 additions and 317 deletions

View File

@ -3,7 +3,7 @@ import 'package:provider/provider.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/providers/friend.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:solian/widgets/account/avatar.dart';
import 'package:solian/widgets/account/account_avatar.dart';
class FriendPicker extends StatefulWidget {
const FriendPicker({super.key});

View File

@ -76,7 +76,7 @@ class _ControlsWidgetState extends State<ControlsWidget> {
if (chat.currentCall != null) {
chat.currentCall!.deactivate();
chat.currentCall!.dispose();
router.pop();
SolianRouter.router.pop();
}
}

View File

@ -52,7 +52,7 @@ class CallOverlay extends StatelessWidget {
),
),
onTap: () {
router.pushNamed(
SolianRouter.router.pushNamed(
'chat.channel.call',
extra: chat.currentCall!.info,
pathParameters: {'channel': chat.currentCall!.channel.alias},

View File

@ -5,7 +5,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:livekit_client/livekit_client.dart';
import 'package:solian/models/account.dart';
import 'package:solian/models/call.dart';
import 'package:solian/widgets/chat/call/no_content.dart';
import 'package:solian/widgets/chat/call/participant_no_content.dart';
import 'package:solian/widgets/chat/call/participant_info.dart';
import 'package:solian/widgets/chat/call/participant_stats.dart';

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:solian/models/account.dart';
import 'package:solian/widgets/account/avatar.dart';
import 'package:solian/widgets/account/account_avatar.dart';
import 'dart:math' as math;
class NoContentWidget extends StatefulWidget {

View File

@ -97,14 +97,14 @@ class ChannelManageAction extends StatelessWidget {
Widget build(BuildContext context) {
return IconButton(
onPressed: () async {
final result = await router.pushNamed(
final result = await SolianRouter.router.pushNamed(
'chat.channel.manage',
extra: channel,
pathParameters: {'channel': channel.alias},
);
switch (result) {
case 'disposed':
if (router.canPop()) router.pop('refresh');
if (SolianRouter.router.canPop()) SolianRouter.router.pop('refresh');
case 'refresh':
onUpdate();
}

View File

@ -29,7 +29,7 @@ class ChatNewAction extends StatelessWidget {
leading: const Icon(Icons.add),
title: Text(AppLocalizations.of(context)!.chatNewCreate),
onTap: () {
router.pushNamed('chat.channel.editor').then((did) {
SolianRouter.router.pushNamed('chat.channel.editor').then((did) {
if (did == true) {
onUpdate();
if (Navigator.canPop(context)) {

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:solian/models/message.dart';
import 'package:solian/widgets/account/avatar.dart';
import 'package:solian/widgets/chat/content.dart';
import 'package:solian/widgets/account/account_avatar.dart';
import 'package:solian/widgets/chat/message_content.dart';
import 'package:solian/widgets/posts/content/attachment.dart';
import 'package:timeago/timeago.dart' as timeago;
import 'dart:math' as math;

View File

@ -1,22 +1,24 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class SelectionEmptyWidget extends StatelessWidget {
const SelectionEmptyWidget({super.key});
class PageEmptyWidget extends StatelessWidget {
const PageEmptyWidget({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('assets/logo.png', width: 64, height: 64),
const SizedBox(height: 2),
Text(
AppLocalizations.of(context)!.appName,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w900),
),
],
return Material(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset('assets/logo.png', width: 64, height: 64),
const SizedBox(height: 2),
Text(
AppLocalizations.of(context)!.appName,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w900),
),
],
),
),
);
}

View File

@ -1,43 +0,0 @@
import 'package:flutter/material.dart';
import 'package:solian/router.dart';
import 'package:solian/widgets/common_wrapper.dart';
import 'package:solian/widgets/navigation_drawer.dart';
class IndentWrapper extends LayoutWrapper {
final bool hideDrawer;
final bool fixedAppBarColor;
const IndentWrapper({
super.key,
super.child,
required super.title,
super.floatingActionButton,
super.appBarActions,
this.hideDrawer = false,
this.fixedAppBarColor = false,
super.noSafeArea = false,
}) : super();
@override
Widget build(BuildContext context) {
final content = child ?? Container();
return Scaffold(
appBar: AppBar(
leading: hideDrawer
? IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => router.pop(),
)
: null,
title: Text(title),
actions: appBarActions,
centerTitle: false,
elevation: fixedAppBarColor ? 4 : null,
),
floatingActionButton: floatingActionButton,
drawer: const SolianNavigationDrawer(),
body: noSafeArea ? content : SafeArea(child: content),
);
}
}

View File

@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:solian/widgets/empty.dart';
class TwoColumnLayout extends StatelessWidget {
final Widget sideChild;
final Widget? mainChild;
const TwoColumnLayout({
super.key,
required this.sideChild,
required this.mainChild,
});
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
child: Scaffold(
body: Row(
children: [
SizedBox(
width: 400,
child: sideChild,
),
const VerticalDivider(width: 0.3, thickness: 0.3),
Expanded(child: mainChild ?? const PageEmptyWidget()),
],
),
),
);
}
}

View File

@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
import 'package:solian/providers/navigation.dart';
import 'package:solian/router.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:solian/utils/theme.dart';
class SolianNavigationDrawer extends StatefulWidget {
const SolianNavigationDrawer({super.key});
@ -17,7 +18,7 @@ class _SolianNavigationDrawerState extends State<SolianNavigationDrawer> {
void _onSelect(String name, int idx) {
setState(() => _selectedIndex = idx);
context.read<NavigationProvider>().selectedIndex = idx;
router.goNamed(name);
SolianRouter.router.goNamed(name);
}
@override
@ -59,6 +60,9 @@ class _SolianNavigationDrawerState extends State<SolianNavigationDrawer> {
return NavigationDrawer(
selectedIndex: _selectedIndex,
elevation: SolianTheme.isLargeScreen(context) ? 20 : 0,
shadowColor: SolianTheme.isLargeScreen(context) ? Theme.of(context).shadowColor : null,
surfaceTintColor: Theme.of(context).colorScheme.background,
onDestinationSelected: (int idx) {
final element = navigationItems[idx];
_onSelect(element.$2, idx);

View File

@ -85,7 +85,7 @@ class _NotificationButtonState extends State<NotificationButton> {
child: IconButton(
icon: const Icon(Icons.notifications),
onPressed: () {
router.pushNamed('notification');
SolianRouter.router.pushNamed('notification');
},
),
);

View File

@ -10,7 +10,7 @@ import 'package:solian/providers/auth.dart';
import 'package:solian/router.dart';
import 'package:solian/screens/posts/comment_editor.dart';
import 'package:solian/utils/service_url.dart';
import 'package:solian/widgets/posts/item.dart';
import 'package:solian/widgets/posts/post.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class CommentList extends StatefulWidget {
@ -120,7 +120,7 @@ class CommentListHeader extends StatelessWidget {
if (snapshot.hasData && snapshot.data == true) {
return TextButton(
onPressed: () async {
final did = await router.pushNamed(
final did = await SolianRouter.router.pushNamed(
'posts.comments.editor',
extra: CommentPostArguments(related: related),
);

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:solian/models/post.dart';
import 'package:solian/widgets/account/avatar.dart';
import 'package:solian/widgets/account/account_avatar.dart';
import 'package:solian/widgets/posts/comment_list.dart';
import 'package:solian/widgets/posts/content/article.dart';
import 'package:solian/widgets/posts/content/attachment.dart';
import 'package:solian/widgets/posts/content/moment.dart';
import 'package:solian/widgets/posts/item_action.dart';
import 'package:solian/widgets/posts/post_action.dart';
import 'package:solian/widgets/posts/reaction_list.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:timeago/timeago.dart' as timeago;

View File

@ -5,7 +5,7 @@ import 'package:solian/providers/auth.dart';
import 'package:solian/router.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:solian/screens/posts/comment_editor.dart';
import 'package:solian/widgets/posts/item_deletion.dart';
import 'package:solian/widgets/posts/post_deletion.dart';
class PostItemAction extends StatelessWidget {
final Post item;
@ -23,17 +23,17 @@ class PostItemAction extends StatelessWidget {
bool ok = false;
switch (item.modelType) {
case 'article':
ok = await router.pushNamed(
ok = await SolianRouter.router.pushNamed(
'posts.articles.editor',
extra: item,
) as bool;
case 'moment':
ok = await router.pushNamed(
ok = await SolianRouter.router.pushNamed(
'posts.moments.editor',
extra: item,
) as bool;
case 'comment':
ok = await router.pushNamed(
ok = await SolianRouter.router.pushNamed(
'posts.comments.editor',
extra: CommentPostArguments(editing: item),
) as bool;

View File

@ -1,19 +1,26 @@
import 'package:flutter/material.dart';
import 'package:solian/utils/theme.dart';
import 'package:solian/widgets/navigation_drawer.dart';
class LayoutWrapper extends StatelessWidget {
class IndentScaffold extends StatelessWidget {
final Widget? child;
final Widget? floatingActionButton;
final Widget? appBarLeading;
final List<Widget>? appBarActions;
final bool noSafeArea;
final bool hideDrawer;
final bool fixedAppBarColor;
final String title;
const LayoutWrapper({
const IndentScaffold({
super.key,
this.child,
required this.title,
this.floatingActionButton,
this.appBarLeading,
this.appBarActions,
this.hideDrawer = false,
this.fixedAppBarColor = false,
this.noSafeArea = false,
});
@ -24,11 +31,14 @@ class LayoutWrapper extends StatelessWidget {
return Scaffold(
appBar: AppBar(
title: Text(title),
leading: appBarLeading,
actions: appBarActions,
centerTitle: false,
elevation: fixedAppBarColor ? 4 : null,
),
floatingActionButton: floatingActionButton,
drawer: const SolianNavigationDrawer(),
drawer: !hideDrawer ? const SolianNavigationDrawer() : null,
drawerScrimColor: SolianTheme.isLargeScreen(context) ? Colors.transparent : null,
body: noSafeArea ? content : SafeArea(child: content),
);
}

View File

@ -32,7 +32,7 @@ class SignInRequiredScreen extends StatelessWidget {
),
),
onTap: () {
router.goNamed('account');
SolianRouter.router.goNamed('account');
},
);
}