Initial commit

This commit is contained in:
2023-02-03 23:33:21 +01:00
commit ee4458d613
147 changed files with 5860 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:anitrack/src/data/anime.dart';
import 'package:anitrack/src/ui/bloc/anime_list_bloc.dart';
import 'package:anitrack/src/ui/bloc/anime_search_bloc.dart';
import 'package:anitrack/src/ui/constants.dart';
import 'package:anitrack/src/ui/widgets/anime.dart';
class AnimeListPage extends StatelessWidget {
static MaterialPageRoute<dynamic> get route => MaterialPageRoute<dynamic>(
builder: (_) => AnimeListPage(),
settings: const RouteSettings(
name: animeListRoute,
),
);
@override
Widget build(BuildContext context) {
return BlocBuilder<AnimeListBloc, AnimeListState>(
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: Text('Animes'),
),
body: ListView.builder(
itemCount: state.animes.length,
itemBuilder: (context, index) {
return AnimeListWidget(
data: state.animes[index],
onLeftSwipe: () {
context.read<AnimeListBloc>().add(
AnimeEpisodeDecrementedEvent(state.animes[index].id),
);
},
onRightSwipe: () {
context.read<AnimeListBloc>().add(
AnimeEpisodeIncrementedEvent(state.animes[index].id),
);
},
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<AnimeSearchBloc>().add(
AnimeSearchRequestedEvent(),
);
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
},
);
}
}

View File

@@ -0,0 +1,112 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:anitrack/src/data/anime.dart';
import 'package:anitrack/src/ui/bloc/anime_search_bloc.dart';
import 'package:anitrack/src/ui/constants.dart';
import 'package:anitrack/src/ui/widgets/anime.dart';
import 'package:anitrack/src/ui/widgets/image.dart';
class AnimeSearchPage extends StatelessWidget {
static MaterialPageRoute<dynamic> get route => MaterialPageRoute<dynamic>(
builder: (_) => AnimeSearchPage(),
settings: const RouteSettings(
name: animeSearchRoute,
),
);
@override
Widget build(BuildContext context) {
return BlocBuilder<AnimeSearchBloc, AnimeSearchState>(
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: Text('Anime Search'),
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Search query',
),
onSubmitted: (_) {
context.read<AnimeSearchBloc>().add(
SearchQuerySubmittedEvent(),
);
},
onChanged: (value) {
context.read<AnimeSearchBloc>().add(
SearchQueryChangedEvent(value),
);
},
),
),
if (state.working)
Expanded(
child: Align(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
)
else
ListView.builder(
shrinkWrap: true,
itemCount: state.searchResults.length,
itemBuilder: (context, index) {
final item = state.searchResults[index];
return InkWell(
onTap: () {
context.read<AnimeSearchBloc>().add(
AnimeAddedEvent(item),
);
},
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AnimeCoverImage(
url: item.thumbnailUrl,
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
item.title,
style: Theme.of(context).textTheme.titleLarge,
maxLines: 2,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
Text(
item.description,
style: Theme.of(context).textTheme.bodyMedium,
maxLines: 4,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
],
),
),
);
}
),
],
),
);
},
);
}
}