Skip to content

Commit 4c4a51f

Browse files
core: add pagination and update example (#222)
* fix: use data not used on setUser * feat: add pagination management to core feed bloc * feat: update and expand core example * docs: update CHANGELOG * fix ci * ui kit: bump depedency * bump dev dependencies * github action build workflow: channel stable * ui kit: fix full screen media test * ui kit: fix debug fill properties test * ui kit: fix FlatActivityListPage test * fix test: !timersPending exception A Timer is still pending even after the widget tree was disposed. * fix flat feed core test * bloc: queryPaginatedReactions wip * loadMoreReactions wip * test bloc.queryPaginatedReactions * Aggregated Feed: Paginated Activities (#219) * aggregated feed builder wip * loadMoreGroupedActivities * fix analyzer * internal annotation * update todo * make NextParams const * apply reviews * test queryPaginatedGroupedActivities wip * clean up a bit + aggregated feed test passing * format * onAddActivityGroup + getEnrichedActivityDetail +onRemoveActivityGroup * test AggregatedFeedCore * test getEnrichedActivity * format * test onAddActivityGroup * feat: add refresh to feed bloc and other fixes * feat: add flags to paginated results * fix: nested child reactions now reactive * fix fileExt extension for .mov * fix linter issues * time parameter in onAddActivity * ImagePreview: fix typo in error message * make GenericFeedBloc immutable * make GenericFeedBloc immutable * fix: add missing pubspec file * test: fix missing flags argument * chore: fix linter warnings * chore: avoid print * test: update * chore: fix lints * chore: remove late keyword * remove activity and lookupAttr * feat: add core build context extensions * docs: expand core example * format * chore: update example * format * fix bloc test * format * update llc and faye changelogs * faye: version bump * update pubspec and tweak changelog * llc: tweak changelog + bump pubspec version * workflow: reduce min_coverage constraint * tweak changelog * update version header in llc * version bump Co-authored-by: Sacha Arbonel <sacha.arbonel@hotmail.fr>
1 parent 4e8b237 commit 4c4a51f

File tree

137 files changed

+3342
-1032
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+3342
-1032
lines changed

.github/workflows/build.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
channel:
18-
- dev
18+
- stable
1919

2020
steps:
2121
- uses: actions/checkout@v2
@@ -64,7 +64,7 @@ jobs:
6464
- uses: VeryGoodOpenSource/very_good_coverage@v1.2.0
6565
with:
6666
path: packages/stream_feed/coverage/lcov.info
67-
min_coverage: 80
67+
min_coverage: 78
6868
- uses: VeryGoodOpenSource/very_good_coverage@v1.2.0
6969
with:
7070
path: packages/faye_dart/coverage/lcov.info

analysis_options.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# This is the default analysis_options.yaml for all packages and examples
32
# If a package needs specific rules, create the analysis_options.yaml on it
43
# include this file, like:
@@ -11,10 +10,13 @@ analyzer:
1110
- lib/**/*.g.dart
1211
- lib/**/*.freezed.dart
1312
- example/main.dart
13+
errors:
14+
todo: ignore
1415

1516
linter:
1617
rules:
1718
- always_use_package_imports
19+
- avoid_print
1820
- avoid_empty_else
1921
- avoid_relative_lib_imports
2022
- avoid_slow_async_io
@@ -60,7 +62,7 @@ linter:
6062
- await_only_futures
6163
- camel_case_extensions
6264
- camel_case_types
63-
- cascade_invocations
65+
# - cascade_invocations
6466

6567
- constant_identifier_names
6668
- curly_braces_in_flow_control_structures
@@ -74,7 +76,7 @@ linter:
7476
- leading_newlines_in_multiline_strings
7577
- library_names
7678
- library_prefixes
77-
- lines_longer_than_80_chars
79+
# - lines_longer_than_80_chars
7880
- missing_whitespace_between_adjacent_strings
7981
- non_constant_identifier_names
8082
- null_closures
@@ -151,4 +153,4 @@ linter:
151153
- cast_nullable_to_non_nullable
152154
- unnecessary_null_checks
153155
- tighten_type_of_initializing_formals
154-
- null_check_on_nullable_type_parameter
156+
- null_check_on_nullable_type_parameter

example/lib/client_provider.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:flutter/foundation.dart';
12
import 'package:flutter/material.dart';
23
import 'package:flutter/widgets.dart';
34
import 'package:stream_feed/stream_feed.dart';
@@ -9,6 +10,7 @@ class ClientProvider extends InheritedWidget {
910
required Widget child,
1011
}) : super(key: key, child: child);
1112

13+
/// Access the [StreamFeedClient] from the provider to perform API actions.
1214
final StreamFeedClient client;
1315

1416
static ClientProvider of(BuildContext context) {
@@ -21,4 +23,10 @@ class ClientProvider extends InheritedWidget {
2123
bool updateShouldNotify(ClientProvider old) {
2224
return old.child != child || old.client != client;
2325
}
26+
27+
@override
28+
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
29+
super.debugFillProperties(properties);
30+
properties.add(DiagnosticsProperty<StreamFeedClient>('client', client));
31+
}
2432
}

example/lib/timeline_screen.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import 'package:stream_feed/stream_feed.dart';
44
import 'package:stream_feed_example/activity_item.dart';
55
import 'package:stream_feed_example/extension.dart';
66

7-
// ignore_for_file: public_member_api_docs
8-
97
class TimelineScreen extends StatefulWidget {
108
const TimelineScreen({
119
required this.currentUser,
@@ -34,14 +32,14 @@ class _TimelineScreenState extends State<TimelineScreen> {
3432
Future<void> _listenToFeed() async {
3533
_feedSubscription = await _client
3634
.flatFeed('timeline', widget.currentUser.id)
35+
// ignore: avoid_print
3736
.subscribe(print);
3837
}
3938

4039
Future<void> _loadActivities({bool pullToRefresh = false}) async {
4140
if (!pullToRefresh) setState(() => _isLoading = true);
4241
final userFeed = _client.flatFeed('timeline', widget.currentUser.id);
4342
final data = await userFeed.getActivities();
44-
final data2 = await userFeed.getEnrichedActivities();
4543
if (!pullToRefresh) _isLoading = false;
4644
setState(() => activities = data);
4745
}
@@ -50,7 +48,7 @@ class _TimelineScreenState extends State<TimelineScreen> {
5048
void didChangeDependencies() {
5149
super.didChangeDependencies();
5250
_client = context.client;
53-
// _listenToFeed();
51+
_listenToFeed();
5452
_loadActivities();
5553
}
5654

example/pubspec.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
name: stream_feed_example
22
description: A new Flutter application.
33

4-
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
4+
publish_to: "none" # Remove this line if you wish to publish to pub.dev
55
version: 1.0.0+1
66

77
environment:
8-
sdk: '>=2.12.0 <3.0.0'
8+
sdk: ">=2.12.0 <3.0.0"
99

1010
dependencies:
1111
cupertino_icons: ^1.0.2
1212
flutter:
1313
sdk: flutter
14-
timeago: ^3.0.2
1514
stream_feed:
1615
path: ../packages/stream_feed
16+
timeago: ^3.0.2
1717

1818
dev_dependencies:
1919
flutter_test:
2020
sdk: flutter
2121

2222
flutter:
23-
uses-material-design: true
23+
uses-material-design: true

packages/faye_dart/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## [0.1.1+2] - (27-05-2022)
2+
- nothing new / lints
3+
14
## [0.1.1+1] - (25-02-2022)
25

36
- fix: implement Equatable on `FayeClient`. With this change, if you fetch your client from an `InheritedWidget` for example, `updateShouldNotify` doesn't trigger every time.

packages/faye_dart/lib/src/channel.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:faye_dart/src/grammar.dart' as grammar;
44
import 'package:faye_dart/src/message.dart';
55
import 'package:faye_dart/src/subscription.dart';
66

7-
const event_message = 'message';
7+
const eventMessage = 'message';
88

99
class Channel with EquatableMixin, EventEmitter<Message> {
1010
Channel(this.name);
@@ -81,14 +81,14 @@ extension ChannelMapX on Map<String, Channel> {
8181

8282
void subscribe(String name, Subscription subscription) {
8383
final channel = putIfAbsent(name, () => Channel(name));
84-
channel.bind(event_message, subscription);
84+
channel.bind(eventMessage, subscription);
8585
}
8686

8787
bool unsubscribe(String name, Subscription subscription) {
8888
final channel = this[name];
8989
if (channel == null) return false;
90-
channel.unbind(event_message, subscription);
91-
if (!channel.hasListeners(event_message)) {
90+
channel.unbind(eventMessage, subscription);
91+
if (!channel.hasListeners(eventMessage)) {
9292
remove(name);
9393
return true;
9494
}
@@ -99,7 +99,7 @@ extension ChannelMapX on Map<String, Channel> {
9999
final channels = Channel.expand(message.channel);
100100
if (channels == null) return;
101101
for (final channel in channels) {
102-
this[channel]?.trigger(event_message, message);
102+
this[channel]?.trigger(eventMessage, message);
103103
}
104104
}
105105
}

packages/faye_dart/lib/src/client.dart

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ import 'dart:math' as math;
55
import 'package:equatable/equatable.dart';
66
import 'package:faye_dart/faye_dart.dart';
77
import 'package:faye_dart/src/channel.dart';
8+
import 'package:faye_dart/src/extensible.dart';
89
import 'package:faye_dart/src/message.dart';
910
import 'package:faye_dart/src/timeout_helper.dart';
1011
import 'package:logging/logging.dart';
1112
import 'package:meta/meta.dart';
1213
import 'package:web_socket_channel/status.dart' as status;
1314
import 'package:web_socket_channel/web_socket_channel.dart';
1415

15-
import 'package:faye_dart/src/extensible.dart';
16-
1716
/// Connexion status of the client
1817
enum FayeClientState {
1918
unconnected,
@@ -67,7 +66,7 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
6766
final int retry;
6867
final _channels = <String, Channel>{};
6968

70-
var _advice = Advice(
69+
var _advice = const Advice(
7170
reconnect: Advice.retry,
7271
interval: 1000 * defaultConnectionInterval,
7372
timeout: 1000 * defaultConnectionTimeout,
@@ -113,7 +112,7 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
113112

114113
void _initWebSocketChannel() {
115114
_manuallyClosed = false;
116-
_logger.info("Initiating connection with $baseUrl");
115+
_logger.info('Initiating connection with $baseUrl');
117116
if (_webSocketChannel != null) {
118117
_closeWebSocketChannel();
119118
}
@@ -129,7 +128,7 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
129128
cancelAllTimeout();
130129

131130
if (_webSocketChannel != null) {
132-
_logger.info("Closing connection for $baseUrl");
131+
_logger.info('Closing connection for $baseUrl');
133132
_unsubscribeFromWebsocket();
134133
_webSocketChannel?.sink.close(status.goingAway);
135134
_webSocketChannel = null;
@@ -150,10 +149,8 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
150149

151150
void _unsubscribeFromWebsocket() {
152151
_logger.info('Stopped listening to $baseUrl');
153-
if (_websocketSubscription != null) {
154-
_websocketSubscription!.cancel();
155-
_websocketSubscription = null;
156-
}
152+
_websocketSubscription?.cancel();
153+
_websocketSubscription = null;
157154
}
158155

159156
void _onDataReceived(dynamic data) {
@@ -194,7 +191,7 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
194191

195192
_initWebSocketChannel();
196193

197-
_logger.info("Initiating handshake with $baseUrl");
194+
_logger.info('Initiating handshake with $baseUrl');
198195

199196
_sendMessage(
200197
Message(
@@ -279,7 +276,9 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
279276
}
280277

281278
void _subscribeChannels(Iterable<String> channels, {bool force = false}) {
282-
for (final channel in channels) subscribe(channel, force: force);
279+
for (final channel in channels) {
280+
subscribe(channel, force: force);
281+
}
283282
}
284283

285284
Future<Subscription> subscribe(
@@ -390,7 +389,7 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
390389
final id = _generateMessageId();
391390
message.id = id;
392391
pipeThroughExtensions('outgoing', message, (message) {
393-
_logger.info("sending message : $message");
392+
_logger.info('sending message : $message');
394393
if (onResponse != null) _responseCallbacks[id] = onResponse;
395394
final data = jsonEncode(message);
396395
_webSocketChannel?.sink.add(data);
@@ -404,7 +403,7 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
404403
callback = _responseCallbacks.remove(id);
405404
}
406405
pipeThroughExtensions('incoming', message, (message) {
407-
_logger.info("received message : $message");
406+
_logger.info('received message : $message');
408407
if (message.advice != null) _handleAdvice(message.advice!);
409408
_deliverMessage(message);
410409
callback?.call(message);
@@ -435,7 +434,7 @@ class FayeClient with Extensible, TimeoutHelper, EquatableMixin {
435434
_connectRequestInProgress = false;
436435
_logger.info('Closed connection for $_clientId');
437436
}
438-
setTimeout(Duration(milliseconds: _advice.interval), () => connect());
437+
setTimeout(Duration(milliseconds: _advice.interval), connect);
439438
}
440439

441440
@override

packages/faye_dart/lib/src/error.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import 'grammar.dart' as grammar;
1+
import 'package:faye_dart/src/grammar.dart' as grammar;
22

33
class FayeClientError {
44
const FayeClientError({

packages/faye_dart/lib/src/event_emitter.dart

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ class EventEmitter<T> {
1919
/// Mapping of events to a list of event handlers
2020
late final _events = <String, LinkedList<_ListenerEntry<T>>>{};
2121

22-
/// A callback for error reporting if one of the listeners added with [bind] throws.
22+
/// A callback for error reporting if one of the listeners added with [bind]
23+
/// throws.
2324
///
2425
/// This callback should not throw.
2526
///
2627
/// It exists for error reporting, and should not be used otherwise.
2728
///
28-
/// If no [onError] is specified, fallbacks to [Zone.current.handleUncaughtError].
29+
/// If no [onError] is specified, fallbacks to
30+
/// [Zone.current.handleUncaughtError].
2931
ErrorListener? onError;
3032

3133
bool _mounted = true;
@@ -71,7 +73,9 @@ class EventEmitter<T> {
7173
}
7274
}
7375
}
74-
for (final entry in removables) listeners.remove(entry);
76+
for (final entry in removables) {
77+
listeners.remove(entry);
78+
}
7579
if (didThrow) throw Error();
7680
}
7781

@@ -123,7 +127,7 @@ class EventEmitter<T> {
123127
assert(_debugIsMounted(), '');
124128
final listeners = _events[event];
125129
if (listeners == null) {
126-
throw "Event not available";
130+
throw 'Event not available';
127131
}
128132
return listeners.isNotEmpty;
129133
}

packages/faye_dart/lib/src/extensible.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'dart:collection';
22

3-
import 'message.dart';
3+
import 'package:faye_dart/src/message.dart';
44

55
typedef MessageHandler = Message Function(Message message);
66

@@ -24,10 +24,10 @@ class Extensible {
2424
void Function(Message message) callback,
2525
) {
2626
if (_extensions.isEmpty) return callback(message);
27-
var extensions = Queue<Map<String, MessageHandler>>.from(_extensions);
27+
final extensions = Queue<Map<String, MessageHandler>>.from(_extensions);
2828
void pipe(Message message) {
2929
if (extensions.isEmpty) return callback(message);
30-
var extension = extensions.removeFirst();
30+
final extension = extensions.removeFirst();
3131
final fn = extension[stage];
3232
if (fn == null) return pipe(message);
3333
final modifiedMessage = fn(message);
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
const channelName =
2-
r"^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$";
2+
r'^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$';
33

44
const channelPattern =
5-
r"^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$";
5+
r'^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$';
66

77
const error =
8-
r"^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$";
8+
r'^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$';
99

1010
const version =
11-
r"^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$";
11+
r'^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$';

0 commit comments

Comments
 (0)