Official flutter package for Pensil
The official Dart client for Pensil communities, a service for building communities applications. This library can be used on any Dart project and on both mobile and web apps with Flutter. You can create your own community from Pensil and use this package to create your customized flutter mobile web application.
Install from pub.dev
Next step is to add pensil_community_flutter to your dependencies, to do that just open pubspec.yaml
file and add it inside the dependencies section.
dependencies:
flutter:
sdk: flutter
pensil_community_flutter: ^[latest-version]
If you want to use the PensilClient on your web/mobile app you need a community id. usertoken is a google authentication uid which is a optional and can be added later.
// Instantiate new client with a communityId and user token
// usertoken is a google authentication token(uid) received during google login.
final pensilClient = PensilClient(communityId: '<Community id>',usertoken: '<user token>');
Add PensilCommunityApp
widget into your rool lavel widget and initialize its bloc
with PensilBloc
constructor and pass pensilClient
in it.
class MyApp extends StatelessWidget {
const MyApp({required this.pensilClient, Key? key}) : super(key: key);
final PensilClient pensilClient;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Community Demo',
builder: (context, child) {
return PensilCommunityApp(
bloc: PensilBloc(client: pensilClient),
child: child!,
);
},
home: const Login(),
);
}
}
Currently pensil_community_flutter
support google authentication only. To authenticate a user, pass google authentication token (uid) to package and it will return user data on successful authentication other wise it will return error message. Authentication works in such a way that user has no need to signup from any where. If user is a new on platform then authentication will create a new user and returns its profile data received from google.
/// uid is authentication token received from google login
void loginWithGoogle(String uid) async {
final pensilClient = PensilProvider.of(context).bloc.client;
final response = await pensilClient.curentUser.loginWithGoogle(uid);
response.fold((error) {
/// Display error message when authentication failed
},
(user) {
print(user.name);
/*
// Display success message when login success
// Navigate to community detail
Navigator.pushReplacement(context, CommunityDetailPage.getRoute(pensilClient));
*/
});
}
final pensilClient = PensilProvider.of(context).bloc.client;
Navigator.pushReplacement(context, CommunityDetailPage.getRoute(pensilClient));
Community Detail page
class CommunityDetailPage extends StatelessWidget {
const CommunityDetailPage({Key? key, this.communityId}) : super(key: key);
static Route<T> getRoute<T>(PensilClient pensilClient) {
return MaterialPageRoute(
builder: (_) {
return CommunityProvider(
bloc: CommunityBloc(pensilClient: pensilClient),
child: CommunityDetailPage(
communityId: pensilClient.communityId,
),
);
},
);
}
final String? communityId;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: PensilCommunityBuilder(
errorBuilder: (_, err) {
return Center(
child: Text(err.message),
);
},
builder: (_, Community? community) {
return PensilGroupListView(
communityId: communityId!,
onGroupTileTap: (group) {
Navigator.push(
context,
GroupDetailPage.getRoute(context.communityClient, group!),
);
},
);
},
),
);
}
}
/// `group` is a selected group from groups list.
final communityClient = CommunityProvider.of(this).bloc.client;
Navigator.push(context,GroupDetailPage.getRoute(communityClient, group!));
Group Detail page
class GroupDetailPage extends StatelessWidget {
const GroupDetailPage({Key? key, required this.group}) : super(key: key);
/// Material Route page to open Group detail
static Route<T> getRoute<T>(CommunityClient communityClient, Group group) {
return MaterialPageRoute(
builder: (_) {
return GroupProvider(
bloc: GroupBloc(
communityClient: communityClient,
groupId: group.id!,
)..addAllSections(group.sections!),
child: GroupDetailPage(group: group),
);
},
);
}
final Group group;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(group.name!)),
body: PensilSectionListView(
groupId: group.id!,
onSectionTileTap: (section) {
final bloc = GroupProvider.of(context).bloc;
Navigator.push(
context,
SectionfeedPage.getRoute(bloc.client, section!),
);
},
),
);
}
}
Navigate to section feed.
/// `section` is a selected section from sections list
final groupClient = GroupProvider.of(context).bloc;
Navigator.push(context,SectionfeedPage.getRoute(groupClient, section!));
Section feed
class SectionfeedPage extends StatelessWidget {
const SectionfeedPage({Key? key, required this.section}) : super(key: key);
static Route<T> getRoute<T>(GroupClient groupClient, Section section) {
return MaterialPageRoute(
builder: (_) {
return SectionProvider(
bloc: SectionBloc(
groupClient: groupClient,
sectionId: section.id!,
type: section.sectionType),
child: SectionfeedPage(section: section),
);
},
);
}
final Section section;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(section.name!)),
body: PensilSectionFeedBuilder(
errorBuilder: (_, err) {
return Center(
child: Text(err.message),
);
},
builder: (BuildContext context, List<Post>? community) {
final id = SectionProvider.of(context).bloc.sectionId;
return PensilPostFeedListView(sectionId: id);
},
),
);
}
}
This package provides two types of components
- UI components
- Bushiness logic components
- PensilCommunityApp: a root level widget which initialize the pensil client and pensil theme.
- PensilCommunityBuilder: a widget designed to get community data to pass it to its children.
- PensilGroupListView: a widget to render group list of a community.
- PensilSectionListView: a widget to render section list of a group.
- PensilSectionFeedBuilder: a widget designed to get section feed and pass it to its children.
- PensilPostFeedListView: a widget to render post feed of a section.
- PensilBloc: handle root level operations.
- PensilProvider: an Inherited widget providing access to PensilBloc in the widget tree.
- CommunityBloc: handle community level operations.
- CommunityProvider: an Inherited widget providing access to CommunityBloc in the widget tree.
- GroupBloc: handle group level operations.
- GroupProvider: an Inherited widget providing access to GroupBloc in the widget tree.
- SectionBloc: handle section level operations.
- SectionProvider: an Inherited widget providing access to SectionBloc in the widget tree.
This API Client project requires Dart v2.12 at a minimum.
There is a detailed Flutter example project in the example folder. You can directly run and play with it.