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
2 changes: 1 addition & 1 deletion docs/code_snippets/03_02_querying_activities.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ late Feed feed;

Future<void> activitySearchAndQueries() async {
final query = ActivitiesQuery(
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
sort: [ActivitiesSort.desc(ActivitiesSortField.createdAt)],
limit: 10,
);
Expand Down
2 changes: 1 addition & 1 deletion melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ command:
shared_preferences: ^2.5.3
state_notifier: ^1.0.0
stream_feeds: ^0.4.0
stream_core: ^0.3.1
stream_core: ^0.3.2
video_player: ^2.10.0
uuid: ^4.5.1

Expand Down
4 changes: 4 additions & 0 deletions packages/stream_feeds/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## Upcoming
- [BREAKING] Unified `ThreadedCommentData` into `CommentData` to handle both flat and threaded comments.
- [BREAKING] Renamed `ActivitiesFilterField.type` to `ActivitiesFilterField.activityType`.
- [BREAKING] Changed `ActivityData.location` field type from `ActivityLocation?` to `LocationCoordinate?`.
- Add support for `enforceUnique` parameter while adding reactions.
- Add location filtering support for activities with `ActivitiesFilterField.near` and `ActivitiesFilterField.withinBounds` filter fields.
- Add new activity filter fields: `ActivitiesFilterField.feed` and `ActivitiesFilterField.interestTags`.

## 0.4.0
- [BREAKING] Change `queryFollowSuggestions` return type to `List<FeedSuggestionData>`.
Expand Down
2 changes: 1 addition & 1 deletion packages/stream_feeds/lib/src/feeds_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ abstract interface class StreamFeedsClient {
/// ```dart
/// final activityList = client.activityList(ActivitiesQuery(
/// filter: Filter.and([
/// Filter.equal(ActivitiesFilterField.type, 'post'),
/// Filter.equal(ActivitiesFilterField.activityType, 'post'),
/// Filter.greaterThan(ActivitiesFilterField.createdAt,
/// DateTime.now().subtract(Duration(days: 7))),
/// ]),
Expand Down
3 changes: 3 additions & 0 deletions packages/stream_feeds/lib/src/models.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export 'package:stream_core/stream_core.dart'
show BoundingBox, CircularRegion, LocationCoordinate;

export 'models/activity_data.dart';
export 'models/aggregated_activity_data.dart';
export 'models/bookmark_data.dart';
Expand Down
9 changes: 7 additions & 2 deletions packages/stream_feeds/lib/src/models/activity_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class ActivityData with _$ActivityData {

/// Geographic location data associated with the activity, if any.
@override
final ActivityLocation? location;
final LocationCoordinate? location;

/// Users mentioned in the activity.
@override
Expand Down Expand Up @@ -277,7 +277,12 @@ extension ActivityResponseMapper on ActivityResponse {
interestTags: interestTags,
isWatched: isWatched,
latestReactions: [...latestReactions.map((r) => r.toModel())],
location: location,
location: location?.let(
(it) => LocationCoordinate(
latitude: it.lat,
longitude: it.lng,
),
),
mentionedUsers: [...mentionedUsers.map((u) => u.toModel())],
moderation: moderation?.toModel(),
notificationContext: notificationContext,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 52 additions & 13 deletions packages/stream_feeds/lib/src/state/query/activities_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ part 'activities_query.freezed.dart';
/// ## Example
/// ```dart
/// final query = ActivitiesQuery(
/// filter: Filter.equal(ActivitiesFilterField.type, "post"),
/// filter: Filter.equal(ActivitiesFilterField.activityType, "post"),
/// sort: [ActivitiesSort.desc(ActivitiesSortField.createdAt)],
/// limit: 20,
/// );
Expand Down Expand Up @@ -66,6 +66,14 @@ class ActivitiesFilterField extends FilterField<ActivityData> {
/// Creates a new activities filter field.
ActivitiesFilterField(super.remote, super.value);

/// Filter by the type of activity (e.g., "post", "comment", "reaction").
///
/// **Supported operators:** `.equal`, `.in`
static final activityType = ActivitiesFilterField(
'activity_type',
(data) => data.type,
);

/// Filter by the creation timestamp of the activity.
///
/// **Supported operators:** `.equal`, `.greaterThan`, `.lessThan`, `.greaterThanOrEqual`, `.lessThanOrEqual`
Expand All @@ -76,7 +84,8 @@ class ActivitiesFilterField extends FilterField<ActivityData> {

/// Filter by the expiration timestamp of the activity.
///
/// **Supported operators:** `.exists`
/// **Supported operators:** `.equal`, `.notEqual`, `.greaterThan`,
/// `.lessThan`, `.greaterThanOrEqual`, `.lessThanOrEqual`, `.exists`
static final expiresAt = ActivitiesFilterField(
'expires_at',
(data) => data.expiresAt,
Expand All @@ -90,14 +99,30 @@ class ActivitiesFilterField extends FilterField<ActivityData> {
(data) => data.id,
);

/// Filter by the feed ID(s) the activity belongs to.
///
/// **Supported operators:** `.equal`, `.in`
static final feed = ActivitiesFilterField(
'feed',
(data) => data.feeds,
);

/// Filter by the filter tags associated with the activity.
///
/// **Supported operators:** `.equal`, `.in`, `.customContains`
/// **Supported operators:** `.equal`, `.in`, `.contains`
static final filterTags = ActivitiesFilterField(
'filter_tags',
(data) => data.filterTags,
);

/// Filter by the interest tags associated with the activity.
///
/// **Supported operators:** `.equal`, `.in`, `.contains`
static final interestTags = ActivitiesFilterField(
'interest_tags',
(data) => data.interestTags,
);

/// Filter by the popularity score of the activity.
///
/// **Supported operators:** `.equal`, `.greaterThan`, `.lessThan`, `.greaterThanOrEqual`, `.lessThanOrEqual`
Expand All @@ -108,35 +133,49 @@ class ActivitiesFilterField extends FilterField<ActivityData> {

/// Filter by the search data content of the activity.
///
/// **Supported operators:** `.equal`, `.customQ`, `.customAutocomplete`
/// **Supported operators:** `.contains`, `.in`, `.pathExists`
static final searchData = ActivitiesFilterField(
'search_data',
(data) => data.searchData,
);

/// Filter by the text content of the activity.
///
/// **Supported operators:** `.equal`, `.customQ`, `.customAutocomplete`
/// **Supported operators:** `.equal`, `.q` (full-text search), `.autocomplete`
static final text = ActivitiesFilterField(
'text',
(data) => data.text,
);

/// Filter by the type of activity (e.g., "post", "comment", "reaction").
///
/// **Supported operators:** `.equal`, `.in`
static final type = ActivitiesFilterField(
'type',
(data) => data.type,
);

/// Filter by the user ID who created the activity.
///
/// **Supported operators:** `.equal`, `.in`
static final userId = ActivitiesFilterField(
'user_id',
(data) => data.user.id,
);

/// Filter by the proximity to a specific location.
///
/// Note: This requires an object with latitude ('lat'), longitude ('lng')
/// and distance in km ('distance).
///
/// **Supported operators:** `.equal`
static final near = ActivitiesFilterField(
'near',
(data) => data.location,
);

/// Filter by activities within specific geographical bounds.
///
/// Note: This requires an object with 'sw_lat', 'sw_lng' (southwest corner)
/// and 'ne_lat', 'ne_lng' (northeast) corner keys.
///
/// **Supported operators:** `.equal`
static final withinBounds = ActivitiesFilterField(
'within_bounds',
(data) => data.location,
);
}

// endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ part 'feed_query.freezed.dart';
/// ```dart
/// final query = FeedQuery(
/// fid: FeedId(group: 'user', id: 'john'),
/// activityFilter: Filter.equal(ActivitiesFilterField.type, 'post'),
/// activityFilter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
/// activityLimit: 25,
/// watch: true,
/// );
Expand Down
2 changes: 1 addition & 1 deletion packages/stream_feeds/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies:
retrofit: ">=4.6.0 <=4.9.0"
rxdart: ^0.28.0
state_notifier: ^1.0.0
stream_core: ^0.3.1
stream_core: ^0.3.2
uuid: ^4.5.1

dev_dependencies:
Expand Down
16 changes: 8 additions & 8 deletions packages/stream_feeds/test/state/activity_list_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void main() {
'ActivityUpdatedEvent - should remove activity when updated to non-matching type',
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
),
),
setUp: (tester) => tester.get(
Expand Down Expand Up @@ -54,7 +54,7 @@ void main() {
'ActivityReactionAddedEvent - should remove activity when reaction causes filter mismatch',
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
),
),
setUp: (tester) => tester.get(
Expand Down Expand Up @@ -91,7 +91,7 @@ void main() {
'ActivityReactionDeletedEvent - should remove activity when reaction deletion causes filter mismatch',
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
),
),
setUp: (tester) => tester.get(
Expand Down Expand Up @@ -128,7 +128,7 @@ void main() {
'BookmarkAddedEvent - should remove activity when bookmark causes filter mismatch',
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
),
),
setUp: (tester) => tester.get(
Expand Down Expand Up @@ -157,7 +157,7 @@ void main() {
'BookmarkDeletedEvent - should remove activity when bookmark deletion causes filter mismatch',
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
),
),
setUp: (tester) => tester.get(
Expand Down Expand Up @@ -186,7 +186,7 @@ void main() {
'CommentAddedEvent - should remove activity when comment causes filter mismatch',
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
),
),
setUp: (tester) => tester.get(
Expand Down Expand Up @@ -220,7 +220,7 @@ void main() {
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.and([
Filter.equal(ActivitiesFilterField.type, 'post'),
Filter.equal(ActivitiesFilterField.activityType, 'post'),
Filter.equal(ActivitiesFilterField.filterTags, ['featured']),
]),
),
Expand Down Expand Up @@ -254,7 +254,7 @@ void main() {
build: (client) => client.activityList(
ActivitiesQuery(
filter: Filter.or([
Filter.equal(ActivitiesFilterField.type, 'post'),
Filter.equal(ActivitiesFilterField.activityType, 'post'),
Filter.equal(ActivitiesFilterField.filterTags, ['featured']),
]),
),
Expand Down
Loading