refactor: add method return types
parent
bb356120fa
commit
8a57992fd5
|
@ -27,7 +27,49 @@ class WikidataMovieData extends MovieData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String createUpcomingMovieQuery(DateTime startDate, int limit) {
|
class WikidataMovieApi implements MovieApi {
|
||||||
|
ApiManager searchApi = ApiManager("https://www.wikidata.org/w/api.php");
|
||||||
|
ApiManager queryApi =
|
||||||
|
ApiManager("https://query.wikidata.org/sparql?format=json");
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> addMovieDetails(List<MovieData> movies) {
|
||||||
|
// TODO: implement addMovieDetails
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<WikidataMovieData>> getUpcomingMovies(DateTime startDate,
|
||||||
|
[int count = 100]) async {
|
||||||
|
Response response = await queryApi.get(
|
||||||
|
"&query=${Uri.encodeComponent(_createUpcomingMovieQuery(startDate, count))}");
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
throw Exception(
|
||||||
|
"The Wikidata request for upcoming movies failed with status ${response.statusCode} ${response.reasonPhrase}");
|
||||||
|
}
|
||||||
|
Map<String, dynamic> result = jsonDecode(response.body);
|
||||||
|
List<dynamic> entries = result["results"]["bindings"];
|
||||||
|
List<WikidataMovieData> movies = [];
|
||||||
|
for (Map<String, dynamic> entry in entries) {
|
||||||
|
String identifier =
|
||||||
|
RegExp(r"Q\d+$").firstMatch(entry["movie"]["value"])![0]!;
|
||||||
|
movies.add(WikidataMovieData(
|
||||||
|
entry["movieLabel"]["value"] as String,
|
||||||
|
DateTime.parse(entry["minReleaseDate"]["value"] as String),
|
||||||
|
_precisionFromWikidata(int.parse(entry["datePrecision"]["value"])),
|
||||||
|
int.parse(identifier.substring(1))));
|
||||||
|
}
|
||||||
|
return movies;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<WikidataMovieData>> searchForMovies(String searchTerm) {
|
||||||
|
// TODO: implement searchForMovies
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _createUpcomingMovieQuery(DateTime startDate, int limit) {
|
||||||
String date = DateFormat("yyyy-MM-dd").format(startDate);
|
String date = DateFormat("yyyy-MM-dd").format(startDate);
|
||||||
return """
|
return """
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -51,7 +93,7 @@ ORDER BY ?minReleaseDate
|
||||||
LIMIT $limit""";
|
LIMIT $limit""";
|
||||||
}
|
}
|
||||||
|
|
||||||
DatePrecision precisionFromWikidata(int precision) {
|
DatePrecision _precisionFromWikidata(int precision) {
|
||||||
return switch (precision) {
|
return switch (precision) {
|
||||||
>= 11 => DatePrecision.day,
|
>= 11 => DatePrecision.day,
|
||||||
10 => DatePrecision.month,
|
10 => DatePrecision.month,
|
||||||
|
@ -61,45 +103,3 @@ DatePrecision precisionFromWikidata(int precision) {
|
||||||
_ => throw Exception("Unexpected precision value: $precision"),
|
_ => throw Exception("Unexpected precision value: $precision"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class WikidataMovieApi implements MovieApi {
|
|
||||||
ApiManager searchApi = ApiManager("https://www.wikidata.org/w/api.php");
|
|
||||||
ApiManager queryApi =
|
|
||||||
ApiManager("https://query.wikidata.org/sparql?format=json");
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> addMovieDetails(List<MovieData> movies) {
|
|
||||||
// TODO: implement addMovieDetails
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<WikidataMovieData>> getUpcomingMovies(DateTime startDate,
|
|
||||||
[int count = 100]) async {
|
|
||||||
Response response = await queryApi.get(
|
|
||||||
"&query=${Uri.encodeComponent(createUpcomingMovieQuery(startDate, count))}");
|
|
||||||
if (response.statusCode != 200) {
|
|
||||||
throw Exception(
|
|
||||||
"The Wikidata request for upcoming movies failed with status ${response.statusCode} ${response.reasonPhrase}");
|
|
||||||
}
|
|
||||||
Map<String, dynamic> result = jsonDecode(response.body);
|
|
||||||
List<dynamic> entries = result["results"]["bindings"];
|
|
||||||
List<WikidataMovieData> movies = [];
|
|
||||||
for (Map<String, dynamic> entry in entries) {
|
|
||||||
String identifier =
|
|
||||||
RegExp(r"Q\d+$").firstMatch(entry["movie"]["value"])![0]!;
|
|
||||||
movies.add(WikidataMovieData(
|
|
||||||
entry["movieLabel"]["value"] as String,
|
|
||||||
DateTime.parse(entry["minReleaseDate"]["value"] as String),
|
|
||||||
precisionFromWikidata(int.parse(entry["datePrecision"]["value"])),
|
|
||||||
int.parse(identifier.substring(1))));
|
|
||||||
}
|
|
||||||
return movies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<WikidataMovieData>> searchForMovies(String searchTerm) {
|
|
||||||
// TODO: implement searchForMovies
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
String _durationApproximatedInWords(Duration duration) {
|
||||||
|
int seconds = duration.inSeconds;
|
||||||
|
int minutes = duration.inMinutes;
|
||||||
|
int hours = duration.inHours;
|
||||||
|
int days = duration.inDays;
|
||||||
|
int weeks = (days / 7).floor();
|
||||||
|
int months = (days / 30).floor();
|
||||||
|
int years = (days / 365).floor();
|
||||||
|
int centuries = (years / 100).floor();
|
||||||
|
if (duration == Duration.zero) {
|
||||||
|
return "now";
|
||||||
|
}
|
||||||
|
if (seconds == 0) {
|
||||||
|
return "now";
|
||||||
|
}
|
||||||
|
if (seconds < 60) {
|
||||||
|
return seconds > 1 ? "$seconds seconds" : "a second";
|
||||||
|
}
|
||||||
|
if (minutes < 60) {
|
||||||
|
return minutes > 1 ? "$minutes minutes" : "a minute";
|
||||||
|
}
|
||||||
|
if (hours < 24) {
|
||||||
|
return hours > 1 ? "$hours hours" : "an hour";
|
||||||
|
}
|
||||||
|
if (days < 7) {
|
||||||
|
return days > 1 ? "$days days" : "a day";
|
||||||
|
}
|
||||||
|
if (months == 0) {
|
||||||
|
return weeks > 1 ? "$weeks weeks" : "a week";
|
||||||
|
}
|
||||||
|
if (years == 0) {
|
||||||
|
return months > 1 ? "$months months" : "a month";
|
||||||
|
}
|
||||||
|
if (years < 100) {
|
||||||
|
return years > 1 ? "$years years" : "a year";
|
||||||
|
}
|
||||||
|
return centuries > 1 ? "$centuries centuries" : "a century";
|
||||||
|
}
|
||||||
|
|
||||||
|
String _durationToRelativeTimeString(Duration duration) {
|
||||||
|
if (duration.isNegative) {
|
||||||
|
return "${_durationApproximatedInWords(-duration)} ago";
|
||||||
|
} else if (duration == Duration.zero) {
|
||||||
|
return "now";
|
||||||
|
} else {
|
||||||
|
return "in ${_durationApproximatedInWords(duration)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String dateRelativeToNow(DateTime date) {
|
||||||
|
DateTime dateOnly = DateTime.utc(date.year, date.month, date.day);
|
||||||
|
DateTime now = DateTime.now().toUtc();
|
||||||
|
DateTime today = DateTime.utc(now.year, now.month, now.day);
|
||||||
|
Duration diff = dateOnly.difference(today);
|
||||||
|
return _durationToRelativeTimeString(diff);
|
||||||
|
}
|
|
@ -39,6 +39,8 @@ class MovieData extends ChangeNotifier {
|
||||||
List<TitleInCountry>? _titles;
|
List<TitleInCountry>? _titles;
|
||||||
List<Review>? _reviews;
|
List<Review>? _reviews;
|
||||||
|
|
||||||
|
MovieData(this._title, this._releaseDate, this._releaseDatePrecision);
|
||||||
|
|
||||||
String get title {
|
String get title {
|
||||||
return _title;
|
return _title;
|
||||||
}
|
}
|
||||||
|
@ -139,8 +141,6 @@ class MovieData extends ChangeNotifier {
|
||||||
return title == other.title && releaseDate == other.releaseDate;
|
return title == other.title && releaseDate == other.releaseDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
MovieData(this._title, this._releaseDate, this._releaseDatePrecision);
|
|
||||||
|
|
||||||
MovieData.fromJsonEncodable(Map json)
|
MovieData.fromJsonEncodable(Map json)
|
||||||
: _title = json["title"],
|
: _title = json["title"],
|
||||||
_releaseDate = DateTime.parse(json["releaseDate"]),
|
_releaseDate = DateTime.parse(json["releaseDate"]),
|
||||||
|
|
|
@ -53,11 +53,11 @@ class MovieManager extends ChangeNotifier {
|
||||||
_loadCache();
|
_loadCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
_loadCache() async {
|
Future<void> _loadCache() async {
|
||||||
addMovies(await cache.retrieve());
|
addMovies(await cache.retrieve());
|
||||||
}
|
}
|
||||||
|
|
||||||
_moviesModified({bool withoutAddingOrRemoving = false}) {
|
void _moviesModified({bool withoutAddingOrRemoving = false}) {
|
||||||
cacheUpdater?.call();
|
cacheUpdater?.call();
|
||||||
if (!withoutAddingOrRemoving) {
|
if (!withoutAddingOrRemoving) {
|
||||||
// only notify listeners if movies are added or removed
|
// only notify listeners if movies are added or removed
|
||||||
|
@ -90,7 +90,7 @@ class MovieManager extends ChangeNotifier {
|
||||||
return actualMovies;
|
return actualMovies;
|
||||||
}
|
}
|
||||||
|
|
||||||
_insertMovie(MovieData movie) {
|
void _insertMovie(MovieData movie) {
|
||||||
int min = 0;
|
int min = 0;
|
||||||
int max = movies.length - 1;
|
int max = movies.length - 1;
|
||||||
while (min - 1 < max) {
|
while (min - 1 < max) {
|
||||||
|
@ -105,7 +105,7 @@ class MovieManager extends ChangeNotifier {
|
||||||
movies.insert(min, movie);
|
movies.insert(min, movie);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeMoviesWhere(bool Function(MovieData movie) test) {
|
void removeMoviesWhere(bool Function(MovieData movie) test) {
|
||||||
bool removedMovies = false;
|
bool removedMovies = false;
|
||||||
for (int i = movies.length - 1; i >= 0; i--) {
|
for (int i = movies.length - 1; i >= 0; i--) {
|
||||||
bool remove = test(movies[i]);
|
bool remove = test(movies[i]);
|
||||||
|
@ -128,11 +128,11 @@ class MovieManager extends ChangeNotifier {
|
||||||
return addMovies(movies);
|
return addMovies(movies);
|
||||||
}
|
}
|
||||||
|
|
||||||
expandDetails(List<MovieData> movies) {
|
void expandDetails(List<MovieData> movies) {
|
||||||
api.addMovieDetails(movies);
|
api.addMovieDetails(movies);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadUpcomingMovies() async {
|
Future<void> loadUpcomingMovies() async {
|
||||||
try {
|
try {
|
||||||
loading = true;
|
loading = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -155,7 +155,7 @@ class LiveSearch<CustomMovieData extends MovieData> extends ChangeNotifier {
|
||||||
|
|
||||||
LiveSearch(this.manager);
|
LiveSearch(this.manager);
|
||||||
|
|
||||||
updateSearch(String search) {
|
void updateSearch(String search) {
|
||||||
searchTerm = search;
|
searchTerm = search;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +1,8 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:release_schedule/model/date_format.dart';
|
||||||
import 'package:release_schedule/model/movie.dart';
|
import 'package:release_schedule/model/movie.dart';
|
||||||
|
|
||||||
String durationApproximatedInWords(Duration duration) {
|
|
||||||
int seconds = duration.inSeconds;
|
|
||||||
int minutes = duration.inMinutes;
|
|
||||||
int hours = duration.inHours;
|
|
||||||
int days = duration.inDays;
|
|
||||||
int weeks = (days / 7).floor();
|
|
||||||
int months = (days / 30).floor();
|
|
||||||
int years = (days / 365).floor();
|
|
||||||
int centuries = (years / 100).floor();
|
|
||||||
if (duration == Duration.zero) {
|
|
||||||
return "now";
|
|
||||||
}
|
|
||||||
if (seconds == 0) {
|
|
||||||
return "now";
|
|
||||||
}
|
|
||||||
if (seconds < 60) {
|
|
||||||
return seconds > 1 ? "$seconds seconds" : "a second";
|
|
||||||
}
|
|
||||||
if (minutes < 60) {
|
|
||||||
return minutes > 1 ? "$minutes minutes" : "a minute";
|
|
||||||
}
|
|
||||||
if (hours < 24) {
|
|
||||||
return hours > 1 ? "$hours hours" : "an hour";
|
|
||||||
}
|
|
||||||
if (days < 7) {
|
|
||||||
return days > 1 ? "$days days" : "a day";
|
|
||||||
}
|
|
||||||
if (months == 0) {
|
|
||||||
return weeks > 1 ? "$weeks weeks" : "a week";
|
|
||||||
}
|
|
||||||
if (years == 0) {
|
|
||||||
return months > 1 ? "$months months" : "a month";
|
|
||||||
}
|
|
||||||
if (years < 100) {
|
|
||||||
return years > 1 ? "$years years" : "a year";
|
|
||||||
}
|
|
||||||
return centuries > 1 ? "$centuries centuries" : "a century";
|
|
||||||
}
|
|
||||||
|
|
||||||
String durationToRelativeTimeString(Duration duration) {
|
|
||||||
if (duration.isNegative) {
|
|
||||||
return "${durationApproximatedInWords(-duration)} ago";
|
|
||||||
} else if (duration == Duration.zero) {
|
|
||||||
return "now";
|
|
||||||
} else {
|
|
||||||
return "in ${durationApproximatedInWords(duration)}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String dateRelativeToNow(DateTime date) {
|
|
||||||
DateTime dateOnly = DateTime.utc(date.year, date.month, date.day);
|
|
||||||
DateTime now = DateTime.now().toUtc();
|
|
||||||
DateTime today = DateTime.utc(now.year, now.month, now.day);
|
|
||||||
Duration diff = dateOnly.difference(today);
|
|
||||||
return durationToRelativeTimeString(diff);
|
|
||||||
}
|
|
||||||
|
|
||||||
class MovieItem extends StatelessWidget {
|
class MovieItem extends StatelessWidget {
|
||||||
final MovieData movie;
|
final MovieData movie;
|
||||||
const MovieItem(this.movie, {super.key});
|
const MovieItem(this.movie, {super.key});
|
||||||
|
|
Loading…
Reference in New Issue