fireflow 0.0.89 fireflow: ^0.0.89 copied to clipboard
This package is designed for FlutterFlow app to provide enhanced features.
FlutterFlow Documents: English | 한국어
Flutter Documents: English
Fireflow #
-
Fireflow
is an open source, easy and rapid development tool to build apps like social network service, forum based community service, online shopping service, and much more. -
Fireflow
is developped forFlutterFlow
. But it can be used forFlutter
also.- For the example code of Flutter, see the example project.
-
If you encounter an error, please create an issue in fireflow git issue.
- Fireflow
- Overview
- Features
- TODO
- Getting started
- The structure of Fireflow
- User
- User setting
- System setting
- Push notification
- Chat
- Chat Overview
- Chat schema
- Logic of chat
- Entering Chat Room to begin chat
- How to list my chat rooms
- How to display menu when the chat message has tapped.
- How to leave a group chat room.
- How to display an uploaded file.
- How to not invite the same user.
- How to display the protocol message.
- How to remove a user
- How to receive and display the push notifications while the app is foreground.
- How to display the number of chat rooms with new messages.
- How to query to the Open AI - GPT.
- How to change chat room title
- How to send chat message
- How to create a group chat
- Chat Design
- Forum
- Files
- Supabase
- Widgets
- Actions
- Functions
- Unit Testing
- Developer coding guide
- Sponsors
- Known Issues
Overview #
Flutterflow is a gorgeous platform to build mobile apps rapidly. The developers can build whatever apps they like without any limitations.
Flutterflow comes easy when the project is relatively small. But when the project grows with complicated functionalities and logics, you will feel the pressure of what the professional developer feels.
To make the apps fully functional, the developers definitely need the use of custom code. It's important, but many of Flutterflow developers are stuck with Custom functions, custom widgets, and custom actions. That's where Fireflow came in.
Fireflow encapsulates all the complicated logics and serve most of the common use cases. Use it build professional apps like chat apps, SNS apps, community apps, and more.
Features #
-
Enhanced user management
- The documents of the
/users
collection have private information and shouldn't be disclosed. But the user information is needed to be disclosed for the most app features. To make it happen, I created another collection named/users_public_data
that does not hold user's prviate information.
- The documents of the
-
File upload and display.
- Any kinds of files can be uploaded and displayed like Image, Video, TXT, PDF, ZIP, etc.
- It can be used in Chat, Forum and for any features.
-
Chat
- Custom design.
- Tap on chat message to delete, edit, copy, open, etc.
- Push notification. User can subscribe/unsubscribe chat room.
- Display the number of chat room that has unread messages.
- Open AI. GPT query. Chat members can query to GPT and share.
- Uploading any kinds of files like Image, Video, TXT, PDF, ZIP, etc.
- User invite and leave in Group chat.
- Moderator can remove a user.
- Custom design.
-
Forum
- Complete functionalities of forum including
- uploading multiple files.
- displaying nested comments.
- etc.
- Forum is the based of all functions. You can create whatever features extending the forum.
- Complete functionalities of forum including
-
Push Notification
- Sending push notification to all users.
- Display the push notification while the app is on foreground.
- Subscribe new comments under my posts and comments.
- Subscribe new posts of a category.
- Subscribe new comments of a category.
-
Enhanced Firestore Security Rules
-
Custom widgets
TODO #
-
Tracking the file uploads and deletes. those should be by
uploadImage
anddeleteImage
methods.- For the search/list functionality of uploaded files.
-
Forum The complete forum functionality including;
- Category management (o)
- User role management
- Post and comment management including (o)
- Nested (threaded) comments (o)
- Push notification
- Subscribing/Unsubscribing a category
- Sending push notifications to the author of the parent comments and post.
-
Hard limit on wait minutes for post creation.
- Add a security rules for timestamp check.
-
Optional push notification.
- There will be an option to enable or disable push notification.
-
Display user online/offline status without Cloud function.
- Record on/offline status on Realtime database only and create a widget to display whether the user is online or offline.
- If the on/off status is not save in firestore, it cannot be searched. but it can display.
-
Chat
- Block the moderator to leave the chat room when there are other members in the room.
- Destroying the chat room. The fireflow will automatically remove all users and delete the chat room.
- Block users not to enter the chat room.
blockUsers
will hold the list of the blocked users. - Sending push notification to all users including those who are unsubscribed the chat room.
-
Since the
AppCheck
is built-in by Flutterflow, why don't fireflow remove the security rules and/users_public_data
? -
Image cropping before uploading.
-
Sample application "Schedule management" app.
- It can be a kind of todo app, calendar app, task app.
- Works based on time line.
- An event can be repeat.
- With push notification. Scheduling push notification in advance will not work here. There must be a cron like scheduler which send push notificatoin by search the event date on every minute.
Getting started #
To get started, you would need to install the necessary parts of the Fireflow.
Setting up Firebase #
Firestore Security Rules #
Fireflow has its own Firestore Security Rules to protect the app safer.
You may think App check
will do for the security. Partly, yes. While App Check
adds an important layer of protection against some (not all) abuse towards your backend, it does not replace Firebase's server-side security rules. See the App Check offical document.
To apply it, you will need to check the Exclude
buttons on the Collections like below.
And copy the fireflow security rules and paste it into your Firebase firestore security rules.
Enable deeplink #
- Enable the Deeplink in FlutterFlow.
Enable Push notifications #
- The fireflow is tightly coupled with the Push Notification as of now. So, you need to enable push notification on Flutterflow.
AppService #
AppService
will serve with the core services of fireflow through the lifecyle of the app. You can initialize like below.
import '../../backend/push_notifications/push_notifications_handler.dart';
import 'package:fireflow/fireflow.dart';
Future appService(BuildContext context) async {
AppService.instance.init(
context: context,
debug: true,
supabase: SupabaseOptions(
usersPublicData: 'users_public_data',
posts: 'posts',
comments: 'comments',
),
messaging: MessagingOptions(
foreground: true,
background: false,
onTap: (String initialPageName, Map<String, String> parameterData) {
dog('on message tap: $initialPageName, Map<String, String> $parameterData');
context.pushNamed(initialPageName, queryParams: parameterData);
},
),
);
}
To see the details, refer the document of AppService.init
As you can see, it uses the push_notifications_handler.dart
that is generated by Fluterflow. So, you need to check Exclude from compilation
.
The onTapMessage
is the push notification handler while the app is foreground. And If you don't want it, you can remove that part including import .../push_notifications_handler.dart;
And uncheck the Exclude from compilation
.
-
There are some functions, widgets and actions that don't need to connect to Firebase and don't need to use BuildContext. They are called as Independent Components.
- For
Independent Components
, you don't have to initialize theAppService
. - I should have decoupled the Independent Components, but I didn't for hoping that people who need the
Independent Components
would get interested in fireflow.
- For
-
Add the
appService
action on the root level screens.- One thing to note is that, the context that is given to
AppService
must be valid context. You may initialize theAppService
on all the root level screens to provide valid context. - The root level screen is the screens that are the at bottom parts of the nav stack and the context of the screens must alive.
- For instance, If the Home screen is always exists at the bottom of the nav stack, then you can only add the
appService
action on Home screen.
- For instance, If the Home screen is always exists at the bottom of the nav stack, then you can only add the
- If you really don't know what to do, you can simply add the action on every page.
- One thing to note is that, the context that is given to
Local State Variable #
Note that, these local state variables may be changed based on your app logic.
defaultImagePath
is the image path that will be used by default. For instance, when you add a Image widget and sometimes it needs the default image.anonymousMaleUrl
is the male picture url that will be shown by default when the user is male and has no profile photo.anonymousFemaleUrl
is the female picture url that will be used when the user is female and has no profile photo.chatSendMessageAskResult
is the state that will hold the result of chat send option. When the user sends a message, he can choose an option whether to query to GPT or not.gptLoader
is the state that when the user query to GPT, it will show the loading indicator.anonymousEmail
is used for guest login.anonymousPassword
is used for guest password. It's okay that the guest password is revealed to the public. Anonyone can login anyway.isGuest
is needed to be set to true on home screen if the user signed in as guest.tempStringArray
is for temporarily saving a string array. For instance, when a user uploads multiple files/photos, the app can save those urls into this temporary string array.setState
is for updating the state.
Keys #
- Some keys like the
Open AI
key can't be exposed to public. Once it did, it will be automatically invalid. So, you need to keep it secret. In this manner, Fireflow keeps the keys in Firestore database.
Open AI Keys #
- Save the Open AI Keys at
/system_settings/keys {openAiApiKey: ... }
.
The structure of Fireflow #
The fireflow reuses the code of the flutterflow since fireflow depends on flutterflow. But fireflow is decoupled from flutterflow. This means you can use fireflow with flutter.
Files and folders #
-
lib/src/actions
This folder contains codes that works like functions but depending on Firebase or Material design. -
lib/src/functions
This folder contains codes that are independent from Firebase, nor Material design. -
lib/src/widgets
This folder contains widgets.
User #
users schema #
-
Add
userPublicDataDocumentReference
tousers
schema. This is the connection tousers_public_data
schema. -
Add
admin
boolean. If this is set to true, the user will see admin menu. To give the user admin permission, you need to add the uid of the user into the system_settings collection.
users_public_data schema #
-
Since
users
collection has private information like email and phone number, fireflow saves public information intousers_public_data
collection.- Even if the app adopts
App Check
, it needs more to secure the data. Since firestore always delivers the whole document to the client, it is vulnerable if you don't keep the private information in seperate document. The abusers can look at the data in the app or browser transfered over the network.
- Even if the app adopts
-
Create the
users_public_data
schema in Flutterflow like below.
uid
is the the uid of the user.userDocumentReference
is the document reference of the user.displayName
is the display name of the user.photoUrl
is the primary profile photo url of the user.registeredAt
is the time that this document was created.updatedAt
is the time that this document was updated.gender
can be one ofM
orF
. M as Male or F as Femalebirthday
is the birthday of the userfollowers
is the list of user document references who follow me(the login user). Meaning, the login user can add other user reference into thefollowers
field in his document. Others don't have permission to update thefollowers
field in other user's document.hasPhoto
is set totrue
if the user has the primary profile photo. Or false.isProfileComplete
is set totrue
if the user filled in the necessary fields in his profile. Or false.coverPhotoUrl
is the url of the cover photo of the user.recentPosts
is the list of the last recent 50 document references that the user posts. Note, create /posts collections andrecentPosts
Data Type first to add this field.lastPostCreatedAt
is the time that the user created the last post.isPremiumUser
is set totrue
if the user is paid for premium service.
Register and sign-in #
-
As long as the user signs in with Firebase Auth
sign-in logic
applies the same. -
When a user signs in, Fireflow will create
/users_public_data/<uid>
document if it does not exists./settings/<uid>
document if it does not exsits.
-
When a user signs in for the first time, fireflow will send a welcome chat message to user.
How to get users_public_data document #
- When you need to get the public data document of a user, filter the
userDocumentReference
in theusers_public_data
schema with theuserPublicDataDocumentReference
ofAuthenticated User
.
Note, that the userPublicDataDocumentReference
in users
collection is set on the very first time the app runs by AppService
. So, it may be a good idea to not use it on the first screen of the app. You may use it on the second page and after.
Profile photo upload #
-
Uploading the profile photo of the user is much complicated than you may think.
- If a user cancels on the following(immediate) upload after the user has just uploaded a profile photo, the app maintains the same URL on the widget state. So, it should simply ignore when the user canceled the upload.
- The existing profile photo should be deleted (or continue to work) even if the actual file does not exist. There might be some cases where the photo fields have urls but the photos are not actually exists and this would cause a problem.
-
When the user uploads his profile photo, use the
Upload Media Action
in fireflow (not in flutterflow), then pass the uploaded URL toafterProfilePhotoUpload
. And leave all the other works to fireflow. -
For cover photo upload, update the photo using
Upload Media Action
in fireflow and url toafterCoverPhotoUpload
action.
Adding extra fields on users_public_data schema #
- You can simply add more fields on users_public_data schema.
User setting #
-
User settigns are kept in
/user_settings/<uid>
document.- It could be saved in
/users_public_data/<uid>
collection. But the problem is when the client lists/searches user information based on the settings, the firestore downloads the whole document whether is it big or small. And this leads the waste of network bandwidth, time consuming and lagging on the app. And even worse it costs more.
- It could be saved in
-
You just set the settings. That's it. It will work.
New Comment Notification #
- If a user enable this option, the user will get push notification on every new comments under his posts or comments.
- To enable it, simple set
notifyNewComments
to true. Example)/user_settings/<uid> {notifyNewComments: true}
. - To disable it, set it to false or delete the field.
Forum Category Subscription #
- There are two types of push notification subscriptions. One is the post subscription, the other is the comment subscription.
- If a user subscribes for the post, then he will get a push notification whenever there is a new post under the category.
- If a user subscribes for the comment, he will get a push notification on very new comments under the category.
- To enable the post subscription, add the category reference into
postSubscriptions
array. Example)/user_settings/<uid> {postSubscriptions: ['category/qnaCategoryReference']}
. - To enable the comment subscription, add the category reference into
commentSubscriptions
array. Example)/user_settings/<uid> {commentSubscriptions: ['category/qna']}
.
System setting #
Some API Keys like Open AI will be invalid once it is open to the public. So, it needs to be kept in the database (or somewhere else).
In Fireflow, those keys should be in /system_settings/keys { keyName: … }
Admin #
To set a user as an admin, You need to update the Firestore directly. You can do so within FF settings, or Firestore.
You need to add your UID (Or any other user’s UID that you want to set as an admin) at /system_settings/admins { <USER_UID>: true }
You need to add {admin: true} in the /users/{uid} {admin: true}
document. It's /users
collection. Not the /users_public_data
collection.
Push notification #
There are some differences from the notification logic of FF.
- The push notification sender's user reference is added to the parameter.
- The sender’s user document reference is always removed. Meaning, the sender will not receive the push notification he sent.
- Foreground push notification works.
Push notification data #
Push notification data of post and comment #
-
To make the flutter push notification work with the flutterflow, it passes the data in a certain compatible format.
- For post and comment,
- the
initialPageName
is fixed toPostView
- the parameter of the
PostView
is fixed topostDocumentReferece
and is set to the post reference.
- the
This means, the page name of the post view must be
PostView
and the parameter of thePostView
page must bepostDocumentReference
. Or when the user taps on the message, the app would not open the proper post view screen. - For post and comment,
Push notification data of chat #
- To make the fireflow push notification work with the flutterflow, it passes the data in a certain compatible format.
- the
intialPageName
is fixed toChatRoom
. So, the chat room must haveChatRoom
as its page name. - the
parameterData
haschatRoomId
and one ofchatRoomDocument
orotherUserPublicDataDocument
. So, theChatRoom
must have parameters ofChatRoomId
,chatRoomDocument
andotherUserPublicDataDocument
.chatRoomId
is a String, and have the chat room id.- the
chatRoomDocument
is set, if it's group chat. It's a string of chat room document path. - or the
otherUserPublicDataDocument
is set if it is one and one chat. It's a string of user public document path. Note that, the chat room requires thechatRoomDocument
or theotherUserPublicDataDocument
as a document. (Well, you may design differently.) And the fireflow will automatically convert the path of the document to a document when the page is opened when the user taps on the message. And the document itself cannot be delivered as push notification data.
- the
Foreground Push Notification and Routing #
It is not ideal to do routings inside fireflow.
You can handle the tap event on push notification by adding onTapMessage
callback to AppService.
MessageModel #
The MessageModel
will handle all kinds of push notification data including, but not limited to chat, post, profile.
Chat #
Chat Overview #
- There are two types of chat room.
- One is the one to one chat
- The other is the group chat.
Chat schema #
- Chat service needs two collections.
Chat Room collection #
userDocumentReferences
is the participants document reference of the chat room.lastMessage
is the last chat message.lastMessageSentAt
is the timestamp of last messagelastMessageSeenBy
is the list of user reference who have read the messagelastMessageSentBy
is the user reference of the last chat message sender.title
is the chat room title. The moderator can change it.moderatorUserDocumentReferences
is the user document references of the moderators. The first user who created the chat room becomes a moderator automatically. And he can add more moderators.unsubscribedUserDocumentReferences
is the document references of the users who disabled the notification of a new message for the chat room.isGroupChat
is set totrue
if it's a group chat. Otherwise, false.isOpenChat
is set totrue
if the chat room is open to anyone. When it is set to true, users can join the chat room.
Chat message collection #
userDocumentReference
is the document reference of the user who sent this message.chatRoomDocumentReference
is the reference of the chat room document.text
is the chat message.uploadUrl
is the url of the uploaded file. It can be an Image Path, Video Path, Audio Path or any upload url.uploadUrlType
is the type of the upload file. It can be one of the following;- Empty string if there is no upload.
- image
- video
- audio
- file ( if the upload file is not one of image, video, audio, then it is file type ).
protocol
is the protocol states the purpose(or action) of the message. For instance, when a user invites another user, then the protocol is set toinvite
. It could be one of;- invite
- remove
- leave When the protocol is set, there might be extra information.
protocolTargetUserDocumentReference
is the target user document reference who is being affected by the protocol. For instance, User A invites user B. then, the protocol is set toinvite
. And A's ref goes into userDocumentReference and B's ref goes into protocolTargetUserDocumentReference.sentAt
is the time that the message was sent.
Logic of chat #
Entering Chat Room to begin chat #
-
For A, to chat with B
- A enters the
ChatRoom
screen with the parameter of theuserPublicDataDocument
of B over - Then, in the
ChatRoom
Screen, - Display user’s photo and name on the app bar from
userPublicDataDocument
- Use the
ChatRoomMessages
custom widget with the reference ofuserPublicDataDocument
. - Note that, If a user document reference is given to fireflow ChatRoomMessages widget, it is considered as 1:1 chat.
- A enters the
-
To begin a group chat,
- A opens a group chat with
chatRoomDocument
. - Display chat room information from
chatRoomDocument
. - In the chat room, it uses the
ChatRoomMessages
custom widget with the reference ofchatRoomDocument
. - If a chat room document reference is given to fireflow ChatRoomMessages widget, it is considered as group chat.
- A opens a group chat with
How to list my chat rooms #
-
Get the chat rooms that have the logged in user’s document reference in the
userDocumentReferences
field. -
To get the list of chat rooms from the Firestore
- Add ListView (or Column)
- Add Backend Query
- Choose
chat_rooms
on Collection. - Query Type to
List of Documents
- Add a Filter
- Collection Field Name to
userDocumentReferences
- Relation to
Array Contains
- Value Source to
User Record Reference
- Collection Field Name to
- Add an ordering
- Collection Field Name to
lastMesageSentAt
- Order to
Decreasing
- Collection Field Name to
- Choose
-
To display the chat rooms
-
Add a
Column
as the child ofList View
. -
Add
Two Containers
to theColumn
. The first Container is for displaying the one to one chat and the second Container is for displaying the group chat. -
(One to One chat Container)
-
Add Backend Query
Query Collection
.- Query Type to
Single Document
. - Add a Filter.
- Collection Field Name to
userDocumentReference
. - Relation to
Equal To
. - Value Source to Custom Function named
chatOtherUserReference
and set its two parameters.- userDocumentReferences to
chat_rooms userDocumentReferences
. - myUserDocumentReference to
logged in user's reference
.
- userDocumentReferences to
-
Add conditional visibility as the Num List Items of
monderatorUserDocumentReferences
is equal to 0.
- Inside the
Container
addRow
- Inside the
Row
addContainer
- Inside the
Container
addRow
again
Inside the
Row
you can now add a widget to display theuser's photo
and text widgets to display theuser's name
,last message
andthe time
it was sent-
To display the user's photo:
- Add
Image Widget
orCustom Widget
- Set its path to
if else condition
(we need to check first if the user's photo is set or not)
- (if condition) check if the user's photo url is set, if it is, then set it as the path of the image widget
- (else condition) another if else condition to check if the user's gender is
male or female
to correctly show the placeholder image based on the user's gender- (if condition) check if the user is female, if it is, then set the path of the image widget to the female placeholder image url stored in local state
- (else condition) if the user is not female, set the path of the image widget to the male placeholder image url stored in local state
- Add
-
To display the user's name and the last message sent:
- Add
Column
- Inside the
Column
add two text widgets
- (top text widget) set its value to user's display name
- (bottom text widget) set its value to chat_rooms last message
- Add
-
To display the chat_rooms last message timestamp
- Add
Column
- Inside the
Column
add text widget - Set text widget's value to chat_rooms
lastMessageSentAt
timestamp with a format ofM/d h:mm a
- Add conditional visibility to check if the lastMessageSent is set
- Add
-
-
(group chat container)
- Add conditional visibility as the
Num List Items
ofmonderatorUserDocumentReferences
is greater than 0.
-
Inside the
Container
addRow
-
Inside the
Row
addContainer
-
Inside the
Container
addRow
again -
Inside the
Row
you can now add a widget to display the users' photos and text widgets to display group chat's last message and the time it was sent
-
To display the group chat's two users' photos:
- Add
Stack
to theRow
- Inside the
Stack
add two image widget or custom widget to display the group chat's two users' photos (the first photo will display the last message sender photo and the second photo will display the last person who entered the chat room)
-
To display the last message sender photo:
- Add
Backend Query
Query Collection
- Collection Field to
users_public_data
- Query Type to
Single Document
- Add a filter
- Collection Field Name to
userDocumentReference
- Relation to
Equal To
- Vaue Source to
lastMessageSentBy
- Collection Field Name to
- Add conditional visibility by checking if the
lastMessageSentBy
field is set.
- Add
-
To display the last person photo who entered the chat room:
- Add
Backend Query
Query Collection
Collection Field
to users_public_dataQuery Type
toSingle Document
- Add a
Filter
Collection Field Name
touserDocumentReference
Relation
toEqual To
Vaue Source
to custom function nameduserDocumentReferenceOfChatRoomLastEnter
and set its parameter:chatRoom
equal tochat_rooms Document
- Add
Note if the chat room don't have any user yet or it has only one user yet, then the photo of the creator of the chatroom will be displayed. Furthermore, since the first image widget will display the photo of the last message sender, if the last message sender is the same with the last person who entered the chat room, the photo of the predecessor of the last person who entered the chat room will be displayed to avoid displaying the same image on the two image widgets.
-
To display the number of users in the group chat room:
- Add
Container
- Inside the
Container
addText widget
- Set the
text widget's value
to the number ofuserDocumentReferences
inside the chat_rooms document
- Add
-
To display the group chat's title and the last message sent:
- Add
Column
- Inside the
Column
add two text widgets
- (top text widget) set its value to chat_rooms title
- (bottom text widget) set its value to chat_rooms last message
- Add
-
To display the chat_rooms last message timestamp:
- Add
Column
to theRow
- Inside the
Column
add text widget - Set text widget's value to chat_rooms
lastMessageSentAt
timestamp with a format of M/d h:mm a
- Add conditional visibility to check if the
lastMessageSent
is set
- Add
- Add
- Add conditional visibility as the
-
How to display menu when the chat message has tapped. #
- Create a component that will accept
chatRoomMessageDocument
as parameter. - Inside the component, put some widgets that will display the menu actions such as copy, edit, delete, open, etc.
- Inside the chat room, when the message has been tapped, open the component created above as a bottom sheet and pass the
chatRoomMessageDocument
.
How to leave a group chat room. #
- Close the dialog or drawer (if the button to leave the chat room is in a dialog or drawer)
- Call the leave method of the ChatService and pass the chat room's document reference
- Navigate to chat page with the replace route option enabled
How to display an uploaded file. #
- Call the FireFlow DisplayMedia widget
- Pass the required parameters such as width, height and url
How to not invite the same user. #
- When the user document reference is already in the chat room userDocumentReferences
How to display the protocol message. #
- When someone invited.
- When someone removed.
- When someone leave.
How to remove a user #
How to receive and display the push notifications while the app is foreground. #
How to display the number of chat rooms with new messages. #
-
Use
ChatNoOfRoomsWithNewMessage
widget. -
It is counted by the number of rooms, not by the number of messages.
-
It is done in steps,
- Listen for the changes of my chat rooms,
- Count the number of rooms that don’t have my user document reference in
lastMessageSeenBy
field.
How to query to the Open AI - GPT. #
- If you don't want to implement GPT query, simply don't add the Open AI key and don't put options for GPT query.
How to change chat room title #
How to send chat message #
When a user inputs and sends a message, simply pass the input over the onChatMessageSubmit
.
How to create a group chat #
Create chat_rooms
document with fields and values of
moderatorUserDocumentReference as the creator’s reference
title as the title of the chat room
userDocumentReferences with the create’s reference.
lastMessageSentAt with Current Time (Not Firestore server timestamp)
Save the created document to createdChatRoom
as action output
And navigate ChatRoom screen passing the createdChatRoom
as chatRoomDocument parameter.
Chat Design #
ChatRoomProtocolMessage #
Forum #
Forum Schema #
recentPosts #
The recent 50 posts of each users wil be saved in recentPosts
.
- Create the
recentPosts
Date Types like below.
Category #
- Admin can create, update or delete the categories.
- Managing the categories is just as simple as creating, updating and deleting documents.
- To create a category, add a document under
/categories
folder withcategory
andtitle
fields. - To update a category, just update it.
- To delete a category, just delete it.
- To create a category, add a document under
Category Logic #
- Fireflow creates its category document with the document id as the category itself. For instance, if the category is
qna
, the document path will be/categories/qna
. The is because- it's easy to specify the category directly into the UI builder. For instance, you want to display the QnA forum, then you can pass
qna
as the category parameter. If you don't use the category as its document id, then the logic would get complicated to get the document id ofqna
. - it's easy to design the firestore security rules.
- it's easy to specify the category directly into the UI builder. For instance, you want to display the QnA forum, then you can pass
Post #
Post Create #
createdAt
must be set toFirestore.serverTimestamp
when the post is created by Flutterflow.updatedAt
is optional. And it is set by the fireflow.- call
PostService.instance.afterCreate
after creating a post.
Post Update #
- call
PostService.instance.afterUpdate
after upating a post.
Post Delete #
- call
PostService.instance.afterDelete
after delete a post.
Comment #
Comment Create #
- call
CommentService.instance.afterCreate
after creating a comment.
Comment Update #
- call
CommentService.instance.afterUpdate
after updating a comment.
Comment Delete #
- call
CommentService.instance.afterDelete
after deleting a comment.
Logic of post creation #
-
When the user fill the form and submit, create a post document with
- category (required)
- userDocumentReference (optional, but recommended)
- createdAt (optional, but recommend)
- title (optional)
- content (optional)
- files (optional)
-
After create, you need to call
PostService.instance.afterCreate()
. This will- fill up the remaining fields
- increment post counters on multiple places
- send push notifications
- backup data into supabase (optiona)
- do other tasks.
Updating post #
updatedAt
is optional. And it is set by the fireflow.
Comment creation #
- The
createdAt
field must be set to Firestore.serverTimestamp by flutterflow.updatedAt
is optional. - The
order
field must be set by Flutterflow. It's not an ideal for the fireflow to update theorder
field since fireflow is a bit slow. And the flutterflow needs it immediately after it creates a comment to display the comments in nested position.
Files #
Overview of file management #
-
If you(as an admin of your app) could see what files are uploaded, Iit would be helpful to manage.
-
It would be helplful if you can
- list images and videos to see if there are any malicious photos, videos.
- list by size, file type, users.
-
It is recommended to update the stroage files list on desktop(or laptop) computer since it consumes more resouces.
Logic of File management #
StorageService.instance.updateStorageFiles()
will get all the files and store them into/storage_files
.- See Storage - List all files and Firestore - Batch Write.
- Since it may consume some resources, it is a good idea to display a confirm dialog to update the list when the admin enters the page.
- That's it. You can customize from here for your projects. See the
Customizing File Managemnt
.
Customizing File Management #
- Once you update(sync) the storage files into
/storage_files
, you have all the list of uploaded files with the fields ofurl, uid, name, full path, size, contentType, type, createdAt
.type
is coming from thecontentType
.- It can be
image
,video
,audio
,text
, etc. - If the
contentType
isaplication/...
, then it will take the type of the file likezip
,pdf
, etc.
- It can be
- You can search the
url
in firestore to know which document that it is attached to.
Supabase #
-
We support the supabase for the text search and the complicated conditional filterings.
- User profile, post, are comment are automatically saved into supabase if the option is enabled.
- Only the public data (non-sensitive private information of the user) should be saved in the supabase.
-
See the offical document for understanding the Supabase.
-
To enable the Supabase in the fireflow,
- Create tabls
users_public_data
,posts
,comments
, andposts_and_comments
in Supabase. - set the
supabase
options like below.AppService.instance.init(supabase: SupabaseOptions(...))
.- See the API reference for details.
- Create tabls
Supabase Table #
users_public_data #
posts #
Widgets #
Custom Popup widget. #
FF provides the bottom shee widget. But it is way different from the popup menu.
So, I made a widget named CustomPopup
that does something like the popup menu in the following screenshot.
Ex) Chat room screenshot
In the screenshot, I display the members of the chat room. Yes, it is a real popup menu and all the designs are coming from Components. You can add custom design and actions as you want.
How to implement the custom ppup #
-
For your information, When you create a Component, you can use that Component in a Custom widget. You need to check
Exclude from Compile
in this case. -
The child widget is the Component that displays as a trigger. The child component in the screenshot above is the widget that has two photos. In the component, the first user is the user who sent the last message. The second user is the user who last entered the chat room.
-
When a user taps on the Component, a popup menu is shown. And the popup menu is the ChatGroupUsers Component.
-
You can make your own child Component and the popup Component with your own design and actions. Just the way you develop your Component.
- And passed them over the CustomPopup widget.
-
Don't put the size of the width in the popup component. Or put it as
inf
. The width of the popup component meant to be automatically sized by theCustomPopup
widget. See the popup component width size issue. -
Options
- dx is the x position where the popup would appear.
- dy is the y position where the popup would appear.
import 'package:app/components/icon_component_widget.dart';
import 'package:app/components/popup_component_widget.dart';
import 'package:fireflow/fireflow.dart';
class PopupExample extends StatefulWidget {
const PopupExample({
Key? key,
this.width,
this.height,
}) : super(key: key);
final double? width;
final double? height;
@override
_PopupExampleSate createState() => _PopupExampleSate();
}
class _PopupExampleSate extends State<PopupExample> {
@override
Widget build(BuildContext context) {
return CustomPopup(
dx: 32,
dy: 38,
child: IconComponentWidget(),
popup: PopupComponentWidget(),
);
}
}
- It can go much complicated customization like below.
- The custom widget
DisplayChatUsers
below takes a parameter ofchatRoom
and it passes over the child widget and popup widget. Then, the child and popup widget may display different information.
- The custom widget
import '../../components/chat_group_user_icons_widget.dart';
import '../../components/chat_group_users_widget.dart';
import 'package:fireflow/fireflow.dart';
class DisplayChatUsers extends StatefulWidget {
const DisplayChatUsers({
Key? key,
this.width,
this.height,
required this.chatRoom,
}) : super(key: key);
final double? width;
final double? height;
final ChatRoomsRecord chatRoom;
@override
_DisplayChatUsersState createState() => _DisplayChatUsersState();
}
class _DisplayChatUsersState extends State<DisplayChatUsers> {
@override
Widget build(BuildContext context) {
return CustomPopup(
dx: 32,
dy: 38,
child: ChatGroupUserIconsWidget(
chatRoom: widget.chatRoom,
width: 80,
iconSize: 42,
),
popup: ChatGroupUsersWidget(
chatRoom: widget.chatRoom,
),
);
}
}
Custom poup step by step example #
Create a child Component
The child component is the widget that will trigger a popup menu to be appeared when a user presses on.
Example)
Just create an icon, or a text or any. You can do whatever design you like, but don’t put a widget that has tap event handler like a button.
Create a popup Component
Create a component that will appear as a popup menu. You can do whatever design you want and you can add whatever actions you like. And yes, it works just as you expect.
Custom widget for Custom Popup
- Create a custom widget to make the child Component and the popup Component work together
The difficult part may be creating the custom widget to make the two widgets work together.
I named the custom widget as ChatRoomMenu
. So, the following code snippet contains ChatRoomMenu
as its class name.
The see import statement. The patterns of the import path are
Add ../../components/
in front.
Then, add the kebab case of the Component.
Lastly, add _widget.dart
.
You will need to import package:fireflow.fireflow.dart for fireflow.
And in the body of the state class, use CustomPopup with child and popup parameters with its respective Components.
And finally, on the Widget Settings.
I checked Exclude from compilation
. This is needed when you refer to codes that are generated by FlutterFlow itself like accessing Components.
And I added fireflow
as its dependency. You may leave the version empty. Note that, when you change the version of fireflow in one place, the version of other places will follow.
Add the custom widget in your design
Now, the easiest part. Just add the custom widget where you want to add. For the example of the code above, the Custom widget is ChatRoomMenu. And I added at the top-right corner.
DisplayMedia widget #
This widget accepts a String of URL together with width and height.
The widget and height is used to size video.
This widget displays any kind of url like photo, video, audio, txt, pdf, etc.
Below is an example of displaying media by giving a photo url.
To make the border round like above,
Disable Enforce Width and Height
And wrap it with a container, put border property, and enable Clip Content
.
The DisplayMedia widget of Fireflow displays files like below.
It displays the file of the given url but does not react on tap. So, it is up to you how you want to design your app.
SafeArea widget #
You can Enable/Disable the SafeArea in FF. But you cannot give SafeArea on top only or bottom only. And you cannot optionally add a space to make the contents(widgets) appear safely from the notches.
For instance, you want to design your app with an image that displays as a background of the full screen. In this case you have to disable the SafeArea. But you need it enabled for some devices that have notches.
In the example below;
Some devices like the one on the left side have no notches. That’s fine without SafeArea. But some devices like the one on the right have notches at the top and at the bottom.
Yes, of course, you may twist the widgets to make the full screen with a background image like below. But that has limitations and the widget tree goes crazy.
So?
Here comes with the two widgets. SafeAreaTop and SafeAreaBottom.
Here is how to create SafeAreaTop and SafeAreaBottom widgets using Fireflow.
How to layout the SafeAreaTop and SafeAreaBottom widgets.
Be sure that you disable the Enforce Width and Height
option.
Actions #
The snackbar in FF is okay. But I want to have my own design of snackbars. So, here are the two. It's relatively easy to design the snackbar.
snackBarSuccess #
Add snackBarSuccess Custom Action like below.
snackBarWarning #
Add snackBarWarning Custom Action like below.
Functions #
Country Code #
- You can display a list of favorite countries on top with divider.
- For favorites, you can add dial_code or country name in the list. And the country name in favotes is case sensitive.
Unit Testing #
The current version of fireflow has no backend. And most of the difficult logics goes under the scene. We have some tests and wil have more in the future.
Developer coding guide #
If you want to update/improve the fireflow or if you want to work on your project other with fireflow, then follow the steps below.
- Fork fireflow.
- Clone fireflow from the fork.
- Create your own branch.
- Clone your project under
<fireflow>/apps
folder. - Change the path of fireflow package to
path: ../..
in the pubspec.yaml of your project. - One you have updated fireflow, create PR.
Sponsors #
FlutterFlow Korean Community
Known Issues #
Push notification and back navigation #
There is an issue regarding the push notification. This bug produces an error on back navigation when the app is opened by tapping on the push message.
[cloud_firestore/permission_denied] The caller does not have permission to execute the specified operation. #
Most of the time, it really causes problems. But in a few cases, it is designed to produce permission errors while it is working fine.
For instance, in the ChatRoomMessageList
widget of fireflow,
The chat room for 1:1 chat will be created in initState
asynchronously while the app queries to read the messages in the ListView widget.
The app will first read the chat messages before the chat room exists. But to read chat messages, the chat room must exist. This is why there is a permission error. The permission error may appear in the console, but still it works fine. This permission error may not appear always.
[cloud_firestore/permission_denied] happens often when the app is listening to some documents and suddenly user login status changes. For instance, the app is listening to a chat room and the user suddenly leaves the chat room. And it would be best if the app handles all the [cloud_firestore/permission_denied] exceptions nicely, but in some cases (or in many cases) it is just okay with the permission exceptions.