import 'package:example/app.dart'; import 'package:example/state/init_data.dart'; import 'package:example/utils/localizations.dart'; import 'package:example/routes/routes.dart'; import 'package:example/widgets/stream_version.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:example/pages/choose_user_page.dart'; class AdvancedOptionsPage extends StatefulWidget { const AdvancedOptionsPage({super.key}); @override State createState() => _AdvancedOptionsPageState(); } class _AdvancedOptionsPageState extends State { final _formKey = GlobalKey(); final TextEditingController _apiKeyController = TextEditingController(); String? _apiKeyError; final TextEditingController _userIdController = TextEditingController(); String? _userIdError; final TextEditingController _userTokenController = TextEditingController(); String? _userTokenError; final TextEditingController _usernameController = TextEditingController(); bool loading = false; @override void dispose() { _apiKeyController.dispose(); _userIdController.dispose(); _userTokenController.dispose(); _usernameController.dispose(); super.dispose(); } Future _login() async { if (loading) { return; } if (_formKey.currentState!.validate()) { final apiKey = _apiKeyController.text; final userId = _userIdController.text; final userToken = _userTokenController.text; final username = _usernameController.text; loading = true; showDialog( barrierDismissible: false, context: context, barrierColor: StreamChatTheme.of(context).colorTheme.overlay, builder: (context) => Center( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), color: StreamChatTheme.of(context).colorTheme.barsBg, ), height: 100, width: 100, child: const Center( child: CircularProgressIndicator(), ), ), ), ); final client = buildStreamChatClient(apiKey); final router = GoRouter.of(context); final initNotifier = context.read(); try { await client.connectUser( User( id: userId, extraData: { 'name': username, }, ), userToken, ); const secureStorage = FlutterSecureStorage(); await Future.wait([ secureStorage.write( key: kStreamApiKey, value: apiKey, ), secureStorage.write( key: kStreamUserId, value: userId, ), secureStorage.write( key: kStreamToken, value: userToken, ), ]); } catch (e) { debugPrint(e.toString()); var errorText = AppLocalizations.of(context).errorConnecting; if (e is Map) { errorText = e['message'] ?? errorText; } Navigator.of(context).pop(); setState(() { _apiKeyError = errorText.toUpperCase(); }); loading = false; return; } loading = false; initNotifier.initData = initNotifier.initData!.copyWith(client: client); router.goNamed(Routes.CHOOSE_USER.name); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.appBg, appBar: AppBar( backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg, elevation: 1, centerTitle: true, title: Text( AppLocalizations.of(context).advancedOptions, style: StreamChatTheme.of(context).textTheme.headlineBold.copyWith( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis), ), leading: IconButton( icon: StreamSvgIcon.left( color: StreamChatTheme.of(context).colorTheme.textHighEmphasis, ), onPressed: () { Navigator.pop(context); }, ), ), body: Builder( builder: (context) { return Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextFormField( controller: _apiKeyController, onChanged: (_) { if (_apiKeyError != null) { setState(() { _apiKeyError = null; }); } }, validator: (value) { if (value!.isEmpty) { setState(() { _apiKeyError = AppLocalizations.of(context) .apiKeyError .toUpperCase(); }); return _apiKeyError; } return null; }, style: TextStyle( fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, ), decoration: InputDecoration( errorStyle: const TextStyle(height: 0, fontSize: 0), labelStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: _apiKeyError != null ? StreamChatTheme.of(context).colorTheme.accentError : StreamChatTheme.of(context) .colorTheme .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _apiKeyError != null ? '${AppLocalizations.of(context).chatApiKey.toUpperCase()}: $_apiKeyError' : AppLocalizations.of(context).chatApiKey, ), textInputAction: TextInputAction.next, ), const SizedBox(height: 8), TextFormField( controller: _userIdController, onChanged: (_) { if (_userIdError != null) { setState(() { _userIdError = null; }); } }, validator: (value) { if (value!.isEmpty) { setState(() { _userIdError = AppLocalizations.of(context) .userIdError .toUpperCase(); }); return _userIdError; } return null; }, style: TextStyle( fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, ), textInputAction: TextInputAction.next, decoration: InputDecoration( errorStyle: const TextStyle(height: 0, fontSize: 0), labelStyle: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, color: _userIdError != null ? StreamChatTheme.of(context).colorTheme.accentError : StreamChatTheme.of(context) .colorTheme .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _userIdError != null ? '${AppLocalizations.of(context).userId.toUpperCase()}: $_userIdError' : AppLocalizations.of(context).userId, ), ), const SizedBox(height: 8), TextFormField( onChanged: (_) { if (_userTokenError != null) { setState(() { _userTokenError = null; }); } }, controller: _userTokenController, validator: (value) { if (value!.isEmpty) { setState(() { _userTokenError = AppLocalizations.of(context) .userTokenError .toUpperCase(); }); return _userTokenError; } return null; }, style: TextStyle( fontSize: 14, color: StreamChatTheme.of(context) .colorTheme .textHighEmphasis, ), textInputAction: TextInputAction.next, decoration: InputDecoration( errorStyle: const TextStyle(height: 0, fontSize: 0), labelStyle: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, color: _userTokenError != null ? StreamChatTheme.of(context).colorTheme.accentError : StreamChatTheme.of(context) .colorTheme .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: _userTokenError != null ? '${AppLocalizations.of(context).userToken.toUpperCase()}: $_userTokenError' : AppLocalizations.of(context).userToken, ), ), const SizedBox(height: 8), TextFormField( controller: _usernameController, textInputAction: TextInputAction.done, decoration: InputDecoration( labelStyle: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: StreamChatTheme.of(context) .colorTheme .textLowEmphasis, ), border: UnderlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none, ), fillColor: StreamChatTheme.of(context).colorTheme.inputBg, filled: true, labelText: AppLocalizations.of(context).usernameOptional, ), ), const Spacer(), ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all( Theme.of(context).brightness == Brightness.light ? StreamChatTheme.of(context) .colorTheme .accentPrimary : Colors.white), elevation: MaterialStateProperty.all(0), padding: MaterialStateProperty.all( const EdgeInsets.symmetric(vertical: 16)), shape: MaterialStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(26), ), ), ), onPressed: _login, child: Text( AppLocalizations.of(context).login, style: TextStyle( fontSize: 16, color: Theme.of(context).brightness != Brightness.light ? StreamChatTheme.of(context) .colorTheme .accentPrimary : Colors.white, ), ), ), const StreamVersion(), ], ), ), ); }, ), ); } }