matecitodb_flutter 0.0.5
matecitodb_flutter: ^0.0.5 copied to clipboard
SDK oficial de Matecito para Flutter (BaaS de alto rendimiento).
example/main.dart
import 'package:flutter/material.dart';
import 'package:matecitodb_flutter/matecitodb_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final db = MatecitoDB.createClient('https://miapp.matecito.dev');
await db.auth.initialize();
runApp(
MatecitoDB_Provider(
db: db,
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MatecitoDB Example',
theme: ThemeData(
primaryColor: const Color(0xFF3ECF8E),
useMaterial3: true,
),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final db = MatecitoDB_Provider.of(context);
if (!db.auth.isLoggedIn) {
return const LoginPage();
}
return Scaffold(
appBar: AppBar(
title: const Text('🧉 Matecito Posts'),
actions: [
IconButton(
icon: const Icon(Icons.logout),
onPressed: () async {
await db.auth.signOut();
(context as Element).markNeedsBuild();
},
)
],
),
body: StreamBuilder<RealtimeEvent>(
stream: db.from('posts').subscribe(),
builder: (context, snapshot) {
return FutureBuilder<MatecitoDB_ListResponse<Map<String, dynamic>>>(
future: db.from('posts').orderBy('created', ascending: false).get(),
builder: (context, postsSnapshot) {
if (postsSnapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
final posts = postsSnapshot.data?.data ?? [];
return ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
leading: post['imagen'] != null
? Image.network(db.storage.getThumb(
collection: 'posts',
recordId: post['id'],
filename: post['imagen'],
size: '100x100'))
: const Icon(Icons.article),
title: Text(post['titulo'] ?? 'Sin título'),
subtitle: Text(post['created'].toString()),
);
},
);
},
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => _showAddPostDialog(context),
child: const Icon(Icons.add),
),
);
}
void _showAddPostDialog(BuildContext context) {
final TextEditingController controller = TextEditingController();
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('Nuevo Post'),
content: TextField(controller: controller),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: const Text('Cancelar'),
),
ElevatedButton(
onPressed: () async {
final db = MatecitoDB_Provider.of(context);
await db.from('posts').insert({
'titulo': controller.text,
'activo': true,
});
Navigator.pop(ctx);
},
child: const Text('Publicar'),
)
],
),
);
}
}
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _email = TextEditingController();
final _pass = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('🧉', style: TextStyle(fontSize: 80)),
TextField(
controller: _email,
decoration: const InputDecoration(labelText: 'Email')),
TextField(
controller: _pass,
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
final db = MatecitoDB_Provider.of(context);
final res = await db.auth
.signIn(email: _email.text, password: _pass.text);
if (res.error != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(res.error!.message)),
);
} else {
setState(() {});
}
},
child: const Text('Entrar'),
)
],
),
),
);
}
}