Null safety

This commit is contained in:
Hillel Coren 2023-10-01 16:03:57 +03:00
parent fbd8b8f5ba
commit e22c4a5228
26 changed files with 131 additions and 132 deletions

View File

@ -186,7 +186,7 @@ class PaymentSidebar extends StatelessWidget {
itemCount: recentPayments.length,
itemBuilder: (BuildContext context, int index) {
return PaymentListItem(
payment: recentPayments[index],
payment: recentPayments[index]!,
showSelected: false,
);
},

View File

@ -189,7 +189,7 @@ class ExpenseOverview extends StatelessWidget {
currencyId: expense.currencyId),
),
ListDivider(),
if ((expense.privateNotes ?? '').isNotEmpty) ...[
if (expense.privateNotes.isNotEmpty) ...[
IconMessage(expense.privateNotes,
iconData: Icons.lock, copyToClipboard: true),
ListDivider(),
@ -223,7 +223,7 @@ class ExpenseOverview extends StatelessWidget {
.present(localization.active, localization.archived),
),
..._buildDetailsList(),
if ((expense.publicNotes ?? '').isNotEmpty) ...[
if (expense.publicNotes.isNotEmpty) ...[
IconMessage(expense.publicNotes, copyToClipboard: true),
ListDivider()
],

View File

@ -250,8 +250,7 @@ class InvoiceEditDesktopState extends State<InvoiceEditDesktop>
!item!.isEmpty && item.typeId == InvoiceItemEntity.TYPE_TASK)
.length;
final showTasksTable =
(invoice.hasTasks || (company.showTasksTable ?? false)) &&
final showTasksTable = (invoice.hasTasks || company.showTasksTable) &&
(invoice.isInvoice || invoice.isQuote);
final settings = getClientSettings(state, client);
@ -376,7 +375,7 @@ class InvoiceEditDesktopState extends State<InvoiceEditDesktop>
))
.toList()),
DatePicker(
labelText: (invoice.lastSentDate ?? '').isNotEmpty
labelText: invoice.lastSentDate.isNotEmpty
? localization.nextSendDate
: localization.startDate,
onSelected: (date, _) {

View File

@ -223,7 +223,7 @@ class InvoiceEditDetailsState extends State<InvoiceEditDetails> {
))
.toList()),
DatePicker(
labelText: (invoice.lastSentDate ?? '').isNotEmpty
labelText: invoice.lastSentDate.isNotEmpty
? localization.nextSendDate
: localization.startDate,
onSelected: (date, _) => viewModel

View File

@ -448,10 +448,10 @@ class _InvoiceEditItemsDesktopState extends State<InvoiceEditItemsDesktop> {
..._columns
.map((column) {
if (column == COLUMN_ITEM) {
return Text(item.productKey ?? '');
return Text(item.productKey);
} else if (column == COLUMN_DESCRIPTION) {
return Text(
item.notes ?? '',
item.notes,
maxLines: 2, // TODO change to 1
overflow: TextOverflow.ellipsis,
);

View File

@ -57,7 +57,7 @@ class _InvoiceViewHistoryState extends State<InvoiceViewHistory> {
itemBuilder: (BuildContext context, index) {
final activity = activityList[index];
final history = activity.history!;
final activityId = history.activityId ?? '';
final activityId = history.activityId;
final state = viewModel.state!;
final client = state.clientState.get(activity.clientId!);

View File

@ -137,7 +137,7 @@ class InvoiceOverview extends StatelessWidget {
ListDivider(),
]);
if ((invoice.privateNotes ?? '').isNotEmpty) {
if (invoice.privateNotes.isNotEmpty) {
widgets.addAll([
IconMessage(invoice.privateNotes,
iconData: Icons.lock, copyToClipboard: true),
@ -516,7 +516,7 @@ class InvoiceOverview extends StatelessWidget {
widgets.add(surchargeRow(localization.partialDue, invoice.partial));
}
if ((invoice.publicNotes ?? '').isNotEmpty) {
if (invoice.publicNotes.isNotEmpty) {
widgets.addAll([
ListDivider(),
IconMessage(invoice.publicNotes, copyToClipboard: true),

View File

@ -625,7 +625,7 @@ class _PaymentableEditorState extends State<PaymentableEditor> {
// If a client isn't selected or a client is selected but the client
// doesn't have any more credits then don't show the picker
if (widget.entityType == EntityType.credit &&
((payment.clientId ?? '').isEmpty ||
(payment.clientId.isEmpty ||
(creditList.isEmpty && (paymentable.creditId ?? '').isEmpty))) {
return SizedBox();
} else if (widget.entityType == EntityType.invoice &&

View File

@ -28,7 +28,7 @@ class PaymentListItem extends StatelessWidget {
this.showSelected = true,
});
final PaymentEntity? payment;
final PaymentEntity payment;
final String? filter;
final bool showCheckbox;
final bool isChecked;
@ -41,31 +41,31 @@ class PaymentListItem extends StatelessWidget {
final uiState = state.uiState;
final paymentUIState = uiState.paymentUIState;
final textStyle = TextStyle(fontSize: 16);
final client = state.clientState.get(payment!.clientId);
final client = state.clientState.get(payment.clientId);
final localization = AppLocalization.of(context);
final filterMatch = filter != null && filter!.isNotEmpty
? (payment!.matchesFilterValue(filter) ??
? (payment.matchesFilterValue(filter) ??
client.matchesFilterValue(filter))
: null;
final mobileSubtitle = filterMatch ??
(payment!.number ?? '') + '' + formatDate(payment!.date, context);
payment.number + '' + formatDate(payment.date, context);
final textColor = Theme.of(context).textTheme.bodyLarge!.color;
String desktopSubtitle = '';
if (payment!.date.isNotEmpty) {
desktopSubtitle = formatDate(payment!.date, context);
if (payment.date.isNotEmpty) {
desktopSubtitle = formatDate(payment.date, context);
}
if (payment!.transactionReference.isNotEmpty) {
if (payment.transactionReference.isNotEmpty) {
if (desktopSubtitle.isNotEmpty) {
desktopSubtitle += '';
}
desktopSubtitle += payment!.transactionReference;
desktopSubtitle += payment.transactionReference;
}
return DismissibleEntity(
isSelected: isDesktop(context) &&
showSelected &&
payment!.id ==
payment.id ==
(uiState.isEditing
? paymentUIState.editing!.id
: paymentUIState.selectedId),
@ -78,10 +78,10 @@ class PaymentListItem extends StatelessWidget {
? InkWell(
onTap: () => onTap != null
? onTap!()
: selectEntity(entity: payment!, forceView: !showCheckbox),
: selectEntity(entity: payment, forceView: !showCheckbox),
onLongPress: () => onTap != null
? null
: selectEntity(entity: payment!, longPress: true),
: selectEntity(entity: payment, longPress: true),
child: Padding(
padding: const EdgeInsets.only(
left: 10,
@ -105,7 +105,7 @@ class PaymentListItem extends StatelessWidget {
),
)
: ActionMenuButton(
entityActions: payment!.getActions(
entityActions: payment.getActions(
userCompany: state.userCompany,
client: client,
includeEdit: true,
@ -121,11 +121,11 @@ class PaymentListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
payment!.number,
payment.number,
style: textStyle,
overflow: TextOverflow.ellipsis,
),
if (!payment!.isActive) EntityStateLabel(payment)
if (!payment.isActive) EntityStateLabel(payment)
],
),
),
@ -152,7 +152,7 @@ class PaymentListItem extends StatelessWidget {
),
SizedBox(width: 10),
Text(
formatNumber(payment!.amount, context,
formatNumber(payment.amount, context,
clientId: client.id)!,
style: textStyle,
textAlign: TextAlign.end,
@ -166,10 +166,10 @@ class PaymentListItem extends StatelessWidget {
: ListTile(
onTap: () => onTap != null
? onTap!()
: selectEntity(entity: payment!, forceView: !showCheckbox),
: selectEntity(entity: payment, forceView: !showCheckbox),
onLongPress: () => onTap != null
? null
: selectEntity(entity: payment!, longPress: true),
: selectEntity(entity: payment, longPress: true),
leading: showCheckbox
? IgnorePointer(
child: Checkbox(
@ -192,8 +192,8 @@ class PaymentListItem extends StatelessWidget {
),
),
Text(
formatNumber(payment!.amount, context,
clientId: payment!.clientId)!,
formatNumber(payment.amount, context,
clientId: payment.clientId)!,
style: Theme.of(context).textTheme.titleMedium),
],
),
@ -214,11 +214,11 @@ class PaymentListItem extends StatelessWidget {
),
Text(
localization!.lookup(
'payment_status_${payment!.calculatedStatusId}')!,
'payment_status_${payment.calculatedStatusId}')!,
style: TextStyle(
color: PaymentStatusColors(
state.prefState.colorThemeModel)
.colors[payment!.calculatedStatusId],
.colors[payment.calculatedStatusId],
)),
],
),

View File

@ -62,7 +62,7 @@ class _PaymentViewState extends State<PaymentView> {
if (payment.date.isNotEmpty) {
fields[PaymentFields.date] = formatDate(payment.date, context);
}
if ((payment.typeId ?? '').isNotEmpty) {
if (payment.typeId.isNotEmpty) {
final paymentType = state.staticState.paymentTypeMap[payment.typeId];
if (paymentType != null) {
fields[PaymentFields.typeId] = paymentType.name;
@ -133,7 +133,7 @@ class _PaymentViewState extends State<PaymentView> {
paymentable.createdAt),
context),
),
if ((payment.companyGatewayId ?? '').isNotEmpty) ...[
if (payment.companyGatewayId.isNotEmpty) ...[
ListTile(
title: Text(
'${localization.gateway} ${companyGateway.label}'),

View File

@ -29,7 +29,7 @@ class ProjectListItem extends StatelessWidget {
final UserEntity? user;
final GestureTapCallback? onTap;
final GestureTapCallback? onLongPress;
final ProjectEntity? project;
final ProjectEntity project;
final String? filter;
final Function(bool?)? onCheckboxChanged;
final bool isChecked;
@ -40,9 +40,9 @@ class ProjectListItem extends StatelessWidget {
final state = store.state;
final uiState = state.uiState;
final projectUIState = uiState.projectUIState;
final client = state.clientState.get(project!.clientId);
final client = state.clientState.get(project.clientId);
final filterMatch = filter != null && filter!.isNotEmpty
? (project!.matchesFilterValue(filter) ??
? (project.matchesFilterValue(filter) ??
client.matchesFilterValue(filter))
: null;
final listUIState = projectUIState.listUIState;
@ -54,7 +54,7 @@ class ProjectListItem extends StatelessWidget {
return DismissibleEntity(
isSelected: isDesktop(context) &&
project!.id ==
project.id ==
(uiState.isEditing
? projectUIState.editing!.id
: projectUIState.selectedId),
@ -65,10 +65,10 @@ class ProjectListItem extends StatelessWidget {
return constraints.maxWidth > kTableListWidthCutoff
? InkWell(
onTap: () =>
onTap != null ? onTap!() : selectEntity(entity: project!),
onTap != null ? onTap!() : selectEntity(entity: project),
onLongPress: () => onLongPress != null
? onLongPress!()
: selectEntity(entity: project!, longPress: true),
: selectEntity(entity: project, longPress: true),
child: Padding(
padding: const EdgeInsets.only(
left: 10,
@ -97,7 +97,7 @@ class ProjectListItem extends StatelessWidget {
),
)
: ActionMenuButton(
entityActions: project!.getActions(
entityActions: project.getActions(
userCompany: state.userCompany,
client: client,
includeEdit: true,
@ -114,11 +114,11 @@ class ProjectListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
project!.number ?? '',
project.number ?? '',
style: textStyle,
overflow: TextOverflow.ellipsis,
),
if (!project!.isActive) EntityStateLabel(project)
if (!project.isActive) EntityStateLabel(project)
],
),
),
@ -128,8 +128,8 @@ class ProjectListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
project!.name +
(project!.documents.isNotEmpty
project.name +
(project.documents.isNotEmpty
? ' 📎'
: ''),
style: textStyle),
@ -150,7 +150,7 @@ class ProjectListItem extends StatelessWidget {
Text(
formatDuration(
Duration(
minutes: (project!.budgetedHours * 60).toInt()),
minutes: (project.budgetedHours * 60).toInt()),
showSeconds: false),
style: textStyle,
textAlign: TextAlign.end,
@ -161,10 +161,10 @@ class ProjectListItem extends StatelessWidget {
)
: ListTile(
onTap: () =>
onTap != null ? onTap!() : selectEntity(entity: project!),
onTap != null ? onTap!() : selectEntity(entity: project),
onLongPress: () => onLongPress != null
? onLongPress!()
: selectEntity(entity: project!, longPress: true),
: selectEntity(entity: project, longPress: true),
leading: showCheckbox
? IgnorePointer(
ignoring: listUIState.isInMultiselect(),
@ -183,8 +183,8 @@ class ProjectListItem extends StatelessWidget {
children: <Widget>[
Expanded(
child: Text(
project!.name +
(project!.documents.isNotEmpty ? ' 📎' : ''),
project.name +
(project.documents.isNotEmpty ? ' 📎' : ''),
style: Theme.of(context).textTheme.titleMedium,
),
),
@ -192,7 +192,7 @@ class ProjectListItem extends StatelessWidget {
formatDuration(
Duration(
minutes:
(project!.budgetedHours * 60).toInt()),
(project.budgetedHours * 60).toInt()),
showSeconds: false),
style: Theme.of(context).textTheme.titleMedium),
],
@ -203,7 +203,7 @@ class ProjectListItem extends StatelessWidget {
children: <Widget>[
Text(
filterMatch == null
? project!.number + '' + client.displayName
? project.number + '' + client.displayName
: filterMatch,
maxLines: 3,
overflow: TextOverflow.ellipsis),

View File

@ -43,7 +43,7 @@ class ProjectListBuilder extends StatelessWidget {
itemBuilder: (BuildContext context, index) {
final state = viewModel.state;
final projectId = viewModel.projectList[index];
final project = viewModel.projectMap[projectId];
final project = viewModel.projectMap[projectId]!;
final listState = state.getListState(EntityType.project);
final isInMultiselect = listState.isInMultiselect();
@ -51,7 +51,7 @@ class ProjectListBuilder extends StatelessWidget {
user: state.user,
filter: viewModel.filter,
project: project,
isChecked: isInMultiselect && listState.isSelected(project!.id),
isChecked: isInMultiselect && listState.isSelected(project.id),
);
});
},

View File

@ -69,7 +69,7 @@ class ProjectPresenter extends EntityPresenter {
return Text(formatNumber(project.budgetedHours, context,
formatNumberType: FormatNumberType.double)!);
case ProjectFields.number:
return Text(project.number ?? '');
return Text(project.number);
case ProjectFields.customValue1:
return Text(presentCustomField(context, project.customValue1)!);
case ProjectFields.customValue2:

View File

@ -111,7 +111,7 @@ class _ProjectOverviewState extends State<ProjectOverview> {
Duration(minutes: (project.budgetedHours * 60).toInt())),
),
ListDivider(),
if ((project.privateNotes ?? '').isNotEmpty) ...[
if (project.privateNotes.isNotEmpty) ...[
IconMessage(project.privateNotes,
iconData: Icons.lock, copyToClipboard: true),
ListDivider()
@ -160,7 +160,7 @@ class _ProjectOverviewState extends State<ProjectOverview> {
FieldGrid(fields),
]);
if ((project.publicNotes ?? '').isNotEmpty) {
if (project.publicNotes.isNotEmpty) {
widgets.addAll([
IconMessage(project.publicNotes, copyToClipboard: true),
ListDivider()

View File

@ -116,7 +116,7 @@ class PurchaseOrderListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
(purchaseOrder.number ?? '').isEmpty
purchaseOrder.number.isEmpty
? localization!.pending
: purchaseOrder.number,
style: textStyle,

View File

@ -206,7 +206,7 @@ class QuoteListItem extends StatelessWidget {
children: <Widget>[
Expanded(
child: filterMatch == null
? Text((((quote.number ?? '').isEmpty
? Text(((quote.number.isEmpty
? localization!.pending
: quote.number) +
'' +

View File

@ -70,9 +70,8 @@ class QuotePresenter extends EntityPresenter {
case QuoteFields.status:
return EntityStatusChip(entity: quote, showState: true);
case QuoteFields.number:
return Text((quote.number ?? '').isEmpty
? localization!.pending
: quote.number);
return Text(
quote.number.isEmpty ? localization!.pending : quote.number);
case QuoteFields.client:
return LinkTextRelatedEntity(entity: client, relation: quote);
case QuoteFields.date:

View File

@ -19,7 +19,7 @@ import 'package:invoiceninja_flutter/utils/platforms.dart';
class RecurringExpenseListItem extends StatelessWidget {
const RecurringExpenseListItem({
required this.expense,
this.filter,
required this.filter,
this.onTap,
this.onCheckboxChanged,
this.showCheckbox = true,
@ -29,7 +29,7 @@ class RecurringExpenseListItem extends StatelessWidget {
final Function(bool?)? onCheckboxChanged;
final GestureTapCallback? onTap;
final ExpenseEntity? expense;
final ExpenseEntity expense;
final String? filter;
final bool showCheckbox;
final bool isDismissible;
@ -41,18 +41,18 @@ class RecurringExpenseListItem extends StatelessWidget {
final state = store.state;
final uiState = state.uiState;
final expenseUIState = uiState.recurringExpenseUIState;
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 listUIState = expenseUIState.listUIState;
final isInMultiselect = listUIState.isInMultiselect();
final showCheckbox = onCheckboxChanged != null || isInMultiselect;
final isChecked = isDismissible
? (isInMultiselect && listUIState.isSelected(expense!.id))
? (isInMultiselect && listUIState.isSelected(expense.id))
: this.isChecked;
final textStyle = TextStyle(fontSize: 16);
final textColor = Theme.of(context).textTheme.bodyLarge!.color;
@ -62,8 +62,8 @@ class RecurringExpenseListItem extends StatelessWidget {
subtitle = filterMatch;
} else if (client != null || vendor != null || category != null) {
final parts = <String>[];
if (expense!.nextSendDate.isNotEmpty) {
parts.add(formatDate(expense!.nextSendDate, context));
if (expense.nextSendDate.isNotEmpty) {
parts.add(formatDate(expense.nextSendDate, context));
}
if (category.isOld) {
parts.add(category.name);
@ -81,7 +81,7 @@ class RecurringExpenseListItem extends StatelessWidget {
showMultiselect: this.showCheckbox,
isDismissible: isDismissible,
isSelected: isDesktop(context) &&
expense!.id ==
expense.id ==
(uiState.isEditing
? expenseUIState.editing!.id
: expenseUIState.selectedId),
@ -92,9 +92,9 @@ class RecurringExpenseListItem extends StatelessWidget {
return constraints.maxWidth > kTableListWidthCutoff
? InkWell(
onTap: () =>
onTap != null ? onTap!() : selectEntity(entity: expense!),
onTap != null ? onTap!() : selectEntity(entity: expense),
onLongPress: () =>
selectEntity(entity: expense!, longPress: true),
selectEntity(entity: expense, longPress: true),
child: Padding(
padding: const EdgeInsets.only(
left: 10,
@ -123,7 +123,7 @@ class RecurringExpenseListItem extends StatelessWidget {
),
)
: ActionMenuButton(
entityActions: expense!.getActions(
entityActions: expense.getActions(
userCompany: state.userCompany,
includeEdit: true,
),
@ -139,11 +139,11 @@ class RecurringExpenseListItem 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)
],
),
),
@ -153,8 +153,8 @@ class RecurringExpenseListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
(expense!.publicNotes ?? '') +
(expense!.documents.isNotEmpty ? ' 📎' : ''),
(expense.publicNotes ?? '') +
(expense.documents.isNotEmpty ? ' 📎' : ''),
style: textStyle,
maxLines: 1,
),
@ -173,8 +173,8 @@ class RecurringExpenseListItem extends StatelessWidget {
),
SizedBox(width: 8),
Text(
formatNumber(expense!.convertedAmount, context,
currencyId: expense!.currencyId)!,
formatNumber(expense.convertedAmount, context,
currencyId: expense.currencyId)!,
style: textStyle,
textAlign: TextAlign.end,
),
@ -186,9 +186,9 @@ class RecurringExpenseListItem extends StatelessWidget {
)
: ListTile(
onTap: () =>
onTap != null ? onTap!() : selectEntity(entity: expense!),
onTap != null ? onTap!() : selectEntity(entity: expense),
onLongPress: () =>
selectEntity(entity: expense!, longPress: true),
selectEntity(entity: expense, longPress: true),
leading: showCheckbox
? IgnorePointer(
ignoring: listUIState.isInMultiselect(),
@ -207,17 +207,17 @@ class RecurringExpenseListItem 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!.convertedAmount, context,
currencyId: expense!.currencyId)!,
formatNumber(expense.convertedAmount, context,
currencyId: expense.currencyId)!,
style: Theme.of(context).textTheme.titleMedium),
],
),

View File

@ -44,7 +44,7 @@ class RecurringExpenseListBuilder extends StatelessWidget {
final state = viewModel.state;
final recurringExpenseId = viewModel.recurringExpenseList[index];
final recurringExpense =
viewModel.recurringExpenseMap[recurringExpenseId];
viewModel.recurringExpenseMap[recurringExpenseId]!;
final listState = state.getListState(EntityType.recurringExpense);
final isInMultiselect = listState.isInMultiselect();
@ -52,7 +52,7 @@ class RecurringExpenseListBuilder extends StatelessWidget {
filter: viewModel.filter,
expense: recurringExpense,
isChecked: isInMultiselect &&
listState.isSelected(recurringExpense!.id),
listState.isSelected(recurringExpense.id),
);
});
},

View File

@ -216,7 +216,7 @@ class RecurringInvoiceListItem extends StatelessWidget {
Expanded(
child: filterMatch == null
? Text(
(((invoice.number ?? '').isEmpty
((invoice.number.isEmpty
? localization.pending
: invoice.number) +
(invoice.nextSendDate.isNotEmpty

View File

@ -52,76 +52,75 @@ class RecurringInvoicePresenter extends EntityPresenter {
Widget getField({String? field, required BuildContext context}) {
final localization = AppLocalization.of(context);
final state = StoreProvider.of<AppState>(context).state;
final invoice = entity as InvoiceEntity?;
final invoice = entity as InvoiceEntity;
switch (field) {
case RecurringInvoiceFields.status:
return EntityStatusChip(entity: invoice, showState: true);
case RecurringInvoiceFields.number:
return Text((invoice!.number ?? '').isEmpty
? localization!.pending
: invoice.number);
return Text(
invoice.number.isEmpty ? localization!.pending : invoice.number);
case RecurringInvoiceFields.client:
final client = state.clientState.get(invoice!.clientId);
final client = state.clientState.get(invoice.clientId);
return LinkTextRelatedEntity(entity: client, relation: invoice);
case RecurringInvoiceFields.date:
return Text(formatDate(invoice!.date, context));
return Text(formatDate(invoice.date, context));
case RecurringInvoiceFields.reminder1Sent:
return Text(formatDate(invoice!.reminder1Sent, context));
return Text(formatDate(invoice.reminder1Sent, context));
case RecurringInvoiceFields.reminder2Sent:
return Text(formatDate(invoice!.reminder2Sent, context));
return Text(formatDate(invoice.reminder2Sent, context));
case RecurringInvoiceFields.reminder3Sent:
return Text(formatDate(invoice!.reminder3Sent, context));
return Text(formatDate(invoice.reminder3Sent, context));
case RecurringInvoiceFields.reminderLastSent:
return Text(formatDate(invoice!.reminderLastSent, context));
return Text(formatDate(invoice.reminderLastSent, context));
case RecurringInvoiceFields.amount:
return Align(
alignment: Alignment.centerRight,
child: Text(formatNumber(invoice!.amount, context,
child: Text(formatNumber(invoice.amount, context,
clientId: invoice.clientId)!),
);
case RecurringInvoiceFields.customValue1:
return Text(presentCustomField(context, invoice!.customValue1)!);
return Text(presentCustomField(context, invoice.customValue1)!);
case RecurringInvoiceFields.customValue2:
return Text(presentCustomField(context, invoice!.customValue2)!);
return Text(presentCustomField(context, invoice.customValue2)!);
case RecurringInvoiceFields.customValue3:
return Text(presentCustomField(context, invoice!.customValue3)!);
return Text(presentCustomField(context, invoice.customValue3)!);
case RecurringInvoiceFields.customValue4:
return Text(presentCustomField(context, invoice!.customValue4)!);
return Text(presentCustomField(context, invoice.customValue4)!);
case RecurringInvoiceFields.publicNotes:
return TableTooltip(message: invoice!.publicNotes);
return TableTooltip(message: invoice.publicNotes);
case RecurringInvoiceFields.privateNotes:
return TableTooltip(message: invoice!.privateNotes);
return TableTooltip(message: invoice.privateNotes);
case RecurringInvoiceFields.discount:
return Text(invoice!.isAmountDiscount
return Text(invoice.isAmountDiscount
? formatNumber(invoice.discount, context,
formatNumberType: FormatNumberType.money,
clientId: invoice.clientId)!
: formatNumber(invoice.discount, context,
formatNumberType: FormatNumberType.percent)!);
case RecurringInvoiceFields.poNumber:
return Text(invoice!.poNumber);
return Text(invoice.poNumber);
case RecurringInvoiceFields.documents:
return Text('${invoice!.documents.length}');
return Text('${invoice.documents.length}');
case RecurringInvoiceFields.taxAmount:
return Text(formatNumber(invoice!.taxAmount, context,
return Text(formatNumber(invoice.taxAmount, context,
clientId: invoice.clientId)!);
case RecurringInvoiceFields.exchangeRate:
return Text(formatNumber(invoice!.exchangeRate, context,
return Text(formatNumber(invoice.exchangeRate, context,
formatNumberType: FormatNumberType.double)!);
case RecurringInvoiceFields.remainingCycles:
return Text(invoice!.remainingCycles == -1
return Text(invoice.remainingCycles == -1
? localization!.endless
: '${invoice.remainingCycles}');
case RecurringInvoiceFields.nextSendDate:
return Text(invoice!.nextSendDatetime.isNotEmpty
return Text(invoice.nextSendDatetime.isNotEmpty
? formatDate(invoice.nextSendDatetime, context,
showTime: true, showSeconds: false)
: formatDate(invoice.nextSendDate, context));
case RecurringInvoiceFields.frequency:
return Text(localization!.lookup(kFrequencies[invoice!.frequencyId])!);
return Text(localization!.lookup(kFrequencies[invoice.frequencyId])!);
case RecurringInvoiceFields.dueDateDays:
return Text(invoice!.dueDateDays == 'terms'
return Text(invoice.dueDateDays == 'terms'
? localization!.paymentTerm
: invoice.dueDateDays == 'on_receipt'
? localization!.dueOnReceipt!
@ -132,7 +131,7 @@ class RecurringInvoicePresenter extends EntityPresenter {
: localization!.dayCount
.replaceFirst(':count', '${invoice.dueDateDays}'));
case RecurringInvoiceFields.autoBill:
return Text(localization!.lookup(invoice!.autoBill)!);
return Text(localization!.lookup(invoice.autoBill)!);
}
return super.getField(field: field, context: context);

View File

@ -722,7 +722,7 @@ class TotalsDataTable extends StatelessWidget {
reportResult.columns.length > reportSettings.sortTotalsIndex
? reportSettings.sortTotalsIndex
: null,
sortAscending: reportSettings.sortTotalsAscending ?? true,
sortAscending: reportSettings.sortTotalsAscending,
columns: reportResult.totalColumns(
context,
(index, ascending) =>
@ -925,7 +925,10 @@ class ReportResult {
return true;
}
static bool matchString({required String filter, String? value}) {
static bool matchString({
required String filter,
String? value,
}) {
filter = filter.trim();
if (filter.isEmpty) {
@ -933,7 +936,7 @@ class ReportResult {
}
value = (value ?? '').toLowerCase();
filter = (filter ?? '').toLowerCase();
filter = filter.toLowerCase();
if (filter == 'null' && value.isEmpty) {
return true;
@ -1120,7 +1123,7 @@ class ReportResult {
))
else if (getReportColumnType(column, context) == ReportColumnType.age)
DataCell(AppDropdownButton<String>(
value: (textEditingControllers[column]!.text ?? '').isNotEmpty &&
value: (textEditingControllers[column]!.text).isNotEmpty &&
textEditingControllers[column]!.text != 'null'
? textEditingControllers[column]!.text
: null,

View File

@ -164,10 +164,10 @@ ReportResult taskReport(
value = task.description;
break;
case TaskReportFields.invoice:
value = invoice.listDisplayName ?? '';
value = invoice.listDisplayName;
break;
case TaskReportFields.invoice_amount:
value = invoice.amount ?? '';
value = invoice.amount;
break;
case TaskReportFields.invoice_date:
value = invoice.isNew ? '' : invoice.date;

View File

@ -152,7 +152,7 @@ class VendorOverview extends StatelessWidget {
vendor.id, state.transactionState.map)
.present(localization.active, localization.archived),
),
if ((vendor.publicNotes ?? '').isNotEmpty) ...[
if (vendor.publicNotes.isNotEmpty) ...[
IconMessage(vendor.publicNotes, copyToClipboard: true),
ListDivider()
],

View File

@ -276,8 +276,7 @@ AppLayout calculateLayout(BuildContext context) {
}
AppLayout getLayout(BuildContext context) =>
StoreProvider.of<AppState>(context).state.prefState.appLayout ??
AppLayout.mobile;
StoreProvider.of<AppState>(context).state.prefState.appLayout;
bool isMobile(BuildContext context) => getLayout(context) == AppLayout.mobile;

View File

@ -34,7 +34,7 @@ String toCamelCase(String subject) {
}
String toSpaceCase(String value) {
if ((value ?? '').isEmpty) {
if (value.isEmpty) {
return '';
}