Skip to content
Open
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
1 change: 1 addition & 0 deletions packages/flutter_feed_utils/lib/flutter_feed_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export "src/config/feed_styles.dart";
export "src/config/feed_theme.dart";
export "src/config/feed_translations.dart";
export "src/widgets/feed_item_widget.dart";
export "src/widgets/overview_layout.dart";
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ class _PostHeader extends StatelessWidget {
var deleteItemButtonText = localizationDeleteItemButtonText;

return SizedBox(
width: double.infinity,
height: 40.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
Expand Down
81 changes: 81 additions & 0 deletions packages/flutter_feed_utils/lib/src/widgets/overview_layout.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import "package:flutter/cupertino.dart";
import "package:flutter/material.dart";
import "package:flutter/widgets.dart";

enum OverviewLayoutOption {
list,
grid;
}

class OverviewLayout extends StatelessWidget {
const OverviewLayout._({
required OverviewLayoutOption activeLayout,
required this.items,
this.columnCount = 1,
}) : _activeLayout = activeLayout;

factory OverviewLayout.list({required List<Widget> children}) =>
OverviewLayout._(
activeLayout: OverviewLayoutOption.list,
items: children,
);

factory OverviewLayout.grid({
required int columnCount,
required List<Widget> children,
}) =>
OverviewLayout._(
activeLayout: OverviewLayoutOption.grid,
columnCount: columnCount,
items: children,
);

final List<Widget> items;
final OverviewLayoutOption _activeLayout;
final int columnCount;

@override
Widget build(BuildContext context) => switch (_activeLayout) {
OverviewLayoutOption.list => SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: items,
),
),
),
OverviewLayoutOption.grid => SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Column(
children: [
// We use a manual column + wrap approach rather than a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really prefer if we used a gridview here and simply change the column count based on the size of the screen. The only difficult part is the ability to modify the ratio of the items.

// gridview as this way we can wrap when the screen becomes
// too small
for (var i = 0; i < items.length; i += columnCount) ...[
SizedBox(
width: double.infinity,
child: Wrap(
spacing: 8.0,
runSpacing: 8.0,
children: [
for (var x = 0; x < columnCount; x++) ...[
if (i + x < items.length) ...[
items[i + x],
],
],
],
),
),
if (i + columnCount < items.length) ...[
const SizedBox(height: 8.0),
],
],
],
),
),
),
};
}
83 changes: 38 additions & 45 deletions packages/flutter_timeline/lib/src/flutter_timeline_userstory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,55 +69,48 @@ class _FlutterFeedTimelineUserstoryState

return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
for (var item in items) ...[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: FeedViewItem(
title: item.title,
authorName: item.authorName,
authorAvatarUrl: item.authorAvatarUrl,
imageUrl: item.media.isNotEmpty ? item.media.first : null,
localizationDeleteItemButtonText:
localizations.timelinePostDeleteButtonText,
localizationLikeCount:
localizations.timelinePostLikeCount(item.likeCount),
localizationViewItemButtonText:
localizations.timelinePostViewButtonText,
actionBuilder: () => Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
onPressed: () async => likeItem(item),
icon: Icon(
item.likedByUser
? Icons.favorite_rounded
: Icons.favorite_outline_rounded,
),
),
],
body: OverviewLayout.list(
children: [
for (var item in items) ...[
FeedViewItem(
title: item.title,
authorName: item.authorName,
authorAvatarUrl: item.authorAvatarUrl,
imageUrl: item.media.isNotEmpty ? item.media.first : null,
localizationDeleteItemButtonText:
localizations.timelinePostDeleteButtonText,
localizationLikeCount:
localizations.timelinePostLikeCount(item.likeCount),
localizationViewItemButtonText:
localizations.timelinePostViewButtonText,
actionBuilder: () => Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
onPressed: () async => likeItem(item),
icon: Icon(
item.likedByUser
? Icons.favorite_rounded
: Icons.favorite_outline_rounded,
),
),
onTap: () async => onItemPressed(item),
),
],
),
],
if (items.isEmpty) ...[
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(localizations.timelineEmptyLabel),
),
onTap: () async => onItemPressed(item),
),
],
if (items.isEmpty) ...[
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(localizations.timelineEmptyLabel),
),
],
),
],
),
],
),
);
}
Expand Down