Create flutter apps quickly by utilizing commonly used tools.

The aim of this package is to make building apps quick and seamless, incorperating some frequently used widgets in app development.

Getting started

  1. add package
flutter pub add close_range_util
  1. Inside your main function when you call runApp, pass in an Entry object
runApp(Entry(
    title: "Testing 123",
    home: MyFirstPage(...), // Widget of inital page page
));

The point of this is to allow for global bindings such as themes to the whole project.

Setup

Some features require an initilization phase.
This can be done right inside of main before calling runApp For example:

void main() async {
  await CREnv.init();
  await CRSave.init();
  await CRDatabase.init(
    url: CREnv["SUPABASE_URL"]!,
    anonKey: CREnv["SUPABASE_ANON_KEY"]!,
  );
  Debug.setActive(false);
  runApp(...);
}

Features

Login
Signup
Documentation
App Bar
Calendar
Debug Page
Settings
Region
Profile Picture
Profile Banner

Systems

Enviroment
Save System
User
Database
Debug
Theme

Login


login login login

Signup


login

Docs


Docs is a way to easily integrate a documentation page into your flutter apps. This can help users of your app learn more about how it works.

docs

App Bar


appbar1 appbar2

Calendar


login login

Debug Page


login login

Settings


login login

Region


login

Profile Picture


login login

Profile Banner


login login

Enviroment


Enviroment or CREnv is a way to grab enviroment variables out of a file. This is a direct mirror of the Env package.

Initialize

Before calling runApp ensure you initilize the enviroment

This takes a parameter for the name of the enviroment file, but can be ommitted for the default file name of .env

void main() async {
    await CREnv.init();
    runApp(...);
}

Creating the file

By default the naem of the file is .env but can be changed as a parameter inside the init function.

The file consists of key value pairs such as:

DATABASE_PASSWORD = "..."
FIREBASE_SENDER_ID = "..."

Getting data

CREnv["env_name"];

Save System


The Save system or CRSave is a way to save data to and from the device. It's a wrapper around SharedPreferences

Initialize

Before calling runApp ensure you initilize the save system:

void main() async {
    await CRSave.init();
    runApp(...);
}

Save / Load

To save and load data to the device simply call save/load providing the variable key.

The load method takes a default value in case the value has yet to be saved into memory.

CRSave.save<int>("myValue", 123);
int v = CRSave.load<int>("myValue", 0);

Clearing data

You can either clear a single key, or clear all data:

await CRSave.clear("myValue");
await CRSave.clearAll();

Binding

Binding to the save system allows you to easily track variables that have changed.

CRSave.bind(
    key: "myValue",
    defaultValue: 0,
    builder: (val) => Text(val.toString())
);

User


The user system controls who is logged in currently to an account and is completly depends on the Database system.

Initalize

Before using the user system, you need to initalize supabase inside the main method

void main() async {
    await CRDatabase.init(
        url: CREnv["SUPABASE_URL"]!,
        anonKey: CREnv["SUPABASE_ANON_KEY"]!,
    );
    runApp(...);
}

Supabase Setup

inside supabase itself, you will need to Enable Phone Provider inside the authentication.

You will also need a table named users with at least the following columns:

  • user_id -> uuid
  • pfp -> text
  • first_name -> text
  • last_name -> text You can provide more columns as well and they will be retrivable directly from the user object

Logging in

To log into an account provide either the phonenumber or email (but not both):

CRUser? user =
    await CRUser.attemptLogin(phone: phone, password: pass);
if(user == null) {...} // invalid credentials

Once logged in you can retrieve any data from the provided user:

user["myColumn"];
user.getValue("myColumn");

When saving, you must provide a map of all values you want to change:

await user.setValue({
    "myColumn": 25
});

By default it will automatically save directly to supabase, but you can set the save parameter to false to only save locally.

Current User

When logging in you don't need to save the provided user, simply get it statically CRUser.current

Loading User

You can load a user and their details without actually logging in:

CRUser? user = await CRUser.load(uuid);

Reloading User

Sometimes you may need to refetch the data from a user and update the values:

await user.reload();
await CRUser.current!.reload();

Binding

You can bind widgets to the user in order to track changes made.

To do this simply call bind from the user in question:

CRUser.current!.bind(
    builder: (user) => Text(user.firstName)
);

Replication

When binding a widget (see above) you can choose to use replication, which will track changes to the database itself rather than tracking the local copy.

In supabase, edit the users database and enable replication.

Then set replication to true

CRUser.current!.bind(
    replication: true,
    builder: (user) => Text(user.firstName)
);

NOTE: This will turn off the default binding, so any bindings will only update if the database itself is modified.

Database


the database system lets you easily use supabase with little work.

Initialize

Before using the database, call the init function

void main() async {
    await CRDatabase.init(
        url: CREnv["SUPABASE_URL"]!,
        anonKey: CREnv["SUPABASE_ANON_KEY"]!,
    );
    runApp(...);
}

The CREnv is a nicer way to store the url and anon key from supabase

Timing

When calling most functions from the database, a fixed delay is added to test out lag within the calls.
This is only active when Debug is active.
You can access the delay manually as well by calling it

await CRDatabase.delay;

Supabase Raw

You can access any supabase function by simply grabbing the auth or client

CRDatabase.client...
CRDatabase.auth...
CRDatabase.getClient()...
CRDatabase.getAuth()...

using the get functions will also add the delay into the calls where getting the raw values will ommit the delay

Getting Data

The easist way to get data is with one of 2 ways:

  • CRDatabase.select(table, [columns])
  • CRDatabase.selectEq(table, column, value, [columns])
    Where [columns] is "*" by default (select all)

Setting Data

For setting data you can insert, update, or delete:

  • CRDatabase.insert(table, values)
  • CRDatabase.update(table, values)
  • CRDatabase.delete(table, column, value) For insert and update take in a map of string value pairs.
    Delete takes a column name and a value to compare to and will delete any entry where the value = column

Debug


Debug is simply a way to log messages and have them show in app.

Enabling

You can check if debug mode is on by using Debug.active You can disable debug mode with either setActive or setReleaseMode

Debug.active; // true by default
Debug.releaseMode; // true by default
Debug.setActive(false); // Turns debug off
Debug.setReleaseMode(false); // will also  make active false

Debug.toggleDebug();

Release Mode

Sometimes you may want to be able to disable or enable debug mode on the fly while testing.

Release mode is meant to be a way to fully disable debug mode, so if release mode is active, you can never turn debug mode on.

Database Delay

Inside Database any calls you make have an automatic delay of 3 seconds if debug mode is active.

This delay can be turned off or changed

Debug.setSqlDelay(false); // turns delay off
Debug.setSqlDelayTime(5000); // sets delay to 5 seconds

Debug Messages

You can also write debug messages that will show up in the Debug Page rather than the console.

Debug.log(message, [inner]);
Debug.warn(message, [inner]);
Debug.error(message, [inner]);

Debug.clearLog();

Theme


Themes is an easy way to change the color of the app.

Initialize

While there is no setup needed for themes directly, you will need to initialize the Save System first

void main() async {
    await CRSave.init();
    runApp(...);
}

Set Theme

To set a them simply call setTheme or setDark

CRTheme.setTheme(CRThemeType.sakura);
CRTheme.setDark(true);

This will automatically save the theme as well for the next time you open the app

Theme Settings

Within the Settings api there is also an option to create a atuo theme selector and dark mode selector:

CRSettings.colorTheme(context);
CRSettings.darkMode(context);