- screaming_possum.gif
This commit is contained in:
		@@ -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);
 | 
			
		||||
              },
 | 
			
		||||
            );
 | 
			
		||||
          },
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user