Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FixedGrid in home and import screens #30

Merged
merged 1 commit into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ migrate_working_dir/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
.vscode/

# Flutter/Dart/Pub related
**/doc/api/
Expand Down
8 changes: 4 additions & 4 deletions lib/pages/home/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:inference/pages/home/widgets/model_card.dart';
import 'package:inference/importers/manifest_importer.dart';
import 'package:inference/pages/home/widgets/project_card.dart';
import 'package:inference/widgets/fixed_grid.dart';
import 'package:inference/widgets/import_model_button.dart';
import 'package:inference/providers/project_provider.dart';
import 'package:provider/provider.dart';
Expand Down Expand Up @@ -127,11 +128,10 @@ class _HomePageState extends State<HomePage> {
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Consumer<ProjectProvider>(builder: (context, value, child) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 320, crossAxisSpacing: 32, mainAxisSpacing: 32, childAspectRatio: 6/8),
shrinkWrap: true,
return FixedGrid(
tileWidth: 268,
spacing: 36,
itemCount: value.projects.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return ProjectCard(project: value.projects.elementAt(index));
}
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/home/widgets/project_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class ProjectCard extends StatelessWidget {
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: const BorderRadius.all(Radius.circular(12)),
color: theme.activeColor,
color: theme.menuColor,
),
child: Text(project.type.name),
),
Expand Down
34 changes: 14 additions & 20 deletions lib/pages/import/import.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:inference/pages/import/widgets/model_card.dart';
import 'package:inference/widgets/controls/search_bar.dart';
import 'package:inference/widgets/controls/dropdown_multiple_select.dart';
import 'package:inference/importers/manifest_importer.dart';
import 'package:inference/widgets/fixed_grid.dart';

class ImportPage extends StatefulWidget {
const ImportPage({super.key});
Expand Down Expand Up @@ -147,27 +148,20 @@ class _ImportPageState extends State<ImportPage> {
return const Text('No models available');
} else {
var allModels = filterModels(snapshot.data!);
return GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 300,
crossAxisSpacing: 24,
mainAxisSpacing: 24,
childAspectRatio: 3/4,
),
shrinkWrap: true,
return FixedGrid(
tileWidth: 226,
spacing: 24,
centered: true,
itemCount: allModels.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return ModelCard(
model: allModels[index],
checked: selectedModel == allModels[index],
onChecked: (value) {
setState(() {
selectedModel = value ? allModels[index] : null;
});
},
);
},
itemBuilder: (context, index) => ModelCard(
model: allModels[index],
checked: selectedModel == allModels[index],
onChecked: (value) {
setState(() {
selectedModel = value ? allModels[index] : null;
});
},
),
);
}
},
Expand Down
179 changes: 65 additions & 114 deletions lib/pages/import/widgets/model_card.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:inference/importers/manifest_importer.dart';
import 'package:inference/pages/models/widgets/model_property.dart';
import 'package:inference/widgets/elevation.dart';

class ModelCard extends StatelessWidget {
Expand All @@ -17,127 +18,77 @@ class ModelCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = FluentTheme.of(context);
return LayoutBuilder(
builder: (context, constraints) {
final showDescription = constraints.maxHeight > 300;
return GestureDetector(
onTap: () { onChecked(!checked); },
child: Elevation(
backgroundColor: theme.cardColor,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
elevation: checked ? 16 : 4,
child: AnimatedContainer(
curve: theme.animationCurve,
duration: theme.mediumAnimationDuration,
decoration: BoxDecoration(
color: checked ? theme.inactiveBackgroundColor.withOpacity(0.5) : theme.cardColor,
borderRadius: const BorderRadius.all(Radius.circular(4)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: 5 / 2,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: model.thumbnail.image,
fit: BoxFit.cover,
),
),
return GestureDetector(
onTap: () { onChecked(!checked); },
child: Elevation(
backgroundColor: theme.cardColor,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
elevation: checked ? 16 : 4,
child: AnimatedContainer(
curve: theme.animationCurve,
duration: theme.mediumAnimationDuration,
decoration: BoxDecoration(
color: checked ? theme.inactiveBackgroundColor.withOpacity(0.5) : theme.cardColor,
borderRadius: const BorderRadius.all(Radius.circular(4)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: 7/4,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: model.thumbnail.image,
fit: BoxFit.cover,
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
model.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Text(
model.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
if (showDescription)
Text(
model.description,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
height: 1.5,
),
),
],
),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
child: Wrap(
spacing: 4.0,
runSpacing: 4.0,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: theme.micaBackgroundColor,
borderRadius: BorderRadius.circular(4),
),
child: RichText(
text: TextSpan(
text: 'Optimization: ',
style: DefaultTextStyle.of(context).style,
children: [
TextSpan(
text: model.optimizationPrecision,
style: const TextStyle(fontWeight: FontWeight.bold),
),
],
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: theme.micaBackgroundColor,
borderRadius: BorderRadius.circular(4),
),
child: RichText(
text: TextSpan(
text: 'Size: ',
style: DefaultTextStyle.of(context).style,
children: [
TextSpan(
text: model.readableFileSize,
style: const TextStyle(fontWeight: FontWeight.bold),
),
],
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: theme.micaBackgroundColor,
borderRadius: BorderRadius.circular(4),
),
child: Text(model.task, style: const TextStyle(fontWeight: FontWeight.bold),),
),
],
Text(
model.description,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
height: 1.5,
),
),
),
],
],
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
child: Wrap(
spacing: 4.0,
runSpacing: 4.0,
children: [
ModelProperty(name: "Optimization", value: model.optimizationPrecision),
ModelProperty(name: "Size", value: model.readableFileSize),
ModelProperty(name: "Task", value: model.task),
],
),
),
),
],
),
);
},
),
),
);
}
}
4 changes: 2 additions & 2 deletions lib/pages/models/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class _ModelsPageState extends State<ModelsPage> {
GridContainer(
color: theme.navigationPaneTheme.backgroundColor,
padding: const EdgeInsets.all(16),
child: Text("My Models",
style: const TextStyle(
child: const Text("My Models",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/models/widgets/model_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ModelList extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SearchBar(onChange: (f) => filter.name = f),
IconButton(icon: Icon(filter.order ? FluentIcons.ascending : FluentIcons.descending), onPressed: () => filter.order = !filter.order),
IconButton(icon: Icon(filter.order ? FluentIcons.descending : FluentIcons.ascending, size: 18,), onPressed: () => filter.order = !filter.order,),
],
),
),
Expand Down
6 changes: 4 additions & 2 deletions lib/widgets/fixed_grid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ class FixedGrid extends StatelessWidget {
final double spacing;
final double tileWidth;
final int itemCount;
final bool centered;
final NullableIndexedWidgetBuilder itemBuilder;

const FixedGrid({
required this.tileWidth,
required this.itemBuilder,
this.centered = false,
this.spacing = 0,
this.itemCount = 0,
super.key,
Expand All @@ -20,10 +22,10 @@ class FixedGrid extends StatelessWidget {
builder: (context, constraints) {
final int columns = ((constraints.maxWidth + spacing) / (tileWidth + spacing)).floor();
final double totalTilesWidth = columns * tileWidth + (columns - 1) * spacing;
final double sidePadding = (constraints.maxWidth - totalTilesWidth);
final double padding = (constraints.maxWidth - totalTilesWidth);

return Padding(
padding: EdgeInsets.only(right: sidePadding),
padding: centered ? EdgeInsets.symmetric(horizontal: padding / 2) : EdgeInsets.only(right: padding),
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: columns,
Expand Down