🐛 Fixes and optimization in programs
This commit is contained in:
parent
9cc577adbe
commit
d7359cfd0d
@ -9,6 +9,7 @@ import 'package:surface/providers/sn_network.dart';
|
|||||||
import 'package:surface/types/account.dart';
|
import 'package:surface/types/account.dart';
|
||||||
import 'package:surface/widgets/dialog.dart';
|
import 'package:surface/widgets/dialog.dart';
|
||||||
import 'package:surface/widgets/loading_indicator.dart';
|
import 'package:surface/widgets/loading_indicator.dart';
|
||||||
|
import 'package:surface/widgets/markdown_content.dart';
|
||||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||||
|
|
||||||
class AccountProgramScreen extends StatefulWidget {
|
class AccountProgramScreen extends StatefulWidget {
|
||||||
@ -86,14 +87,17 @@ class _AccountProgramScreenState extends State<AccountProgramScreen> {
|
|||||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => _ProgramJoinPopup(
|
builder: (context) => _ProgramJoinPopup(
|
||||||
program: ele,
|
program: ele,
|
||||||
isJoined: _programMembers
|
isJoined:
|
||||||
.any((ele) => ele.programId == ele.id),
|
_programMembers.any((e) => e.programId == ele.id),
|
||||||
),
|
),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
_fetchProgramMembers();
|
if (value == true) {
|
||||||
|
_fetchProgramMembers();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -137,7 +141,7 @@ class _AccountProgramScreenState extends State<AccountProgramScreen> {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
if (_programMembers
|
if (_programMembers
|
||||||
.any((ele) => ele.programId == ele.id))
|
.any((e) => e.programId == ele.id))
|
||||||
Text('accountProgramAlreadyJoined'.tr())
|
Text('accountProgramAlreadyJoined'.tr())
|
||||||
.opacity(0.75),
|
.opacity(0.75),
|
||||||
],
|
],
|
||||||
@ -205,80 +209,82 @@ class _ProgramJoinPopupState extends State<_ProgramJoinPopup> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return SizedBox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
height: MediaQuery.of(context).size.height * 0.75,
|
||||||
children: [
|
child: SingleChildScrollView(
|
||||||
Row(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.add, size: 24),
|
|
||||||
const Gap(16),
|
|
||||||
Text(
|
|
||||||
'accountProgramJoin',
|
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
|
||||||
).tr(),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 20, top: 16, bottom: 12),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (widget.program.appearance['banner'] != null)
|
Row(
|
||||||
AspectRatio(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
aspectRatio: 16 / 5,
|
children: [
|
||||||
child: ClipRRect(
|
const Icon(Symbols.add, size: 24),
|
||||||
borderRadius: BorderRadius.circular(8),
|
const Gap(16),
|
||||||
child: Container(
|
Text(
|
||||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
'accountProgramJoin',
|
||||||
child: Image.network(
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
widget.program.appearance['banner'],
|
).tr(),
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
],
|
||||||
|
).padding(horizontal: 20, top: 16, bottom: 12),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (widget.program.appearance['banner'] != null)
|
||||||
|
AspectRatio(
|
||||||
|
aspectRatio: 16 / 5,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: Container(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||||
|
child: Image.network(
|
||||||
|
widget.program.appearance['banner'],
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
).padding(bottom: 12),
|
||||||
|
Text(
|
||||||
|
widget.program.name,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
).bold(),
|
||||||
|
MarkdownTextContent(content: widget.program.description),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
'accountProgramJoinRequirements',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
).tr().bold(),
|
||||||
|
Text('≥EXP ${widget.program.expRequirement}'),
|
||||||
|
Text('≥Lv${getLevelFromExp(widget.program.expRequirement)}'),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
'accountProgramJoinPricing',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
).tr().bold(),
|
||||||
|
Text('walletCurrency${widget.program.price['currency'].toString().capitalize().replaceFirst('Normal', '')}')
|
||||||
|
.plural(widget.program.price['amount'].toDouble()),
|
||||||
|
Text('accountProgramJoinPricingHint').tr().opacity(0.75),
|
||||||
|
const Gap(8),
|
||||||
|
if (widget.isJoined)
|
||||||
|
Text('accountProgramLeaveHint')
|
||||||
|
.tr()
|
||||||
|
.opacity(0.75)
|
||||||
|
.padding(bottom: 8),
|
||||||
|
if (!widget.isJoined)
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _isBusy ? null : _joinProgram,
|
||||||
|
child: Text('join').tr(),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _isBusy ? null : _leaveProgram,
|
||||||
|
child: Text('leave').tr(),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
).padding(bottom: 12),
|
).padding(horizontal: 24),
|
||||||
Text(
|
Gap(MediaQuery.of(context).padding.bottom),
|
||||||
widget.program.name,
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
).bold(),
|
|
||||||
Text(
|
|
||||||
widget.program.description,
|
|
||||||
maxLines: 3,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
Text(
|
|
||||||
'accountProgramJoinRequirements',
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
).tr().bold(),
|
|
||||||
Text('≥EXP ${widget.program.expRequirement}'),
|
|
||||||
Text('≥Lv${getLevelFromExp(widget.program.expRequirement)}'),
|
|
||||||
const Gap(8),
|
|
||||||
Text(
|
|
||||||
'accountProgramJoinPricing',
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
).tr().bold(),
|
|
||||||
Text('walletCurrency${widget.program.price['currency'].toString().capitalize().replaceFirst('Normal', '')}')
|
|
||||||
.plural(widget.program.price['amount'].toDouble()),
|
|
||||||
Text('accountProgramJoinPricingHint').tr().opacity(0.75),
|
|
||||||
const Gap(8),
|
|
||||||
if (widget.isJoined)
|
|
||||||
Text('accountProgramLeaveHint')
|
|
||||||
.tr()
|
|
||||||
.opacity(0.75)
|
|
||||||
.padding(bottom: 8),
|
|
||||||
if (!widget.isJoined)
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: _isBusy ? null : _joinProgram,
|
|
||||||
child: Text('join').tr(),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: _isBusy ? null : _leaveProgram,
|
|
||||||
child: Text('leave').tr(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24),
|
),
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:responsive_framework/responsive_framework.dart';
|
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/providers/channel.dart';
|
import 'package:surface/providers/channel.dart';
|
||||||
import 'package:surface/providers/config.dart';
|
import 'package:surface/providers/config.dart';
|
||||||
@ -48,17 +47,6 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
|||||||
final nav = context.watch<NavigationProvider>();
|
final nav = context.watch<NavigationProvider>();
|
||||||
final cfg = context.watch<ConfigProvider>();
|
final cfg = context.watch<ConfigProvider>();
|
||||||
|
|
||||||
final routeName = GoRouter.of(context)
|
|
||||||
.routerDelegate
|
|
||||||
.currentConfiguration
|
|
||||||
.last
|
|
||||||
.route
|
|
||||||
.name;
|
|
||||||
final showNavButtons = cfg.hideBottomNav ||
|
|
||||||
!(nav.showBottomNavScreen.contains(routeName)
|
|
||||||
? ResponsiveBreakpoints.of(context).smallerOrEqualTo(MOBILE)
|
|
||||||
: false);
|
|
||||||
|
|
||||||
final backgroundColor = cfg.drawerIsExpanded ? Colors.transparent : null;
|
final backgroundColor = cfg.drawerIsExpanded ? Colors.transparent : null;
|
||||||
|
|
||||||
return ListenableBuilder(
|
return ListenableBuilder(
|
||||||
@ -67,7 +55,8 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
|||||||
return Drawer(
|
return Drawer(
|
||||||
elevation: widget.elevation,
|
elevation: widget.elevation,
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(0))),
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(0))),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -92,42 +81,39 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: _DrawerContentList(),
|
child: _DrawerContentList(),
|
||||||
),
|
),
|
||||||
if (showNavButtons)
|
Row(
|
||||||
Row(
|
spacing: 8,
|
||||||
spacing: 8,
|
children:
|
||||||
children:
|
nav.destinations.where((ele) => ele.isPinned).mapIndexed(
|
||||||
nav.destinations.where((ele) => ele.isPinned).mapIndexed(
|
(idx, ele) {
|
||||||
(idx, ele) {
|
return Expanded(
|
||||||
return Expanded(
|
child: Tooltip(
|
||||||
child: Tooltip(
|
message: ele.label.tr(),
|
||||||
message: ele.label.tr(),
|
child: IconButton(
|
||||||
child: IconButton(
|
icon: ele.icon,
|
||||||
icon: ele.icon,
|
color: nav.currentIndex == idx
|
||||||
color: nav.currentIndex == idx
|
? Theme.of(context).colorScheme.onPrimaryContainer
|
||||||
? Theme.of(context)
|
: Theme.of(context).colorScheme.onSurface,
|
||||||
.colorScheme
|
style: ButtonStyle(
|
||||||
.onPrimaryContainer
|
backgroundColor: WidgetStatePropertyAll(
|
||||||
: Theme.of(context).colorScheme.onSurface,
|
nav.currentIndex == idx
|
||||||
style: ButtonStyle(
|
? Theme.of(context)
|
||||||
backgroundColor: WidgetStatePropertyAll(
|
.colorScheme
|
||||||
nav.currentIndex == idx
|
.primaryContainer
|
||||||
? Theme.of(context)
|
: Colors.transparent,
|
||||||
.colorScheme
|
|
||||||
.primaryContainer
|
|
||||||
: Colors.transparent,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
onPressed: () {
|
|
||||||
GoRouter.of(context).goNamed(ele.screen);
|
|
||||||
Scaffold.of(context).closeDrawer();
|
|
||||||
nav.setIndex(idx);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
onPressed: () {
|
||||||
|
GoRouter.of(context).goNamed(ele.screen);
|
||||||
|
Scaffold.of(context).closeDrawer();
|
||||||
|
nav.setIndex(idx);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
).toList(),
|
},
|
||||||
).padding(horizontal: 16, bottom: 8),
|
).toList(),
|
||||||
|
).padding(horizontal: 16, bottom: 8),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user