taplatch 0.1.0
taplatch: ^0.1.0 copied to clipboard
A Flutter async button that prevents repeated taps, shows loading, handles errors, and supports a success cooldown.
import 'package:flutter/material.dart';
import 'package:taplatch/taplatch.dart';
void main() => runApp(const TapLatchExampleApp());
class TapLatchExampleApp extends StatelessWidget {
const TapLatchExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TapLatch Example',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF1F6B3A)),
useMaterial3: true,
),
home: const ExampleHomePage(),
);
}
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({super.key});
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
int _requestCount = 0;
void _message(String value) {
if (!mounted) return;
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(value)));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('TapLatch Demo')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Tap repeatedly: only one request runs at a time.'),
const SizedBox(height: 16),
TapLatchButton(
label: 'Book Now',
loadingLabel: 'Booking...',
icon: const Icon(Icons.calendar_month),
cooldown: const Duration(seconds: 2),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF1F6B3A),
foregroundColor: Colors.white,
minimumSize: const Size(220, 48),
),
onPressed: () async {
setState(() => _requestCount++);
await Future<void>.delayed(const Duration(seconds: 2));
},
onSuccess: () => _message('Booking completed (demo)'),
onError: (error, stackTrace) => _message('Error: $error'),
),
const SizedBox(height: 16),
Text('Requests started: $_requestCount'),
const SizedBox(height: 24),
TapLatchButton(
label: 'Try failure handling',
onPressed: () async {
await Future<void>.delayed(const Duration(milliseconds: 500));
throw StateError('Demo network error');
},
onError: (error, stackTrace) => _message('Handled: $error'),
),
],
),
),
),
);
}
}