diff --git a/docs_code_snippets/04_01_feeds.dart b/docs_code_snippets/04_01_feeds.dart index 08771a3f..bb25dee4 100644 --- a/docs_code_snippets/04_01_feeds.dart +++ b/docs_code_snippets/04_01_feeds.dart @@ -1,4 +1,4 @@ -// ignore_for_file: unused_local_variable, avoid_redundant_argument_values +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values import 'package:stream_feeds/stream_feeds.dart'; diff --git a/docs_code_snippets/04_02_feeds_and_activity_visibility.dart b/docs_code_snippets/04_02_feeds_and_activity_visibility.dart new file mode 100644 index 00000000..41c8c64d --- /dev/null +++ b/docs_code_snippets/04_02_feeds_and_activity_visibility.dart @@ -0,0 +1,30 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; + +Future feedVisibilityLevels() async { + // More options + const query = FeedQuery( + fid: FeedId(group: 'user', id: 'jack'), + data: FeedInputData( + visibility: FeedVisibility.public, + ), + ); + final feed = client.feedFromQuery(query); + await feed.getOrCreate(); +} + +Future activityVisibilityLevels() async { + // Premium users can see full activity, others a preview + final privateActivity = await feed.addActivity( + request: const FeedAddActivityRequest( + text: 'Premium content', + type: 'post', + visibility: AddActivityRequestVisibility.tag, + visibilityTag: 'premium', + ), + ); +} diff --git a/docs_code_snippets/04_03_follows.dart b/docs_code_snippets/04_03_follows.dart new file mode 100644 index 00000000..3824e3b6 --- /dev/null +++ b/docs_code_snippets/04_03_follows.dart @@ -0,0 +1,68 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late StreamFeedsClient saraClient; +late StreamFeedsClient adamClient; +late Feed feed; +late Feed timeline; + +Future followsAndUnfollows() async { + // Follow a user + final timeline = client.feed(group: 'timeline', id: 'john'); + await timeline.follow(targetFid: const FeedId(group: 'user', id: 'tom')); + // Follow a stock + await timeline.follow(targetFid: const FeedId(group: 'stock', id: 'apple')); + // Follow with more fields + await timeline.follow( + targetFid: const FeedId(group: 'stock', id: 'apple'), + custom: {'reason': 'investment'}, + ); +} + +Future queryFollows() async { + // Do I follow a list of feeds + // My feed is timeline:john + const followQuery = FollowsQuery( + filter: Filter.and([ + Filter.equal(FollowsFilterField.sourceFeed, 'timeline:john'), + Filter.in_(FollowsFilterField.targetFeed, ['user:sara', 'user:adam']), + ]), + ); + final followList = client.followList(followQuery); + final page1 = await followList.get(); + final page2 = await followList.queryMoreFollows(); + final page1And2 = followList.state.follows; + // Paginating through followers for a feed + // My feed is timeline:john + const followerQuery = FollowsQuery( + filter: Filter.equal(FollowsFilterField.targetFeed, 'timeline:john'), + ); + final followerList = client.followList(followerQuery); + final followerPage1 = await followerList.get(); +} + +Future followRequests() async { + // Sara needs to configure the feed with visibility = followers for enabling follow requests + const saraFeedQuery = FeedQuery( + fid: FeedId(group: 'user', id: 'sara'), + data: FeedInputData(visibility: FeedVisibility.followers), + ); + final saraFeed = saraClient.feedFromQuery(saraFeedQuery); + await saraFeed.getOrCreate(); + + // Adam requesting to follow the feed + final adamTimeline = adamClient.feed(group: 'timeline', id: 'adam'); + await adamTimeline.getOrCreate(); + final followRequest = + await adamTimeline.follow(targetFid: saraFeed.fid); // user:sara + print(followRequest.getOrNull()?.status); // .pending + // Sara accepting + await saraFeed.acceptFollow( + sourceFid: adamTimeline.fid, // timeline:adam + role: 'feed_member', // optional + ); + // or rejecting the request + await saraFeed.rejectFollow(sourceFid: adamTimeline.fid); // timeline:adam +} diff --git a/docs_code_snippets/05_01_intro_defaults.dart b/docs_code_snippets/05_01_intro_defaults.dart new file mode 100644 index 00000000..f46acc5c --- /dev/null +++ b/docs_code_snippets/05_01_intro_defaults.dart @@ -0,0 +1,25 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; +late Feed notificationFeed; + +Future notificationFeedExample() async { + final notificationFeed = client.feed(group: 'notification', id: 'john'); + await notificationFeed.getOrCreate(); +} + +Future markNotificationsAsRead() async { + await notificationFeed.markActivity( + request: const MarkActivityRequest( + // Mark all notifications as read... + markAllRead: true, + // ...or only selected ones + markRead: [ + // group names to mark as read + ], + ), + ); +} diff --git a/docs_code_snippets/05_02_feed_views.dart b/docs_code_snippets/05_02_feed_views.dart new file mode 100644 index 00000000..16311255 --- /dev/null +++ b/docs_code_snippets/05_02_feed_views.dart @@ -0,0 +1,15 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; + +Future whenToUseFeedViews() async { + const query = FeedQuery( + fid: FeedId(group: 'user', id: 'john'), + view: '', // Override the default view id + ); + final feed = client.feedFromQuery(query); + await feed.getOrCreate(); +} diff --git a/docs_code_snippets/05_06_notification_feeds.dart b/docs_code_snippets/05_06_notification_feeds.dart new file mode 100644 index 00000000..f750816b --- /dev/null +++ b/docs_code_snippets/05_06_notification_feeds.dart @@ -0,0 +1,78 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; +late Feed ericFeed; +late Feed janeFeed; +late Feed notificationFeed; +late Activity janeActivity; +late Activity saraComment; + +Future creatingNotificationActivities() async { +// Eric follows Jane + await ericFeed.follow( + targetFid: janeFeed.fid, + createNotificationActivity: + true, // When true Jane's notification feed will be updated with follow activity + ); +// Eric comments on Jane's activity + await ericFeed.addComment( + request: ActivityAddCommentRequest( + comment: 'Agree!', + activityId: janeActivity.activityId, + createNotificationActivity: + true, // When true Jane's notification feed will be updated with comment activity + ), + ); +// Eric reacts to Jane's activity + await ericFeed.addReaction( + activityId: janeActivity.activityId, + request: const AddReactionRequest( + type: 'like', + createNotificationActivity: + true, // When true Jane's notification feed will be updated with reaction activity + ), + ); +// Eric reacts to a comment posted to Jane's activity by Sara + await ericFeed.addCommentReaction( + commentId: saraComment.activityId, + request: const AddCommentReactionRequest( + type: 'like', + createNotificationActivity: + true, // When true Sara's notification feed will be updated with comment reaction activity + ), + ); +} + +Future readingNotificationActivities() async { + final notificationFeed = client.feed(group: 'notification', id: 'jane'); + final notifications = await notificationFeed.getOrCreate(); +} + +Future markNotificationsAsSeen() async { + await notificationFeed.markActivity( + request: const MarkActivityRequest( + // Mark all notifications as seen... + markAllSeen: true, + // ...or only selected ones + markSeen: [ + /* group names to mark as seen */ + ], + ), + ); +} + +Future markNotificationsAsRead() async { + await notificationFeed.markActivity( + request: const MarkActivityRequest( + // Mark all notifications as seen... + markAllRead: true, + // ...or only selected ones + markRead: [ + /* group names to mark as seen */ + ], + ), + ); +} diff --git a/docs_code_snippets/05_07_processors.dart b/docs_code_snippets/05_07_processors.dart new file mode 100644 index 00000000..8ebf006e --- /dev/null +++ b/docs_code_snippets/05_07_processors.dart @@ -0,0 +1,19 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; +late ActivityData activity; + +Future readingTopics() async { + await feed.addActivity( + request: const FeedAddActivityRequest( + text: 'check out my 10 fitness tips for reducing lower back pain', + type: 'post', + ), + ); + + // Wait for feeds.activity.updated event + print(activity.interestTags); // ["fitness", "health", "tips"] +} diff --git a/docs_code_snippets/06_01_reactions.dart b/docs_code_snippets/06_01_reactions.dart new file mode 100644 index 00000000..b0911cf8 --- /dev/null +++ b/docs_code_snippets/06_01_reactions.dart @@ -0,0 +1,24 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; + +Future overview() async { + // Add a reaction to an activity + final reaction = await feed.addReaction( + activityId: 'activity_123', + request: const AddReactionRequest(custom: {'emoji': '❤️'}, type: 'like'), + ); + // Remove a reaction + await feed.deleteReaction(activityId: 'activity_123', type: 'like'); +} + +Future overviewRead() async { + final feedData = await feed.getOrCreate(); +// Last 15 reactions on the first activity + print(feed.state.activities[0].latestReactions); +// Count of reactions by type + print(feed.state.activities[0].reactionGroups); +} diff --git a/docs_code_snippets/06_02_bookmarks.dart b/docs_code_snippets/06_02_bookmarks.dart new file mode 100644 index 00000000..aae81c70 --- /dev/null +++ b/docs_code_snippets/06_02_bookmarks.dart @@ -0,0 +1,82 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; + +Future addingBookmarks() async { +// Adding a bookmark to a new folder + final bookmark = await feed.addBookmark(activityId: 'activity_123'); +// Adding to an existing folder + final bookmarkWithFolder = await feed.addBookmark( + activityId: 'activity_123', + request: const AddBookmarkRequest(folderId: 'folder_456'), + ); +// Update a bookmark (without a folder initially) - add custom data and move it to a new folder + final updatedBookmark = await feed.updateBookmark( + activityId: 'activity_123', + request: const UpdateBookmarkRequest( + custom: {'color': 'blue'}, + newFolder: AddFolderRequest( + custom: {'icon': '📁'}, + name: 'New folder name', + ), + ), + ); +// Update a bookmark - move it from one existing folder to another existing folder + final movedBookmark = await feed.updateBookmark( + activityId: 'activity_123', + request: const UpdateBookmarkRequest( + folderId: 'folder_456', + newFolderId: 'folder_789', + ), + ); +} + +Future removingBookmarks() async { + // Removing a bookmark + await feed.deleteBookmark(activityId: 'activity_123', folderId: 'folder_456'); + // When you read a feed we include the bookmark + final feedData = await feed.getOrCreate(); + print(feed.state.activities[0].ownBookmarks); +} + +Future queryingBookmarks() async { + // Query bookmarks + const query = BookmarksQuery(limit: 5); + final bookmarkList = client.bookmarkList(query); + final page1 = await bookmarkList.get(); + // Get next page + final page2 = await bookmarkList.queryMoreBookmarks(limit: 3); + // Query by activity ID + final activityBookmarkList = client.bookmarkList( + const BookmarksQuery( + filter: Filter.equal(BookmarksFilterField.activityId, 'activity_123'), + ), + ); + final activityBookmarks = await activityBookmarkList.get(); + // Query by folder ID + final folderBookmarkList = client.bookmarkList( + const BookmarksQuery( + filter: Filter.equal(BookmarksFilterField.folderId, 'folder_456'), + ), + ); + final folderBookmarks = await folderBookmarkList.get(); +} + +Future queryingBookmarkFolders() async { + // Query bookmark folders + const query = BookmarkFoldersQuery(limit: 5); + final bookmarkFolderList = client.bookmarkFolderList(query); + final page1 = await bookmarkFolderList.get(); + // Get next page + final page2 = await bookmarkFolderList.queryMoreBookmarkFolders(limit: 3); + // Query by folder name (partial matching) + final projectFolderList = client.bookmarkFolderList( + const BookmarkFoldersQuery( + filter: Filter.contains(BookmarkFoldersFilterField.name, 'project'), + ), + ); + final projectFolders = await projectFolderList.get(); +} diff --git a/docs_code_snippets/06_03_comments.dart b/docs_code_snippets/06_03_comments.dart new file mode 100644 index 00000000..80d37deb --- /dev/null +++ b/docs_code_snippets/06_03_comments.dart @@ -0,0 +1,119 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; + +Future addingComments() async { +// Adding a comment to an activity + final comment = await feed.addComment( + request: const ActivityAddCommentRequest( + comment: 'So great!', + custom: {'sentiment': 'positive'}, + activityId: 'activity_123', + activityType: 'activity', + ), + ); +// Adding a reply to a comment + final reply = await feed.addComment( + request: const ActivityAddCommentRequest( + comment: 'I agree!', + activityId: 'activity_123', + activityType: 'activity', + parentId: 'comment_456', + ), + ); +} + +Future updatingComments() async { + // Updating a comment + final updatedComment = await feed.updateComment( + commentId: 'comment_123', + request: const UpdateCommentRequest( + comment: 'Not so great', + custom: {'edited': true}, + ), + ); +} + +Future removingComments() async { + await feed.deleteComment(commentId: 'comment_123'); +} + +Future readingComments() async { + await feed.getOrCreate(); + print(feed.state.activities[0].comments); + // or + final activity = client.activity( + fid: const FeedId(group: 'user', id: 'john'), + activityId: 'activity_123', + ); + await activity.get(); + print(activity.state.comments); +} + +Future queryingComments() async { + // Search in comment texts + final list1 = client.commentList( + const CommentsQuery( + filter: Filter.query(CommentsFilterField.commentText, 'oat'), + ), + ); + final comments1 = await list1.get(); + + // All comments for an activity + final list2 = client.commentList( + const CommentsQuery( + filter: Filter.and([ + Filter.equal(CommentsFilterField.objectId, 'activity_123'), + Filter.equal(CommentsFilterField.objectType, 'activity'), + ]), + ), + ); + final comments2 = await list2.get(); + + // Replies to a parent activity + final list3 = client.commentList( + const CommentsQuery( + filter: Filter.equal(CommentsFilterField.parentId, 'parent_id'), + ), + ); + final comments3 = await list3.get(); + + // Comments from an user + final list4 = client.commentList( + const CommentsQuery( + filter: Filter.equal(CommentsFilterField.userId, 'jane'), + ), + ); + final comments4 = await list4.get(); +} + +Future commentReactions() async { + // Add a reaction to a comment + await feed.addCommentReaction( + commentId: 'comment_123', + request: const AddCommentReactionRequest(type: 'like'), + ); + // Remove a reaction from a comment + await feed.deleteCommentReaction(commentId: 'comment_123', type: 'like'); +} + +Future commentThreading() async { + final commentList = client.activityCommentList( + const ActivityCommentsQuery( + objectId: 'activity_123', + objectType: 'activity', + depth: 3, + limit: 20, + ), + ); + final comments = await commentList.get(); + + // Get replies of a specific parent comment + final replyList = client.commentReplyList( + const CommentRepliesQuery(commentId: 'parent_123'), + ); + final replies = await replyList.get(); +} diff --git a/docs_code_snippets/06_04_pins.dart b/docs_code_snippets/06_04_pins.dart new file mode 100644 index 00000000..95481783 --- /dev/null +++ b/docs_code_snippets/06_04_pins.dart @@ -0,0 +1,23 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; + +Future overview() async { + final activity = client.activity( + activityId: 'activity_123', + fid: const FeedId(group: 'user', id: 'john'), + ); + // Pin an activity + await activity.pin(); + + // Unpin an activity + await activity.unpin(); +} + +Future overviewRead() async { + await feed.getOrCreate(); + print(feed.state.pinnedActivities); +} diff --git a/docs_code_snippets/07_01_state_layer.dart b/docs_code_snippets/07_01_state_layer.dart new file mode 100644 index 00000000..8ad1dfb5 --- /dev/null +++ b/docs_code_snippets/07_01_state_layer.dart @@ -0,0 +1 @@ +//TODO diff --git a/docs_code_snippets/08_01_events.dart b/docs_code_snippets/08_01_events.dart new file mode 100644 index 00000000..8ad1dfb5 --- /dev/null +++ b/docs_code_snippets/08_01_events.dart @@ -0,0 +1 @@ +//TODO diff --git a/docs_code_snippets/09_01_polls.dart b/docs_code_snippets/09_01_polls.dart new file mode 100644 index 00000000..495e7324 --- /dev/null +++ b/docs_code_snippets/09_01_polls.dart @@ -0,0 +1,160 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; +late Activity activity; + +Future creatingAPoll() async { + // Create a poll + final poll = await feed.createPoll( + request: const CreatePollRequest( + name: 'Where should we host our next company event?', + options: [ + PollOptionInput(text: 'Amsterdam, The Netherlands'), + PollOptionInput(text: 'Boulder, CO'), + ], + ), + activityType: 'poll', + ); + + // The poll is automatically added as an activity to the feed + print('Poll created with ID: ${poll.getOrThrow().id}'); +} + +Future pollOptions() async { + final poll = await feed.createPoll( + request: const CreatePollRequest( + custom: {'category': 'event_planning', 'priority': 'high'}, + name: 'Where should we host our next company event?', + options: [ + PollOptionInput( + custom: {'country': 'Netherlands', 'timezone': 'CET'}, + text: 'Amsterdam, The Netherlands', + ), + PollOptionInput( + custom: {'country': 'USA', 'timezone': 'MST'}, + text: 'Boulder, CO', + ), + ], + ), + activityType: 'poll', + ); +} + +Future sendVoteOnOption() async { + final activity = client.activity( + activityId: 'activity_123', + fid: const FeedId(group: 'user', id: 'test'), + ); + + final votes = await activity.castPollVote( + const CastPollVoteRequest(vote: VoteData(optionId: 'option_789')), + ); +} + +Future sendAnAnswer() async { + final votes = await activity.castPollVote( + const CastPollVoteRequest( + vote: VoteData(answerText: "Let's go somewhere else"), + ), + ); +} + +Future removingAVote() async { + final votes = await activity.deletePollVote(voteId: 'vote_789'); +} + +Future closingAPoll() async { + final poll = await activity.closePoll(); +} + +Future retrievingAPoll() async { + final poll = await activity.getPoll(); +} + +Future fullUpdate() async { + final updatedPoll = await activity.updatePoll( + const UpdatePollRequest( + id: 'poll_456', + name: 'Where should we not go to?', + options: [ + PollOptionRequest( + custom: {'reason': 'too expensive'}, + id: 'option_789', + text: 'Amsterdam, The Netherlands', + ), + PollOptionRequest( + custom: {'reason': 'too far'}, + id: 'option_790', + text: 'Boulder, CO', + ), + ], + ), + ); +} + +Future partialUpdate() async { + final updatedPoll = await activity.updatePollPartial( + const UpdatePollPartialRequest( + set: {'name': 'Updated poll name'}, + unset: ['custom_property'], + ), + ); +} + +Future deletingAPoll() async { + final poll = await activity.deletePoll(); +} + +Future addPollOption() async { + final pollOption = await activity.createPollOption( + const CreatePollOptionRequest( + custom: {'added_by': 'user_123'}, + text: 'Another option', + ), + ); +} + +Future updatePollOption() async { + final updatedPollOption = await activity.updatePollOption( + const UpdatePollOptionRequest( + custom: {'my_custom_property': 'my_custom_value'}, + id: 'option_789', + text: 'Updated option', + ), + ); +} + +Future deletePollOption() async { + final pollOption = await activity.deletePollOption(optionId: 'option_789'); +} + +Future queryingVotes() async { + // Retrieve all votes on either option1Id or option2Id + final pollVoteList = client.pollVoteList( + const PollVotesQuery( + pollId: 'poll_456', + filter: Filter.in_( + PollVotesFilterField.optionId, + ['option_789', 'option_790'], + ), + ), + ); + final votesPage1 = await pollVoteList.get(); + final votesPage2 = await pollVoteList.queryMorePollVotes(); + final votesPage1And2 = pollVoteList.state.votes; +} + +Future queryingPolls() async { + // Retrieve all polls that are closed for voting sorted by created_at + final pollList = client.pollList( + const PollsQuery( + filter: Filter.equal(PollsFilterField.isClosed, true), + ), + ); + final pollsPage1 = await pollList.get(); + final pollsPage2 = await pollList.queryMorePolls(); + final pollsPage1And2 = pollList.state.polls; +} diff --git a/docs_code_snippets/10_01_push_notifications.dart b/docs_code_snippets/10_01_push_notifications.dart new file mode 100644 index 00000000..8ad1dfb5 --- /dev/null +++ b/docs_code_snippets/10_01_push_notifications.dart @@ -0,0 +1 @@ +//TODO diff --git a/docs_code_snippets/11_01_moderation.dart b/docs_code_snippets/11_01_moderation.dart new file mode 100644 index 00000000..8d4ec670 --- /dev/null +++ b/docs_code_snippets/11_01_moderation.dart @@ -0,0 +1,125 @@ +// ignore_for_file: file_names, unused_local_variable, avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; + +late StreamFeedsClient client; +late Feed feed; +late String apiKey; +late User user; +late TokenProvider token; +late BanRequest banRequest; + +Future overview() async { + final client = + StreamFeedsClient(apiKey: apiKey, user: user, tokenProvider: token); + final moderation = client.moderation; +} + +Future banUsers() async { + const banRequest = BanRequest( + targetUserId: 'user-123', + reason: 'Violation of community guidelines', + timeout: 3600, // 1 hour in seconds + shadow: false, + ipBan: false, + ); + + final response = await client.moderation.ban(banRequest: banRequest); + print('User banned for: ${response.getOrThrow().duration}'); +} + +Future muteUsers() async { + const muteRequest = MuteRequest( + targetIds: ['user-123', 'user-456'], + timeout: 86400, // 24 hours in seconds + ); + + final response = await client.moderation.mute(muteRequest: muteRequest); +} + +Future blockUsers() async { + const blockRequest = BlockUsersRequest(blockedUserId: 'user-123'); + final response = + await client.moderation.blockUsers(blockUsersRequest: blockRequest); +} + +Future unblockUsers() async { + const unblockRequest = UnblockUsersRequest(blockedUserId: 'user-123'); + final response = + await client.moderation.unblockUsers(unblockUsersRequest: unblockRequest); +} + +Future getBlockedUsers() async { + final blockedUsers = await client.moderation.getBlockedUsers(); + for (final user in blockedUsers.getOrThrow().blocks) { + print('Blocked user: ${user.blockedUserId}'); + } +} + +Future flagContent() async { + const flagRequest = FlagRequest( + entityId: 'activity-123', + entityType: 'activity', + reason: 'Inappropriate content', + entityCreatorId: 'user-456', + ); + + final response = await client.moderation.flag(flagRequest: flagRequest); +} + +Future submitModerationActions() async { + const actionRequest = SubmitActionRequest( + // Action details for moderation + actionType: SubmitActionRequestActionType.ban, + itemId: 'user-123', + ); + + final response = + await client.moderation.submitAction(submitActionRequest: actionRequest); +} + +Future queryReviewQueue() async { + const queryRequest = QueryReviewQueueRequest( + // Query parameters for filtering and pagination + ); + + final reviewQueue = await client.moderation + .queryReviewQueue(queryReviewQueueRequest: queryRequest); +} + +Future upsertModerationConfig() async { + const upsertRequest = UpsertConfigRequest( + key: 'feeds', + // Configuration details for moderation + ); + + final response = await client.moderation.upsertConfig(upsertRequest); +} + +Future getModerationConfig() async { + final config = await client.moderation.getConfig(key: 'feeds'); +} + +Future deleteModerationConfig() async { + final response = await client.moderation.deleteConfig(key: 'feeds'); +} + +Future queryModerationConfigs() async { + const queryRequest = ModerationConfigsQuery( + // Query parameters for filtering and pagination + ); + + final configs = await client.moderation + .queryModerationConfigs(queryModerationConfigsRequest: queryRequest); +} + +Future errorHandling() async { + final response = await client.moderation.ban(banRequest: banRequest); + + switch (response) { + case Success(data: final banResponse): + print('User banned for: ${banResponse.duration}'); + case Failure(error: final error): + print('Error banning user: $error'); + } +} diff --git a/packages/stream_feeds/lib/src/client/moderation_client.dart b/packages/stream_feeds/lib/src/client/moderation_client.dart index 922c7aba..0d1c3df4 100644 --- a/packages/stream_feeds/lib/src/client/moderation_client.dart +++ b/packages/stream_feeds/lib/src/client/moderation_client.dart @@ -1,5 +1,6 @@ import 'package:stream_core/stream_core.dart'; +import '../../stream_feeds.dart' show ModerationConfigsQuery; import '../generated/api/api.dart' as api; import '../repository/moderation_repository.dart'; @@ -41,7 +42,7 @@ class ModerationClient { /// Prohibits the user specified in [banRequest] from accessing platform features. /// /// Returns a [Result] containing a [api.BanResponse] or an error. - Future> ban(api.BanRequest banRequest) { + Future> ban({required api.BanRequest banRequest}) { return _moderationRepository.ban(banRequest); } @@ -50,30 +51,32 @@ class ModerationClient { /// Restricts communication for the users specified in [muteRequest]. /// /// Returns a [Result] containing a [api.MuteResponse] or an error. - Future> mute(api.MuteRequest muteRequest) { + Future> mute({ + required api.MuteRequest muteRequest, + }) { return _moderationRepository.mute(muteRequest); } /// Blocks a user. /// - /// Prevents interaction with the user specified in [blockUserRequest]. + /// Prevents interaction with the user specified in [blockUsersRequest]. /// /// Returns a [Result] containing a [api.BlockUsersResponse] or an error. - Future> blockUser( - api.BlockUsersRequest blockUserRequest, - ) { - return _moderationRepository.blockUsers(blockUserRequest); + Future> blockUsers({ + required api.BlockUsersRequest blockUsersRequest, + }) { + return _moderationRepository.blockUsers(blockUsersRequest); } /// Unblocks a user. /// - /// Restores interaction capabilities with the user specified in [unblockUserRequest]. + /// Restores interaction capabilities with the user specified in [unblockUsersRequest]. /// /// Returns a [Result] containing a [api.UnblockUsersResponse] or an error. - Future> unblockUser( - api.UnblockUsersRequest unblockUserRequest, - ) { - return _moderationRepository.unblockUsers(unblockUserRequest); + Future> unblockUsers({ + required api.UnblockUsersRequest unblockUsersRequest, + }) { + return _moderationRepository.unblockUsers(unblockUsersRequest); } /// Gets the list of blocked users. @@ -90,7 +93,9 @@ class ModerationClient { /// Reports inappropriate content specified in [flagRequest] for review. /// /// Returns a [Result] containing a [api.FlagResponse] or an error. - Future> flag(api.FlagRequest flagRequest) { + Future> flag({ + required api.FlagRequest flagRequest, + }) { return _moderationRepository.flag(flagRequest); } @@ -99,9 +104,9 @@ class ModerationClient { /// Executes a moderation decision using the data in [submitActionRequest]. /// /// Returns a [Result] containing a [api.SubmitActionResponse] or an error. - Future> submitAction( - api.SubmitActionRequest submitActionRequest, - ) { + Future> submitAction({ + required api.SubmitActionRequest submitActionRequest, + }) { return _moderationRepository.submitAction(submitActionRequest); } @@ -110,9 +115,9 @@ class ModerationClient { /// Retrieves pending moderation items using the specified [queryReviewQueueRequest] filters and pagination. /// /// Returns a [Result] containing a [api.QueryReviewQueueResponse] or an error. - Future> queryReviewQueue( - api.QueryReviewQueueRequest queryReviewQueueRequest, - ) { + Future> queryReviewQueue({ + required api.QueryReviewQueueRequest queryReviewQueueRequest, + }) { return _moderationRepository.queryReviewQueue(queryReviewQueueRequest); } @@ -132,8 +137,8 @@ class ModerationClient { /// Removes the configuration identified by [key] and optional [team]. /// /// Returns a [Result] containing a [api.DeleteModerationConfigResponse] or an error. - Future> deleteConfig( - String key, { + Future> deleteConfig({ + required String key, String? team, }) { return _moderationRepository.deleteConfig(key, team: team); @@ -144,10 +149,22 @@ class ModerationClient { /// Retrieves the configuration identified by [key] and optional [team]. /// /// Returns a [Result] containing a [api.GetConfigResponse] or an error. - Future> getConfig( - String key, { + Future> getConfig({ + required String key, String? team, }) { return _moderationRepository.getConfig(key, team: team); } + + /// Queries the moderation configurations. + /// + /// Retrieves moderation configurations using the specified [queryModerationConfigsRequest] filters and pagination. + /// + /// Returns a [Result] containing a [api.QueryModerationConfigsResponse] or an error. + Future queryModerationConfigs({ + required ModerationConfigsQuery queryModerationConfigsRequest, + }) { + return _moderationRepository + .queryModerationConfigs(queryModerationConfigsRequest); + } } diff --git a/packages/stream_feeds/lib/src/state.dart b/packages/stream_feeds/lib/src/state.dart index 957fea95..f2c748bb 100644 --- a/packages/stream_feeds/lib/src/state.dart +++ b/packages/stream_feeds/lib/src/state.dart @@ -1,6 +1,20 @@ export 'state/activity.dart'; +export 'state/activity_comment_list.dart'; +export 'state/comment_list.dart'; +export 'state/comment_reaction_list.dart'; +export 'state/comment_reply_list.dart'; export 'state/feed.dart'; export 'state/feed_state.dart'; export 'state/query/activities_query.dart'; +export 'state/query/activity_comments_query.dart'; +export 'state/query/bookmark_folders_query.dart'; +export 'state/query/bookmarks_query.dart'; +export 'state/query/comment_reactions_query.dart'; +export 'state/query/comment_replies_query.dart'; +export 'state/query/comments_query.dart'; export 'state/query/feed_query.dart'; export 'state/query/feeds_query.dart'; +export 'state/query/follows_query.dart'; +export 'state/query/moderation_configs_query.dart'; +export 'state/query/poll_votes_query.dart'; +export 'state/query/polls_query.dart'; diff --git a/packages/stream_feeds/lib/src/state/activity.dart b/packages/stream_feeds/lib/src/state/activity.dart index fd588d77..fa63efcd 100644 --- a/packages/stream_feeds/lib/src/state/activity.dart +++ b/packages/stream_feeds/lib/src/state/activity.dart @@ -338,7 +338,7 @@ class Activity with Disposable { /// Deletes a poll option by its ID. /// /// Returns a [Result] containing void or an error. - Future> deletePollOption(String optionId) async { + Future> deletePollOption({required String optionId}) async { final pollIdResult = await _pollId(); final result = await pollIdResult.flatMapAsync((pollId) { return pollsRepository.deletePollOption(pollId, optionId); @@ -390,7 +390,7 @@ class Activity with Disposable { /// Deletes a poll vote by its ID. /// /// Returns a [Result] containing the deleted [PollVoteData] or an error. - Future> deletePollVote(String voteId) async { + Future> deletePollVote({required String voteId}) async { final pollIdResult = await _pollId(); final result = await pollIdResult.flatMapAsync((pollId) { return pollsRepository.deletePollVote(activityId, pollId, voteId); diff --git a/pubspec.yaml b/pubspec.yaml index 9d9dc17f..d68427ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,13 +5,13 @@ environment: dependencies: flutter_state_notifier: ^1.0.0 - stream_feeds: - path: ./packages/stream_feeds stream_core: git: url: https://github.com/GetStream/stream-core-flutter.git ref: 280b1045e39388668fd060439259831611b51b5a path: packages/stream_core + stream_feeds: + path: ./packages/stream_feeds dev_dependencies: melos: ^6.2.0 diff --git a/sample_app/lib/navigation/app_router.gr.dart b/sample_app/lib/navigation/app_router.gr.dart index 08d870c2..15d3e3e9 100644 --- a/sample_app/lib/navigation/app_router.gr.dart +++ b/sample_app/lib/navigation/app_router.gr.dart @@ -14,7 +14,7 @@ part of 'app_router.dart'; /// [ChooseUserScreen] class ChooseUserRoute extends PageRouteInfo { const ChooseUserRoute({List? children}) - : super(ChooseUserRoute.name, initialChildren: children); + : super(ChooseUserRoute.name, initialChildren: children); static const String name = 'ChooseUserRoute'; @@ -30,7 +30,7 @@ class ChooseUserRoute extends PageRouteInfo { /// [HomeScreen] class HomeRoute extends PageRouteInfo { const HomeRoute({List? children}) - : super(HomeRoute.name, initialChildren: children); + : super(HomeRoute.name, initialChildren: children); static const String name = 'HomeRoute'; @@ -46,7 +46,7 @@ class HomeRoute extends PageRouteInfo { /// [UserFeedScreen] class UserFeedRoute extends PageRouteInfo { const UserFeedRoute({List? children}) - : super(UserFeedRoute.name, initialChildren: children); + : super(UserFeedRoute.name, initialChildren: children); static const String name = 'UserFeedRoute'; diff --git a/sample_app/lib/screens/user_feed/comment/user_comments_item.dart b/sample_app/lib/screens/user_feed/comment/user_comments_item.dart index 095455c0..b650d5ef 100644 --- a/sample_app/lib/screens/user_feed/comment/user_comments_item.dart +++ b/sample_app/lib/screens/user_feed/comment/user_comments_item.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_positional_boolean_parameters + import 'package:flutter/material.dart'; import 'package:stream_feeds/stream_feeds.dart'; diff --git a/sample_app/pubspec.yaml b/sample_app/pubspec.yaml index faa1e169..8315d48b 100644 --- a/sample_app/pubspec.yaml +++ b/sample_app/pubspec.yaml @@ -11,15 +11,15 @@ dependencies: auto_route: ^10.0.0 cached_network_image: ^3.4.1 collection: ^1.18.0 + file_picker: ^8.1.4 flex_color_scheme: ^8.1.1 + flex_grid_view: ^0.1.0 flutter: sdk: flutter flutter_state_notifier: ^1.0.0 flutter_svg: ^2.2.0 get_it: ^8.0.3 google_fonts: ^6.3.0 - file_picker: ^8.1.4 - flex_grid_view: ^0.1.0 injectable: ^2.5.1 jiffy: ^6.3.2 shared_preferences: ^2.5.3