import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'shorten_service.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( debugShowCheckedModeBanner: false, home: Home(), ); } } class Home extends StatefulWidget { const Home({super.key}); @override State createState() => _HomeState(); } class _HomeState extends State { late final TextEditingController controller; final GlobalKey formKey = GlobalKey(); String? shortenedUrl; bool loading = false; @override void initState() { super.initState(); controller = TextEditingController(); } @override void dispose() { super.dispose(); controller.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Stack( children: [ Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'Url shortner', style: TextStyle(fontSize: 24), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const SizedBox(width: 30), ConstrainedBox( constraints: const BoxConstraints(maxWidth: 300), child: Form( key: formKey, child: TextFormField( controller: controller, onFieldSubmitted: loading ? null : (_) => processUrl(), validator: (String? url) { try { if (url == null || url.isEmpty) { return 'No url entered.'; } final Uri uri = Uri.parse(url); if (!uri.hasScheme || (!uri.isScheme('HTTP') && !uri.isScheme('HTTPS'))) { throw const FormatException(); } return null; } on FormatException { return 'Bad URL'; } }, ), ), ), IconButton( icon: const Icon(Icons.arrow_circle_right_rounded), onPressed: loading ? null : () => processUrl(), ), ], ), AnimatedOpacity( opacity: shortenedUrl == null ? 0.0 : 1.0, duration: const Duration(milliseconds: 200), child: Padding( padding: const EdgeInsets.only(top: 14.0), child: Column( children: [ const Text('Short URL:'), InkWell( onTap: shortenedUrl == null ? null : () => launchUrl(Uri.parse(shortenedUrl!)), child: Text( shortenedUrl ?? '', style: const TextStyle(color: Colors.blue, fontSize: 24), ), ), ], ), ), ), ], ), Center( child: AnimatedOpacity( opacity: loading ? 1.0 : 0.0, duration: const Duration(milliseconds: 200), child: const CircularProgressIndicator(), ), ) ], ), ), ); } Future processUrl() async { try { assert(formKey.currentState != null, 'Could not validate form, formKey currentState is null'); if (loading) { return; } setState(() => loading = true); final bool isValid = formKey.currentState!.validate(); if (!isValid) { setState(() => loading = false); return; } final String? shortUrl = await shortenUrl(controller.text); if (shortUrl != null) { setState(() { shortenedUrl = shortUrl; loading = false; }); } else { // show error setState(() { shortenedUrl = null; loading = false; }); } } catch (err, st) { if (kDebugMode) { print(st); print('An error occurred trying to shorten the url: $err'); } setState(() => loading = false); } } }