Null safety

This commit is contained in:
Hillel Coren 2023-10-01 14:19:01 +03:00
parent f885b64013
commit 5377657beb
29 changed files with 87 additions and 86 deletions

View File

@ -94,8 +94,7 @@ class TransactionRepository {
.map((transactionId) => { .map((transactionId) => {
'id': transactionId, 'id': transactionId,
if (vendorId.isNotEmpty) 'vendor_id': vendorId, if (vendorId.isNotEmpty) 'vendor_id': vendorId,
if (categoryId.isNotEmpty) if (categoryId.isNotEmpty) 'ninja_category_id': categoryId,
'ninja_category_id': categoryId,
}) })
.toList() .toList()
}, },

View File

@ -368,8 +368,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
data: data.copyWith( data: data.copyWith(
textScaleFactor: state.prefState.textScaleFactor, textScaleFactor: state.prefState.textScaleFactor,
alwaysUse24HourFormat: alwaysUse24HourFormat:
state.company?.settings.enableMilitaryTime ?? state.company?.settings.enableMilitaryTime ?? false,
false,
), ),
child: child!, child: child!,
); );

View File

@ -108,8 +108,7 @@ abstract class DashboardUISettings
String get groupBy; String get groupBy;
bool matchesCurrency(String? match) { bool matchesCurrency(String? match) {
if (currencyId.isEmpty || if (currencyId.isEmpty || currencyId == kCurrencyAll) {
currencyId == kCurrencyAll) {
return true; return true;
} }

View File

@ -491,24 +491,24 @@ void handleDocumentAction(
.dispatch(LoadCredit(creditId: document.parentId))); .dispatch(LoadCredit(creditId: document.parentId)));
break; break;
case EntityType.expense: case EntityType.expense:
completer.future.then<Null>((_) => store.dispatch( completer.future.then<Null>((_) => store
LoadExpense(expenseId: document.parentId))); .dispatch(LoadExpense(expenseId: document.parentId)));
break; break;
case EntityType.group: case EntityType.group:
completer.future.then<Null>((_) => store completer.future.then<Null>((_) => store
.dispatch(LoadGroup(groupId: document.parentId))); .dispatch(LoadGroup(groupId: document.parentId)));
break; break;
case EntityType.invoice: case EntityType.invoice:
completer.future.then<Null>((_) => store.dispatch( completer.future.then<Null>((_) => store
LoadInvoice(invoiceId: document.parentId))); .dispatch(LoadInvoice(invoiceId: document.parentId)));
break; break;
case EntityType.product: case EntityType.product:
completer.future.then<Null>((_) => store.dispatch( completer.future.then<Null>((_) => store
LoadProduct(productId: document.parentId))); .dispatch(LoadProduct(productId: document.parentId)));
break; break;
case EntityType.project: case EntityType.project:
completer.future.then<Null>((_) => store.dispatch( completer.future.then<Null>((_) => store
LoadProject(projectId: document.parentId))); .dispatch(LoadProject(projectId: document.parentId)));
break; break;
case EntityType.purchaseOrder: case EntityType.purchaseOrder:
completer.future.then<Null>((_) => store.dispatch( completer.future.then<Null>((_) => store.dispatch(

View File

@ -728,8 +728,7 @@ void handlePurchaseOrderAction(BuildContext? context,
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
editEntity( editEntity(
entity: entity: state.vendorState.get(purchaseOrder!.vendorId));
state.vendorState.get(purchaseOrder!.vendorId));
}, },
child: Text(localization.editVendor.toUpperCase())) child: Text(localization.editVendor.toUpperCase()))
]); ]);

View File

@ -378,7 +378,8 @@ class _AppBottomBarState extends State<AppBottomBar> {
final settings = state.userCompany.settings.rebuild((b) => b final settings = state.userCompany.settings.rebuild((b) => b
..tableColumns['${widget.entityType}'] = ..tableColumns['${widget.entityType}'] =
BuiltList<String>(selected)); BuiltList<String>(selected));
final userCompany = state.userCompany.rebuild((b) => b..settings.replace(settings)); final userCompany =
state.userCompany.rebuild((b) => b..settings.replace(settings));
final user = final user =
state.user.rebuild((b) => b..userCompany.replace(userCompany)); state.user.rebuild((b) => b..userCompany.replace(userCompany));
final completer = snackBarCompleter<Null>( final completer = snackBarCompleter<Null>(

View File

@ -248,8 +248,7 @@ class LoginVM {
provider: UserEntity.OAUTH_PROVIDER_MICROSOFT, provider: UserEntity.OAUTH_PROVIDER_MICROSOFT,
oneTimePassword: oneTimePassword, oneTimePassword: oneTimePassword,
)); ));
completer.future completer.future.then<Null>((_) => _handleLogin(context: context));
.then<Null>((_) => _handleLogin(context: context));
}, (dynamic error) { }, (dynamic error) {
completer.completeError(error); completer.completeError(error);
}); });
@ -359,8 +358,8 @@ class LoginVM {
email: email.trim(), email: email.trim(),
password: password.trim(), password: password.trim(),
)); ));
completer.future.then<Null>( completer.future
(_) => _handleLogin(context: context, isSignUp: true)); .then<Null>((_) => _handleLogin(context: context, isSignUp: true));
}, },
onRecoverPressed: ( onRecoverPressed: (
BuildContext context, BuildContext context,

View File

@ -46,8 +46,8 @@ class _ClientEditContactsState extends State<ClientEditContacts> {
key: Key(contact!.entityKey), key: Key(contact!.entityKey),
contact: contact, contact: contact,
isDialog: client.contacts.length > 1, isDialog: client.contacts.length > 1,
index: client.contacts.indexOf( index: client.contacts
client.contacts.firstWhere((c) => c.id == contact.id)), .indexOf(client.contacts.firstWhere((c) => c.id == contact.id)),
); );
}); });
} }

View File

@ -137,8 +137,7 @@ class CreditPresenter extends EntityPresenter {
case CreditFields.clientPostalCode: case CreditFields.clientPostalCode:
return Text(client.postalCode); return Text(client.postalCode);
case CreditFields.clientCountry: case CreditFields.clientCountry:
return Text( return Text(state.staticState.countryMap[client.countryId]?.name ?? '');
state.staticState.countryMap[client.countryId]?.name ?? '');
case CreditFields.contactName: case CreditFields.contactName:
case CreditFields.contactEmail: case CreditFields.contactEmail:
final contact = creditContactSelector( final contact = creditContactSelector(

View File

@ -607,7 +607,8 @@ class DashboardPanels extends StatelessWidget {
child: StaggeredGrid.count( child: StaggeredGrid.count(
crossAxisCount: isMobile(context) crossAxisCount: isMobile(context)
? userCompanySettings.dashboardFieldsPerRowMobile ? userCompanySettings.dashboardFieldsPerRowMobile
: userCompanySettings.dashboardFieldsPerRowDesktop, : userCompanySettings
.dashboardFieldsPerRowDesktop,
crossAxisSpacing: 8, crossAxisSpacing: 8,
mainAxisSpacing: 12, mainAxisSpacing: 12,
children: state.userCompany.settings.dashboardFields children: state.userCompany.settings.dashboardFields
@ -1121,7 +1122,8 @@ class __DashboardSettingsState extends State<_DashboardSettings> {
onPressed: () { onPressed: () {
final completer = snackBarCompleter<Null>( final completer = snackBarCompleter<Null>(
context, AppLocalization.of(context)!.savedSettings); context, AppLocalization.of(context)!.savedSettings);
final user = state.user.rebuild((b) => b..userCompany.replace(state.userCompany)); final user = state.user
.rebuild((b) => b..userCompany.replace(state.userCompany));
store.dispatch( store.dispatch(
SaveUserSettingsRequest( SaveUserSettingsRequest(
completer: completer, completer: completer,

View File

@ -315,10 +315,12 @@ class InvoiceEditDesktopState extends State<InvoiceEditDesktop>
InkWell( InkWell(
onLongPress: () => editEntity( onLongPress: () => editEntity(
entity: invoice.isPurchaseOrder entity: invoice.isPurchaseOrder
? vendor: client), ? vendor
: client),
onTap: () => viewEntity( onTap: () => viewEntity(
entity: invoice.isPurchaseOrder entity: invoice.isPurchaseOrder
? vendor: client), ? vendor
: client),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minWidth: double.infinity, minHeight: 40), minWidth: double.infinity, minHeight: 40),
@ -328,7 +330,8 @@ class InvoiceEditDesktopState extends State<InvoiceEditDesktop>
EntityPresenter() EntityPresenter()
.initialize( .initialize(
invoice.isPurchaseOrder invoice.isPurchaseOrder
? vendor: client, ? vendor
: client,
context) context)
.title()!, .title()!,
style: style:

View File

@ -206,7 +206,8 @@ class InvoiceEditVM extends AbstractInvoiceEditVM {
store.dispatch(UpdateInvoice(invoice.rebuild((b) => b store.dispatch(UpdateInvoice(invoice.rebuild((b) => b
..clientId = clientId ?? '' ..clientId = clientId ?? ''
..projectId = projectId ?? '' ..projectId = projectId ?? ''
..invitations.replace(BuiltList<InvitationEntity>(client.emailContacts ..invitations.replace(BuiltList<InvitationEntity>(client
.emailContacts
.map( .map(
(contact) => InvitationEntity(clientContactId: contact!.id)) (contact) => InvitationEntity(clientContactId: contact!.id))
.toList()))))); .toList())))));

View File

@ -190,8 +190,7 @@ class InvoiceListItem extends StatelessWidget {
: ListTile( : ListTile(
onTap: () => onTap != null onTap: () => onTap != null
? onTap!() ? onTap!()
: selectEntity( : selectEntity(entity: invoice, forceView: !showCheckbox),
entity: invoice, forceView: !showCheckbox),
onLongPress: () => onTap != null onLongPress: () => onTap != null
? null ? null
: selectEntity(entity: invoice, longPress: true), : selectEntity(entity: invoice, longPress: true),

View File

@ -164,8 +164,7 @@ class InvoicePresenter extends EntityPresenter {
case InvoiceFields.clientPostalCode: case InvoiceFields.clientPostalCode:
return Text(client.postalCode); return Text(client.postalCode);
case InvoiceFields.clientCountry: case InvoiceFields.clientCountry:
return Text( return Text(state.staticState.countryMap[client.countryId]?.name ?? '');
state.staticState.countryMap[client.countryId]?.name ?? '');
case InvoiceFields.contactName: case InvoiceFields.contactName:
case InvoiceFields.contactEmail: case InvoiceFields.contactEmail:
final contact = invoiceContactSelector( final contact = invoiceContactSelector(

View File

@ -343,7 +343,7 @@ class InvoiceOverview extends StatelessWidget {
EntityListTile( EntityListTile(
isFilter: isFilter, isFilter: isFilter,
entity: payment, entity: payment,
subtitle: amount+ '' + formatDate(payment.date, context), subtitle: amount + '' + formatDate(payment.date, context),
), ),
); );
}); });
@ -373,7 +373,7 @@ class InvoiceOverview extends StatelessWidget {
EntityListTile( EntityListTile(
isFilter: isFilter, isFilter: isFilter,
entity: credit, entity: credit,
subtitle: amount+ '' + formatDate(credit.date, context), subtitle: amount + '' + formatDate(credit.date, context),
), ),
); );
}); });

View File

@ -104,9 +104,8 @@ class _PaymentTermEditState extends State<PaymentTermEdit> {
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
controller: _numDaysController, controller: _numDaysController,
label: localization.numberOfDays, label: localization.numberOfDays,
validator: (value) => value.isEmpty validator: (value) =>
? localization.pleaseEnterAValue value.isEmpty ? localization.pleaseEnterAValue : null,
: null,
onSavePressed: (context) => _onSavePressed(), onSavePressed: (context) => _onSavePressed(),
), ),
], ],

View File

@ -135,8 +135,7 @@ class PurchaseOrderPresenter extends EntityPresenter {
case PurchaseOrderFields.vendorPostalCode: case PurchaseOrderFields.vendorPostalCode:
return Text(vendor.postalCode); return Text(vendor.postalCode);
case PurchaseOrderFields.vendorCountry: case PurchaseOrderFields.vendorCountry:
return Text( return Text(state.staticState.countryMap[client.countryId]?.name ?? '');
state.staticState.countryMap[client.countryId]?.name ?? '');
case PurchaseOrderFields.contactName: case PurchaseOrderFields.contactName:
case PurchaseOrderFields.contactEmail: case PurchaseOrderFields.contactEmail:
final contact = purchaseOrderContactSelector( final contact = purchaseOrderContactSelector(

View File

@ -131,8 +131,7 @@ class QuotePresenter extends EntityPresenter {
case QuoteFields.clientPostalCode: case QuoteFields.clientPostalCode:
return Text(client.postalCode); return Text(client.postalCode);
case QuoteFields.clientCountry: case QuoteFields.clientCountry:
return Text( return Text(state.staticState.countryMap[client.countryId]?.name ?? '');
state.staticState.countryMap[client.countryId]?.name ?? '');
case QuoteFields.contactName: case QuoteFields.contactName:
case QuoteFields.contactEmail: case QuoteFields.contactEmail:
final contact = final contact =

View File

@ -222,8 +222,8 @@ class RecurringInvoiceListItem extends StatelessWidget {
(invoice.nextSendDate.isNotEmpty (invoice.nextSendDate.isNotEmpty
? '' ? ''
: '') + : '') +
formatDate(invoice.nextSendDate, formatDate(
context) + invoice.nextSendDate, context) +
(invoice.documents.isNotEmpty (invoice.documents.isNotEmpty
? ' 📎' ? ' 📎'
: '')) : ''))

View File

@ -646,7 +646,8 @@ class _ReportDataTableState extends State<ReportDataTable> {
final reportResult = viewModel.reportResult!; final reportResult = viewModel.reportResult!;
final reportState = viewModel.reportState; final reportState = viewModel.reportState;
final settings = state.userCompany.settings; final settings = state.userCompany.settings;
final reportSettings = settings.reportSettings.containsKey(reportState.report) final reportSettings =
settings.reportSettings.containsKey(reportState.report)
? settings.reportSettings[reportState.report]! ? settings.reportSettings[reportState.report]!
: ReportSettingsEntity(); : ReportSettingsEntity();
final sortedColumns = reportResult.sortedColumns(reportState); final sortedColumns = reportResult.sortedColumns(reportState);
@ -714,7 +715,8 @@ class TotalsDataTable extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return mt.DataTable( return mt.DataTable(
sortColumnIndex: reportResult!.columns.length > reportSettings!.sortTotalsIndex sortColumnIndex:
reportResult!.columns.length > reportSettings!.sortTotalsIndex
? reportSettings!.sortTotalsIndex ? reportSettings!.sortTotalsIndex
: null, : null,
sortAscending: reportSettings!.sortTotalsAscending ?? true, sortAscending: reportSettings!.sortTotalsAscending ?? true,
@ -1481,7 +1483,8 @@ class ReportResult {
final state = store.state; final state = store.state;
final reportState = state.uiState.reportsUIState; final reportState = state.uiState.reportsUIState;
final settings = state.userCompany.settings; final settings = state.userCompany.settings;
final reportSettings = settings.reportSettings.containsKey(reportState.report) final reportSettings =
settings.reportSettings.containsKey(reportState.report)
? settings.reportSettings[reportState.report]! ? settings.reportSettings[reportState.report]!
: ReportSettingsEntity(); : ReportSettingsEntity();

View File

@ -324,8 +324,8 @@ class _ScheduleEditState extends State<ScheduleEdit> {
HelpText(localization.allClients), HelpText(localization.allClients),
for (var clientId in parameters.clients!) for (var clientId in parameters.clients!)
ListTile( ListTile(
title: Text( title:
state.clientState.get(clientId).displayName), Text(state.clientState.get(clientId).displayName),
trailing: IconButton( trailing: IconButton(
icon: Icon(Icons.clear), icon: Icon(Icons.clear),
onPressed: () { onPressed: () {

View File

@ -77,7 +77,8 @@ class _ScheduleViewState extends State<ScheduleView> {
? localization.allClients ? localization.allClients
: parameters.clients!.length == 1 : parameters.clients!.length == 1
? state.clientState ? state.clientState
.get(parameters.clients!.first).displayName .get(parameters.clients!.first)
.displayName
: '${parameters.clients!.length} ${localization.clients}', : '${parameters.clients!.length} ${localization.clients}',
localization.dateRange: localization.lookup(parameters.dateRange), localization.dateRange: localization.lookup(parameters.dateRange),
localization.showAgingTable: parameters.showAgingTable! localization.showAgingTable: parameters.showAgingTable!

View File

@ -277,8 +277,8 @@ class _UserDetailsState extends State<UserDetails>
.toUpperCase(), .toUpperCase(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
onPressed: state.user.isConnectedToGoogle || onPressed:
state.user.isConnectedToMicrosoft state.user.isConnectedToGoogle || state.user.isConnectedToMicrosoft
? null ? null
: () { : () {
if (state.settingsUIState.isChanged) { if (state.settingsUIState.isChanged) {

View File

@ -106,8 +106,8 @@ class SubscriptionListVM {
EntityAction action) => EntityAction action) =>
handleSubscriptionAction(context, subscriptions, action), handleSubscriptionAction(context, subscriptions, action),
onRefreshed: (context) => _handleRefresh(context), onRefreshed: (context) => _handleRefresh(context),
tableColumns: state.userCompany.settings tableColumns:
.getTableColumns(EntityType.subscription) ?? state.userCompany.settings.getTableColumns(EntityType.subscription) ??
SubscriptionPresenter.getDefaultTableFields(state.userCompany), SubscriptionPresenter.getDefaultTableFields(state.userCompany),
onSortColumn: (field) => store.dispatch(SortSubscriptions(field)), onSortColumn: (field) => store.dispatch(SortSubscriptions(field)),
onClearMultielsect: () => store.dispatch(ClearSubscriptionMultiselect()), onClearMultielsect: () => store.dispatch(ClearSubscriptionMultiselect()),

View File

@ -229,8 +229,7 @@ class _BottomBar extends StatelessWidget {
)!, )!,
), ),
context, context,
clientId: clientId: state.clientState.get(task.clientId).id,
state.clientState.get(task.clientId).id,
)!; )!;
} }

View File

@ -120,7 +120,8 @@ class TransactionListItem extends StatelessWidget {
style: textStyle), style: textStyle),
Text( Text(
state.bankAccountState state.bankAccountState
.get(transaction!.bankAccountId).name, .get(transaction!.bankAccountId)
.name,
maxLines: 3, maxLines: 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: Theme.of(context) style: Theme.of(context)
@ -212,7 +213,8 @@ class TransactionListItem extends StatelessWidget {
Expanded( Expanded(
child: filterMatch == null child: filterMatch == null
? Text(state.bankAccountState ? Text(state.bankAccountState
.get(transaction!.bankAccountId).name + .get(transaction!.bankAccountId)
.name +
'' + '' +
(transaction!.isDeposit (transaction!.isDeposit
? localization!.deposit! ? localization!.deposit!

View File

@ -65,8 +65,8 @@ class _TransactionRuleViewState extends State<TransactionRuleView> {
: localization.disabled, : localization.disabled,
localization.vendor: localization.vendor:
state.vendorState.get(transactionRule.vendorId).name, state.vendorState.get(transactionRule.vendorId).name,
localization.category: state.expenseCategoryState localization.category:
.get(transactionRule.categoryId).name, state.expenseCategoryState.get(transactionRule.categoryId).name,
}), }),
if (transactionRule.rules.isNotEmpty) ...[ if (transactionRule.rules.isNotEmpty) ...[
Padding( Padding(

View File

@ -45,8 +45,8 @@ class _VendorEditContactsState extends State<VendorEditContacts> {
key: Key(contact!.entityKey), key: Key(contact!.entityKey),
contact: contact, contact: contact,
isDialog: vendor.contacts.length > 1, isDialog: vendor.contacts.length > 1,
index: vendor.contacts.indexOf( index: vendor.contacts
vendor.contacts.firstWhere((c) => c.id == contact.id)), .indexOf(vendor.contacts.firstWhere((c) => c.id == contact.id)),
); );
}); });
} }