diff --git a/lib/pages/select_server_page.dart b/lib/pages/select_server_page.dart index cd9ef83..f0e7dff 100644 --- a/lib/pages/select_server_page.dart +++ b/lib/pages/select_server_page.dart @@ -8,7 +8,6 @@ import "package:nexus/models/homeserver.dart"; import "package:nexus/pages/login_page.dart"; import "package:nexus/widgets/appbar.dart"; import "package:nexus/widgets/divider_text.dart"; -import "package:nexus/widgets/loading.dart"; class SelectServerPage extends HookConsumerWidget { const SelectServerPage({super.key}); @@ -16,199 +15,155 @@ class SelectServerPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final theme = Theme.of(context); - final client = ref.watch(ClientController.provider.notifier); - final hasError = useState(false); - final isLoading = useState(false); - final homeserverFocusNode = useFocusNode(); final launch = ref.watch(LaunchHelper.provider).launchUrl; + + final isLoading = useState(false); final homeserverUrl = useTextEditingController(); Future setHomeserver(Uri? newHomeserver) async { isLoading.value = true; - if (newHomeserver?.hasScheme == false) { - newHomeserver = Uri.https(newHomeserver!.path); - } - - final newUrl = newHomeserver == null - ? null - : await client.discoverHomeserver(newHomeserver); - - if (context.mounted) { - if (newUrl == null) { - hasError.value = true; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - "Homeserver verification failed. Is your homeserver down?", - style: TextStyle(color: theme.colorScheme.onErrorContainer), - ), - backgroundColor: theme.colorScheme.errorContainer, - ), - ); - } else { - homeserverUrl.text = newHomeserver!.origin; - await Navigator.of(context).push( - MaterialPageRoute(builder: (_) => LoginPage(homeserver: newUrl)), - ); + try { + if (newHomeserver?.hasScheme == false) { + newHomeserver = Uri.https(newHomeserver!.path); } - } - homeserverFocusNode.requestFocus(); - isLoading.value = false; + final newUrl = newHomeserver == null + ? null + : await ref + .watch(ClientController.provider.notifier) + .discoverHomeserver(newHomeserver); + + if (context.mounted) { + if (newUrl == null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + "Homeserver verification failed. Is your homeserver down?", + style: .new(color: theme.colorScheme.onErrorContainer), + ), + backgroundColor: theme.colorScheme.errorContainer, + ), + ); + } else { + await Navigator.of(context).push( + MaterialPageRoute(builder: (_) => LoginPage(homeserver: newUrl)), + ); + } + } + } finally { + isLoading.value = false; + } } return Scaffold( appBar: Appbar(), - body: isLoading.value - ? const Loading() - : Center( - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 600), - child: Column( - children: [ - Row( + body: Center( + child: ConstrainedBox( + constraints: .new(maxWidth: 600), + child: ListView( + children: [ + Row( + children: [ + SvgPicture.asset("assets/icon.svg", width: 128), + SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: .start, children: [ - SvgPicture.asset("assets/icon.svg", width: 128), - SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Nexus", - style: theme.textTheme.displayMedium, - ), - Text( - "A Simple Matrix Client", - style: theme.textTheme.headlineMedium, - overflow: TextOverflow.ellipsis, - ), - ], - ), + Text("Nexus", style: theme.textTheme.displayMedium), + Text( + "A Simple Matrix Client", + style: theme.textTheme.headlineMedium, + overflow: .ellipsis, ), ], ), - Padding( - padding: EdgeInsetsGeometry.symmetric(vertical: 12), - child: Divider(), - ), - DividerText("Enter a homeserver domain:"), - Row( - spacing: 8, - children: [ - Expanded( - child: TextField( - focusNode: homeserverFocusNode, - textInputAction: TextInputAction.done, - onSubmitted: (_) => - setHomeserver(Uri.tryParse(homeserverUrl.text)), - onChanged: (newVal) { - if (hasError.value) { - hasError.value = false; - } - }, - controller: homeserverUrl, - decoration: InputDecoration( - labelText: "Homeserver URL (e.g. matrix.org)", - hintText: "e.g. matrix.org", - focusedBorder: hasError.value - ? OutlineInputBorder( - borderSide: BorderSide( - color: theme.colorScheme.error, - ), - ) - : null, - enabledBorder: hasError.value - ? OutlineInputBorder( - borderSide: BorderSide( - color: theme.colorScheme.error, - ), - ) - : null, - ), - ), - ), - IconButton.filled( - tooltip: "Confirm homeserver choice", - onPressed: isLoading.value || hasError.value - ? null - : () => setHomeserver( - Uri.tryParse(homeserverUrl.text), - ), - icon: Icon(Icons.check), - ), - ], - ), - Expanded( - child: ListView( - padding: EdgeInsets.only(top: 12), - children: [ - DividerText( - "Or, choose from some popular homeservers:", - ), - ...([ - Homeserver( - name: "Matrix.org", - description: - "The Matrix.org Foundation offers the matrix.org homeserver as an easy entry point for anyone wanting to try out Matrix.", - url: Uri.https("matrix.org"), - iconUrl: - "https://raw.githubusercontent.com/element-hq/logos/refs/heads/master/matrix/matrix-favicon${Theme.brightnessOf(context) == Brightness.dark ? "-white" : ""}.png", - ), - Homeserver( - name: "Federated Nexus", - description: - "Federated Nexus is a community resource hosting multiple FOSS (especially federated) services, including Matrix and Forgejo. By the same developers who made Nexus client.", - url: Uri.https("federated.nexus"), - iconUrl: - "https://federated.nexus/images/icon.png", - ), - Homeserver( - name: "Unredacted", - description: - "Unredacted is a 501(c)(3) non-profit organization that builds Internet infrastructure and services to help people evade censorship and protect their right to privacy.", - url: Uri.https( - "unredacted.org", - "services/si/matrix", - ), - iconUrl: "https://unredacted.org/favicon.ico", - ), - ].map( - (homeserver) => Card( - child: ListTile( - title: Text(homeserver.name), - leading: Image.network( - homeserver.iconUrl, - errorBuilder: (_, _, _) => SizedBox.shrink(), - height: 32, - ), - subtitle: Text(homeserver.description), - onTap: isLoading.value - ? null - : () => setHomeserver(homeserver.url), - trailing: IconButton( - tooltip: "Launch homeserver info page", - onPressed: () => launch(homeserver.url), - icon: Icon(Icons.info_outline), - ), - ), - ), - )), - ], + ), + ], + ), + Padding(padding: .symmetric(vertical: 12), child: Divider()), + DividerText("Enter a homeserver domain:"), + Row( + spacing: 8, + children: [ + Expanded( + child: TextField( + textInputAction: .done, + autofocus: true, + onSubmitted: (text) => setHomeserver(.tryParse(text)), + controller: homeserverUrl, + decoration: .new( + labelText: "Homeserver URL", + hintText: "matrix.org", ), ), - SizedBox(height: 5), - TextButton( - onPressed: () => - launch(Uri.https("servers.joinmatrix.org")), - child: Text("See more homeservers..."), - ), - ], - ), + ), + IconButton.filled( + tooltip: "Confirm homeserver choice", + onPressed: isLoading.value + ? null + : () => setHomeserver(.tryParse(homeserverUrl.text)), + icon: Icon(Icons.check), + ), + ], ), - ), + DividerText("Or, choose from some popular homeservers:"), + ...([ + .new( + name: "Matrix.org", + description: + "The Matrix.org Foundation offers the matrix.org homeserver as an easy entry point for anyone wanting to try out Matrix.", + url: .https("matrix.org"), + iconUrl: + "https://raw.githubusercontent.com/element-hq/logos/refs/heads/master/matrix/matrix-favicon${Theme.brightnessOf(context) == Brightness.dark ? "-white" : ""}.png", + ), + .new( + name: "Federated Nexus", + description: + "Federated Nexus is a community resource hosting multiple FOSS (especially federated) services, including Matrix and Forgejo. By the same developers who made Nexus client.", + url: .https("federated.nexus"), + iconUrl: "https://federated.nexus/images/icon.png", + ), + .new( + name: "Unredacted", + description: + "Unredacted is a 501(c)(3) non-profit organization that builds Internet infrastructure and services to help people evade censorship and protect their right to privacy.", + url: .https("unredacted.org", "services/si/matrix"), + iconUrl: "https://unredacted.org/favicon.ico", + ), + ].map( + (homeserver) => Card( + child: ListTile( + enabled: !isLoading.value, + title: Text(homeserver.name), + leading: Image.network( + homeserver.iconUrl, + errorBuilder: (_, _, _) => SizedBox.shrink(), + height: 32, + ), + subtitle: Text(homeserver.description), + onTap: isLoading.value + ? null + : () => setHomeserver(homeserver.url), + trailing: IconButton( + tooltip: "Launch homeserver info page", + onPressed: () => launch(homeserver.url), + icon: Icon(Icons.info_outline), + ), + ), + ), + )), + + TextButton( + onPressed: () => launch(.https("servers.joinmatrix.org")), + child: Text("See more homeservers..."), + ), + ], + ), + ), + ), ); } }