Skip to content

Commit

Permalink
feat: add mastery tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
SlayerOrnstein committed Dec 21, 2024
1 parent 4ab9298 commit c97f601
Show file tree
Hide file tree
Showing 61 changed files with 2,177 additions and 366 deletions.
4 changes: 4 additions & 0 deletions devtools_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
- drift: true
2 changes: 1 addition & 1 deletion lib/app/view/app_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class AppView extends StatelessWidget {
child: child,
);
},
child: SafeArea(child: children[currentIndex]),
child: children[currentIndex],
),
bottomNavigationBar: NavigationBar(
onDestinationSelected: (i) {
Expand Down
11 changes: 11 additions & 0 deletions lib/app/view/app_root.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:dynamic_color/dynamic_color.dart';
import 'package:feedback_sentry/feedback_sentry.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:navis/arsenal/arsenal.dart';
import 'package:navis/l10n/l10n.dart';
import 'package:navis/router/app_router.dart';
import 'package:navis/settings/settings.dart';
Expand Down Expand Up @@ -106,6 +107,16 @@ class _NavisAppState extends State<NavisApp> with WidgetsBindingObserver {
super.didChangeDependencies();

BlocProvider.of<WorldstateCubit>(context).fetchWorldstate();

final settings = context.read<UserSettingsCubit>().state;
final username = switch (settings) {
UserSettingsSuccess() => settings.username,
_ => null,
};

if (username != null) {
BlocProvider.of<ArsenalCubit>(context).updateArsenal(username);
}
}

@override
Expand Down
13 changes: 8 additions & 5 deletions lib/app/widgets/bloc_bootstrap.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:navis/arsenal/cubit/arsenal_cubit.dart';
import 'package:navis/settings/settings.dart';
import 'package:navis/worldstate/worldstate.dart';
import 'package:warframestat_repository/warframestat_repository.dart';
Expand All @@ -16,17 +17,18 @@ class BlocBootstrap extends StatefulWidget {
class _BlocBootstrapState extends State<BlocBootstrap> {
late WorldstateCubit _worldstateCubit;
late UserSettingsCubit _userSettingsCubit;
late ArsenalCubit _arsenalCubit;

@override
void initState() {
super.initState();

final worldstateRepo =
RepositoryProvider.of<WarframestatRepository>(context);
final usersettings = RepositoryProvider.of<UserSettings>(context);
final wsRepo = RepositoryProvider.of<WarframestatRepository>(context);
final settings = RepositoryProvider.of<UserSettings>(context);

_worldstateCubit = WorldstateCubit(worldstateRepo);
_userSettingsCubit = UserSettingsCubit(usersettings);
_worldstateCubit = WorldstateCubit(wsRepo);
_userSettingsCubit = UserSettingsCubit(settings);
_arsenalCubit = ArsenalCubit(wsRepo);
}

@override
Expand All @@ -35,6 +37,7 @@ class _BlocBootstrapState extends State<BlocBootstrap> {
providers: [
BlocProvider.value(value: _worldstateCubit),
BlocProvider.value(value: _userSettingsCubit),
BlocProvider.value(value: _arsenalCubit),
],
child: widget.child,
);
Expand Down
7 changes: 5 additions & 2 deletions lib/app/widgets/repo_bootstrap.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:drift_flutter/drift_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart';
Expand Down Expand Up @@ -31,8 +32,10 @@ class _RepositoryBootstrapState extends State<RepositoryBootstrap> {
super.initState();

_notifications = NotificationRepository();
_warframestatRepository =
WarframestatRepository(client: SentryHttpClient());
_warframestatRepository = WarframestatRepository(
client: SentryHttpClient(),
database: ArsenalDatabase(driftDatabase(name: 'arsenal')),
);

_notifications.configure();
}
Expand Down
2 changes: 2 additions & 0 deletions lib/arsenal/arsenal.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'cubit/arsenal_cubit.dart';
export 'widgets/widgets.dart';
32 changes: 32 additions & 0 deletions lib/arsenal/cubit/arsenal_cubit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:bloc/bloc.dart';
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:warframestat_repository/warframestat_repository.dart';

part 'arsenal_state.dart';

class ArsenalCubit extends Cubit<ArsenalState> {
ArsenalCubit(this.repository) : super(ArsenalInitial());

final WarframestatRepository repository;

late List<MasteryProgress> _xpInfo;

Future<void> updateArsenal(String username, {bool update = false}) async {
try {
emit(ArsenalUpdating());
await repository.updateArsenalItems(update: update);

_xpInfo = await repository.syncXpInfo(username);

emit(ArsenalSuccess(_xpInfo));
} catch (e, stack) {
debugPrint(e.toString());
emit(ArsenalFailure());

await Sentry.captureException(e, stackTrace: stack);
}
}
}
49 changes: 49 additions & 0 deletions lib/arsenal/cubit/arsenal_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
part of 'arsenal_cubit.dart';

sealed class ArsenalState extends Equatable {
const ArsenalState();

@override
List<Object> get props => [];
}

final class ArsenalInitial extends ArsenalState {}

final class ArsenalUpdating extends ArsenalState {}

final class ArsenalSuccess extends ArsenalState {
const ArsenalSuccess(this.xpInfo);

final List<MasteryProgress> xpInfo;

List<MasteryProgress> get inProgress {
return xpInfo.where((i) => i.rank < i.maxRank).toList()
..sort((a, b) {
if (a.rank == 0 && b.rank == 0) return 0;
if (a.rank == 0) return 1;
if (b.rank == 0) return -1;

return a.rank.compareTo(b.rank);
});
}

List<MasteryProgress> get warframes =>
xpInfo.whereNot((i) => i.item.type.isWeapon).toList();

List<MasteryProgress> get weapons =>
xpInfo.where((i) => i.item.type.isWeapon).toList();

List<MasteryProgress> get primaries =>
xpInfo.where((i) => i.item.type.isPrimary).toList();

List<MasteryProgress> get secondary =>
xpInfo.where((i) => i.item.type.isSecondary).toList();

List<MasteryProgress> get melee =>
xpInfo.where((i) => i.item.type.isMelee).toList();

@override
List<Object> get props => [xpInfo];
}

final class ArsenalFailure extends ArsenalState {}
33 changes: 33 additions & 0 deletions lib/arsenal/widgets/arsenal_item.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:navis/utils/item_extensions.dart';
import 'package:navis_ui/navis_ui.dart';
import 'package:warframestat_repository/warframestat_repository.dart';

class ArsenalItemWidget extends StatelessWidget {
const ArsenalItemWidget({super.key, required this.arsenalItem});

final MasteryProgress arsenalItem;

@override
Widget build(BuildContext context) {
return AppCard(
child: ListTile(
leading: CachedNetworkImage(
imageUrl: arsenalItem.item.imageUrl,
width: 50,
),
title: Text(arsenalItem.item.name),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Rank ${arsenalItem.rank}'),
LinearProgressIndicator(
value: arsenalItem.rank / arsenalItem.maxRank,
),
],
),
),
);
}
}
1 change: 1 addition & 0 deletions lib/arsenal/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'arsenal_item.dart';
4 changes: 4 additions & 0 deletions lib/codex/cubit/item_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class ItemCubit extends HydratedCubit<ItemState> {

Future<void> fetchItem() async {
final item = await _handleItemFetch(() async => repo.fetchItem(name));
if (item == null) {
emit(const ItemFetchFailure('Item does not exist'));
return;
}

emit(ItemFetchSuccess(item));
}
Expand Down
8 changes: 4 additions & 4 deletions lib/codex/views/codex_search_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ class CodexSearchPage extends StatelessWidget {
context,
),
sliver: SliverAppBar(
titleSpacing: 0,
floating: true,
scrolledUnderElevation: 0,
automaticallyImplyLeading: false,
clipBehavior: Clip.none,
shape: const StadiumBorder(),
scrolledUnderElevation: 0,
titleSpacing: 0,
backgroundColor: Colors.transparent,
automaticallyImplyLeading: false,
floating: true,
forceElevated: innerBoxIsScrolled,
title: const CodexSearchBar(),
),
Expand Down
2 changes: 1 addition & 1 deletion lib/codex/widgets/codex_entry/gun_stats.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class GunStats extends StatelessWidget {
),
RowItem(
text: Text(l10n.weaponTypeTitle),
child: Text(gun.type.category),
child: Text(gun.type.type),
),
if (gun.polarities?.isNotEmpty ?? false)
RowItem(
Expand Down
2 changes: 1 addition & 1 deletion lib/codex/widgets/codex_entry/melee_stats.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class MeleeStats extends StatelessWidget {
),
RowItem(
text: Text(l10n.weaponTypeTitle),
child: Text(melee.type.category),
child: Text(melee.type.type),
),
if (melee.stancePolarity != null)
RowItem(
Expand Down
25 changes: 22 additions & 3 deletions lib/home/views/home.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:navis/home/widgets/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:navis/home/home.dart';
import 'package:navis/settings/settings.dart';
import 'package:navis_ui/navis_ui.dart';

class HomePage extends StatelessWidget {
Expand All @@ -16,8 +18,25 @@ class HomeView extends StatelessWidget {

@override
Widget build(BuildContext context) {
return ListView(
children: const [NewsSection(), Gaps.gap16, ActivitiesSection()],
return BlocBuilder<UserSettingsCubit, UserSettingsState>(
builder: (context, state) {
final username = switch (state) {
UserSettingsSuccess() => state.username,
_ => null
};

final children = [
const NewsSection(),
const ActivitiesSection(),
if (username != null) const MasteryInProgressSection(),
];

return ListView.separated(
itemCount: children.length,
separatorBuilder: (_, __) => Gaps.gap16,
itemBuilder: (context, index) => children[index],
);
},
);
}
}
49 changes: 49 additions & 0 deletions lib/home/widgets/mastery_section.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:navis/arsenal/arsenal.dart';
import 'package:navis/home/widgets/section.dart';
import 'package:navis_ui/navis_ui.dart';

class MasteryInProgressSection extends StatelessWidget {
const MasteryInProgressSection({super.key});

@override
Widget build(BuildContext context) {
return Section(
title: const Text('Mastery in progress'),
content: BlocBuilder<ArsenalCubit, ArsenalState>(
builder: (context, state) {
const padding = EdgeInsets.symmetric(vertical: 16);

if (state is ArsenalUpdating) {
return const Padding(
padding: padding,
child: Text('Updating XP info'),
);
}

if (state is ArsenalFailure) {
return const Padding(
padding: padding,
child: Text('Error updating XP info'),
);
}

if (state is! ArsenalSuccess) {
return const Padding(
padding: padding,
child: WarframeSpinner(size: 100),
);
}

return Column(
children: [
for (final i in state.inProgress.take(5))
ArsenalItemWidget(arsenalItem: i),
],
);
},
),
);
}
}
1 change: 1 addition & 0 deletions lib/home/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export 'activities_section.dart';
export 'mastery_section.dart';
export 'news_section.dart';
Loading

0 comments on commit c97f601

Please sign in to comment.