refactor: use short names for genres

main
daniel-michel 2024-01-09 13:24:35 +01:00
parent a0e4edb508
commit 497c2e6d2e
5 changed files with 30 additions and 18 deletions

View File

@ -25,6 +25,7 @@ class WikidataProperties {
static const String reviewScore = "P444"; static const String reviewScore = "P444";
static const String fskFilmRating = "P1981"; static const String fskFilmRating = "P1981";
static const String placeOfPublication = "P291"; static const String placeOfPublication = "P291";
static const String shortName = "P1813";
} }
class WikidataEntities { class WikidataEntities {
@ -236,16 +237,24 @@ Future<Map<String, String>> _getLabelsForEntities(
final start = i * batchSize; final start = i * batchSize;
final end = min((i + 1) * batchSize, entityIds.length); final end = min((i + 1) * batchSize, entityIds.length);
Response response = await _wikidataApi.get( Response response = await _wikidataApi.get(
"&action=wbgetentities&format=json&props=labels&ids=${entityIds.sublist(start, end).join("|")}"); "&action=wbgetentities&format=json&props=labels|claims&ids=${entityIds.sublist(start, end).join("|")}");
Map<String, dynamic> result = jsonDecode(response.body); Map<String, dynamic> result = jsonDecode(response.body);
Map<String, dynamic> batchEntities = result["entities"]; Map<String, dynamic> batchEntities = result["entities"];
for (String entityId in batchEntities.keys) { for (String entityId in batchEntities.keys) {
Map<String, dynamic> labels = batchEntities[entityId]["labels"]; String? shortName = selectInJson(batchEntities[entityId],
String label = labels.containsKey("en") "claims.${WikidataProperties.shortName}.*.mainsnak.datavalue.value")
? labels["en"]["value"] .where((value) => value["language"] == "en")
: labels[labels.keys.first]["value"]; .map((value) => (value["text"] as String))
labels[entityId] = label; .firstOrNull;
_labelCache[entityId] = label; Map<String, dynamic> responseLabels = batchEntities[entityId]["labels"];
if (shortName != null) {
_labelCache[entityId] = labels[entityId] = shortName;
continue;
}
String label = responseLabels.containsKey("en")
? responseLabels["en"]["value"]
: responseLabels[responseLabels.keys.first]["value"];
_labelCache[entityId] = labels[entityId] = label;
} }
} }
return labels; return labels;

View File

@ -3,16 +3,21 @@ import 'dart:async';
class DelayedFunctionCaller { class DelayedFunctionCaller {
final void Function() function; final void Function() function;
final Duration duration; final Duration duration;
final bool resetTimerOnCall;
Timer? _timer; Timer? _timer;
DelayedFunctionCaller(this.function, this.duration); DelayedFunctionCaller(this.function, this.duration,
{this.resetTimerOnCall = false});
get scheduled => _timer != null && _timer!.isActive; get scheduled => _timer != null && _timer!.isActive;
void call() { void call() {
// If a timer is already active, return.
if (_timer != null && _timer!.isActive) { if (_timer != null && _timer!.isActive) {
return; // If a timer is already active and we don't want to reset it, return.
if (!resetTimerOnCall) {
return;
}
_timer!.cancel();
} }
// Create a timer that calls the function after the specified duration. // Create a timer that calls the function after the specified duration.

View File

@ -6,13 +6,16 @@ import 'package:release_schedule/model/movie_manager.dart';
class LiveSearch extends ChangeNotifier { class LiveSearch extends ChangeNotifier {
String searchTerm = ""; String searchTerm = "";
List<MovieData> searchResults = []; List<MovieData> searchResults = [];
Duration minTimeBetweenRequests = const Duration(milliseconds: 200);
late final DelayedFunctionCaller _searchCaller; late final DelayedFunctionCaller _searchCaller;
final MovieManager manager; final MovieManager manager;
bool searchingOnline = false; bool searchingOnline = false;
LiveSearch(this.manager) { LiveSearch(this.manager) {
_searchCaller = DelayedFunctionCaller(searchOnline, minTimeBetweenRequests); _searchCaller = DelayedFunctionCaller(
searchOnline,
const Duration(milliseconds: 750),
resetTimerOnCall: true,
);
} }
get loading => searchingOnline || _searchCaller.scheduled; get loading => searchingOnline || _searchCaller.scheduled;

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:release_schedule/model/date_format.dart';
import 'package:release_schedule/model/movie.dart'; import 'package:release_schedule/model/movie.dart';
import 'package:release_schedule/view/movie_page.dart'; import 'package:release_schedule/view/movie_page.dart';
@ -14,8 +13,7 @@ class MovieItem extends StatelessWidget {
builder: (context, widget) { builder: (context, widget) {
return ListTile( return ListTile(
title: Text(movie.title), title: Text(movie.title),
subtitle: Text( subtitle: Text(movie.genres?.join(", ") ?? ""),
"${dateRelativeToNow(movie.releaseDate.date)}, ${movie.releaseDate.toString()}, ${movie.genres?.join(", ") ?? ""}"),
trailing: IconButton( trailing: IconButton(
icon: Icon(movie.bookmarked icon: Icon(movie.bookmarked
? Icons.bookmark_added ? Icons.bookmark_added

View File

@ -24,9 +24,6 @@ void main() {
expect(find.text('Test Movie'), findsOneWidget); expect(find.text('Test Movie'), findsOneWidget);
final formattedDate = movie.releaseDate.toString();
expect(find.textContaining(formattedDate), findsOneWidget);
expect(find.textContaining('Action, Adventure'), findsOneWidget); expect(find.textContaining('Action, Adventure'), findsOneWidget);
}); });