From 854528128fac50a147add0ce256310aa5e433007 Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Sat, 21 Dec 2024 17:51:16 +0100 Subject: [PATCH] Use new list/sheets api instead of paged one --- lib/api.dart | 12 ++--- lib/home_page.dart | 6 ++- lib/sheet.dart | 127 +++++++++++++++++++++++++++++---------------- 3 files changed, 90 insertions(+), 55 deletions(-) diff --git a/lib/api.dart b/lib/api.dart index a303056..d6a8d32 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -121,15 +121,9 @@ class ApiClient { return null; } - Future> fetchSheets({String sortBy = "last_opened desc"}) async { + Future> fetchSheets() async { try { - final bodyFormData = { - "page": 1, - "limit": "1000", - "sort_by": sortBy, - }; - - final response = await postFormData("/sheets", jsonEncode(bodyFormData)); + final response = await get("/list/sheets"); if (response == null) { return List.empty(); @@ -138,7 +132,7 @@ class ApiClient { if (response.statusCode == 200) { final data = jsonDecode(response.body); log("Data: $data"); - return (data['rows'] as List) + return (data as List) .map((sheet) => Sheet.fromJson(sheet as Map)) .toList(); } else { diff --git a/lib/home_page.dart b/lib/home_page.dart index 463003b..050d09c 100644 --- a/lib/home_page.dart +++ b/lib/home_page.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:sheetless/sheet_viewer_page.dart'; import 'package:sheetless/storage_helper.dart'; @@ -37,7 +39,9 @@ class _MyHomePageState extends State { final jwt = await _storageHelper.read(StorageKey.jwt); apiClient = ApiClient(baseUrl: url!, token: jwt); // TODO: check if really logged in - return await apiClient!.fetchSheets(); + final sheets = await apiClient!.fetchSheets(); + log("${sheets.length} sheets fetched"); + return sheets; // return api.main(); // final directory = await getApplicationDocumentsDirectory(); diff --git a/lib/sheet.dart b/lib/sheet.dart index 3815bc4..91246bb 100644 --- a/lib/sheet.dart +++ b/lib/sheet.dart @@ -1,37 +1,16 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:path/path.dart' as p; class Sheet { final String uuid; final String name; final String composerUuid; - final DateTime releaseDate; - final String file; - final String fileHash; - final bool wasUploaded; - final int uploaderId; - final DateTime createdAt; - final DateTime updatedAt; - final DateTime lastOpened; - final List tags; - final String informationText; + final String composerName; Sheet({ required this.uuid, required this.name, required this.composerUuid, - required this.releaseDate, - required this.file, - required this.fileHash, - required this.wasUploaded, - required this.uploaderId, - required this.createdAt, - required this.updatedAt, - required this.lastOpened, - required this.tags, - required this.informationText, + required this.composerName, }); // Factory constructor for creating a Sheet from JSON @@ -40,37 +19,95 @@ class Sheet { uuid: json['uuid'], name: json['sheet_name'], composerUuid: json['composer_uuid'], - releaseDate: DateTime.parse(json['release_date']), - file: json['file'], - fileHash: json['file_hash'], - wasUploaded: json['was_uploaded'], - uploaderId: json['uploader_id'], - createdAt: DateTime.parse(json['created_at']), - updatedAt: DateTime.parse(json['updated_at']), - lastOpened: DateTime.parse(json['last_opened']), - tags: List.from(json['tags']), - informationText: json['information_text'], + composerName: json['composer_name'], ); } } -class SheetsWidget extends StatelessWidget { +class SheetsWidget extends StatefulWidget { final List sheets; final ValueSetter callback; const SheetsWidget({super.key, required this.sheets, required this.callback}); @override - Widget build(context) { - return ListView.builder( - itemCount: sheets.length, - itemBuilder: (context, index) { - var sheet = sheets[index]; - return ListTile( - title: Text(sheet.name), - subtitle: Text(sheet.uuid), - onTap: () => callback(sheet), - ); - }); + _SheetsWidgetState createState() => _SheetsWidgetState(); +} + +class _SheetsWidgetState extends State { + late List filteredSheets; + final TextEditingController _searchController = TextEditingController(); + + @override + void initState() { + super.initState(); + filteredSheets = widget.sheets; + _searchController.addListener(_filterSheets); + } + + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + + void _filterSheets() { + setState(() { + String query = _searchController.text.toLowerCase().trim(); + List terms = query.split(RegExp(r'\s+')); // Split by whitespace + + filteredSheets = widget.sheets.where((sheet) { + String name = sheet.name.toLowerCase(); + String composer = sheet.composerName.toLowerCase(); + + // Each term must be found in either the name or composer + return terms + .every((term) => name.contains(term) || composer.contains(term)); + }).toList(); + }); + } + + void _clearSearch() { + _searchController.clear(); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _searchController, + decoration: InputDecoration( + hintText: 'Search...', + prefixIcon: const Icon(Icons.search), + suffixIcon: _searchController.text.isNotEmpty + ? IconButton( + icon: const Icon(Icons.clear), + onPressed: _clearSearch, + ) + : null, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ), + ), + ), + Expanded( + child: ListView.builder( + itemCount: filteredSheets.length, + itemBuilder: (context, index) { + var sheet = filteredSheets[index]; + return ListTile( + title: Text(sheet.name), + subtitle: Text(sheet.composerName), + onTap: () => widget.callback(sheet), + ); + }, + ), + ), + ], + ); } }