Skip to content

Commit

Permalink
Merge branch 'release/v0.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
JuanM04 committed Jan 11, 2020
2 parents b5e9cfe + de3bef4 commit 7911e2a
Show file tree
Hide file tree
Showing 98 changed files with 18,134 additions and 430 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Animú es una app para ver anime sin complicaciones. Funciona con los servidores

Animú consta de la app (hecha en Flutter) y un servidor en ZEIT Now.

Este último sirve para saltarse la seguridad de Cloudflare al momento de pedirle información a AnimeFLV. Esto se hace porque Animú usa Web Scraping, que básicamente es descargar el HTML y sacar el contenido de ahí (en vez de pedirlo a una API). Todo lo que tiene que ver con eso está en `web/api/`; la página web está en `web/`.
Este último sirve para saltarse la seguridad de Cloudflare al momento de pedirle información a AnimeFLV. Esto se hace porque Animú usa Web Scraping, que básicamente es descargar el HTML y sacar el contenido de ahí (en vez de pedirlo a una API). Usa `web/api/get-cloudflare-id.ts` solamente para "fingir un PC real" y luego sigue haciendo peticiones desde la app. La página web está en `web/`.

Para el modo Transmitir, se usa la API proveida por VLC 3+. Más información [aquí](https://wiki.videolan.org/VLC_HTTP_requests/).

Expand All @@ -22,8 +22,6 @@ Tengo problemas, no me peguen.

## To-do

- Quitar retrocompatibilidades
- `web/api/search-animes.ts`: eliminar el parámetro `value`
- `web/api/get-natsiku.ts`: eliminar y poner el *Sources Service* en `web/api/get-episode-sources.ts`
- Animaciones
- Vincular animes guardados con Google
- Hacer tests
3 changes: 2 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:allowBackup="true">
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@style/LaunchTheme"
Expand Down
8 changes: 6 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:animu/screens/browse.dart';
import 'package:animu/screens/saved_animes.dart';
import 'package:animu/screens/settings/settings.dart';
import 'package:animu/screens/splash_screen/splash_screen.dart';
import 'package:animu/services/requests.dart';
import 'package:animu/utils/notifiers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand All @@ -26,8 +27,11 @@ class MyApp extends StatelessWidget {

final primaryColor = Color(0xFFBF3030); // Strawberry Red

return ChangeNotifierProvider<VLCNotifier>(
create: (_) => VLCNotifier(),
return MultiProvider(
providers: [
ChangeNotifierProvider<VLCNotifier>.value(value: VLCNotifier()),
Provider<RequestsService>.value(value: RequestsService()),
],
child: MaterialApp(
title: 'Animú',
theme: ThemeData(
Expand Down
12 changes: 7 additions & 5 deletions lib/screens/anime/anime.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:animu/screens/anime/episode_list.dart';
import 'package:animu/services/requests.dart';
import 'package:animu/utils/models.dart';
import 'package:animu/services/anime_database.dart';
import 'package:animu/utils/helpers.dart';
Expand All @@ -8,6 +9,7 @@ import 'package:animu/widgets/spinner.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';

import 'main_button.dart';

Expand All @@ -17,6 +19,7 @@ class AnimeScreen extends StatefulWidget {
}

class _AnimeScreenState extends State<AnimeScreen> {
RequestsService requestsService;
Anime anime;
List<Episode> episodes;
bool loading = true;
Expand All @@ -29,10 +32,7 @@ class _AnimeScreenState extends State<AnimeScreen> {
}

void getEpisodes() async {
List response = await getJSONFromServer('/get-episodes', {
'anime_id': anime.id.toString(),
'anime_slug': anime.slug,
});
List response = await requestsService.getEpisodes(anime: anime);

if (mounted)
setState(() {
Expand All @@ -47,6 +47,7 @@ class _AnimeScreenState extends State<AnimeScreen> {
Widget build(BuildContext context) {
if (anime == null) {
anime = ModalRoute.of(context).settings.arguments;
requestsService = Provider.of<RequestsService>(context);
getAnimeDBData();
}
if (episodes == null) getEpisodes();
Expand All @@ -61,9 +62,10 @@ class _AnimeScreenState extends State<AnimeScreen> {
overflow: Overflow.visible,
children: <Widget>[
Image.network(
'https://animeflv.net/uploads/animes/covers/${anime.id}.jpg',
getImageURL(ImageURLType.cover, anime: anime),
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
headers: requestsService.headers,
),
Positioned(
bottom: 5,
Expand Down
12 changes: 11 additions & 1 deletion lib/screens/anime/episode_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import 'dart:math';

import 'package:animu/screens/cast_player/cast_player.dart';
import 'package:animu/screens/player/player.dart';
import 'package:animu/services/requests.dart';
import 'package:animu/utils/helpers.dart';
import 'package:animu/utils/models.dart';
import 'package:animu/utils/notifiers.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -34,6 +36,8 @@ class EpisodeList extends StatelessWidget {

@override
Widget build(BuildContext context) {
final requestsService = Provider.of<RequestsService>(context);

return Column(
children: <Widget>[
Expanded(
Expand All @@ -53,7 +57,13 @@ class EpisodeList extends StatelessWidget {
ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Image.network(
'https://animu.juanm04.com/api/get-image?type=thumbnail&anime_id=${anime.id}&episode_n=${episodes[i].n}'),
getImageURL(
ImageURLType.thumbnail,
anime: anime,
episode: episodes[i],
),
headers: requestsService.headers,
),
),
Align(
alignment: Alignment.center,
Expand Down
15 changes: 11 additions & 4 deletions lib/screens/browse.dart
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
import 'package:animu/services/requests.dart';
import 'package:animu/widgets/anime_list.dart';
import 'package:animu/widgets/search_bar.dart';
import 'package:animu/utils/models.dart';
import 'package:animu/utils/helpers.dart';
import 'package:animu/widgets/spinner.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class Browse extends StatefulWidget {
@override
_BrowseState createState() => _BrowseState();
}

class _BrowseState extends State<Browse> {
RequestsService requestsService;
List<Anime> animes;
bool loading = false;

void getAnimes(String query) async {
setState(() => loading = true);

List response = await getJSONFromServer('/search-animes', {'query': query});
List response = await requestsService.searchAnimes(query);

if (mounted)
setState(() {
animes = new List<Anime>.from(response
.map((map) => Anime(
.map(
(map) => Anime(
id: int.parse(map['id']),
name: map['title'],
slug: map['slug']))
slug: map['slug'],
),
)
.toList());
loading = false;
});
Expand All @@ -51,6 +56,8 @@ class _BrowseState extends State<Browse> {

@override
Widget build(BuildContext context) {
requestsService = Provider.of<RequestsService>(context);

return Scaffold(
body: SafeArea(
child: Padding(
Expand Down
8 changes: 7 additions & 1 deletion lib/screens/cast_player/cast_player.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';

import 'package:animu/services/requests.dart';
import 'package:animu/services/sources.dart';
import 'package:animu/widgets/previous_next.dart';
import 'package:animu/utils/models.dart';
Expand All @@ -18,6 +19,7 @@ class CastPlayer extends StatefulWidget {
class _CastPlayerState extends State<CastPlayer> {
PlayerData data;
VLCNotifier vlc;
RequestsService requestsService;

Timer ticker;
dynamic tickerData;
Expand All @@ -28,7 +30,10 @@ class _CastPlayerState extends State<CastPlayer> {
}

void initPlayer() async {
final url = await getEpisodeURLFromData(data);
final url = await getEpisodeURLFromData(
requestsService: requestsService,
data: data,
);
if (!mounted) return;
if (url == null) return initPlayer();
tickerData = await vlc.send('in_play', input: url);
Expand Down Expand Up @@ -56,6 +61,7 @@ class _CastPlayerState extends State<CastPlayer> {
if (data == null) {
data = ModalRoute.of(context).settings.arguments;
vlc = Provider.of<VLCNotifier>(context);
requestsService = Provider.of<RequestsService>(context);
initPlayer();
}

Expand Down
23 changes: 18 additions & 5 deletions lib/screens/player/controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,22 @@ import 'package:video_player/video_player.dart';
class PlayerControls extends StatelessWidget {
final PlayerData data;
final VideoPlayerController controller;
final Function togglePlay;
final Function(Duration moment) seekTo;
final Function(Episode episode) changeEpisode;
PlayerControls({this.data, this.controller, this.seekTo, this.changeEpisode});

PlayerControls({
this.data,
this.togglePlay,
this.controller,
this.seekTo,
this.changeEpisode,
});

@override
Widget build(BuildContext context) {
return Container(
color: Colors.black26,
color: Colors.black38,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Expand All @@ -29,9 +37,14 @@ class PlayerControls extends StatelessWidget {
data: data,
changeEpisode: changeEpisode,
),
Icon(
Icons.play_arrow,
size: 100,
GestureDetector(
onTap: togglePlay,
child: Icon(
controller.value.isPlaying
? Icons.pause
: Icons.play_arrow,
size: 100,
),
),
PreviousNext(
type: PreviousNextType.next,
Expand Down
73 changes: 52 additions & 21 deletions lib/screens/player/player.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'package:animu/services/requests.dart';
import 'package:animu/services/sources.dart';
import 'package:animu/utils/models.dart';
import 'package:animu/widgets/spinner.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:screen/screen.dart';
import 'package:video_player/video_player.dart';

Expand All @@ -14,26 +16,46 @@ class Player extends StatefulWidget {
}

class _PlayerState extends State<Player> {
RequestsService requestsService;
PlayerData data;
VideoPlayerController _controller;
bool _showControls = true;

void initPlayer() async {
final url = await getEpisodeURLFromData(data);
final url = await getEpisodeURLFromData(
requestsService: requestsService,
data: data,
);

if (!mounted) return;
if (url == null) return initPlayer();

_controller = VideoPlayerController.network(url)
..initialize().then((_) => setState(() {}));
..initialize().then(
(_) {
_controller.addListener(() {
if (_controller != null) setState(() {});
});
setState(() {});
},
);
}

void togglePlay() {
if (_controller.value.isPlaying)
_controller.pause();
else
_controller.play();
}

void seekTo(Duration moment) {
_controller.seekTo(moment);
setState(() {});
}

void changeEpisode(Episode episode) {
data.currentEpisode = episode;
_controller.dispose();
_controller = null;
setState(() {});
}

@override
Expand All @@ -48,7 +70,10 @@ class _PlayerState extends State<Player> {

@override
void dispose() {
if (_controller != null) _controller.dispose();
if (_controller != null) {
_controller.dispose();
_controller = null;
}
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
Expand All @@ -60,7 +85,10 @@ class _PlayerState extends State<Player> {

@override
Widget build(BuildContext context) {
if (data == null) data = ModalRoute.of(context).settings.arguments;
if (data == null) {
data = ModalRoute.of(context).settings.arguments;
requestsService = Provider.of<RequestsService>(context);
}
if (_controller == null) initPlayer();

if (_controller != null && _controller.value.initialized)
Expand All @@ -81,23 +109,26 @@ class _PlayerState extends State<Player> {
),
),
GestureDetector(
child: !_controller.value.isPlaying
? PlayerControls(
data: data,
controller: _controller,
seekTo: seekTo,
changeEpisode: changeEpisode,
)
: Opacity(
opacity: 0,
child: Container(color: Colors.black),
),
onTap: () {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
setState(() {});
setState(() {
_showControls = !_showControls;
});
},
child: AnimatedSwitcher(
duration: Duration(milliseconds: 200),
child: _showControls
? PlayerControls(
data: data,
controller: _controller,
togglePlay: togglePlay,
seekTo: seekTo,
changeEpisode: changeEpisode,
)
: Opacity(
opacity: 0,
child: Container(color: Colors.black),
),
),
),
],
)
Expand Down
Loading

0 comments on commit 7911e2a

Please sign in to comment.