Compare commits

...

5 commits

Author SHA1 Message Date
65d27ce4a0 fix: reload posts when the parent widget has rebuilt on the timeline screen
This way if the service passed to us is changed we'll update our posts from it instead
of keeping the ones from the previous service.
2025-04-22 15:07:11 +02:00
3615342c64 fix: don't use TimelineService as state
Otherwise the widget won't use a new service if it has been provided by
the parent. It really isn't state anyway.
2025-04-22 15:06:56 +02:00
13ba6ada07 chore: relax the Firebase versions we support
We don't currently use API that's incompatible with the latest versions
of all Firebase packages, so let's indicate that we support them.
2025-04-22 08:50:54 +02:00
4f0c36a1cc fix: use a minimum of Dart 3.4.3 and don't use 'any' for any dep version constraints
We're very inconsistent with marking what Flutter and Dart versions we support. The .fvmrc indicates
Flutter 3.27.4 which comes with Dart 3.6.2, but the packages said 3.0 and 3.1.
This commit brings all versions in line and sets the minimum to Dart 3.4.3. This version is chosen
so it can be used as is with one of our projects that currently uses that Dart version.
2025-04-22 08:50:54 +02:00
a62935eb60 chore: add fvm configuration to gitignore 2025-02-17 15:52:52 +01:00
11 changed files with 70 additions and 52 deletions

3
.fvmrc Normal file
View file

@ -0,0 +1,3 @@
{
"flutter": "3.22.2"
}

3
.gitignore vendored
View file

@ -51,3 +51,6 @@ pubspec_overrides.yaml
**/example/windows
**/example/web
**/example/README.md
# FVM Version Cache
.fvm/

View file

@ -1,3 +1,8 @@
## 5.1.1
- Be honest about which Dart and Flutter versions we support
- Relax our Firebase version constraint, we also support the current newest versions
## 5.1.0
* Added `routeToPostDetail` to the `TimelineUserStory` to allow for navigation to the post detail screen.

View file

@ -3,26 +3,27 @@
# SPDX-License-Identifier: GPL-3.0-or-later
name: flutter_timeline
description: Visual elements and interface combined into one package
version: 5.1.0
version: 5.1.1
homepage: https://github.com/Iconica-Development/flutter_timeline
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
environment:
sdk: ">=3.1.3 <4.0.0"
sdk: ">=3.4.3 <4.0.0"
flutter: '>=3.22.2'
dependencies:
flutter:
sdk: flutter
flutter_timeline_view:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: ^5.1.0
version: ^5.1.1
flutter_timeline_interface:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: ^5.1.0
collection: any
version: ^5.1.1
collection: ^1.18.0
dev_dependencies:
flutter_lints: ^2.0.0
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis

View file

@ -2,9 +2,6 @@
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
@immutable
class FirebaseTimelineOptions {
const FirebaseTimelineOptions({
this.usersCollectionName = 'users',

View file

@ -2,9 +2,6 @@
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
@immutable
class FirebaseUserDocument {
const FirebaseUserDocument({
this.firstName,

View file

@ -4,26 +4,27 @@
name: flutter_timeline_firebase
description: Implementation of the Flutter Timeline interface for Firebase.
version: 5.1.0
version: 5.1.1
homepage: https://github.com/Iconica-Development/flutter_timeline
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
environment:
sdk: ">=3.1.3 <4.0.0"
sdk: ">=3.4.3 <4.0.0"
flutter: '>=3.22.2'
dependencies:
flutter:
sdk: flutter
cloud_firestore: ^4.13.1
firebase_core: ^2.22.0
firebase_storage: ^11.5.1
cloud_firestore: '>=4.13.1 <6.0.0'
firebase_core: '>=2.22.0 <4.0.0'
firebase_storage: '>=11.5.1 <13.0.0'
uuid: ^4.2.1
collection: ^1.18.0
flutter_timeline_interface:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: ^5.1.0
version: ^5.1.1
dev_dependencies:
flutter_lints: ^2.0.0
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis

View file

@ -4,18 +4,18 @@
name: flutter_timeline_interface
description: Interface for the service of the Flutter Timeline component
version: 5.1.0
version: 5.1.1
homepage: https://github.com/Iconica-Development/flutter_timeline
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
environment:
sdk: '>=3.1.3 <4.0.0'
sdk: '>=3.4.3 <4.0.0'
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_lints: ^2.0.0
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis

View file

@ -4,15 +4,14 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
import 'package:flutter_timeline_view/flutter_timeline_view.dart';
class TimelineScreen extends StatefulWidget {
const TimelineScreen({
TimelineScreen({
this.userId = 'test_user',
this.service,
TimelineService? service,
this.options = const TimelineOptions(),
this.onPostTap,
this.scrollController,
@ -24,7 +23,10 @@ class TimelineScreen extends StatefulWidget {
this.filterEnabled = false,
this.allowAllDeletion = false,
super.key,
});
}) : service = service ??
TimelineService(
postService: LocalTimelinePostService(),
);
/// The user id of the current user
final String userId;
@ -34,7 +36,7 @@ class TimelineScreen extends StatefulWidget {
final bool allowAllDeletion;
/// The service to use for fetching and manipulating posts
final TimelineService? service;
final TimelineService service;
/// All the configuration options for the timelinescreens and widgets
final TimelineOptions options;
@ -73,10 +75,6 @@ class _TimelineScreenState extends State<TimelineScreen> {
late var textFieldController = TextEditingController(
text: widget.options.filterOptions.initialFilterWord,
);
late var service = widget.service ??
TimelineService(
postService: LocalTimelinePostService(),
);
bool isLoading = true;
@ -111,6 +109,15 @@ class _TimelineScreenState extends State<TimelineScreen> {
});
}
@override
void didUpdateWidget(covariant TimelineScreen oldWidget) {
super.didUpdateWidget(oldWidget);
WidgetsBinding.instance.addPostFrameCallback((_) {
unawaited(loadPosts());
});
}
@override
Widget build(BuildContext context) {
if (isLoading && widget.posts == null) {
@ -119,14 +126,15 @@ class _TimelineScreenState extends State<TimelineScreen> {
// Build the list of posts
return ListenableBuilder(
listenable: service.postService,
listenable: widget.service.postService,
builder: (context, _) {
if (!context.mounted) return const SizedBox();
var posts = widget.posts ?? service.postService.getPosts(category);
var posts =
widget.posts ?? widget.service.postService.getPosts(category);
if (widget.filterEnabled && filterWord != null) {
if (service.postService is TimelineFilterService) {
posts = (service.postService as TimelineFilterService)
if (widget.service.postService is TimelineFilterService) {
posts = (widget.service.postService as TimelineFilterService)
.filterPosts(filterWord!, {});
} else {
debugPrint('Timeline service needs to mixin'
@ -149,7 +157,7 @@ class _TimelineScreenState extends State<TimelineScreen> {
);
}
var categories = service.postService.categories;
var categories = widget.service.postService.categories;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -255,7 +263,7 @@ class _TimelineScreenState extends State<TimelineScreen> {
padding: widget.options.paddings.postPadding,
child: widget.postWidgetBuilder?.call(post) ??
TimelinePostWidget(
service: service,
service: widget.service,
userId: widget.userId,
options: widget.options,
allowAllDeletion: widget.allowAllDeletion,
@ -273,11 +281,11 @@ class _TimelineScreenState extends State<TimelineScreen> {
builder: (context) => Scaffold(
body: TimelinePostScreen(
userId: 'test_user',
service: service,
service: widget.service,
options: widget.options,
post: post,
onPostDelete: () {
service.postService
widget.service.postService
.deletePost(post);
Navigator.of(context).pop();
},
@ -286,12 +294,14 @@ class _TimelineScreenState extends State<TimelineScreen> {
),
);
},
onTapLike: () async => service.postService
onTapLike: () async => widget
.service.postService
.likePost(widget.userId, post),
onTapUnlike: () async => service.postService
onTapUnlike: () async => widget
.service.postService
.unlikePost(widget.userId, post),
onPostDelete: () async =>
service.postService.deletePost(post),
widget.service.postService.deletePost(post),
onUserTap: widget.onUserTap,
),
),
@ -327,8 +337,8 @@ class _TimelineScreenState extends State<TimelineScreen> {
Future<void> loadPosts() async {
if (widget.posts != null || !context.mounted) return;
try {
await service.postService.fetchCategories();
await service.postService.fetchPosts(category);
await widget.service.postService.fetchCategories();
await widget.service.postService.fetchPosts(category);
setState(() {
isLoading = false;
});

View file

@ -4,29 +4,30 @@
name: flutter_timeline_view
description: Visual elements of the Flutter Timeline Component
version: 5.1.0
version: 5.1.1
homepage: https://github.com/Iconica-Development/flutter_timeline
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
environment:
sdk: ">=3.1.3 <4.0.0"
sdk: ">=3.4.3 <4.0.0"
flutter: '>=3.22.2'
dependencies:
flutter:
sdk: flutter
intl: any
intl: ^0.19.0
cached_network_image: ^3.2.2
dotted_border: ^2.1.0
collection: any
collection: ^1.18.0
flutter_svg: ^2.0.10+1
flutter_timeline_interface:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: ^5.1.0
version: ^5.1.1
flutter_image_picker:
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
version: ^4.0.0
dev_dependencies:
flutter_lints: ^2.0.0
flutter_iconica_analysis:
git:
url: https://github.com/Iconica-Development/flutter_iconica_analysis

View file

@ -5,6 +5,6 @@
name: flutter_timeline_workspace
environment:
sdk: '>=2.18.0 <3.0.0'
sdk: '>=3.4.3 <4.0.0'
dev_dependencies:
melos: ^3.0.1