Flutter CTO Report 2024
Get insights about Flutter directly from CTOs, CIOs, Tech Leads, and Engineering Managers!

Implementing Live Whiteboard With Flutter and Firestore Database

Robert Odrowąż-Sypniewski
Mobile Flutter Developer and the assistant to Head of mobile development at LeanCode. In the project involved in key business areas - accounts squad, framework and overall architecture design.

Rating: 4.88 / 5 Based on 8 reviews

Aug 6th, 2020 • 5 min
Free product design tips
Join our Newsletter for Expert Flutter Tips & Product Design Insights from our seasoned team!
By submitting your email you agree to receive the content requested and to LeanCode's Privacy Policy.
or follow us

Whiteboard is an irreplaceable tool in many business processes. Live whiteboards have been created to allow for the same kind of collaborative process using whiteboards online. In this blog post, we explore a possible implementation of such a whiteboard using Flutter to create a mobile application and Firestore database as a backend.

Flutter is a framework for creating cross-platform applications for mobile devices (Android and iOS), desktop (Mac and PC), and web.

Firestore is a document database offered by Google as a part of the Firebase platform. Features that make it especially well suited for use cases such as live whiteboard are low latency synchronization and the ability for clients to subscribe to notifications about data changes.

This blog post will analyze the most important aspects of creating a simple whiteboard app. The app consists of two pages, the first StartPage for providing the id of the whiteboard the user intends to connect to. Second WhiteboardPage displays the selected whiteboard and allows for adding and removing lines.

Live whiteboard

Rendering

The widget responsible for rendering the lines to the screen is WhiteboardView. WhiteboardView consists of a CustomPaint widget with WhiteboardPainter. WhiteboardPainter in the paint method, iterates over all lines and draws lines joining consecutive points to the canvas.

Rendering

WhiteboardView is also responsible for detecting user inputs and exposing appropriate onGestureStart, onGestureUpdate, and onGestureEnd callbacks. Gestures are detected using a GestureDetector widget and mapped to Point models after being scaled relative to whiteboard width. Using coordinated relative to screen width resolves issues related to different screen dimensions across devices. WhiteboardView has also fixed the aspect ratio to 9/16 for the same reason.

Communication with Firestore

The app uses a very simple data structure in Firestore. Every whiteboard is saved in a single document consisting of a content id and a list of lines. Such a structure results from the Firestore pricing model, which is based mostly on a number of documents being read and written. Not separating the whiteboard into multiple documents has some drawbacks, the most significant of which in this case is the limit to 1 write per second to a document. 

Whiteboard, firestore communication

New lines are saved to the database when the drawing is finished to reduce the number of writes and Firestore costs. The new content id is also added to the list of written ids to allow for the comparison explained earlier.

Whiteboard content

Editing content

Adding a new line is pretty straightforward. A new line is created in the onGestureStart method and stored in the _currentLine field. Further points are added in the onGestureUpdate method. In onGestureEnd, a line is added to the WhiteboardContent model and saved in Firestore.

Deleting lines is a bit more complex. In each onGestureStart or onGestureUpdate invocations rectangle created by current and previous pointer positions is checked for intersection with rectangles created by each two consecutive line points (or with a rectangle of size equal to double the line width centered around the point in case of only one available). If any of the rectangles created by the line section intersect, the line is removed from WhiteboardContent, and changes are saved in the database.

Whiteboard, editing content

Optimizing Firestore

Firestore, by default created indexes for each array field in a document to allow for, “contains” querying. Large arrays lead to a huge number of indexes being created, which translates to higher database costs and slower write speeds. In our case “contains” query is completely useless, so it’s important to disable the creation of those indexes.

Optimizing Firestore

You can find the application source code on GitHub.

In this case, Firestore is a great use; however, there are also some drawbacks of Firestore usage you should be aware of.

Free product design tips
Join our Newsletter for Expert Flutter Tips & Product Design Insights from our seasoned team!
By submitting your email you agree to receive the content requested and to LeanCode's Privacy Policy.
or follow us
Rate this article
4.88 / 5 Based on 8 reviews

Read more

Lessons Learned After Making the First 10 Commercial Apps in Flutter

There is always exciting technology our team wants to try out. We challenged them and asked for proof on how Flutter can bring value to the client. We are sharing the insights after making the first 10 commercial apps within the last 24 months during which we’ve spent some 17.193,00 hours on Flutter projects.
Four mobile phones with small icons

Why Firestore, Part I: Reasons to Love It

Firestore and Firebase suite are great technologies. They allow developers to build some features in Flutter and other mobile frameworks really fast. However, Firestore has also many pain points that outweigh the pros in most of the more advanced cases. Is Firestore appropriate for you? Read on to find out why!
Image tile

Complex Animations in Flutter

Flutter ships with plenty of high-quality widgets, layouts, and themes that developers can use to speed up the whole creation process. A great example of custom widgets made in Flutter is the Placement Wheel developed for one of our clients. See how to do it.
Image tile