Compare commits
No commits in common. "e742338d920e9de2ec7122313ab79ff05b9c7d21" and "c0680a3134a5529e38444ec4b8da7f684c5b7ba2" have entirely different histories.
e742338d92
...
c0680a3134
@ -47,11 +47,7 @@ class SolianApp extends StatelessWidget {
|
|||||||
child: Overlay(
|
child: Overlay(
|
||||||
initialEntries: [
|
initialEntries: [
|
||||||
OverlayEntry(builder: (context) {
|
OverlayEntry(builder: (context) {
|
||||||
return ScaffoldMessenger(
|
return NotificationNotifier(child: child ?? Container());
|
||||||
child: Scaffold(
|
|
||||||
body: NotificationNotifier(child: child ?? Container()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
OverlayEntry(builder: (context) => const CallOverlay()),
|
OverlayEntry(builder: (context) => const CallOverlay()),
|
||||||
],
|
],
|
||||||
|
133
lib/router.dart
133
lib/router.dart
@ -26,52 +26,16 @@ import 'package:solian/widgets/layouts/two_column.dart';
|
|||||||
abstract class SolianRouter {
|
abstract class SolianRouter {
|
||||||
static final router = GoRouter(
|
static final router = GoRouter(
|
||||||
routes: [
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: '/',
|
||||||
|
name: 'explore',
|
||||||
|
builder: (context, state) => const ExploreScreen(),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/notification',
|
path: '/notification',
|
||||||
name: 'notification',
|
name: 'notification',
|
||||||
builder: (context, state) => const NotificationScreen(),
|
builder: (context, state) => const NotificationScreen(),
|
||||||
),
|
),
|
||||||
ShellRoute(
|
|
||||||
pageBuilder: (context, state, child) => defaultPageBuilder(
|
|
||||||
context,
|
|
||||||
state,
|
|
||||||
SolianTheme.isLargeScreen(context)
|
|
||||||
? TwoColumnLayout(
|
|
||||||
sideChild: const ExplorePostScreen(),
|
|
||||||
mainChild: child,
|
|
||||||
)
|
|
||||||
: child,
|
|
||||||
),
|
|
||||||
routes: [
|
|
||||||
GoRoute(
|
|
||||||
path: '/',
|
|
||||||
name: 'explore',
|
|
||||||
builder: (context, state) =>
|
|
||||||
!SolianTheme.isLargeScreen(context) ? const ExplorePostScreen() : const PageEmptyWidget(),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: '/posts/publish/moments',
|
|
||||||
name: 'posts.moments.editor',
|
|
||||||
builder: (context, state) => MomentEditorScreen(editing: state.extra as Post?),
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: '/posts/publish/comments',
|
|
||||||
name: 'posts.comments.editor',
|
|
||||||
builder: (context, state) {
|
|
||||||
final args = state.extra as CommentPostArguments;
|
|
||||||
return CommentEditorScreen(editing: args.editing, related: args.related);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: '/posts/:dataset/:alias',
|
|
||||||
name: 'posts.screen',
|
|
||||||
builder: (context, state) => PostScreen(
|
|
||||||
alias: state.pathParameters['alias'] as String,
|
|
||||||
dataset: state.pathParameters['dataset'] as String,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
ShellRoute(
|
ShellRoute(
|
||||||
pageBuilder: (context, state, child) => defaultPageBuilder(
|
pageBuilder: (context, state, child) => defaultPageBuilder(
|
||||||
context,
|
context,
|
||||||
@ -117,50 +81,55 @@ abstract class SolianRouter {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
ShellRoute(
|
GoRoute(
|
||||||
pageBuilder: (context, state, child) => defaultPageBuilder(
|
path: '/account',
|
||||||
context,
|
name: 'account',
|
||||||
state,
|
builder: (context, state) => const AccountScreen(),
|
||||||
SolianTheme.isLargeScreen(context)
|
),
|
||||||
? TwoColumnLayout(
|
GoRoute(
|
||||||
sideChild: const AccountScreen(),
|
path: '/posts/publish/moments',
|
||||||
mainChild: child,
|
name: 'posts.moments.editor',
|
||||||
)
|
builder: (context, state) => MomentEditorScreen(editing: state.extra as Post?),
|
||||||
: child,
|
),
|
||||||
),
|
GoRoute(
|
||||||
routes: [
|
path: '/posts/publish/comments',
|
||||||
GoRoute(
|
name: 'posts.comments.editor',
|
||||||
path: '/account',
|
builder: (context, state) {
|
||||||
name: 'account',
|
final args = state.extra as CommentPostArguments;
|
||||||
builder: (context, state) =>
|
return CommentEditorScreen(editing: args.editing, related: args.related);
|
||||||
!SolianTheme.isLargeScreen(context) ? const AccountScreen() : const PageEmptyWidget(),
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/auth/sign-in',
|
path: '/posts/:dataset/:alias',
|
||||||
name: 'auth.sign-in',
|
name: 'posts.screen',
|
||||||
builder: (context, state) => SignInScreen(),
|
builder: (context, state) => PostScreen(
|
||||||
),
|
alias: state.pathParameters['alias'] as String,
|
||||||
GoRoute(
|
dataset: state.pathParameters['dataset'] as String,
|
||||||
path: '/auth/sign-up',
|
),
|
||||||
name: 'auth.sign-up',
|
),
|
||||||
builder: (context, state) => SignUpScreen(),
|
GoRoute(
|
||||||
),
|
path: '/auth/sign-in',
|
||||||
GoRoute(
|
name: 'auth.sign-in',
|
||||||
path: '/account/friend',
|
builder: (context, state) => SignInScreen(),
|
||||||
name: 'account.friend',
|
),
|
||||||
builder: (context, state) => const FriendScreen(),
|
GoRoute(
|
||||||
),
|
path: '/auth/sign-up',
|
||||||
GoRoute(
|
name: 'auth.sign-up',
|
||||||
path: '/account/personalize',
|
builder: (context, state) => SignUpScreen(),
|
||||||
name: 'account.personalize',
|
),
|
||||||
builder: (context, state) => const PersonalizeScreen(),
|
GoRoute(
|
||||||
),
|
path: '/account/friend',
|
||||||
]),
|
name: 'account.friend',
|
||||||
|
builder: (context, state) => const FriendScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/account/personalize',
|
||||||
|
name: 'account.personalize',
|
||||||
|
builder: (context, state) => const PersonalizeScreen(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
static GoRoute get currentRoute => SolianRouter.router.routerDelegate.currentConfiguration.last.route;
|
|
||||||
|
|
||||||
static Page defaultPageBuilder(
|
static Page defaultPageBuilder(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
GoRouterState state,
|
GoRouterState state,
|
||||||
|
@ -2,30 +2,73 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
|
import 'package:solian/screens/account/friend.dart';
|
||||||
|
import 'package:solian/screens/account/personalize.dart';
|
||||||
import 'package:solian/widgets/account/account_avatar.dart';
|
import 'package:solian/widgets/account/account_avatar.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
import 'package:solian/widgets/empty.dart';
|
||||||
import 'package:solian/widgets/scaffold.dart';
|
import 'package:solian/widgets/scaffold.dart';
|
||||||
|
|
||||||
class AccountScreen extends StatelessWidget {
|
class AccountScreen extends StatefulWidget {
|
||||||
const AccountScreen({super.key});
|
const AccountScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AccountScreen> createState() => _AccountScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AccountScreenState extends State<AccountScreen> {
|
||||||
|
String? _title;
|
||||||
|
String? _selectedTab;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
final isLargeScreen = screenWidth >= 600;
|
||||||
|
|
||||||
|
Widget renderContent() {
|
||||||
|
switch (_selectedTab) {
|
||||||
|
case 'account.friend':
|
||||||
|
return const FriendScreenWidget();
|
||||||
|
case 'account.personalize':
|
||||||
|
return const PersonalizeScreenWidget();
|
||||||
|
default:
|
||||||
|
return const PageEmptyWidget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return IndentScaffold(
|
return IndentScaffold(
|
||||||
title: AppLocalizations.of(context)!.account,
|
title: _title ?? AppLocalizations.of(context)!.account,
|
||||||
noSafeArea: true,
|
noSafeArea: true,
|
||||||
fixedAppBarColor: true,
|
fixedAppBarColor: true,
|
||||||
child: AccountScreenWidget(
|
child: isLargeScreen
|
||||||
onSelect: (item) {
|
? Row(
|
||||||
SolianRouter.router.pushNamed(item);
|
children: [
|
||||||
},
|
Flexible(
|
||||||
),
|
flex: 2,
|
||||||
|
child: AccountScreenWidget(
|
||||||
|
onSelect: (item, title) {
|
||||||
|
setState(() {
|
||||||
|
_selectedTab = item;
|
||||||
|
_title = title;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const VerticalDivider(thickness: 0.3, width: 0.3),
|
||||||
|
Flexible(flex: 4, child: renderContent()),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: AccountScreenWidget(
|
||||||
|
onSelect: (item, _) {
|
||||||
|
SolianRouter.router.pushNamed(item);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccountScreenWidget extends StatefulWidget {
|
class AccountScreenWidget extends StatefulWidget {
|
||||||
final Function(String item) onSelect;
|
final Function(String item, String title) onSelect;
|
||||||
|
|
||||||
const AccountScreenWidget({super.key, required this.onSelect});
|
const AccountScreenWidget({super.key, required this.onSelect});
|
||||||
|
|
||||||
@ -62,7 +105,7 @@ class _AccountScreenWidgetState extends State<AccountScreenWidget> {
|
|||||||
leading: const Icon(Icons.color_lens),
|
leading: const Icon(Icons.color_lens),
|
||||||
title: Text(AppLocalizations.of(context)!.personalize),
|
title: Text(AppLocalizations.of(context)!.personalize),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.onSelect('account.personalize');
|
widget.onSelect('account.personalize', AppLocalizations.of(context)!.personalize);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@ -70,7 +113,7 @@ class _AccountScreenWidgetState extends State<AccountScreenWidget> {
|
|||||||
leading: const Icon(Icons.diversity_1),
|
leading: const Icon(Icons.diversity_1),
|
||||||
title: Text(AppLocalizations.of(context)!.friend),
|
title: Text(AppLocalizations.of(context)!.friend),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.onSelect('account.friend');
|
widget.onSelect('account.friend', AppLocalizations.of(context)!.friend);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
@ -32,6 +32,7 @@ class ChatScreen extends StatelessWidget {
|
|||||||
title: chat.focusChannel?.name ?? 'Loading...',
|
title: chat.focusChannel?.name ?? 'Loading...',
|
||||||
hideDrawer: true,
|
hideDrawer: true,
|
||||||
fixedAppBarColor: SolianTheme.isLargeScreen(context),
|
fixedAppBarColor: SolianTheme.isLargeScreen(context),
|
||||||
|
appBarLeading: IconButton(icon: const Icon(Icons.tag), onPressed: () {}),
|
||||||
appBarActions: chat.focusChannel != null
|
appBarActions: chat.focusChannel != null
|
||||||
? [
|
? [
|
||||||
ChannelCallAction(
|
ChannelCallAction(
|
||||||
|
@ -25,17 +25,10 @@ class ChatListScreen extends StatelessWidget {
|
|||||||
fixedAppBarColor: SolianTheme.isLargeScreen(context),
|
fixedAppBarColor: SolianTheme.isLargeScreen(context),
|
||||||
child: ChatListWidget(
|
child: ChatListWidget(
|
||||||
onSelect: (item) {
|
onSelect: (item) {
|
||||||
if (SolianRouter.currentRoute.name == 'chat.channel') {
|
SolianRouter.router.pushReplacementNamed(
|
||||||
SolianRouter.router.pushReplacementNamed(
|
'chat.channel',
|
||||||
'chat.channel',
|
pathParameters: {'channel': item.alias},
|
||||||
pathParameters: {'channel': item.alias},
|
);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
SolianRouter.router.pushNamed(
|
|
||||||
'chat.channel',
|
|
||||||
pathParameters: {'channel': item.alias},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -6,50 +6,85 @@ import 'package:solian/models/pagination.dart';
|
|||||||
import 'package:solian/models/post.dart';
|
import 'package:solian/models/post.dart';
|
||||||
import 'package:solian/providers/auth.dart';
|
import 'package:solian/providers/auth.dart';
|
||||||
import 'package:solian/router.dart';
|
import 'package:solian/router.dart';
|
||||||
|
import 'package:solian/screens/posts/screen.dart';
|
||||||
import 'package:solian/utils/service_url.dart';
|
import 'package:solian/utils/service_url.dart';
|
||||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:solian/utils/theme.dart';
|
import 'package:solian/widgets/empty.dart';
|
||||||
import 'package:solian/widgets/scaffold.dart';
|
import 'package:solian/widgets/scaffold.dart';
|
||||||
import 'package:solian/widgets/notification_notifier.dart';
|
import 'package:solian/widgets/notification_notifier.dart';
|
||||||
import 'package:solian/widgets/posts/post.dart';
|
import 'package:solian/widgets/posts/post.dart';
|
||||||
|
|
||||||
class ExplorePostScreen extends StatelessWidget {
|
class ExploreScreen extends StatefulWidget {
|
||||||
const ExplorePostScreen({super.key});
|
const ExploreScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ExploreScreen> createState() => _ExploreScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExploreScreenState extends State<ExploreScreen> {
|
||||||
|
Post? _selectedPost;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
final isLargeScreen = screenWidth >= 600;
|
||||||
|
|
||||||
return IndentScaffold(
|
return IndentScaffold(
|
||||||
noSafeArea: true,
|
noSafeArea: true,
|
||||||
fixedAppBarColor: SolianTheme.isLargeScreen(context),
|
fixedAppBarColor: isLargeScreen,
|
||||||
appBarActions: const [NotificationButton()],
|
appBarActions: const [NotificationButton()],
|
||||||
title: AppLocalizations.of(context)!.explore,
|
title: AppLocalizations.of(context)!.explore,
|
||||||
child: ExplorePostWidget(
|
child: isLargeScreen
|
||||||
onSelect: (item) {
|
? Row(
|
||||||
SolianRouter.router.pushNamed(
|
children: [
|
||||||
'posts.screen',
|
Flexible(
|
||||||
pathParameters: {
|
flex: 2,
|
||||||
'alias': item.alias,
|
child: ExploreScreenWidget(
|
||||||
'dataset': item.dataset,
|
onSelect: (item) {
|
||||||
},
|
setState(() => _selectedPost = item);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
|
const VerticalDivider(thickness: 0.3, width: 0.3),
|
||||||
|
Flexible(
|
||||||
|
flex: 4,
|
||||||
|
child: _selectedPost == null
|
||||||
|
? const PageEmptyWidget()
|
||||||
|
: PostScreenWidget(
|
||||||
|
key: Key('p${_selectedPost!.id}'),
|
||||||
|
dataset: _selectedPost!.dataset,
|
||||||
|
alias: _selectedPost!.alias,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: ExploreScreenWidget(
|
||||||
|
onSelect: (item) {
|
||||||
|
SolianRouter.router.pushNamed(
|
||||||
|
'posts.screen',
|
||||||
|
pathParameters: {
|
||||||
|
'alias': item.alias,
|
||||||
|
'dataset': item.dataset,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExplorePostWidget extends StatefulWidget {
|
class ExploreScreenWidget extends StatefulWidget {
|
||||||
final Function(Post item) onSelect;
|
final Function(Post item) onSelect;
|
||||||
|
|
||||||
const ExplorePostWidget({super.key, required this.onSelect});
|
const ExploreScreenWidget({super.key, required this.onSelect});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ExplorePostWidget> createState() => _ExplorePostWidgetState();
|
State<ExploreScreenWidget> createState() => _ExploreScreenWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ExplorePostWidgetState extends State<ExplorePostWidget> {
|
class _ExploreScreenWidgetState extends State<ExploreScreenWidget> {
|
||||||
final PagingController<int, Post> _pagingController = PagingController(firstPageKey: 0);
|
final PagingController<int, Post> _pagingController = PagingController(firstPageKey: 0);
|
||||||
|
|
||||||
final http.Client _client = http.Client();
|
final http.Client _client = http.Client();
|
||||||
|
@ -9,6 +9,9 @@ abstract class SolianTheme {
|
|||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
colorScheme: ColorScheme.fromSeed(brightness: brightness, seedColor: Colors.indigo),
|
colorScheme: ColorScheme.fromSeed(brightness: brightness, seedColor: Colors.indigo),
|
||||||
|
snackBarTheme: const SnackBarThemeData(
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,15 +13,19 @@ class TwoColumnLayout extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return ScaffoldMessenger(
|
||||||
children: [
|
child: Scaffold(
|
||||||
SizedBox(
|
body: Row(
|
||||||
width: 400,
|
children: [
|
||||||
child: sideChild,
|
SizedBox(
|
||||||
|
width: 400,
|
||||||
|
child: sideChild,
|
||||||
|
),
|
||||||
|
const VerticalDivider(width: 0.3, thickness: 0.3),
|
||||||
|
Expanded(child: mainChild ?? const PageEmptyWidget()),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const VerticalDivider(width: 0.3, thickness: 0.3),
|
),
|
||||||
Expanded(child: mainChild ?? const PageEmptyWidget()),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||||
import 'package:solian/models/post.dart';
|
import 'package:solian/models/post.dart';
|
||||||
import 'package:solian/utils/theme.dart';
|
|
||||||
import 'package:solian/widgets/account/account_avatar.dart';
|
import 'package:solian/widgets/account/account_avatar.dart';
|
||||||
import 'package:solian/widgets/posts/comment_list.dart';
|
import 'package:solian/widgets/posts/comment_list.dart';
|
||||||
import 'package:solian/widgets/posts/content/article.dart';
|
import 'package:solian/widgets/posts/content/article.dart';
|
||||||
@ -88,13 +87,16 @@ class _PostItemState extends State<PostItem> {
|
|||||||
Widget renderAttachments() {
|
Widget renderAttachments() {
|
||||||
if (widget.item.modelType == 'article') return Container();
|
if (widget.item.modelType == 'article') return Container();
|
||||||
|
|
||||||
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
final isLargeScreen = screenWidth >= 600;
|
||||||
|
|
||||||
if (widget.item.attachments != null && widget.item.attachments!.isNotEmpty) {
|
if (widget.item.attachments != null && widget.item.attachments!.isNotEmpty) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(top: 8),
|
padding: const EdgeInsets.only(top: 8),
|
||||||
child: AttachmentList(
|
child: AttachmentList(
|
||||||
items: widget.item.attachments!,
|
items: widget.item.attachments!,
|
||||||
provider: 'interactive',
|
provider: 'interactive',
|
||||||
noTag: SolianTheme.isLargeScreen(context) && widget.brief,
|
noTag: isLargeScreen && widget.brief,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user