Flutter upgrade
This commit is contained in:
parent
d5388e5567
commit
b1a7444a61
|
|
@ -123,353 +123,341 @@ class EditScaffold extends StatelessWidget {
|
||||||
|
|
||||||
final showOverflow = isDesktop(context) && state.isFullScreen;
|
final showOverflow = isDesktop(context) && state.isFullScreen;
|
||||||
|
|
||||||
return WillPopScope(
|
return CallbackShortcuts(
|
||||||
onWillPop: () async {
|
bindings: <ShortcutActivator, VoidCallback>{
|
||||||
return true;
|
const SingleActivator(LogicalKeyboardKey.keyS, control: true): () =>
|
||||||
|
onSavePressed!(context),
|
||||||
},
|
},
|
||||||
child: CallbackShortcuts(
|
child: FocusTraversalGroup(
|
||||||
bindings: <ShortcutActivator, VoidCallback>{
|
child: Scaffold(
|
||||||
const SingleActivator(LogicalKeyboardKey.keyS, control: true): () =>
|
body: state.companies.isEmpty
|
||||||
onSavePressed!(context),
|
? LoadingIndicator()
|
||||||
},
|
: Stack(
|
||||||
child: FocusTraversalGroup(
|
alignment: Alignment.topCenter,
|
||||||
child: Scaffold(
|
children: [
|
||||||
body: state.companies.isEmpty
|
Column(
|
||||||
? LoadingIndicator()
|
children: [
|
||||||
: Stack(
|
if (showUpgradeBanner &&
|
||||||
alignment: Alignment.topCenter,
|
state.userCompany.isOwner &&
|
||||||
children: [
|
(!isApple() || supportsInAppPurchase()))
|
||||||
Column(
|
InkWell(
|
||||||
children: [
|
child: IconMessage(
|
||||||
if (showUpgradeBanner &&
|
upgradeMessage,
|
||||||
state.userCompany.isOwner &&
|
color: Colors.orange.shade800,
|
||||||
(!isApple() || supportsInAppPurchase()))
|
|
||||||
InkWell(
|
|
||||||
child: IconMessage(
|
|
||||||
upgradeMessage,
|
|
||||||
color: Colors.orange.shade800,
|
|
||||||
),
|
|
||||||
onTap: () async {
|
|
||||||
if (bannerClick != null) {
|
|
||||||
bannerClick();
|
|
||||||
} else if (supportsInAppPurchase() &&
|
|
||||||
account.canMakeIAP) {
|
|
||||||
showDialog<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => UpgradeDialog(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
launchUrl(Uri.parse(
|
|
||||||
state.userCompany.ninjaPortalUrl));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
Expanded(
|
onTap: () async {
|
||||||
child: body,
|
if (bannerClick != null) {
|
||||||
),
|
bannerClick();
|
||||||
],
|
} else if (supportsInAppPurchase() &&
|
||||||
),
|
account.canMakeIAP) {
|
||||||
if (state.isSaving) LinearProgressIndicator(),
|
showDialog<void>(
|
||||||
],
|
context: context,
|
||||||
),
|
builder: (context) => UpgradeDialog(),
|
||||||
drawer: isDesktop(context) ? MenuDrawerBuilder() : null,
|
|
||||||
appBar: AppBar(
|
|
||||||
centerTitle: false,
|
|
||||||
automaticallyImplyLeading: isMobile(context),
|
|
||||||
title: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
if (showOverflow)
|
|
||||||
Text(title!)
|
|
||||||
else
|
|
||||||
Flexible(child: Text(title!)),
|
|
||||||
SizedBox(width: 16),
|
|
||||||
if (isDesktop(context) &&
|
|
||||||
isFullscreen &&
|
|
||||||
entity != null &&
|
|
||||||
entity!.isOld) ...[
|
|
||||||
EntityStatusChip(
|
|
||||||
entity:
|
|
||||||
state.getEntity(entity!.entityType, entity!.id)),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
],
|
|
||||||
if (showOverflow)
|
|
||||||
Expanded(
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: FocusTraversalGroup(
|
|
||||||
// TODO this is needed as a workaround to prevent
|
|
||||||
// breaking tab focus traversal
|
|
||||||
descendantsAreFocusable: false,
|
|
||||||
child: OverflowView.flexible(
|
|
||||||
spacing: 8,
|
|
||||||
children: entityActions.map(
|
|
||||||
(action) {
|
|
||||||
String? label;
|
|
||||||
if (action == EntityAction.save &&
|
|
||||||
saveLabel != null) {
|
|
||||||
label = saveLabel;
|
|
||||||
} else {
|
|
||||||
label = localization.lookup('$action');
|
|
||||||
}
|
|
||||||
|
|
||||||
return OutlinedButton(
|
|
||||||
style: action == EntityAction.save &&
|
|
||||||
isEnabled
|
|
||||||
? ButtonStyle(
|
|
||||||
backgroundColor:
|
|
||||||
MaterialStateProperty.all(state
|
|
||||||
.prefState
|
|
||||||
.colorThemeModel!
|
|
||||||
.colorSuccess))
|
|
||||||
: null,
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
minWidth:
|
|
||||||
isDesktop(context) ? 60 : 0),
|
|
||||||
child: isDesktop(context)
|
|
||||||
? IconText(
|
|
||||||
icon: getEntityActionIcon(action),
|
|
||||||
text: label,
|
|
||||||
style: state.isSaving
|
|
||||||
? null
|
|
||||||
: action == EntityAction.save
|
|
||||||
? textStyle.copyWith(
|
|
||||||
color: Colors.white)
|
|
||||||
: textStyle,
|
|
||||||
)
|
|
||||||
: Text(label!,
|
|
||||||
style: state.isSaving
|
|
||||||
? null
|
|
||||||
: textStyle),
|
|
||||||
),
|
|
||||||
onPressed: state.isSaving
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
if (action == EntityAction.back) {
|
|
||||||
if (onCancelPressed != null) {
|
|
||||||
onCancelPressed!(context);
|
|
||||||
} else {
|
|
||||||
store.dispatch(ResetSettings());
|
|
||||||
}
|
|
||||||
} else if (action ==
|
|
||||||
EntityAction.save) {
|
|
||||||
// Clear focus now to prevent un-focus after save from
|
|
||||||
// marking the form as changed and to hide the keyboard
|
|
||||||
FocusScope.of(context).unfocus(
|
|
||||||
disposition: UnfocusDisposition
|
|
||||||
.previouslyFocusedChild);
|
|
||||||
|
|
||||||
onSavePressed!(context);
|
|
||||||
} else {
|
|
||||||
onActionPressed!(context, action);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).toList(),
|
|
||||||
builder: (context, remaining) {
|
|
||||||
return PopupMenuButton<EntityAction>(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 8),
|
|
||||||
child: isDesktop(context)
|
|
||||||
? Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
localization.more,
|
|
||||||
style: textStyle,
|
|
||||||
),
|
|
||||||
SizedBox(width: 4),
|
|
||||||
Icon(Icons.arrow_drop_down,
|
|
||||||
color: state.headerTextColor),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: Icon(Icons.more_vert),
|
|
||||||
),
|
|
||||||
onSelected: (EntityAction action) {
|
|
||||||
onActionPressed!(context, action);
|
|
||||||
},
|
|
||||||
itemBuilder: (BuildContext context) {
|
|
||||||
return entityActions
|
|
||||||
.toList()
|
|
||||||
.sublist(
|
|
||||||
entityActions.length - remaining)
|
|
||||||
.map((action) {
|
|
||||||
return PopupMenuItem<EntityAction>(
|
|
||||||
value: action,
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(getEntityActionIcon(action),
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.secondary),
|
|
||||||
SizedBox(width: 16.0),
|
|
||||||
Text(AppLocalization.of(context)!
|
|
||||||
.lookup(action.toString())),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}),
|
} else {
|
||||||
),
|
launchUrl(Uri.parse(
|
||||||
),
|
state.userCompany.ninjaPortalUrl));
|
||||||
),
|
}
|
||||||
],
|
},
|
||||||
),
|
|
||||||
actions: showOverflow
|
|
||||||
? []
|
|
||||||
: [
|
|
||||||
if (state.isSaving && isMobile(context))
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 20),
|
|
||||||
child: Center(
|
|
||||||
child: SizedBox(
|
|
||||||
width: 26,
|
|
||||||
height: 26,
|
|
||||||
child:
|
|
||||||
CircularProgressIndicator(color: Colors.white),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
else if (isDesktop(context))
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
OutlinedButton(
|
|
||||||
onPressed: state.isSaving
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
if (onCancelPressed != null) {
|
|
||||||
onCancelPressed!(context);
|
|
||||||
} else {
|
|
||||||
store.dispatch(ResetSettings());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(minWidth: 60),
|
|
||||||
child: IconText(
|
|
||||||
icon: getEntityActionIcon(EntityAction.back),
|
|
||||||
text: (entity != null &&
|
|
||||||
entity!.entityType!.isSetting)
|
|
||||||
? localization.back
|
|
||||||
: localization.cancel,
|
|
||||||
style: state.isSaving ? null : textStyle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
OutlinedButton(
|
|
||||||
style: isEnabled
|
|
||||||
? ButtonStyle(
|
|
||||||
backgroundColor:
|
|
||||||
MaterialStateProperty.all(state
|
|
||||||
.prefState
|
|
||||||
.colorThemeModel!
|
|
||||||
.colorSuccess))
|
|
||||||
: null,
|
|
||||||
onPressed: !isEnabled ||
|
|
||||||
state.isSaving ||
|
|
||||||
onSavePressed == null
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
// Clear focus now to prevent un-focus after save from
|
|
||||||
// marking the form as changed and to hide the keyboard
|
|
||||||
FocusScope.of(context).unfocus(
|
|
||||||
disposition: UnfocusDisposition
|
|
||||||
.previouslyFocusedChild);
|
|
||||||
|
|
||||||
onSavePressed!(context);
|
|
||||||
},
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(minWidth: 60),
|
|
||||||
child: IconText(
|
|
||||||
icon: getEntityActionIcon(EntityAction.save),
|
|
||||||
text: localization.save,
|
|
||||||
style: state.isSaving
|
|
||||||
? null
|
|
||||||
: textStyle.copyWith(color: Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 16),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
else
|
|
||||||
SaveCancelButtons(
|
|
||||||
isEnabled: isEnabled && onSavePressed != null,
|
|
||||||
isHeader: true,
|
|
||||||
isCancelEnabled: isCancelEnabled,
|
|
||||||
saveLabel: saveLabel,
|
|
||||||
cancelLabel: localization.cancel,
|
|
||||||
onSavePressed: onSavePressed == null
|
|
||||||
? null
|
|
||||||
: (context) {
|
|
||||||
// Clear focus now to prevent un-focus after save from
|
|
||||||
// marking the form as changed and to hide the keyboard
|
|
||||||
FocusScope.of(context).unfocus(
|
|
||||||
disposition: UnfocusDisposition
|
|
||||||
.previouslyFocusedChild);
|
|
||||||
|
|
||||||
onSavePressed!(context);
|
|
||||||
},
|
|
||||||
onCancelPressed: isMobile(context)
|
|
||||||
? null
|
|
||||||
: (context) {
|
|
||||||
if (onCancelPressed != null) {
|
|
||||||
onCancelPressed!(context);
|
|
||||||
} else {
|
|
||||||
store.dispatch(ResetSettings());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (actions != null &&
|
|
||||||
actions!.isNotEmpty &&
|
|
||||||
onActionPressed != null)
|
|
||||||
PopupMenuButton<EntityAction>(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.more_vert,
|
|
||||||
//size: iconSize,
|
|
||||||
//color: color,
|
|
||||||
),
|
),
|
||||||
itemBuilder: (BuildContext context) => [
|
Expanded(
|
||||||
...actions!
|
child: body,
|
||||||
.map((action) => action == null
|
),
|
||||||
? PopupMenuDivider()
|
],
|
||||||
: PopupMenuItem<EntityAction>(
|
),
|
||||||
child: Row(
|
if (state.isSaving) LinearProgressIndicator(),
|
||||||
children: <Widget>[
|
],
|
||||||
Icon(
|
),
|
||||||
getEntityActionIcon(action),
|
drawer: isDesktop(context) ? MenuDrawerBuilder() : null,
|
||||||
|
appBar: AppBar(
|
||||||
|
centerTitle: false,
|
||||||
|
automaticallyImplyLeading: isMobile(context),
|
||||||
|
title: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (showOverflow)
|
||||||
|
Text(title!)
|
||||||
|
else
|
||||||
|
Flexible(child: Text(title!)),
|
||||||
|
SizedBox(width: 16),
|
||||||
|
if (isDesktop(context) &&
|
||||||
|
isFullscreen &&
|
||||||
|
entity != null &&
|
||||||
|
entity!.isOld) ...[
|
||||||
|
EntityStatusChip(
|
||||||
|
entity: state.getEntity(entity!.entityType, entity!.id)),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
],
|
||||||
|
if (showOverflow)
|
||||||
|
Expanded(
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: FocusTraversalGroup(
|
||||||
|
// TODO this is needed as a workaround to prevent
|
||||||
|
// breaking tab focus traversal
|
||||||
|
descendantsAreFocusable: false,
|
||||||
|
child: OverflowView.flexible(
|
||||||
|
spacing: 8,
|
||||||
|
children: entityActions.map(
|
||||||
|
(action) {
|
||||||
|
String? label;
|
||||||
|
if (action == EntityAction.save &&
|
||||||
|
saveLabel != null) {
|
||||||
|
label = saveLabel;
|
||||||
|
} else {
|
||||||
|
label = localization.lookup('$action');
|
||||||
|
}
|
||||||
|
|
||||||
|
return OutlinedButton(
|
||||||
|
style: action == EntityAction.save &&
|
||||||
|
isEnabled
|
||||||
|
? ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
MaterialStateProperty.all(state
|
||||||
|
.prefState
|
||||||
|
.colorThemeModel!
|
||||||
|
.colorSuccess))
|
||||||
|
: null,
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minWidth: isDesktop(context) ? 60 : 0),
|
||||||
|
child: isDesktop(context)
|
||||||
|
? IconText(
|
||||||
|
icon: getEntityActionIcon(action),
|
||||||
|
text: label,
|
||||||
|
style: state.isSaving
|
||||||
|
? null
|
||||||
|
: action == EntityAction.save
|
||||||
|
? textStyle.copyWith(
|
||||||
|
color: Colors.white)
|
||||||
|
: textStyle,
|
||||||
|
)
|
||||||
|
: Text(label!,
|
||||||
|
style: state.isSaving
|
||||||
|
? null
|
||||||
|
: textStyle),
|
||||||
|
),
|
||||||
|
onPressed: state.isSaving
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (action == EntityAction.back) {
|
||||||
|
if (onCancelPressed != null) {
|
||||||
|
onCancelPressed!(context);
|
||||||
|
} else {
|
||||||
|
store.dispatch(ResetSettings());
|
||||||
|
}
|
||||||
|
} else if (action ==
|
||||||
|
EntityAction.save) {
|
||||||
|
// Clear focus now to prevent un-focus after save from
|
||||||
|
// marking the form as changed and to hide the keyboard
|
||||||
|
FocusScope.of(context).unfocus(
|
||||||
|
disposition: UnfocusDisposition
|
||||||
|
.previouslyFocusedChild);
|
||||||
|
|
||||||
|
onSavePressed!(context);
|
||||||
|
} else {
|
||||||
|
onActionPressed!(context, action);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).toList(),
|
||||||
|
builder: (context, remaining) {
|
||||||
|
return PopupMenuButton<EntityAction>(
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
child: isDesktop(context)
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
localization.more,
|
||||||
|
style: textStyle,
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Icon(Icons.arrow_drop_down,
|
||||||
|
color: state.headerTextColor),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Icon(Icons.more_vert),
|
||||||
|
),
|
||||||
|
onSelected: (EntityAction action) {
|
||||||
|
onActionPressed!(context, action);
|
||||||
|
},
|
||||||
|
itemBuilder: (BuildContext context) {
|
||||||
|
return entityActions
|
||||||
|
.toList()
|
||||||
|
.sublist(entityActions.length - remaining)
|
||||||
|
.map((action) {
|
||||||
|
return PopupMenuItem<EntityAction>(
|
||||||
|
value: action,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(getEntityActionIcon(action),
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
.secondary,
|
.secondary),
|
||||||
),
|
SizedBox(width: 16.0),
|
||||||
SizedBox(width: 16.0),
|
Text(AppLocalization.of(context)!
|
||||||
Text(AppLocalization.of(context)!
|
.lookup(action.toString())),
|
||||||
.lookup(action.toString())),
|
],
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
value: action,
|
}).toList();
|
||||||
))
|
},
|
||||||
.whereType<PopupMenuEntry<EntityAction>>()
|
);
|
||||||
.toList()
|
}),
|
||||||
],
|
),
|
||||||
onSelected: (action) =>
|
),
|
||||||
onActionPressed!(context, action),
|
),
|
||||||
enabled: isEnabled,
|
],
|
||||||
)
|
|
||||||
],
|
|
||||||
bottom: isFullscreen && isDesktop(context)
|
|
||||||
? null
|
|
||||||
: appBarBottom as PreferredSizeWidget?,
|
|
||||||
),
|
),
|
||||||
bottomNavigationBar: bottomNavigationBar,
|
actions: showOverflow
|
||||||
floatingActionButtonLocation:
|
? []
|
||||||
FloatingActionButtonLocation.endDocked,
|
: [
|
||||||
floatingActionButton: floatingActionButton,
|
if (state.isSaving && isMobile(context))
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 20),
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 26,
|
||||||
|
height: 26,
|
||||||
|
child: CircularProgressIndicator(color: Colors.white),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
else if (isDesktop(context))
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: state.isSaving
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (onCancelPressed != null) {
|
||||||
|
onCancelPressed!(context);
|
||||||
|
} else {
|
||||||
|
store.dispatch(ResetSettings());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minWidth: 60),
|
||||||
|
child: IconText(
|
||||||
|
icon: getEntityActionIcon(EntityAction.back),
|
||||||
|
text: (entity != null &&
|
||||||
|
entity!.entityType!.isSetting)
|
||||||
|
? localization.back
|
||||||
|
: localization.cancel,
|
||||||
|
style: state.isSaving ? null : textStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
OutlinedButton(
|
||||||
|
style: isEnabled
|
||||||
|
? ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(
|
||||||
|
state.prefState.colorThemeModel!
|
||||||
|
.colorSuccess))
|
||||||
|
: null,
|
||||||
|
onPressed: !isEnabled ||
|
||||||
|
state.isSaving ||
|
||||||
|
onSavePressed == null
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
// Clear focus now to prevent un-focus after save from
|
||||||
|
// marking the form as changed and to hide the keyboard
|
||||||
|
FocusScope.of(context).unfocus(
|
||||||
|
disposition: UnfocusDisposition
|
||||||
|
.previouslyFocusedChild);
|
||||||
|
|
||||||
|
onSavePressed!(context);
|
||||||
|
},
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minWidth: 60),
|
||||||
|
child: IconText(
|
||||||
|
icon: getEntityActionIcon(EntityAction.save),
|
||||||
|
text: localization.save,
|
||||||
|
style: state.isSaving
|
||||||
|
? null
|
||||||
|
: textStyle.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 16),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
SaveCancelButtons(
|
||||||
|
isEnabled: isEnabled && onSavePressed != null,
|
||||||
|
isHeader: true,
|
||||||
|
isCancelEnabled: isCancelEnabled,
|
||||||
|
saveLabel: saveLabel,
|
||||||
|
cancelLabel: localization.cancel,
|
||||||
|
onSavePressed: onSavePressed == null
|
||||||
|
? null
|
||||||
|
: (context) {
|
||||||
|
// Clear focus now to prevent un-focus after save from
|
||||||
|
// marking the form as changed and to hide the keyboard
|
||||||
|
FocusScope.of(context).unfocus(
|
||||||
|
disposition: UnfocusDisposition
|
||||||
|
.previouslyFocusedChild);
|
||||||
|
|
||||||
|
onSavePressed!(context);
|
||||||
|
},
|
||||||
|
onCancelPressed: isMobile(context)
|
||||||
|
? null
|
||||||
|
: (context) {
|
||||||
|
if (onCancelPressed != null) {
|
||||||
|
onCancelPressed!(context);
|
||||||
|
} else {
|
||||||
|
store.dispatch(ResetSettings());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (actions != null &&
|
||||||
|
actions!.isNotEmpty &&
|
||||||
|
onActionPressed != null)
|
||||||
|
PopupMenuButton<EntityAction>(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.more_vert,
|
||||||
|
//size: iconSize,
|
||||||
|
//color: color,
|
||||||
|
),
|
||||||
|
itemBuilder: (BuildContext context) => [
|
||||||
|
...actions!
|
||||||
|
.map((action) => action == null
|
||||||
|
? PopupMenuDivider()
|
||||||
|
: PopupMenuItem<EntityAction>(
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(
|
||||||
|
getEntityActionIcon(action),
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondary,
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.0),
|
||||||
|
Text(AppLocalization.of(context)!
|
||||||
|
.lookup(action.toString())),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
value: action,
|
||||||
|
))
|
||||||
|
.whereType<PopupMenuEntry<EntityAction>>()
|
||||||
|
.toList()
|
||||||
|
],
|
||||||
|
onSelected: (action) =>
|
||||||
|
onActionPressed!(context, action),
|
||||||
|
enabled: isEnabled,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
bottom: isFullscreen && isDesktop(context)
|
||||||
|
? null
|
||||||
|
: appBarBottom as PreferredSizeWidget?,
|
||||||
),
|
),
|
||||||
|
bottomNavigationBar: bottomNavigationBar,
|
||||||
|
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
||||||
|
floatingActionButton: floatingActionButton,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -124,10 +124,10 @@ class ListScaffold extends StatelessWidget {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return WillPopScope(
|
return PopScope(
|
||||||
onWillPop: () async {
|
canPop: false,
|
||||||
|
onPopInvoked: (_) {
|
||||||
store.dispatch(ViewDashboard());
|
store.dispatch(ViewDashboard());
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
child: FocusTraversalGroup(
|
child: FocusTraversalGroup(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
|
|
|
||||||
|
|
@ -258,8 +258,9 @@ class MainScreen extends StatelessWidget {
|
||||||
print('## Error: main screen route $mainRoute not defined');
|
print('## Error: main screen route $mainRoute not defined');
|
||||||
}
|
}
|
||||||
|
|
||||||
return WillPopScope(
|
return PopScope(
|
||||||
onWillPop: () async {
|
canPop: false,
|
||||||
|
onPopInvoked: (_) async {
|
||||||
final state = store.state;
|
final state = store.state;
|
||||||
final historyList = state.historyList;
|
final historyList = state.historyList;
|
||||||
final isEditing = state.uiState.isEditing;
|
final isEditing = state.uiState.isEditing;
|
||||||
|
|
@ -268,7 +269,6 @@ class MainScreen extends StatelessWidget {
|
||||||
|
|
||||||
if (state.uiState.isPreviewing) {
|
if (state.uiState.isPreviewing) {
|
||||||
store.dispatch(PopPreviewStack());
|
store.dispatch(PopPreviewStack());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = index; i < historyList.length; i++) {
|
for (int i = index; i < historyList.length; i++) {
|
||||||
|
|
@ -300,38 +300,35 @@ class MainScreen extends StatelessWidget {
|
||||||
|
|
||||||
if (history == null) {
|
if (history == null) {
|
||||||
store.dispatch(ViewDashboard());
|
store.dispatch(ViewDashboard());
|
||||||
return false;
|
} else {
|
||||||
|
switch (history.entityType) {
|
||||||
|
case EntityType.dashboard:
|
||||||
|
store.dispatch(ViewDashboard());
|
||||||
|
break;
|
||||||
|
case EntityType.reports:
|
||||||
|
store.dispatch(ViewReports());
|
||||||
|
break;
|
||||||
|
case EntityType.settings:
|
||||||
|
store.dispatch(ViewSettings(
|
||||||
|
section: history.id,
|
||||||
|
company: state.company,
|
||||||
|
user: state.user,
|
||||||
|
tabIndex: 0,
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ((history.id ?? '').isEmpty) {
|
||||||
|
viewEntitiesByType(
|
||||||
|
entityType: history.entityType, page: history.page);
|
||||||
|
} else {
|
||||||
|
viewEntityById(
|
||||||
|
entityId: history.id,
|
||||||
|
entityType: history.entityType,
|
||||||
|
showError: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (history.entityType) {
|
|
||||||
case EntityType.dashboard:
|
|
||||||
store.dispatch(ViewDashboard());
|
|
||||||
break;
|
|
||||||
case EntityType.reports:
|
|
||||||
store.dispatch(ViewReports());
|
|
||||||
break;
|
|
||||||
case EntityType.settings:
|
|
||||||
store.dispatch(ViewSettings(
|
|
||||||
section: history.id,
|
|
||||||
company: state.company,
|
|
||||||
user: state.user,
|
|
||||||
tabIndex: 0,
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if ((history.id ?? '').isEmpty) {
|
|
||||||
viewEntitiesByType(
|
|
||||||
entityType: history.entityType, page: history.page);
|
|
||||||
} else {
|
|
||||||
viewEntityById(
|
|
||||||
entityId: history.id,
|
|
||||||
entityType: history.entityType,
|
|
||||||
showError: false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
child: DesktopSessionTimeout(
|
child: DesktopSessionTimeout(
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
|
|
|
||||||
|
|
@ -89,73 +89,67 @@ class ViewScaffold extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return WillPopScope(
|
return FocusTraversalGroup(
|
||||||
onWillPop: () async {
|
child: Scaffold(
|
||||||
return true;
|
backgroundColor: Theme.of(context).cardColor,
|
||||||
},
|
appBar: AppBar(
|
||||||
child: FocusTraversalGroup(
|
centerTitle: false,
|
||||||
child: Scaffold(
|
leading: leading,
|
||||||
backgroundColor: Theme.of(context).cardColor,
|
automaticallyImplyLeading: isMobile(context),
|
||||||
appBar: AppBar(
|
title: CopyToClipboard(
|
||||||
centerTitle: false,
|
value: appBarTitle,
|
||||||
leading: leading,
|
child: Text(appBarTitle!),
|
||||||
automaticallyImplyLeading: isMobile(context),
|
),
|
||||||
title: CopyToClipboard(
|
bottom: appBarBottom as PreferredSizeWidget?,
|
||||||
value: appBarTitle,
|
actions: entity.isNew
|
||||||
child: Text(appBarTitle!),
|
? []
|
||||||
),
|
: [
|
||||||
bottom: appBarBottom as PreferredSizeWidget?,
|
if (isSettings && isDesktop(context) && !isFilter)
|
||||||
actions: entity.isNew
|
TextButton(
|
||||||
? []
|
onPressed: () {
|
||||||
: [
|
onBackPressed != null
|
||||||
if (isSettings && isDesktop(context) && !isFilter)
|
? onBackPressed!()
|
||||||
TextButton(
|
: store.dispatch(UpdateCurrentRoute(
|
||||||
onPressed: () {
|
state.uiState.previousRoute));
|
||||||
onBackPressed != null
|
},
|
||||||
? onBackPressed!()
|
child: Text(
|
||||||
: store.dispatch(UpdateCurrentRoute(
|
localization!.back,
|
||||||
state.uiState.previousRoute));
|
style: TextStyle(color: state.headerTextColor),
|
||||||
},
|
)),
|
||||||
child: Text(
|
if (isEditable && userCompany.canEditEntity(entity))
|
||||||
localization!.back,
|
Builder(builder: (context) {
|
||||||
style: TextStyle(color: state.headerTextColor),
|
final isDisabled = state.uiState.isEditing &&
|
||||||
)),
|
state.uiState.mainRoute ==
|
||||||
if (isEditable && userCompany.canEditEntity(entity))
|
state.uiState.filterEntityType.toString();
|
||||||
Builder(builder: (context) {
|
|
||||||
final isDisabled = state.uiState.isEditing &&
|
|
||||||
state.uiState.mainRoute ==
|
|
||||||
state.uiState.filterEntityType.toString();
|
|
||||||
|
|
||||||
return AppTextButton(
|
return AppTextButton(
|
||||||
label: localization!.edit,
|
label: localization!.edit,
|
||||||
isInHeader: true,
|
isInHeader: true,
|
||||||
onPressed: isDisabled
|
onPressed: isDisabled
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
editEntity(entity: entity);
|
editEntity(entity: entity);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
ViewActionMenuButton(
|
ViewActionMenuButton(
|
||||||
isSaving: state.isSaving && !isFilter,
|
isSaving: state.isSaving && !isFilter,
|
||||||
entity: entity,
|
entity: entity,
|
||||||
onSelected: (context, action) =>
|
onSelected: (context, action) =>
|
||||||
handleEntityAction(entity, action, autoPop: true),
|
handleEntityAction(entity, action, autoPop: true),
|
||||||
entityActions: entity.getActions(
|
entityActions: entity.getActions(
|
||||||
userCompany: userCompany,
|
userCompany: userCompany,
|
||||||
client: entity is BelongsToClient
|
client: entity is BelongsToClient
|
||||||
? state.clientState
|
? state.clientState
|
||||||
.map[(entity as BelongsToClient).clientId]
|
.map[(entity as BelongsToClient).clientId]
|
||||||
: null,
|
: null,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
body: SafeArea(
|
),
|
||||||
child: entity.isNew
|
body: SafeArea(
|
||||||
? BlankScreen(localization!.noRecordSelected)
|
child:
|
||||||
: body,
|
entity.isNew ? BlankScreen(localization!.noRecordSelected) : body,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -373,29 +373,26 @@ class _DashboardScreenState extends State<DashboardScreen>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return WillPopScope(
|
return isDesktop(context)
|
||||||
onWillPop: () async => true,
|
? Row(
|
||||||
child: isDesktop(context)
|
children: [
|
||||||
? Row(
|
Flexible(
|
||||||
children: [
|
child: mainScaffold,
|
||||||
|
flex: 3,
|
||||||
|
),
|
||||||
|
if (state.dashboardUIState.showSidebar)
|
||||||
Flexible(
|
Flexible(
|
||||||
child: mainScaffold,
|
child: AppBorder(
|
||||||
flex: 3,
|
isLeft: true,
|
||||||
),
|
child: SidebarScaffold(
|
||||||
if (state.dashboardUIState.showSidebar)
|
tabController: _sideTabController,
|
||||||
Flexible(
|
|
||||||
child: AppBorder(
|
|
||||||
isLeft: true,
|
|
||||||
child: SidebarScaffold(
|
|
||||||
tabController: _sideTabController,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
flex: 2,
|
|
||||||
),
|
),
|
||||||
],
|
flex: 2,
|
||||||
)
|
),
|
||||||
: mainScaffold,
|
],
|
||||||
);
|
)
|
||||||
|
: mainScaffold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -326,10 +326,10 @@ class ReportsScreen extends StatelessWidget {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
return WillPopScope(
|
return PopScope(
|
||||||
onWillPop: () async {
|
canPop: false,
|
||||||
|
onPopInvoked: (_) {
|
||||||
store.dispatch(ViewDashboard());
|
store.dispatch(ViewDashboard());
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
drawer: isMobile(context) || state.prefState.isMenuFloated
|
drawer: isMobile(context) || state.prefState.isMenuFloated
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue