fireproof 0.0.2+9
fireproof: ^0.0.2+9 copied to clipboard
A builder used to create type safe bindings between models and Firestore
example/lib/main.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:example/models/root/root.dart';
import 'package:example/models/user/user.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
// I want to be able to create a traversable tree.
// The entire firebase structure should be known at
// compile time
//
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(App());
}
const kPa = 16.0;
final instance = FirebaseFirestore.instance;
final database = Database(instance);
final users = database.users;
class App extends StatelessWidget {
// Create the initialization Future outside of `build`:
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FutureBuilder(
future: _initialization,
builder: (context, snapshot) {
if (snapshot.hasError) {
return SomethingWentWrong();
}
if (snapshot.connectionState == ConnectionState.done) {
return Home();
}
return Loading();
},
),
);
}
}
class SomethingWentWrong extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text('Something went wrong')),
);
}
}
class Loading extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Test')),
body: StreamBuilder<List<User>>(
stream: users.snapshots().map((event) => event.docs),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Error has occured'));
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (!snapshot.hasData) {
return Center(child: Text('No data'));
}
final users = snapshot.data!;
return Column(
children: [
Expanded(
child: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
title: Text(user.data.name),
subtitle: Text(user.data.email),
);
},
),
),
Card(
margin: EdgeInsets.fromLTRB(kPa, 0.0, kPa, kPa),
elevation: 10.0,
child: Container(
padding: const EdgeInsets.fromLTRB(kPa, 0.0, kPa, kPa),
child: CreateUserForm(),
),
)
],
);
},
),
);
}
}
class CreateUserForm extends StatefulWidget {
@override
CreateUserFormState createState() => CreateUserFormState();
}
class CreateUserFormState extends State<CreateUserForm> {
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _nameController = TextEditingController();
@override
void dispose() {
_emailController.dispose();
_nameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Stack(
fit: StackFit.passthrough,
children: [
Column(
children: [
TextFormField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Name'),
validator: (value) => value == null || value.isEmpty
? 'Name cannot be empty'
: null,
),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'email'),
validator: (value) => value == null || value.isEmpty
? 'Email cannot be empty'
: null,
)
],
),
FractionalTranslation(
translation: Offset(0, -.5),
child: Align(
alignment: Alignment.topRight,
child: FloatingActionButton(
onPressed: () async {
final isValid = _formKey.currentState?.validate();
if (isValid ?? false) {
final user = UserBase(
name: _nameController.text,
email: _emailController.text,
);
_nameController.clear();
_emailController.clear();
await database.users.add(user);
}
},
child: Text('Done'),
),
),
),
],
),
);
}
}