From 4bd55ead33de3ee7640de34d500c40249996c6f0 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Fri, 7 May 2021 17:25:02 +0530 Subject: [PATCH 0001/1241] Convert `UserClient` into a `StreamUser` for easier user management Signed-off-by: Sahil Kumar --- example/lib/activity_item.dart | 10 +- example/lib/app_user.dart | 38 +++++ .../utils.dart => client_provider.dart} | 11 +- example/lib/dummy_app_user.dart | 41 ----- example/lib/extension.dart | 14 ++ example/lib/home.dart | 10 +- example/lib/people_screen.dart | 33 ++-- example/lib/profile_screen.dart | 32 ++-- example/lib/timeline_screen.dart | 26 ++- example/pubspec.yaml | 5 +- .../stream_feed/lib/src/client/index.dart | 1 + .../lib/src/client/stream_client.dart | 8 +- .../lib/src/client/stream_client_impl.dart | 26 ++- .../lib/src/client/stream_user.dart | 152 ++++++++++++++++++ .../lib/src/client/user_client.dart | 101 ------------ .../lib/src/core/api/users_api.dart | 11 +- packages/stream_feed/lib/src/core/index.dart | 3 - packages/stream_feed/lib/stream_feed.dart | 4 +- .../stream_feed/test/faye_client_test.dart | 1 - packages/stream_feed/test/models_test.dart | 1 + .../stream_feed/test/users_client_test.dart | 14 +- 21 files changed, 304 insertions(+), 238 deletions(-) create mode 100644 example/lib/app_user.dart rename example/lib/{utils/utils.dart => client_provider.dart} (61%) delete mode 100644 example/lib/dummy_app_user.dart create mode 100644 example/lib/extension.dart create mode 100644 packages/stream_feed/lib/src/client/stream_user.dart delete mode 100644 packages/stream_feed/lib/src/client/user_client.dart diff --git a/example/lib/activity_item.dart b/example/lib/activity_item.dart index f1b500808..c96400dbe 100644 --- a/example/lib/activity_item.dart +++ b/example/lib/activity_item.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:stream_feed/stream_feed.dart'; import 'package:timeago/timeago.dart' as timeago; -import 'dummy_app_user.dart'; +import 'app_user.dart'; class ActivityCard extends StatelessWidget { final Activity activity; @@ -11,8 +11,8 @@ class ActivityCard extends StatelessWidget { @override Widget build(BuildContext context) { - final user = - DummyAppUser.values.firstWhere((it) => it.id == activity.actor); + final user = appUsers + .firstWhere((it) => createUserReference(it.id) == activity.actor); return Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8), child: Column( @@ -21,7 +21,7 @@ class ActivityCard extends StatelessWidget { Row( children: [ CircleAvatar( - child: Text(user.name![0]), + child: Text(user.name[0]), ), SizedBox(width: 16), Expanded( @@ -29,7 +29,7 @@ class ActivityCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - user.name!, + user.name, style: TextStyle( fontSize: 18, ), diff --git a/example/lib/app_user.dart b/example/lib/app_user.dart new file mode 100644 index 000000000..835de2211 --- /dev/null +++ b/example/lib/app_user.dart @@ -0,0 +1,38 @@ +class AppUser { + final String id; + final String name; + final String token; + + const AppUser.sahil() + : id = 'sahil-kumar', + name = 'Sahil Kumar', + token = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwta3VtYXIifQ.d6RW5eZedEl949w-IeZ40Ukji3yXfFnMw3baLsow028'; + + const AppUser.sacha() + : id = 'sacha-arbonel', + name = 'Sacha Arbonel', + token = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FjaGEtYXJib25lbCJ9.fzDKEyiQ40J4YYgtZxpeQhn6ajX-GEnKZOOmcb-xa7M'; + + const AppUser.nash() + : id = 'neevash-ramdial', + name = 'Neevash Ramdial', + token = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaC1yYW1kaWFsIn0.yKqSehu_O5WJGh3-aa5qipnBRs7Qtue-1T9TZhT2ejw'; + + Map get data { + final parts = name.split(' '); + return { + 'first_name': parts[0], + 'last_name': parts[1], + 'full_name': name, + }; + } +} + +const appUsers = [ + AppUser.sahil(), + AppUser.sacha(), + AppUser.nash(), +]; diff --git a/example/lib/utils/utils.dart b/example/lib/client_provider.dart similarity index 61% rename from example/lib/utils/utils.dart rename to example/lib/client_provider.dart index 803c8584f..9dfe691dd 100644 --- a/example/lib/utils/utils.dart +++ b/example/lib/client_provider.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:stream_feed/stream_feed.dart'; @@ -10,8 +11,10 @@ class ClientProvider extends InheritedWidget { final StreamClient client; - static ClientProvider? of(BuildContext context) { - return context.dependOnInheritedWidgetOfExactType(); + static ClientProvider of(BuildContext context) { + final client = context.dependOnInheritedWidgetOfExactType(); + assert(client != null, 'Client not found in the widget tree'); + return client!; } @override @@ -19,7 +22,3 @@ class ClientProvider extends InheritedWidget { return old.child != child || old.client != client; } } - -extension ProviderX on BuildContext { - StreamClient get client => ClientProvider.of(this)!.client; -} diff --git a/example/lib/dummy_app_user.dart b/example/lib/dummy_app_user.dart deleted file mode 100644 index 3673cb9fa..000000000 --- a/example/lib/dummy_app_user.dart +++ /dev/null @@ -1,41 +0,0 @@ -enum DummyAppUser { - sahil, - sacha, - nash, -} - -/// Convenient class Extension on [DummyAppUser] enum -extension DummyAppUserX on DummyAppUser { - /// Convenient method Extension to generate an [id] from [DummyAppUser] enum - String? get id => { - DummyAppUser.sahil: 'sahil-kumar', - DummyAppUser.sacha: 'sacha-arbonel', - DummyAppUser.nash: 'neevash-ramdial', - }[this]; - - /// Convenient method Extension to generate a [name] from [DummyAppUser] enum - String? get name => { - DummyAppUser.sahil: 'Sahil Kumar', - DummyAppUser.sacha: 'Sacha Arbonel', - DummyAppUser.nash: 'Neevash Ramdial', - }[this]; - - /// Convenient method Extension to generate [data] from [DummyAppUser] enum - Map? get data => { - DummyAppUser.sahil: { - 'first_name': 'Sahil', - 'last_name': 'Kumar', - 'full_name': 'Sahil Kumar', - }, - DummyAppUser.sacha: { - 'first_name': 'Sacha', - 'last_name': 'Arbonel', - 'full_name': 'Sacha Arbonel', - }, - DummyAppUser.nash: { - 'first_name': 'Neevash', - 'last_name': 'Ramdial', - 'full_name': 'Neevash Ramdial', - }, - }[this]; -} diff --git a/example/lib/extension.dart b/example/lib/extension.dart new file mode 100644 index 000000000..005e0597b --- /dev/null +++ b/example/lib/extension.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:stream_feed/stream_feed.dart'; + +import 'client_provider.dart'; + +extension ProviderX on BuildContext { + StreamClient get client => ClientProvider.of(this).client; +} + +extension Snackbar on BuildContext { + void showSnackBar(final String message) { + ScaffoldMessenger.of(this).showSnackBar(SnackBar(content: Text(message))); + } +} diff --git a/example/lib/home.dart b/example/lib/home.dart index ca5eeb74b..26b3e408b 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -5,9 +5,9 @@ import 'package:flutter/material.dart'; import 'package:stream_feed/stream_feed.dart'; class HomeScreen extends StatefulWidget { - final User streamUser; + final StreamUser currentUser; - const HomeScreen({Key? key, required this.streamUser}) : super(key: key); + const HomeScreen({Key? key, required this.currentUser}) : super(key: key); @override _HomeScreenState createState() => _HomeScreenState(); @@ -31,9 +31,9 @@ class _HomeScreenState extends State { body: IndexedStack( index: _currentIndex, children: [ - TimelineScreen(streamUser: widget.streamUser), - ProfileScreen(streamUser: widget.streamUser), - PeopleScreen(streamUser: widget.streamUser), + TimelineScreen(currentUser: widget.currentUser), + ProfileScreen(currentUser: widget.currentUser), + PeopleScreen(currentUser: widget.currentUser), ], ), bottomNavigationBar: BottomNavigationBar( diff --git a/example/lib/people_screen.dart b/example/lib/people_screen.dart index 3b2cb1eac..d40f1a7d1 100644 --- a/example/lib/people_screen.dart +++ b/example/lib/people_screen.dart @@ -1,13 +1,13 @@ -import 'package:example/dummy_app_user.dart'; -import 'package:example/utils/utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:stream_feed/stream_feed.dart'; +import 'app_user.dart'; +import 'extension.dart'; class PeopleScreen extends StatefulWidget { - final User streamUser; + final StreamUser currentUser; - const PeopleScreen({Key? key, required this.streamUser}) : super(key: key); + const PeopleScreen({Key? key, required this.currentUser}) : super(key: key); @override _PeopleScreenState createState() => _PeopleScreenState(); @@ -16,8 +16,8 @@ class PeopleScreen extends StatefulWidget { class _PeopleScreenState extends State { @override Widget build(BuildContext context) { - final users = List.from(DummyAppUser.values) - ..removeWhere((it) => it.id == widget.streamUser.id); + final users = List.from(appUsers) + ..removeWhere((it) => it.id == widget.currentUser.id); final _client = context.client; final followDialog = CupertinoAlertDialog( @@ -50,29 +50,22 @@ class _PeopleScreenState extends State { builder: (_) => followDialog, ); if (result != null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Following User...'), - ), - ); + context.showSnackBar('Following User...'); final currentUserFeed = - _client.flatFeed('timeline', widget.streamUser.id!); - final selectedUserFeed = _client.flatFeed('user', user.id!); + _client.flatFeed('timeline', widget.currentUser.id); + final selectedUserFeed = _client.flatFeed('user', user.id); await currentUserFeed.follow(selectedUserFeed); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Followed User'), - ), - ); + + context.showSnackBar('Followed User'); } }, child: ListTile( leading: CircleAvatar( - child: Text(user.name![0]), + child: Text(user.name[0]), ), title: Text( - user.name!, + user.name, style: TextStyle( fontSize: 24, fontWeight: FontWeight.w300, diff --git a/example/lib/profile_screen.dart b/example/lib/profile_screen.dart index fcc2b9f00..ca8ddd496 100644 --- a/example/lib/profile_screen.dart +++ b/example/lib/profile_screen.dart @@ -1,4 +1,4 @@ -import 'package:example/utils/utils.dart'; +import 'extension.dart'; import 'package:flutter/material.dart'; import 'package:stream_feed/stream_feed.dart'; @@ -8,9 +8,10 @@ import 'add_activity_dialog.dart'; class ProfileScreen extends StatefulWidget { const ProfileScreen({ Key? key, - required this.streamUser, + required this.currentUser, }) : super(key: key); - final User streamUser; + + final StreamUser currentUser; @override _ProfileScreenState createState() => _ProfileScreenState(); @@ -25,7 +26,7 @@ class _ProfileScreenState extends State { Future _loadActivities({bool pullToRefresh = false}) async { if (!pullToRefresh) setState(() => _isLoading = true); - final userFeed = _client.flatFeed('user', widget.streamUser.id!); + final userFeed = _client.flatFeed('user', widget.currentUser.id); final data = await userFeed.getActivities(); if (!pullToRefresh) _isLoading = false; setState(() => activities = data); @@ -40,7 +41,7 @@ class _ProfileScreenState extends State { @override Widget build(BuildContext context) { - final user = widget.streamUser; + final user = widget.currentUser; return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () async { @@ -49,28 +50,19 @@ class _ProfileScreenState extends State { builder: (_) => AddActivityDialog(), ); if (message != null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Posting Activity...'), - ), - ); + context.showSnackBar('Posting Activity...'); final activity = Activity( - actor: user.id, + actor: user.ref, verb: 'tweet', object: '1', - extraData: { - 'tweet': message, - }, + extraData: {'tweet': message}, ); - final userFeed = _client.flatFeed('user', user.id!); + + final userFeed = _client.flatFeed('timeline', user.id); await userFeed.addActivity(activity); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Activity Posted...'), - ), - ); + context.showSnackBar('Activity Posted...'); _loadActivities(); } }, diff --git a/example/lib/timeline_screen.dart b/example/lib/timeline_screen.dart index 7e6165a95..09a5e66cb 100644 --- a/example/lib/timeline_screen.dart +++ b/example/lib/timeline_screen.dart @@ -1,13 +1,13 @@ -import 'package:example/utils/utils.dart'; +import 'extension.dart'; import 'package:flutter/material.dart'; import 'package:stream_feed/stream_feed.dart'; import 'activity_item.dart'; class TimelineScreen extends StatefulWidget { - final User streamUser; + final StreamUser currentUser; - const TimelineScreen({Key? key, required this.streamUser}) : super(key: key); + const TimelineScreen({Key? key, required this.currentUser}) : super(key: key); @override _TimelineScreenState createState() => _TimelineScreenState(); @@ -18,10 +18,21 @@ class _TimelineScreenState extends State { bool _isLoading = true; List activities = []; + late final Subscription _feedSubscription; + + Future _listenToFeed() async { + _feedSubscription = await _client + .flatFeed('timeline', widget.currentUser.id) + .subscribe((message) { + print(message); + }); + } + Future _loadActivities({bool pullToRefresh = false}) async { if (!pullToRefresh) setState(() => _isLoading = true); - final userFeed = _client.flatFeed('timeline', widget.streamUser.id!); + final userFeed = _client.flatFeed('timeline', widget.currentUser.id); final data = await userFeed.getActivities(); + final data2 = await userFeed.getEnrichedActivities(); if (!pullToRefresh) _isLoading = false; setState(() => activities = data); } @@ -30,9 +41,16 @@ class _TimelineScreenState extends State { void didChangeDependencies() { super.didChangeDependencies(); _client = context.client; + // _listenToFeed(); _loadActivities(); } + @override + void dispose() { + super.dispose(); + _feedSubscription.cancel(); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/example/pubspec.yaml b/example/pubspec.yaml index b3f909e45..75f4bca92 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,7 +1,6 @@ name: example description: A new Flutter application. - publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 @@ -11,10 +10,10 @@ environment: dependencies: flutter: sdk: flutter + cupertino_icons: ^1.0.2 + timeago: ^3.0.2 stream_feed: path: ../packages/stream_feed - timeago: ^3.0.2 - cupertino_icons: ^1.0.2 dev_dependencies: flutter_test: diff --git a/packages/stream_feed/lib/src/client/index.dart b/packages/stream_feed/lib/src/client/index.dart index 69d1d9b40..2b432e826 100644 --- a/packages/stream_feed/lib/src/client/index.dart +++ b/packages/stream_feed/lib/src/client/index.dart @@ -1,2 +1,3 @@ export 'analytics_client.dart'; export 'stream_client.dart'; +export 'stream_user.dart'; diff --git a/packages/stream_feed/lib/src/client/stream_client.dart b/packages/stream_feed/lib/src/client/stream_client.dart index 2c147c0de..8b9312061 100644 --- a/packages/stream_feed/lib/src/client/stream_client.dart +++ b/packages/stream_feed/lib/src/client/stream_client.dart @@ -11,7 +11,7 @@ import 'package:stream_feed/src/core/http/token.dart'; import 'package:stream_feed/src/core/index.dart'; import 'package:stream_feed/src/client/reactions_client.dart'; -import 'package:stream_feed/src/client/user_client.dart'; +import 'package:stream_feed/src/client/stream_user.dart'; import 'package:stream_feed/src/client/stream_client_impl.dart'; /// Different sides on which you can run this [StreamClient] on @@ -79,7 +79,7 @@ abstract class StreamClient { /// Convenient getter for [UsersClient]: /// /// {@macro user} - UserClient user(String userId); + StreamUser user(String userId); /// Convenient getter for [PersonalizationClient]: /// @@ -137,8 +137,8 @@ abstract class StreamClient { Future og(String targetUrl); /// - UserClient? get currentUser; + StreamUser? get currentUser; /// - Future setUser(Map data); + Future setUser(Map data); } diff --git a/packages/stream_feed/lib/src/client/stream_client_impl.dart b/packages/stream_feed/lib/src/client/stream_client_impl.dart index 8fe641a15..29c580137 100644 --- a/packages/stream_feed/lib/src/client/stream_client_impl.dart +++ b/packages/stream_feed/lib/src/client/stream_client_impl.dart @@ -17,7 +17,7 @@ import 'package:stream_feed/src/core/http/token.dart'; import 'package:stream_feed/src/core/index.dart'; import 'package:stream_feed/src/core/models/feed_id.dart'; -import 'package:stream_feed/src/client/user_client.dart'; +import 'package:stream_feed/src/client/stream_user.dart'; import 'package:stream_feed/src/client/stream_client.dart'; import 'package:stream_feed/src/core/util/extension.dart'; import 'package:stream_feed/src/core/util/token_helper.dart'; @@ -116,8 +116,9 @@ class StreamClientImpl implements StreamClient { if (record.stackTrace != null) print(record.stackTrace); } - UserClient? _currentUser; - bool _isUserConnected = false; + StreamUser? _currentUser; + + bool get _userConnected => _currentUser?.createdAt != null; late final _authExtension = { 'outgoing': (message) { @@ -161,8 +162,8 @@ class StreamClientImpl implements StreamClient { userToken: userToken, secret: secret); @override - UserClient user(String userId) => - UserClient(_api.users, userId, userToken: userToken, secret: secret); + StreamUser user(String userId) => + StreamUser(_api.users, userId, userToken: userToken, secret: secret); @override FileStorageClient get files => @@ -199,13 +200,12 @@ class StreamClientImpl implements StreamClient { } String _getUserId([String? userId]) { - var _userId = userId; assert( - _isUserConnected || _userId != null, + _userConnected || userId != null, 'Provide a `userId` if you are using it server-side ' 'or call `setUser` before creating feeds', ); - return _userId ??= currentUser!.userId; + return userId ??= currentUser!.id; } @override @@ -276,19 +276,17 @@ class StreamClientImpl implements StreamClient { } @override - UserClient? get currentUser => _currentUser; + StreamUser? get currentUser => _currentUser; @override - Future setUser(Map data) async { + Future setUser(Map data) async { assert( runner == Runner.client, 'This method can only be used client-side using a user token', ); final body = {...data}..remove('id'); - final userObject = await _currentUser!.getOrCreate(body); - _currentUser = user(userObject.id!); - _isUserConnected = true; - return userObject; + await _currentUser!.getOrCreate(body); + return _currentUser!; } } diff --git a/packages/stream_feed/lib/src/client/stream_user.dart b/packages/stream_feed/lib/src/client/stream_user.dart new file mode 100644 index 000000000..da522c990 --- /dev/null +++ b/packages/stream_feed/lib/src/client/stream_user.dart @@ -0,0 +1,152 @@ +import 'package:equatable/equatable.dart'; +import 'package:stream_feed/src/core/api/users_api.dart'; +import 'package:stream_feed/src/core/http/token.dart'; +import 'package:stream_feed/src/core/index.dart' show User; +import 'package:stream_feed/src/core/util/token_helper.dart'; +import 'package:stream_feed/stream_feed.dart'; + +/// {@template user} +/// Stream allows you to store user information +/// and embed them inside activities or use them for personalization. +/// +/// When stored in activities, users are automatically enriched by Stream. +/// {@endtemplate} +class StreamUser with EquatableMixin { + ///Initialize a [UsersClient] session object + StreamUser( + this._users, + this.id, { + Token? userToken, + String? secret, + }) : _secret = secret, + _userToken = userToken; + + ///User id + final String id; + + ///User JWT token + final Token? _userToken; + + ///The users client + final UsersAPI _users; + + /// You API secret + final String? _secret; + + /// Create a stream user ref + String get ref => createUserReference(id); + + Map? _data; + + /// User additional data. + Map? get data => _data; + + DateTime? _createdAt; + + /// When the user was created. + DateTime? get createdAt => _createdAt; + + DateTime? _updatedAt; + + /// When the user was last updated. + DateTime? get updatedAt => _updatedAt; + + int? _followersCount; + + /// Number of users that follow this user. + int? get followersCount => _followersCount; + + int? _followingCount; + + /// Number of users this user is following. + int? get followingCount => _followingCount; + + void _enrichUser(User user) { + _data = user.data; + _createdAt = user.createdAt; + _updatedAt = user.updatedAt; + _followersCount = user.followersCount; + _followingCount = user.followingCount; + } + + /// Create a new user in stream + /// + /// Usage + /// + /// ```dart + /// await user('john-doe').add( { + /// 'name': 'John Doe', + /// 'occupation': 'Software Engineer', + /// 'gender': 'male', + /// }); + /// ``` + /// API docs: [adding-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#adding-users) + Future create( + Map data, { + bool getOrCreate = false, + }) async { + final token = + _userToken ?? TokenHelper.buildUsersToken(_secret!, TokenAction.write); + final user = await _users.add(token, id, data, getOrCreate: getOrCreate); + _enrichUser(user); + return this; + } + + ///Get or Create a new user in stream + Future getOrCreate(Map data) => + create(data, getOrCreate: true); + + /// Delete the user + /// Usage: + ///```dart + ///await user('123').delete(); + ///``` + ///API docs: [removing-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#removing-users) + Future delete() { + final token = + _userToken ?? TokenHelper.buildUsersToken(_secret!, TokenAction.delete); + return _users.delete(token, id); + } + + /// Get the user profile, it includes the follow counts by default + Future profile({bool withFollowCounts = true}) => + get(withFollowCounts: withFollowCounts); + + /// Get the user data + /// Usage + /// ```dart + /// await user('123').get(); + /// ``` + /// API docs: [retrieving-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#retrieving-users) + Future get({ + bool withFollowCounts = false, + }) async { + final token = + _userToken ?? TokenHelper.buildUsersToken(_secret!, TokenAction.read); + final user = + await _users.get(token, id, withFollowCounts: withFollowCounts); + _enrichUser(user); + return this; + } + + /// Update the user + /// # Usage: + /// ```dart + /// await user('123').update({ + /// 'name': 'Jane Doe', + /// 'occupation': 'Software Engineer', + /// 'gender': 'female', + /// }); + /// ``` + /// API docs: [updating-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#updating-users) + Future update(Map data) async { + final token = + _userToken ?? TokenHelper.buildUsersToken(_secret!, TokenAction.write); + final user = await _users.update(token, id, data); + _enrichUser(user); + return this; + } + + @override + List get props => [id, createdAt]; +} diff --git a/packages/stream_feed/lib/src/client/user_client.dart b/packages/stream_feed/lib/src/client/user_client.dart deleted file mode 100644 index 2a207541c..000000000 --- a/packages/stream_feed/lib/src/client/user_client.dart +++ /dev/null @@ -1,101 +0,0 @@ -import 'package:stream_feed/src/core/api/users_api.dart'; -import 'package:stream_feed/src/core/http/token.dart'; -import 'package:stream_feed/src/core/models/user.dart'; -import 'package:stream_feed/src/core/util/token_helper.dart'; -import 'package:stream_feed/stream_feed.dart'; - -/// {@template user} -/// Stream allows you to store user information -/// and embed them inside activities or use them for personalization. -/// -/// When stored in activities, users are automatically enriched by Stream. -/// {@endtemplate} -class UserClient { - ///Initialize a [UsersClient] session object - const UserClient(this._user, this.userId, {this.userToken, this.secret}); - - ///User JWT token - final Token? userToken; - - ///User id - final String userId; - - ///The users client - final UsersAPI _user; - - /// You API secret - final String? secret; - - String get ref => createUserReference(userId); - - /// Create a new user in stream - /// - /// Usage - /// - /// ```dart - /// await user('john-doe').add( { - /// 'name': 'John Doe', - /// 'occupation': 'Software Engineer', - /// 'gender': 'male', - /// }); - /// ``` - /// API docs: [adding-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#adding-users) - Future create( - Map data, { - bool? getOrCreate, - }) { - final token = - userToken ?? TokenHelper.buildUsersToken(secret!, TokenAction.write); - return _user.add(token, userId, data, getOrCreate ?? false); - } - - ///Get or Create a new user in stream - Future getOrCreate(Map data) => - create(data, getOrCreate: true); - - /// Delete the user - /// Usage: - ///```dart - ///await user('123').delete(); - ///``` - ///API docs: [removing-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#removing-users) - Future delete() { - final token = - userToken ?? TokenHelper.buildUsersToken(secret!, TokenAction.delete); - return _user.delete(token, userId); - } - - /// Get the user profile, it includes the follow counts by default - Future profile({bool withFollowCounts = true}) => - get(withFollowCounts: withFollowCounts); - - /// Get the user data - /// Usage - /// ```dart - /// await user('123').get(); - /// ``` - /// API docs: [retrieving-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#retrieving-users) - Future get({ - bool? withFollowCounts = false, - }) { - final token = - userToken ?? TokenHelper.buildUsersToken(secret!, TokenAction.read); - return _user.get(token, userId, withFollowCounts!); - } - - /// Update the user - /// # Usage: - /// ```dart - /// await user('123').update({ - /// 'name': 'Jane Doe', - /// 'occupation': 'Software Engineer', - /// 'gender': 'female', - /// }); - /// ``` - /// API docs: [updating-users](https://getstream.io/activity-feeds/docs/flutter-dart/users_introduction/?language=dart#updating-users) - Future update(Map data) { - final token = - userToken ?? TokenHelper.buildUsersToken(secret!, TokenAction.write); - return _user.update(token, userId, data); - } -} diff --git a/packages/stream_feed/lib/src/core/api/users_api.dart b/packages/stream_feed/lib/src/core/api/users_api.dart index cc9388b6a..93363fa09 100644 --- a/packages/stream_feed/lib/src/core/api/users_api.dart +++ b/packages/stream_feed/lib/src/core/api/users_api.dart @@ -15,9 +15,9 @@ class UsersAPI { Future add( Token token, String id, - Map data, [ + Map data, { bool getOrCreate = false, - ]) async { + }) async { checkArgument(id.isNotEmpty, 'Missing user ID'); final user = User(id: id, data: data); final result = await _client.post>( @@ -30,8 +30,11 @@ class UsersAPI { } /// Get the user data - Future get(Token token, String id, - [bool withFollowCounts = false]) async { + Future get( + Token token, + String id, { + bool withFollowCounts = false, + }) async { checkArgument(id.isNotEmpty, 'Missing user ID'); final result = await _client.get( Routes.buildUsersUrl('$id/'), diff --git a/packages/stream_feed/lib/src/core/index.dart b/packages/stream_feed/lib/src/core/index.dart index 1cfa0f293..2019d6327 100644 --- a/packages/stream_feed/lib/src/core/index.dart +++ b/packages/stream_feed/lib/src/core/index.dart @@ -1,6 +1,3 @@ -export 'package:dio/dio.dart' show MultipartFile; -export 'package:http_parser/http_parser.dart' show MediaType; - export 'http/stream_http_client.dart' show StreamHttpClientOptions; export 'http/token.dart'; export 'location.dart'; diff --git a/packages/stream_feed/lib/stream_feed.dart b/packages/stream_feed/lib/stream_feed.dart index fa6157148..30669ffa5 100644 --- a/packages/stream_feed/lib/stream_feed.dart +++ b/packages/stream_feed/lib/stream_feed.dart @@ -1,5 +1,7 @@ library stream_feed_dart; +export 'package:faye_dart/faye_dart.dart' show Subscription; export 'package:logging/logging.dart' show Level; + export 'src/client/index.dart'; -export 'src/core/index.dart'; +export 'src/core/index.dart' hide User; diff --git a/packages/stream_feed/test/faye_client_test.dart b/packages/stream_feed/test/faye_client_test.dart index a283e74d5..bd8d21ec4 100644 --- a/packages/stream_feed/test/faye_client_test.dart +++ b/packages/stream_feed/test/faye_client_test.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:stream_feed/src/client/stream_client.dart'; -import 'package:stream_feed/src/client/stream_client_impl.dart'; import 'package:stream_feed/src/core/models/feed_id.dart'; import 'package:stream_feed/src/core/models/realtime_message.dart'; import 'package:stream_feed/stream_feed.dart'; diff --git a/packages/stream_feed/test/models_test.dart b/packages/stream_feed/test/models_test.dart index a3f8a0667..38862b7e4 100644 --- a/packages/stream_feed/test/models_test.dart +++ b/packages/stream_feed/test/models_test.dart @@ -10,6 +10,7 @@ import 'package:stream_feed/src/core/models/group.dart'; import 'package:stream_feed/src/core/models/paginated_reactions.dart'; import 'package:stream_feed/src/core/models/personalized_feed.dart'; import 'package:stream_feed/src/core/models/thumbnail.dart'; +import 'package:stream_feed/src/core/models/user.dart'; import 'package:stream_feed/stream_feed.dart'; import 'package:test/test.dart'; diff --git a/packages/stream_feed/test/users_client_test.dart b/packages/stream_feed/test/users_client_test.dart index fb23020b4..eb9c54b09 100644 --- a/packages/stream_feed/test/users_client_test.dart +++ b/packages/stream_feed/test/users_client_test.dart @@ -1,6 +1,6 @@ import 'package:dio/dio.dart'; import 'package:mocktail/mocktail.dart'; -import 'package:stream_feed/src/client/user_client.dart'; +import 'package:stream_feed/src/client/stream_user.dart'; import 'package:stream_feed/src/core/http/token.dart'; import 'package:stream_feed/src/core/models/user.dart'; import 'package:test/test.dart'; @@ -13,7 +13,7 @@ void main() { const token = Token('dummyToken'); const id = 'john-doe'; - final client = UserClient(api, id, userToken: token); + final client = StreamUser(api, id, userToken: token); test('ref', () { expect(client.ref, 'SU:john-doe'); @@ -26,9 +26,10 @@ void main() { 'gender': 'male', }; const user = User(id: id, data: data); - when(() => api.add(token, id, data, true)).thenAnswer((_) async => user); + when(() => api.add(token, id, data, getOrCreate: true)) + .thenAnswer((_) async => user); await client.getOrCreate(data); - verify(() => api.add(token, id, data, true)).called(1); + verify(() => api.add(token, id, data, getOrCreate: true)).called(1); }); test('add', () async { const data = { @@ -62,10 +63,11 @@ void main() { 'gender': 'male', }; const user = User(id: id, data: data); - when(() => api.get(token, id, true)).thenAnswer((_) async => user); + when(() => api.get(token, id, withFollowCounts: true)) + .thenAnswer((_) async => user); await client.profile(); - verify(() => api.get(token, id, true)).called(1); + verify(() => api.get(token, id, withFollowCounts: true)).called(1); }); test('get', () async { From 4d801d1eb12cbd98e677d057cd7edf9ff8058d7b Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Sat, 8 May 2021 00:11:30 +0530 Subject: [PATCH 0002/1241] (stream_feed): remove web_socket_channel dependency Signed-off-by: Sahil Kumar --- packages/stream_feed/pubspec.yaml | 3 +-- packages/stream_feed/test/mock.dart | 18 ------------------ 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/packages/stream_feed/pubspec.yaml b/packages/stream_feed/pubspec.yaml index c80cb22ed..25c8c5954 100644 --- a/packages/stream_feed/pubspec.yaml +++ b/packages/stream_feed/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_feed -description: Stream Feed official Dart SDK. Build your own feed experience using Dart and Flutter. +description: Stream Feed official Dart SDK. Build your own feed experience using Dart and Flutter. version: 0.1.2 repository: https://github.com/GetStream/stream-feed-flutter issue_tracker: https://github.com/GetStream/stream-feed-flutter/issues @@ -17,7 +17,6 @@ dependencies: logging: ^1.0.1 meta: ^1.3.0 mime: ^1.0.0 - web_socket_channel: ^2.1.0 dev_dependencies: build_runner: ^2.0.2 diff --git a/packages/stream_feed/test/mock.dart b/packages/stream_feed/test/mock.dart index 34b266e57..044f05dac 100644 --- a/packages/stream_feed/test/mock.dart +++ b/packages/stream_feed/test/mock.dart @@ -9,7 +9,6 @@ import 'package:stream_feed/src/core/api/reactions_api.dart'; import 'package:stream_feed/src/core/api/stream_api.dart'; import 'package:stream_feed/src/core/api/users_api.dart'; import 'package:stream_feed/src/core/http/stream_http_client.dart'; -import 'package:web_socket_channel/web_socket_channel.dart'; class MockHttpClientAdapter extends Mock implements HttpClientAdapter {} @@ -43,21 +42,4 @@ class MockFeedAPI extends Mock implements FeedAPI {} class MockAPI extends Mock implements StreamAPI {} -class Functions { - WebSocketChannel? connectFunc( - String url, { - Iterable? protocols, - Duration? connectionTimeout, - }) => - null; - -// void handleFunc(Event event) => null; -} - -class MockFunctions extends Mock implements Functions {} - -class MockWSChannel extends Mock implements WebSocketChannel {} - -class MockWSSink extends Mock implements WebSocketSink {} - class MultipartFileFake extends Fake implements MultipartFile {} From 9f8ff0091277203e0501bdf675c1a6c665a7104e Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Mon, 17 May 2021 08:16:40 -0400 Subject: [PATCH 0003/1241] scaffold core --- packages/stream_feed_flutter_core/.gitignore | 13 ++ .../stream_feed_flutter_core/CHANGELOG.md | 3 + packages/stream_feed_flutter_core/LICENSE | 219 ++++++++++++++++++ packages/stream_feed_flutter_core/README.md | 22 ++ .../analysis_options.yaml | 14 ++ .../stream_feed_flutter_core_example.dart | 6 + .../src/stream_feed_flutter_core_base.dart | 6 + .../lib/stream_feed_flutter_core.dart | 8 + .../stream_feed_flutter_core/pubspec.yaml | 14 ++ .../test/stream_feed_flutter_core_test.dart | 16 ++ 10 files changed, 321 insertions(+) create mode 100644 packages/stream_feed_flutter_core/.gitignore create mode 100644 packages/stream_feed_flutter_core/CHANGELOG.md create mode 100644 packages/stream_feed_flutter_core/LICENSE create mode 100644 packages/stream_feed_flutter_core/README.md create mode 100644 packages/stream_feed_flutter_core/analysis_options.yaml create mode 100644 packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart create mode 100644 packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart create mode 100644 packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart create mode 100644 packages/stream_feed_flutter_core/pubspec.yaml create mode 100644 packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart diff --git a/packages/stream_feed_flutter_core/.gitignore b/packages/stream_feed_flutter_core/.gitignore new file mode 100644 index 000000000..0c44ab06c --- /dev/null +++ b/packages/stream_feed_flutter_core/.gitignore @@ -0,0 +1,13 @@ +# Files and directories created by pub +.dart_tool/ +.packages + +# Omit commiting pubspec.lock for library packages: +# https://dart.dev/guides/libraries/private-files#pubspeclock +pubspec.lock + +# Conventional directory for build outputs +build/ + +# Directory created by dartdoc +doc/api/ diff --git a/packages/stream_feed_flutter_core/CHANGELOG.md b/packages/stream_feed_flutter_core/CHANGELOG.md new file mode 100644 index 000000000..61d8cf982 --- /dev/null +++ b/packages/stream_feed_flutter_core/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.0 + +- domain parking 🏎 diff --git a/packages/stream_feed_flutter_core/LICENSE b/packages/stream_feed_flutter_core/LICENSE new file mode 100644 index 000000000..4dcdfd417 --- /dev/null +++ b/packages/stream_feed_flutter_core/LICENSE @@ -0,0 +1,219 @@ +SOURCE CODE LICENSE AGREEMENT + +IMPORTANT - READ THIS CAREFULLY BEFORE DOWNLOADING, INSTALLING, USING OR +ELECTRONICALLY ACCESSING THIS PROPRIETARY PRODUCT. + +THIS IS A LEGAL AGREEMENT BETWEEN STREAM.IO, INC. (“STREAM.IO”) AND THE +BUSINESS ENTITY OR PERSON FOR WHOM YOU (“YOU”) ARE ACTING (“CUSTOMER”) AS THE +LICENSEE OF THE PROPRIETARY SOFTWARE INTO WHICH THIS AGREEMENT HAS BEEN +INCLUDED (THE “AGREEMENT”). YOU AGREE THAT YOU ARE THE CUSTOMER, OR YOU ARE AN +EMPLOYEE OR AGENT OF CUSTOMER AND ARE ENTERING INTO THIS AGREEMENT FOR LICENSE +OF THE SOFTWARE BY CUSTOMER FOR CUSTOMER’S BUSINESS PURPOSES AS DESCRIBED IN +AND IN ACCORDANCE WITH THIS AGREEMENT. YOU HEREBY AGREE THAT YOU ENTER INTO +THIS AGREEMENT ON BEHALF OF CUSTOMER AND THAT YOU HAVE THE AUTHORITY TO BIND +CUSTOMER TO THIS AGREEMENT. + +STREAM.IO IS WILLING TO LICENSE THE SOFTWARE TO CUSTOMER ONLY ON THE FOLLOWING +CONDITIONS: (1) YOU ARE A CURRENT CUSTOMER OF STREAM.IO; (2) YOU ARE NOT A +COMPETITOR OF STREAM.IO; AND (3) THAT YOU ACCEPT ALL THE TERMS IN THIS +AGREEMENT. BY DOWNLOADING, INSTALLING, CONFIGURING, ACCESSING OR OTHERWISE +USING THE SOFTWARE, INCLUDING ANY UPDATES, UPGRADES, OR NEWER VERSIONS, YOU +REPRESENT, WARRANT AND ACKNOWLEDGE THAT (A) CUSTOMER IS A CURRENT CUSTOMER OF +STREAM.IO; (B) CUSTOMER IS NOT A COMPETITOR OF STREAM.IO; AND THAT (C) YOU HAVE +READ THIS AGREEMENT, UNDERSTAND THIS AGREEMENT, AND THAT CUSTOMER AGREES TO BE +BOUND BY ALL THE TERMS OF THIS AGREEMENT. + +IF YOU DO NOT AGREE TO ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT, +STREAM.IO IS UNWILLING TO LICENSE THE SOFTWARE TO CUSTOMER, AND THEREFORE, DO +NOT COMPLETE THE DOWNLOAD PROCESS, ACCESS OR OTHERWISE USE THE SOFTWARE, AND +CUSTOMER SHOULD IMMEDIATELY RETURN THE SOFTWARE AND CEASE ANY USE OF THE +SOFTWARE. + +1. SOFTWARE. The Stream.io software accompanying this Agreement, may include +Source Code, Executable Object Code, associated media, printed materials and +documentation (collectively, the “Software”). The Software also includes any +updates or upgrades to or new versions of the original Software, if and when +made available to you by Stream.io. “Source Code” means computer programming +code in human readable form that is not suitable for machine execution without +the intervening steps of interpretation or compilation. “Executable Object +Code" means the computer programming code in any other form than Source Code +that is not readily perceivable by humans and suitable for machine execution +without the intervening steps of interpretation or compilation. “Site” means a +Customer location controlled by Customer. “Authorized User” means any employee +or contractor of Customer working at the Site, who has signed a written +confidentiality agreement with Customer or is otherwise bound in writing by +confidentiality and use obligations at least as restrictive as those imposed +under this Agreement. + +2. LICENSE GRANT. Subject to the terms and conditions of this Agreement, in +consideration for the representations, warranties, and covenants made by +Customer in this Agreement, Stream.io grants to Customer, during the term of +this Agreement, a personal, non-exclusive, non-transferable, non-sublicensable +license to: + +a. install and use Software Source Code on password protected computers at a Site, +restricted to Authorized Users; + +b. create derivative works, improvements (whether or not patentable), extensions +and other modifications to the Software Source Code (“Modifications”) to build +unique scalable newsfeeds, activity streams, and in-app messaging via Stream’s +application program interface (“API”); + +c. compile the Software Source Code to create Executable Object Code versions of +the Software Source Code and Modifications to build such newsfeeds, activity +streams, and in-app messaging via the API; + +d. install, execute and use such Executable Object Code versions solely for +Customer’s internal business use (including development of websites through +which data generated by Stream services will be streamed (“Apps”)); + +e. use and distribute such Executable Object Code as part of Customer’s Apps; and + +f. make electronic copies of the Software and Modifications as required for backup +or archival purposes. + +3. RESTRICTIONS. Customer is responsible for all activities that occur in +connection with the Software. Customer will not, and will not attempt to: (a) +sublicense or transfer the Software or any Source Code related to the Software +or any of Customer’s rights under this Agreement, except as otherwise provided +in this Agreement, (b) use the Software Source Code for the benefit of a third +party or to operate a service; (c) allow any third party to access or use the +Software Source Code; (d) sublicense or distribute the Software Source Code or +any Modifications in Source Code or other derivative works based on any part of +the Software Source Code; (e) use the Software in any manner that competes with +Stream.io or its business; or (e) otherwise use the Software in any manner that +exceeds the scope of use permitted in this Agreement. Customer shall use the +Software in compliance with any accompanying documentation any laws applicable +to Customer. + +4. OPEN SOURCE. Customer and its Authorized Users shall not use any software or +software components that are open source in conjunction with the Software +Source Code or any Modifications in Source Code or in any way that could +subject the Software to any open source licenses. + +5. CONTRACTORS. Under the rights granted to Customer under this Agreement, +Customer may permit its employees, contractors, and agencies of Customer to +become Authorized Users to exercise the rights to the Software granted to +Customer in accordance with this Agreement solely on behalf of Customer to +provide services to Customer; provided that Customer shall be liable for the +acts and omissions of all Authorized Users to the extent any of such acts or +omissions, if performed by Customer, would constitute a breach of, or otherwise +give rise to liability to Customer under, this Agreement. Customer shall not +and shall not permit any Authorized User to use the Software except as +expressly permitted in this Agreement. + +6. COMPETITIVE PRODUCT DEVELOPMENT. Customer shall not use the Software in any way +to engage in the development of products or services which could be reasonably +construed to provide a complete or partial functional or commercial alternative +to Stream.io’s products or services (a “Competitive Product”). Customer shall +ensure that there is no direct or indirect use of, or sharing of, Software +source code, or other information based upon or derived from the Software to +develop such products or services. Without derogating from the generality of +the foregoing, development of Competitive Products shall include having direct +or indirect access to, supervising, consulting or assisting in the development +of, or producing any specifications, documentation, object code or source code +for, all or part of a Competitive Product. + +7. LIMITATION ON MODIFICATIONS. Notwithstanding any provision in this Agreement, +Modifications may only be created and used by Customer as permitted by this +Agreement and Modification Source Code may not be distributed to third parties. +Customer will not assert against Stream.io, its affiliates, or their customers, +direct or indirect, agents and contractors, in any way, any patent rights that +Customer may obtain relating to any Modifications for Stream.io, its +affiliates’, or their customers’, direct or indirect, agents’ and contractors’ +manufacture, use, import, offer for sale or sale of any Stream.io products or +services. + +8. DELIVERY AND ACCEPTANCE. The Software will be delivered electronically pursuant +to Stream.io standard download procedures. The Software is deemed accepted upon +delivery. + +9. IMPLEMENTATION AND SUPPORT. Stream.io has no obligation under this Agreement to +provide any support or consultation concerning the Software. + +10. TERM AND TERMINATION. The term of this Agreement begins when the Software is +downloaded or accessed and shall continue until terminated. Either party may +terminate this Agreement upon written notice. This Agreement shall +automatically terminate if Customer is or becomes a competitor of Stream.io or +makes or sells any Competitive Products. Upon termination of this Agreement for +any reason, (a) all rights granted to Customer in this Agreement immediately +cease to exist, (b) Customer must promptly discontinue all use of the Software +and return to Stream.io or destroy all copies of the Software in Customer’s +possession or control. Any continued use of the Software by Customer or attempt +by Customer to exercise any rights under this Agreement after this Agreement +has terminated shall be considered copyright infringement and subject Customer +to applicable remedies for copyright infringement. Sections 2, 5, 6, 8 and 9 +shall survive expiration or termination of this Agreement for any reason. + +11. OWNERSHIP. As between the parties, the Software and all worldwide intellectual +property rights and proprietary rights relating thereto or embodied therein, +are the exclusive property of Stream.io and its suppliers. Stream.io and its +suppliers reserve all rights in and to the Software not expressly granted to +Customer in this Agreement, and no other licenses or rights are granted by +implication, estoppel or otherwise. + +12. WARRANTY DISCLAIMER. USE OF THIS SOFTWARE IS ENTIRELY AT YOURS AND CUSTOMER’S +OWN RISK. THE SOFTWARE IS PROVIDED “AS IS” WITHOUT ANY WARRANTY OF ANY KIND +WHATSOEVER. STREAM.IO DOES NOT MAKE, AND HEREBY DISCLAIMS, ANY WARRANTY OF ANY +KIND, WHETHER EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING WITHOUT +LIMITATION, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, TITLE, NON-INFRINGEMENT OF THIRD-PARTY RIGHTS, RESULTS, EFFORTS, +QUALITY OR QUIET ENJOYMENT. STREAM.IO DOES NOT WARRANT THAT THE SOFTWARE IS +ERROR-FREE, WILL FUNCTION WITHOUT INTERRUPTION, WILL MEET ANY SPECIFIC NEED +THAT CUSTOMER HAS, THAT ALL DEFECTS WILL BE CORRECTED OR THAT IT IS +SUFFICIENTLY DOCUMENTED TO BE USABLE BY CUSTOMER. TO THE EXTENT THAT STREAM.IO +MAY NOT DISCLAIM ANY WARRANTY AS A MATTER OF APPLICABLE LAW, THE SCOPE AND +DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER SUCH LAW. +CUSTOMER ACKNOWLEDGES THAT IT HAS RELIED ON NO WARRANTIES OTHER THAN THE +EXPRESS WARRANTIES IN THIS AGREEMENT. + +13. LIMITATION OF LIABILITY. TO THE FULLEST EXTENT PERMISSIBLE BY LAW, STREAM.IO’S +TOTAL LIABILITY FOR ALL DAMAGES ARISING OUT OF OR RELATED TO THE SOFTWARE OR +THIS AGREEMENT, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, +SHALL NOT EXCEED $100. IN NO EVENT WILL STREAM.IO BE LIABLE FOR ANY INDIRECT, +CONSEQUENTIAL, EXEMPLARY, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES OF ANY KIND +WHATSOEVER, INCLUDING ANY LOST DATA AND LOST PROFITS, ARISING FROM OR RELATING +TO THE SOFTWARE EVEN IF STREAM.IO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. CUSTOMER ACKNOWLEDGES THAT THIS PROVISION REFLECTS THE AGREED UPON +ALLOCATION OF RISK FOR THIS AGREEMENT AND THAT STREAM.IO WOULD NOT ENTER INTO +THIS AGREEMENT WITHOUT THESE LIMITATIONS ON ITS LIABILITY. + +14. General. Customer may not assign or transfer this Agreement, by operation of +law or otherwise, or any of its rights under this Agreement (including the +license rights granted to Customer) to any third party without Stream.io’s +prior written consent, which consent will not be unreasonably withheld or +delayed. Stream.io may assign this Agreement, without consent, including, but +limited to, affiliate or any successor to all or substantially all its business +or assets to which this Agreement relates, whether by merger, sale of assets, +sale of stock, reorganization or otherwise. Any attempted assignment or +transfer in violation of the foregoing will be null and void. Stream.io shall +not be liable hereunder by reason of any failure or delay in the performance of +its obligations hereunder for any cause which is beyond the reasonable control. +All notices, consents, and approvals under this Agreement must be delivered in +writing by courier, by electronic mail, or by certified or registered mail, +(postage prepaid and return receipt requested) to the other party at the +address set forth in the customer agreement between Stream.io and Customer and +will be effective upon receipt or when delivery is refused. This Agreement will +be governed by and interpreted in accordance with the laws of the State of +Colorado, without reference to its choice of laws rules. The United Nations +Convention on Contracts for the International Sale of Goods does not apply to +this Agreement. Any action or proceeding arising from or relating to this +Agreement shall be brought in a federal or state court in Denver, Colorado, and +each party irrevocably submits to the jurisdiction and venue of any such court +in any such action or proceeding. All waivers must be in writing. Any waiver or +failure to enforce any provision of this Agreement on one occasion will not be +deemed a waiver of any other provision or of such provision on any other +occasion. If any provision of this Agreement is unenforceable, such provision +will be changed and interpreted to accomplish the objectives of such provision +to the greatest extent possible under applicable law and the remaining +provisions will continue in full force and effect. Customer shall not violate +any applicable law, rule or regulation, including those regarding the export of +technical data. The headings of Sections of this Agreement are for convenience +and are not to be used in interpreting this Agreement. As used in this +Agreement, the word “including” means “including but not limited to.” This +Agreement (including all exhibits and attachments) constitutes the entire +agreement between the parties regarding the subject hereof and supersedes all +prior or contemporaneous agreements, understandings and communication, whether +written or oral. This Agreement may be amended only by a written document +signed by both parties. The terms of any purchase order or similar document +submitted by Customer to Stream.io will have no effect. \ No newline at end of file diff --git a/packages/stream_feed_flutter_core/README.md b/packages/stream_feed_flutter_core/README.md new file mode 100644 index 000000000..d73af4673 --- /dev/null +++ b/packages/stream_feed_flutter_core/README.md @@ -0,0 +1,22 @@ +A library for Dart developers. + +Created from templates made available by Stagehand under a BSD-style +[license](https://github.com/dart-lang/stagehand/blob/master/LICENSE). + +## Usage + +A simple usage example: + +```dart +import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart'; + +main() { + var awesome = new Awesome(); +} +``` + +## Features and bugs + +Please file feature requests and bugs at the [issue tracker][tracker]. + +[tracker]: http://example.com/issues/replaceme diff --git a/packages/stream_feed_flutter_core/analysis_options.yaml b/packages/stream_feed_flutter_core/analysis_options.yaml new file mode 100644 index 000000000..a686c1b45 --- /dev/null +++ b/packages/stream_feed_flutter_core/analysis_options.yaml @@ -0,0 +1,14 @@ +# Defines a default set of lint rules enforced for +# projects at Google. For details and rationale, +# see https://github.com/dart-lang/pedantic#enabled-lints. +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. +# Uncomment to specify additional rules. +# linter: +# rules: +# - camel_case_types + +analyzer: +# exclude: +# - path/to/excluded/files/** diff --git a/packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart b/packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart new file mode 100644 index 000000000..f1fd9cdc4 --- /dev/null +++ b/packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart @@ -0,0 +1,6 @@ +import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart'; + +void main() { + var awesome = Awesome(); + print('awesome: ${awesome.isAwesome}'); +} diff --git a/packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart b/packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart new file mode 100644 index 000000000..e8a6f1590 --- /dev/null +++ b/packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart @@ -0,0 +1,6 @@ +// TODO: Put public facing types in this file. + +/// Checks if you are awesome. Spoiler: you are. +class Awesome { + bool get isAwesome => true; +} diff --git a/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart new file mode 100644 index 000000000..94be03247 --- /dev/null +++ b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart @@ -0,0 +1,8 @@ +/// Support for doing something awesome. +/// +/// More dartdocs go here. +library stream_feed_flutter_core; + +export 'src/stream_feed_flutter_core_base.dart'; + +// TODO: Export any libraries intended for clients of this package. diff --git a/packages/stream_feed_flutter_core/pubspec.yaml b/packages/stream_feed_flutter_core/pubspec.yaml new file mode 100644 index 000000000..b9916e53a --- /dev/null +++ b/packages/stream_feed_flutter_core/pubspec.yaml @@ -0,0 +1,14 @@ +name: stream_feed_flutter_core +description: Stream Feed official Flutter SDK Core. Build your own chat experience using Dart and Flutter. +version: 0.0.0 +homepage: https://getstream.io/ + +environment: + sdk: '>=2.10.0 <3.0.0' + +#dependencies: +# path: ^1.7.0 + +dev_dependencies: + pedantic: ^1.9.0 + test: ^1.14.4 diff --git a/packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart b/packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart new file mode 100644 index 000000000..084c5b7fe --- /dev/null +++ b/packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart @@ -0,0 +1,16 @@ +import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart'; +import 'package:test/test.dart'; + +void main() { + group('A group of tests', () { + Awesome awesome; + + setUp(() { + awesome = Awesome(); + }); + + test('First Test', () { + expect(awesome.isAwesome, isTrue); + }); + }); +} From 69cbf35dfd657b5ab5b85882fc7106b321255510 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Mon, 17 May 2021 09:09:20 -0400 Subject: [PATCH 0004/1241] core wip --- .../stream_feed/lib/src/client/index.dart | 1 + packages/stream_feed/lib/stream_feed.dart | 4 +- .../stream_feed_flutter_core_example.dart | 4 +- .../lib/src/stream_feed_core.dart | 144 ++++++++++++++++++ .../src/stream_feed_flutter_core_base.dart | 6 - .../lib/stream_feed_flutter_core.dart | 2 +- .../stream_feed_flutter_core/pubspec.yaml | 15 +- .../stream_feed_flutter_core/test/mocks.dart | 13 ++ .../test/stream_feed_flutter_core_test.dart | 30 ++-- 9 files changed, 194 insertions(+), 25 deletions(-) create mode 100644 packages/stream_feed_flutter_core/lib/src/stream_feed_core.dart delete mode 100644 packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart create mode 100644 packages/stream_feed_flutter_core/test/mocks.dart diff --git a/packages/stream_feed/lib/src/client/index.dart b/packages/stream_feed/lib/src/client/index.dart index dd636f70d..3dc3291a6 100644 --- a/packages/stream_feed/lib/src/client/index.dart +++ b/packages/stream_feed/lib/src/client/index.dart @@ -1,2 +1,3 @@ export 'analytics_client.dart'; export 'stream_feed_client.dart'; +export 'user_client.dart'; diff --git a/packages/stream_feed/lib/stream_feed.dart b/packages/stream_feed/lib/stream_feed.dart index fa6157148..d075bf24f 100644 --- a/packages/stream_feed/lib/stream_feed.dart +++ b/packages/stream_feed/lib/stream_feed.dart @@ -1,5 +1,5 @@ -library stream_feed_dart; +library stream_feed; -export 'package:logging/logging.dart' show Level; +export 'package:logging/logging.dart' show Level, Logger; export 'src/client/index.dart'; export 'src/core/index.dart'; diff --git a/packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart b/packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart index f1fd9cdc4..2b78d2c75 100644 --- a/packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart +++ b/packages/stream_feed_flutter_core/example/stream_feed_flutter_core_example.dart @@ -1,6 +1,6 @@ import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart'; void main() { - var awesome = Awesome(); - print('awesome: ${awesome.isAwesome}'); + // var awesome = Awesome(); + // print('awesome: ${awesome.isAwesome}'); } diff --git a/packages/stream_feed_flutter_core/lib/src/stream_feed_core.dart b/packages/stream_feed_flutter_core/lib/src/stream_feed_core.dart new file mode 100644 index 000000000..08fb7db33 --- /dev/null +++ b/packages/stream_feed_flutter_core/lib/src/stream_feed_core.dart @@ -0,0 +1,144 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:stream_feed/stream_feed.dart'; + +/// Widget used to provide information about the chat to the widget tree. +/// This Widget is used to react to life cycle changes and system updates. +/// When the app goes into the background, the websocket connection is kept +/// alive for two minutes before being terminated. +/// +/// Conversely, when app is resumed or restarted, a new connection is initiated. +/// +/// ```dart +/// class MyApp extends StatelessWidget { +/// final StreamFeedClient client; +/// +/// MyApp(this.client); +/// +/// @override +/// Widget build(BuildContext context) { +/// return MaterialApp( +/// home: Container( +/// child: StreamFeedCore( +/// client: client, +/// child: child, +/// ), +/// ), +/// ); +/// } +/// } +/// ``` +/// +class StreamFeedCore extends StatefulWidget { + /// Constructor used for creating a new instance of [StreamFeedCore]. + /// + /// [StreamFeedCore] is a stateful widget which reacts to system events and + /// updates Stream's connection status accordingly. + const StreamFeedCore({ + Key? key, + required this.client, + required this.child, + // this.onBackgroundEventReceived, + // this.backgroundKeepAlive = const Duration(minutes: 1), + }) : super(key: key); + + /// Instance of Stream Chat Client containing information about the current + /// application. + final StreamFeedClient client; + + /// Widget descendant. + final Widget child; + + /// The amount of time that will pass before disconnecting the client in + /// the background + // final Duration backgroundKeepAlive; + + /// Handler called whenever the [client] receives a new [Event] while the app + /// is in background. Can be used to display various notifications depending + /// upon the [Event.type] + // final EventHandler? onBackgroundEventReceived; + + @override + StreamFeedCoreState createState() => StreamFeedCoreState(); + + /// Use this method to get the current [StreamFeedCoreState] instance + static StreamFeedCoreState of(BuildContext context) { + StreamFeedCoreState? StreamFeedState; + + StreamFeedState = context.findAncestorStateOfType(); + + assert( + StreamFeedState != null, + 'You must have a StreamFeed widget at the top of your widget tree', + ); + + return StreamFeedState!; + } +} + +/// State class associated with [StreamFeedCore]. +class StreamFeedCoreState extends State + with WidgetsBindingObserver { + /// Initialized client used throughout the application. + StreamFeedClient get client => widget.client; + + Timer? _disconnectTimer; + + @override + Widget build(BuildContext context) => widget.child; + + /// The current user + UserClient? get user => client.currentUser; + + /// The current user as a stream + // Stream get userStream => client.state.userStream; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance?.addObserver(this); + } + + StreamSubscription? _eventSubscription; + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + // if (user != null) { + // if (state == AppLifecycleState.paused) { + // if (widget.onBackgroundEventReceived == null) { + // client.disconnect(); + // return; + // } + // _eventSubscription = client.on().listen( + // widget.onBackgroundEventReceived, + // ); + + // void onTimerComplete() { + // _eventSubscription?.cancel(); + // client.disconnect(); + // } + + // _disconnectTimer = Timer(widget.backgroundKeepAlive, onTimerComplete); + // } else if (state == AppLifecycleState.resumed) { + // if (_disconnectTimer?.isActive == true) { + // _eventSubscription?.cancel(); + // _disconnectTimer?.cancel(); + // } else { + // if (client.wsConnectionStatus == ConnectionStatus.disconnected) { + // client.connect(); + // } + // } + // } + // } + } + + @override + void dispose() { + WidgetsBinding.instance?.removeObserver(this); + _eventSubscription?.cancel(); + _disconnectTimer?.cancel(); + super.dispose(); + } +} diff --git a/packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart b/packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart deleted file mode 100644 index e8a6f1590..000000000 --- a/packages/stream_feed_flutter_core/lib/src/stream_feed_flutter_core_base.dart +++ /dev/null @@ -1,6 +0,0 @@ -// TODO: Put public facing types in this file. - -/// Checks if you are awesome. Spoiler: you are. -class Awesome { - bool get isAwesome => true; -} diff --git a/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart index 94be03247..e3814d775 100644 --- a/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart +++ b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart @@ -3,6 +3,6 @@ /// More dartdocs go here. library stream_feed_flutter_core; -export 'src/stream_feed_flutter_core_base.dart'; +export 'src/stream_feed_core.dart'; // TODO: Export any libraries intended for clients of this package. diff --git a/packages/stream_feed_flutter_core/pubspec.yaml b/packages/stream_feed_flutter_core/pubspec.yaml index b9916e53a..19e290a20 100644 --- a/packages/stream_feed_flutter_core/pubspec.yaml +++ b/packages/stream_feed_flutter_core/pubspec.yaml @@ -2,13 +2,20 @@ name: stream_feed_flutter_core description: Stream Feed official Flutter SDK Core. Build your own chat experience using Dart and Flutter. version: 0.0.0 homepage: https://getstream.io/ +publish_to: none environment: - sdk: '>=2.10.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' + flutter: ">=1.17.0" -#dependencies: -# path: ^1.7.0 +dependencies: + flutter: + sdk: flutter + stream_feed: + path: ../stream_feed dev_dependencies: - pedantic: ^1.9.0 + mocktail: ^0.1.2 test: ^1.14.4 + flutter_test: + sdk: flutter \ No newline at end of file diff --git a/packages/stream_feed_flutter_core/test/mocks.dart b/packages/stream_feed_flutter_core/test/mocks.dart new file mode 100644 index 000000000..f806de120 --- /dev/null +++ b/packages/stream_feed_flutter_core/test/mocks.dart @@ -0,0 +1,13 @@ +import 'package:mocktail/mocktail.dart'; +import 'package:stream_feed/stream_feed.dart'; + +class MockLogger extends Mock implements Logger {} + +class MockClient extends Mock implements StreamFeedClient { + final Logger logger = MockLogger(); + + // ClientState _state; + + // @override + // ClientState get state => _state ??= MockClientState(); +} diff --git a/packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart b/packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart index 084c5b7fe..f625c7a2f 100644 --- a/packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart +++ b/packages/stream_feed_flutter_core/test/stream_feed_flutter_core_test.dart @@ -1,16 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart'; -import 'package:test/test.dart'; + +import 'mocks.dart'; void main() { - group('A group of tests', () { - Awesome awesome; + testWidgets( + 'should render StreamFeedCore if both client and child is provided', + (tester) async { + final mockClient = MockClient(); + const streamFeedCoreKey = Key('streamFeedCore'); + const childKey = Key('child'); + final streamFeedCore = StreamFeedCore( + key: streamFeedCoreKey, + client: mockClient, + child: Offstage(key: childKey), + ); - setUp(() { - awesome = Awesome(); - }); + await tester.pumpWidget(streamFeedCore); - test('First Test', () { - expect(awesome.isAwesome, isTrue); - }); - }); + expect(find.byKey(streamFeedCoreKey), findsOneWidget); + expect(find.byKey(childKey), findsOneWidget); + }, + ); } From 96e3472847fdaacc24935e2d3859cdd5cc4e08cb Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 08:00:10 -0400 Subject: [PATCH 0005/1241] scaffold ui --- stream_feed_flutter/.gitignore | 13 ++ stream_feed_flutter/CHANGELOG.md | 3 + stream_feed_flutter/LICENSE | 219 ++++++++++++++++++ stream_feed_flutter/README.md | 22 ++ stream_feed_flutter/analysis_options.yaml | 14 ++ .../example/stream_feed_flutter_example.dart | 6 + .../lib/src/stream_feed_flutter_base.dart | 6 + .../lib/stream_feed_flutter.dart | 8 + stream_feed_flutter/pubspec.yaml | 14 ++ .../test/stream_feed_flutter_test.dart | 16 ++ 10 files changed, 321 insertions(+) create mode 100644 stream_feed_flutter/.gitignore create mode 100644 stream_feed_flutter/CHANGELOG.md create mode 100644 stream_feed_flutter/LICENSE create mode 100644 stream_feed_flutter/README.md create mode 100644 stream_feed_flutter/analysis_options.yaml create mode 100644 stream_feed_flutter/example/stream_feed_flutter_example.dart create mode 100644 stream_feed_flutter/lib/src/stream_feed_flutter_base.dart create mode 100644 stream_feed_flutter/lib/stream_feed_flutter.dart create mode 100644 stream_feed_flutter/pubspec.yaml create mode 100644 stream_feed_flutter/test/stream_feed_flutter_test.dart diff --git a/stream_feed_flutter/.gitignore b/stream_feed_flutter/.gitignore new file mode 100644 index 000000000..0c44ab06c --- /dev/null +++ b/stream_feed_flutter/.gitignore @@ -0,0 +1,13 @@ +# Files and directories created by pub +.dart_tool/ +.packages + +# Omit commiting pubspec.lock for library packages: +# https://dart.dev/guides/libraries/private-files#pubspeclock +pubspec.lock + +# Conventional directory for build outputs +build/ + +# Directory created by dartdoc +doc/api/ diff --git a/stream_feed_flutter/CHANGELOG.md b/stream_feed_flutter/CHANGELOG.md new file mode 100644 index 000000000..61d8cf982 --- /dev/null +++ b/stream_feed_flutter/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.0 + +- domain parking 🏎 diff --git a/stream_feed_flutter/LICENSE b/stream_feed_flutter/LICENSE new file mode 100644 index 000000000..4dcdfd417 --- /dev/null +++ b/stream_feed_flutter/LICENSE @@ -0,0 +1,219 @@ +SOURCE CODE LICENSE AGREEMENT + +IMPORTANT - READ THIS CAREFULLY BEFORE DOWNLOADING, INSTALLING, USING OR +ELECTRONICALLY ACCESSING THIS PROPRIETARY PRODUCT. + +THIS IS A LEGAL AGREEMENT BETWEEN STREAM.IO, INC. (“STREAM.IO”) AND THE +BUSINESS ENTITY OR PERSON FOR WHOM YOU (“YOU”) ARE ACTING (“CUSTOMER”) AS THE +LICENSEE OF THE PROPRIETARY SOFTWARE INTO WHICH THIS AGREEMENT HAS BEEN +INCLUDED (THE “AGREEMENT”). YOU AGREE THAT YOU ARE THE CUSTOMER, OR YOU ARE AN +EMPLOYEE OR AGENT OF CUSTOMER AND ARE ENTERING INTO THIS AGREEMENT FOR LICENSE +OF THE SOFTWARE BY CUSTOMER FOR CUSTOMER’S BUSINESS PURPOSES AS DESCRIBED IN +AND IN ACCORDANCE WITH THIS AGREEMENT. YOU HEREBY AGREE THAT YOU ENTER INTO +THIS AGREEMENT ON BEHALF OF CUSTOMER AND THAT YOU HAVE THE AUTHORITY TO BIND +CUSTOMER TO THIS AGREEMENT. + +STREAM.IO IS WILLING TO LICENSE THE SOFTWARE TO CUSTOMER ONLY ON THE FOLLOWING +CONDITIONS: (1) YOU ARE A CURRENT CUSTOMER OF STREAM.IO; (2) YOU ARE NOT A +COMPETITOR OF STREAM.IO; AND (3) THAT YOU ACCEPT ALL THE TERMS IN THIS +AGREEMENT. BY DOWNLOADING, INSTALLING, CONFIGURING, ACCESSING OR OTHERWISE +USING THE SOFTWARE, INCLUDING ANY UPDATES, UPGRADES, OR NEWER VERSIONS, YOU +REPRESENT, WARRANT AND ACKNOWLEDGE THAT (A) CUSTOMER IS A CURRENT CUSTOMER OF +STREAM.IO; (B) CUSTOMER IS NOT A COMPETITOR OF STREAM.IO; AND THAT (C) YOU HAVE +READ THIS AGREEMENT, UNDERSTAND THIS AGREEMENT, AND THAT CUSTOMER AGREES TO BE +BOUND BY ALL THE TERMS OF THIS AGREEMENT. + +IF YOU DO NOT AGREE TO ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT, +STREAM.IO IS UNWILLING TO LICENSE THE SOFTWARE TO CUSTOMER, AND THEREFORE, DO +NOT COMPLETE THE DOWNLOAD PROCESS, ACCESS OR OTHERWISE USE THE SOFTWARE, AND +CUSTOMER SHOULD IMMEDIATELY RETURN THE SOFTWARE AND CEASE ANY USE OF THE +SOFTWARE. + +1. SOFTWARE. The Stream.io software accompanying this Agreement, may include +Source Code, Executable Object Code, associated media, printed materials and +documentation (collectively, the “Software”). The Software also includes any +updates or upgrades to or new versions of the original Software, if and when +made available to you by Stream.io. “Source Code” means computer programming +code in human readable form that is not suitable for machine execution without +the intervening steps of interpretation or compilation. “Executable Object +Code" means the computer programming code in any other form than Source Code +that is not readily perceivable by humans and suitable for machine execution +without the intervening steps of interpretation or compilation. “Site” means a +Customer location controlled by Customer. “Authorized User” means any employee +or contractor of Customer working at the Site, who has signed a written +confidentiality agreement with Customer or is otherwise bound in writing by +confidentiality and use obligations at least as restrictive as those imposed +under this Agreement. + +2. LICENSE GRANT. Subject to the terms and conditions of this Agreement, in +consideration for the representations, warranties, and covenants made by +Customer in this Agreement, Stream.io grants to Customer, during the term of +this Agreement, a personal, non-exclusive, non-transferable, non-sublicensable +license to: + +a. install and use Software Source Code on password protected computers at a Site, +restricted to Authorized Users; + +b. create derivative works, improvements (whether or not patentable), extensions +and other modifications to the Software Source Code (“Modifications”) to build +unique scalable newsfeeds, activity streams, and in-app messaging via Stream’s +application program interface (“API”); + +c. compile the Software Source Code to create Executable Object Code versions of +the Software Source Code and Modifications to build such newsfeeds, activity +streams, and in-app messaging via the API; + +d. install, execute and use such Executable Object Code versions solely for +Customer’s internal business use (including development of websites through +which data generated by Stream services will be streamed (“Apps”)); + +e. use and distribute such Executable Object Code as part of Customer’s Apps; and + +f. make electronic copies of the Software and Modifications as required for backup +or archival purposes. + +3. RESTRICTIONS. Customer is responsible for all activities that occur in +connection with the Software. Customer will not, and will not attempt to: (a) +sublicense or transfer the Software or any Source Code related to the Software +or any of Customer’s rights under this Agreement, except as otherwise provided +in this Agreement, (b) use the Software Source Code for the benefit of a third +party or to operate a service; (c) allow any third party to access or use the +Software Source Code; (d) sublicense or distribute the Software Source Code or +any Modifications in Source Code or other derivative works based on any part of +the Software Source Code; (e) use the Software in any manner that competes with +Stream.io or its business; or (e) otherwise use the Software in any manner that +exceeds the scope of use permitted in this Agreement. Customer shall use the +Software in compliance with any accompanying documentation any laws applicable +to Customer. + +4. OPEN SOURCE. Customer and its Authorized Users shall not use any software or +software components that are open source in conjunction with the Software +Source Code or any Modifications in Source Code or in any way that could +subject the Software to any open source licenses. + +5. CONTRACTORS. Under the rights granted to Customer under this Agreement, +Customer may permit its employees, contractors, and agencies of Customer to +become Authorized Users to exercise the rights to the Software granted to +Customer in accordance with this Agreement solely on behalf of Customer to +provide services to Customer; provided that Customer shall be liable for the +acts and omissions of all Authorized Users to the extent any of such acts or +omissions, if performed by Customer, would constitute a breach of, or otherwise +give rise to liability to Customer under, this Agreement. Customer shall not +and shall not permit any Authorized User to use the Software except as +expressly permitted in this Agreement. + +6. COMPETITIVE PRODUCT DEVELOPMENT. Customer shall not use the Software in any way +to engage in the development of products or services which could be reasonably +construed to provide a complete or partial functional or commercial alternative +to Stream.io’s products or services (a “Competitive Product”). Customer shall +ensure that there is no direct or indirect use of, or sharing of, Software +source code, or other information based upon or derived from the Software to +develop such products or services. Without derogating from the generality of +the foregoing, development of Competitive Products shall include having direct +or indirect access to, supervising, consulting or assisting in the development +of, or producing any specifications, documentation, object code or source code +for, all or part of a Competitive Product. + +7. LIMITATION ON MODIFICATIONS. Notwithstanding any provision in this Agreement, +Modifications may only be created and used by Customer as permitted by this +Agreement and Modification Source Code may not be distributed to third parties. +Customer will not assert against Stream.io, its affiliates, or their customers, +direct or indirect, agents and contractors, in any way, any patent rights that +Customer may obtain relating to any Modifications for Stream.io, its +affiliates’, or their customers’, direct or indirect, agents’ and contractors’ +manufacture, use, import, offer for sale or sale of any Stream.io products or +services. + +8. DELIVERY AND ACCEPTANCE. The Software will be delivered electronically pursuant +to Stream.io standard download procedures. The Software is deemed accepted upon +delivery. + +9. IMPLEMENTATION AND SUPPORT. Stream.io has no obligation under this Agreement to +provide any support or consultation concerning the Software. + +10. TERM AND TERMINATION. The term of this Agreement begins when the Software is +downloaded or accessed and shall continue until terminated. Either party may +terminate this Agreement upon written notice. This Agreement shall +automatically terminate if Customer is or becomes a competitor of Stream.io or +makes or sells any Competitive Products. Upon termination of this Agreement for +any reason, (a) all rights granted to Customer in this Agreement immediately +cease to exist, (b) Customer must promptly discontinue all use of the Software +and return to Stream.io or destroy all copies of the Software in Customer’s +possession or control. Any continued use of the Software by Customer or attempt +by Customer to exercise any rights under this Agreement after this Agreement +has terminated shall be considered copyright infringement and subject Customer +to applicable remedies for copyright infringement. Sections 2, 5, 6, 8 and 9 +shall survive expiration or termination of this Agreement for any reason. + +11. OWNERSHIP. As between the parties, the Software and all worldwide intellectual +property rights and proprietary rights relating thereto or embodied therein, +are the exclusive property of Stream.io and its suppliers. Stream.io and its +suppliers reserve all rights in and to the Software not expressly granted to +Customer in this Agreement, and no other licenses or rights are granted by +implication, estoppel or otherwise. + +12. WARRANTY DISCLAIMER. USE OF THIS SOFTWARE IS ENTIRELY AT YOURS AND CUSTOMER’S +OWN RISK. THE SOFTWARE IS PROVIDED “AS IS” WITHOUT ANY WARRANTY OF ANY KIND +WHATSOEVER. STREAM.IO DOES NOT MAKE, AND HEREBY DISCLAIMS, ANY WARRANTY OF ANY +KIND, WHETHER EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING WITHOUT +LIMITATION, THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, TITLE, NON-INFRINGEMENT OF THIRD-PARTY RIGHTS, RESULTS, EFFORTS, +QUALITY OR QUIET ENJOYMENT. STREAM.IO DOES NOT WARRANT THAT THE SOFTWARE IS +ERROR-FREE, WILL FUNCTION WITHOUT INTERRUPTION, WILL MEET ANY SPECIFIC NEED +THAT CUSTOMER HAS, THAT ALL DEFECTS WILL BE CORRECTED OR THAT IT IS +SUFFICIENTLY DOCUMENTED TO BE USABLE BY CUSTOMER. TO THE EXTENT THAT STREAM.IO +MAY NOT DISCLAIM ANY WARRANTY AS A MATTER OF APPLICABLE LAW, THE SCOPE AND +DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER SUCH LAW. +CUSTOMER ACKNOWLEDGES THAT IT HAS RELIED ON NO WARRANTIES OTHER THAN THE +EXPRESS WARRANTIES IN THIS AGREEMENT. + +13. LIMITATION OF LIABILITY. TO THE FULLEST EXTENT PERMISSIBLE BY LAW, STREAM.IO’S +TOTAL LIABILITY FOR ALL DAMAGES ARISING OUT OF OR RELATED TO THE SOFTWARE OR +THIS AGREEMENT, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, +SHALL NOT EXCEED $100. IN NO EVENT WILL STREAM.IO BE LIABLE FOR ANY INDIRECT, +CONSEQUENTIAL, EXEMPLARY, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES OF ANY KIND +WHATSOEVER, INCLUDING ANY LOST DATA AND LOST PROFITS, ARISING FROM OR RELATING +TO THE SOFTWARE EVEN IF STREAM.IO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. CUSTOMER ACKNOWLEDGES THAT THIS PROVISION REFLECTS THE AGREED UPON +ALLOCATION OF RISK FOR THIS AGREEMENT AND THAT STREAM.IO WOULD NOT ENTER INTO +THIS AGREEMENT WITHOUT THESE LIMITATIONS ON ITS LIABILITY. + +14. General. Customer may not assign or transfer this Agreement, by operation of +law or otherwise, or any of its rights under this Agreement (including the +license rights granted to Customer) to any third party without Stream.io’s +prior written consent, which consent will not be unreasonably withheld or +delayed. Stream.io may assign this Agreement, without consent, including, but +limited to, affiliate or any successor to all or substantially all its business +or assets to which this Agreement relates, whether by merger, sale of assets, +sale of stock, reorganization or otherwise. Any attempted assignment or +transfer in violation of the foregoing will be null and void. Stream.io shall +not be liable hereunder by reason of any failure or delay in the performance of +its obligations hereunder for any cause which is beyond the reasonable control. +All notices, consents, and approvals under this Agreement must be delivered in +writing by courier, by electronic mail, or by certified or registered mail, +(postage prepaid and return receipt requested) to the other party at the +address set forth in the customer agreement between Stream.io and Customer and +will be effective upon receipt or when delivery is refused. This Agreement will +be governed by and interpreted in accordance with the laws of the State of +Colorado, without reference to its choice of laws rules. The United Nations +Convention on Contracts for the International Sale of Goods does not apply to +this Agreement. Any action or proceeding arising from or relating to this +Agreement shall be brought in a federal or state court in Denver, Colorado, and +each party irrevocably submits to the jurisdiction and venue of any such court +in any such action or proceeding. All waivers must be in writing. Any waiver or +failure to enforce any provision of this Agreement on one occasion will not be +deemed a waiver of any other provision or of such provision on any other +occasion. If any provision of this Agreement is unenforceable, such provision +will be changed and interpreted to accomplish the objectives of such provision +to the greatest extent possible under applicable law and the remaining +provisions will continue in full force and effect. Customer shall not violate +any applicable law, rule or regulation, including those regarding the export of +technical data. The headings of Sections of this Agreement are for convenience +and are not to be used in interpreting this Agreement. As used in this +Agreement, the word “including” means “including but not limited to.” This +Agreement (including all exhibits and attachments) constitutes the entire +agreement between the parties regarding the subject hereof and supersedes all +prior or contemporaneous agreements, understandings and communication, whether +written or oral. This Agreement may be amended only by a written document +signed by both parties. The terms of any purchase order or similar document +submitted by Customer to Stream.io will have no effect. \ No newline at end of file diff --git a/stream_feed_flutter/README.md b/stream_feed_flutter/README.md new file mode 100644 index 000000000..e6b2e6aa1 --- /dev/null +++ b/stream_feed_flutter/README.md @@ -0,0 +1,22 @@ +A library for Dart developers. + +Created from templates made available by Stagehand under a BSD-style +[license](https://github.com/dart-lang/stagehand/blob/master/LICENSE). + +## Usage + +A simple usage example: + +```dart +import 'package:stream_feed_flutter/stream_feed_flutter.dart'; + +main() { + var awesome = new Awesome(); +} +``` + +## Features and bugs + +Please file feature requests and bugs at the [issue tracker][tracker]. + +[tracker]: http://example.com/issues/replaceme diff --git a/stream_feed_flutter/analysis_options.yaml b/stream_feed_flutter/analysis_options.yaml new file mode 100644 index 000000000..a686c1b45 --- /dev/null +++ b/stream_feed_flutter/analysis_options.yaml @@ -0,0 +1,14 @@ +# Defines a default set of lint rules enforced for +# projects at Google. For details and rationale, +# see https://github.com/dart-lang/pedantic#enabled-lints. +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. +# Uncomment to specify additional rules. +# linter: +# rules: +# - camel_case_types + +analyzer: +# exclude: +# - path/to/excluded/files/** diff --git a/stream_feed_flutter/example/stream_feed_flutter_example.dart b/stream_feed_flutter/example/stream_feed_flutter_example.dart new file mode 100644 index 000000000..c69efefca --- /dev/null +++ b/stream_feed_flutter/example/stream_feed_flutter_example.dart @@ -0,0 +1,6 @@ +import 'package:stream_feed_flutter/stream_feed_flutter.dart'; + +void main() { + var awesome = Awesome(); + print('awesome: ${awesome.isAwesome}'); +} diff --git a/stream_feed_flutter/lib/src/stream_feed_flutter_base.dart b/stream_feed_flutter/lib/src/stream_feed_flutter_base.dart new file mode 100644 index 000000000..e8a6f1590 --- /dev/null +++ b/stream_feed_flutter/lib/src/stream_feed_flutter_base.dart @@ -0,0 +1,6 @@ +// TODO: Put public facing types in this file. + +/// Checks if you are awesome. Spoiler: you are. +class Awesome { + bool get isAwesome => true; +} diff --git a/stream_feed_flutter/lib/stream_feed_flutter.dart b/stream_feed_flutter/lib/stream_feed_flutter.dart new file mode 100644 index 000000000..b0df7d479 --- /dev/null +++ b/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -0,0 +1,8 @@ +/// Support for doing something awesome. +/// +/// More dartdocs go here. +library stream_feed_flutter; + +export 'src/stream_feed_flutter_base.dart'; + +// TODO: Export any libraries intended for clients of this package. diff --git a/stream_feed_flutter/pubspec.yaml b/stream_feed_flutter/pubspec.yaml new file mode 100644 index 000000000..b37df0687 --- /dev/null +++ b/stream_feed_flutter/pubspec.yaml @@ -0,0 +1,14 @@ +name: stream_feed_flutter +description: Stream Feed official Flutter SDK. Build your own chat experience using Dart and Flutter. +version: 0.0.0 +homepage: https://getstream.io/ + +environment: + sdk: '>=2.10.0 <3.0.0' + +#dependencies: +# path: ^1.7.0 + +dev_dependencies: + pedantic: ^1.9.0 + test: ^1.14.4 diff --git a/stream_feed_flutter/test/stream_feed_flutter_test.dart b/stream_feed_flutter/test/stream_feed_flutter_test.dart new file mode 100644 index 000000000..72c96f847 --- /dev/null +++ b/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -0,0 +1,16 @@ +import 'package:stream_feed_flutter/stream_feed_flutter.dart'; +import 'package:test/test.dart'; + +void main() { + group('A group of tests', () { + Awesome awesome; + + setUp(() { + awesome = Awesome(); + }); + + test('First Test', () { + expect(awesome.isAwesome, isTrue); + }); + }); +} From 5fc239d36a1fd19643966511775bc69e38d7c730 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 08:42:07 -0400 Subject: [PATCH 0006/1241] loveActive + golden --- .../example/stream_feed_flutter_example.dart | 6 -- stream_feed_flutter/lib/src/icons.dart | 63 ++++++++++++++++++ .../lib/src/stream_feed_flutter_base.dart | 6 -- .../lib/stream_feed_flutter.dart | 7 +- stream_feed_flutter/lib/svgs/love_active.svg | 5 ++ .../lib/svgs/love_inactive.svg | 3 + stream_feed_flutter/pubspec.yaml | 14 +++- .../test/goldens/love_active_icon.png | Bin 0 -> 464 bytes .../test/stream_feed_flutter_test.dart | 20 +++--- 9 files changed, 93 insertions(+), 31 deletions(-) delete mode 100644 stream_feed_flutter/example/stream_feed_flutter_example.dart create mode 100644 stream_feed_flutter/lib/src/icons.dart delete mode 100644 stream_feed_flutter/lib/src/stream_feed_flutter_base.dart create mode 100644 stream_feed_flutter/lib/svgs/love_active.svg create mode 100644 stream_feed_flutter/lib/svgs/love_inactive.svg create mode 100644 stream_feed_flutter/test/goldens/love_active_icon.png diff --git a/stream_feed_flutter/example/stream_feed_flutter_example.dart b/stream_feed_flutter/example/stream_feed_flutter_example.dart deleted file mode 100644 index c69efefca..000000000 --- a/stream_feed_flutter/example/stream_feed_flutter_example.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'package:stream_feed_flutter/stream_feed_flutter.dart'; - -void main() { - var awesome = Awesome(); - print('awesome: ${awesome.isAwesome}'); -} diff --git a/stream_feed_flutter/lib/src/icons.dart b/stream_feed_flutter/lib/src/icons.dart new file mode 100644 index 000000000..717e84dc5 --- /dev/null +++ b/stream_feed_flutter/lib/src/icons.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +/// Icon set of stream chat +class StreamSvgIcon extends StatelessWidget { + /// Constructor for creating a [StreamSvgIcon] + const StreamSvgIcon({ + Key? key, + this.assetName, + this.color, + this.width = 24, + this.height = 24, + }) : super(key: key); + + /// Name of icon asset + final String? assetName; + + /// Width of icon + final double? width; + + /// Height of icon + final double? height; + + /// Color of icon + final Color? color; + + /// [StreamSvgIcon] type + factory StreamSvgIcon.loveActive({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'love_active.svg', + color: color, + width: size, + height: size, + ); + + /// [StreamSvgIcon] type + factory StreamSvgIcon.loveInactive({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'love_inactive.svg', + color: color, + width: size, + height: size, + ); + + @override + Widget build(BuildContext context) { + final key = Key('StreamSvgIcon-$assetName'); + return SvgPicture.asset( + 'lib/svgs/$assetName', + package: 'stream_feed_flutter', + key: key, + width: width, + height: height, + color: color, + ); + } +} diff --git a/stream_feed_flutter/lib/src/stream_feed_flutter_base.dart b/stream_feed_flutter/lib/src/stream_feed_flutter_base.dart deleted file mode 100644 index e8a6f1590..000000000 --- a/stream_feed_flutter/lib/src/stream_feed_flutter_base.dart +++ /dev/null @@ -1,6 +0,0 @@ -// TODO: Put public facing types in this file. - -/// Checks if you are awesome. Spoiler: you are. -class Awesome { - bool get isAwesome => true; -} diff --git a/stream_feed_flutter/lib/stream_feed_flutter.dart b/stream_feed_flutter/lib/stream_feed_flutter.dart index b0df7d479..4c311c594 100644 --- a/stream_feed_flutter/lib/stream_feed_flutter.dart +++ b/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -1,8 +1,3 @@ -/// Support for doing something awesome. -/// -/// More dartdocs go here. library stream_feed_flutter; -export 'src/stream_feed_flutter_base.dart'; - -// TODO: Export any libraries intended for clients of this package. +export 'src/icons.dart'; diff --git a/stream_feed_flutter/lib/svgs/love_active.svg b/stream_feed_flutter/lib/svgs/love_active.svg new file mode 100644 index 000000000..6a2535d69 --- /dev/null +++ b/stream_feed_flutter/lib/svgs/love_active.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/stream_feed_flutter/lib/svgs/love_inactive.svg b/stream_feed_flutter/lib/svgs/love_inactive.svg new file mode 100644 index 000000000..5e5cd4b06 --- /dev/null +++ b/stream_feed_flutter/lib/svgs/love_inactive.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/stream_feed_flutter/pubspec.yaml b/stream_feed_flutter/pubspec.yaml index b37df0687..1a1de63c7 100644 --- a/stream_feed_flutter/pubspec.yaml +++ b/stream_feed_flutter/pubspec.yaml @@ -4,11 +4,19 @@ version: 0.0.0 homepage: https://getstream.io/ environment: - sdk: '>=2.10.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' -#dependencies: -# path: ^1.7.0 +dependencies: + flutter_svg: ^0.22.0 + flutter: + sdk: flutter + dev_dependencies: + golden_toolkit: ^0.9.0 pedantic: ^1.9.0 test: ^1.14.4 + +flutter: + assets: + - lib/svgs/ \ No newline at end of file diff --git a/stream_feed_flutter/test/goldens/love_active_icon.png b/stream_feed_flutter/test/goldens/love_active_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..444b773f0bf454bb697d48ea459f2cc3ca219306 GIT binary patch literal 464 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^R}EX7WqAsj$Z z!;#Vfl&kV|aSX|5d^=%Z6rAq;VnJYR> zLR_TeWgLAX56wC6u`c{Tb&HO30bin>`-x5Gq>A?+o}!wdJL~0^&23YdOE-AwiK`q} ze(?A3>$62S*ICQRv2PGNo79+Qws?u7uwiQF$-M9Dk0h*d-FtVEmUET+q|2Rpj12d- zZ`9ZsU^e@9Z%OgFh%Le0i=})vW++{ow5{AD_)^&<4-KwMXRSBRQGTo58PM+oRMKT} zJZNfw$osV%3|Cf*zK!*~Y{n*7wLVq%)!ApJlG%aluj{n4d0&?J^rv#>dUkYGsHgV`7V)WCy7ONkd8O35Zl^QRwg4ZQRHeI_tg7(8A5T-G@yGywp3 CM8+}z literal 0 HcmV?d00001 diff --git a/stream_feed_flutter/test/stream_feed_flutter_test.dart b/stream_feed_flutter/test/stream_feed_flutter_test.dart index 72c96f847..2ba90409a 100644 --- a/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -1,16 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; import 'package:stream_feed_flutter/stream_feed_flutter.dart'; -import 'package:test/test.dart'; void main() { - group('A group of tests', () { - Awesome awesome; - - setUp(() { - awesome = Awesome(); - }); - - test('First Test', () { - expect(awesome.isAwesome, isTrue); + group('Icons', () { + testGoldens('StreamSvgIcon loveActive', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: StreamSvgIcon.loveActive()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'love_active_icon'); }); }); } From f284102954a883e7e6bd11b7f9aaeea0cc9cf033 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 08:43:07 -0400 Subject: [PATCH 0007/1241] icons: loveinactive --- .../test/goldens/love_inactive_icon.png | Bin 0 -> 638 bytes .../test/stream_feed_flutter_test.dart | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100644 stream_feed_flutter/test/goldens/love_inactive_icon.png diff --git a/stream_feed_flutter/test/goldens/love_inactive_icon.png b/stream_feed_flutter/test/goldens/love_inactive_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..36cd663fb5b436425edbbdf4150963dea0be65ab GIT binary patch literal 638 zcmV-^0)hRBP)Px#1am@3R0s$N2z&@+hyVZrC`m*?RA_0}MHWXTl1h+B zehd;@S!5+RDqBY-HnO&Zxf4u#$1NPY4c*N!`D|V?@9UeqJa{{w&%by9etdTV&%%nB zh7~alD`FZ}#5AmkX;=}{up*}M^BIR!RmFb4=Xg9)*ENpg;CUXC$ppu7u3}E76IE3q zgkU%vUd8C}ru)Mx&vVi=rLOCn>$BMmfbDjBb6p6*bUI};8tJ5=CsI`v>-Cztu8~p_ zh9R!&qLkurI8YSDRlM)}jK||PX1Ci>mL)<6R;!g(Wwb<+B%vq@q?F9(^LOi6mXW3@ z0MqG|APC;Y#BoenmiWF;6h&QA(YqsMSppD-;m!3R2yk5&0MGMo#)M%=S(fctUC|P0 z?nRUAE$#_4G<)yev5%tFeuWUg<*sz4**h2vbW+h1kx~Me&efG>@1x2+LQAA+nOT-~ zs!CN=WLb7~R#&t{JkLW)NnO{(as281aU8d;`&%ml5JeF}2$WKHAH7>7NrF;}!C;`( zb{n)sgb*y3ON0>QdHx}p=KT>uuvjeGrlG@AhDO(Q+pqda=5LARa{1rZ{TZG%{Yoj@ zx$2%wUlQga zphpq7%uk!m2B7V1ebK83{22!Olz=Y~`6^!K&j%}F8dk(KtcYn?5!0|DreQ@)<7GsC Y1DpZ~H!rUSApigX07*qoM6N<$f+tZLVE_OC literal 0 HcmV?d00001 diff --git a/stream_feed_flutter/test/stream_feed_flutter_test.dart b/stream_feed_flutter/test/stream_feed_flutter_test.dart index 2ba90409a..35b277d1d 100644 --- a/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -12,5 +12,14 @@ void main() { ); await screenMatchesGolden(tester, 'love_active_icon'); }); + + + testGoldens('StreamSvgIcon loveInactive', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: StreamSvgIcon.loveInactive()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'love_inactive_icon'); + }); }); } From 1c0ccb81fb613966a298534ed4fdb4d39e62009e Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 08:58:19 -0400 Subject: [PATCH 0008/1241] wrong directory --- .../stream_feed_flutter}/.gitignore | 0 .../stream_feed_flutter}/CHANGELOG.md | 0 .../stream_feed_flutter}/LICENSE | 0 .../stream_feed_flutter}/README.md | 0 .../stream_feed_flutter}/analysis_options.yaml | 0 .../stream_feed_flutter}/lib/src/icons.dart | 0 .../lib/stream_feed_flutter.dart | 0 .../stream_feed_flutter}/lib/svgs/love_active.svg | 0 .../stream_feed_flutter}/lib/svgs/love_inactive.svg | 0 .../stream_feed_flutter}/pubspec.yaml | 0 .../test/goldens/love_active_icon.png | Bin .../test/goldens/love_inactive_icon.png | Bin .../test/stream_feed_flutter_test.dart | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename {stream_feed_flutter => packages/stream_feed_flutter}/.gitignore (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/CHANGELOG.md (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/LICENSE (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/README.md (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/analysis_options.yaml (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/lib/src/icons.dart (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/lib/stream_feed_flutter.dart (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/lib/svgs/love_active.svg (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/lib/svgs/love_inactive.svg (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/pubspec.yaml (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/test/goldens/love_active_icon.png (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/test/goldens/love_inactive_icon.png (100%) rename {stream_feed_flutter => packages/stream_feed_flutter}/test/stream_feed_flutter_test.dart (100%) diff --git a/stream_feed_flutter/.gitignore b/packages/stream_feed_flutter/.gitignore similarity index 100% rename from stream_feed_flutter/.gitignore rename to packages/stream_feed_flutter/.gitignore diff --git a/stream_feed_flutter/CHANGELOG.md b/packages/stream_feed_flutter/CHANGELOG.md similarity index 100% rename from stream_feed_flutter/CHANGELOG.md rename to packages/stream_feed_flutter/CHANGELOG.md diff --git a/stream_feed_flutter/LICENSE b/packages/stream_feed_flutter/LICENSE similarity index 100% rename from stream_feed_flutter/LICENSE rename to packages/stream_feed_flutter/LICENSE diff --git a/stream_feed_flutter/README.md b/packages/stream_feed_flutter/README.md similarity index 100% rename from stream_feed_flutter/README.md rename to packages/stream_feed_flutter/README.md diff --git a/stream_feed_flutter/analysis_options.yaml b/packages/stream_feed_flutter/analysis_options.yaml similarity index 100% rename from stream_feed_flutter/analysis_options.yaml rename to packages/stream_feed_flutter/analysis_options.yaml diff --git a/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart similarity index 100% rename from stream_feed_flutter/lib/src/icons.dart rename to packages/stream_feed_flutter/lib/src/icons.dart diff --git a/stream_feed_flutter/lib/stream_feed_flutter.dart b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart similarity index 100% rename from stream_feed_flutter/lib/stream_feed_flutter.dart rename to packages/stream_feed_flutter/lib/stream_feed_flutter.dart diff --git a/stream_feed_flutter/lib/svgs/love_active.svg b/packages/stream_feed_flutter/lib/svgs/love_active.svg similarity index 100% rename from stream_feed_flutter/lib/svgs/love_active.svg rename to packages/stream_feed_flutter/lib/svgs/love_active.svg diff --git a/stream_feed_flutter/lib/svgs/love_inactive.svg b/packages/stream_feed_flutter/lib/svgs/love_inactive.svg similarity index 100% rename from stream_feed_flutter/lib/svgs/love_inactive.svg rename to packages/stream_feed_flutter/lib/svgs/love_inactive.svg diff --git a/stream_feed_flutter/pubspec.yaml b/packages/stream_feed_flutter/pubspec.yaml similarity index 100% rename from stream_feed_flutter/pubspec.yaml rename to packages/stream_feed_flutter/pubspec.yaml diff --git a/stream_feed_flutter/test/goldens/love_active_icon.png b/packages/stream_feed_flutter/test/goldens/love_active_icon.png similarity index 100% rename from stream_feed_flutter/test/goldens/love_active_icon.png rename to packages/stream_feed_flutter/test/goldens/love_active_icon.png diff --git a/stream_feed_flutter/test/goldens/love_inactive_icon.png b/packages/stream_feed_flutter/test/goldens/love_inactive_icon.png similarity index 100% rename from stream_feed_flutter/test/goldens/love_inactive_icon.png rename to packages/stream_feed_flutter/test/goldens/love_inactive_icon.png diff --git a/stream_feed_flutter/test/stream_feed_flutter_test.dart b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart similarity index 100% rename from stream_feed_flutter/test/stream_feed_flutter_test.dart rename to packages/stream_feed_flutter/test/stream_feed_flutter_test.dart From ffb9bb4774c7d9b1c043e2eca6b0f1f1d5f01411 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 09:01:53 -0400 Subject: [PATCH 0009/1241] update actions --- .github/workflows/build.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5aef10673..5228d4855 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -66,3 +66,7 @@ jobs: with: path: packages/faye_dart/coverage/lcov.info min_coverage: 49 + - uses: VeryGoodOpenSource/very_good_coverage@v1.1.1 + with: + path: packages/stream_feed_flutter_core/coverage/lcov.info + min_coverage: 70 From d012afe69d7987743edba54767fc92325d74b1f1 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 09:07:12 -0400 Subject: [PATCH 0010/1241] format --- packages/stream_feed_flutter/test/stream_feed_flutter_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart index 35b277d1d..d7d024f2b 100644 --- a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -13,7 +13,6 @@ void main() { await screenMatchesGolden(tester, 'love_active_icon'); }); - testGoldens('StreamSvgIcon loveInactive', (tester) async { await tester.pumpWidgetBuilder( Center(child: StreamSvgIcon.loveInactive()), From 432d334bf6ab44af9f3ac4fa264e49efcb4d94ec Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 09:11:00 -0400 Subject: [PATCH 0011/1241] icons: repost --- packages/stream_feed_flutter/lib/src/icons.dart | 12 ++++++++++++ packages/stream_feed_flutter/lib/svgs/repost.svg | 4 ++++ .../stream_feed_flutter/test/goldens/repost.png | Bin 0 -> 323 bytes .../test/stream_feed_flutter_test.dart | 12 ++++++++++-- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 packages/stream_feed_flutter/lib/svgs/repost.svg create mode 100644 packages/stream_feed_flutter/test/goldens/repost.png diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index 717e84dc5..1adfa63bb 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -48,6 +48,18 @@ class StreamSvgIcon extends StatelessWidget { height: size, ); + /// [StreamSvgIcon] type + factory StreamSvgIcon.repost({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'repost.svg', + color: color, + width: size, + height: size, + ); + @override Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); diff --git a/packages/stream_feed_flutter/lib/svgs/repost.svg b/packages/stream_feed_flutter/lib/svgs/repost.svg new file mode 100644 index 000000000..fdcd38462 --- /dev/null +++ b/packages/stream_feed_flutter/lib/svgs/repost.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/packages/stream_feed_flutter/test/goldens/repost.png b/packages/stream_feed_flutter/test/goldens/repost.png new file mode 100644 index 0000000000000000000000000000000000000000..886afe091208f3f4d89ac38af78e3137800af3ae GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^R}EX7WqAsj$Z z!;#Vfof z%zn5~Mm_I<@^8k72p8V&6^VkTI*Zy|uWaa$66@TwPJ3(ItP}g*-`Lh0reB)9^;(9J zzn3V()@$D1w_amlxNOpTZMwyq=aT<#EmOS|Iqm84*HulAEt2Lv|FCOi=LVGq7r|vL z6EqG@VQ4t`f9nws;gwtC-r3$?(DminG)CVR%enGE)I%39 zO@ Date: Tue, 18 May 2021 09:13:05 -0400 Subject: [PATCH 0012/1241] icons: reply --- packages/stream_feed_flutter/lib/src/icons.dart | 12 ++++++++++++ packages/stream_feed_flutter/lib/svgs/reply.svg | 3 +++ .../stream_feed_flutter/test/goldens/reply.png | Bin 0 -> 433 bytes .../test/stream_feed_flutter_test.dart | 8 ++++++++ 4 files changed, 23 insertions(+) create mode 100644 packages/stream_feed_flutter/lib/svgs/reply.svg create mode 100644 packages/stream_feed_flutter/test/goldens/reply.png diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index 1adfa63bb..22f86a4f7 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -60,6 +60,18 @@ class StreamSvgIcon extends StatelessWidget { height: size, ); + /// [StreamSvgIcon] type + factory StreamSvgIcon.reply({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'reply.svg', + color: color, + width: size, + height: size, + ); + @override Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); diff --git a/packages/stream_feed_flutter/lib/svgs/reply.svg b/packages/stream_feed_flutter/lib/svgs/reply.svg new file mode 100644 index 000000000..d38f2b83c --- /dev/null +++ b/packages/stream_feed_flutter/lib/svgs/reply.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/stream_feed_flutter/test/goldens/reply.png b/packages/stream_feed_flutter/test/goldens/reply.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f63c3b8af7635a399ab10cea980e109ba01559 GIT binary patch literal 433 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^R}EX7WqAsj$Z z!;#Vfl#BLsaSX|5e0#$%?~s8=!^8Qjn#23!jN2|MYbU#1i)qX*U|%P&?tq|8+r+EM z5`x^a0TWj(6S|`RbY<25dFggJ+D$i~7VZ4RUse5;eZnb)TSgt*coyk4XPibbvyD8w zGFM$(?91e-x$*YfWfFgrA592XaFF<<#d5&sRs0mgmhbZfm_GlUvuj=9IZqwaSsYI$ z&Mi16n4GdR#*ay>&8B+Jp6^?7y*U=9+|2*`vpPkBZQE^K%k+yok4}(KUVZh|%Jg&3 zH(R)+xYu>R+~t>4$#8Ee+ffO|eRrmxO=G^(ciDhPhL8Q%zUL)Yj1!90mX_3SQ!(V| zNq$gvaPRk!P}j>QPv*Sb)i=lZ_un`crMjE)mT8JC*It|YUcOVl%H*Q#&o>wID>g$B)XMSbu|J3$>h7H#< QV6ZcIy85}Sb4q9e02k7_p8x;= literal 0 HcmV?d00001 diff --git a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart index b94cf0a19..af4929865 100644 --- a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -27,6 +27,14 @@ void main() { surfaceSize: const Size(50, 50), ); await screenMatchesGolden(tester, 'repost'); + }); + + testGoldens('reply', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: StreamSvgIcon.reply()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'reply'); }); }); } From 7498e0918029d58a2b58157404542331a4c793d6 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 09:14:42 -0400 Subject: [PATCH 0013/1241] icons: share --- packages/stream_feed_flutter/lib/src/icons.dart | 11 +++++++++++ packages/stream_feed_flutter/lib/svgs/share.svg | 5 +++++ .../stream_feed_flutter/test/goldens/share.png | Bin 0 -> 505 bytes .../test/stream_feed_flutter_test.dart | 10 +++++++++- 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 packages/stream_feed_flutter/lib/svgs/share.svg create mode 100644 packages/stream_feed_flutter/test/goldens/share.png diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index 22f86a4f7..2ae80ea49 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -72,6 +72,17 @@ class StreamSvgIcon extends StatelessWidget { height: size, ); + /// [StreamSvgIcon] type + factory StreamSvgIcon.share({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'share.svg', + color: color, + width: size, + height: size, + ); @override Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); diff --git a/packages/stream_feed_flutter/lib/svgs/share.svg b/packages/stream_feed_flutter/lib/svgs/share.svg new file mode 100644 index 000000000..87a045dc4 --- /dev/null +++ b/packages/stream_feed_flutter/lib/svgs/share.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/packages/stream_feed_flutter/test/goldens/share.png b/packages/stream_feed_flutter/test/goldens/share.png new file mode 100644 index 0000000000000000000000000000000000000000..c4a7e6b7a2584d05624e0018981541b7d7815661 GIT binary patch literal 505 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^R}EX7WqAsj$Z z!;#Vflw0iS;uw<_S^B zVcEJld0E=3LVx|M`Z?h%e@|bc|MP9p&X`KZy1!qT=edeal8W@mN>N-nv2}?XgtMn- z!u^f7+sKfgBJqp|3#$NldW@7?#W%qsYEvN}bAZQE_#!v+dUQ&Kq{u9tRjtn#{Sa`3y4 z+L1FK?%l6W+8D7RMo(~}<~nZuwfoZ1y{EdHa3a zqMo-==XNF-UX1Y$m5=(Q%>AD)@NKxujI(KzkM!BOA5;5lysZ99{M~5%KikjRnO3@b p_UfpZZkllAgj0|*H;nUx*-d;~{-)o8`+?EN;OXk;vd$@?2>_KF;R65w literal 0 HcmV?d00001 diff --git a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart index af4929865..8a6f927d9 100644 --- a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -29,12 +29,20 @@ void main() { await screenMatchesGolden(tester, 'repost'); }); - testGoldens('reply', (tester) async { + testGoldens('reply', (tester) async { await tester.pumpWidgetBuilder( Center(child: StreamSvgIcon.reply()), surfaceSize: const Size(50, 50), ); await screenMatchesGolden(tester, 'reply'); }); + + testGoldens('share', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: StreamSvgIcon.share()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'share'); + }); }); } From 42bd5a0c5b65cb17702ceaeb29a40758dbad49ab Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 09:22:23 -0400 Subject: [PATCH 0014/1241] github actions min coverage --- .github/workflows/build.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5aef10673..a9e98cbbf 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -58,6 +58,10 @@ jobs: - name: Post Codecov report run: bash <(curl -s https://codecov.io/bash) -t ${{ secrets.CODECOV_TOKEN }} + - uses: VeryGoodOpenSource/very_good_coverage@v1.1.1 + with: + path: packages/stream_feed_flutter/coverage/lcov.info + min_coverage: 70 - uses: VeryGoodOpenSource/very_good_coverage@v1.1.1 with: path: packages/stream_feed/coverage/lcov.info From be154c33d05f05fd3dbb80f27b5ab72b27c5d66e Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 09:28:23 -0400 Subject: [PATCH 0015/1241] post --- packages/stream_feed_flutter/lib/src/icons.dart | 12 ++++++++++++ packages/stream_feed_flutter/lib/svgs/post.svg | 9 +++++++++ .../stream_feed_flutter/test/goldens/post.png | Bin 0 -> 1148 bytes .../test/stream_feed_flutter_test.dart | 8 ++++++++ 4 files changed, 29 insertions(+) create mode 100644 packages/stream_feed_flutter/lib/svgs/post.svg create mode 100644 packages/stream_feed_flutter/test/goldens/post.png diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index 2ae80ea49..d414ab86e 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -83,6 +83,18 @@ class StreamSvgIcon extends StatelessWidget { width: size, height: size, ); + + /// [StreamSvgIcon] type + factory StreamSvgIcon.post({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'post.svg', + color: color, + width: size, + height: size, + ); @override Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); diff --git a/packages/stream_feed_flutter/lib/svgs/post.svg b/packages/stream_feed_flutter/lib/svgs/post.svg new file mode 100644 index 000000000..4b0aae397 --- /dev/null +++ b/packages/stream_feed_flutter/lib/svgs/post.svg @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/packages/stream_feed_flutter/test/goldens/post.png b/packages/stream_feed_flutter/test/goldens/post.png new file mode 100644 index 0000000000000000000000000000000000000000..be571e204c5b440c1ea11a28c973ede10e23fb49 GIT binary patch literal 1148 zcmV-?1cUpDP)Px#1am@3R0s$N2z&@+hyVZtCP_p=RA_vvFqtjP*z9!wqGxJS6zJ*Ixv&+Fz1F9>T=rlt?78SxckdhAbdp zjc>Etsc&i}C~)(-Apj(P68>6T6p1AEL~Qn1OlHd(e`?yqoq<87P39H8D-Zx?s})W7 zHjzkTASp>&Y|eR_rq|Mn7*@X+Wl zk#Oon5jpuq0PIfE3PAwm78LXG$r8~hfCmm%Hv24vrKf4QRE<3{Dn2SX?x|aQ76f2^exBa`y9^nOjEs(9vCg0l55qp| zASEf0xR@y3NZaGxpMzeeHq4hsABeZf2jXq=fq0vIAl@b)h_`9Ofcy=;2$1bV@vYVX O0000 Date: Tue, 18 May 2021 09:33:37 -0400 Subject: [PATCH 0016/1241] categories --- packages/stream_feed_flutter/lib/src/icons.dart | 12 ++++++++++++ .../stream_feed_flutter/lib/svgs/categories.svg | 14 ++++++++++++++ .../test/goldens/categories.png | Bin 0 -> 601 bytes .../test/stream_feed_flutter_test.dart | 8 ++++++++ 4 files changed, 34 insertions(+) create mode 100644 packages/stream_feed_flutter/lib/svgs/categories.svg create mode 100644 packages/stream_feed_flutter/test/goldens/categories.png diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index d414ab86e..fcf6346be 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -95,6 +95,18 @@ class StreamSvgIcon extends StatelessWidget { width: size, height: size, ); + + /// [StreamSvgIcon] type + factory StreamSvgIcon.categories({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'categories.svg', + color: color, + width: size, + height: size, + ); @override Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); diff --git a/packages/stream_feed_flutter/lib/svgs/categories.svg b/packages/stream_feed_flutter/lib/svgs/categories.svg new file mode 100644 index 000000000..b70b1b239 --- /dev/null +++ b/packages/stream_feed_flutter/lib/svgs/categories.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/stream_feed_flutter/test/goldens/categories.png b/packages/stream_feed_flutter/test/goldens/categories.png new file mode 100644 index 0000000000000000000000000000000000000000..fc661ff9501be5af3ae4532f44823d44710fd359 GIT binary patch literal 601 zcmV-f0;c_mP)Px#1am@3R0s$N2z&@+hyVZr14%?dRA_M@06`Ey2mvW2q?AVI zd@$~vDs`|$AEto)>@O+LpFPsWhjb*H0eD?qY=jA zaqB#CMUKZKHT5o3pOAO}i@_J#)<-$1!;=>^7d;!Z-B${hJTd2KMhaO;h%HfAq`qKBo00000NkvXXu0mjfzRVA% literal 0 HcmV?d00001 diff --git a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart index 2a0624a97..05c7c14f6 100644 --- a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -52,5 +52,13 @@ void main() { ); await screenMatchesGolden(tester, 'post'); }); + + testGoldens('categories', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: StreamSvgIcon.categories()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'categories'); + }); }); } From 773f34fc2a35d51429b1e6a69665f6654d74c7c5 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 09:36:23 -0400 Subject: [PATCH 0017/1241] gear --- packages/stream_feed_flutter/lib/src/icons.dart | 12 ++++++++++++ packages/stream_feed_flutter/lib/svgs/gear.svg | 8 ++++++++ .../stream_feed_flutter/test/goldens/gear.png | Bin 0 -> 1314 bytes .../test/stream_feed_flutter_test.dart | 8 ++++++++ 4 files changed, 28 insertions(+) create mode 100644 packages/stream_feed_flutter/lib/svgs/gear.svg create mode 100644 packages/stream_feed_flutter/test/goldens/gear.png diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index fcf6346be..7c30dd922 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -107,6 +107,18 @@ class StreamSvgIcon extends StatelessWidget { width: size, height: size, ); + + /// [StreamSvgIcon] type + factory StreamSvgIcon.gear({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'gear.svg', + color: color, + width: size, + height: size, + ); @override Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); diff --git a/packages/stream_feed_flutter/lib/svgs/gear.svg b/packages/stream_feed_flutter/lib/svgs/gear.svg new file mode 100644 index 000000000..3de0eb2de --- /dev/null +++ b/packages/stream_feed_flutter/lib/svgs/gear.svg @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/packages/stream_feed_flutter/test/goldens/gear.png b/packages/stream_feed_flutter/test/goldens/gear.png new file mode 100644 index 0000000000000000000000000000000000000000..6512b21481d2d535e9256e87276246807c4538ac GIT binary patch literal 1314 zcmV+-1>O3IP)Px#1am@3R0s$N2z&@+hyVZt%t=H+RA_WgN#pM{(*oG%Rn!KuNQla_Nwm z*~K-poHUpM zxp83c(;vtyMf5WG1S1}?uh~)H@#DOXpjhY+cv0s0u^7L6!lM`f{v$>h< z+&p6Ey-U!rz)oY#mP;7+A7FWM0{!~-mF=6h?cjNR1XCuzq9_(sAONu+B(Zj7IwM0y zD4wIH?jl*6wo;tGUGW^ML7;n>mX;PyoGRza)h31o4rRjlNc#A>XR{|Dz(c#%J8#eA z`yg)@hCz_94b9Rd`dd!t83&wk`R<0{e@XGr>hUb<#GwNzl=}T ziMsj*xm{tZ63JjnOklNHS(1__`zDN!vs=Ggx2z&@*~g-~wobNH z*Vc;6wGVOE>ZsD6ex|}y#mcmgWZSt5)qJ)ipT`3Nh>Fy6;#3({n~fFAml85O7ywC< z$jvWc^wT4m{>BtlF?a-IZd^P?c{y&i6F^IAD<{j0ST0>=cyJI=k11L2QZ{F;AvoyC`yMAr61{rec|GeJ%&gAZz~0@;VN{hUEv>B# z7!cqFVRtxKzcHIev!%;14Q4aByY^7uXqIguBZ3(>=2?#a`Iq8YRDtMpIuf4B`Gx%eMA@qhJ8fOS-_QRO#ocI)R{=V0f8t{1QD|t}Vw0CFlKt}+C-RuipM*sV z2@f5sDh7{Sb@kz4^y}M?v16Wbv$xew;;!}`73FQmV!6yyA;VS2;E^(3qtSGNXjgj$ zU^G>A^7Zla^9TfZD7F4e9ScB3C-!}+$3gxtJu;t6eIVW@ABeZf2jXq=fq0vIAl{~b Y0kWnvj1U38&Hw-a07*qoM6N<$g6|P_zW@LL literal 0 HcmV?d00001 diff --git a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart index 05c7c14f6..f80bee9ad 100644 --- a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart @@ -60,5 +60,13 @@ void main() { ); await screenMatchesGolden(tester, 'categories'); }); + + testGoldens('gear', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: StreamSvgIcon.gear()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'gear'); + }); }); } From cd6f310dd0f00f285f8ec25211f9025e13894a52 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 10:35:41 -0400 Subject: [PATCH 0018/1241] make asset name non nullable --- packages/stream_feed_flutter/lib/src/icons.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index 7c30dd922..7f14991fd 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -6,14 +6,14 @@ class StreamSvgIcon extends StatelessWidget { /// Constructor for creating a [StreamSvgIcon] const StreamSvgIcon({ Key? key, - this.assetName, + required this.assetName, this.color, this.width = 24, this.height = 24, }) : super(key: key); /// Name of icon asset - final String? assetName; + final String assetName; /// Width of icon final double? width; From 4ad5b11346495ecb9cfbc84994660b032e0bcec6 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 10:54:04 -0400 Subject: [PATCH 0019/1241] avatar wip: default + from url --- .../stream_feed_flutter/lib/src/avatar.dart | 23 ++++++++++++++++ .../stream_feed_flutter/lib/src/icons.dart | 12 +++++++++ .../lib/stream_feed_flutter.dart | 1 + .../stream_feed_flutter/lib/svgs/avatar.svg | 9 +++++++ packages/stream_feed_flutter/pubspec.yaml | 1 + .../stream_feed_flutter/test/avatar_test.dart | 25 ++++++++++++++++++ .../test/goldens/avatar.png | Bin 0 -> 950 bytes .../test/goldens/avatar_icon.png | Bin 0 -> 615 bytes .../{categories.png => categories_icon.png} | Bin .../test/goldens/{gear.png => gear_icon.png} | Bin .../test/goldens/love_active_icon.png | Bin 464 -> 0 bytes .../test/goldens/love_inactive_icon.png | Bin 638 -> 0 bytes .../test/goldens/{post.png => post_icon.png} | Bin .../goldens/{reply.png => reply_icon.png} | Bin .../goldens/{repost.png => repost_icon.png} | Bin .../goldens/{share.png => share_icon.png} | Bin ...feed_flutter_test.dart => icons_test.dart} | 20 +++++++++----- 17 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 packages/stream_feed_flutter/lib/src/avatar.dart create mode 100644 packages/stream_feed_flutter/lib/svgs/avatar.svg create mode 100644 packages/stream_feed_flutter/test/avatar_test.dart create mode 100644 packages/stream_feed_flutter/test/goldens/avatar.png create mode 100644 packages/stream_feed_flutter/test/goldens/avatar_icon.png rename packages/stream_feed_flutter/test/goldens/{categories.png => categories_icon.png} (100%) rename packages/stream_feed_flutter/test/goldens/{gear.png => gear_icon.png} (100%) delete mode 100644 packages/stream_feed_flutter/test/goldens/love_active_icon.png delete mode 100644 packages/stream_feed_flutter/test/goldens/love_inactive_icon.png rename packages/stream_feed_flutter/test/goldens/{post.png => post_icon.png} (100%) rename packages/stream_feed_flutter/test/goldens/{reply.png => reply_icon.png} (100%) rename packages/stream_feed_flutter/test/goldens/{repost.png => repost_icon.png} (100%) rename packages/stream_feed_flutter/test/goldens/{share.png => share_icon.png} (100%) rename packages/stream_feed_flutter/test/{stream_feed_flutter_test.dart => icons_test.dart} (76%) diff --git a/packages/stream_feed_flutter/lib/src/avatar.dart b/packages/stream_feed_flutter/lib/src/avatar.dart new file mode 100644 index 000000000..1ce22a4a9 --- /dev/null +++ b/packages/stream_feed_flutter/lib/src/avatar.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:stream_feed_flutter/stream_feed_flutter.dart'; + +class Avatar extends StatelessWidget { + final String? url; + Avatar({this.url}); + @override + Widget build(BuildContext context) { + return url != null + ? ClipOval( + child: Image.network( + url!, + width: 30, + height: 30, + fit: BoxFit.cover, + ), + ) + : ClipOval( + child: StreamSvgIcon.avatar( + size: 30, + )); + } +} diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index 7c30dd922..e706113b2 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -119,6 +119,18 @@ class StreamSvgIcon extends StatelessWidget { width: size, height: size, ); + + /// [StreamSvgIcon] type + factory StreamSvgIcon.avatar({ + double? size, + Color? color, + }) => + StreamSvgIcon( + assetName: 'avatar.svg', + color: color, + width: size, + height: size, + ); @override Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); diff --git a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart index 4c311c594..d33a5d840 100644 --- a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart +++ b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -1,3 +1,4 @@ library stream_feed_flutter; export 'src/icons.dart'; +export 'src/avatar.dart'; diff --git a/packages/stream_feed_flutter/lib/svgs/avatar.svg b/packages/stream_feed_flutter/lib/svgs/avatar.svg new file mode 100644 index 000000000..8935b91bc --- /dev/null +++ b/packages/stream_feed_flutter/lib/svgs/avatar.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/packages/stream_feed_flutter/pubspec.yaml b/packages/stream_feed_flutter/pubspec.yaml index 1a1de63c7..547ab0634 100644 --- a/packages/stream_feed_flutter/pubspec.yaml +++ b/packages/stream_feed_flutter/pubspec.yaml @@ -16,6 +16,7 @@ dev_dependencies: golden_toolkit: ^0.9.0 pedantic: ^1.9.0 test: ^1.14.4 + mocktail_image_network: ^0.1.0 flutter: assets: diff --git a/packages/stream_feed_flutter/test/avatar_test.dart b/packages/stream_feed_flutter/test/avatar_test.dart new file mode 100644 index 000000000..78a61182b --- /dev/null +++ b/packages/stream_feed_flutter/test/avatar_test.dart @@ -0,0 +1,25 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; +import 'package:mocktail_image_network/mocktail_image_network.dart'; +import 'package:stream_feed_flutter/stream_feed_flutter.dart'; +// import 'package:test/test.dart'; + +void main() { + group('Avatar', () { + testWidgets('url', (tester) async { + await mockNetworkImages(() async { + await tester.pumpWidget(Avatar(url: 'https://via.placeholder.com/150')); + expect(find.byType(Image), findsOneWidget); + }); + }); + + testGoldens('avatar', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: Avatar()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'avatar'); + }); + }); +} diff --git a/packages/stream_feed_flutter/test/goldens/avatar.png b/packages/stream_feed_flutter/test/goldens/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..60978243f68f2cf27e73ddc6215853ead32497fe GIT binary patch literal 950 zcmV;n14;aeP)Px#1am@3R0s$N2z&@+hyVZsU`a$lRA_mU0$yIli4J>W562QesE4Jwt}c`&H8JKC{+pB@^HGIX-}v-aCM#v;dhmEkNc? z3y^u!0%YE#ByG_1eGCQz42KLO&M_Pg$Bq;QON2mCC{n2uGU;@pen}E73g;ZQX=)bvTrTqZ z$a|!3ns8k&aJ<#-psVY!Z3h65$)r&(l~7-QcszU{aeagJg>A1R(l841gT?Kn8Q zxPs^VQ^zT#*l+BjSePDg)XYeiU)S|QAx=)u10eu_F@_&!=ja<|fDJcveUPL;IOi}d zD{%bs*KaV!glwH%UIotW8>V#ekOB!SudQ|mw&MufVvOPO>3QndxSWgI0;EBLD^$0q zOF0I{@KJnClQ4+q`=ROX>hd6-?+5M&&bicH5e69y2Es;Vuq8H#PeN$yqDkj0qQveawQ5y*&Du&mDfi+a zbSZplv5-e?SsbR2pFLku#9KjOkfo4MV4}v(HY%mk%z2usqPe#_bDqpSMHnQd%mx8~ z{k>gmtgi)r`)ez895%m%?hRR=fJFD}`9Ac%A#9j2hHg)PIn*ensFX`m)vZ)42+tS( z2s7z42qB>*(RLj44HJfGf-&}{!|mxhD5cO;6_s)cni^bs2_aI@Quh(dwqeof9 zp4%P#d3u&^zccAHR#)m%FIzcHMNZR%ZApP}&e7_0U$W9_cW`}sC)~ORiBgK4&5f5T zMhHQzT9Ml9(lcCS%XDVNaL*+#WemhKd!55#OXgPyJ@4grj>0)}Np zYIh=??1#;Ltk!E$mWFDzUPH4n`+S+ESkFPo+&u^bQA)A3v5w|m1L;&MZV1VM{HvS$ z2edmK7^a2ckioKT06Px#1am@3R0s$N2z&@+hyVZr5lKWrRA_crN4N&EkQ zWzss)Q8gk;MiW9v7Auyl_5v}r+d5+RrL~aH9mdv^6TgXVXbB;1aR9t}=?kF3ikOBK zF%2tX8dk(KtcYo}RR=7RbRXC87bl~kQvZXQk%JLYE-e)*&ao~^NGWmD>!R1~?k#IC zA{FPD{4t{1J{r_j~|**lRhCgHIpMk*#th=@RR5v$lAQVLTj=m(&(=5h*1q&QWm= z&tpJq)9x{bS_l+n36C*zXCz6N$nqT7D*xyA+x9TpeC{9n==(m|47F7MR`~O%yDmxu z^AHu+Tcta$i}SY=9Q7W)x}Wu^o1{xzOfR)1fX$BJVtR@AiJM66(ux;12U-{h-p|6)373@aR>7U%AyhqEad%Z6rAq;VnJYR> zLR_TeWgLAX56wC6u`c{Tb&HO30bin>`-x5Gq>A?+o}!wdJL~0^&23YdOE-AwiK`q} ze(?A3>$62S*ICQRv2PGNo79+Qws?u7uwiQF$-M9Dk0h*d-FtVEmUET+q|2Rpj12d- zZ`9ZsU^e@9Z%OgFh%Le0i=})vW++{ow5{AD_)^&<4-KwMXRSBRQGTo58PM+oRMKT} zJZNfw$osV%3|Cf*zK!*~Y{n*7wLVq%)!ApJlG%aluj{n4d0&?J^rv#>dUkYGsHgV`7V)WCy7ONkd8O35Zl^QRwg4ZQRHeI_tg7(8A5T-G@yGywp3 CM8+}z diff --git a/packages/stream_feed_flutter/test/goldens/love_inactive_icon.png b/packages/stream_feed_flutter/test/goldens/love_inactive_icon.png deleted file mode 100644 index 36cd663fb5b436425edbbdf4150963dea0be65ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 638 zcmV-^0)hRBP)Px#1am@3R0s$N2z&@+hyVZrC`m*?RA_0}MHWXTl1h+B zehd;@S!5+RDqBY-HnO&Zxf4u#$1NPY4c*N!`D|V?@9UeqJa{{w&%by9etdTV&%%nB zh7~alD`FZ}#5AmkX;=}{up*}M^BIR!RmFb4=Xg9)*ENpg;CUXC$ppu7u3}E76IE3q zgkU%vUd8C}ru)Mx&vVi=rLOCn>$BMmfbDjBb6p6*bUI};8tJ5=CsI`v>-Cztu8~p_ zh9R!&qLkurI8YSDRlM)}jK||PX1Ci>mL)<6R;!g(Wwb<+B%vq@q?F9(^LOi6mXW3@ z0MqG|APC;Y#BoenmiWF;6h&QA(YqsMSppD-;m!3R2yk5&0MGMo#)M%=S(fctUC|P0 z?nRUAE$#_4G<)yev5%tFeuWUg<*sz4**h2vbW+h1kx~Me&efG>@1x2+LQAA+nOT-~ zs!CN=WLb7~R#&t{JkLW)NnO{(as281aU8d;`&%ml5JeF}2$WKHAH7>7NrF;}!C;`( zb{n)sgb*y3ON0>QdHx}p=KT>uuvjeGrlG@AhDO(Q+pqda=5LARa{1rZ{TZG%{Yoj@ zx$2%wUlQga zphpq7%uk!m2B7V1ebK83{22!Olz=Y~`6^!K&j%}F8dk(KtcYn?5!0|DreQ@)<7GsC Y1DpZ~H!rUSApigX07*qoM6N<$f+tZLVE_OC diff --git a/packages/stream_feed_flutter/test/goldens/post.png b/packages/stream_feed_flutter/test/goldens/post_icon.png similarity index 100% rename from packages/stream_feed_flutter/test/goldens/post.png rename to packages/stream_feed_flutter/test/goldens/post_icon.png diff --git a/packages/stream_feed_flutter/test/goldens/reply.png b/packages/stream_feed_flutter/test/goldens/reply_icon.png similarity index 100% rename from packages/stream_feed_flutter/test/goldens/reply.png rename to packages/stream_feed_flutter/test/goldens/reply_icon.png diff --git a/packages/stream_feed_flutter/test/goldens/repost.png b/packages/stream_feed_flutter/test/goldens/repost_icon.png similarity index 100% rename from packages/stream_feed_flutter/test/goldens/repost.png rename to packages/stream_feed_flutter/test/goldens/repost_icon.png diff --git a/packages/stream_feed_flutter/test/goldens/share.png b/packages/stream_feed_flutter/test/goldens/share_icon.png similarity index 100% rename from packages/stream_feed_flutter/test/goldens/share.png rename to packages/stream_feed_flutter/test/goldens/share_icon.png diff --git a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart b/packages/stream_feed_flutter/test/icons_test.dart similarity index 76% rename from packages/stream_feed_flutter/test/stream_feed_flutter_test.dart rename to packages/stream_feed_flutter/test/icons_test.dart index f80bee9ad..c0e0e6920 100644 --- a/packages/stream_feed_flutter/test/stream_feed_flutter_test.dart +++ b/packages/stream_feed_flutter/test/icons_test.dart @@ -26,7 +26,7 @@ void main() { Center(child: StreamSvgIcon.repost()), surfaceSize: const Size(50, 50), ); - await screenMatchesGolden(tester, 'repost'); + await screenMatchesGolden(tester, 'repost_icon'); }); testGoldens('reply', (tester) async { @@ -34,7 +34,7 @@ void main() { Center(child: StreamSvgIcon.reply()), surfaceSize: const Size(50, 50), ); - await screenMatchesGolden(tester, 'reply'); + await screenMatchesGolden(tester, 'reply_icon'); }); testGoldens('share', (tester) async { @@ -42,7 +42,7 @@ void main() { Center(child: StreamSvgIcon.share()), surfaceSize: const Size(50, 50), ); - await screenMatchesGolden(tester, 'share'); + await screenMatchesGolden(tester, 'share_icon'); }); testGoldens('post', (tester) async { @@ -50,7 +50,7 @@ void main() { Center(child: StreamSvgIcon.post()), surfaceSize: const Size(50, 50), ); - await screenMatchesGolden(tester, 'post'); + await screenMatchesGolden(tester, 'post_icon'); }); testGoldens('categories', (tester) async { @@ -58,7 +58,7 @@ void main() { Center(child: StreamSvgIcon.categories()), surfaceSize: const Size(50, 50), ); - await screenMatchesGolden(tester, 'categories'); + await screenMatchesGolden(tester, 'categories_icon'); }); testGoldens('gear', (tester) async { @@ -66,7 +66,15 @@ void main() { Center(child: StreamSvgIcon.gear()), surfaceSize: const Size(50, 50), ); - await screenMatchesGolden(tester, 'gear'); + await screenMatchesGolden(tester, 'gear_icon'); + }); + + testGoldens('avatar', (tester) async { + await tester.pumpWidgetBuilder( + Center(child: StreamSvgIcon.avatar()), + surfaceSize: const Size(50, 50), + ); + await screenMatchesGolden(tester, 'avatar_icon'); }); }); } From b86189dbde61705831f815fae9c71c96a1fddd13 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 11:20:22 -0400 Subject: [PATCH 0020/1241] make avatar depedent of stream_feed User type --- packages/stream_feed_flutter/lib/src/avatar.dart | 12 +++++++----- packages/stream_feed_flutter/pubspec.yaml | 8 +++++--- .../stream_feed_flutter/test/avatar_test.dart | 12 ++++++++++-- .../test/goldens/love_active_icon.png | Bin 0 -> 464 bytes .../test/goldens/love_inactive_icon.png | Bin 0 -> 638 bytes .../lib/stream_feed_flutter_core.dart | 6 +----- 6 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 packages/stream_feed_flutter/test/goldens/love_active_icon.png create mode 100644 packages/stream_feed_flutter/test/goldens/love_inactive_icon.png diff --git a/packages/stream_feed_flutter/lib/src/avatar.dart b/packages/stream_feed_flutter/lib/src/avatar.dart index 1ce22a4a9..4bd3c73f5 100644 --- a/packages/stream_feed_flutter/lib/src/avatar.dart +++ b/packages/stream_feed_flutter/lib/src/avatar.dart @@ -1,15 +1,17 @@ import 'package:flutter/material.dart'; -import 'package:stream_feed_flutter/stream_feed_flutter.dart'; +import 'package:stream_feed_flutter/src/icons.dart'; +import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart' + hide Image; class Avatar extends StatelessWidget { - final String? url; - Avatar({this.url}); + final User? user; + Avatar({this.user}); @override Widget build(BuildContext context) { - return url != null + return user != null ? ClipOval( child: Image.network( - url!, + user!.data!['profile_image'] as String, width: 30, height: 30, fit: BoxFit.cover, diff --git a/packages/stream_feed_flutter/pubspec.yaml b/packages/stream_feed_flutter/pubspec.yaml index 547ab0634..120eb4bfd 100644 --- a/packages/stream_feed_flutter/pubspec.yaml +++ b/packages/stream_feed_flutter/pubspec.yaml @@ -2,15 +2,17 @@ name: stream_feed_flutter description: Stream Feed official Flutter SDK. Build your own chat experience using Dart and Flutter. version: 0.0.0 homepage: https://getstream.io/ +publish_to: none environment: sdk: '>=2.12.0 <3.0.0' dependencies: - flutter_svg: ^0.22.0 - flutter: + flutter_svg: ^0.22.0 + flutter: sdk: flutter - + stream_feed_flutter_core: + path: ../stream_feed_flutter_core dev_dependencies: golden_toolkit: ^0.9.0 diff --git a/packages/stream_feed_flutter/test/avatar_test.dart b/packages/stream_feed_flutter/test/avatar_test.dart index 78a61182b..5ebad2832 100644 --- a/packages/stream_feed_flutter/test/avatar_test.dart +++ b/packages/stream_feed_flutter/test/avatar_test.dart @@ -3,18 +3,26 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:golden_toolkit/golden_toolkit.dart'; import 'package:mocktail_image_network/mocktail_image_network.dart'; import 'package:stream_feed_flutter/stream_feed_flutter.dart'; +import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart' + hide Image; // import 'package:test/test.dart'; void main() { group('Avatar', () { testWidgets('url', (tester) async { await mockNetworkImages(() async { - await tester.pumpWidget(Avatar(url: 'https://via.placeholder.com/150')); + await tester.pumpWidget(Avatar( + user: User( + data: { + 'name': 'Sloan Humfrey', + 'profile_image': 'https://randomuser.me/api/portraits/women/1.jpg', + }, + ))); expect(find.byType(Image), findsOneWidget); }); }); - testGoldens('avatar', (tester) async { + testGoldens('avatar default', (tester) async { await tester.pumpWidgetBuilder( Center(child: Avatar()), surfaceSize: const Size(50, 50), diff --git a/packages/stream_feed_flutter/test/goldens/love_active_icon.png b/packages/stream_feed_flutter/test/goldens/love_active_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..444b773f0bf454bb697d48ea459f2cc3ca219306 GIT binary patch literal 464 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^R}EX7WqAsj$Z z!;#Vfl&kV|aSX|5d^=%Z6rAq;VnJYR> zLR_TeWgLAX56wC6u`c{Tb&HO30bin>`-x5Gq>A?+o}!wdJL~0^&23YdOE-AwiK`q} ze(?A3>$62S*ICQRv2PGNo79+Qws?u7uwiQF$-M9Dk0h*d-FtVEmUET+q|2Rpj12d- zZ`9ZsU^e@9Z%OgFh%Le0i=})vW++{ow5{AD_)^&<4-KwMXRSBRQGTo58PM+oRMKT} zJZNfw$osV%3|Cf*zK!*~Y{n*7wLVq%)!ApJlG%aluj{n4d0&?J^rv#>dUkYGsHgV`7V)WCy7ONkd8O35Zl^QRwg4ZQRHeI_tg7(8A5T-G@yGywp3 CM8+}z literal 0 HcmV?d00001 diff --git a/packages/stream_feed_flutter/test/goldens/love_inactive_icon.png b/packages/stream_feed_flutter/test/goldens/love_inactive_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..36cd663fb5b436425edbbdf4150963dea0be65ab GIT binary patch literal 638 zcmV-^0)hRBP)Px#1am@3R0s$N2z&@+hyVZrC`m*?RA_0}MHWXTl1h+B zehd;@S!5+RDqBY-HnO&Zxf4u#$1NPY4c*N!`D|V?@9UeqJa{{w&%by9etdTV&%%nB zh7~alD`FZ}#5AmkX;=}{up*}M^BIR!RmFb4=Xg9)*ENpg;CUXC$ppu7u3}E76IE3q zgkU%vUd8C}ru)Mx&vVi=rLOCn>$BMmfbDjBb6p6*bUI};8tJ5=CsI`v>-Cztu8~p_ zh9R!&qLkurI8YSDRlM)}jK||PX1Ci>mL)<6R;!g(Wwb<+B%vq@q?F9(^LOi6mXW3@ z0MqG|APC;Y#BoenmiWF;6h&QA(YqsMSppD-;m!3R2yk5&0MGMo#)M%=S(fctUC|P0 z?nRUAE$#_4G<)yev5%tFeuWUg<*sz4**h2vbW+h1kx~Me&efG>@1x2+LQAA+nOT-~ zs!CN=WLb7~R#&t{JkLW)NnO{(as281aU8d;`&%ml5JeF}2$WKHAH7>7NrF;}!C;`( zb{n)sgb*y3ON0>QdHx}p=KT>uuvjeGrlG@AhDO(Q+pqda=5LARa{1rZ{TZG%{Yoj@ zx$2%wUlQga zphpq7%uk!m2B7V1ebK83{22!Olz=Y~`6^!K&j%}F8dk(KtcYn?5!0|DreQ@)<7GsC Y1DpZ~H!rUSApigX07*qoM6N<$f+tZLVE_OC literal 0 HcmV?d00001 diff --git a/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart index e3814d775..c06173f0b 100644 --- a/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart +++ b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart @@ -1,8 +1,4 @@ -/// Support for doing something awesome. -/// -/// More dartdocs go here. library stream_feed_flutter_core; export 'src/stream_feed_core.dart'; - -// TODO: Export any libraries intended for clients of this package. +export 'package:stream_feed/stream_feed.dart'; From 62f86599b1ba7ff29988b6198124a5848fc429f1 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 12:03:53 -0400 Subject: [PATCH 0021/1241] reaction icon wip + golden --- .../lib/src/reaction_icon.dart | 15 ++++++++++++ .../lib/stream_feed_flutter.dart | 1 + .../test/flutter_test_config.dart | 9 +++++++ .../test/goldens/repost.png | Bin 0 -> 1037 bytes .../test/reaction_icon_test.dart | 22 ++++++++++++++++++ 5 files changed, 47 insertions(+) create mode 100644 packages/stream_feed_flutter/lib/src/reaction_icon.dart create mode 100644 packages/stream_feed_flutter/test/flutter_test_config.dart create mode 100644 packages/stream_feed_flutter/test/goldens/repost.png create mode 100644 packages/stream_feed_flutter/test/reaction_icon_test.dart diff --git a/packages/stream_feed_flutter/lib/src/reaction_icon.dart b/packages/stream_feed_flutter/lib/src/reaction_icon.dart new file mode 100644 index 000000000..3b6178337 --- /dev/null +++ b/packages/stream_feed_flutter/lib/src/reaction_icon.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class ReactionIcon extends StatelessWidget { + ReactionIcon({required this.count, required this.icon}); + final int count; + final Widget icon; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [icon, SizedBox(width: 6), Text('$count')], + ); + } +} diff --git a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart index d33a5d840..1a86f9937 100644 --- a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart +++ b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -2,3 +2,4 @@ library stream_feed_flutter; export 'src/icons.dart'; export 'src/avatar.dart'; +export 'src/reaction_icon.dart'; diff --git a/packages/stream_feed_flutter/test/flutter_test_config.dart b/packages/stream_feed_flutter/test/flutter_test_config.dart new file mode 100644 index 000000000..c09db7005 --- /dev/null +++ b/packages/stream_feed_flutter/test/flutter_test_config.dart @@ -0,0 +1,9 @@ +import 'dart:async'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; + +Future testExecutable(FutureOr Function() testMain) async { + await loadAppFonts(); + return testMain(); +} diff --git a/packages/stream_feed_flutter/test/goldens/repost.png b/packages/stream_feed_flutter/test/goldens/repost.png new file mode 100644 index 0000000000000000000000000000000000000000..fc5eb646cc0c87eed417ba7c8aa20f4fb5c1f706 GIT binary patch literal 1037 zcmeAS@N?(olHy`uVBq!ia0vp^DM0Ma!3HGTB$T!TDaPU;cPEB*=VV?2IV{Cao*^7S zP{WbZ!N9=0-P6S}q+-t7TmBlq3uTUfoIYQ6pK6rn;|C8EKJDE#A?Ct9shu9)L0)3I zry4CS1Wnn~Z&~aN*uil#eCOsT=gr$SHy`$kXP=bM_lNJ+jr0EB?tc4P>Hq$?>)X$B z_g4O@+yA?6`GcQ7e~R|>*e_yFSZTpwDAOXr=fuOV*w!p?*sE%DDQ4c0~ff5(P~2H$RXQeNcNbFj-c-yvXU$RrZD<+hjm)*H#|Nj2Nhn?4~UAxpq zj)P^x)~&4`Doy+L*;&jzCqG~JJzwOiRkQY${q(qO($m+Ml#|2r_3Ky7>`gk07cXYs zq?24;EuOjg18sb3T54{``5d#o67ze^*bLG9}{E-ph(P{4d|Uaj}u}f2WwX z-hGXd5u3t~y!XcsPYbR8_|xsh?lt#+&2%$ssh4Bg^Hy_`N~c^ii;&|D>xbfPI-(RN edsyCirmx# Date: Tue, 18 May 2021 13:23:45 -0400 Subject: [PATCH 0022/1241] todo --- packages/stream_feed_flutter/lib/src/icons.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_feed_flutter/lib/src/icons.dart b/packages/stream_feed_flutter/lib/src/icons.dart index e706113b2..e4db315d7 100644 --- a/packages/stream_feed_flutter/lib/src/icons.dart +++ b/packages/stream_feed_flutter/lib/src/icons.dart @@ -135,7 +135,7 @@ class StreamSvgIcon extends StatelessWidget { Widget build(BuildContext context) { final key = Key('StreamSvgIcon-$assetName'); return SvgPicture.asset( - 'lib/svgs/$assetName', + 'lib/svgs/$assetName', //TODO: allow to load via url for ReactionIcon package: 'stream_feed_flutter', key: key, width: width, From 98178ffd35eb967c71a5344bc1e2c262f36e15a0 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 14:31:48 -0400 Subject: [PATCH 0023/1241] ReactionToggleIcon --- .../lib/src/reaction_icon.dart | 10 +++-- .../lib/src/reaction_toggle_icon.dart | 27 +++++++++++++ .../lib/stream_feed_flutter.dart | 1 + .../goldens/reaction_toggle_icon_grid.png | Bin 0 -> 5835 bytes .../test/reaction_toggle_icon_test.dart | 37 ++++++++++++++++++ .../lib/src/extensions.dart | 6 +++ .../lib/stream_feed_flutter_core.dart | 1 + 7 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 packages/stream_feed_flutter/lib/src/reaction_toggle_icon.dart create mode 100644 packages/stream_feed_flutter/test/goldens/reaction_toggle_icon_grid.png create mode 100644 packages/stream_feed_flutter/test/reaction_toggle_icon_test.dart create mode 100644 packages/stream_feed_flutter_core/lib/src/extensions.dart diff --git a/packages/stream_feed_flutter/lib/src/reaction_icon.dart b/packages/stream_feed_flutter/lib/src/reaction_icon.dart index 3b6178337..dfb36b7e4 100644 --- a/packages/stream_feed_flutter/lib/src/reaction_icon.dart +++ b/packages/stream_feed_flutter/lib/src/reaction_icon.dart @@ -1,15 +1,19 @@ import 'package:flutter/material.dart'; class ReactionIcon extends StatelessWidget { - ReactionIcon({required this.count, required this.icon}); - final int count; + ReactionIcon({this.count, required this.icon}); + final int? count; final Widget icon; @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, - children: [icon, SizedBox(width: 6), Text('$count')], + children: [ + icon, + SizedBox(width: 6), + count != null ? Text('$count') : Container() + ], ); } } diff --git a/packages/stream_feed_flutter/lib/src/reaction_toggle_icon.dart b/packages/stream_feed_flutter/lib/src/reaction_toggle_icon.dart new file mode 100644 index 000000000..ec0e81f7e --- /dev/null +++ b/packages/stream_feed_flutter/lib/src/reaction_toggle_icon.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:stream_feed_flutter/src/reaction_icon.dart'; +import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart'; + +class ReactionToggleIcon extends StatelessWidget { + final List? ownReactions; + final Widget activeIcon; + final Widget inactiveIcon; + final String kind; + final int? count; + + ReactionToggleIcon( + {required this.activeIcon, + required this.inactiveIcon, + required this.kind, + this.ownReactions, + this.count}); + @override + Widget build(BuildContext context) { + final hasReactions = ownReactions != null; + final icon = hasReactions && ownReactions!.filterByKind(kind).isNotEmpty + ? activeIcon + : inactiveIcon; + + return ReactionIcon(icon: icon, count: count); + } +} diff --git a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart index 1a86f9937..e9f1e8c13 100644 --- a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart +++ b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -3,3 +3,4 @@ library stream_feed_flutter; export 'src/icons.dart'; export 'src/avatar.dart'; export 'src/reaction_icon.dart'; +export 'src/reaction_toggle_icon.dart'; \ No newline at end of file diff --git a/packages/stream_feed_flutter/test/goldens/reaction_toggle_icon_grid.png b/packages/stream_feed_flutter/test/goldens/reaction_toggle_icon_grid.png new file mode 100644 index 0000000000000000000000000000000000000000..16885eceb0b091542f0cc5dfa92c0cad5d1d2af3 GIT binary patch literal 5835 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 SVksC%Lo`)&RVtLM!~O$3drx%$ literal 0 HcmV?d00001 diff --git a/packages/stream_feed_flutter/test/reaction_toggle_icon_test.dart b/packages/stream_feed_flutter/test/reaction_toggle_icon_test.dart new file mode 100644 index 000000000..73068b5c6 --- /dev/null +++ b/packages/stream_feed_flutter/test/reaction_toggle_icon_test.dart @@ -0,0 +1,37 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; +import 'package:mocktail_image_network/mocktail_image_network.dart'; +import 'package:stream_feed_flutter/stream_feed_flutter.dart'; +import 'package:stream_feed_flutter_core/stream_feed_flutter_core.dart' + hide Image; +// import 'package:test/test.dart'; + +void main() { + group('ReactionToggleIcon', () { + testGoldens('reaction toggle icon', (tester) async { + final builder = GoldenBuilder.grid(columns: 2, widthToHeightRatio: 0.5) + ..addScenario( + 'without own reactions', + ReactionToggleIcon( + kind: 'like', + count: 1300, + inactiveIcon: StreamSvgIcon.loveInactive(), + activeIcon: StreamSvgIcon.loveInactive())) + ..addScenario( + 'with own reactions', + ReactionToggleIcon( + kind: 'like', + count: 1300, + ownReactions: [Reaction(kind: 'like')], + inactiveIcon: StreamSvgIcon.loveInactive(), + activeIcon: StreamSvgIcon.loveActive())); + await tester.pumpWidgetBuilder(builder.build()); + await tester.pumpWidgetBuilder( + builder.build(), + surfaceSize: const Size(250, 100), + ); + await screenMatchesGolden(tester, 'reaction_toggle_icon_grid'); + }); + }); +} diff --git a/packages/stream_feed_flutter_core/lib/src/extensions.dart b/packages/stream_feed_flutter_core/lib/src/extensions.dart new file mode 100644 index 000000000..ea984e627 --- /dev/null +++ b/packages/stream_feed_flutter_core/lib/src/extensions.dart @@ -0,0 +1,6 @@ +import 'package:stream_feed/stream_feed.dart'; + +extension ReactionX on List { + List filterByKind(String kind) => + where((element) => element.kind == kind).toList(); +} diff --git a/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart index c06173f0b..d887ad8d6 100644 --- a/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart +++ b/packages/stream_feed_flutter_core/lib/stream_feed_flutter_core.dart @@ -2,3 +2,4 @@ library stream_feed_flutter_core; export 'src/stream_feed_core.dart'; export 'package:stream_feed/stream_feed.dart'; +export 'src/extensions.dart'; From e7b547922e54e34415dab52d22521b2db661232c Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 15:21:24 -0400 Subject: [PATCH 0024/1241] gradient button --- .../stream_feed_flutter/lib/src/button.dart | 36 ++++++++++++++++++ .../lib/stream_feed_flutter.dart | 3 +- .../stream_feed_flutter/test/button_test.dart | 22 +++++++++++ .../test/goldens/button.png | Bin 0 -> 1373 bytes 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 packages/stream_feed_flutter/lib/src/button.dart create mode 100644 packages/stream_feed_flutter/test/button_test.dart create mode 100644 packages/stream_feed_flutter/test/goldens/button.png diff --git a/packages/stream_feed_flutter/lib/src/button.dart b/packages/stream_feed_flutter/lib/src/button.dart new file mode 100644 index 000000000..f7c510a5d --- /dev/null +++ b/packages/stream_feed_flutter/lib/src/button.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class Button extends StatelessWidget { + final String label; + final VoidCallback onPressed; + Button({required this.label, required this.onPressed}); + @override + Widget build(BuildContext context) { + return Container( + width: 80, + height: 30, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + boxShadow: [ + BoxShadow( + color: Color(0x28000000), + blurRadius: 2, + offset: Offset(0, 1), + ), + ], + gradient: LinearGradient( + // begin: Alignment.topCenter, + // end: Alignment.bottomCenter, + colors: [Color(0xFF00A1FF), Color(0xFF007AFF)], + ), + ), + child: TextButton( + onPressed: onPressed, + child: Text( + label, + style: TextStyle(color: Colors.white), + ), + ), + ); + } +} diff --git a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart index e9f1e8c13..92ec8525a 100644 --- a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart +++ b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -3,4 +3,5 @@ library stream_feed_flutter; export 'src/icons.dart'; export 'src/avatar.dart'; export 'src/reaction_icon.dart'; -export 'src/reaction_toggle_icon.dart'; \ No newline at end of file +export 'src/reaction_toggle_icon.dart'; +export 'src/button.dart'; diff --git a/packages/stream_feed_flutter/test/button_test.dart b/packages/stream_feed_flutter/test/button_test.dart new file mode 100644 index 000000000..22bd4c8e6 --- /dev/null +++ b/packages/stream_feed_flutter/test/button_test.dart @@ -0,0 +1,22 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; +import 'package:stream_feed_flutter/stream_feed_flutter.dart'; +// import 'package:test/test.dart'; + +void main() { + group('Button', () { + testGoldens('button', (tester) async { + await tester.pumpWidgetBuilder( + Center( + child: Button( + label: 'Follow', + onPressed: () {}, + ), + ), + surfaceSize: const Size(100, 75), + ); + await screenMatchesGolden(tester, 'button'); + }); + }); +} diff --git a/packages/stream_feed_flutter/test/goldens/button.png b/packages/stream_feed_flutter/test/goldens/button.png new file mode 100644 index 0000000000000000000000000000000000000000..70f6f54e8dc88c8c3a075df9532ccebdee6c0ca3 GIT binary patch literal 1373 zcmbW1`#Tc~7{{lCY%!9{T(@$|!VD>Lofau_jV>oPI@4@UtK8;3*NEyMmtiNw;aTHJ zb6m4c91N$9CAGBX8aC$$t%t#0gI z;GK(2aV<{6$ZHPlx0H{x=|#WcZ_sxfu1veVCA=$e*lt+NgQVY~sCWdupk{2y_VcKLssB>g@0k&DxT4Oe>)D0JrR0(MH0@zrClv z>5}6?AE>}_A4-n%$n_#Ih`vAJDdeg}UwgNyN^gy-%AuDCG91Q?mY%^ILX1TCUK~IWizb>>@7+^7c{}(gs-eKBnUHI zIpZt_&eFCUTgqPA>i>2$U|gJa+%TINr4tGekEZK9{ugOt+TrY>!gGbsjj@)cG^E1a zv$X;}_*CSuDm+Vqp(Wbt;kuHO1Q!?`8jvwo2Gvzhr6o-wtW5-MlQlISl+s79xHZez zd8d2aNli-hUMaz@RBImoUV>X2`ni#q!7_qVK~}+!42PJ<{2eKp$$>|BH5u?Q z(&EXZTf}8R>#lLc^*WA;y!aFbTZPXto&&G-^VsuNijPFEflZtfje? z9rhltP9au}quDIJ3Eu(83t`y-qr?&{xil)k7 zTREHsUtN-ZD8V76!Qd-PJWN`i05gOWZ>f@9B?;H=^mVvP^2m|)&xwi?F0itez>`&l z!p+w5o-cxvu;UwDI)m=RIi8C2y1IHYWgW9{@r>sXq~pPZ(){~lMN|xQ+1pV`vXX9b zG+9X!!{dr#FVD0VuYLE#lWS`#&v=K~2R~P{G`}gkg8OF1EAj#FOsU~M);R$+T@=JV zK0fsm=*GPKn)LfUp-m!F%Sb&hc4s?5<*M>p64vYurnmPHfv|dh;fjbI+sB>#&5Se{ zrlF-3;OAG|kjXT~KzmRywa(5?Mhrj1{~rliKC{2T^UH&Fu(8Wx7R@>^_XpWgq}+LL U?}Mrjl~p9b%kw;n?tU%fKh}tUb^rhX literal 0 HcmV?d00001 From 5a19fe35481d1aee632e959a32962c62a12bf299 Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Tue, 18 May 2021 16:33:17 -0400 Subject: [PATCH 0025/1241] button faded --- .../stream_feed_flutter/lib/src/button.dart | 58 +++++++++++++++++- .../stream_feed_flutter/test/button_test.dart | 27 +++++--- .../test/goldens/button.png | Bin 1373 -> 0 bytes .../test/goldens/buttons_grid.png | Bin 0 -> 6156 bytes 4 files changed, 74 insertions(+), 11 deletions(-) delete mode 100644 packages/stream_feed_flutter/test/goldens/button.png create mode 100644 packages/stream_feed_flutter/test/goldens/buttons_grid.png diff --git a/packages/stream_feed_flutter/lib/src/button.dart b/packages/stream_feed_flutter/lib/src/button.dart index f7c510a5d..e9393b812 100644 --- a/packages/stream_feed_flutter/lib/src/button.dart +++ b/packages/stream_feed_flutter/lib/src/button.dart @@ -1,9 +1,63 @@ import 'package:flutter/material.dart'; +enum ButtonType { faded, info, primary } + class Button extends StatelessWidget { final String label; final VoidCallback onPressed; - Button({required this.label, required this.onPressed}); + final ButtonType type; + Button({required this.label, required this.onPressed, required this.type}); + @override + Widget build(BuildContext context) { + switch (type) { + case ButtonType.primary: + return _GradientButton(onPressed: onPressed, label: label); + case ButtonType.faded: + return _BorderButton(onPressed: onPressed, label: label); + default: + return _GradientButton(onPressed: onPressed, label: label); + } + } +} + +class _BorderButton extends StatelessWidget { + final VoidCallback onPressed; + final String label; + const _BorderButton({ + Key? key, + required this.onPressed, + required this.label, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: 80, + height: 30, + child: TextButton( + onPressed: onPressed, + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(Colors.white), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6.0), + side: BorderSide(color: Color(0xFF007AFF))))), + child: Text(label), + ), + ); + } +} + +class _GradientButton extends StatelessWidget { + const _GradientButton({ + Key? key, + required this.onPressed, + required this.label, + }) : super(key: key); + + final VoidCallback onPressed; + final String label; + @override Widget build(BuildContext context) { return Container( @@ -19,8 +73,6 @@ class Button extends StatelessWidget { ), ], gradient: LinearGradient( - // begin: Alignment.topCenter, - // end: Alignment.bottomCenter, colors: [Color(0xFF00A1FF), Color(0xFF007AFF)], ), ), diff --git a/packages/stream_feed_flutter/test/button_test.dart b/packages/stream_feed_flutter/test/button_test.dart index 22bd4c8e6..62ed8d6af 100644 --- a/packages/stream_feed_flutter/test/button_test.dart +++ b/packages/stream_feed_flutter/test/button_test.dart @@ -7,16 +7,27 @@ import 'package:stream_feed_flutter/stream_feed_flutter.dart'; void main() { group('Button', () { testGoldens('button', (tester) async { + final builder = GoldenBuilder.grid(columns: 2, widthToHeightRatio: 0.5) + ..addScenario( + 'Button primary', + Button( + label: 'Follow', + onPressed: () {}, + type: ButtonType.primary, + )) + ..addScenario( + 'Button faded', + Button( + label: 'Following', + onPressed: () {}, + type: ButtonType.faded, + )); + await tester.pumpWidgetBuilder( - Center( - child: Button( - label: 'Follow', - onPressed: () {}, - ), - ), - surfaceSize: const Size(100, 75), + builder.build(), + surfaceSize: const Size(200, 150), ); - await screenMatchesGolden(tester, 'button'); + await screenMatchesGolden(tester, 'buttons_grid'); }); }); } diff --git a/packages/stream_feed_flutter/test/goldens/button.png b/packages/stream_feed_flutter/test/goldens/button.png deleted file mode 100644 index 70f6f54e8dc88c8c3a075df9532ccebdee6c0ca3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1373 zcmbW1`#Tc~7{{lCY%!9{T(@$|!VD>Lofau_jV>oPI@4@UtK8;3*NEyMmtiNw;aTHJ zb6m4c91N$9CAGBX8aC$$t%t#0gI z;GK(2aV<{6$ZHPlx0H{x=|#WcZ_sxfu1veVCA=$e*lt+NgQVY~sCWdupk{2y_VcKLssB>g@0k&DxT4Oe>)D0JrR0(MH0@zrClv z>5}6?AE>}_A4-n%$n_#Ih`vAJDdeg}UwgNyN^gy-%AuDCG91Q?mY%^ILX1TCUK~IWizb>>@7+^7c{}(gs-eKBnUHI zIpZt_&eFCUTgqPA>i>2$U|gJa+%TINr4tGekEZK9{ugOt+TrY>!gGbsjj@)cG^E1a zv$X;}_*CSuDm+Vqp(Wbt;kuHO1Q!?`8jvwo2Gvzhr6o-wtW5-MlQlISl+s79xHZez zd8d2aNli-hUMaz@RBImoUV>X2`ni#q!7_qVK~}+!42PJ<{2eKp$$>|BH5u?Q z(&EXZTf}8R>#lLc^*WA;y!aFbTZPXto&&G-^VsuNijPFEflZtfje? z9rhltP9au}quDIJ3Eu(83t`y-qr?&{xil)k7 zTREHsUtN-ZD8V76!Qd-PJWN`i05gOWZ>f@9B?;H=^mVvP^2m|)&xwi?F0itez>`&l z!p+w5o-cxvu;UwDI)m=RIi8C2y1IHYWgW9{@r>sXq~pPZ(){~lMN|xQ+1pV`vXX9b zG+9X!!{dr#FVD0VuYLE#lWS`#&v=K~2R~P{G`}gkg8OF1EAj#FOsU~M);R$+T@=JV zK0fsm=*GPKn)LfUp-m!F%Sb&hc4s?5<*M>p64vYurnmPHfv|dh;fjbI+sB>#&5Se{ zrlF-3;OAG|kjXT~KzmRywa(5?Mhrj1{~rliKC{2T^UH&Fu(8Wx7R@>^_XpWgq}+LL U?}Mrjl~p9b%kw;n?tU%fKh}tUb^rhX diff --git a/packages/stream_feed_flutter/test/goldens/buttons_grid.png b/packages/stream_feed_flutter/test/goldens/buttons_grid.png new file mode 100644 index 0000000000000000000000000000000000000000..1ebd55683542ea64ebb8b337cf101481d1909e41 GIT binary patch literal 6156 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 Date: Tue, 18 May 2021 16:38:24 -0400 Subject: [PATCH 0026/1241] format --- packages/stream_feed_flutter/lib/stream_feed_flutter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart index e9f1e8c13..2a72439fc 100644 --- a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart +++ b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -3,4 +3,4 @@ library stream_feed_flutter; export 'src/icons.dart'; export 'src/avatar.dart'; export 'src/reaction_icon.dart'; -export 'src/reaction_toggle_icon.dart'; \ No newline at end of file +export 'src/reaction_toggle_icon.dart'; From 6a57566b68e944c4ce1129f4b147478e56de221f Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Wed, 19 May 2021 08:43:03 -0400 Subject: [PATCH 0027/1241] format --- packages/stream_feed_flutter/lib/stream_feed_flutter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart index 96195f7d5..92ec8525a 100644 --- a/packages/stream_feed_flutter/lib/stream_feed_flutter.dart +++ b/packages/stream_feed_flutter/lib/stream_feed_flutter.dart @@ -4,4 +4,4 @@ export 'src/icons.dart'; export 'src/avatar.dart'; export 'src/reaction_icon.dart'; export 'src/reaction_toggle_icon.dart'; -export 'src/button.dart'; \ No newline at end of file +export 'src/button.dart'; From 0e73819241f46488d0620925c8e9090514a9438e Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Wed, 19 May 2021 09:21:38 -0400 Subject: [PATCH 0028/1241] update config --- .../test/flutter_test_config.dart | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/stream_feed_flutter/test/flutter_test_config.dart b/packages/stream_feed_flutter/test/flutter_test_config.dart index c09db7005..6c6b3be3a 100644 --- a/packages/stream_feed_flutter/test/flutter_test_config.dart +++ b/packages/stream_feed_flutter/test/flutter_test_config.dart @@ -1,9 +1,19 @@ import 'dart:async'; +import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; import 'package:golden_toolkit/golden_toolkit.dart'; Future testExecutable(FutureOr Function() testMain) async { - await loadAppFonts(); - return testMain(); + return GoldenToolkit.runWithConfiguration( + () async { + await loadAppFonts(); + await testMain(); + }, + config: GoldenToolkitConfiguration( + // Currently, goldens are not generated/validated in CI for this repo. We have settled on the goldens for this package + // being captured/validated by developers running on MacOSX. We may revisit this in the future if there is a reason to invest + // in more sophistication + skipGoldenAssertion: () => !Platform.isMacOS, + ), + ); } From 79ccd315c6b5ea804f86490b45eca78f247b296f Mon Sep 17 00:00:00 2001 From: Sacha Arbonel Date: Fri, 21 May 2021 16:26:21 -0400 Subject: [PATCH 0029/1241] textarea wip --- .../stream_feed_flutter/lib/src/textarea.dart | 73 +++++++++++++++++++ .../test/text_area_test.dart | 20 +++++ 2 files changed, 93 insertions(+) create mode 100644 packages/stream_feed_flutter/lib/src/textarea.dart create mode 100644 packages/stream_feed_flutter/test/text_area_test.dart diff --git a/packages/stream_feed_flutter/lib/src/textarea.dart b/packages/stream_feed_flutter/lib/src/textarea.dart new file mode 100644 index 000000000..a1981a379 --- /dev/null +++ b/packages/stream_feed_flutter/lib/src/textarea.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; + +class TextArea extends StatefulWidget { + TextArea( + {this.textEditingController, + this.maxHeight = 150, + this.focusNode, + this.autofocus = false, + this.keyboardType = TextInputType.multiline, + this.inputTextStyle, + this.hintText}); + + /// The text controller of the TextField + final TextEditingController? textEditingController; + + /// Maximum Height for the TextField to grow before it starts scrolling + final double maxHeight; + + /// The focus node associated to the TextField + final FocusNode? focusNode; + + /// Autofocus property passed to the TextField + final bool autofocus; + + /// The keyboard type assigned to the TextField + final TextInputType keyboardType; + + final String? hintText; + + final TextStyle? inputTextStyle; + + @override + _TextAreaState createState() => _TextAreaState(); +} + +class _TextAreaState extends State