Skip to content

Commit 1216639

Browse files
authored
feat(llc): add support for location based filtering for activities (#66)
1 parent 4bbd1dc commit 1216639

File tree

12 files changed

+108
-39
lines changed

12 files changed

+108
-39
lines changed

docs/code_snippets/03_02_querying_activities.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ late Feed feed;
55

66
Future<void> activitySearchAndQueries() async {
77
final query = ActivitiesQuery(
8-
filter: Filter.equal(ActivitiesFilterField.type, 'post'),
8+
filter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
99
sort: [ActivitiesSort.desc(ActivitiesSortField.createdAt)],
1010
limit: 10,
1111
);

melos.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ command:
4848
shared_preferences: ^2.5.3
4949
state_notifier: ^1.0.0
5050
stream_feeds: ^0.4.0
51-
stream_core: ^0.3.1
51+
stream_core: ^0.3.2
5252
video_player: ^2.10.0
5353
uuid: ^4.5.1
5454

packages/stream_feeds/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
## Upcoming
22
- [BREAKING] Unified `ThreadedCommentData` into `CommentData` to handle both flat and threaded comments.
3+
- [BREAKING] Renamed `ActivitiesFilterField.type` to `ActivitiesFilterField.activityType`.
4+
- [BREAKING] Changed `ActivityData.location` field type from `ActivityLocation?` to `LocationCoordinate?`.
35
- Add support for `enforceUnique` parameter while adding reactions.
6+
- Add location filtering support for activities with `ActivitiesFilterField.near` and `ActivitiesFilterField.withinBounds` filter fields.
7+
- Add new activity filter fields: `ActivitiesFilterField.feed` and `ActivitiesFilterField.interestTags`.
48

59
## 0.4.0
610
- [BREAKING] Change `queryFollowSuggestions` return type to `List<FeedSuggestionData>`.

packages/stream_feeds/lib/src/feeds_client.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ abstract interface class StreamFeedsClient {
319319
/// ```dart
320320
/// final activityList = client.activityList(ActivitiesQuery(
321321
/// filter: Filter.and([
322-
/// Filter.equal(ActivitiesFilterField.type, 'post'),
322+
/// Filter.equal(ActivitiesFilterField.activityType, 'post'),
323323
/// Filter.greaterThan(ActivitiesFilterField.createdAt,
324324
/// DateTime.now().subtract(Duration(days: 7))),
325325
/// ]),

packages/stream_feeds/lib/src/models.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
export 'package:stream_core/stream_core.dart'
2+
show BoundingBox, CircularRegion, LocationCoordinate;
3+
14
export 'models/activity_data.dart';
25
export 'models/aggregated_activity_data.dart';
36
export 'models/bookmark_data.dart';

packages/stream_feeds/lib/src/models/activity_data.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class ActivityData with _$ActivityData {
127127

128128
/// Geographic location data associated with the activity, if any.
129129
@override
130-
final ActivityLocation? location;
130+
final LocationCoordinate? location;
131131

132132
/// Users mentioned in the activity.
133133
@override
@@ -277,7 +277,12 @@ extension ActivityResponseMapper on ActivityResponse {
277277
interestTags: interestTags,
278278
isWatched: isWatched,
279279
latestReactions: [...latestReactions.map((r) => r.toModel())],
280-
location: location,
280+
location: location?.let(
281+
(it) => LocationCoordinate(
282+
latitude: it.lat,
283+
longitude: it.lng,
284+
),
285+
),
281286
mentionedUsers: [...mentionedUsers.map((u) => u.toModel())],
282287
moderation: moderation?.toModel(),
283288
notificationContext: notificationContext,

packages/stream_feeds/lib/src/models/activity_data.freezed.dart

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/stream_feeds/lib/src/state/query/activities_query.dart

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ part 'activities_query.freezed.dart';
1616
/// ## Example
1717
/// ```dart
1818
/// final query = ActivitiesQuery(
19-
/// filter: Filter.equal(ActivitiesFilterField.type, "post"),
19+
/// filter: Filter.equal(ActivitiesFilterField.activityType, "post"),
2020
/// sort: [ActivitiesSort.desc(ActivitiesSortField.createdAt)],
2121
/// limit: 20,
2222
/// );
@@ -66,6 +66,14 @@ class ActivitiesFilterField extends FilterField<ActivityData> {
6666
/// Creates a new activities filter field.
6767
ActivitiesFilterField(super.remote, super.value);
6868

69+
/// Filter by the type of activity (e.g., "post", "comment", "reaction").
70+
///
71+
/// **Supported operators:** `.equal`, `.in`
72+
static final activityType = ActivitiesFilterField(
73+
'activity_type',
74+
(data) => data.type,
75+
);
76+
6977
/// Filter by the creation timestamp of the activity.
7078
///
7179
/// **Supported operators:** `.equal`, `.greaterThan`, `.lessThan`, `.greaterThanOrEqual`, `.lessThanOrEqual`
@@ -76,7 +84,8 @@ class ActivitiesFilterField extends FilterField<ActivityData> {
7684

7785
/// Filter by the expiration timestamp of the activity.
7886
///
79-
/// **Supported operators:** `.exists`
87+
/// **Supported operators:** `.equal`, `.notEqual`, `.greaterThan`,
88+
/// `.lessThan`, `.greaterThanOrEqual`, `.lessThanOrEqual`, `.exists`
8089
static final expiresAt = ActivitiesFilterField(
8190
'expires_at',
8291
(data) => data.expiresAt,
@@ -90,14 +99,30 @@ class ActivitiesFilterField extends FilterField<ActivityData> {
9099
(data) => data.id,
91100
);
92101

102+
/// Filter by the feed ID(s) the activity belongs to.
103+
///
104+
/// **Supported operators:** `.equal`, `.in`
105+
static final feed = ActivitiesFilterField(
106+
'feed',
107+
(data) => data.feeds,
108+
);
109+
93110
/// Filter by the filter tags associated with the activity.
94111
///
95-
/// **Supported operators:** `.equal`, `.in`, `.customContains`
112+
/// **Supported operators:** `.equal`, `.in`, `.contains`
96113
static final filterTags = ActivitiesFilterField(
97114
'filter_tags',
98115
(data) => data.filterTags,
99116
);
100117

118+
/// Filter by the interest tags associated with the activity.
119+
///
120+
/// **Supported operators:** `.equal`, `.in`, `.contains`
121+
static final interestTags = ActivitiesFilterField(
122+
'interest_tags',
123+
(data) => data.interestTags,
124+
);
125+
101126
/// Filter by the popularity score of the activity.
102127
///
103128
/// **Supported operators:** `.equal`, `.greaterThan`, `.lessThan`, `.greaterThanOrEqual`, `.lessThanOrEqual`
@@ -108,35 +133,49 @@ class ActivitiesFilterField extends FilterField<ActivityData> {
108133

109134
/// Filter by the search data content of the activity.
110135
///
111-
/// **Supported operators:** `.equal`, `.customQ`, `.customAutocomplete`
136+
/// **Supported operators:** `.contains`, `.in`, `.pathExists`
112137
static final searchData = ActivitiesFilterField(
113138
'search_data',
114139
(data) => data.searchData,
115140
);
116141

117142
/// Filter by the text content of the activity.
118143
///
119-
/// **Supported operators:** `.equal`, `.customQ`, `.customAutocomplete`
144+
/// **Supported operators:** `.equal`, `.q` (full-text search), `.autocomplete`
120145
static final text = ActivitiesFilterField(
121146
'text',
122147
(data) => data.text,
123148
);
124149

125-
/// Filter by the type of activity (e.g., "post", "comment", "reaction").
126-
///
127-
/// **Supported operators:** `.equal`, `.in`
128-
static final type = ActivitiesFilterField(
129-
'type',
130-
(data) => data.type,
131-
);
132-
133150
/// Filter by the user ID who created the activity.
134151
///
135152
/// **Supported operators:** `.equal`, `.in`
136153
static final userId = ActivitiesFilterField(
137154
'user_id',
138155
(data) => data.user.id,
139156
);
157+
158+
/// Filter by the proximity to a specific location.
159+
///
160+
/// Note: This requires an object with latitude ('lat'), longitude ('lng')
161+
/// and distance in km ('distance).
162+
///
163+
/// **Supported operators:** `.equal`
164+
static final near = ActivitiesFilterField(
165+
'near',
166+
(data) => data.location,
167+
);
168+
169+
/// Filter by activities within specific geographical bounds.
170+
///
171+
/// Note: This requires an object with 'sw_lat', 'sw_lng' (southwest corner)
172+
/// and 'ne_lat', 'ne_lng' (northeast) corner keys.
173+
///
174+
/// **Supported operators:** `.equal`
175+
static final withinBounds = ActivitiesFilterField(
176+
'within_bounds',
177+
(data) => data.location,
178+
);
140179
}
141180

142181
// endregion

packages/stream_feeds/lib/src/state/query/feed_query.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ part 'feed_query.freezed.dart';
1919
/// ```dart
2020
/// final query = FeedQuery(
2121
/// fid: FeedId(group: 'user', id: 'john'),
22-
/// activityFilter: Filter.equal(ActivitiesFilterField.type, 'post'),
22+
/// activityFilter: Filter.equal(ActivitiesFilterField.activityType, 'post'),
2323
/// activityLimit: 25,
2424
/// watch: true,
2525
/// );

packages/stream_feeds/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ dependencies:
3030
retrofit: ">=4.6.0 <=4.9.0"
3131
rxdart: ^0.28.0
3232
state_notifier: ^1.0.0
33-
stream_core: ^0.3.1
33+
stream_core: ^0.3.2
3434
uuid: ^4.5.1
3535

3636
dev_dependencies:

0 commit comments

Comments
 (0)