Null safety

This commit is contained in:
Hillel Coren 2023-10-01 14:57:32 +03:00
parent df7e3576b1
commit fbd8b8f5ba
18 changed files with 85 additions and 88 deletions

View File

@ -236,18 +236,17 @@ class _CompanyGatewayEditState extends State<CompanyGatewayEdit>
AppDropdownButton<String>(
labelText: localization.captureCard,
value: companyGateway.tokenBilling,
selectedItemBuilder:
(companyGateway.tokenBilling ?? '').isEmpty
? null
: (context) => [
SettingsEntity.AUTO_BILL_ALWAYS,
SettingsEntity.AUTO_BILL_OPT_OUT,
SettingsEntity.AUTO_BILL_OPT_IN,
SettingsEntity.AUTO_BILL_OFF,
]
.map((type) =>
Text(localization.lookup(type)!))
.toList(),
selectedItemBuilder: companyGateway.tokenBilling.isEmpty
? null
: (context) => [
SettingsEntity.AUTO_BILL_ALWAYS,
SettingsEntity.AUTO_BILL_OPT_OUT,
SettingsEntity.AUTO_BILL_OPT_IN,
SettingsEntity.AUTO_BILL_OFF,
]
.map((type) =>
Text(localization.lookup(type)!))
.toList(),
onChanged: (dynamic value) => viewModel.onChanged(
companyGateway
.rebuild((b) => b..tokenBilling = value)),
@ -767,11 +766,11 @@ class _LimitEditorState extends State<LimitEditor> {
_minController!.text = settings.minLimit == -1
? ''
: formatNumber((settings.minLimit ?? 0).toDouble(), context,
: formatNumber(settings.minLimit.toDouble(), context,
formatNumberType: FormatNumberType.inputMoney)!;
_maxController!.text = settings.maxLimit == -1
? ''
: formatNumber((settings.maxLimit ?? 0).toDouble(), context,
: formatNumber(settings.maxLimit.toDouble(), context,
formatNumberType: FormatNumberType.inputMoney)!;
_minController!.addListener(_onTextChange);

View File

@ -116,7 +116,7 @@ class CreditListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
(credit.number ?? '').isEmpty
credit.number.isEmpty
? localization!.pending
: credit.number,
style: textStyle,
@ -211,7 +211,7 @@ class CreditListItem extends StatelessWidget {
children: <Widget>[
Expanded(
child: filterMatch == null
? Text((((credit.number ?? '').isEmpty
? Text(((credit.number.isEmpty
? localization!.pending
: credit.number) +
'' +

View File

@ -70,9 +70,8 @@ class CreditPresenter extends EntityPresenter {
case CreditFields.status:
return EntityStatusChip(entity: credit, showState: true);
case CreditFields.number:
return Text((credit.number ?? '').isEmpty
? localization!.pending
: credit.number);
return Text(
credit.number.isEmpty ? localization!.pending : credit.number);
case CreditFields.client:
return LinkTextRelatedEntity(entity: client, relation: credit);
case CreditFields.date:
@ -146,7 +145,7 @@ class CreditPresenter extends EntityPresenter {
return SizedBox();
}
if (field == CreditFields.contactName) {
return Text(contact.fullName ?? '');
return Text(contact.fullName);
}
return CopyToClipboard(
value: contact.email,

View File

@ -865,7 +865,7 @@ class __DashboardPanelState extends State<_DashboardPanel> {
title: widget.title,
onDateSelected: widget.onDateSelected,
onSelected: widget.onSelected as dynamic Function(),
currencyId: (settings.currencyId ?? '').isNotEmpty
currencyId: settings.currencyId.isNotEmpty
? settings.currencyId
: state.company!.currencyId,
);
@ -996,7 +996,7 @@ class __OverviewPanelState extends State<_OverviewPanel> {
title: widget.title,
onSelected: () => null,
onDateSelected: widget.onDateSelected,
currencyId: (settings.currencyId ?? '').isNotEmpty
currencyId: settings.currencyId.isNotEmpty
? settings.currencyId
: state.company!.currencyId,
isOverview: true,

View File

@ -405,7 +405,7 @@ class ExpenseSidbar extends StatelessWidget {
itemCount: recentExpenses.length,
itemBuilder: (BuildContext context, int index) {
return ExpenseListItem(
expense: recentExpenses[index],
expense: recentExpenses[index]!,
showCheckbox: false,
showSelected: false,
);

View File

@ -140,7 +140,7 @@ class _DesignEditState extends State<DesignEdit>
kDesignBody: _bodyController.text.trim(),
kDesignFooter: _footerController.text.trim(),
kDesignProducts: _productsController.text.trim(),
kDesignTasks: _tasksController.text.trim() ?? '',
kDesignTasks: _tasksController.text.trim(),
kDesignIncludes: _includesController.text.trim()
})));

View File

@ -180,7 +180,7 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
(client as ClientEntity).settings.currencyId ??
company.currencyId;
viewModel.onChanged!(expense.rebuild((b) => b
..clientId = client.id ?? ''
..clientId = client.id
..invoiceCurrencyId = currencyId));
},
onAddPressed: (completer) {
@ -195,7 +195,7 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
final project = store.state.projectState.get(selectedId);
viewModel.onChanged!(expense.rebuild((b) => b
..projectId = project.id
..clientId = (project.clientId ?? '').isNotEmpty
..clientId = project.clientId.isNotEmpty
? project.clientId
: expense.clientId));
},
@ -361,7 +361,7 @@ class ExpenseEditDetailsState extends State<ExpenseEditDetails> {
))
.toList()),
DatePicker(
labelText: (expense.lastSentDate ?? '').isNotEmpty
labelText: expense.lastSentDate.isNotEmpty
? localization.nextSendDate
: localization.startDate,
onSelected: (date, _) {

View File

@ -33,7 +33,7 @@ class ExpenseListItem extends StatelessWidget {
final Function(bool?)? onCheckboxChanged;
final GestureTapCallback? onTap;
final ExpenseEntity? expense;
final ExpenseEntity expense;
final String? filter;
final bool showCheckbox;
final bool isDismissible;
@ -48,11 +48,11 @@ class ExpenseListItem extends StatelessWidget {
final uiState = state.uiState;
final expenseUIState = uiState.expenseUIState;
final listUIState = expenseUIState.listUIState;
final client = state.clientState.get(expense!.clientId!);
final vendor = state.vendorState.get(expense!.vendorId!);
final category = state.expenseCategoryState.get(expense!.categoryId);
final client = state.clientState.get(expense.clientId!);
final vendor = state.vendorState.get(expense.vendorId!);
final category = state.expenseCategoryState.get(expense.categoryId);
final filterMatch = filter != null && filter!.isNotEmpty
? (expense!.matchesFilterValue(filter) ??
? (expense.matchesFilterValue(filter) ??
client.matchesFilterValue(filter))
: null;
final textStyle = TextStyle(fontSize: 16);
@ -63,7 +63,7 @@ class ExpenseListItem extends StatelessWidget {
subtitle = filterMatch;
} else if (client != null || vendor != null || category != null) {
final parts = <String>[
formatDate(expense!.date, context),
formatDate(expense.date, context),
];
if (category.isOld) {
parts.add(category.name);
@ -82,7 +82,7 @@ class ExpenseListItem extends StatelessWidget {
isDismissible: isDismissible,
isSelected: isDesktop(context) &&
showSelected &&
expense!.id ==
expense.id ==
(uiState.isEditing
? expenseUIState.editing!.id
: expenseUIState.selectedId),
@ -93,10 +93,10 @@ class ExpenseListItem extends StatelessWidget {
return constraints.maxWidth > kTableListWidthCutoff
? InkWell(
onTap: () =>
onTap != null ? onTap!() : selectEntity(entity: expense!),
onTap != null ? onTap!() : selectEntity(entity: expense),
onLongPress: () => onTap != null
? null
: selectEntity(entity: expense!, longPress: true),
: selectEntity(entity: expense, longPress: true),
child: Padding(
padding: const EdgeInsets.only(
left: 10,
@ -125,7 +125,7 @@ class ExpenseListItem extends StatelessWidget {
),
)
: ActionMenuButton(
entityActions: expense!.getActions(
entityActions: expense.getActions(
userCompany: state.userCompany,
includeEdit: true,
),
@ -141,11 +141,11 @@ class ExpenseListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
expense!.number,
expense.number,
style: textStyle,
overflow: TextOverflow.ellipsis,
),
if (!expense!.isActive) EntityStateLabel(expense)
if (!expense.isActive) EntityStateLabel(expense)
],
),
),
@ -155,12 +155,12 @@ class ExpenseListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
(expense!.publicNotes ?? '') +
(expense!.documents.isNotEmpty ? ' 📎' : ''),
expense.publicNotes +
(expense.documents.isNotEmpty ? ' 📎' : ''),
style: textStyle,
maxLines: 1,
),
Text(subtitle ?? filterMatch!,
Text(subtitle,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
@ -175,8 +175,8 @@ class ExpenseListItem extends StatelessWidget {
),
SizedBox(width: 8),
Text(
formatNumber(expense!.grossAmount, context,
currencyId: expense!.currencyId)!,
formatNumber(expense.grossAmount, context,
currencyId: expense.currencyId)!,
style: textStyle,
textAlign: TextAlign.end,
),
@ -188,10 +188,10 @@ class ExpenseListItem extends StatelessWidget {
)
: ListTile(
onTap: () =>
onTap != null ? onTap!() : selectEntity(entity: expense!),
onTap != null ? onTap!() : selectEntity(entity: expense),
onLongPress: () => onTap != null
? null
: selectEntity(entity: expense!, longPress: true),
: selectEntity(entity: expense, longPress: true),
leading: showCheckbox
? IgnorePointer(
ignoring: listUIState.isInMultiselect(),
@ -210,17 +210,17 @@ class ExpenseListItem extends StatelessWidget {
children: <Widget>[
Expanded(
child: Text(
(expense!.publicNotes.isEmpty
? expense!.number
: expense!.publicNotes) +
(expense!.documents.isNotEmpty ? ' 📎' : ''),
(expense.publicNotes.isEmpty
? expense.number
: expense.publicNotes) +
(expense.documents.isNotEmpty ? ' 📎' : ''),
style: Theme.of(context).textTheme.titleMedium,
maxLines: 1,
),
),
Text(
formatNumber(expense!.amount, context,
currencyId: expense!.currencyId)!,
formatNumber(expense.amount, context,
currencyId: expense.currencyId)!,
style: Theme.of(context).textTheme.titleMedium),
],
),
@ -247,14 +247,14 @@ class ExpenseListItem extends StatelessWidget {
),
Text(
localization!.lookup(
kExpenseStatuses[expense!.calculatedStatusId])!,
kExpenseStatuses[expense.calculatedStatusId])!,
style: TextStyle(
color: category.color.isNotEmpty &&
category.color != '#fff'
? convertHexStringToColor(category.color)
: ExpenseStatusColors(
state.prefState.colorThemeModel)
.colors[expense!.calculatedStatusId])),
.colors[expense.calculatedStatusId])),
],
),
);

View File

@ -456,19 +456,19 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
overflow: TextOverflow.ellipsis,
);
} else if (column == COLUMN_CUSTOM1) {
return Text(item.customValue1 ?? '');
return Text(item.customValue1);
} else if (column == COLUMN_CUSTOM2) {
return Text(item.customValue2 ?? '');
return Text(item.customValue2);
} else if (column == COLUMN_CUSTOM3) {
return Text(item.customValue3 ?? '');
return Text(item.customValue3);
} else if (column == COLUMN_CUSTOM4) {
return Text(item.customValue4 ?? '');
return Text(item.customValue4);
} else if (column == COLUMN_TAX1) {
return Text(item.taxName1 ?? '');
return Text(item.taxName1);
} else if (column == COLUMN_TAX2) {
return Text(item.taxName2 ?? '');
return Text(item.taxName2);
} else if (column == COLUMN_TAX3) {
return Text(item.taxName3 ?? '');
return Text(item.taxName3);
} else if (column == COLUMN_TAX_CATEGORY) {
return Text(localization
.lookup(kTaxCategories[item.taxCategoryId])!);

View File

@ -126,7 +126,7 @@ class InvoiceEditVM extends AbstractInvoiceEditVM {
for (int i = 0; i < invoice.lineItems.length; i++) {
final lineItem = invoice.lineItems[i]!;
final task = state.taskState.get(lineItem.taskId ?? '');
if ((task.clientId ?? '').isNotEmpty && task.clientId != clientId) {
if (task.clientId.isNotEmpty && task.clientId != clientId) {
showDialog<ErrorDialog>(
context: navigatorKey.currentContext!,
builder: (BuildContext context) {
@ -204,8 +204,8 @@ class InvoiceEditVM extends AbstractInvoiceEditVM {
if ((clientId ?? '').isNotEmpty || (projectId ?? '').isNotEmpty) {
final client = state.clientState.get(clientId!);
store.dispatch(UpdateInvoice(invoice.rebuild((b) => b
..clientId = clientId ?? ''
..projectId = projectId ?? ''
..clientId = clientId
..projectId = projectId
..invitations.replace(BuiltList<InvitationEntity>(client
.emailContacts
.map(

View File

@ -134,7 +134,7 @@ class InvoiceListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
(invoice.number ?? '').isEmpty
invoice.number.isEmpty
? localization.pending
: invoice.number,
style: textStyle,
@ -236,7 +236,7 @@ class InvoiceListItem extends StatelessWidget {
children: <Widget>[
Expanded(
child: filterMatch == null
? Text((((invoice.number ?? '').isEmpty
? Text(((invoice.number.isEmpty
? localization.pending
: invoice.number) +
'' +

View File

@ -79,9 +79,8 @@ class InvoicePresenter extends EntityPresenter {
case InvoiceFields.status:
return EntityStatusChip(entity: invoice, showState: true);
case InvoiceFields.number:
return Text((invoice.number ?? '').isEmpty
? localization!.pending
: invoice.number);
return Text(
invoice.number.isEmpty ? localization!.pending : invoice.number);
case InvoiceFields.client:
return LinkTextRelatedEntity(entity: client, relation: invoice);
case InvoiceFields.project:
@ -203,7 +202,7 @@ class InvoicePresenter extends EntityPresenter {
return Text(localization!.secondReminder);
} else if ((invoice.reminder1Sent ?? '').isNotEmpty) {
return Text(localization!.firstReminder);
} else if ((invoice.lastSentDate ?? '').isNotEmpty) {
} else if (invoice.lastSentDate.isNotEmpty) {
return Text(localization!.initialEmail);
} else {
return Text('');

View File

@ -264,12 +264,12 @@ class InvoiceOverview extends StatelessWidget {
);
}
if ((invoice.projectId ?? '').isNotEmpty) {
if (invoice.projectId.isNotEmpty) {
final project = state.projectState.get(invoice.projectId);
widgets.add(EntityListTile(entity: project, isFilter: isFilter));
}
if ((invoice.expenseId ?? '').isNotEmpty) {
if (invoice.expenseId.isNotEmpty) {
final expense = state.vendorState.get(invoice.expenseId);
widgets.add(EntityListTile(entity: expense, isFilter: isFilter));
}

View File

@ -133,7 +133,7 @@ class ProjectListItem extends StatelessWidget {
? ' 📎'
: ''),
style: textStyle),
Text(subtitle ?? filterMatch!,
Text(subtitle,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)

View File

@ -158,7 +158,7 @@ class RecurringExpenseListItem extends StatelessWidget {
style: textStyle,
maxLines: 1,
),
Text(subtitle ?? filterMatch!,
Text(subtitle,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)

View File

@ -706,28 +706,28 @@ class _ReportDataTableState extends State<ReportDataTable> {
class TotalsDataTable extends StatelessWidget {
const TotalsDataTable({
this.reportSettings,
this.reportResult,
this.viewModel,
required this.reportSettings,
required this.reportResult,
required this.viewModel,
});
final ReportsScreenVM? viewModel;
final ReportSettingsEntity? reportSettings;
final ReportResult? reportResult;
final ReportsScreenVM viewModel;
final ReportSettingsEntity reportSettings;
final ReportResult reportResult;
@override
Widget build(BuildContext context) {
return mt.DataTable(
sortColumnIndex:
reportResult!.columns.length > reportSettings!.sortTotalsIndex
? reportSettings!.sortTotalsIndex
reportResult.columns.length > reportSettings.sortTotalsIndex
? reportSettings.sortTotalsIndex
: null,
sortAscending: reportSettings!.sortTotalsAscending ?? true,
columns: reportResult!.totalColumns(
sortAscending: reportSettings.sortTotalsAscending ?? true,
columns: reportResult.totalColumns(
context,
(index, ascending) =>
viewModel!.onReportTotalsSorted(index, ascending)),
rows: reportResult!.totalRows(context),
viewModel.onReportTotalsSorted(index, ascending)),
rows: reportResult.totalRows(context),
);
}
}

View File

@ -190,7 +190,7 @@ class TaskListItem extends StatelessWidget {
overflow: TextOverflow.ellipsis,
style: textStyle),
Text(
subtitle ?? filterMatch!,
subtitle,
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: Theme.of(context)

View File

@ -1047,7 +1047,7 @@ class _MatchWithdrawalsState extends State<_MatchWithdrawals> {
separatorBuilder: (context, index) => ListDivider(),
itemCount: _expenses.length,
itemBuilder: (BuildContext context, int index) {
final expense = _expenses[index];
final expense = _expenses[index]!;
return ExpenseListItem(
expense: expense,
showCheckbox: true,