Official flutter package for Pensil Community
The official Dart client for Pensil communities, a service for building communites 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 customised flutter mobile web application.
🛠Installation
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]
🔌 Usage
Client setup Serverside + Clientside
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.
Client API init
// 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>');
Configure rool level widget
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(),
);
}
}
How to authenticate a user
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 successfull authentication other wise it will retun error message. Authentication works in such an 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 recieved from google.
/// uid is authentication token recieved 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));
*/
});
}
How to Open community detail page
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!),
);
},
);
},
),
);
}
}
How to display sections of a 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!),
);
},
),
);
}
}
How to display section feed
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);
},
),
);
}
}
Docs
This package provides two types of components
- UI components
- Bussiness logic components
UI components
- PensilCommunityApp: a root level widget which initilise 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.
Bussiness logic components
- 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.
Dart version requirements
This API Client project requires Dart v2.12 at a minimum.
Example Project
There is a detailed Flutter example project in the example folder. You can directly run and play with it.