You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fluffychat/lib/pages/homeserver_picker/homeserver_picker_view.dart

233 lines
9.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart';
import 'package:fluffychat/widgets/layouts/login_scaffold.dart';
import 'package:fluffychat/widgets/matrix.dart';
import '../../config/themes.dart';
import 'homeserver_picker.dart';
class HomeserverPickerView extends StatelessWidget {
final HomeserverPickerController controller;
const HomeserverPickerView(
this.controller, {
super.key,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return LoginScaffold(
enforceMobileMode: Matrix.of(context).client.isLogged(),
appBar: AppBar(
centerTitle: true,
title: Text(
controller.widget.addMultiAccount
? L10n.of(context).addAccount
: L10n.of(context).login,
),
actions: [
PopupMenuButton<MoreLoginActions>(
onSelected: controller.onMoreAction,
itemBuilder: (_) => [
PopupMenuItem(
value: MoreLoginActions.importBackup,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.import_export_outlined),
const SizedBox(width: 12),
Text(L10n.of(context).hydrate),
],
),
),
PopupMenuItem(
value: MoreLoginActions.privacy,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.privacy_tip_outlined),
const SizedBox(width: 12),
Text(L10n.of(context).privacy),
],
),
),
PopupMenuItem(
value: MoreLoginActions.about,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.info_outlined),
const SizedBox(width: 12),
Text(L10n.of(context).about),
],
),
),
],
),
],
),
body: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: IntrinsicHeight(
child: Column(
children: [
// display a prominent banner to import session for TOR browser
// users. This feature is just some UX sugar as TOR users are
// usually forced to logout as TOR browser is non-persistent
AnimatedContainer(
height: controller.isTorBrowser ? 64 : 0,
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(),
child: Material(
clipBehavior: Clip.hardEdge,
borderRadius: const BorderRadius.vertical(
bottom: Radius.circular(8),
),
color: theme.colorScheme.surface,
child: ListTile(
leading: const Icon(Icons.vpn_key),
title: Text(L10n.of(context).hydrateTor),
subtitle: Text(L10n.of(context).hydrateTorLong),
trailing: const Icon(Icons.chevron_right_outlined),
onTap: controller.restoreBackup,
),
),
),
Container(
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Hero(
tag: 'info-logo',
child: Image.asset(
'./assets/banner_transparent.png',
fit: BoxFit.fitWidth,
),
),
),
const SizedBox(height: 32),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32.0),
child: SelectableLinkify(
text: L10n.of(context).appIntroduction,
textAlign: TextAlign.center,
linkStyle: TextStyle(
color: theme.colorScheme.secondary,
decorationColor: theme.colorScheme.secondary,
),
onOpen: (link) => launchUrlString(link.url),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
onSubmitted: (_) =>
controller.checkHomeserverAction(),
controller: controller.homeserverController,
autocorrect: false,
keyboardType: TextInputType.url,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search_outlined),
filled: false,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(
AppConfig.borderRadius,
),
),
hintText: AppConfig.defaultHomeserver,
hintStyle: TextStyle(
color: theme.colorScheme.surfaceTint,
),
labelText: 'Sign in with:',
errorText: controller.error,
errorMaxLines: 4,
suffixIcon: IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog.adaptive(
title: Text(
L10n.of(context).whatIsAHomeserver,
),
content: Linkify(
text: L10n.of(context)
.homeserverDescription,
),
actions: [
AdaptiveDialogAction(
onPressed: () => launchUrl(
Uri.https('servers.joinmatrix.org'),
),
child: Text(
L10n.of(context)
.discoverHomeservers,
),
),
AdaptiveDialogAction(
onPressed: Navigator.of(context).pop,
child: Text(L10n.of(context).close),
),
],
),
);
},
icon: const Icon(Icons.info_outlined),
),
),
),
const SizedBox(height: 32),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.primary,
foregroundColor: theme.colorScheme.onPrimary,
),
onPressed: controller.isLoading
? null
: controller.checkHomeserverAction,
child: controller.isLoading
? const LinearProgressIndicator()
: Text(L10n.of(context).continueText),
),
TextButton(
style: TextButton.styleFrom(
foregroundColor: theme.colorScheme.secondary,
textStyle: theme.textTheme.labelMedium,
),
onPressed: controller.isLoading
? null
: () => controller.checkHomeserverAction(
legacyPasswordLogin: true,
),
child: Text(L10n.of(context).loginWithMatrixId),
),
],
),
),
],
),
),
),
);
},
),
);
}
}