import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/data/models/client_model.dart'; import 'package:invoiceninja_flutter/data/models/entities.dart'; import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/redux/app/app_actions.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/ui/app/actions_menu_button.dart'; import 'package:invoiceninja_flutter/ui/app/entity_state_label.dart'; import 'package:invoiceninja_flutter/ui/app/lists/list_divider.dart'; import 'package:invoiceninja_flutter/ui/app/lists/selected_indicator.dart'; import 'package:invoiceninja_flutter/utils/icons.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; class EntityListTile extends StatefulWidget { const EntityListTile({ @required this.entity, @required this.isFilter, this.onEntityActionSelected, this.subtitle, this.client, }); final String subtitle; final BaseEntity entity; final bool isFilter; final ClientEntity client; final Function(BuildContext, BaseEntity, EntityAction) onEntityActionSelected; @override _EntityListTileState createState() => _EntityListTileState(); } class _EntityListTileState extends State { bool _isHovered = false; @override Widget build(BuildContext context) { if (widget.entity == null) { return SizedBox(); } final localization = AppLocalization.of(context); final store = StoreProvider.of(context); final state = store.state; final isFilteredBy = state.uiState.filterEntityId == widget.entity.id && state.uiState.filterEntityType == widget.entity.entityType; final entityClient = widget.client ?? (widget.entity is BelongsToClient ? state.clientState.map[(widget.entity as BelongsToClient).clientId] : null); final showMoreIcon = (!RendererBinding.instance.mouseTracker.mouseIsConnected && isFilteredBy) || _isHovered; final leading = ActionMenuButton( iconData: showMoreIcon ? Icons.more_vert : getEntityIcon(widget.entity.entityType), iconSize: showMoreIcon ? null : 18, entityActions: widget.entity.getActions( userCompany: state.userCompany, includeEdit: true, client: entityClient), isSaving: false, color: isFilteredBy ? (state.prefState.enableDarkMode ? Colors.white : Theme.of(context).accentColor) : null, entity: widget.entity, onSelected: (context, action) => widget.onEntityActionSelected != null ? widget.onEntityActionSelected(context, widget.entity, action) : handleEntityAction(context, widget.entity, action), ); Widget trailing; if (isNotMobile(context) && widget.isFilter != true) { if (isFilteredBy) { trailing = IconButton( color: state.prefState.enableDarkMode ? Colors.white : Theme.of(context).accentColor, icon: Icon(Icons.chevron_right), onPressed: () => viewEntity(entity: widget.entity, context: context), ); } else { trailing = IgnorePointer( child: IconButton( icon: Icon(Icons.filter_list), onPressed: () => null, ), ); } } else { trailing = IgnorePointer( child: IconButton( icon: Icon(Icons.navigate_next), onPressed: () => null, ), ); } return MouseRegion( onEnter: (event) => setState(() => _isHovered = true), onExit: (event) => setState(() => _isHovered = false), child: Column( mainAxisSize: MainAxisSize.min, children: [ SelectedIndicator( isSelected: isFilteredBy && isDesktop(context), isMenu: true, child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16), onTap: () => inspectEntity(context: context, entity: widget.entity), onLongPress: () => inspectEntity( context: context, entity: widget.entity, longPress: true), title: Text(localization.lookup('${widget.entity.entityType}') + ' › ' + widget.entity.listDisplayName), subtitle: (widget.subtitle ?? '').isEmpty && widget.entity.isActive ? null : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if ((widget.subtitle ?? '').isNotEmpty) Text(widget.subtitle), if (!widget.entity.isActive) EntityStateLabel(widget.entity), ], ), leading: leading, trailing: trailing, isThreeLine: (widget.subtitle ?? '').isNotEmpty && !widget.entity.isActive, ), ), ListDivider(), ], ), ); } } class EntitiesListTile extends StatelessWidget { const EntitiesListTile({ this.entityType, this.onTap, this.onLongPress, this.title, this.subtitle, @required this.isFilter, }); final Function onTap; final Function onLongPress; final EntityType entityType; final String title; final String subtitle; final bool isFilter; @override Widget build(BuildContext context) { final store = StoreProvider.of(context); final state = store.state; final mainRoute = state.uiState.mainRoute; final isFilterMatch = isFilter && '$entityType' == mainRoute; return Column( mainAxisSize: MainAxisSize.min, children: [ SelectedIndicator( isSelected: isFilterMatch, isMenu: true, child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16), title: Text(title), subtitle: Text(subtitle ?? ''), leading: IgnorePointer( child: IconButton( icon: Icon(getEntityIcon(entityType), size: 18.0), onPressed: onTap, ), ), trailing: isFilter ? onLongPress == null ? SizedBox() : IconButton( icon: Icon(Icons.add_circle_outline), onPressed: onLongPress, ) : IgnorePointer( child: IconButton( icon: Icon(Icons.navigate_next), onPressed: () => null, ), ), onTap: onTap, onLongPress: onLongPress, ), ), ListDivider(), ], ); } }