From fff874cc94eb5be79e70cd046d85a5abf16a6bce Mon Sep 17 00:00:00 2001 From: Ronald Hecker Date: Thu, 13 Feb 2025 14:21:41 +0100 Subject: [PATCH 1/3] Implement filter for huggingface too --- lib/pages/import/huggingface.dart | 235 +++++++++++---------- lib/pages/import/import.dart | 9 +- lib/pages/models/models.dart | 26 ++- lib/pages/models/widgets/model_filter.dart | 7 +- lib/providers/project_filter_provider.dart | 44 ++-- pubspec.lock | 86 ++++---- 6 files changed, 219 insertions(+), 188 deletions(-) diff --git a/lib/pages/import/huggingface.dart b/lib/pages/import/huggingface.dart index 22545ab9..5cdc400b 100644 --- a/lib/pages/import/huggingface.dart +++ b/lib/pages/import/huggingface.dart @@ -7,10 +7,14 @@ import 'package:inference/importers/manifest_importer.dart'; import 'package:inference/pages/import/providers/import_provider.dart'; import 'package:inference/pages/import/widgets/badge.dart'; import 'package:inference/pages/import/widgets/model_card.dart'; +import 'package:inference/pages/models/widgets/model_filter.dart'; +import 'package:inference/providers/project_filter_provider.dart'; +import 'package:inference/theme_fluent.dart'; import 'package:inference/widgets/controls/dropdown_multiple_select.dart'; import 'package:inference/widgets/controls/search_bar.dart'; import 'package:inference/widgets/empty_model_widget.dart'; import 'package:inference/widgets/fixed_grid.dart'; +import 'package:inference/widgets/grid_container.dart'; import 'package:provider/provider.dart'; class Huggingface extends StatefulWidget { @@ -25,124 +29,143 @@ class _HuggingfaceState extends State { String? searchValue; bool orderAsc = true; - List filterModels(List models) { - var filteredModels = models; - if (searchValue != null && searchValue!.isNotEmpty) { - filteredModels = filteredModels.where((model) => model.name.toLowerCase().contains(searchValue!.toLowerCase())).toList(); - } - if (selectedOptimizations.isNotEmpty) { - filteredModels = filteredModels.where((model) => selectedOptimizations.contains(model.optimizationPrecision)).toList(); - } + static Map> get filterOptions { + var options = { + "Text Generation": [ + const Option("Text generation", "text-generation"), + ], + "Image Generation": [ + const Option("Text to Image", "text-to-image") + ], + "Audio": [ + const Option("Speech to text", "speech") + ] + }; - filteredModels.sort((a,b) => a.name.compareTo(b.name) * (orderAsc ? -1 : 1)); - return filteredModels; + return options; } @override Widget build(BuildContext context) { + final theme = FluentTheme.of(context); + return Consumer(builder: (context, importProvider, child) { - return ConstrainedBox(constraints: const BoxConstraints(maxWidth: 1228), - child: Padding( - padding: const EdgeInsets.only(left: 133, right: 80, top: 36, bottom: 50), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 280), - child: Semantics( - label: 'Find a model', - child: SearchBar(onChange: (value) { setState(() { - searchValue = value; - }); }, placeholder: 'Find a model',), + return Consumer( + builder: (context, filter, child) { + return ConstrainedBox(constraints: const BoxConstraints(maxWidth: 1228), + child: Row( + children: [ + GridContainer( + color: backgroundColor.of(theme), + padding: const EdgeInsets.all(13), + child: ModelFilter(filterOptions: filterOptions) + ), + Expanded( + child: GridContainer( + color: backgroundColor.of(theme), + padding: const EdgeInsets.only(left: 33, right: 80, top: 36, bottom: 50), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 280), + child: Semantics( + label: 'Find a model', + child: SearchBar( + placeholder: 'Find a model', + onChange: (value) { + filter.name = value; + }, + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 8), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 184), + child: DropdownMultipleSelect( + items: const ['int4', 'int8', 'fp16'], + selectedItems: selectedOptimizations, + onChanged: (value) { + filter.optimizations = value; + }, + placeholder: 'Select optimizations', + ), + ), + ) + ], + ), + IconButton(icon: Icon(orderAsc ? FluentIcons.descending : FluentIcons.ascending, size: 18,), onPressed: () => setState(() => orderAsc = !orderAsc),), + ], ), - ), - Padding( - padding: const EdgeInsets.only(left: 8), - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 184), - child: DropdownMultipleSelect( - items: const ['int4', 'int8', 'fp16'], - selectedItems: selectedOptimizations, - onChanged: (value) { - if (!value.contains(importProvider.selectedModel?.optimizationPrecision)) { - importProvider.selectedModel = null; - } - setState(() { - selectedOptimizations = value; - }); - }, - placeholder: 'Select optimizations', + Padding( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 2), + child: SizedBox( + height: 28, + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: Wrap( + spacing: 8, + children: selectedOptimizations.map((opt) { + return Badge(text: opt, onDelete: () { + if (opt == importProvider.selectedModel?.optimizationPrecision && selectedOptimizations.length > 1) { + importProvider.selectedModel = null; + } + setState(() { + selectedOptimizations.remove(opt); + }); + }); + }).toList(), + ), + ), ), ), - ) - ], - ), - IconButton(icon: Icon(orderAsc ? FluentIcons.descending : FluentIcons.ascending, size: 18,), onPressed: () => setState(() => orderAsc = !orderAsc),), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 2), - child: SizedBox( - height: 28, - width: double.infinity, - child: Align( - alignment: Alignment.centerLeft, - child: Wrap( - spacing: 8, - children: selectedOptimizations.map((opt) { - return Badge(text: opt, onDelete: () { - if (opt == importProvider.selectedModel?.optimizationPrecision && selectedOptimizations.length > 1) { - importProvider.selectedModel = null; - } - setState(() { - selectedOptimizations.remove(opt); - }); - }); - }).toList(), - ), - ), - ), - ), - Expanded( - child: SingleChildScrollView( - child: FutureBuilder>( - future: importProvider.allModelsFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const ProgressRing(); - } else if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return const Text('No models available'); - } else { - var allModels = filterModels(snapshot.data!); - return FixedGrid( - tileWidth: 226, - spacing: 24, - itemCount: allModels.length, - emptyWidget: EmptyModelListWidget(searchQuery: searchValue), - itemBuilder: (context, index) => ModelCard( - model: allModels[index], - checked: importProvider.selectedModel == allModels[index], - onChecked: (value) { - setState(() { - importProvider.selectedModel = value ? allModels[index] : null; - }); - }, + Expanded( + child: SingleChildScrollView( + child: FutureBuilder>( + future: importProvider.allModelsFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const ProgressRing(); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return const Text('No models available'); + } else { + var allModels = filter.applyFilterOnModel(snapshot.data!); + return FixedGrid( + tileWidth: 226, + spacing: 24, + itemCount: allModels.length, + emptyWidget: EmptyModelListWidget(searchQuery: searchValue), + itemBuilder: (context, index) => ModelCard( + model: allModels[index], + checked: importProvider.selectedModel == allModels[index], + onChecked: (value) { + setState(() { + importProvider.selectedModel = value ? allModels[index] : null; + }); + }, + ), + ); + } + }, + ), ), - ); - } - }, + ), + ], + ), ), ), - ), - ], - ), - ), + ], + ), + ); + } ); }); } diff --git a/lib/pages/import/import.dart b/lib/pages/import/import.dart index 57fc40d3..53feb7c8 100644 --- a/lib/pages/import/import.dart +++ b/lib/pages/import/import.dart @@ -8,6 +8,8 @@ import 'package:go_router/go_router.dart'; import 'package:inference/pages/import/huggingface.dart'; import 'package:inference/pages/import/providers/import_provider.dart'; import 'package:inference/pages/import/widgets/import_geti_model_dialog.dart'; +import 'package:inference/providers/project_filter_provider.dart'; +import 'package:inference/theme_fluent.dart'; import 'package:inference/widgets/controls/close_model_button.dart'; import 'package:provider/provider.dart'; @@ -26,7 +28,7 @@ class _ImportPageState extends State { final theme = FluentTheme.of(context); final updatedTheme = theme.copyWith( navigationPaneTheme: theme.navigationPaneTheme.merge(NavigationPaneThemeData( - backgroundColor: theme.scaffoldBackgroundColor, + backgroundColor: backgroundColor.of(theme), )) ); @@ -56,7 +58,10 @@ class _ImportPageState extends State { PaneItem( icon: SvgPicture.asset('images/huggingface_logo-noborder.svg', width: 15,), title: const Text("Huggingface"), - body: const Huggingface(), + body: ChangeNotifierProvider( + create: (_) => ProjectFilterProvider(), + child: const Huggingface() + ), ), PaneItemAction( icon: const Icon(FluentIcons.project_collection), diff --git a/lib/pages/models/models.dart b/lib/pages/models/models.dart index 5742a0d2..d24ab26a 100644 --- a/lib/pages/models/models.dart +++ b/lib/pages/models/models.dart @@ -19,6 +19,28 @@ class ModelsPage extends StatefulWidget { } class _ModelsPageState extends State { + static Map> get filterOptions { + var options = { + "Image": [ + const Option("Detection", "detection"), + const Option("Classification", "classification"), + const Option("Segmentation", "segmentation"), + const Option("Anomaly detection","anomaly") + ], + "Text Generation": [ + const Option("Text generation", "text"), + ], + "Image Generation": [ + const Option("Text to Image", "text-to-image") + ], + "Audio": [ + const Option("Speech to text", "speech") + ] + }; + + return options; + } + @override Widget build(BuildContext context) { final theme = FluentTheme.of(context); @@ -50,9 +72,9 @@ class _ModelsPageState extends State { ), Expanded( child: GridContainer( - color: backgroundColor.of(theme), + color: backgroundColor.of(theme), padding: const EdgeInsets.all(13), - child: const ModelFilter() + child: ModelFilter(filterOptions: filterOptions) ), ), ], diff --git a/lib/pages/models/widgets/model_filter.dart b/lib/pages/models/widgets/model_filter.dart index 7e32e6f1..c279168f 100644 --- a/lib/pages/models/widgets/model_filter.dart +++ b/lib/pages/models/widgets/model_filter.dart @@ -9,7 +9,8 @@ import 'package:provider/provider.dart'; class ModelFilter extends StatelessWidget { - const ModelFilter({super.key}); + final Map> filterOptions; + const ModelFilter({super.key, required this.filterOptions}); @override Widget build(BuildContext context) { @@ -19,8 +20,8 @@ class ModelFilter extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - ...Option.filterOptions.keys.map((key) { - return Group(key, Option.filterOptions[key]!); + ...filterOptions.keys.map((key) { + return Group(key, filterOptions[key]!); }), ] ), diff --git a/lib/providers/project_filter_provider.dart b/lib/providers/project_filter_provider.dart index 80925630..a348e253 100644 --- a/lib/providers/project_filter_provider.dart +++ b/lib/providers/project_filter_provider.dart @@ -4,6 +4,7 @@ import 'dart:core'; import 'package:fluent_ui/fluent_ui.dart'; +import 'package:inference/importers/manifest_importer.dart'; import 'package:inference/project.dart'; import 'package:inference/public_model_info.dart'; @@ -12,28 +13,6 @@ class Option { final String filter; const Option(this.name, this.filter); - - static Map> get filterOptions { - var options = { - "Image": [ - const Option("Detection", "detection"), - const Option("Classification", "classification"), - const Option("Segmentation", "segmentation"), - const Option("Anomaly detection","anomaly") - ], - "Text Generation": [ - const Option("Text generation", "text"), - ], - "Image Generation": [ - const Option("Text to Image", "text-to-image") - ], - "Audio": [ - const Option("Speech to text", "speech") - ] - }; - - return options; - } } @@ -53,15 +32,20 @@ class ProjectFilterProvider extends ChangeNotifier { notifyListeners(); } - final List optimizations = []; + List _optimizations = []; + List get optimizations => _optimizations; + set optimizations(List optimizations) { + _optimizations = optimizations; + notifyListeners(); + } void addOptimization(String opt) { - optimizations.add(opt); + _optimizations.add(opt); notifyListeners(); } void removeOptimization(String opt) { - optimizations.remove(opt); + _optimizations.remove(opt); notifyListeners(); } @@ -90,22 +74,18 @@ class ProjectFilterProvider extends ChangeNotifier { return filteredList; } - List applyFilterOnPublicModelInfo(List projects) { + List applyFilterOnModel(List projects) { var filtered = projects .where((project) => project.id.toLowerCase().contains((name ?? "").toLowerCase()) ); if (optimizations.isNotEmpty) { - filtered = filtered.where((model) { - return optimizations.where((opt) { - return model.name.contains(opt); - }).isNotEmpty; - }); + filtered = filtered.where((model) => optimizations.contains(model.optimizationPrecision)).toList(); } if (option != null) { - filtered = filtered.where((model) => model.taskType == option!.filter); + filtered = filtered.where((model) => model.task == option!.filter); } diff --git a/pubspec.lock b/pubspec.lock index ae0ea22c..6e72f1f1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,18 +42,18 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" build: dependency: transitive description: @@ -122,10 +122,10 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" checked_yaml: dependency: transitive description: @@ -146,10 +146,10 @@ packages: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" code_builder: dependency: transitive description: @@ -162,10 +162,10 @@ packages: dependency: "direct main" description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" console: dependency: transitive description: @@ -282,10 +282,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" ffi: dependency: "direct main" description: @@ -306,10 +306,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" file_picker: dependency: "direct main" description: @@ -541,18 +541,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -605,10 +605,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -629,10 +629,10 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.16.0" mime: dependency: "direct main" description: @@ -693,10 +693,10 @@ packages: dependency: "direct main" description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_parsing: dependency: transitive description: @@ -773,10 +773,10 @@ packages: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" plugin_platform_interface: dependency: "direct dev" description: @@ -797,10 +797,10 @@ packages: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.3" provider: dependency: "direct main" description: @@ -970,10 +970,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" sprintf: dependency: transitive description: @@ -986,18 +986,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" stream_transform: dependency: transitive description: @@ -1010,10 +1010,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" super_clipboard: dependency: "direct main" description: @@ -1066,18 +1066,18 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.4" timing: dependency: transitive description: @@ -1266,10 +1266,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "14.3.1" volume_controller: dependency: transitive description: @@ -1391,5 +1391,5 @@ packages: source: hosted version: "2.2.1" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.7.0-0 <4.0.0" flutter: ">=3.24.5" From 307771bf022c12d880951879efe7c18591cbb835 Mon Sep 17 00:00:00 2001 From: Ronald Hecker Date: Thu, 13 Feb 2025 14:38:13 +0100 Subject: [PATCH 2/3] Clean up model filter in huggingface and models page --- lib/pages/import/huggingface.dart | 43 ++++++++----------- lib/pages/models/models.dart | 7 +-- lib/providers/project_filter_provider.dart | 5 ++- .../models/widgets/model_filter_test.dart | 5 ++- 4 files changed, 25 insertions(+), 35 deletions(-) diff --git a/lib/pages/import/huggingface.dart b/lib/pages/import/huggingface.dart index 5cdc400b..527ac979 100644 --- a/lib/pages/import/huggingface.dart +++ b/lib/pages/import/huggingface.dart @@ -17,18 +17,9 @@ import 'package:inference/widgets/fixed_grid.dart'; import 'package:inference/widgets/grid_container.dart'; import 'package:provider/provider.dart'; -class Huggingface extends StatefulWidget { +class Huggingface extends StatelessWidget { const Huggingface({super.key}); - @override - State createState() => _HuggingfaceState(); -} - -class _HuggingfaceState extends State { - List selectedOptimizations = []; - String? searchValue; - bool orderAsc = true; - static Map> get filterOptions { var options = { "Text Generation": [ @@ -89,7 +80,7 @@ class _HuggingfaceState extends State { constraints: const BoxConstraints(maxWidth: 184), child: DropdownMultipleSelect( items: const ['int4', 'int8', 'fp16'], - selectedItems: selectedOptimizations, + selectedItems: filter.optimizations, onChanged: (value) { filter.optimizations = value; }, @@ -99,7 +90,7 @@ class _HuggingfaceState extends State { ) ], ), - IconButton(icon: Icon(orderAsc ? FluentIcons.descending : FluentIcons.ascending, size: 18,), onPressed: () => setState(() => orderAsc = !orderAsc),), + IconButton(icon: Icon(filter.order ? FluentIcons.descending : FluentIcons.ascending, size: 18,), onPressed: () => filter.order = !filter.order), ], ), Padding( @@ -111,16 +102,20 @@ class _HuggingfaceState extends State { alignment: Alignment.centerLeft, child: Wrap( spacing: 8, - children: selectedOptimizations.map((opt) { - return Badge(text: opt, onDelete: () { - if (opt == importProvider.selectedModel?.optimizationPrecision && selectedOptimizations.length > 1) { - importProvider.selectedModel = null; - } - setState(() { - selectedOptimizations.remove(opt); + children: [ + ...filter.optimizations.map((opt) { + return Badge(text: opt, onDelete: () { + if (opt == importProvider.selectedModel?.optimizationPrecision && filter.optimizations.length > 1) { + importProvider.selectedModel = null; + } + filter.removeOptimization(opt); }); - }); - }).toList(), + }), + if (filter.option != null) + Badge(text: filter.option!.name, onDelete: () { + filter.option = null; + }) + ] ), ), ), @@ -142,14 +137,12 @@ class _HuggingfaceState extends State { tileWidth: 226, spacing: 24, itemCount: allModels.length, - emptyWidget: EmptyModelListWidget(searchQuery: searchValue), + emptyWidget: EmptyModelListWidget(searchQuery: filter.name), itemBuilder: (context, index) => ModelCard( model: allModels[index], checked: importProvider.selectedModel == allModels[index], onChecked: (value) { - setState(() { - importProvider.selectedModel = value ? allModels[index] : null; - }); + importProvider.selectedModel = value ? allModels[index] : null; }, ), ); diff --git a/lib/pages/models/models.dart b/lib/pages/models/models.dart index d24ab26a..fb7a5904 100644 --- a/lib/pages/models/models.dart +++ b/lib/pages/models/models.dart @@ -11,14 +11,9 @@ import 'package:inference/theme_fluent.dart'; import 'package:inference/widgets/import_model_button.dart'; import 'package:provider/provider.dart'; -class ModelsPage extends StatefulWidget { +class ModelsPage extends StatelessWidget { const ModelsPage({super.key}); - @override - State createState() => _ModelsPageState(); -} - -class _ModelsPageState extends State { static Map> get filterOptions { var options = { "Image": [ diff --git a/lib/providers/project_filter_provider.dart b/lib/providers/project_filter_provider.dart index a348e253..27b93d99 100644 --- a/lib/providers/project_filter_provider.dart +++ b/lib/providers/project_filter_provider.dart @@ -6,7 +6,6 @@ import 'dart:core'; import 'package:fluent_ui/fluent_ui.dart'; import 'package:inference/importers/manifest_importer.dart'; import 'package:inference/project.dart'; -import 'package:inference/public_model_info.dart'; class Option { final String name; @@ -88,7 +87,9 @@ class ProjectFilterProvider extends ChangeNotifier { filtered = filtered.where((model) => model.task == option!.filter); } + final filteredList = filtered.toList(); + filteredList.sort((a,b) => a.name.compareTo(b.name) * (order ? -1 : 1)); - return filtered.toList(); + return filteredList; } } diff --git a/test/pages/models/widgets/model_filter_test.dart b/test/pages/models/widgets/model_filter_test.dart index 77acb64d..1e1d36d1 100644 --- a/test/pages/models/widgets/model_filter_test.dart +++ b/test/pages/models/widgets/model_filter_test.dart @@ -5,6 +5,7 @@ import 'package:fluent_ui/fluent_ui.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:inference/pages/models/models.dart'; import 'package:inference/pages/models/widgets/model_filter.dart'; import 'package:inference/providers/project_filter_provider.dart'; import 'package:provider/provider.dart'; @@ -12,8 +13,8 @@ import 'package:provider/provider.dart'; Widget modelWidget(ProjectFilterProvider provider) { return ChangeNotifierProvider.value( value: provider, - child: const FluentApp( - home: ModelFilter() + child: FluentApp( + home: ModelFilter(filterOptions: ModelsPage.filterOptions) ) ); } From ad355308c3df4113f0e3906e423199c9ea2049c0 Mon Sep 17 00:00:00 2001 From: "Hecker, Ronald" Date: Fri, 14 Feb 2025 07:47:21 +0100 Subject: [PATCH 3/3] Fix issues with macos due to package upgrades --- macos/Flutter/GeneratedPluginRegistrant.swift | 4 ++ macos/Podfile.lock | 50 ++++++++++++------- .../xcshareddata/xcschemes/Runner.xcscheme | 1 + pubspec.lock | 18 +++---- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index fd35ea17..65f5fe1e 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,6 +7,7 @@ import Foundation import desktop_drop import device_info_plus +import file_picker import irondash_engine_context import macos_window_utils import objectbox_flutter_libs @@ -19,12 +20,14 @@ import system_theme import universal_video_controls import url_launcher_macos import video_player_avfoundation +import volume_controller import wakelock_plus import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin")) MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin")) ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin")) @@ -37,6 +40,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { UniversalVideoControlsPlugin.register(with: registry.registrar(forPlugin: "UniversalVideoControlsPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) + VolumeControllerPlugin.register(with: registry.registrar(forPlugin: "VolumeControllerPlugin")) WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index e05d79b0..b8dc6f23 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -3,15 +3,17 @@ PODS: - FlutterMacOS - device_info_plus (0.0.1): - FlutterMacOS + - file_picker (0.0.1): + - FlutterMacOS - FlutterMacOS (1.0.0) - irondash_engine_context (0.0.1): - FlutterMacOS - macos_window_utils (1.0.0): - FlutterMacOS - - ObjectBox (4.0.1) + - ObjectBox (4.1.0) - objectbox_flutter_libs (0.0.1): - FlutterMacOS - - ObjectBox (= 4.0.1) + - ObjectBox (= 4.1.0) - package_info_plus (0.0.1): - FlutterMacOS - path_provider_foundation (0.0.1): @@ -32,6 +34,8 @@ PODS: - video_player_avfoundation (0.0.1): - Flutter - FlutterMacOS + - volume_controller (0.0.1): + - FlutterMacOS - wakelock_plus (0.0.1): - FlutterMacOS - window_manager (0.2.0): @@ -40,6 +44,7 @@ PODS: DEPENDENCIES: - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) + - file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`) - macos_window_utils (from `Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos`) @@ -53,6 +58,7 @@ DEPENDENCIES: - universal_video_controls (from `Flutter/ephemeral/.symlinks/plugins/universal_video_controls/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`) + - volume_controller (from `Flutter/ephemeral/.symlinks/plugins/volume_controller/macos`) - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) @@ -65,6 +71,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos device_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos + file_picker: + :path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos FlutterMacOS: :path: Flutter/ephemeral irondash_engine_context: @@ -91,30 +99,34 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos video_player_avfoundation: :path: Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin + volume_controller: + :path: Flutter/ephemeral/.symlinks/plugins/volume_controller/macos wakelock_plus: :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos window_manager: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - desktop_drop: e0b672a7d84c0a6cbc378595e82cdb15f2970a43 - device_info_plus: a56e6e74dbbd2bb92f2da12c64ddd4f67a749041 + desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898 + device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720 + file_picker: e716a70a9fe5fd9e09ebc922d7541464289443af FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba - macos_window_utils: 3bca8603c2a1cf2257351dfe6bbccc9accf739fd - ObjectBox: 0bc4bb75eea85f6af06b369148b334c2056bbc29 - objectbox_flutter_libs: 769e6f44f7381c8a8e46a2ed5c71c6068bb476f7 - package_info_plus: f0052d280d17aa382b932f399edf32507174e870 - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 - screen_brightness_macos: 2a3ee243f8051c340381e8e51bcedced8360f421 - screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f - super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189 - system_theme: ed74293ad07d3a05e3e2d0059ff342360346f1a0 - universal_video_controls: a89c586ac49c73d6965eabe1908c2e47d0b6a9b9 - url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 - video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b - wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497 - window_manager: 1d01fa7ac65a6e6f83b965471b1a7fdd3f06166c + irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478 + macos_window_utils: 933f91f64805e2eb91a5bd057cf97cd097276663 + ObjectBox: bf3d4b51075d52868422d5d1f2f2141b1d630d30 + objectbox_flutter_libs: 90e8897eeef16e16bccaf0f91a6c92d53589dd64 + package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda + screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161 + super_native_extensions: 85efee3a7495b46b04befcfc86ed12069264ebf3 + system_theme: c7b9f6659a5caa26c9bc2284da096781e9a6fcbc + universal_video_controls: 6e055af943bd4e3cba227253ac516f790e8923f2 + url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 + video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3 + volume_controller: 90a5978956cf18ebb7739bf5382fc1b0cfef66d0 + wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 + window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 PODFILE CHECKSUM: b5ff078e9cf81bae88fdc8e0ce3668e57b68e9b6 diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index b58ae974..f8490322 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -59,6 +59,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/pubspec.lock b/pubspec.lock index 15774f15..956e9012 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -573,10 +573,10 @@ packages: dependency: transitive description: name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.1" json_annotation: dependency: transitive description: @@ -685,10 +685,10 @@ packages: dependency: transitive description: name: math_expressions - sha256: "218dc65bed4726562bb31c53d8daa3cc824664b26fb72d77bc592757edf74ba0" + sha256: e32d803d758ace61cc6c4bdfed1226ff60a6a23646b35685670d28b5616139f8 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.6.0" meta: dependency: transitive description: @@ -845,10 +845,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.0.2" pixel_snap: dependency: transitive description: @@ -1154,10 +1154,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6" + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.3.0+3" system_theme: dependency: "direct main" description: @@ -1511,5 +1511,5 @@ packages: source: hosted version: "2.2.2" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.7.0-0 <4.0.0" flutter: ">=3.27.0"