From c777ccbbcab01d744805040e413bb5cdbc7cda9c Mon Sep 17 00:00:00 2001 From: Juan Gilsanz Polo Date: Wed, 28 Feb 2024 18:25:48 +0100 Subject: [PATCH] Ui improvements for tablet mode --- lib/config/sizes.dart | 3 + .../bookmarks/ui/bookmark_form_modal.dart | 153 +++++++++++------- lib/screens/onboarding/ui/onboarding.dart | 44 ++++- lib/screens/onboarding/ui/welcome.dart | 111 ++++++------- lib/widgets/circle_page_transition.dart | 2 +- 5 files changed, 195 insertions(+), 118 deletions(-) create mode 100644 lib/config/sizes.dart diff --git a/lib/config/sizes.dart b/lib/config/sizes.dart new file mode 100644 index 0000000..ee26a9e --- /dev/null +++ b/lib/config/sizes.dart @@ -0,0 +1,3 @@ +class Sizes { + static int tabletBreakpoint = 800; +} diff --git a/lib/screens/bookmarks/ui/bookmark_form_modal.dart b/lib/screens/bookmarks/ui/bookmark_form_modal.dart index 95d3158..0254286 100644 --- a/lib/screens/bookmarks/ui/bookmark_form_modal.dart +++ b/lib/screens/bookmarks/ui/bookmark_form_modal.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:easy_autocomplete/easy_autocomplete.dart'; @@ -8,17 +6,16 @@ import 'package:linkdy/screens/bookmarks/provider/bookmark_form.provider.dart'; import 'package:linkdy/widgets/section_label.dart'; import 'package:linkdy/models/data/bookmarks.dart'; +import 'package:linkdy/config/sizes.dart'; import 'package:linkdy/i18n/strings.g.dart'; import 'package:linkdy/constants/global_keys.dart'; import 'package:linkdy/constants/enums.dart'; class BookmarkFormModal extends ConsumerStatefulWidget { - final bool fullscreen; final Bookmark? bookmark; const BookmarkFormModal({ super.key, - required this.fullscreen, this.bookmark, }); @@ -37,60 +34,111 @@ class BookmarkFormModalState extends ConsumerState { @override Widget build(BuildContext context) { - return ScaffoldMessenger( - key: ScaffoldMessengerKeys.addBookmark, - child: Dialog.fullscreen( - child: Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - leading: CloseButton( - onPressed: () => Navigator.pop(context), + final width = MediaQuery.of(context).size.width; + + if (width > Sizes.tabletBreakpoint) { + return ScaffoldMessenger( + key: ScaffoldMessengerKeys.addBookmark, + child: Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 500, maxHeight: 700), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + CloseButton( + onPressed: () => Navigator.pop(context), + ), + const SizedBox(width: 16), + Text( + widget.bookmark != null + ? t.bookmarks.addBookmark.editBookmark + : t.bookmarks.addBookmark.addBookmark, + style: const TextStyle(fontSize: 24), + ), + ], + ), + IconButton( + onPressed: ref.watch(bookmarkFormProvider).checkBookmark != null + ? () => ref.read(bookmarkFormProvider.notifier).saveBookmark() + : null, + icon: const Icon(Icons.save_rounded), + tooltip: t.generic.save, + ), + ], ), - title: Text( - widget.bookmark != null - ? t.bookmarks.addBookmark.editBookmark - : t.bookmarks.addBookmark.addBookmark, - ), - actions: [ - IconButton( - onPressed: ref.watch(bookmarkFormProvider).checkBookmark != null - ? () => ref.read(bookmarkFormProvider.notifier).saveBookmark() - : null, - icon: const Icon(Icons.save_rounded), - tooltip: t.generic.save, - ), - const SizedBox(width: 8), - ], ), - ), - ], - body: SafeArea( - top: false, - bottom: true, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + Expanded( + child: ListView( + children: const [_ModalContent()], + ), + ), + ], + ), + ), + ), + ); + } else { + return ScaffoldMessenger( + key: ScaffoldMessengerKeys.addBookmark, + child: Dialog.fullscreen( + child: Scaffold( + body: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) => [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + sliver: SliverAppBar.large( + pinned: true, + floating: true, + centerTitle: false, + forceElevated: innerBoxIsScrolled, + leading: CloseButton( + onPressed: () => Navigator.pop(context), ), - SliverList.list( - children: const [_ModalContent()], + title: Text( + widget.bookmark != null + ? t.bookmarks.addBookmark.editBookmark + : t.bookmarks.addBookmark.addBookmark, ), - ], + actions: [ + IconButton( + onPressed: ref.watch(bookmarkFormProvider).checkBookmark != null + ? () => ref.read(bookmarkFormProvider.notifier).saveBookmark() + : null, + icon: const Icon(Icons.save_rounded), + tooltip: t.generic.save, + ), + const SizedBox(width: 8), + ], + ), + ), + ], + body: SafeArea( + top: false, + bottom: true, + child: Builder( + builder: (context) => CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), + ), + SliverList.list( + children: const [_ModalContent()], + ), + ], + ), ), ), ), ), ), - ), - ); + ); + } } } @@ -377,7 +425,7 @@ void openBookmarkFormModal({ }) { showGeneralDialog( context: context, - barrierColor: !(width > 700 || !(Platform.isAndroid || Platform.isIOS)) ? Colors.transparent : Colors.black54, + barrierColor: Colors.black54, transitionBuilder: (context, anim1, anim2, child) { return SlideTransition( position: Tween(begin: const Offset(0, 1), end: const Offset(0, 0)).animate( @@ -386,9 +434,6 @@ void openBookmarkFormModal({ child: child, ); }, - pageBuilder: (context, animation, secondaryAnimation) => BookmarkFormModal( - fullscreen: width <= 700, - bookmark: bookmark, - ), + pageBuilder: (context, animation, secondaryAnimation) => const BookmarkFormModal(), ); } diff --git a/lib/screens/onboarding/ui/onboarding.dart b/lib/screens/onboarding/ui/onboarding.dart index a177aef..d0bc944 100644 --- a/lib/screens/onboarding/ui/onboarding.dart +++ b/lib/screens/onboarding/ui/onboarding.dart @@ -7,6 +7,7 @@ import 'package:linkdy/screens/onboarding/ui/server_required.dart'; import 'package:linkdy/screens/onboarding/ui/welcome.dart'; import 'package:linkdy/widgets/system_overlay_style.dart'; +import 'package:linkdy/config/sizes.dart'; import 'package:linkdy/constants/global_keys.dart'; class Onboarding extends ConsumerWidget { @@ -19,14 +20,41 @@ class Onboarding extends ConsumerWidget { key: ScaffoldMessengerKeys.onboarding, child: Scaffold( body: SafeArea( - child: PageView( - controller: ref.watch(onboardingProvider).pageController, - physics: const NeverScrollableScrollPhysics(), - children: const [ - OnboardingWelcome(), - OnboardingServerRequired(), - OnboardingConnect(), - ], + child: LayoutBuilder( + builder: (context, constraints) { + return Center( + child: ConstrainedBox( + constraints: constraints.maxWidth > Sizes.tabletBreakpoint + ? const BoxConstraints(maxWidth: 500, maxHeight: 600) + : const BoxConstraints.expand(), + child: Container( + decoration: constraints.maxWidth > Sizes.tabletBreakpoint + ? BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(28), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 7, + offset: const Offset(0, 3), // changes position of shadow + ), + ], + ) + : null, + child: PageView( + controller: ref.watch(onboardingProvider).pageController, + physics: const NeverScrollableScrollPhysics(), + children: const [ + OnboardingWelcome(), + OnboardingServerRequired(), + OnboardingConnect(), + ], + ), + ), + ), + ); + }, ), ), ), diff --git a/lib/screens/onboarding/ui/welcome.dart b/lib/screens/onboarding/ui/welcome.dart index 544a505..afaf93a 100644 --- a/lib/screens/onboarding/ui/welcome.dart +++ b/lib/screens/onboarding/ui/welcome.dart @@ -5,76 +5,77 @@ import 'package:linkdy/i18n/strings.g.dart'; import 'package:linkdy/screens/onboarding/provider/onboarding.provider.dart'; class OnboardingWelcome extends ConsumerWidget { - const OnboardingWelcome({Key? key}) : super(key: key); + const OnboardingWelcome({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final width = MediaQuery.of(context).size.width; - final height = MediaQuery.of(context).size.height; - - final iconSize = width > height ? height : width; - - return Padding( - padding: const EdgeInsets.all(24), - child: Stack( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, + return LayoutBuilder( + builder: (context, constraints) { + return Padding( + padding: const EdgeInsets.all(24), + child: Stack( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Image.asset( - 'assets/icon/icon1024.png', - width: 50, - height: 50, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + 'assets/icon/icon1024.png', + width: 50, + height: 50, + ), + const SizedBox(height: 24), + Text( + t.onboarding.title, + style: const TextStyle(fontSize: 28), + ), + const SizedBox(height: 16), + Text( + t.onboarding.subtitle, + style: TextStyle( + fontSize: 16, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ], ), - const SizedBox(height: 24), - Text( - t.onboarding.title, - style: const TextStyle(fontSize: 28), - ), - const SizedBox(height: 16), - Text( - t.onboarding.subtitle, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(), + FilledButton( + onPressed: () => ref.read(onboardingProvider.notifier).nextPage(), + child: Row( + children: [ + Text(t.onboarding.start), + const SizedBox(width: 8), + const Icon(Icons.arrow_forward_rounded), + ], + ), + ), + ], ), ], ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const SizedBox(), - FilledButton( - onPressed: () => ref.read(onboardingProvider.notifier).nextPage(), - child: Row( - children: [ - Text(t.onboarding.start), - const SizedBox(width: 8), - const Icon(Icons.arrow_forward_rounded), - ], - ), + Center( + child: Transform.rotate( + angle: 0.7, + child: Icon( + Icons.link_rounded, + size: constraints.maxWidth > constraints.maxHeight + ? constraints.maxHeight + : constraints.maxWidth - 48, + color: Theme.of(context).colorScheme.secondary.withOpacity(0.2), ), - ], + ), ), ], ), - Center( - child: Transform.rotate( - angle: 0.7, - child: Icon( - Icons.link_rounded, - size: iconSize - 48, - color: Theme.of(context).colorScheme.secondary.withOpacity(0.2), - ), - ), - ), - ], - ), + ); + }, ); } } diff --git a/lib/widgets/circle_page_transition.dart b/lib/widgets/circle_page_transition.dart index d8f3190..ef42894 100644 --- a/lib/widgets/circle_page_transition.dart +++ b/lib/widgets/circle_page_transition.dart @@ -14,7 +14,7 @@ Route circlePageBuilder({ fullscreenDialog: fullScreenDialog ?? false, transitionsBuilder: (context, animation, secondaryAnimation, child) { const double beganRadius = 0.0; - final double endRadius = MediaQuery.of(context).size.height * 1.2; + final double endRadius = MediaQuery.of(context).size.height * 1.7; final radiusTweenAnimation = animation.drive( Tween(begin: beganRadius, end: endRadius),