Stream Feed official Flutter SDK. Build your own feed experience using Dart and Flutter.

Overview

Official Flutter packages for Stream Activity Feeds

The official Dart client for Stream Activity Feeds, a service for building activity feed applications. This library can be used on any Dart project and on both mobile and web apps with Flutter. You can sign up for a Stream account at https://getstream.io/get_started.

Pub Build status codecov melos

Stream Feed Activity Feed cover image

๐Ÿ”— Quick Links

  • Register to get an API key for Stream Activity Feeds
  • Tutorial to learn how to setup a timeline feed, follow other feeds and post new activities.
  • Stream Activity Feeds UI Kit to jumpstart your design with notifications and social feeds

๐Ÿ›  Installation

Install from pub

Next step is to add stream_feed to your dependencies, to do that just open pubspec.yaml and add it inside the dependencies section.

dependencies:
  flutter:
    sdk: flutter

  stream_feed: ^[latest-version]

Using with Flutter

This package can be integrated into Flutter applications. Remember to not expose the App Secret in your Flutter web apps, mobile apps, or other non-trusted environments like desktop apps.

๐Ÿ”Œ Usage

API client setup Serverside + Clientside

If you want to use the API client directly on your web/mobile app you need to generate a user token server-side and pass it.

Server-side token generation

// Instantiate a new client (server side)
const apiKey = 'my-API-key';
const secret = 'my-API-secret';

// Instantiate a new client (server side)
var client = StreamFeedClient(apiKey, secret: secret);

// Optionally supply the app identifier and an options object specifying the data center to use and timeout for requests (15s)
client = StreamFeedClient(apiKey,
      secret: secret,
      appId: 'yourappid',
      options: StreamHttpClientOptions(
          location: Location.usEast, connectTimeout: Duration(seconds: 15)));

// Create a token for user with id "the-user-id"
final userToken = client.frontendToken('the-user-id');

โš ๏ธ for security, you must never expose your API secret or generated client side token, and it's highly recommended to use exp claim in client side token.

Client API init

// Instantiate new client with a user token
var client = StreamFeedClient(apiKey, token: Token('userToken'));

๐Ÿ”ฎ Examples

// Instantiate a feed object server side
var user1 = client.flatFeed('user', '1');

// Get activities from 5 to 10 (slow pagination)
final activities = await user1.getActivities(limit: 5, offset: 5);
// Filter on an id less than a given UUID
final filtered_activities = await user1.getActivities(
      limit: 5,
      filter: Filter().idLessThan('e561de8f-00f1-11e4-b400-0cc47a024be0')

// All API calls are performed asynchronous and return a Promise object
await user1
    .getActivities(
        limit: 5,
        filter: Filter().idLessThan('e561de8f-00f1-11e4-b400-0cc47a024be0'))
    .then((value) => /* on success */
        print(value))
    .onError((error,
              stackTrace) => /* on failure, reason.error contains an explanation */
        print(error));

// Create a new activity
final activity = Activity( actor: '1', verb: 'tweet', object: '1', foreignId: 'tweet:1' );
final added_activity = await user1.addActivity(activity);
// Create a bit more complex activity
final complex_activity = Activity(
    actor: '1',
    verb: 'run',
    object: '1',
    foreignId: 'run:1',
    extraData: {
      'course': {'name': 'Golden Gate park', 'distance': 10},
      'participants': ['Thierry', 'Tommaso'],
      'started_at': DateTime.now().toIso8601String(),
    },
  );
final added_complex_activity = await user1.addActivity(complex_activity);

// Remove an activity by its id
await user1.removeActivityById('e561de8f-00f1-11e4-b400-0cc47a024be0');
// or remove by the foreign id
await user1.removeActivityByForeignId('tweet:1');

// mark a notification feed as read
await notification1.getActivities(
  marker: ActivityMarker().allRead(),
);


// mark a notification feed as seen
await notification1.getActivities(
  marker: ActivityMarker().allSeen(),
);

// Follow another feed
await user1.follow(client.flatFeed('flat', '42'));

// Stop following another feed
await user1.unfollow(client.flatFeed('flat', '42'));

// Stop following another feed while keeping previously published activities
// from that feed
await user1.unfollow(client.flatFeed('flat', '42'), keepHistory: true);

// Follow another feed without copying the history
await user1.follow(client.flatFeed('flat', '42'), activityCopyLimit: 0);

// List followers, following
await user1.getFollowers(limit: 10, offset: 10);
await user1.getFollowed(limit: 10, offset: 0);


await user1.follow(client.flatFeed('flat', '42'));

// adding multiple activities
const activities = [
  Activity(actor: '1', verb: 'tweet', object: '1'),
  Activity(actor: '2', verb: 'tweet', object: '3'),
];
await user1.addActivities(activities);

// specifying additional feeds to push the activity to using the to param
// especially useful for notification style feeds
final to = FeedId.fromIds(['user:2', 'user:3']);
final activityTo = Activity(
  to: to,
  actor: '1',
  verb: 'tweet',
  object: '1',
  foreignId: 'tweet:1',
);
await user1.addActivity(activityTo);


// adding one activity to multiple feeds
final feeds = FeedId.fromIds(['flat:1', 'flat:2', 'flat:3', 'flat:4']);
final activityTarget = Activity(
  actor: 'User:2',
  verb: 'pin',
  object: 'Place:42',
  target: 'Board:1',
);

// โš ๏ธ server-side only!
await client.batch.addToMany(activityTarget, feeds!);

// Batch create follow relations (let flat:1 follow user:1, user:2 and user:3 feeds in one single request)
const follows = [
  FollowRelation(source: 'flat:1', target: 'user:1'),
  FollowRelation(source:'flat:1', target: 'user:2'),
  FollowRelation(source:'flat:1', target: 'user:3'),
];

// โš ๏ธ server-side only!
await client.batch.followMany(follows);

// Updating parts of an activity
final set = {
  'product.price': 19.99,
  shares: {
    facebook: '...',
    twitter: '...',
  },
};
final unset = ['daily_likes', 'popularity'];

// ...by ID
final update = ActivityUpdate.withId( '54a60c1e-4ee3-494b-a1e3-50c06acb5ed4', set, unset);
await client.updateActivityById(update);
// ...or by combination of foreign ID and time
const timestamp = DateTime.now();
const foreignID= 'product:123';
final update2 = ActivityUpdate.withForeignId(
  foreignID,
  timestamp,
  set,
  unset,
);
await client.updateActivityById(update2);


// update the 'to' fields on an existing activity
// client.flatFeed("user", "ken").function (foreign_id, timestamp, new_targets, added_targets, removed_targets)
// new_targets, added_targets, and removed_targets are all arrays of feed IDs
// either provide only the `new_targets` parameter (will replace all targets on the activity),
// OR provide the added_targets and removed_targets parameters
// NOTE - the updateActivityToTargets method is not intended to be used in a browser environment.
await client.flatFeed('user', 'ken').updateActivityToTargets('foreign_id:1234', timestamp, ['feed:1234']);
await client.flatFeed('user', 'ken').updateActivityToTargets('foreign_id:1234', timestamp, null, ['feed:1234']);
await client.flatFeed('user', 'ken').updateActivityToTargets('foreign_id:1234', timestamp, null, null, ['feed:1234']);

Realtime (Faye)

Stream uses Faye for realtime notifications. Below is quick guide to subscribing to feed changes

// โš ๏ธ userToken is generated server-side (see previous section)
final client = StreamFeedClient('YOUR_API_KEY', token: userToken,appId: 'APP_ID');
final user1 = client.flatFeed('user', '1');

// subscribe to the changes
final subscription = await userFeed.subscribe((message) => print(message));
// now whenever something changes to the feed user 1
// the callback will be called

// To cancel a subscription you can call cancel on the
// object returned from a subscribe call.
// This will remove the listener from this channel.
await subscription.cancel();

Docs are available on GetStream.io.

Free for Makers

Stream is free for most side and hobby projects. To qualify your project/company needs to have < 5 team members and < $10k in monthly revenue. For complete pricing details visit our Feed Pricing Page

Structure

Stream Feed Dart is a monorepo built using Melos. Individual packages can be found in the packages directory while configuration and top level commands can be found in melos.yaml.

To get started, run bootstrap after cloning the project.

melos bootstrap

Dart version requirements

This API Client project requires Dart v2.12 at a minimum.

See the github action configuration for details of how it is built, tested and packaged.

Contributing

See extensive at test documentation for your changes.

You can find generic API documentation enriched by code snippets from this package at https://getstream.io/activity-feeds/docs/flutter-dart/?language=dart

Copyright and License Information

Project is licensed under the BSD 3-Clause.

We are hiring

We've recently closed a $38 million Series B funding round and we keep actively growing. Our APIs are used by more than a billion end-users, and you'll have a chance to make a huge impact on the product within a team of the strongest engineers all over the world.

Check out our current openings and apply via Stream's website.

Comments
  • Getting Current Stream User Issue

    Getting Current Stream User Issue

    Describe the bug A clear and concise description of what the bug is. When calling widget.streamClient.currentUser It returns null. It worked before switching to the lastest version. I have tried all sorts of ways to set the user but the issue reamins. What version of Flutter do you use? 2.5.3

    What package are you using? What version? 0.4.0

    What platform is it about?

    • [x] Android
    • [x] iOS
    • [ ] Web
    • [ ] Windows
    • [ ] MacOS
    • [ ] Linux
    bug 
    opened by rlee1990 22
  • Better Pagination Support

    Better Pagination Support

    It would be nice to get the feed items with a page number and a max page number when we get activities so we can know when the last page is showing and to not try and fetch more pages.

    enhancement 
    opened by rlee1990 20
  • EnrichedActivity Not Returning Reactions

    EnrichedActivity Not Returning Reactions

    I am not sure what is happening. I add a reaction like so:

    widget.streamClient.reactions
                          .add('like', widget.post.id,
                              userId: widget.streamClient.currentUser.userId,
                              data: {
                                'value': index,
                              });
    

    Then I get the enriched activities like so:

     timeline
            .getEnrichedActivities(
                limit: 100,
                offset: 0,
                flags: EnrichmentFlags()
                    .withReactionCounts()
                    .withOwnReactions()
                    .withRecentReactions())
    

    It will return the activities but not any reactions it's like they do not get updated even though I get a return value.

    I/flutter (29491): *** Request ***
    I/flutter (29491): uri: https://api.stream-io-api.com/api/v1.0/reaction/?api_key=hmwext26344q&location=unspecified
    I/flutter (29491): method: POST
    I/flutter (29491): responseType: ResponseType.json
    I/flutter (29491): followRedirects: true
    I/flutter (29491): connectTimeout: 10000
    I/flutter (29491): sendTimeout: 0
    I/flutter (29491): receiveTimeout: 10000
    I/flutter (29491): receiveDataWhenStatusError: true
    I/flutter (29491): extra: {}
    I/flutter (29491): headers:
    I/flutter (29491):  stream-auth-type: jwt
    I/flutter (29491):  x-stream-client: stream-feed-dart-client-android-0.1.2
    I/flutter (29491):  Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMEFKWmZVT1Rxb1hMOHlCeVhZODZUYzBMS3VsMnBlcnNvbmFsIn0.YnnMv2ApNpKPdh6aBCQm9hlB-W7C0DDyuzAMO2g61IA
    I/flutter (29491):  content-type: application/json; charset=utf-8
    I/flutter (29491): data:
    I/flutter (29491): Reaction(null, like, bc1118f0-b2d2-11eb-8c76-1254437355c5, 0AJZfUOTqoXL8yByXY86Tc0LKul2personal, null, null, null, null, null, null, {value: 4}, null, null)
    I/flutter (29491):
    I/flutter (29491): *** Response ***
    I/flutter (29491): uri: https://api.stream-io-api.com/api/v1.0/reaction/?api_key=hmwext26344q&location=unspecified
    I/flutter (29491): statusCode: 201
    I/flutter (29491): headers:
    I/flutter (29491):  connection: keep-alive
    I/flutter (29491):  cache-control: no-cache
    I/flutter (29491):  date: Wed, 12 May 2021 19:14:05 GMT
    I/flutter (29491):  access-control-allow-origin: *
    I/flutter (29491):  x-ratelimit-limit: 1000
    I/flutter (29491):  x-ratelimit-reset: 1620846900
    I/flutter (29491):  x-ratelimit-remaining: 999
    I/flutter (29491):  content-type: application/json;charset=utf-8
    I/flutter (29491):  access-control-max-age: 86400
    I/flutter (29491):  server: nginx
    I/flutter (29491):  access-control-allow-headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken, x-stream-client, stream-auth-type
    I/flutter (29491):  access-control-allow-methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
    I/flutter (29491):  content-length: 691
    I/flutter (29491): Response Text:
    I/flutter (29491): {"created_at":"2021-05-12T19:14:05.323360Z","updated_at":"2021-05-12T19:14:05.323360Z","id":"e95a85d0-b44b-4017-9fcd-cfae75d62d90","user_id":"0AJZfUOTqoXL8yByXY86Tc0LKul2personal","user":{"created_at":"2021-04-13T23:04:05.306176Z","updated_at":"2021-04-13T23:04:05.306176Z","id":"0AJZfUOTqoXL8yByXY86Tc0LKul2personal","data":{"gender":"Female","name":"jane doe","photo":"https://firebasestorage.googleapis.com/v0/b/fire-snab.appspot.com/o/profile-image-placeholder.png?alt=media&token=b17598bb-a510-4167-8354-ab75642ba89e"}},"kind":"like","activity_id":"bc1118f0-b2d2-11eb-8c76-1254437355c5","data":{"value":4},"parent":"","latest_children":{},"children_counts":{},"duration":"5.79ms"}
    I/flutter (29491):
    I/flutter (29491): Reaction(e95a85d0-b44b-4017-9fcd-cfae75d62d90, like, bc1118f0-b2d2-11eb-8c76-1254437355c5, 0AJZfUOTqoXL8yByXY86Tc0LKul2personal, , 2021-05-12 19:14:05.323360Z, 2021-05-12 19:14:05.323360Z, null, {created_at: 2021-04-13T23:04:05.306176Z, updated_at: 2021-04-13T23:04:05.306176Z, id: 0AJZfUOTqoXL8yByXY86Tc0LKul2personal, data: {gender: Female, name: jane doe, photo: https://firebasestorage.googleapis.com/v0/b/fire-snab.appspot.com/o/profile-image-placeholder.png?alt=media&token=b17598bb-a510-4167-8354-ab75642ba89e}}, null, {value: 4}, {}, {})
    
    bug 
    opened by rlee1990 19
  • Getting Following Feeds

    Getting Following Feeds

    When I try to get the feeds that the current user is following I get null trying to access the data. If you look at the response from the request it shows there is indeed data but using value[0].target or value[0] each returns null.

    I/flutter (17428): *** Request ***
    I/flutter (17428): uri: https://api.stream-io-api.com/api/v1.0/feed/timeline/Prhia3HUNgPesoCjkaEdEUPuOWZ2personal/following?limit=100&offset=0&api_key=hmwext26344q&location=unspecified
    I/flutter (17428): method: GET
    I/flutter (17428): responseType: ResponseType.json
    I/flutter (17428): followRedirects: true
    I/flutter (17428): connectTimeout: 10000
    I/flutter (17428): sendTimeout: 0
    I/flutter (17428): receiveTimeout: 10000
    I/flutter (17428): receiveDataWhenStatusError: true
    I/flutter (17428): extra: {}
    I/flutter (17428): headers:
    I/flutter (17428):  stream-auth-type: jwt
    I/flutter (17428):  x-stream-client: stream-feed-dart-client-android-0.1.3
    I/flutter (17428):  Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiUHJoaWEzSFVOZ1Blc29DamthRWRFVVB1T1daMnBlcnNvbmFsIn0.L8Yu4YxwCb4JykadVwlwTJyidBhIerqGpWn1LAK0Sj4
    I/flutter (17428): data:
    I/flutter (17428): null
    I/flutter (17428):
    I/flutter (17428): *** Response ***
    I/flutter (17428): uri: https://api.stream-io-api.com/api/v1.0/feed/timeline/Prhia3HUNgPesoCjkaEdEUPuOWZ2personal/following?limit=100&offset=0&api_key=hmwext26344q&location=unspecified
    I/flutter (17428): statusCode: 200
    I/flutter (17428): headers:
    I/flutter (17428):  connection: keep-alive
    I/flutter (17428):  cache-control: no-cache
    I/flutter (17428):  x-ratelimit-reset: 1621443000
    I/flutter (17428):  date: Wed, 19 May 2021 16:49:38 GMT
    I/flutter (17428):  access-control-allow-origin: *
    I/flutter (17428):  x-ratelimit-limit: 500
    I/flutter (17428):  content-encoding: gzip
    I/flutter (17428):  x-ratelimit-remaining: 499
    I/flutter (17428):  content-type: application/json;charset=utf-8
    I/flutter (17428):  access-control-max-age: 86400
    I/flutter (17428):  server: nginx
    I/flutter (17428):  access-control-allow-headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken, x-stream-client, stream-auth-type
    I/flutter (17428):  access-control-allow-methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
    I/flutter (17428):  content-length: 192
    I/flutter (17428): Response Text:
    I/flutter (17428): {"results":[{"feed_id":"timeline:Prhia3HUNgPesoCjkaEdEUPuOWZ2personal","target_id":"user:WPpmnSSN1uURXNODPak2rlsCV332personal","created_at":"2021-05-14T19:58:27.274792063Z","updated_at":"2021-05-14T19:58:27.274792063Z"}],"duration":"1.62ms"}
    I/flutter (17428):
    I/flutter (17428): Following: Follow(null, null)
    
    bug 
    opened by rlee1990 15
  • Respost Issue

    Respost Issue

    I have a question. I am trying to do a repost/share as Facebook and Twitter do but when I use the code below I have issues. The activity is not copied to the target feed just the reaction does and not even the data that is added to the reaction.

    streamClient!.reactions.add(
                                                  'share', widget.post.id!,
                                                  userId: streamClient
                                                      .currentUser!.userId,
                                                  data: {
                                                    'id': widget.post.id!,
                                                  },
                                                  targetFeeds: [
                                                    feed.FeedId(
                                                        'user',
                                                        streamClient
                                                            .currentUser!.userId)
                                                  ]);
    
    question 
    opened by rlee1990 14
  • Subscribing to the feed throws exception and doesn't show a message

    Subscribing to the feed throws exception and doesn't show a message

    Describe the bug When the user subscribes to the feed, if there is a new event, it throws an error. Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String?' in type cast

    What version of Flutter do you use? Flutter (Channel stable, 2.2.1, on macOS 11.2.3 20D91 darwin-x64, locale en-TR)

    What package are you using? What version? stream_feed: ^0.2.1

    What platform is it about? Only tested on

    • [x] MacOS

    a copy of flutter doctor --verbose

    [โœ“] Flutter (Channel stable, 2.2.1, on macOS 11.2.3 20D91 darwin-x64, locale en-TR)
        โ€ข Flutter version 2.2.1 at /Users/salih/Desktop/flutter
        โ€ข Framework revision 02c026b03c (13 days ago), 2021-05-27 12:24:44 -0700
        โ€ข Engine revision 0fdb562ac8
        โ€ข Dart version 2.13.1
    
    [!] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
        โ€ข Android SDK at /Users/salih/Library/Android/sdk
        โ€ข Platform android-30, build-tools 30.0.2
        โ€ข Java binary at: /Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home/bin/java
        โ€ข Java version Java(TM) SE Runtime Environment (build 15.0.1+9-18)
        โœ— Android license status unknown.
          Run `flutter doctor --android-licenses` to accept the SDK licenses.
          See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
    
    [โœ“] Xcode - develop for iOS and macOS
        โ€ข Xcode at /Applications/Xcode.app/Contents/Developer
        โ€ข Xcode 12.5, Build version 12E262
        โ€ข CocoaPods version 1.10.1
    
    [โœ“] Chrome - develop for the web
        โ€ข Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [!] Android Studio
        โ€ข Android Studio at /Users/salih/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/203.7717.56.2111.7361063/Android Studio Preview.app/Contents
        โ€ข Flutter plugin can be installed from:
          ๐Ÿ”จ https://plugins.jetbrains.com/plugin/9212-flutter
        โ€ข Dart plugin can be installed from:
          ๐Ÿ”จ https://plugins.jetbrains.com/plugin/6351-dart
        โœ— Unable to find bundled Java version.
        โ€ข Try updating or re-installing Android Studio.
    
    [โœ“] IntelliJ IDEA Ultimate Edition (version 2021.1.2)
        โ€ข IntelliJ at /Users/salih/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
        โ€ข Flutter plugin version 57.0.5
        โ€ข Dart plugin version 211.7233
    
    [โœ“] VS Code (version 1.56.2)
        โ€ข VS Code at /Applications/Visual Studio Code.app/Contents
        โ€ข Flutter extension version 3.23.0
    
    [โœ“] Connected device (2 available)
        โ€ข macOS (desktop) โ€ข macos  โ€ข darwin-x64     โ€ข macOS 11.2.3 20D91 darwin-x64
        โ€ข Chrome (web)    โ€ข chrome โ€ข web-javascript โ€ข Google Chrome 91.0.4472.77
    

    To Reproduce

    1. Run the following code
     final _streamFeedClient = StreamFeedClient.connect(
       <api-key>
        token: token,
        appId: <appId>,
      );
      final feed = _streamFeedClient.notificationFeed('user', userId);
      final activity = Activity(
        actor: createUserReference(userId),
        verb: 'created',
        object: 'created',
        time: DateTime.now(),
        extraData: {
          "createdTask": task.toJson(),
        },
      );
      feed.addActivity(activity);
      feed.subscribe((message) {
        print('message in a bottle $message');
      });
    
    1. Add a new activity to the feed.

    Expected behavior It should print "message in a bottle" with a message variable.

    **Logs **

    flutter: *** Request ***
    flutter: uri: https://api.stream-io-api.com/api/v1.0/feed/task/32db0f46-3593-4e14-aa57-f05af4887260/?api_key=yn6bquc5zs6m&location=unspecified
    flutter: method: POST
    flutter: responseType: ResponseType.json
    flutter: followRedirects: true
    flutter: connectTimeout: 10000
    flutter: sendTimeout: 0
    flutter: receiveTimeout: 10000
    flutter: receiveDataWhenStatusError: true
    flutter: extra: {}
    flutter: headers:
    flutter:  stream-auth-type: jwt
    flutter:  x-stream-client: stream-feed-dart-client-macos-0.2.1
    flutter:  Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjMyNzE0NTMsImlhdCI6MTYyMzI3MDI1MywidXNlcl9pZCI6IjMyZGIwZjQ2LTM1OTMtNGUxNC1hYTU3LWYwNWFmNDg4NzI2MCJ9.UNxSVBQLpFLiGqFz8rUePQJdsvKmtt8ipe-9Kt2jsTc
    flutter:  content-type: application/json; charset=utf-8
    flutter: data:
    flutter: Activity(SU:32db0f46-3593-4e14-aa57-f05af4887260, task_situation_updated to true, updated, null, null, null, null, 2021-06-09 23:24:18.238189, null, null, null, null, {createdTask: {"id": "32db0f46-3593-4e14-aa57-f05af4887260", "title": "KeyPack", "isFinished": true}})
    flutter: 
    flutter: *** Response ***
    flutter: uri: https://api.stream-io-api.com/api/v1.0/feed/task/32db0f46-3593-4e14-aa57-f05af4887260/?api_key=yn6bquc5zs6m&location=unspecified
    flutter: statusCode: 201
    flutter: headers:
    flutter:  connection: keep-alive
    flutter:  cache-control: no-cache
    flutter:  date: Wed, 09 Jun 2021 20:24:19 GMT
    flutter:  access-control-allow-origin: *
    flutter:  x-ratelimit-limit: 1000
    flutter:  x-ratelimit-reset: 1623270300
    flutter:  x-ratelimit-remaining: 998
    flutter:  content-type: application/json;charset=utf-8
    flutter:  access-control-max-age: 86400
    flutter:  server: nginx
    flutter:  access-control-allow-headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken, x-stream-client, stream-auth-type
    flutter:  access-control-allow-methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
    flutter:  content-length: 366
    flutter: Response Text:
    flutter: {"actor":"SU:32db0f46-3593-4e14-aa57-f05af4887260","createdTask":"{\"id\": \"32db0f46-3593-4e14-aa57-f05af4887260\", \"title\": \"KeyPack\", \"isFinished\": true}","duration":"6.90ms","foreign_id":"","id":"cff95542-c979-11eb-8080-80005abdd229","object":"task_situation_updated to true","origin":null,"target":"","time":"2021-06-09T23:24:18.238189","verb":"updated"}
    flutter: 
    flutter: (2021-06-09 23:24:18.877664) โ„น๏ธ ๐Ÿ•’ received message : {data: {deleted: [], deleted_foreign_ids: [], feed: task:32db0f46-3593-4e14-aa57-f05af4887260, new: [{actor: {error: ReferenceNotFound, id: 32db0f46-3593-4e14-aa57-f05af4887260, reference: SU:32db0f46-3593-4e14-aa57-f05af4887260, reference_type: user}, createdTask: {"id": "32db0f46-3593-4e14-aa57-f05af4887260", "title": "KeyPack", "isFinished": true}, foreign_id: , group: updated_2021-06-09, id: cff95542-c979-11eb-8080-80005abdd229, object: task_situation_updated to true, origin: null, target: , time: 2021-06-09T23:24:18.238189, verb: updated}]}, channel: /site-1128601-feed-task32db0f46-3593-4e14-aa57-f05af4887260, successful: false}
    flutter: (2021-06-09 23:24:18.877872) โ„น๏ธ ๐Ÿ•’ Client 1-4add16cf-2e01-4a95-b84e-2782369ab005 calling listeners for /site-1128601-feed-task32db0f46-3593-4e14-aa57-f05af4887260 with {deleted: [], deleted_foreign_ids: [], feed: task:32db0f46-3593-4e14-aa57-f05af4887260, new: [{actor: {error: ReferenceNotFound, id: 32db0f46-3593-4e14-aa57-f05af4887260, reference: SU:32db0f46-3593-4e14-aa57-f05af4887260, reference_type: user}, createdTask: {"id": "32db0f46-3593-4e14-aa57-f05af4887260", "title": "KeyPack", "isFinished": true}, foreign_id: , group: updated_2021-06-09, id: cff95542-c979-11eb-8080-80005abdd229, object: task_situation_updated to true, origin: null, target: , time: 2021-06-09T23:24:18.238189, verb: updated}]}
    [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String?' in type cast
    #0      _$ActivityFromJson (package:stream_feed/src/core/models/activity.g.dart:11:26)
    #1      new Activity.fromJson (package:stream_feed/src/core/models/activity.dart:33:7)
    #2      _$RealtimeMessageFromJson.<anonymous closure> (package:stream_feed/src/core/models/realtime_message.g.dart:17:30)
    #3      MappedListIterable.elementAt (dart:_internal/iterable.dart:412:31)
    #4      ListIterator.moveNext (dart:_internal/iterable.dart:341:26)
    #5      new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:188:27)
    #6      new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
    #7      new List.of (dart:core-patch/array_patch.dart:50:28)
    #8      ListIterable.toList (dart:_internal/iterable.dart:212:44)
    #9      _$RealtimeMessageFromJson (package:stream_feed/src/core/models/realtime_message.g.dart:20:10)
    #10     new RealtimeMessage.fromJson (package:stream_feed/src/core/models/realtime_message.dart:26:7)
    #11     Feed.subscribe.<anonymous closure> (package:stream_feed/src/client/feed.dart:76:47)
    #12     Subscription.call (package:faye_dart/src/subscription.dart:21:16)
    #13     EventEmitter.emit (package:faye_dart/src/event_emitter.dart:59:23)
    #14     Channel.trigger (package:faye_dart/src/channel.dart:26:50)
    #15     ChannelMapX.distributeMessage (package:faye_dart/src/channel.dart:103:22)
    #16     FayeClient._deliverMessage (package:faye_dart/src/client.dart:430:15)
    #17     FayeClient._receiveMessage.<anonymous closure> (package:faye_dart/src/client.dart:409:7)
    #18     Extensible.pipeThroughExtensions.pipe (package:faye_dart/src/extensible.dart:29:46)
    #19     Extensible.pipeThroughExtensions.pipe (package:faye_dart/src/extensible.dart:32:34)
    #20     Extensible.pipeThroughExtensions (package:faye_dart/src/extensible.dart:37:9)
    #21     FayeClient._receiveMessage (package:faye_dart/src/client.dart:406:5)
    #22     FayeClient._onDataReceived (package:faye_dart/src/client.dart:169:7)
    #23     _rootRunUnary (dart:async/zone.dart:1362:47)
    #24     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #25     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #26     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #27     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #28     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
    #29     _HandleErrorStream._handleData (dart:async/stream_pipe.dart:256:10)
    #30     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)
    #31     _rootRunUnary (dart:async/zone.dart:1362:47)
    #32     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #33     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #34     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #35     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #36     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #37     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #38     _rootRunUnary (dart:async/zone.dart:1362:47)
    #39     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #40     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #41     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #42     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #43     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #44     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #45     _StreamController.add (dart:async/stream_controller.dart:554:5)
    #46     new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
    #47     _rootRunUnary (dart:async/zone.dart:1362:47)
    #48     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #49     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #50     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #51     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #52     _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:63:11)
    #53     _EventSinkWrapper.add (dart:async/stream_transformers.dart:13:11)
    #54     _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
    #55     _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
    #56     _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:111:24)
    #57     _rootRunUnary (dart:async/zone.dart:1362:47)
    #58     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #59     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #60     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #61     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #62     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #63     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #64     _StreamController.add (dart:async/stream_controller.dart:554:5)
    #65     _Socket._onData (dart:io-patch/socket_patch.dart:2160:41)
    #66     _rootRunUnary (dart:async/zone.dart:1362:47)
    #67     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #68     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #69     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #70     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #71     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #72     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #73     _StreamController.add (dart:async/stream_controller.dart:554:5)
    #74     _RawSecureSocket._sendReadEvent (dart:io/secure_socket.dart:991:19)
    #75     _rootRun (dart:async/zone.dart:1346:47)
    #76     _CustomZone.run (dart:async/zone.dart:1258:19)
    #77     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
    #78     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
    #79     _rootRun (dart:async/zone.dart:1354:13)
    #80     _CustomZone.run (dart:async/zone.dart:1258:19)
    #81     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1186:23)
    #82     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
    #83     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19)
    #84     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5)
    #85     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
    
    [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Instance of 'Error'
    #0      EventEmitter.emit (package:faye_dart/src/event_emitter.dart:75:19)
    #1      Channel.trigger (package:faye_dart/src/channel.dart:26:50)
    #2      ChannelMapX.distributeMessage (package:faye_dart/src/channel.dart:103:22)
    #3      FayeClient._deliverMessage (package:faye_dart/src/client.dart:430:15)
    #4      FayeClient._receiveMessage.<anonymous closure> (package:faye_dart/src/client.dart:409:7)
    #5      Extensible.pipeThroughExtensions.pipe (package:faye_dart/src/extensible.dart:29:46)
    #6      Extensible.pipeThroughExtensions.pipe (package:faye_dart/src/extensible.dart:32:34)
    #7      Extensible.pipeThroughExtensions (package:faye_dart/src/extensible.dart:37:9)
    #8      FayeClient._receiveMessage (package:faye_dart/src/client.dart:406:5)
    #9      FayeClient._onDataReceived (package:faye_dart/src/client.dart:169:7)
    #10     _rootRunUnary (dart:async/zone.dart:1362:47)
    #11     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #12     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #13     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #14     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #15     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
    #16     _HandleErrorStream._handleData (dart:async/stream_pipe.dart:256:10)
    #17     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)
    #18     _rootRunUnary (dart:async/zone.dart:1362:47)
    #19     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #20     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #21     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #22     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #23     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #24     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #25     _rootRunUnary (dart:async/zone.dart:1362:47)
    #26     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #27     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #28     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #29     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #30     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #31     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #32     _StreamController.add (dart:async/stream_controller.dart:554:5)
    #33     new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
    #34     _rootRunUnary (dart:async/zone.dart:1362:47)
    #35     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #36     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #37     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #38     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #39     _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:63:11)
    #40     _EventSinkWrapper.add (dart:async/stream_transformers.dart:13:11)
    #41     _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
    #42     _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
    #43     _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:111:24)
    #44     _rootRunUnary (dart:async/zone.dart:1362:47)
    #45     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #46     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #47     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #48     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #49     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #50     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #51     _StreamController.add (dart:async/stream_controller.dart:554:5)
    #52     _Socket._onData (dart:io-patch/socket_patch.dart:2160:41)
    #53     _rootRunUnary (dart:async/zone.dart:1362:47)
    #54     _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #55     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #56     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #57     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
    #58     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
    #59     _StreamController._add (dart:async/stream_controller.dart:607:7)
    #60     _StreamController.add (dart:async/stream_controller.dart:554:5)
    #61     _RawSecureSocket._sendReadEvent (dart:io/secure_socket.dart:991:19)
    #62     _rootRun (dart:async/zone.dart:1346:47)
    #63     _CustomZone.run (dart:async/zone.dart:1258:19)
    #64     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
    #65     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
    #66     _rootRun (dart:async/zone.dart:1354:13)
    #67     _CustomZone.run (dart:async/zone.dart:1258:19)
    #68     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1186:23)
    #69     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
    #70     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19)
    #71     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5)
    #72     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
    
    

    Additional context Add any other context about the problem here.

    bug 
    opened by salihgueler 13
  • Finally fixed timezone issue

    Finally fixed timezone issue

    Pull Request

    Timezone Fix

    There was still an issue with #144 where activity.time!.isUtc returns false for me.

    The issue in this case was, that there was an JsonConverter<DateTime, String> created but a JsonConverter<DateTime?, String> required while the time property is a DateTime?.

    Here is the referred generated code where the converter is still unused: https://github.com/GetStream/stream-feed-flutter/blob/master/packages/stream_feed/lib/src/core/models/enriched_activity.g.dart#L24

    The succeeded new implemented tests were false positive because the local timezone used here was UTC. So maybe there could be some room for test improvements...

    Dependency Updates

    Additionally I updated the json_annotations and json_serializable package to latest version.

    CLA

    • [x] I have signed the Stream CLA (required).
    • [x] The code changes follow best practices
    • [ ] Code changes are tested (add some information if not applicable)
    opened by obrunsmann 11
  • Get An Activity By An Extra Field

    Get An Activity By An Extra Field

    It would be nice to get an activity by an extra field. Say like if you have a pinned activity but its not the first 25 or even the first 100 activities returned for the feed it would be nice to be able to search on a key word like pinned and get that one to show.

    enhancement backend 
    opened by rlee1990 9
  • Error trying to get activity feeds

    Error trying to get activity feeds

    I am receiving this error each time:

     *** Request ***
    flutter: uri: https://api.stream-io-api.com/api/v1.0/enrich/feed/timeline/eTHVBnEm0FQB2HeaRKVlEfVf58B3personal/?limit=100&offset=0&api_key=hmwext26344q&location=unspecified
    flutter: method: GET
    flutter: responseType: ResponseType.json
    flutter: followRedirects: true
    flutter: connectTimeout: 10000
    flutter: sendTimeout: 0
    flutter: receiveTimeout: 10000
    flutter: receiveDataWhenStatusError: true
    flutter: extra: {}
    flutter: headers:
    flutter:  stream-auth-type: jwt
    flutter:  x-stream-client: stream-feed-dart-client-ios-0.1.2
    flutter:  Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZVRIVkJuRW0wRlFCMkhlYVJLVmxFZlZmNThCM3BlcnNvbmFsIn0.fg1c3TDXi2yqGWCWmljOQgGM3NdgjZwFRw9Q_bK5mTA
    flutter: data:
    flutter: null
    flutter:
    flutter: *** DioError ***:
    flutter: uri: https://api.stream-io-api.com/api/v1.0/enrich/feed/timeline/eTHVBnEm0FQB2HeaRKVlEfVf58B3personal/?limit=100&offset=0&api_key=hmwext26344q&location=unspecified
    flutter: DioError [DioErrorType.response]: Http status error [403]
    #0      DioMixin.assureDioError
    package:dio/src/dio_mixin.dart:819
    #1      DioMixin._dispatchRequest
    package:dio/src/dio_mixin.dart:678
    <asynchronous suspension>
    #2      DioMixin.fetch.<anonymous closure>.<anonymous closure> (package:dio/src/dio_mixin.dart)
    package:dio/src/dio_mixin.dart:1
    <asynchronous suspension>
    flutter: uri: https://api.stream-io-api.com/api/v1.0/enrich/feed/timeline/eTHVBnEm0FQB2HeaRKVlEfVf58B3personal/?limit=100&offset=0&api_key=hmwext26344q&location=unspecified
    flutter: statusCode: 403
    flutter: headers:
    flutter:  connection: keep-alive
    flutter:  x-ratelimit-reset: 1620604260
    flutter:  date: Sun, 09 May 2021 23:50:30 GMT
    flutter:  transfer-encoding: chunked
    flutter:  access-control-allow-origin: *
    flutter:  x-ratelimit-limit: 2000
    flutter:  content-encoding: gzip
    flutter:  x-ratelimit-remaining: 1999
    flutter:  content-type: text/plain; charset=utf-8
    flutter:  server: nginx
    flutter: Response Text:
    flutter: {"detail":"signature is invalid","status_code":403,"code":17,"exception":"NotAllowedException","duration":"0.00ms","more_info":"https://getstream.io/docs/api_error_responses"}
    2
    flutter:
    [VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: StreamApiException{body: {"detail":"signature is invalid","status_code":403,"code":17,"exception":"NotAllowedException","duration":"0.00ms","more_info":"https://getstream.io/docs/api_error_responses"}, jsonData: {detail: signature is invalid, status_code: 403, code: 17, exception: NotAllowedException, duration: 0.00ms, more_info: https://getstream.io/docs/api_error_responses}, status: 403, code: 17}
    

    The request is:

    widget.streamClient
            .flatFeed('timeline', widget.sUser.userId)
            .getEnrichedActivities(
                limit: 100,
                offset: 0,
                flags: EnrichmentFlags()
                    .withReactionCounts()
                    .withOwnReactions()
                    .withOwnChildren()
                    .withRecentReactions())
            .then((value) {
          print(value[0]);
        });
    
    bug 
    opened by rlee1990 9
  • getEnrichedActivities - Filter

    getEnrichedActivities - Filter

    Describe the bug Hi team, im using filters when getting activities.

    getEnrichedActivities(
                limit: _itemsMaxSize,
                filter: filter.idGreaterThanOrEqual(lastActivityId),
    

    My problem is if i keep: filter.idGreaterThanOrEqual(lastActivityId) im seeing my activity => Great

    activityId:2157117b-dd7b-11eb-a6fd-12d73b08236b newItems => [2157117b-dd7b-11eb-a6fd-12d73b08236b]
    

    but, if i switch to filter.idLessThanOrEqual(lastActivityId) im not seeing anymore the activity, i see old activities only

    activityId:2157117b-dd7b-11eb-a6fd-12d73b08236b newItems => [ac4ed14a-dd67-11eb-b60d-128a130028af, 1212b7b7-dd65-11eb-9337-0a1200300037, e8f71af1-dd63-11eb-92b9-0a1200300037, dcd17743-dd04-11eb-9c64-0ae838defca7, 861fc8c3-dd04-11eb-b74c-128a130028af]
    

    What package are you using? What version? develop

    What platform is it about?

    • [ ] Android
    • [X ] iOS
    • [ ] Web
    • [ ] Windows
    • [ ] MacOS
    • [ ] Linux

    Additional context Dont know why, but after some time... idLessThanOrEqual works :

    activityId:2157117b-dd7b-11eb-a6fd-12d73b08236b newItems => [2157117b-dd7b-11eb-a6fd-12d73b08236b, 86944ce2-dd78-11eb-a1e9-0a1200300037, dbe68432-dd77-11eb-81ad-128a130028af, d8a3e027-dd76-11eb-a495-0ae838defca7, b85db3c1-dd76-11eb-8f6f-0a0d7a10423a]
    

    Is there some cache involve ? Best regards, Nelson

    bug documentation 
    opened by Abacaxi-Nelson 7
  • No longer can get a list of followers

    No longer can get a list of followers

    I am using stream_feed: ^0.5.1 on android and ios. When I run ``` streamFeedClient .flatFeed("timeline", widget.accountToCheck) .following(limit: 100, offset: 0)

    I receive this error: ```
    "You do not have permission to do this, you got this error because there are no policies allowing this request o
    flutter: (2022-03-25 15:23:45.711296) ๐Ÿšจ ๐Ÿ“œ โ•‘         n this application. Please consult the documentation [https://getstream.io/docs/]()"
    flutter: (2022-03-25 15:23:45.711413) ๐Ÿšจ ๐Ÿ“œ โ•‘         status_code: 403,
    flutter: (2022-03-25 15:23:45.711511) ๐Ÿšจ ๐Ÿ“œ โ•‘         code: 17,
    flutter: (2022-03-25 15:23:45.711601) ๐Ÿšจ ๐Ÿ“œ โ•‘         exception: "NotAllowedException",
    flutter: (2022-03-25 15:23:45.711675) ๐Ÿšจ ๐Ÿ“œ โ•‘         duration: "0.15ms",
    flutter: (2022-03-25 15:23:45.711763) ๐Ÿšจ ๐Ÿ“œ โ•‘         more_info: "[https://getstream.io/docs/api_error_responses]()"
    

    I am just having any user that visits someone's page or even their own page to be able to see who that person follows or who follows that person. This was working before and now it is not.

    bug backend 
    opened by rlee1990 6
  • is this package still maintained?

    is this package still maintained?

    Hello, it's been a while since this package has been updated and there was no progress about the UI elements that were planned to be build, my app depends in this package, is it still maintained by the stream team?

    opened by Nader2004 0
  • Update pubspec so that using this repo as a git dependency works

    Update pubspec so that using this repo as a git dependency works

    Submit a pull request

    CLA

    • [x] I have signed the Stream CLA (required).
    • [x] The code changes follow best practices
    • [ ] Code changes are tested (add some information if not applicable)

    Description of the pull request

    • Updates stream_feed_flutter/pubspec.yaml so that it can be used as a git dependency
    • Updates stream_feed_flutter/README.md to reflect a more responsible use of git dependencies

    I looked through the major dependency upgrades and it looks like nothing should have broken. The commit that was used for the photo_view dependency is included in the latest release.

    opened by Rexios80 0
  • StateError when adding a child comment

    StateError when adding a child comment

    Hello,

    I get an error when I try to add a child comment. I use the onAddChildReaction() method in the feed_bloc.dart file.

    The error returned is StateError, it appears in the line of the indexWhere :

    final _reactions = getReactions(lookupValue, reaction);
    final reactionPath = _reactions.getReactionPath(reaction);
    final indexPath = _reactions
        .indexWhere((r) => r.id! == reaction.id); //TODO: handle null safety
    

    The error does not occur on all comments. Each time the child comment is well created. Maybe the limit to retrieve the last 25 comments is a problem

    Version

    • stream_feed_flutter_core : 0.8.0
    • Flutter : 3.3.6

    Thanks !

    bug 
    opened by PKeviin 0
  • The GenericFeed parsing problem

    The GenericFeed parsing problem

    Is your feature request related to a problem? Please describe. The problem is that we receiving the type of model from the stream as this: image

    When we tried to use FlatFeed it's says that there was a problem with parsing data like this: image

    So then we changed all FlatFeed using to the GenericFeed(want to say that documentation also should be improved for this), so after we changed the implementation, we started to receive the parsing data error of field 'foreign_id' image


    Such as I've understood and you can see from the response structure, we have a root called foreign_id and which also has a field inside with the same name, foreign_id Untitled

    so when the library tries to get this data from json response and extract the main keys from json, you can follow here: image it's said that foreign_id is not a type of String.

    Describe the solution you'd like From our side, we tried to just replace the data to another key and everything start to worked: image

    JSON Response from stream

    {
      "results": [
        {
          "actor": {
            "created_at": "2022-11-04T10:34:26.427440Z",
            "updated_at": "2022-11-04T10:34:26.427440Z",
            "id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
            "data": {
              "first_name": "il",
              "last_name": "io"
            }
          },
          "foreign_id": {
            "id": "2c9200d9-1d07-4875-96c1-315353817809",
            "collection": "post",
            "foreign_id": "post:2c9200d9-1d07-4875-96c1-315353817809",
            "data": {
              "body": "ffff",
              "date": "2022-11-07T16:49:25.807000"
            },
            "created_at": "2022-11-07T16:49:26.4748Z",
            "updated_at": "2022-11-07T16:49:26.4748Z"
          },
          "id": "23563bf0-5ebc-11ed-8080-80012ce6320f",
          "object": {
            "id": "2c9200d9-1d07-4875-96c1-315353817809",
            "collection": "post",
            "foreign_id": "post:2c9200d9-1d07-4875-96c1-315353817809",
            "data": {
              "body": "ffff",
              "date": "2022-11-07T16:49:25.807000"
            },
            "created_at": "2022-11-07T16:49:26.4748Z",
            "updated_at": "2022-11-07T16:49:26.4748Z"
          },
          "origin": null,
          "target": "",
          "time": "2022-11-07T16:49:25.807000",
          "user_id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
          "verb": "post"
        },
        {
          "actor": {
            "created_at": "2022-11-04T10:34:26.427440Z",
            "updated_at": "2022-11-04T10:34:26.427440Z",
            "id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
            "data": {
              "first_name": "il",
              "last_name": "io"
            }
          },
          "foreign_id": {
            "id": "7c22a074-fba9-45a8-a6a3-734d7daa82bf",
            "collection": "post",
            "foreign_id": "post:7c22a074-fba9-45a8-a6a3-734d7daa82bf",
            "data": {
              "body": "Hhh",
              "date": "2022-11-07T11:07:51.037867"
            },
            "created_at": "2022-11-07T11:07:52.509356Z",
            "updated_at": "2022-11-07T11:07:52.509356Z"
          },
          "id": "6b80a4ae-5e8c-11ed-8080-8000357a1441",
          "object": {
            "id": "7c22a074-fba9-45a8-a6a3-734d7daa82bf",
            "collection": "post",
            "foreign_id": "post:7c22a074-fba9-45a8-a6a3-734d7daa82bf",
            "data": {
              "body": "Hhh",
              "date": "2022-11-07T11:07:51.037867"
            },
            "created_at": "2022-11-07T11:07:52.509356Z",
            "updated_at": "2022-11-07T11:07:52.509356Z"
          },
          "origin": null,
          "target": "",
          "time": "2022-11-07T11:07:51.037867",
          "user_id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
          "verb": "post"
        },
        {
          "actor": {
            "created_at": "2022-11-04T10:34:26.427440Z",
            "updated_at": "2022-11-04T10:34:26.427440Z",
            "id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
            "data": {
              "first_name": "il",
              "last_name": "io"
            }
          },
          "foreign_id": {
            "id": "d5bf20c2-b5be-41af-a6fe-10b8eed7ae88",
            "collection": "post",
            "foreign_id": "post:d5bf20c2-b5be-41af-a6fe-10b8eed7ae88",
            "data": {
              "body": "Yyg",
              "date": "2022-11-07T11:00:20.356377"
            },
            "created_at": "2022-11-07T11:00:21.43526Z",
            "updated_at": "2022-11-07T11:00:21.43526Z"
          },
          "id": "5ee01afa-5e8b-11ed-8080-80001eed094b",
          "object": {
            "id": "d5bf20c2-b5be-41af-a6fe-10b8eed7ae88",
            "collection": "post",
            "foreign_id": "post:d5bf20c2-b5be-41af-a6fe-10b8eed7ae88",
            "data": {
              "body": "Yyg",
              "date": "2022-11-07T11:00:20.356377"
            },
            "created_at": "2022-11-07T11:00:21.43526Z",
            "updated_at": "2022-11-07T11:00:21.43526Z"
          },
          "origin": null,
          "target": "",
          "time": "2022-11-07T11:00:20.356377",
          "user_id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
          "verb": "post"
        },
        {
          "actor": {
            "created_at": "2022-11-04T10:34:26.427440Z",
            "updated_at": "2022-11-04T10:34:26.427440Z",
            "id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
            "data": {
              "first_name": "il",
              "last_name": "io"
            }
          },
          "foreign_id": {
            "id": "c6a550a4-a7df-4119-87fc-56ecbf7b23eb",
            "collection": "post",
            "foreign_id": "post:c6a550a4-a7df-4119-87fc-56ecbf7b23eb",
            "data": {
              "body": "Vvv",
              "date": "2022-11-07T09:56:24.539436"
            },
            "created_at": "2022-11-07T09:56:25.855634Z",
            "updated_at": "2022-11-07T09:56:25.855634Z"
          },
          "id": "708ce3b8-5e82-11ed-8080-80003da76b62",
          "object": {
            "id": "c6a550a4-a7df-4119-87fc-56ecbf7b23eb",
            "collection": "post",
            "foreign_id": "post:c6a550a4-a7df-4119-87fc-56ecbf7b23eb",
            "data": {
              "body": "Vvv",
              "date": "2022-11-07T09:56:24.539436"
            },
            "created_at": "2022-11-07T09:56:25.855634Z",
            "updated_at": "2022-11-07T09:56:25.855634Z"
          },
          "origin": null,
          "target": "",
          "time": "2022-11-07T09:56:24.539436",
          "user_id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
          "verb": "post"
        },
        {
          "actor": {
            "created_at": "2022-11-04T10:34:26.427440Z",
            "updated_at": "2022-11-04T10:34:26.427440Z",
            "id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
            "data": {
              "first_name": "il",
              "last_name": "io"
            }
          },
          "foreign_id": {
            "id": "e147b773-d13d-4952-ba14-c0faec1b6794",
            "collection": "post",
            "foreign_id": "post:e147b773-d13d-4952-ba14-c0faec1b6794",
            "data": {
              "body": "Ffff",
              "date": "2022-11-07T09:10:13.573073"
            },
            "created_at": "2022-11-07T09:10:14.770503Z",
            "updated_at": "2022-11-07T09:10:14.770503Z"
          },
          "id": "fcecfa2a-5e7b-11ed-8080-80014ea006de",
          "object": {
            "id": "e147b773-d13d-4952-ba14-c0faec1b6794",
            "collection": "post",
            "foreign_id": "post:e147b773-d13d-4952-ba14-c0faec1b6794",
            "data": {
              "body": "Ffff",
              "date": "2022-11-07T09:10:13.573073"
            },
            "created_at": "2022-11-07T09:10:14.770503Z",
            "updated_at": "2022-11-07T09:10:14.770503Z"
          },
          "origin": null,
          "target": "",
          "time": "2022-11-07T09:10:13.573073",
          "user_id": "95db56be-2c60-46d6-8b4a-c2f71d7e666e",
          "verb": "post"
        }
      ],
      "next": "/api/v1.0/enrich/feed/PROFILE/95db56be-2c60-46d6-8b4a-c2f71d7e666e/?api_key=q8jk2pkj8fur&id_lt=fcecfa2a-5e7b-11ed-8080-80014ea006de&limit=5",
      "duration": "12.94ms"
    }
    
    enhancement 
    opened by followthemoney1 3
  • Examples on using Stream Feeds using Stream Auth Firebase Function Extention

    Examples on using Stream Feeds using Stream Auth Firebase Function Extention

    Is your feature request related to a problem? Please describe. Currently no documents or examples on using Stream Feeds alone with Firebase extention of Stream. Even the examples looks outdated for regular use case in pub.dev readme.

    Describe the solution you'd like An example for using Feeds along with Firebase extenions.

    enhancement 
    opened by Purus 0
Releases(v0.8.0)
  • v0.8.0(May 27, 2022)

    stream_feed

    0.6.0

    Changelog

    • new: aggregatedFeed.getEnrichedActivityDetail and aggregatedFeed.getPaginatedActivities
    • new: PaginatedActivitiesGroup model
    • fix: setUser now take the data field of User if provided
    • enhancement/breaking: make the constructor parameters of PaginatedReactions named

    stream_feed_flutter_core

    0.8.0

    Changelog

    • bump llc: fix: setUser not using user.data on user create.
    • new: FeedBloc and GenericFeedBloc now have queryPaginatedEnrichedActivities, loadMoreEnrichedActivities, and paginatedParams to easily manage pagination.
    class _CommentsPageState extends State<CommentsPage> {
      bool _isPaginating = false;
      
      Future<void> _loadMore() async {
        // Ensure we're not already loading more reactions.
        if (!_isPaginating) {
          _isPaginating = true;
          context.feedBloc
              .loadMoreReactions(widget.activity.id!, flags: _flags)
              .whenComplete(() {
            _isPaginating = false;
          });
        }
      }
    
      ...
    
      return ReactionListCore(
        reactionsBuilder: (context, reactions) =>
                     RefreshIndicator(
                        onRefresh: () {
                          return context.feedBloc.refreshPaginatedReactions(
                            widget.activity.id!,
                            flags: _flags,
                          );
                        },
                        child: ListView.separated(
                          itemCount: reactions.length,
                          separatorBuilder: (context, index) => const Divider(),
                          itemBuilder: (context, index) {
                            bool shouldLoadMore = reactions.length - 3 == index;
                            if (shouldLoadMore) {
                              _loadMore();
                            }
                            return ListReactionItem(reaction:reactions[index]);
                            }
                            ))
      );
    
    
    • changed: GenericFlatFeedCore and FlatFeedCore now calls queryPaginatedEnrichedActivities on initial load.
    • fix/breaking: onAddChildReaction commenting on a comment is now reactive but we had to remove the activity parameter and replace it with lookupValue. For example:
     FeedProvider.of(context).bloc.onAddChildReaction(
                kind: 'comment',
                reaction: reaction,
                lookupValue: widget.reaction.id!,
                data: {"text": "this is a comment on a comment"},
              );
    
    • docs: Stream Feed Core documentation and examples updated
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0+1(Feb 28, 2022)

    stream_feed_flutter_core

    0.7.0+1

    Changelog

    • fixes(FeedBloc):
      • bug when adding to a fix lengthed list
      • change the init behavior of queryEnrichedActivities (to allow it to be called again)
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Feb 25, 2022)

    faye_dart

    0.1.1+1

    Changelog

    • FIX: implement Equatable on FayeClient. With this change, if you fetch your client from an InheritedWidget for example, updateShouldNotify doesn't trigger every time.
    • NEW: expose connexion status stream Stream<FayeClientState> via the Subscription class to check if the Faye client is unconnected, connecting, connected or disconnected, and act accordingly.

    stream_feed

    0.5.1

    Changelog

    • UPSTREAM(realtime): version bump. You can now listen to connexion status in the Subscription class. For example:
    final subscription = await feed.subscribe();
    final subscriptionStatus = subscription.stateStream;
    
    • NEW(realtime): you can now adjust log level when subscribing
    • FIX: implement Equatable on StreamFeedClient. With this change, if you fetch your client from an InheritedWidget for example, updateShouldNotify doesn't trigger every time.

    stream_feed_flutter_core

    0.7.0

    Changelog

    • FIX: FeedProvider inherited widget had an issue with the updateShouldNotify being triggered everytime. This has been fixed via the llc, being bumped to 0.5.1.
    • UPSTREAM(realtime): version bump
    • BREAKING: onAddActivity signature changed. The named parameter datachanged from Map<String, String>? to Map<String, Object>?.
    • BREAKING: Refactors all of our builder methods to return data and not be opinionated about widgets in Core package new: Various additional code documentation added
    • NEW: new model and convenient extensions for the UploadController An Attachment model to convert a MediaUri TO a Map<String, Object?> to send as an extraData along an activity or a reaction. For example:
    final bloc = FeedProvider.of(context).bloc;
    final uploadController = bloc.uploadController;
    final extraData = uploadController.getMediaUris()?.toExtraData();
    await bloc.onAddReaction( kind: 'comment', data: extraData, activity: parentActivity, feedGroup: feedGroup );
    

    The attachment model is also useful to convert FROM extraData in an activity or reaction via the toAttachments extension. For example:

    final attachments = activity.extraData?.toAttachments()
    
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Jan 12, 2022)

    stream_feed

    0.5.0

    Changelog

    • BREAKING: we no longer accept a token in the constructor. This change is inspired by Stream Chat, and allows for use cases like multi account management. It allows to instantiate StreamFeedClient at the top of your widget tree for example, and connect the user later.
    -  client = StreamFeedClient(apiKey, token: frontendToken);
    +  client = StreamFeedClient(apiKey);
    +
    +  await client.setUser(
    +    const User(
    +      data: {
    +        'name': 'John Doe',
    +        'occupation': 'Software Engineer',
    +        'gender': 'male'
    +      },
    +    ),
    +    frontendToken,
    +  );
    

    stream_feed_flutter_core

    0.6.0

    Changelog

    • breaking: bump version of breaking change llc
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Dec 27, 2021)

    stream_feed

    0.4.0+3

    Changelog

    • fix: call profile in setUser, so that currentUser data is not null

    stream_feed_flutter_core

    0.5.0

    Changelog

    • fix: the convenient typedefs on generic classes we provided was breaking autocomplete
    • breaking: we renamed some methods
      • followFlatFeed -> followFeed
      • unfollowFlatFeed -> unfollowFeed
      • isFollowingUser -> isFollowingFeed
    • fix: export MediaUri
    • new: add scrollPhysics parameter to ReactionListCore
    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Dec 22, 2021)

    stream_feed

    0.4.0+2

    Changelog

    • fix: export image_storage_client.dart

    stream_feed_flutter_core

    0.4.1

    Changelog

    • new: UploadListCore and UploadController Uploads are at the heart of feeds applications so we made this convenient classes to help you manage the state of media uploads (fail, progress, success, cancel) in your Stream's powered app

    Usage :

    import 'package:flutter/material.dart';
    import 'package:image_picker/image_picker.dart';
    import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart';
    
    ....
    
    class ComposeScreen extends StatefulWidget {
      const ComposeScreen({Key? key}) : super(key: key);
    
      @override
      State<ComposeScreen> createState() => _ComposeScreenState();
    }
    
    class _ComposeScreenState extends State<ComposeScreen> {
      late AttachmentFile? _file = null;
      @override
      Widget build(BuildContext context) {
        final uploadController = FeedProvider.of(context).bloc.uploadController;
        return Scaffold(
          appBar: AppBar(title: const Text('Compose'), actions: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: ActionChip(
                  label: const Text(
                    'Post',
                    style: TextStyle(
                      color: Colors.blue,
                    ),
                  ),
                  backgroundColor: Colors.white,
                  onPressed: () {
                    final attachments = uploadController.getMediaUris();
                    print(attachments);
                    uploadController.clear();
                  }),
            )
          ]),
          body: SingleChildScrollView(
              child: Column(children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextField(
                decoration: InputDecoration(hintText: "this is a text field"),
              ),
            ),
            IconButton(
                onPressed: () async {
                  final ImagePicker _picker = ImagePicker();
                  final XFile? image =
                      await _picker.pickImage(source: ImageSource.gallery);
    
                  if (image != null) {
                    await FeedProvider.of(context)
                        .bloc
                        .uploadController
                        .uploadImage(AttachmentFile(path: image.path));
                  } else {
                    // User canceled the picker
                  }
                },
                icon: Icon(Icons.file_copy)),
            UploadListCore(
              uploadController: FeedProvider.of(context).bloc.uploadController,
              uploadsBuilder: (context, uploads) {
                return SizedBox(
                  height: 100,
                  child: ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemCount: uploads.length,
                    itemBuilder: (context, index) => FileUploadStateWidget(
                        fileState: uploads[index],
                        onRemoveUpload: (attachment) {
                          return uploadController.removeUpload(attachment);
                        },
                        onCancelUpload: (attachment) {
                          uploadController.cancelUpload(attachment);
                        },
                        onRetryUpload: (attachment) async {
                          return uploadController.uploadImage(attachment);
                        }),
                  ),
                );
              },
            ),
          ])),
        );
      }
    }
    
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0+1(Dec 7, 2021)

    stream_feed

    0.4.0+1

    Changelog

    • fix: support null values extraData's map
    • fix: utc date parsing with a JsonConverter<DateTime,String> and intl
    • fix: unread/unseen count in NotificationFeedMeta model

    stream_feed_flutter_core

    0.4.0+1

    Changelog

    • Use secure link in readme
    • version bump llc
    • barebone core sample app to get you started
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Oct 29, 2021)

    stream_feed

    0.4.0

    Changelog

    • breaking: StreamFeedClient.connect is now StreamFeedClient for better user session handling. The connect verb was confusing, and made you think that it will perform the connection immediately. Also, it doesn't infer the id anymore from the token anymore. You can now have to call setUser down the tree or before runApp
    • breaking: setUser now takes a User (must contain id) and a token. Passing the user token in the client constructor was making the whole instance depend on a single user.
    • new: we support generics EnrichedActivity is now GenericEnrichedActivity<A,Ob,T,Or> in order to have a more flexible API surface. Those generic parameters can be as follows: A = [actor]: can be an User, String Ob = [object] can a String, or a CollectionEntry T = [target] can be a String or an Activity Or = [origin] can be a String or a Reaction or a User
    • breaking: along with these changes we removed the EnrichableField field from EnrichedActivity
    • new: there is a type definition EnrichedActivity to handle most use cases of GenericEnrichedActivity (User,String,String,String)
    • fix: a time drift issue in a token generation when using the low-level client sever-side
    • bump: dart SDK package constraints to 2.14 to make use of typedefs for nonfunction types

    stream_feed_flutter_core

    0.4.0

    First Release of Core ๐ŸŽ‰

    This package provides business logic to fetch common things required for integrating Stream Feed into your application. The core package allows more customization and hence provides business logic but no UI components. Use stream_feed for the low-level client.

    The package primarily contains three types of classes:

    1. Business Logic Components
    2. Core Components

    Business Logic Components

    These components allow you to have the maximum and lower-level control of the queries being executed. The BLoCs we provide are:

    1. FeedBloc

    Core Components

    Core components usually are an easy way to fetch data associated with Stream Feed which are decoupled from UI and often expose UI builders. Data fetching can be controlled with the controllers of the respective core components.

    1. FlatFeedCore (Fetch a list of activities)
    2. ReactionListCore (Fetch a list of reactions)
    3. FeedProvider (Inherited widget providing FeedBloc to the widget tree)

    Usage

    import 'package:flutter/material.dart';
    import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart';
    
    void main() {
      const apiKey = 'API-KEY';
      const userToken = 'USER-TOKEN';
      final client = StreamFeedClient(
        apiKey,
        token: const Token(userToken),
      );
    
      runApp(
        MaterialApp(
          /// Wrap your application in a `FeedProvider`. This requires a `FeedBloc`.
          /// The `FeedBloc` is used to perform various Stream Feed operations.
          builder: (context, child) => FeedProvider(
            bloc: FeedBloc(client: client),
            child: child!,
          ),
          home: Scaffold(
            /// Returns `Activities`s for the given `feedGroup` in the `feedBuilder`.
            body: FlatFeedCore(
              feedGroup: 'user',
              feedBuilder: (BuildContext context, activities, int index) {
                return InkWell(
                  child: Column(children: [
                    Text("${activities[index].actor}"),
                    Text("${activities[index].object}"),
                  ]),
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute<void>(
                        builder: (BuildContext context) => Scaffold(
                          /// Returns `Reaction`s for the given
                          /// `lookupValue` in the `reactionsBuilder`.
                          body: ReactionListCore(
                            lookupValue: activities[index].id!,
                            reactionsBuilder: (context, reactions, idx) =>
                                Text("${reactions[index].data?["text"]}"),
                          ),
                        ),
                      ),
                    );
                  },
                );
              },
            ),
          ),
        ),
      );
    }
    
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Sep 6, 2021)

    • improvements:
      • docs
      • better error handling and expose exception type
      • const constructors when possible
    • breaking: UserClient user(String userId) is now StreamUser user(String userId) for easier state management
    • breaking: change type of Reaction model field user from Map<String,dynamic> to User
    • new: serverside methods for CRUD operations on User(getUser, createUser, updateUser, deleteUser)
    • new: CancelToken, OnSendProgress named parameters to support cancelling an upload and tracking its progress
    • new: logger options to allow choosing the Logger level
    • fix: missing field ownChildren in Reaction model
    • new: allow sending enrichment flags in filter mehod
    • new: createReactionReference
    Source code(tar.gz)
    Source code(zip)
  • v0.2.3(Aug 3, 2021)

  • v0.2.2(Jun 14, 2021)

    • fix: RealTime message serialization issue #89 RealtimeMessage newActivities field now of type List<EnrichedActivity> instead of List<Activity>
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(May 26, 2021)

  • v.0.2.0(May 21, 2021)

    • fix: Follow model #71
    • new: FollowRelation
    • breaking: un/followMany batch methods now accept Iterable<FollowRelation> parameter instead of Iterable<Follow>
    Source code(tar.gz)
    Source code(zip)
  • v0.1.3(May 17, 2021)

  • v0.1.2(May 7, 2021)

Owner
Stream
Build scalable newsfeeds, activity streams, chat and messaging in a few hours instead of weeks
Stream
Stream sticker animation - Stream Sticker Animation using Rive

Stream Sticker Animation using Rive Sample Flutter project to demonstrate how to

Souvik Biswas 4 Feb 8, 2022
An open source encrypted peer-to-peer system. Own data, own privacy. (Rust+Flutter)

An open source encrypted peer-to-peer system. Own data, own privacy. (Rust+Flutter)

Cymple Tech 124 Oct 7, 2021
An open source encrypted peer-to-peer system. Own data, own privacy.

An open source encrypted peer-to-peer system. Own data, own privacy.

Cymple Tech 456 Jan 3, 2023
Encrypted peer-to-peer system for data security. Own data, own privacy

ESSE (Encrypted Symmetrical Session Engine) An open source encrypted peer-to-pee

CympleTech 455 Dec 26, 2022
P2P payment solution using Stream's Flutter SDK and Rapyd's Wallet API

Peer-to-peer payment integration to a messaging app using Flutter ?? This project shows how to integrate a peer-to-peer payment solution to your Strea

Souvik Biswas 15 Dec 8, 2022
The official sdk for the user-friendly API of Mega services on the Dart language.

megasdkdart The official sdk for the user-friendly API of Mega services in the Dart language. Example: import 'package:megasdkdart/megasdkdart.dart';

meg4cyberc4t 4 Mar 30, 2022
Official plugin for using Thepeer SDK with flutter https://thepeer.co

Flutter Thepeer This package makes it easy to use the Thepeer in a flutter project. ?? Screen Shots ?? How to Use plugin ThePeer Send Launch ThepeerSe

The Peer 23 Dec 27, 2022
Official plugin for using Thepeer SDK with flutter https://thepeer.co

Flutter Thepeer This package makes it easy to use the Thepeer in a flutter project. ?? Screen Shots ?? How to Use plugin Adding MaterialSupport Add th

Thepeer 23 Dec 27, 2022
A discord bot, made with Dart, which lets you run your own pure Dart code snippets directly via a discord ping, and get the output in an instant.

A discord bot, made with Dart, which lets you run your own pure Dart code snippets directly via a discord ping, and get the output in an instant.

Anikate De 3 Oct 21, 2022
Official Flutter SDK for Khalti Payment systems

Khalti Payment Gateway for Flutter Use Khalti Payment Gateway solution in your app or website to simplify payment for your customers. You do not need

Khalti 16 Oct 13, 2022
Official sdk for vchat

V_Chat_SDK Micro service Check Our Full documention VCHAT DOCS Quick Review Android IOS Don't forget to see the example attached to github here V_CHAT

Hatem Ragab 42 Dec 17, 2022
A Simple Todo app design in Flutter to keep track of your task on daily basis. Its build on BLoC Pattern. You can add a project, labels, and due-date to your task also you can sort your task on the basis of project, label, and dates

WhatTodo Life can feel overwhelming. But it doesnโ€™t have to. A Simple To-do app design in flutter to keep track of your task on daily basis. You can a

Burhanuddin Rashid 1k Jan 6, 2023
A package that lets you include a cool, nice looking and validated Password TextFormField in your app to enhance user experience. The package is fully & easily modifiable.

A package that lets you include a cool, nice looking and validated Password TextFormField in your app to enhance user experience. The package is fully

Muhammad Hamza 21 Jan 1, 2023
validate JSON against your own Blueprint ๐Ÿ‘‘๐Ÿงฌ

PART OF QUEEN ?? Validate JSON Against Your Own Blueprint ?? ?? Content Validate JSON Against Your Own Blueprint ?? ?? Content Motivation NOTE Feature

Ahmed Masoud 12 Oct 29, 2022
Enhancing your WhatsApp experience.

WhishApp Enhancing your WhatsApp experience. Chat with unknown Number Status Saver Represent a name using emoji's (Coming soon) Sticker chat (Coming s

Prateek SU 5 Oct 16, 2022
A flutter widget that show the camera stream and allow ML vision recognition on it, it allow you to detect barcodes, labels, text, faces...

Flutter Camera Ml Vision A Flutter package for iOS and Android to show a preview of the camera and detect things with Firebase ML Vision. Installation

Rushio Consulting 257 Jan 2, 2023
A fully functional chat application built with Flutter and Stream

?? SpikeChat A fully functional chat application built with Flutter and Stream! โœ… Join the chat room (If you have the secret passcode hehe) โœ… Send tex

Ashton Jones 20 Apr 30, 2022
Flutter Chat App with localization - powered by Stream

flutter_chat_app A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

Pawan Kumar 49 Dec 23, 2022
Hybrid App build on flutter SDK able to run on Android, IOS, web, desktop

Codeforces Visualizer APP Ready to use Flutter Application. Uses codeforces API. Useful for codeforces programmers. ScreenShots Single User Page Compa

vikas yadav 13 Dec 31, 2022