Skip to content
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ a Pull Request. Thanks.

## 0.1 Initial release

+ Fixed excess lines of code in ListNews widget [0.0.13 30360331 jesscmoore]
+ Centre embeded images [0.0.12 20260331 jesscmoore]
+ Finished migration from notes to news [0.0.11 20260331 jesscmoore]
+ Shows first image thumbnail in news list [0.0.10 20260328 jesscmoore]
Expand Down
113 changes: 9 additions & 104 deletions lib/news/list_news.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ import 'package:communitypod/constants/ui.dart';
import 'package:communitypod/models/news.dart';
import 'package:communitypod/models/selected_news.dart';
import 'package:communitypod/news/list_news_screen.dart';
import 'package:communitypod/news/non_readable_news_post.dart';
import 'package:communitypod/news/view_news.dart';
import 'package:communitypod/widgets/highlight_image.dart';
import 'package:communitypod/widgets/item_subtitle.dart';
import 'package:communitypod/widgets/item_trailing_buttons.dart';
import 'package:communitypod/widgets/item_card.dart';
import 'package:communitypod/widgets/list_del_button.dart';

/// A [stateful] widget to list news accessible to the
Expand Down Expand Up @@ -558,105 +554,14 @@ class _ListNewsState extends State<ListNews> {
controller: _scrollController,
padding: const EdgeInsets.all(10),
itemCount: _foundNews.length,
itemBuilder: (context, index) => Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
HighlightImage(
imageUrl: _foundNews[index]
.permissionList
.contains('read')
? _foundNews[index].content?.highlightImageUrl
: null,
),
Center(
child: Container(
// Show color decoration when selected
decoration: _foundNews[index].isSelected
? BoxDecoration(
color: theme.colorScheme.onInverseSurface,
borderRadius: const BorderRadius.all(
Radius.circular(5),
),
)
: const BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(5)),
),
child: ListTile(
// Select and count selected news files, including whether
// an externally owned news files are selected
leading: SizedBox(
width: NewsIconSize.width,
child: Center(
child: Ink(
decoration: buttonShapeList,
child: IconButton(
icon: _foundNews[index].isSelected
? const Icon(Icons.done)
: const Icon(Icons.edit_document),
onPressed: () {
updateSelectionMode(
_isSelectionMode,
index,
);
updateSelected(index);
},
),
),
),
),
// News post info
title: (_foundNews[index]
.permissionList
.contains('read'))
? Text(
_foundNews[index].content!.newsTitle,
maxLines:
(!isNarrow) ? 1 : 3, // Limit lines
overflow: TextOverflow.ellipsis,
)
: const Text(''),
// News post item subtitle
subtitle: ItemSubtitle(
item: _foundNews[index],
isNarrow: isNarrow,
),
// Define width to avoid consuming full width
trailing: SizedBox(
height: 60,
width: 120,
child: ItemTrailingButtons(
item: _foundNews[index],
scaffoldController: _scaffoldController,
),
),

onTap: () {
// Open news file object if read in permissions
String access =
_foundNews[index].permissionList;
if (access.contains('read')) {
_scaffoldController.navigateToSubpage(
ViewNews(
newsPost: _foundNews[index],
scaffoldController: _scaffoldController,
),
);
} else {
_scaffoldController.navigateToSubpage(
NonReadableNewsPost(
newsPost: _foundNews[index],
scaffoldController: _scaffoldController,
),
);
}
},
),
),
),
],
),
itemBuilder: (context, index) => ItemCard(
item: _foundNews[index],
isNarrow: isNarrow,
scaffoldController: _scaffoldController,
onSelectPressed: () {
updateSelectionMode(_isSelectionMode, index);
updateSelected(index);
},
),
),
),
Expand Down
145 changes: 145 additions & 0 deletions lib/widgets/item_card.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/// A stateful widget to display a news post card.
///
/// Copyright (C) 2026 Software Innovation Institute, Australian National University
///
/// License: GNU General Public License, Version 3 (the "License")
/// https://opensource.org/license/gpl-3-0
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <https://opensource.org/license/gpl-3-0>.
///
/// Authors: Jess Moore

library;

import 'package:flutter/material.dart';

import 'package:solidui/solidui.dart';

import 'package:communitypod/constants/app.dart';
import 'package:communitypod/models/news.dart';
import 'package:communitypod/news/non_readable_news_post.dart';
import 'package:communitypod/news/view_news.dart';
import 'package:communitypod/widgets/highlight_image.dart';
import 'package:communitypod/widgets/item_subtitle.dart';
import 'package:communitypod/widgets/item_title.dart';
import 'package:communitypod/widgets/item_trailing_buttons.dart';

/// A [stateful] widget to display a news post card.
///
/// Arguments:
/// - [item] - The news post to display.
/// - [isNarrow] - Whether the window is narrower than the narrow threshold.
/// - [scaffoldController] - Controller for the Solid scaffold.
/// - [onSelectPressed] - Callback invoked when the select button is pressed.

class ItemCard extends StatefulWidget {
const ItemCard({
super.key,
required this.item,
required this.isNarrow,
required this.scaffoldController,
required this.onSelectPressed,
});

final News item;
final bool isNarrow;
final SolidScaffoldController scaffoldController;
final VoidCallback onSelectPressed;

@override
State<ItemCard> createState() => _ItemCardState();
}

class _ItemCardState extends State<ItemCard> {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
HighlightImage(
imageUrl: widget.item.permissionList.contains('read')
? widget.item.content?.highlightImageUrl
: null,
),
Center(
child: Container(
decoration: widget.item.isSelected
? BoxDecoration(
color: theme.colorScheme.onInverseSurface,
borderRadius: const BorderRadius.all(
Radius.circular(5),
),
)
: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
),
child: ListTile(
leading: SizedBox(
width: NewsIconSize.width,
child: Center(
child: Ink(
decoration: buttonShapeList,
child: IconButton(
icon: widget.item.isSelected
? const Icon(Icons.done)
: const Icon(Icons.edit_document),
onPressed: widget.onSelectPressed,
),
),
),
),
title: ItemTitle(
item: widget.item,
isNarrow: widget.isNarrow,
),
subtitle: ItemSubtitle(
item: widget.item,
isNarrow: widget.isNarrow,
),
trailing: SizedBox(
height: 60,
width: 120,
child: ItemTrailingButtons(
item: widget.item,
scaffoldController: widget.scaffoldController,
),
),
onTap: () {
final access = widget.item.permissionList;
if (access.contains('read')) {
widget.scaffoldController.navigateToSubpage(
ViewNews(
newsPost: widget.item,
scaffoldController: widget.scaffoldController,
),
);
} else {
widget.scaffoldController.navigateToSubpage(
NonReadableNewsPost(
newsPost: widget.item,
scaffoldController: widget.scaffoldController,
),
);
}
},
),
),
),
],
),
);
}
}
58 changes: 58 additions & 0 deletions lib/widgets/item_title.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/// A stateless widget to show the title of a list item.
///
/// Copyright (C) 2026 Software Innovation Institute, Australian National University
///
/// License: GNU General Public License, Version 3 (the "License")
/// https://opensource.org/license/gpl-3-0
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <https://opensource.org/license/gpl-3-0>.
///
/// Authors: Jess Moore

library;

import 'package:flutter/material.dart';

import 'package:communitypod/models/news.dart';

/// A [stateless] widget to show the title of a list item.
///
/// Arguments:
/// - [item] - A list item.
/// - [isNarrow] - Flag describing whether window is narrower than
/// narrow threshold.
///
class ItemTitle extends StatelessWidget {
const ItemTitle({
super.key,
required News item,
required bool isNarrow,
}) : _item = item,
_isNarrow = isNarrow;

final News _item;
final bool _isNarrow;

@override
Widget build(BuildContext context) {
if (!_item.permissionList.contains('read')) {
return const Text('');
}
return Text(
_item.content!.newsTitle,
maxLines: (!_isNarrow) ? 1 : 3,
overflow: TextOverflow.ellipsis,
);
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: communitypod
description: 'Privacy preserving news sharing app using PODs.'
publish_to: 'none'
version: 0.0.12+1
version: 0.0.13+1

environment:
sdk: '>=3.2.3 <4.0.0'
Expand Down
2 changes: 1 addition & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: communitypod
version: 0.0.12
version: 0.0.13
summary: Privacy preserving news sharing app using PODs.
description: |
communitypod is a news sharing app, storing your news post files within your Solid
Expand Down
Loading