Correct scrolling in mobile apps

This commit is contained in:
Hillel Coren 2022-01-13 22:04:47 +02:00
parent 734b2033d1
commit 764d51d8b7
2 changed files with 292 additions and 308 deletions

View File

@ -136,6 +136,7 @@ void main({bool isTesting = false}) async {
doWhenWindowReady(() { doWhenWindowReady(() {
final win = appWindow; final win = appWindow;
win.title = 'Invoice Ninja';
//const initialSize = Size(600, 450); //const initialSize = Size(600, 450);
//win.minSize = initialSize; //win.minSize = initialSize;
//win.size = initialSize; //win.size = initialSize;

View File

@ -243,15 +243,6 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
state.prefState.enableDarkMode ? Colors.white : Colors.black87, state.prefState.enableDarkMode ? Colors.white : Colors.black87,
); );
// https://stackoverflow.com/a/69883043/497368
MediaQueryData windowData =
MediaQueryData.fromWindow(WidgetsBinding.instance.window);
windowData = windowData.copyWith(
textScaleFactor: state.prefState.textScaleFactor,
alwaysUse24HourFormat:
state.company?.settings?.enableMilitaryTime ?? false,
);
return StyledToast( return StyledToast(
locale: locale, locale: locale,
duration: Duration(seconds: 3), duration: Duration(seconds: 3),
@ -264,308 +255,300 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
), ),
child: WebSocketRefresh( child: WebSocketRefresh(
companyId: state.company?.id, companyId: state.company?.id,
child: MediaQuery( child: MaterialApp(
data: windowData, builder: (BuildContext context, Widget child) {
child: MaterialApp( final MediaQueryData data = MediaQuery.of(context);
useInheritedMediaQuery: true, return MediaQuery(
scrollBehavior: MyCustomScrollBehavior(), data: data.copyWith(
navigatorKey: navigatorKey, textScaleFactor: state.prefState.textScaleFactor,
supportedLocales: kLanguages alwaysUse24HourFormat:
.map((String locale) => state.company?.settings?.enableMilitaryTime ?? false,
AppLocalization.createLocale(locale)) ),
.toList(), child: child,
debugShowCheckedModeBanner: false, );
//showPerformanceOverlay: true, },
navigatorObservers: [ useInheritedMediaQuery: true,
SentryNavigatorObserver(), scrollBehavior: MyCustomScrollBehavior(),
], navigatorKey: navigatorKey,
localizationsDelegates: [ supportedLocales: kLanguages
const AppLocalizationsDelegate(), .map(
GlobalCupertinoLocalizations.delegate, (String locale) => AppLocalization.createLocale(locale))
GlobalWidgetsLocalizations.delegate, .toList(),
GlobalMaterialLocalizations.delegate debugShowCheckedModeBanner: false,
], //showPerformanceOverlay: true,
home: state.prefState.requireAuthentication && !_authenticated navigatorObservers: [
? LockScreen(onAuthenticatePressed: _authenticate) SentryNavigatorObserver(),
: InitScreen(), ],
locale: locale, localizationsDelegates: [
theme: state.prefState.enableDarkMode const AppLocalizationsDelegate(),
? ThemeData( GlobalCupertinoLocalizations.delegate,
colorScheme: ColorScheme.dark().copyWith( GlobalWidgetsLocalizations.delegate,
secondary: accentColor, GlobalMaterialLocalizations.delegate
primary: accentColor, ],
), home: state.prefState.requireAuthentication && !_authenticated
pageTransitionsTheme: pageTransitionsTheme, ? LockScreen(onAuthenticatePressed: _authenticate)
indicatorColor: accentColor, : InitScreen(),
textSelectionTheme: TextSelectionThemeData( locale: locale,
selectionHandleColor: accentColor, theme: state.prefState.enableDarkMode
), ? ThemeData(
fontFamily: fontFamily, colorScheme: ColorScheme.dark().copyWith(
backgroundColor: Colors.black, secondary: accentColor,
canvasColor: Colors.black, primary: accentColor,
cardColor: const Color(0xFF1B1C1E),
bottomAppBarColor: const Color(0xFF1B1C1E),
primaryColorDark: Colors.black,
textButtonTheme:
TextButtonThemeData(style: textButtonTheme),
outlinedButtonTheme: OutlinedButtonThemeData(
style: outlinedButtonTheme),
)
: ThemeData(
colorScheme: ColorScheme.fromSwatch()
.copyWith(secondary: accentColor),
pageTransitionsTheme: pageTransitionsTheme,
primaryColor: accentColor,
indicatorColor: accentColor,
textSelectionTheme: TextSelectionThemeData(
selectionColor: accentColor,
),
fontFamily: fontFamily,
backgroundColor: Colors.white,
canvasColor: Colors.white,
cardColor: Colors.white,
bottomAppBarColor: Colors.white,
primaryColorDark: hasAccentColor
? accentColor
: const Color(0xFF0D5D91),
primaryColorLight: hasAccentColor
? accentColor
: const Color(0xFF5dabf4),
scaffoldBackgroundColor: const Color(0xFFE4E8EB),
tabBarTheme: TabBarTheme(
labelColor:
hasAccentColor ? Colors.white : Colors.black,
unselectedLabelColor: hasAccentColor
? Colors.white.withOpacity(.65)
: Colors.black.withOpacity(.65),
),
iconTheme: IconThemeData(
color: hasAccentColor ? null : accentColor,
),
appBarTheme: AppBarTheme(
color: hasAccentColor ? accentColor : Colors.white,
iconTheme: IconThemeData(
color:
hasAccentColor ? Colors.white : accentColor,
),
titleTextStyle: TextStyle(
fontSize: 20,
color: hasAccentColor
? Colors.white
: Colors.black),
),
textButtonTheme:
TextButtonThemeData(style: textButtonTheme),
outlinedButtonTheme: OutlinedButtonThemeData(
style: outlinedButtonTheme),
), ),
title: kAppName, pageTransitionsTheme: pageTransitionsTheme,
onGenerateRoute: isMobile(context) ? null : generateRoute, indicatorColor: accentColor,
routes: isMobile(context) textSelectionTheme: TextSelectionThemeData(
? { selectionHandleColor: accentColor,
LoginScreen.route: (context) => LoginScreen(), ),
MainScreen.route: (context) => MainScreen(), fontFamily: fontFamily,
DashboardScreenBuilder.route: (context) => backgroundColor: Colors.black,
ChangeLayoutBanner( canvasColor: Colors.black,
suggestedLayout: AppLayout.mobile, cardColor: const Color(0xFF1B1C1E),
appLayout: state.prefState.appLayout, bottomAppBarColor: const Color(0xFF1B1C1E),
child: DashboardScreenBuilder(), primaryColorDark: Colors.black,
), textButtonTheme:
ProductScreen.route: (context) => TextButtonThemeData(style: textButtonTheme),
ProductScreenBuilder(), outlinedButtonTheme:
ProductViewScreen.route: (context) => OutlinedButtonThemeData(style: outlinedButtonTheme),
ProductViewScreen(), )
ProductEditScreen.route: (context) => : ThemeData(
ProductEditScreen(), colorScheme: ColorScheme.fromSwatch()
ClientScreen.route: (context) => .copyWith(secondary: accentColor),
ClientScreenBuilder(), pageTransitionsTheme: pageTransitionsTheme,
ClientViewScreen.route: (context) => primaryColor: accentColor,
ClientViewScreen(), indicatorColor: accentColor,
ClientEditScreen.route: (context) => textSelectionTheme: TextSelectionThemeData(
ClientEditScreen(), selectionColor: accentColor,
ClientPdfScreen.route: (context) => ClientPdfScreen(), ),
InvoiceScreen.route: (context) => fontFamily: fontFamily,
InvoiceScreenBuilder(), backgroundColor: Colors.white,
InvoiceViewScreen.route: (context) => canvasColor: Colors.white,
InvoiceViewScreen(), cardColor: Colors.white,
InvoiceEditScreen.route: (context) => bottomAppBarColor: Colors.white,
InvoiceEditScreen(), primaryColorDark: hasAccentColor
InvoiceEmailScreen.route: (context) => ? accentColor
InvoiceEmailScreen(), : const Color(0xFF0D5D91),
InvoicePdfScreen.route: (context) => primaryColorLight: hasAccentColor
InvoicePdfScreen(), ? accentColor
DocumentScreen.route: (context) => : const Color(0xFF5dabf4),
DocumentScreenBuilder(), scaffoldBackgroundColor: const Color(0xFFE4E8EB),
DocumentViewScreen.route: (context) => tabBarTheme: TabBarTheme(
DocumentViewScreen(), labelColor:
DocumentEditScreen.route: (context) => hasAccentColor ? Colors.white : Colors.black,
DocumentEditScreen(), unselectedLabelColor: hasAccentColor
ExpenseScreen.route: (context) => ? Colors.white.withOpacity(.65)
ExpenseScreenBuilder(), : Colors.black.withOpacity(.65),
ExpenseViewScreen.route: (context) => ),
ExpenseViewScreen(), iconTheme: IconThemeData(
ExpenseEditScreen.route: (context) => color: hasAccentColor ? null : accentColor,
ExpenseEditScreen(), ),
VendorScreen.route: (context) => appBarTheme: AppBarTheme(
VendorScreenBuilder(), color: hasAccentColor ? accentColor : Colors.white,
VendorViewScreen.route: (context) => iconTheme: IconThemeData(
VendorViewScreen(), color: hasAccentColor ? Colors.white : accentColor,
VendorEditScreen.route: (context) => ),
VendorEditScreen(), titleTextStyle: TextStyle(
TaskScreen.route: (context) => TaskScreenBuilder(), fontSize: 20,
TaskViewScreen.route: (context) => TaskViewScreen(), color:
TaskEditScreen.route: (context) => TaskEditScreen(), hasAccentColor ? Colors.white : Colors.black),
ProjectScreen.route: (context) => ),
ProjectScreenBuilder(), textButtonTheme:
ProjectViewScreen.route: (context) => TextButtonThemeData(style: textButtonTheme),
ProjectViewScreen(), outlinedButtonTheme:
ProjectEditScreen.route: (context) => OutlinedButtonThemeData(style: outlinedButtonTheme),
ProjectEditScreen(), ),
PaymentScreen.route: (context) => title: kAppName,
PaymentScreenBuilder(), onGenerateRoute: isMobile(context) ? null : generateRoute,
PaymentViewScreen.route: (context) => routes: isMobile(context)
PaymentViewScreen(), ? {
PaymentEditScreen.route: (context) => LoginScreen.route: (context) => LoginScreen(),
PaymentEditScreen(), MainScreen.route: (context) => MainScreen(),
PaymentRefundScreen.route: (context) => DashboardScreenBuilder.route: (context) =>
PaymentRefundScreen(), ChangeLayoutBanner(
QuoteScreen.route: (context) => QuoteScreenBuilder(), suggestedLayout: AppLayout.mobile,
QuoteViewScreen.route: (context) => QuoteViewScreen(), appLayout: state.prefState.appLayout,
QuoteEditScreen.route: (context) => QuoteEditScreen(), child: DashboardScreenBuilder(),
QuoteEmailScreen.route: (context) => ),
QuoteEmailScreen(), ProductScreen.route: (context) =>
QuotePdfScreen.route: (context) => QuotePdfScreen(), ProductScreenBuilder(),
// STARTER: routes - do not remove comment ProductViewScreen.route: (context) =>
RecurringExpenseScreen.route: (context) => ProductViewScreen(),
RecurringExpenseScreenBuilder(), ProductEditScreen.route: (context) =>
RecurringExpenseViewScreen.route: (context) => ProductEditScreen(),
RecurringExpenseViewScreen(), ClientScreen.route: (context) => ClientScreenBuilder(),
RecurringExpenseEditScreen.route: (context) => ClientViewScreen.route: (context) => ClientViewScreen(),
RecurringExpenseEditScreen(), ClientEditScreen.route: (context) => ClientEditScreen(),
ClientPdfScreen.route: (context) => ClientPdfScreen(),
InvoiceScreen.route: (context) =>
InvoiceScreenBuilder(),
InvoiceViewScreen.route: (context) =>
InvoiceViewScreen(),
InvoiceEditScreen.route: (context) =>
InvoiceEditScreen(),
InvoiceEmailScreen.route: (context) =>
InvoiceEmailScreen(),
InvoicePdfScreen.route: (context) => InvoicePdfScreen(),
DocumentScreen.route: (context) =>
DocumentScreenBuilder(),
DocumentViewScreen.route: (context) =>
DocumentViewScreen(),
DocumentEditScreen.route: (context) =>
DocumentEditScreen(),
ExpenseScreen.route: (context) =>
ExpenseScreenBuilder(),
ExpenseViewScreen.route: (context) =>
ExpenseViewScreen(),
ExpenseEditScreen.route: (context) =>
ExpenseEditScreen(),
VendorScreen.route: (context) => VendorScreenBuilder(),
VendorViewScreen.route: (context) => VendorViewScreen(),
VendorEditScreen.route: (context) => VendorEditScreen(),
TaskScreen.route: (context) => TaskScreenBuilder(),
TaskViewScreen.route: (context) => TaskViewScreen(),
TaskEditScreen.route: (context) => TaskEditScreen(),
ProjectScreen.route: (context) =>
ProjectScreenBuilder(),
ProjectViewScreen.route: (context) =>
ProjectViewScreen(),
ProjectEditScreen.route: (context) =>
ProjectEditScreen(),
PaymentScreen.route: (context) =>
PaymentScreenBuilder(),
PaymentViewScreen.route: (context) =>
PaymentViewScreen(),
PaymentEditScreen.route: (context) =>
PaymentEditScreen(),
PaymentRefundScreen.route: (context) =>
PaymentRefundScreen(),
QuoteScreen.route: (context) => QuoteScreenBuilder(),
QuoteViewScreen.route: (context) => QuoteViewScreen(),
QuoteEditScreen.route: (context) => QuoteEditScreen(),
QuoteEmailScreen.route: (context) => QuoteEmailScreen(),
QuotePdfScreen.route: (context) => QuotePdfScreen(),
// STARTER: routes - do not remove comment
RecurringExpenseScreen.route: (context) =>
RecurringExpenseScreenBuilder(),
RecurringExpenseViewScreen.route: (context) =>
RecurringExpenseViewScreen(),
RecurringExpenseEditScreen.route: (context) =>
RecurringExpenseEditScreen(),
SubscriptionScreen.route: (context) => SubscriptionScreen.route: (context) =>
SubscriptionScreenBuilder(), SubscriptionScreenBuilder(),
SubscriptionViewScreen.route: (context) => SubscriptionViewScreen.route: (context) =>
SubscriptionViewScreen(), SubscriptionViewScreen(),
SubscriptionEditScreen.route: (context) => SubscriptionEditScreen.route: (context) =>
SubscriptionEditScreen(), SubscriptionEditScreen(),
TaskStatusScreen.route: (context) => TaskStatusScreen.route: (context) =>
TaskStatusScreenBuilder(), TaskStatusScreenBuilder(),
TaskStatusViewScreen.route: (context) => TaskStatusViewScreen.route: (context) =>
TaskStatusViewScreen(), TaskStatusViewScreen(),
TaskStatusEditScreen.route: (context) => TaskStatusEditScreen.route: (context) =>
TaskStatusEditScreen(), TaskStatusEditScreen(),
ExpenseCategoryScreen.route: (context) => ExpenseCategoryScreen.route: (context) =>
ExpenseCategoryScreenBuilder(), ExpenseCategoryScreenBuilder(),
ExpenseCategoryViewScreen.route: (context) => ExpenseCategoryViewScreen.route: (context) =>
ExpenseCategoryViewScreen(), ExpenseCategoryViewScreen(),
ExpenseCategoryEditScreen.route: (context) => ExpenseCategoryEditScreen.route: (context) =>
ExpenseCategoryEditScreen(), ExpenseCategoryEditScreen(),
RecurringInvoiceScreen.route: (context) => RecurringInvoiceScreen.route: (context) =>
RecurringInvoiceScreenBuilder(), RecurringInvoiceScreenBuilder(),
RecurringInvoiceViewScreen.route: (context) => RecurringInvoiceViewScreen.route: (context) =>
RecurringInvoiceViewScreen(), RecurringInvoiceViewScreen(),
RecurringInvoiceEditScreen.route: (context) => RecurringInvoiceEditScreen.route: (context) =>
RecurringInvoiceEditScreen(), RecurringInvoiceEditScreen(),
RecurringInvoicePdfScreen.route: (context) => RecurringInvoicePdfScreen.route: (context) =>
RecurringInvoicePdfScreen(), RecurringInvoicePdfScreen(),
WebhookScreen.route: (context) => WebhookScreen.route: (context) =>
WebhookScreenBuilder(), WebhookScreenBuilder(),
WebhookViewScreen.route: (context) => WebhookViewScreen.route: (context) =>
WebhookViewScreen(), WebhookViewScreen(),
WebhookEditScreen.route: (context) => WebhookEditScreen.route: (context) =>
WebhookEditScreen(), WebhookEditScreen(),
TokenScreen.route: (context) => TokenScreenBuilder(), TokenScreen.route: (context) => TokenScreenBuilder(),
TokenViewScreen.route: (context) => TokenViewScreen(), TokenViewScreen.route: (context) => TokenViewScreen(),
TokenEditScreen.route: (context) => TokenEditScreen(), TokenEditScreen.route: (context) => TokenEditScreen(),
PaymentTermScreen.route: (context) => PaymentTermScreen.route: (context) =>
PaymentTermScreenBuilder(), PaymentTermScreenBuilder(),
PaymentTermEditScreen.route: (context) => PaymentTermEditScreen.route: (context) =>
PaymentTermEditScreen(), PaymentTermEditScreen(),
PaymentTermViewScreen.route: (context) => PaymentTermViewScreen.route: (context) =>
PaymentTermViewScreen(), PaymentTermViewScreen(),
DesignScreen.route: (context) => DesignScreen.route: (context) => DesignScreenBuilder(),
DesignScreenBuilder(), DesignViewScreen.route: (context) => DesignViewScreen(),
DesignViewScreen.route: (context) => DesignEditScreen.route: (context) => DesignEditScreen(),
DesignViewScreen(), CreditScreen.route: (context) => CreditScreenBuilder(),
DesignEditScreen.route: (context) => CreditViewScreen.route: (context) => CreditViewScreen(),
DesignEditScreen(), CreditEditScreen.route: (context) => CreditEditScreen(),
CreditScreen.route: (context) => CreditEmailScreen.route: (context) =>
CreditScreenBuilder(), CreditEmailScreen(),
CreditViewScreen.route: (context) => CreditPdfScreen.route: (context) => CreditPdfScreen(),
CreditViewScreen(), UserScreen.route: (context) => UserScreenBuilder(),
CreditEditScreen.route: (context) => UserViewScreen.route: (context) => UserViewScreen(),
CreditEditScreen(), UserEditScreen.route: (context) => UserEditScreen(),
CreditEmailScreen.route: (context) => GroupSettingsScreen.route: (context) =>
CreditEmailScreen(), GroupScreenBuilder(),
CreditPdfScreen.route: (context) => CreditPdfScreen(), GroupViewScreen.route: (context) => GroupViewScreen(),
UserScreen.route: (context) => UserScreenBuilder(), GroupEditScreen.route: (context) => GroupEditScreen(),
UserViewScreen.route: (context) => UserViewScreen(), SettingsScreen.route: (context) =>
UserEditScreen.route: (context) => UserEditScreen(), SettingsScreenBuilder(),
GroupSettingsScreen.route: (context) => ReportsScreen.route: (context) =>
GroupScreenBuilder(), ReportsScreenBuilder(),
GroupViewScreen.route: (context) => GroupViewScreen(), CompanyDetailsScreen.route: (context) =>
GroupEditScreen.route: (context) => GroupEditScreen(), CompanyDetailsScreen(),
SettingsScreen.route: (context) => UserDetailsScreen.route: (context) =>
SettingsScreenBuilder(), UserDetailsScreen(),
ReportsScreen.route: (context) => LocalizationScreen.route: (context) =>
ReportsScreenBuilder(), LocalizationScreen(),
CompanyDetailsScreen.route: (context) => OnlinePaymentsScreen.route: (context) =>
CompanyDetailsScreen(), OnlinePaymentsScreen(),
UserDetailsScreen.route: (context) => CompanyGatewayScreen.route: (context) =>
UserDetailsScreen(), CompanyGatewayScreenBuilder(),
LocalizationScreen.route: (context) => CompanyGatewayViewScreen.route: (context) =>
LocalizationScreen(), CompanyGatewayViewScreen(),
OnlinePaymentsScreen.route: (context) => CompanyGatewayEditScreen.route: (context) =>
OnlinePaymentsScreen(), CompanyGatewayEditScreen(),
CompanyGatewayScreen.route: (context) => TaxSettingsScreen.route: (context) =>
CompanyGatewayScreenBuilder(), TaxSettingsScreen(),
CompanyGatewayViewScreen.route: (context) => TaxRateSettingsScreen.route: (context) =>
CompanyGatewayViewScreen(), TaxRateScreenBuilder(),
CompanyGatewayEditScreen.route: (context) => TaxRateViewScreen.route: (context) =>
CompanyGatewayEditScreen(), TaxRateViewScreen(),
TaxSettingsScreen.route: (context) => TaxRateEditScreen.route: (context) =>
TaxSettingsScreen(), TaxRateEditScreen(),
TaxRateSettingsScreen.route: (context) => ProductSettingsScreen.route: (context) =>
TaxRateScreenBuilder(), ProductSettingsScreen(),
TaxRateViewScreen.route: (context) => ExpenseSettingsScreen.route: (context) =>
TaxRateViewScreen(), ExpenseSettingsScreen(),
TaxRateEditScreen.route: (context) => TaskSettingsScreen.route: (context) =>
TaxRateEditScreen(), TaskSettingsScreen(),
ProductSettingsScreen.route: (context) => ImportExportScreen.route: (context) =>
ProductSettingsScreen(), ImportExportScreen(),
ExpenseSettingsScreen.route: (context) => DeviceSettingsScreen.route: (context) =>
ExpenseSettingsScreen(), DeviceSettingsScreen(),
TaskSettingsScreen.route: (context) => AccountManagementScreen.route: (context) =>
TaskSettingsScreen(), AccountManagementScreen(),
ImportExportScreen.route: (context) => CustomFieldsScreen.route: (context) =>
ImportExportScreen(), CustomFieldsScreen(),
DeviceSettingsScreen.route: (context) => GeneratedNumbersScreen.route: (context) =>
DeviceSettingsScreen(), GeneratedNumbersScreen(),
AccountManagementScreen.route: (context) => WorkflowSettingsScreen.route: (context) =>
AccountManagementScreen(), WorkflowSettingsScreen(),
CustomFieldsScreen.route: (context) => InvoiceDesignScreen.route: (context) =>
CustomFieldsScreen(), InvoiceDesignScreen(),
GeneratedNumbersScreen.route: (context) => ClientPortalScreen.route: (context) =>
GeneratedNumbersScreen(), ClientPortalScreen(),
WorkflowSettingsScreen.route: (context) => EmailSettingsScreen.route: (context) =>
WorkflowSettingsScreen(), EmailSettingsScreen(),
InvoiceDesignScreen.route: (context) => TemplatesAndRemindersScreen.route: (context) =>
InvoiceDesignScreen(), TemplatesAndRemindersScreen(),
ClientPortalScreen.route: (context) => CreditCardsAndBanksScreen.route: (context) =>
ClientPortalScreen(), CreditCardsAndBanksScreen(),
EmailSettingsScreen.route: (context) => DataVisualizationsScreen.route: (context) =>
EmailSettingsScreen(), DataVisualizationsScreen(),
TemplatesAndRemindersScreen.route: (context) => }
TemplatesAndRemindersScreen(), : {},
CreditCardsAndBanksScreen.route: (context) =>
CreditCardsAndBanksScreen(),
DataVisualizationsScreen.route: (context) =>
DataVisualizationsScreen(),
}
: {},
),
), ),
), ),
); );