v1.2.0+54
All checks were successful
Flutter Schmutter / build (push) Successful in 3m37s

- screaming_possum.gif
This commit is contained in:
2025-06-13 13:55:05 +02:00
parent dff9cda829
commit 9655f15927
18 changed files with 628 additions and 878 deletions

View File

@ -1,11 +1,16 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:f0ckapp/services/api_service.dart';
import 'package:f0ckapp/models/suggestion_model.dart';
import 'package:f0ckapp/providers/media_provider.dart';
class CustomSearchDelegate extends SearchDelegate<String> {
final ApiService apiService = Get.find<ApiService>();
Timer? _debounceTimer;
List<Suggestion>? _suggestions;
bool _isLoading = false;
@ -42,13 +47,52 @@ class CustomSearchDelegate extends SearchDelegate<String> {
return Center(child: Text('Suchergebnisse für: "$query"'));
}
Future<List<Suggestion>> fetchSuggestions(String query) async {
final Uri uri = Uri.parse('https://api.f0ck.me/search/?q=$query');
try {
final http.Response response = await http
.get(uri)
.timeout(const Duration(seconds: 5));
if (response.statusCode == 200) {
final dynamic decoded = jsonDecode(response.body);
if (decoded is List) {
final suggestions = decoded
.map((item) => Suggestion.fromJson(item as Map<String, dynamic>))
.toList();
suggestions.sort((a, b) => b.score.compareTo(a.score));
return suggestions;
} else {
throw Exception('Unerwartetes Format: Es wurde eine Liste erwartet.');
}
} else if (response.statusCode == 400) {
final dynamic error = jsonDecode(response.body);
final String message = error is Map<String, dynamic>
? error['detail']?.toString() ?? 'Unbekannter Fehler.'
: 'Unbekannter Fehler.';
throw Exception('Client-Fehler 400: $message');
} else {
throw Exception(
'Fehler beim Abrufen der Vorschläge: ${response.statusCode}',
);
}
} on TimeoutException {
throw Exception('Anfrage an die API hat zu lange gedauert.');
} catch (e) {
throw Exception('Fehler bei der Verarbeitung der Anfrage: $e');
}
}
@override
Widget buildSuggestions(BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, void Function(void Function()) setState) {
if (query.isEmpty) {
_debounceTimer?.cancel();
return Container(padding: const EdgeInsets.all(16.0), child: const Text(''));
return Container(
padding: const EdgeInsets.all(16.0),
child: const Text(''),
);
}
if (query != _lastFetchedQuery) {
@ -90,23 +134,19 @@ class CustomSearchDelegate extends SearchDelegate<String> {
return Center(child: const Text("Keine Ergebnisse gefunden."));
}
return Consumer(
builder: (BuildContext context, WidgetRef ref, Widget? child) {
return ListView.builder(
itemCount: _suggestions!.length,
itemBuilder: (BuildContext context, int index) {
final Suggestion suggestion = _suggestions![index];
return ListTile(
title: Text(suggestion.tag),
subtitle: Text(
'Getaggt: ${suggestion.tagged}x • Score: ${suggestion.score.toStringAsFixed(2)}',
style: TextStyle(fontSize: 12),
),
onTap: () {
ref.read(mediaProvider.notifier).setTag(suggestion.tag);
close(context, suggestion.tag);
},
);
return ListView.builder(
itemCount: _suggestions!.length,
itemBuilder: (BuildContext context, int index) {
final Suggestion suggestion = _suggestions![index];
return ListTile(
title: Text(suggestion.tag),
subtitle: Text(
'Getaggt: ${suggestion.tagged}x • Score: ${suggestion.score.toStringAsFixed(2)}',
style: TextStyle(fontSize: 12),
),
onTap: () async {
await apiService.setTag(suggestion.tag);
close(context, suggestion.tag);
},
);
},

View File

@ -1,42 +0,0 @@
import 'package:flutter/material.dart';
class PageTransformer extends StatelessWidget {
final List<Widget> pages;
final PageController controller;
const PageTransformer({
super.key,
required this.pages,
required this.controller,
});
@override
Widget build(BuildContext context) {
return PageView.builder(
controller: controller,
itemCount: pages.length,
itemBuilder: (context, index) {
return _buildPage(pages[index], index);
},
);
}
Widget _buildPage(Widget page, int index) {
return AnimatedBuilder(
animation: controller,
builder: (context, child) {
double value = 1.0;
if (controller.position.haveDimensions) {
value = controller.page! - index;
value = (1 - (value.abs() * 0.5)).clamp(0.0, 1.0);
}
return Transform(
transform: Matrix4.identity()..scale(value, value),
alignment: Alignment.center,
child: child,
);
},
child: page,
);
}
}