A lightweight & effective Todo app made with Flutter

Overview


Blue Diary
Blue Diary

A lightweight & effective Todo app made with Flutter. Supports English and Korean.

ScreenshotsDownloadUsageArchitectureFeedbackLicense

Screenshots

Download

Get it on Google Play Download on the App Store

Usage

You can build and run this app by yourself. You'll need Git, Flutter, NPM and Android Studio installed.

Building this app for yourself needs 2 steps:

  1. Basic Setup
  2. Firebase Integration

I'll describe these steps in detail.

1. Basic Setup

First of all, clone this project by running command:

$ git clone https://github.com/giantsol/Blue-Diary.git

Open cloned directory with Android Studio and it'll notify you to run Packages get to install dependencies. Do that.

Next is to integrate Firebase.

2. Firebase Integration

This app uses various features of Firebase, including Firebase Authentication, Cloud Firestore and more. If Firebase is not set up, you can still build the app, but you won't be able to see the first screen.

(1) Create Firebase project

First, you have to create a new project in Firebase Console. Click Create a project as below:

Set a project name as below(can be anything else):

Go into your newly created project. We'll add Android app first. Click Android button:

In package name, put com.giantsol.blue_diary.debug since this is the applicationId for debug builds. You can put anything for App nickname(e.g. Blue Diary Debug).

Click next, and click Download google-service.json and save it right below your-cloned-dir/android/app directory. You should skip step 3 and 4:

Run flutter packages get in your cloned directory to install dependencies.
Next we'll add iOS app. Click iOS button:

In bundle ID, put com.giantsol.blue-diary.debug(note that iOS bundle id and Android applicationId is subtly different!). You can put anything for App nickname(e.g. Blue Diary Debug).

Click next, and click Download GoogleService-Info.plist and save it anywhere for now. You should skip step 3, 4 and 5:

Open your cloned project using Xcode. If you're using Android Studio, you can open ios module in Xcode by right clicking your project directory from Project panel - Flutter - Open iOS module in Xcode:

In Xcode, drag and drop GoogleService-Info.plist file you downloaded into Runner/Runner directory. Note that you must use Xcode in this procedure, since it needs to update indexes of file:

Done! Run flutter packages get in your cloned directory again.

(2) Firebase Authentication Integration

We use google sign-in. First, you need to turn on google sign-in function in your Firebase project by navigating to Authentication - Sign-in method tab and enabling Google by toggling switch button. Click Save:

Nothing else to do for Android, but if you're planning to build on iOS, you need one more step. Go to your Info.plist file located in your-cloned-dir/ios/Runner/Info.plist. It should have below code:


CFBundleURLTypes

	
		CFBundleTypeRole
		Editor
		CFBundleURLSchemes
		
			
			
			$(GOOGLE_SERVICE_INFO_REVERSED_CLIENT_ID)
		
	


Change $(GOOGLE_SERVICE_INFO_REVERSED_CLIENT_ID) with your own GoogleService-Info.plist's REVERSED_CLIENT_ID value.

(3) Firebase Functions Integration

You need to deploy firebase functions to your Firebase project. First, run npm install -g firebase-tools from anywhere in cmd. If you don't have npm installed, follow this link.

After firebase-tools is installed, run firebase login anywhere in your cmd to authenticate firebase tool.

Then run firebase init functions in your cloned directory. It would ask you for options. Select Use an existing project -> JavaScript -> No -> Yes as below:

New file should have been created as your-cloned-dir/functions/index.js. Copy and paste below code to index.js:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();

exports.getTodayInMillis = functions.https.onCall((data, context) => {
    return Date.now();
});

exports.setMyRankingUserInfo = functions.https.onCall(async (data, context) => {
    const currentInMillis = Date.now();
    const uid = data.uid;
    const modifiedData = data;
    modifiedData.last_updated_millis = currentInMillis;
    await db.collection('ranking_user_info').doc(uid).set(modifiedData, { merge: true });
});

Finally, run firebase deploy --only functions from your cloned directory. This command uploads these functions to your firebase project server.

(4) Cloud Firestore Integration

Our last step is to create the database we need in your Firebase project. In your Firebase console, click Database - Create Database - Start in test mode:

When database is created, we need to create an index for this database. In Database page, click Indexes - Composite - Add index and fill in fields as below:

Click Create index and wait for the process to finish.


All Done! Build and run app. If you still can't see the first screen although internet is connected, you should first check your Firebase account's quota. Perhaps your Spark plan's quota is all used. If there's other problems, please leave Feedback!

Architecture

This app is based on BLoC pattern, together with my own architectural practices.

Inside the lib folder, there are three main folders:

  1. data: This folder contains Dart files that actually update/fetch data from Preferences, Databases, or Network (although we don't use Network here). Most of the files here are implementations of Repository interface declared in domain/repository folder.

  2. domain: This folder contains the so called 'Business Logic' of this app. It is further divided into three main folders:

    • entity: contains pure data classes such as ToDo and Category.
    • repository: contains interfaces defining functions that update/fetch data. Actual implementations are located in data folder.
    • usecase: contains per-screen business logics that utilizes several repositories to achieve each screen's needs. This is the layer that presentation has access to to utilize app data. For instance, WeekScreen uses (well, actually WeekBloc uses) WeekUsecases to interact with data underneath without directly touching repositories.
  3. presentation: This folder contains Screens, Blocs and States that are used to display UI. It is divided into further directories that correspond to each screens in the app.

    • **Screen: where Widget's build method is called to build the actual UI shown to the user. UI is determined by values inside State, and any interactions users make (e.g. clicking a button) are delegated to corresponding Blocs.
    • **Bloc: what this basically does is "User does something (e.g. click a button)" -> "Set/Get data using corresponding usecase and update the values inside State obect" -> "Notify Screen that State has changed and you have to rebuild".
    • **State: holds all the information Screen needs to draw UI. For instance, currentDate, todos, and isLocked kinds of things.

Above three directories are divided to as closely follow Uncle Bob's Clean Architecture pattern. Any tackles, highly welcomed.

Besides these directories are flat Dart files inside lib folder:

  1. AppColors.dart: just simple color constants.
  2. Delegators.dart: I used delegators when children needed to call parent's methods. However, as I've become more familiar with Flutter now, I guess ancestorStateOfType can just do that job... researching on it!
  3. Dependencies.dart: contains singleton objects such as repositories and usecases. Basically, it enables a very simple injection pattern like dependencies.weekUsecases as in WeekBloc.dart.
  4. Localization.dart: where localization texts are declared.
  5. Main.dart: the main entry point of this app.
  6. Utils.dart: Utils (duh).

If you have any questions, or have any suggestions to make this app better, do contact me as shown in Feedback. Thanks!

Feedback

Feel free to leave any feedback about this app, code, or whatever.

Leave Issues, Pull requests or email me at [email protected].

License

MIT

You might also like...

Fa-chapter-2 - Lightweight Recipe App Built With Flutter

Recipe App Our app will offer a hard-coded list of recipes and let us use a Slid

Jan 2, 2022

Bmprogresshud - A lightweight progress HUD for Flutter app

Bmprogresshud - A lightweight progress HUD for Flutter app

bmprogresshud A lightweight progress HUD for your Flutter app, Inspired by SVProgressHUD. Showcase Example local HUD place ProgressHud to you containe

Nov 19, 2021

A clean and lightweight progress HUD for your iOS and tvOS app.

SVProgressHUD SVProgressHUD is a clean and easy-to-use HUD meant to display the progress of an ongoing task on iOS and tvOS. Demo Try SVProgressHUD on

Jan 3, 2023

A lightweight and customizable http client that allows you to create offline-first dart app easily.

Enjoyable & customizable offline-first REST API client Unruffled is lightweight and customizable http client that allows you to create offline-first e

May 20, 2022

A lightweight flutter package to linkify texts containing urls, emails and hashtags

A lightweight flutter package to linkify texts containing urls, emails and hashtags

linkfy_text A lightweight flutter package to linkify texts containing urls, emails and hashtags. Usage To use this package, add linkfy_text as a depen

Nov 23, 2022

A lightweight HTML-Richtext editor for Flutter

A lightweight HTML-Richtext editor for Flutter

Flutter HTML Editor Flutter HTML Editor is a simple HTML-based Richtext editor, which is able to edit and parse a selected set of HTML tags into a Flu

Oct 19, 2022

Easy to use, reliable and lightweight gesture detector for Flutter apps, exposing simple API for basic gestures

Simple Gesture Detector Easy to use, reliable and lightweight gesture detector for Flutter apps. Exposes simple API to react to basic gestures. Featur

Nov 4, 2022

Zerker is a lightweight and powerful flutter graphic animation library

Zerker is a lightweight and powerful flutter graphic animation library

What is Zerker Zerker is a flexible and lightweight flutter canvas graphic animation library. With Zerker, you can create a lot of seemingly cumbersom

Dec 31, 2022

Lightweight i18n solution for Flutter

fast_i18n Lightweight i18n solution. Use JSON, YAML or CSV files to create typesafe translations. About this library 🚀 Minimal setup, create JSON fil

Dec 26, 2022
Comments
  • run error

    run error

    Running "flutter pub get" in Blue-Diary...                          0.7s
    
    Launching lib/main.dart on iPhone Xʀ in debug mode...
    
    Compiler message:
    lib/presentation/settings/SettingsBloc.dart:9:8: Error: Error when reading 'lib/Secrets.dart': No such file or
    directory
    import 'package:todo_app/Secrets.dart';
           ^
    lib/presentation/settings/SettingsBloc.dart:129:44: Error: The getter 'SENDGRID_AUTHORIZATION' isn't defined for the
    class 'SettingsBloc'.
     - 'SettingsBloc' is from 'package:todo_app/presentation/settings/SettingsBloc.dart'
     ('lib/presentation/settings/SettingsBloc.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named
    'SENDGRID_AUTHORIZATION'.
              HttpHeaders.authorizationHeader: SENDGRID_AUTHORIZATION,
                                               ^^^^^^^^^^^^^^^^^^^^^^
    Exception: Errors during snapshot creation: null
    #0      KernelSnapshot.build (package:flutter_tools/src/build_system/targets/dart.dart:230:7)
    <asynchronous suspension>
    #1      _BuildInstance._invokeInternal (package:flutter_tools/src/build_system/build_system.dart:526:25)
    <asynchronous suspension>
    #2      _BuildInstance.invokeTarget.<anonymous closure>
    (package:flutter_tools/src/build_system/build_system.dart:481:35)
    #3      new Future.sync (dart:async/future.dart:222:31)
    #4      AsyncMemoizer.runOnce (package:async/src/async_memoizer.dart:43:45)
    #5      _BuildInstance.invokeTarget (package:flutter_tools/src/build_system/build_system.dart:481:21)
    <asynchronous suspension>
    <asynchronous suspension>
    #6      BuildSystem.build (package:flutter_tools/src/build_system/build_system.dart:419:36)
    #7      _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    #8      BuildSystem.build (package:flutter_tools/src/build_system/build_system.dart:400:28)
    #9      buildWithAssemble (package:flutter_tools/src/bundle.dart:125:48)
    #10     _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    #11     buildWithAssemble (package:flutter_tools/src/bundle.dart:99:31)
    #12     BundleBuilder.build (package:flutter_tools/src/bundle.dart:75:11)
    #13     _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    #14     BundleBuilder.build (package:flutter_tools/src/bundle.dart:52:21)
    #15     IOSSimulator._sideloadUpdatedAssetsForInstalledApplicationBundle
    (package:flutter_tools/src/ios/simulators.dart:453:28)
    #16     IOSSimulator._setupUpdatedApplicationBundle (package:flutter_tools/src/ios/simulators.dart:420:11)
    #17     _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    #18     IOSSimulator._setupUpdatedApplicationBundle (package:flutter_tools/src/ios/simulators.dart:419:46)
    #19     IOSSimulator.startApp (package:flutter_tools/src/ios/simulators.dart:352:15)
    #20     _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    #21     IOSSimulator.startApp (package:flutter_tools/src/ios/simulators.dart:339:32)
    #22     FlutterDevice.runHot (package:flutter_tools/src/resident_runner.dart:393:54)
    #23     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:71:64)
    #24     _rootRunUnary (dart:async/zone.dart:1132:38)
    #25     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    #26     _FutureListener.handleValue (dart:async/future_impl.dart:137:18)
    #27     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45)
    #28     Future._propagateToListeners (dart:async/future_impl.dart:707:32)
    #29     Future._completeWithValue (dart:async/future_impl.dart:522:5)
    #30     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:30:15)
    #31     _completeOnAsyncReturn (d
    
    opened by mana-ai 2
  • Release 1.1.0

    Release 1.1.0

    • [x] Thoroughly debug app
    • [x] Update description and screenshots in PlayStore and full rollout!
    • [x] Update description and screenshots in this README.md
    • [x] Update description and screenshots in itsallwidgets.com
    • [x] Create 1.1.0 release tag
    opened by giantsol 2
  • add catch condition on timeout of cloud function

    add catch condition on timeout of cloud function

    The application can't be used without internet, this is a main issue as most of the information required to use the app is stored locally on the device, but if the date can't be fetched from the server all the information stored in the users phone can't be reached. To correct this I add a catch condition on the scenario where the server responds with a timeout

    opened by jccastiblancor 0
  • Readme is incomplete, Sign in not working

    Readme is incomplete, Sign in not working

    I tried following the instructions for compiling the app, but the sign in didn't seem to work. This is because a couple of steps are missing,

    1. Sign the firebase app like shown here https://stackoverflow.com/questions/39144629/how-to-add-sha-1-to-android-application/39145068.
    2. Re Download the google-services.json file and add it to the project
    opened by maescalante 0
Owner
Hansol Lee
:P
Hansol Lee
Todo app codelab - A simple UI for todo app to showcase Flutter features and core concepts

Codelab Todo App A simple todo app UI for to showcase Flutter and Dart core conc

Junior Medehou 3 May 12, 2022
🎨 An opinionated, effective and correct way to provide multiple themes to your app.

theming This is an opinionated and effective way to provide multi-theme choice for your app. theming depends on provider and shared_preference for sta

Chinyeaka Chinonso 3 Nov 28, 2022
A super effective dart library delivering performance & ensuring greater build speed.

A super effective Dart and Flutter library for delivering performante app ?? & ensuring greater build speed ?? . The package has some cook utilizes wh

Rexford Asamoah 2 Nov 22, 2021
Linter rules corresponding to the guidelines in Effective Dart

effective_dart This package is deprecated. Before it was deprecated, it was the way to provide analysis options corresponding to the guidelines in Eff

Honza Bittner 127 Dec 9, 2022
腾讯云 1 Feb 10, 2022
The XOR Encryption algorithm is a effective and easy to implement method of symmetric encryption.

Symmetric XOR cipher library About XOR cipher XOR Encryption is an encryption method used to encrypt data and is hard to crack by brute-force method,

Plague Fox 7 Apr 20, 2022
ToDo App made with flutter which stores your todos based on their categories. The data is stored in external application storage in your device in JSON file.

⭐ My ToDo ⭐ Built with ❤︎ by Akash Debnath This is my second project on Flutter. This app hepls you to keep record of your ToDos. You can create your

Akash Debnath 38 Dec 25, 2022
https://dribbble.com/shots/3812962-iPhone-X-Todo-Concept Made With Flutter

?? FlutterTodo ?? Install Note: Make sure your Flutter environment is setup. In the command terminal, run the following commands: $ git clone https://

Marc L. 552 Dec 27, 2022
A lightweight flutter plugin to check if your app is up-to-date on Google Play Store or Apple App Store

App Version Checker this package is used to check if your app has a new version on playstore or apple app store. or you can even check what is the lat

Iheb Briki 6 Dec 14, 2022
Bhagavad Gita app using flutter & Bhagavad-Gita-API is A lightweight Node.js based Bhagavad Gita API [An open source rest api on indian Vedic Scripture Shrimad Bhagavad Gita].

Gita Bhagavad Gita flutter app. Download App - Playstore Web Application About Bhagavad Gita app using flutter & Bhagavad-Gita-API is A lightweight No

Ravi Kovind 7 Apr 5, 2022