Skip to content

Commit

Permalink
[Presentation] Reworked the game codes page
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfteam committed Jun 3, 2021
1 parent a704ef9 commit 9467603
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 98 deletions.
1 change: 0 additions & 1 deletion lib/infrastructure/data_service.dart
Expand Up @@ -37,7 +37,6 @@ class DataServiceImpl implements DataService {
_gameCodesBox = await Hive.openBox<GameCode>('gameCodes');
_gameCodeRewardsBox = await Hive.openBox<GameCodeReward>('gameCodeRewards');
_tierListBox = await Hive.openBox<TierListItem>('tierList');
await _gameCodesBox.clear();
}

@override
Expand Down
3 changes: 3 additions & 0 deletions lib/injection.dart
@@ -1,6 +1,7 @@
import 'package:genshindb/domain/services/calculator_service.dart';
import 'package:genshindb/domain/services/data_service.dart';
import 'package:genshindb/domain/services/device_info_service.dart';
import 'package:genshindb/domain/services/game_code_service.dart';
import 'package:genshindb/domain/services/genshin_service.dart';
import 'package:genshindb/domain/services/locale_service.dart';
import 'package:genshindb/domain/services/logging_service.dart';
Expand Down Expand Up @@ -36,4 +37,6 @@ Future<void> initInjection() async {
final dataService = DataServiceImpl(getIt<GenshinService>(), getIt<CalculatorService>());
await dataService.init();
getIt.registerSingleton<DataService>(dataService);

getIt.registerSingleton<GameCodeService>(GameCodeServiceImpl(getIt<LoggingService>(), getIt<GenshinService>()));
}
5 changes: 4 additions & 1 deletion lib/main.dart
Expand Up @@ -5,6 +5,7 @@ import 'application/bloc.dart';
import 'domain/services/calculator_service.dart';
import 'domain/services/data_service.dart';
import 'domain/services/device_info_service.dart';
import 'domain/services/game_code_service.dart';
import 'domain/services/genshin_service.dart';
import 'domain/services/locale_service.dart';
import 'domain/services/logging_service.dart';
Expand Down Expand Up @@ -105,7 +106,9 @@ class MyApp extends StatelessWidget {
create: (ctx) {
final dataService = getIt<DataService>();
final telemetryService = getIt<TelemetryService>();
return GameCodesBloc(dataService, telemetryService);
final gameCodeService = getIt<GameCodeService>();
final networkService = getIt<NetworkService>();
return GameCodesBloc(dataService, telemetryService, gameCodeService, networkService);
},
),
BlocProvider(
Expand Down
185 changes: 90 additions & 95 deletions lib/presentation/game_codes/game_codes_page.dart
@@ -1,21 +1,29 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:genshindb/application/bloc.dart';
import 'package:genshindb/domain/models/models.dart';
import 'package:genshindb/generated/l10n.dart';
import 'package:genshindb/presentation/shared/common_table_cell.dart';
import 'package:genshindb/presentation/shared/bullet_list.dart';
import 'package:genshindb/presentation/shared/item_description_detail.dart';
import 'package:genshindb/presentation/shared/styles.dart';
import 'package:genshindb/presentation/shared/nothing_found_column.dart';
import 'package:genshindb/presentation/shared/utils/toast_utils.dart';
import 'package:genshindb/presentation/shared/wrapped_ascension_material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:url_launcher/url_launcher.dart';

class GameCodesPage extends StatelessWidget {
import 'widgets/game_code_list_item.dart';

class GameCodesPage extends StatefulWidget {
const GameCodesPage({
Key key,
}) : super(key: key);

@override
_GameCodesPageState createState() => _GameCodesPageState();
}

class _GameCodesPageState extends State<GameCodesPage> {
final RefreshController _refreshController = RefreshController(initialRefresh: false);

@override
Widget build(BuildContext context) {
final s = S.of(context);
Expand All @@ -26,111 +34,75 @@ class GameCodesPage extends StatelessWidget {
IconButton(
icon: const Icon(Icons.open_in_new),
onPressed: () => _launchUrl('https://genshin.mihoyo.com/en/gift'),
)
),
IconButton(
icon: const Icon(Icons.info),
onPressed: () => _showInfoDialog(context),
),
],
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: Styles.edgeInsetAll10,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
BlocBuilder<GameCodesBloc, GameCodesState>(
builder: (ctx, state) => state.map(
loaded: (state) => _buildTableCard(s.workingCodes, state.workingGameCodes, context),
),
),
BlocBuilder<GameCodesBloc, GameCodesState>(
builder: (ctx, state) => state.map(
loaded: (state) => _buildTableCard(s.expiredCodes, state.expiredGameCodes, context),
child: SmartRefresher(
header: const MaterialClassicHeader(),
controller: _refreshController,
onRefresh: () {
context.read<GameCodesBloc>().add(const GameCodesEvent.refresh());
},
child: BlocConsumer<GameCodesBloc, GameCodesState>(
listener: (ctx, state) {
if (!state.isBusy) {
_refreshController.refreshCompleted();
}

if (state.isInternetAvailable == false) {
ToastUtils.showWarningToast(ToastUtils.of(context), s.noInternetConnection);
}
},
builder: (ctx, state) => state.expiredGameCodes.isEmpty && state.workingGameCodes.isEmpty
? state.isBusy
? const Center(child: CircularProgressIndicator())
: NothingFoundColumn(msg: '${s.noGameCodesHaveBeenLoaded}\n${s.pullToRefreshItems}', icon: Icons.refresh)
: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
margin: const EdgeInsets.only(top: 10),
child: _buildTableCard(s.workingCodes, state.isBusy, state.workingGameCodes, context),
),
_buildTableCard(s.expiredCodes, state.isBusy, state.expiredGameCodes, context),
],
),
),
),
],
),
),
),
),
);
}

Widget _buildTableCard(String title, List<GameCodeModel> codes, BuildContext context) {
final s = S.of(context);
final body = Card(
elevation: Styles.cardTenElevation,
margin: Styles.edgeInsetAll5,
shape: Styles.cardShape,
child: Padding(
padding: Styles.edgeInsetAll5,
child: Table(
columnWidths: const {
0: FractionColumnWidth(.3),
1: FractionColumnWidth(.4),
2: FractionColumnWidth(.3),
},
children: [
TableRow(
children: [
CommonTableCell(text: s.codes, padding: Styles.edgeInsetAll10),
CommonTableCell(text: s.rewards, padding: Styles.edgeInsetAll10),
Container(),
],
),
...codes.map((e) => _buildRow(s, context, e)).toList(),
],
),
),
);
@override
void dispose() {
_refreshController.dispose();
super.dispose();
}

Widget _buildTableCard(String title, bool isBusy, List<GameCodeModel> codes, BuildContext context) {
if (isBusy) {
return ItemDescriptionDetail(
title: title,
body: const SizedBox(height: 200, child: Center(child: CircularProgressIndicator())),
textColor: Theme.of(context).accentColor,
);
}
return ItemDescriptionDetail(
title: title,
body: body,
textColor: Theme.of(context).accentColor,
);
}

TableRow _buildRow(S s, BuildContext context, GameCodeModel model) {
final fToast = ToastUtils.of(context);
final rewards = model.rewards.map((m) => WrappedAscensionMaterial(image: m.fullImagePath, quantity: m.quantity, size: 20)).toList();
return TableRow(
children: [
CommonTableCell.child(
child: Center(
child: Tooltip(
message: model.code,
child: Text(
model.code,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle2.copyWith(fontSize: 12),
),
body: codes.isEmpty
? Container()
: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: codes.map((e) => GameCodeListItem(item: e)).toList(),
),
),
),
CommonTableCell.child(
child: Wrap(alignment: WrapAlignment.center, children: rewards),
),
CommonTableCell.child(
child: Wrap(
alignment: WrapAlignment.center,
children: [
IconButton(
tooltip: !model.isUsed ? s.markAsUsed : s.markAsUnused,
splashRadius: 20,
icon: Icon(Icons.check, color: model.isUsed ? Colors.green : Colors.red),
onPressed: () => context.read<GameCodesBloc>().add(GameCodesEvent.markAsUsed(code: model.code, wasUsed: !model.isUsed)),
),
IconButton(
tooltip: s.copy,
splashRadius: 20,
icon: const Icon(Icons.copy),
onPressed: () => Clipboard.setData(ClipboardData(text: model.code)).then(
(value) => ToastUtils.showInfoToast(fToast, s.codeXWasCopied(model.code)),
),
)
],
),
)
],
);
}

Expand All @@ -139,4 +111,27 @@ class GameCodesPage extends StatelessWidget {
await launch(url);
}
}

Future<void> _showInfoDialog(BuildContext context) async {
final s = S.of(context);
//TODO: SWIPE TO SEE MORE
final explanations = [
s.internetIsRequiredToRefreshItems,
];
await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(s.information),
content: SingleChildScrollView(
child: BulletList(items: explanations, fontSize: 14),
),
actions: [
ElevatedButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(s.ok),
)
],
),
);
}
}

0 comments on commit 9467603

Please sign in to comment.