diff --git a/packages/neon/neon/lib/src/pages/account_settings.dart b/packages/neon/neon/lib/src/pages/account_settings.dart index 89341e13..907cf879 100644 --- a/packages/neon/neon/lib/src/pages/account_settings.dart +++ b/packages/neon/neon/lib/src/pages/account_settings.dart @@ -144,10 +144,12 @@ class AccountSettingsPage extends StatelessWidget { return Scaffold( resizeToAvoidBottomInset: false, appBar: appBar, - body: Center( - child: ConstrainedBox( - constraints: NeonDialogTheme.of(context).constraints, - child: body, + body: SafeArea( + child: Center( + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: body, + ), ), ), ); diff --git a/packages/neon/neon/lib/src/pages/home.dart b/packages/neon/neon/lib/src/pages/home.dart index 4d16bd9b..c82cd0eb 100644 --- a/packages/neon/neon/lib/src/pages/home.dart +++ b/packages/neon/neon/lib/src/pages/home.dart @@ -157,7 +157,9 @@ class _HomePageState extends State { return const SizedBox(); } - return activeAppIDSnapshot.requireData.page; + return SafeArea( + child: activeAppIDSnapshot.requireData.page, + ); }, ); }, diff --git a/packages/neon/neon/lib/src/pages/login.dart b/packages/neon/neon/lib/src/pages/login.dart index 0a399f59..438c72b6 100644 --- a/packages/neon/neon/lib/src/pages/login.dart +++ b/packages/neon/neon/lib/src/pages/login.dart @@ -51,72 +51,74 @@ class _LoginPageState extends State { leading: const CloseButton(), ) : null, - body: Center( - child: ConstrainedBox( - constraints: NeonDialogTheme.of(context).constraints, - child: SingleChildScrollView( - padding: const EdgeInsets.all(10), - primary: true, - child: Column( - children: [ - ExcludeSemantics( - child: branding.logo, - ), - Text( - branding.name, - style: Theme.of(context).textTheme.titleLarge, - ), - if (branding.showLoginWithNextcloud) ...[ - const SizedBox( - height: 10, - ), - Text(NeonLocalizations.of(context).loginWorksWith), - const SizedBox( - height: 10, + body: SafeArea( + child: Center( + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: SingleChildScrollView( + padding: const EdgeInsets.all(10), + primary: true, + child: Column( + children: [ + ExcludeSemantics( + child: branding.logo, ), - Semantics( - label: NeonLocalizations.of(context).nextcloud, - child: const NextcloudLogo(), + Text( + branding.name, + style: Theme.of(context).textTheme.titleLarge, ), - ], - const SizedBox( - height: 50, - ), - Form( - key: _formKey, - child: TextFormField( - focusNode: _focusNode, - controller: _controller, - decoration: InputDecoration( - hintText: 'https://...', - labelText: NeonLocalizations.of(context).loginUsingServerAddress, - suffixIcon: IconButton( - icon: const Icon(Icons.arrow_forward), - onPressed: () { - login(_controller.text); - }, - ), + if (branding.showLoginWithNextcloud) ...[ + const SizedBox( + height: 10, ), - keyboardType: TextInputType.url, - validator: (final input) => validateHttpUrl(context, input), - onFieldSubmitted: login, - autofillHints: const [AutofillHints.url], - ), - ), - if (NeonPlatform.instance.canUseCamera) ...[ + Text(NeonLocalizations.of(context).loginWorksWith), + const SizedBox( + height: 10, + ), + Semantics( + label: NeonLocalizations.of(context).nextcloud, + child: const NextcloudLogo(), + ), + ], const SizedBox( height: 50, ), - IconButton( - tooltip: NeonLocalizations.of(context).loginUsingQRcode, - icon: const Icon( - Icons.qr_code_scanner_rounded, - size: 60, + Form( + key: _formKey, + child: TextFormField( + focusNode: _focusNode, + controller: _controller, + decoration: InputDecoration( + hintText: 'https://...', + labelText: NeonLocalizations.of(context).loginUsingServerAddress, + suffixIcon: IconButton( + icon: const Icon(Icons.arrow_forward), + onPressed: () { + login(_controller.text); + }, + ), + ), + keyboardType: TextInputType.url, + validator: (final input) => validateHttpUrl(context, input), + onFieldSubmitted: login, + autofillHints: const [AutofillHints.url], ), - onPressed: () => const LoginQRcodeRoute().go(context), ), + if (NeonPlatform.instance.canUseCamera) ...[ + const SizedBox( + height: 50, + ), + IconButton( + tooltip: NeonLocalizations.of(context).loginUsingQRcode, + icon: const Icon( + Icons.qr_code_scanner_rounded, + size: 60, + ), + onPressed: () => const LoginQRcodeRoute().go(context), + ), + ], ], - ], + ), ), ), ), diff --git a/packages/neon/neon/lib/src/pages/login_check_account.dart b/packages/neon/neon/lib/src/pages/login_check_account.dart index 6bb9e207..c1142bc1 100644 --- a/packages/neon/neon/lib/src/pages/login_check_account.dart +++ b/packages/neon/neon/lib/src/pages/login_check_account.dart @@ -54,57 +54,59 @@ class _LoginCheckAccountPageState extends State { @override Widget build(final BuildContext context) => Scaffold( appBar: AppBar(), - body: Center( - child: Padding( - padding: const EdgeInsets.all(10), - child: ConstrainedBox( - constraints: NeonDialogTheme.of(context).constraints, - child: ResultBuilder.behaviorSubject( - subject: bloc.state, - builder: (final context, final state) => Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (state.hasError) ...[ - Builder( - builder: (final context) { - final details = NeonError.getDetails(state.error); - return NeonValidationTile( - title: details.isUnauthorized - ? NeonLocalizations.of(context).errorCredentialsForAccountNoLongerMatch - : details.getText(context), - state: ValidationState.failure, - ); - }, - ), - ], - _buildAccountTile(state), - Align( - alignment: Alignment.bottomRight, - child: ElevatedButton( - onPressed: state.hasData - ? () { - NeonProvider.of(context) - ..updateAccount(state.requireData) - ..setActiveAccount(state.requireData); + body: SafeArea( + child: Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: ResultBuilder.behaviorSubject( + subject: bloc.state, + builder: (final context, final state) => Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (state.hasError) ...[ + Builder( + builder: (final context) { + final details = NeonError.getDetails(state.error); + return NeonValidationTile( + title: details.isUnauthorized + ? NeonLocalizations.of(context).errorCredentialsForAccountNoLongerMatch + : details.getText(context), + state: ValidationState.failure, + ); + }, + ), + ], + _buildAccountTile(state), + Align( + alignment: Alignment.bottomRight, + child: ElevatedButton( + onPressed: state.hasData + ? () { + NeonProvider.of(context) + ..updateAccount(state.requireData) + ..setActiveAccount(state.requireData); - const HomeRoute().go(context); - } - : () { - if (state.hasError && NeonError.getDetails(state.error).isUnauthorized) { - Navigator.pop(context); - return; + const HomeRoute().go(context); } + : () { + if (state.hasError && NeonError.getDetails(state.error).isUnauthorized) { + Navigator.pop(context); + return; + } - unawaited(bloc.refresh()); - }, - child: Text( - state.hasData - ? NeonLocalizations.of(context).actionContinue - : NeonLocalizations.of(context).actionRetry, + unawaited(bloc.refresh()); + }, + child: Text( + state.hasData + ? NeonLocalizations.of(context).actionContinue + : NeonLocalizations.of(context).actionRetry, + ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/packages/neon/neon/lib/src/pages/login_check_server_status.dart b/packages/neon/neon/lib/src/pages/login_check_server_status.dart index c4e4a384..042b024f 100644 --- a/packages/neon/neon/lib/src/pages/login_check_server_status.dart +++ b/packages/neon/neon/lib/src/pages/login_check_server_status.dart @@ -51,41 +51,43 @@ class _LoginCheckServerStatusPageState extends State @override Widget build(final BuildContext context) => Scaffold( appBar: AppBar(), - body: Center( - child: Padding( - padding: const EdgeInsets.all(10), - child: ConstrainedBox( - constraints: NeonDialogTheme.of(context).constraints, - child: ResultBuilder.behaviorSubject( - subject: bloc.state, - builder: (final context, final state) { - final success = state.hasData && state.requireData.isSupported && !state.requireData.maintenance; - - return Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (state.hasError) ...[ - NeonValidationTile( - title: NeonError.getDetails(state.error).getText(context), - state: ValidationState.failure, - ), - ], - _buildServerVersionTile(state), - _buildMaintenanceModeTile(state), - Align( - alignment: Alignment.bottomRight, - child: ElevatedButton( - onPressed: success ? _onContinue : bloc.refresh, - child: Text( - success - ? NeonLocalizations.of(context).actionContinue - : NeonLocalizations.of(context).actionRetry, + body: SafeArea( + child: Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: ResultBuilder.behaviorSubject( + subject: bloc.state, + builder: (final context, final state) { + final success = state.hasData && state.requireData.isSupported && !state.requireData.maintenance; + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (state.hasError) ...[ + NeonValidationTile( + title: NeonError.getDetails(state.error).getText(context), + state: ValidationState.failure, + ), + ], + _buildServerVersionTile(state), + _buildMaintenanceModeTile(state), + Align( + alignment: Alignment.bottomRight, + child: ElevatedButton( + onPressed: success ? _onContinue : bloc.refresh, + child: Text( + success + ? NeonLocalizations.of(context).actionContinue + : NeonLocalizations.of(context).actionRetry, + ), ), ), - ), - ], - ); - }, + ], + ); + }, + ), ), ), ), diff --git a/packages/neon/neon/lib/src/pages/login_flow.dart b/packages/neon/neon/lib/src/pages/login_flow.dart index 327b84cc..ef50d6c7 100644 --- a/packages/neon/neon/lib/src/pages/login_flow.dart +++ b/packages/neon/neon/lib/src/pages/login_flow.dart @@ -57,32 +57,34 @@ class _LoginFlowPageState extends State { @override Widget build(final BuildContext context) => Scaffold( appBar: AppBar(), - body: Center( - child: Padding( - padding: const EdgeInsets.all(10), - child: ResultBuilder.behaviorSubject( - subject: bloc.init, - builder: (final context, final init) => Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - NeonLinearProgressIndicator( - visible: init.isLoading, - ), - NeonError( - init.error, - onRetry: bloc.refresh, - ), - if (init.hasData) ...[ - Text(NeonLocalizations.of(context).loginSwitchToBrowserWindow), - const SizedBox( - height: 10, + body: SafeArea( + child: Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: ResultBuilder.behaviorSubject( + subject: bloc.init, + builder: (final context, final init) => Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + NeonLinearProgressIndicator( + visible: init.isLoading, ), - ElevatedButton( - onPressed: bloc.refresh, - child: Text(NeonLocalizations.of(context).loginOpenAgain), + NeonError( + init.error, + onRetry: bloc.refresh, ), + if (init.hasData) ...[ + Text(NeonLocalizations.of(context).loginSwitchToBrowserWindow), + const SizedBox( + height: 10, + ), + ElevatedButton( + onPressed: bloc.refresh, + child: Text(NeonLocalizations.of(context).loginOpenAgain), + ), + ], ], - ], + ), ), ), ), diff --git a/packages/neon/neon/lib/src/pages/login_qr_code.dart b/packages/neon/neon/lib/src/pages/login_qr_code.dart index e43d63dc..5c063dad 100644 --- a/packages/neon/neon/lib/src/pages/login_qr_code.dart +++ b/packages/neon/neon/lib/src/pages/login_qr_code.dart @@ -23,41 +23,43 @@ class _LoginQRcodePageState extends State { @override Widget build(final BuildContext context) => Scaffold( appBar: AppBar(), - body: ReaderWidget( - codeFormat: Format.qrCode, - showGallery: false, - showToggleCamera: false, - showScannerOverlay: false, - tryHarder: true, - cropPercent: 0, - scanDelaySuccess: const Duration(seconds: 3), - onScan: (final code) async { - String? url; - try { - url = code.text; - if (url == null) { - throw const InvalidQRcodeException(); - } - final match = LoginQRcode.tryParse(url); - if (match == null) { - throw const InvalidQRcodeException(); - } + body: SafeArea( + child: ReaderWidget( + codeFormat: Format.qrCode, + showGallery: false, + showToggleCamera: false, + showScannerOverlay: false, + tryHarder: true, + cropPercent: 0, + scanDelaySuccess: const Duration(seconds: 3), + onScan: (final code) async { + String? url; + try { + url = code.text; + if (url == null) { + throw const InvalidQRcodeException(); + } + final match = LoginQRcode.tryParse(url); + if (match == null) { + throw const InvalidQRcodeException(); + } - LoginCheckServerStatusRoute.withCredentials( - serverUrl: match.serverURL, - loginName: match.username, - password: match.password, - ).pushReplacement(context); - } catch (e, s) { - if (_lastErrorURL != url) { - debugPrint(e.toString()); - debugPrint(s.toString()); + LoginCheckServerStatusRoute.withCredentials( + serverUrl: match.serverURL, + loginName: match.username, + password: match.password, + ).pushReplacement(context); + } catch (e, s) { + if (_lastErrorURL != url) { + debugPrint(e.toString()); + debugPrint(s.toString()); - _lastErrorURL = url; - NeonError.showSnackbar(context, e); + _lastErrorURL = url; + NeonError.showSnackbar(context, e); + } } - } - }, + }, + ), ), ); } diff --git a/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart b/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart index 09a1b459..b26b5451 100644 --- a/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart +++ b/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart @@ -61,10 +61,12 @@ class NextcloudAppSettingsPage extends StatelessWidget { return Scaffold( resizeToAvoidBottomInset: false, appBar: appBar, - body: Center( - child: ConstrainedBox( - constraints: NeonDialogTheme.of(context).constraints, - child: body, + body: SafeArea( + child: Center( + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: body, + ), ), ), ); diff --git a/packages/neon/neon/lib/src/pages/route_not_found.dart b/packages/neon/neon/lib/src/pages/route_not_found.dart index b8b2071d..b9dfa75f 100644 --- a/packages/neon/neon/lib/src/pages/route_not_found.dart +++ b/packages/neon/neon/lib/src/pages/route_not_found.dart @@ -59,8 +59,10 @@ class _RouteNotFoundPageState extends State { }, ), ), - body: Center( - child: Text(NeonLocalizations.of(context).errorRouteNotFound(widget.uri.toString())), + body: SafeArea( + child: Center( + child: Text(NeonLocalizations.of(context).errorRouteNotFound(widget.uri.toString())), + ), ), ); } diff --git a/packages/neon/neon/lib/src/pages/settings.dart b/packages/neon/neon/lib/src/pages/settings.dart index 8f095a4a..0d842b73 100644 --- a/packages/neon/neon/lib/src/pages/settings.dart +++ b/packages/neon/neon/lib/src/pages/settings.dart @@ -370,10 +370,12 @@ class _SettingsPageState extends State { return Scaffold( resizeToAvoidBottomInset: false, appBar: appBar, - body: Center( - child: ConstrainedBox( - constraints: NeonDialogTheme.of(context).constraints, - child: body, + body: SafeArea( + child: Center( + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: body, + ), ), ), ); diff --git a/packages/neon/neon/lib/src/widgets/app_bar.dart b/packages/neon/neon/lib/src/widgets/app_bar.dart index d5fccfd5..2ff61ae5 100644 --- a/packages/neon/neon/lib/src/widgets/app_bar.dart +++ b/packages/neon/neon/lib/src/widgets/app_bar.dart @@ -233,7 +233,9 @@ class _NotificationIconButtonState extends State { ], ), ), - body: app.page, + body: SafeArea( + child: app.page, + ), ); await Navigator.of(context).push( diff --git a/packages/neon/neon_files/lib/pages/details.dart b/packages/neon/neon_files/lib/pages/details.dart index 9cbc5ded..36d50c1f 100644 --- a/packages/neon/neon_files/lib/pages/details.dart +++ b/packages/neon/neon_files/lib/pages/details.dart @@ -16,59 +16,61 @@ class FilesDetailsPage extends StatelessWidget { appBar: AppBar( title: Text(details.name), ), - body: ListView( - primary: true, - children: [ - ColoredBox( - color: Theme.of(context).colorScheme.primary, - child: FilePreview( - bloc: bloc, - details: details, - color: Theme.of(context).colorScheme.onPrimary, - size: Size( - MediaQuery.of(context).size.width, - MediaQuery.of(context).size.height / 4, + body: SafeArea( + child: ListView( + primary: true, + children: [ + ColoredBox( + color: Theme.of(context).colorScheme.primary, + child: FilePreview( + bloc: bloc, + details: details, + color: Theme.of(context).colorScheme.onPrimary, + size: Size( + MediaQuery.of(context).size.width, + MediaQuery.of(context).size.height / 4, + ), ), ), - ), - DataTable( - headingRowHeight: 0, - columns: const [ - DataColumn(label: SizedBox()), - DataColumn(label: SizedBox()), - ], - rows: [ - for (final entry in { - details.isDirectory - ? FilesLocalizations.of(context).detailsFolderName - : FilesLocalizations.of(context).detailsFileName: details.name, - FilesLocalizations.of(context).detailsParentFolder: - details.path.length == 1 ? '/' : details.path.sublist(0, details.path.length - 1).join('/'), - if (details.size != null) ...{ + DataTable( + headingRowHeight: 0, + columns: const [ + DataColumn(label: SizedBox()), + DataColumn(label: SizedBox()), + ], + rows: [ + for (final entry in { details.isDirectory - ? FilesLocalizations.of(context).detailsFolderSize - : FilesLocalizations.of(context).detailsFileSize: filesize(details.size, 1), - }, - if (details.lastModified != null) ...{ - FilesLocalizations.of(context).detailsLastModified: - details.lastModified!.toLocal().toIso8601String(), - }, - if (details.isFavorite != null) ...{ - FilesLocalizations.of(context).detailsIsFavorite: details.isFavorite! - ? FilesLocalizations.of(context).actionYes - : FilesLocalizations.of(context).actionNo, - }, - }.entries) ...[ - DataRow( - cells: [ - DataCell(Text(entry.key)), - DataCell(Text(entry.value)), - ], - ), + ? FilesLocalizations.of(context).detailsFolderName + : FilesLocalizations.of(context).detailsFileName: details.name, + FilesLocalizations.of(context).detailsParentFolder: + details.path.length == 1 ? '/' : details.path.sublist(0, details.path.length - 1).join('/'), + if (details.size != null) ...{ + details.isDirectory + ? FilesLocalizations.of(context).detailsFolderSize + : FilesLocalizations.of(context).detailsFileSize: filesize(details.size, 1), + }, + if (details.lastModified != null) ...{ + FilesLocalizations.of(context).detailsLastModified: + details.lastModified!.toLocal().toIso8601String(), + }, + if (details.isFavorite != null) ...{ + FilesLocalizations.of(context).detailsIsFavorite: details.isFavorite! + ? FilesLocalizations.of(context).actionYes + : FilesLocalizations.of(context).actionNo, + }, + }.entries) ...[ + DataRow( + cells: [ + DataCell(Text(entry.key)), + DataCell(Text(entry.value)), + ], + ), + ], ], - ], - ), - ], + ), + ], + ), ), ); } diff --git a/packages/neon/neon_news/lib/pages/article.dart b/packages/neon/neon_news/lib/pages/article.dart index a3211e01..d088fe11 100644 --- a/packages/neon/neon_news/lib/pages/article.dart +++ b/packages/neon/neon_news/lib/pages/article.dart @@ -167,28 +167,30 @@ class _NewsArticlePageState extends State { ], ], ), - body: widget.useWebView - ? WebViewWidget( - controller: _webviewController!, - ) - : SingleChildScrollView( - padding: const EdgeInsets.all(10), - child: Html( - data: widget.bodyData, - onLinkTap: ( - final url, - final attributes, - final element, - ) async { - if (url != null) { - await launchUrlString( - url, - mode: LaunchMode.externalApplication, - ); - } - }, + body: SafeArea( + child: widget.useWebView + ? WebViewWidget( + controller: _webviewController!, + ) + : SingleChildScrollView( + padding: const EdgeInsets.all(10), + child: Html( + data: widget.bodyData, + onLinkTap: ( + final url, + final attributes, + final element, + ) async { + if (url != null) { + await launchUrlString( + url, + mode: LaunchMode.externalApplication, + ); + } + }, + ), ), - ), + ), ), ); } diff --git a/packages/neon/neon_news/lib/pages/feed.dart b/packages/neon/neon_news/lib/pages/feed.dart index e216bac3..ba2c9b04 100644 --- a/packages/neon/neon_news/lib/pages/feed.dart +++ b/packages/neon/neon_news/lib/pages/feed.dart @@ -16,15 +16,17 @@ class NewsFeedPage extends StatelessWidget { appBar: AppBar( title: Text(feed.title), ), - body: NewsArticlesView( - bloc: NewsArticlesBloc( - bloc, - bloc.options, - bloc.account, - id: feed.id, - listType: ListType.feed, + body: SafeArea( + child: NewsArticlesView( + bloc: NewsArticlesBloc( + bloc, + bloc.options, + bloc.account, + id: feed.id, + listType: ListType.feed, + ), + newsBloc: bloc, ), - newsBloc: bloc, ), ); } diff --git a/packages/neon/neon_news/lib/pages/folder.dart b/packages/neon/neon_news/lib/pages/folder.dart index d08b84c3..61e3671c 100644 --- a/packages/neon/neon_news/lib/pages/folder.dart +++ b/packages/neon/neon_news/lib/pages/folder.dart @@ -16,9 +16,11 @@ class NewsFolderPage extends StatelessWidget { appBar: AppBar( title: Text(folder.name), ), - body: NewsFolderView( - bloc: bloc, - folder: folder, + body: SafeArea( + child: NewsFolderView( + bloc: bloc, + folder: folder, + ), ), floatingActionButton: NewsFeedFloatingActionButton( bloc: bloc, diff --git a/packages/neon/neon_notes/lib/pages/category.dart b/packages/neon/neon_notes/lib/pages/category.dart index 520797c2..91c9b052 100644 --- a/packages/neon/neon_notes/lib/pages/category.dart +++ b/packages/neon/neon_notes/lib/pages/category.dart @@ -16,9 +16,11 @@ class NotesCategoryPage extends StatelessWidget { appBar: AppBar( title: Text(category.name.isNotEmpty ? category.name : NotesLocalizations.of(context).categoryUncategorized), ), - body: NotesView( - bloc: bloc, - category: category.name, + body: SafeArea( + child: NotesView( + bloc: bloc, + category: category.name, + ), ), floatingActionButton: NotesFloatingActionButton( bloc: bloc, diff --git a/packages/neon/neon_notes/lib/pages/note.dart b/packages/neon/neon_notes/lib/pages/note.dart index 651cc44b..cb99dd82 100644 --- a/packages/neon/neon_notes/lib/pages/note.dart +++ b/packages/neon/neon_notes/lib/pages/note.dart @@ -141,42 +141,44 @@ class _NotesNotePageState extends State { ), ], ), - body: GestureDetector( - onTap: () { - setState(() { - _showEditor = true; - }); - }, - child: Container( - padding: EdgeInsets.symmetric( - vertical: 10, - horizontal: _showEditor ? 20 : 10, - ), - color: Colors.transparent, - constraints: const BoxConstraints.expand(), - child: _showEditor - ? TextField( - controller: _contentController, - focusNode: _contentFocusNode, - keyboardType: TextInputType.multiline, - maxLines: null, - decoration: const InputDecoration( - border: InputBorder.none, - ), - ) - : SingleChildScrollView( - child: MarkdownBody( - data: _contentController.text, - onTapLink: (final text, final href, final title) async { - if (href != null) { - await launchUrlString( - href, - mode: LaunchMode.externalApplication, - ); - } - }, + body: SafeArea( + child: GestureDetector( + onTap: () { + setState(() { + _showEditor = true; + }); + }, + child: Container( + padding: EdgeInsets.symmetric( + vertical: 10, + horizontal: _showEditor ? 20 : 10, + ), + color: Colors.transparent, + constraints: const BoxConstraints.expand(), + child: _showEditor + ? TextField( + controller: _contentController, + focusNode: _contentFocusNode, + keyboardType: TextInputType.multiline, + maxLines: null, + decoration: const InputDecoration( + border: InputBorder.none, + ), + ) + : SingleChildScrollView( + child: MarkdownBody( + data: _contentController.text, + onTapLink: (final text, final href, final title) async { + if (href != null) { + await launchUrlString( + href, + mode: LaunchMode.externalApplication, + ); + } + }, + ), ), - ), + ), ), ), ),