ML-113 Add ability to copy equipment profile (#120)

* Display range values instead of values count

* copy equipment profile

* added `IconButton` tooltips
This commit is contained in:
Vadim 2023-09-18 16:59:53 +02:00 committed by GitHub
parent 0fbf252d9e
commit abbc4c92de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 136 additions and 59 deletions

View file

@ -36,7 +36,7 @@ class EquipmentProfileProviderState extends State<EquipmentProfileProvider> {
void setProfile(EquipmentProfile data) {} void setProfile(EquipmentProfile data) {}
void addProfile(String name) {} void addProfile(String name, [EquipmentProfile? copyFrom]) {}
void updateProdile(EquipmentProfile data) {} void updateProdile(EquipmentProfile data) {}

View file

@ -96,5 +96,17 @@
"buyLightmeterPro": "Buy Lightmeter Pro", "buyLightmeterPro": "Buy Lightmeter Pro",
"lightmeterPro": "Lightmeter Pro", "lightmeterPro": "Lightmeter Pro",
"lightmeterProDescription": "Unlocks extra features, such as equipment profiles containing filters for aperture, shutter speed, and more; and a list of films with compensation for what's known as reciprocity failure.\n\nThe source code of Lightmeter is available on GitHub. You are welcome to compile it yourself. However, if you want to support the development and receive new features and updates, consider purchasing Lightmeter Pro.", "lightmeterProDescription": "Unlocks extra features, such as equipment profiles containing filters for aperture, shutter speed, and more; and a list of films with compensation for what's known as reciprocity failure.\n\nThe source code of Lightmeter is available on GitHub. You are welcome to compile it yourself. However, if you want to support the development and receive new features and updates, consider purchasing Lightmeter Pro.",
"buy": "Buy" "buy": "Buy",
"tooltipAdd": "Add",
"tooltipClose": "Close",
"tooltipExpand": "Expand",
"tooltipCollapse": "Collapse",
"tooltipCopy": "Copy",
"tooltipDelete": "Delete",
"tooltipSelectAll": "Select all",
"tooltipDesecelectAll": "Deselect all",
"tooltipResetToZero": "Reset to zero",
"tooltipUseLightSensor": "Use lightsensor",
"tooltipUseCamera": "Use camera",
"tooltipOpenSettings": "Open settings"
} }

View file

@ -96,5 +96,17 @@
"buyLightmeterPro": "Acheter Lightmeter Pro", "buyLightmeterPro": "Acheter Lightmeter Pro",
"lightmeterPro": "Lightmeter Pro", "lightmeterPro": "Lightmeter Pro",
"lightmeterProDescription": "Déverrouille des fonctionnalités supplémentaires, telles que des profils d'équipement contenant des filtres pour l'ouverture, la vitesse d'obturation et plus encore, ainsi qu'une liste de films avec une compensation pour ce que l'on appelle l'échec de réciprocité.\n\nLe code source du Lightmeter est disponible sur GitHub. Vous pouvez le compiler vous-même. Cependant, si vous souhaitez soutenir le développement et recevoir de nouvelles fonctionnalités et mises à jour, envisagez d'acheter Lightmeter Pro.", "lightmeterProDescription": "Déverrouille des fonctionnalités supplémentaires, telles que des profils d'équipement contenant des filtres pour l'ouverture, la vitesse d'obturation et plus encore, ainsi qu'une liste de films avec une compensation pour ce que l'on appelle l'échec de réciprocité.\n\nLe code source du Lightmeter est disponible sur GitHub. Vous pouvez le compiler vous-même. Cependant, si vous souhaitez soutenir le développement et recevoir de nouvelles fonctionnalités et mises à jour, envisagez d'acheter Lightmeter Pro.",
"buy": "Acheter" "buy": "Acheter",
"tooltipAdd": "Ajouter",
"tooltipClose": "Fermer",
"tooltipExpand": "Élargir",
"tooltipCollapse": "Effondrement",
"tooltipCopy": "Copie",
"tooltipDelete": "Supprimer",
"tooltipSelectAll": "Tout sélectionner",
"tooltipDesecelectAll": "Désélectionner tout",
"tooltipResetToZero": "Remise à zéro",
"tooltipUseLightSensor": "Utiliser un capteur de lumière",
"tooltipUseCamera": "Utiliser la caméra",
"tooltipOpenSettings": "Ouvrir les paramètres"
} }

View file

@ -96,5 +96,17 @@
"buyLightmeterPro": "Купить Lightmeter Pro", "buyLightmeterPro": "Купить Lightmeter Pro",
"lightmeterPro": "Lightmeter Pro", "lightmeterPro": "Lightmeter Pro",
"lightmeterProDescription": "Даёт доступ к таким функциям как профили оборудования, содержащие фильтры для диафрагмы, выдержки и других значений, а также набору пленок с компенсацией эффекта Шварцшильда.\n\nИсходный код Lightmeter доступен на GitHub. Вы можете собрать его самостоятельно. Однако если вы хотите поддержать разработку и получать новые функции и обновления, то приобретите Lightmeter Pro.", "lightmeterProDescription": "Даёт доступ к таким функциям как профили оборудования, содержащие фильтры для диафрагмы, выдержки и других значений, а также набору пленок с компенсацией эффекта Шварцшильда.\n\nИсходный код Lightmeter доступен на GitHub. Вы можете собрать его самостоятельно. Однако если вы хотите поддержать разработку и получать новые функции и обновления, то приобретите Lightmeter Pro.",
"buy": "Купить" "buy": "Купить",
"tooltipAdd": "Добавить",
"tooltipClose": "Закрыть",
"tooltipExpand": "Развернуть",
"tooltipCollapse": "Свернуть",
"tooltipCopy": "Скопировать",
"tooltipDelete": "Удалить",
"tooltipSelectAll": "Выбрать все",
"tooltipDesecelectAll": "Отменить все",
"tooltipResetToZero": "Сбросить до 0",
"tooltipUseLightSensor": "Использовать датчик освещенности",
"tooltipUseCamera": "Использовать камеру",
"tooltipOpenSettings": "Открыть настройки"
} }

View file

@ -96,5 +96,17 @@
"buyLightmeterPro": "Buy Lightmeter Pro", "buyLightmeterPro": "Buy Lightmeter Pro",
"lightmeterPro": "Lightmeter Pro", "lightmeterPro": "Lightmeter Pro",
"lightmeterProDescription": "Unlocks extra features, such as equipment profiles containing filters for aperture, shutter speed, and more; and a list of films with compensation for what's known as reciprocity failure.\n\nThe source code of Lightmeter is available on GitHub. You are welcome to compile it yourself. However, if you want to support the development and receive new features and updates, consider purchasing Lightmeter Pro.", "lightmeterProDescription": "Unlocks extra features, such as equipment profiles containing filters for aperture, shutter speed, and more; and a list of films with compensation for what's known as reciprocity failure.\n\nThe source code of Lightmeter is available on GitHub. You are welcome to compile it yourself. However, if you want to support the development and receive new features and updates, consider purchasing Lightmeter Pro.",
"buy": "Buy" "buy": "Buy",
"tooltipAdd": "Add",
"tooltipClose": "Close",
"tooltipExpand": "Expand",
"tooltipCollapse": "Collapse",
"tooltipCopy": "Copy",
"tooltipDelete": "Delete",
"tooltipSelectAll": "Select all",
"tooltipDesecelectAll": "Deselect all",
"resetToZero": "Reset to zero",
"tooltipUseLightSensor": "Use lightsensor",
"tooltipUseCamera": "Use camera",
"tooltipOpenSettings": "Open settings"
} }

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/ev_source_type.dart'; import 'package:lightmeter/data/models/ev_source_type.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart'; import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/bottom_controls/components/measure_button/widget_button_measure.dart'; import 'package:lightmeter/screens/metering/components/bottom_controls/components/measure_button/widget_button_measure.dart';
@ -46,6 +47,10 @@ class MeteringBottomControls extends StatelessWidget {
? Icons.camera_rear ? Icons.camera_rear
: Icons.wb_incandescent, : Icons.wb_incandescent,
), ),
tooltip:
UserPreferencesProvider.evSourceTypeOf(context) != EvSourceType.camera
? S.of(context).tooltipUseCamera
: S.of(context).tooltipUseLightSensor,
), ),
), ),
) )
@ -61,6 +66,7 @@ class MeteringBottomControls extends StatelessWidget {
child: IconButton( child: IconButton(
onPressed: onSettings, onPressed: onSettings,
icon: const Icon(Icons.settings), icon: const Icon(Icons.settings),
tooltip: S.of(context).tooltipOpenSettings,
), ),
), ),
), ),

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/shared/centered_slider/widget_slider_centered.dart'; import 'package:lightmeter/screens/shared/centered_slider/widget_slider_centered.dart';
import 'package:lightmeter/utils/to_string_signed.dart'; import 'package:lightmeter/utils/to_string_signed.dart';
@ -22,6 +23,7 @@ class ExposureOffsetSlider extends StatelessWidget {
IconButton( IconButton(
icon: const Icon(Icons.sync), icon: const Icon(Icons.sync),
onPressed: value != 0.0 ? () => onChanged(0.0) : null, onPressed: value != 0.0 ? () => onChanged(0.0) : null,
tooltip: S.of(context).tooltipResetToZero,
), ),
Expanded( Expanded(
child: Row( child: Row(

View file

@ -36,9 +36,6 @@ class EquipmentListTiles extends StatelessWidget {
title: S.of(context).isoValues, title: S.of(context).isoValues,
description: S.of(context).isoValuesFilterDescription, description: S.of(context).isoValuesFilterDescription,
values: IsoValue.values, values: IsoValue.values,
valuesCount: selectedIsoValues.length == IsoValue.values.length
? S.of(context).equipmentProfileAllValues
: selectedIsoValues.length.toString(),
selectedValues: selectedIsoValues, selectedValues: selectedIsoValues,
rangeSelect: false, rangeSelect: false,
onChanged: onIsoValuesSelecred, onChanged: onIsoValuesSelecred,
@ -48,9 +45,6 @@ class EquipmentListTiles extends StatelessWidget {
title: S.of(context).ndFilters, title: S.of(context).ndFilters,
description: S.of(context).ndFiltersFilterDescription, description: S.of(context).ndFiltersFilterDescription,
values: NdValue.values, values: NdValue.values,
valuesCount: selectedNdValues.length == NdValue.values.length
? S.of(context).equipmentProfileAllValues
: selectedNdValues.length.toString(),
selectedValues: selectedNdValues, selectedValues: selectedNdValues,
rangeSelect: false, rangeSelect: false,
onChanged: onNdValuesSelected, onChanged: onNdValuesSelected,
@ -60,9 +54,6 @@ class EquipmentListTiles extends StatelessWidget {
title: S.of(context).apertureValues, title: S.of(context).apertureValues,
description: S.of(context).apertureValuesFilterDescription, description: S.of(context).apertureValuesFilterDescription,
values: ApertureValue.values, values: ApertureValue.values,
valuesCount: selectedApertureValues.length == ApertureValue.values.length
? S.of(context).equipmentProfileAllValues
: selectedApertureValues.length.toString(),
selectedValues: selectedApertureValues, selectedValues: selectedApertureValues,
rangeSelect: true, rangeSelect: true,
onChanged: onApertureValuesSelected, onChanged: onApertureValuesSelected,
@ -72,9 +63,6 @@ class EquipmentListTiles extends StatelessWidget {
title: S.of(context).shutterSpeedValues, title: S.of(context).shutterSpeedValues,
description: S.of(context).shutterSpeedValuesFilterDescription, description: S.of(context).shutterSpeedValuesFilterDescription,
values: ShutterSpeedValue.values, values: ShutterSpeedValue.values,
valuesCount: selectedShutterSpeedValues.length == ShutterSpeedValue.values.length
? S.of(context).equipmentProfileAllValues
: selectedShutterSpeedValues.length.toString(),
selectedValues: selectedShutterSpeedValues, selectedValues: selectedShutterSpeedValues,
rangeSelect: true, rangeSelect: true,
onChanged: onShutterSpeedValuesSelected, onChanged: onShutterSpeedValuesSelected,
@ -87,7 +75,6 @@ class EquipmentListTiles extends StatelessWidget {
class _EquipmentListTile<T extends PhotographyValue> extends StatelessWidget { class _EquipmentListTile<T extends PhotographyValue> extends StatelessWidget {
final IconData icon; final IconData icon;
final String title; final String title;
final String valuesCount;
final String description; final String description;
final List<T> selectedValues; final List<T> selectedValues;
final List<T> values; final List<T> values;
@ -97,7 +84,6 @@ class _EquipmentListTile<T extends PhotographyValue> extends StatelessWidget {
const _EquipmentListTile({ const _EquipmentListTile({
required this.icon, required this.icon,
required this.title, required this.title,
required this.valuesCount,
required this.description, required this.description,
required this.selectedValues, required this.selectedValues,
required this.values, required this.values,
@ -111,7 +97,13 @@ class _EquipmentListTile<T extends PhotographyValue> extends StatelessWidget {
return ListTile( return ListTile(
leading: Icon(icon), leading: Icon(icon),
title: Text(title), title: Text(title),
trailing: Text(valuesCount), trailing: rangeSelect
? Text("${selectedValues.first} - ${selectedValues.last}")
: Text(
values.length == selectedValues.length
? S.of(context).equipmentProfileAllValues
: selectedValues.length.toString(),
),
onTap: () { onTap: () {
showDialog<List<T>>( showDialog<List<T>>(
context: context, context: context,

View file

@ -2,6 +2,7 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/components/equipment_list_tiles/widget_list_tiles_equipments.dart'; import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/components/equipment_list_tiles/widget_list_tiles_equipments.dart';
import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_name_dialog/widget_dialog_equipment_profile_name.dart'; import 'package:lightmeter/screens/settings/components/equipment/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_name_dialog/widget_dialog_equipment_profile_name.dart';
@ -10,12 +11,14 @@ import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
class EquipmentProfileContainer extends StatefulWidget { class EquipmentProfileContainer extends StatefulWidget {
final EquipmentProfile data; final EquipmentProfile data;
final ValueChanged<EquipmentProfile> onUpdate; final ValueChanged<EquipmentProfile> onUpdate;
final VoidCallback onCopy;
final VoidCallback onDelete; final VoidCallback onDelete;
final VoidCallback onExpand; final VoidCallback onExpand;
const EquipmentProfileContainer({ const EquipmentProfileContainer({
required this.data, required this.data,
required this.onUpdate, required this.onUpdate,
required this.onCopy,
required this.onDelete, required this.onDelete,
required this.onExpand, required this.onExpand,
super.key, super.key,
@ -85,20 +88,10 @@ class EquipmentProfileContainerState extends State<EquipmentProfileContainer>
), ),
], ],
), ),
trailing: Row( trailing: _AnimatedArrowButton(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
_AnimatedArrowButton(
controller: _controller, controller: _controller,
onPressed: () => _expanded ? collapse() : expand(), onPressed: () => _expanded ? collapse() : expand(),
), ),
IconButton(
onPressed: widget.onDelete,
icon: const Icon(Icons.delete),
),
],
),
onTap: () => _expanded ? _showNameDialog() : expand(), onTap: () => _expanded ? _showNameDialog() : expand(),
), ),
_AnimatedEquipmentListTiles( _AnimatedEquipmentListTiles(
@ -120,6 +113,8 @@ class EquipmentProfileContainerState extends State<EquipmentProfileContainer>
_equipmentData = _equipmentData.copyWith(shutterSpeedValues: value); _equipmentData = _equipmentData.copyWith(shutterSpeedValues: value);
widget.onUpdate(_equipmentData); widget.onUpdate(_equipmentData);
}, },
onCopy: widget.onCopy,
onDelete: widget.onDelete,
), ),
], ],
), ),
@ -194,6 +189,7 @@ class _AnimatedArrowButton extends AnimatedWidget {
angle: _progress.value * pi, angle: _progress.value * pi,
child: const Icon(Icons.keyboard_arrow_down), child: const Icon(Icons.keyboard_arrow_down),
), ),
tooltip: _progress.value == 0 ? S.of(context).tooltipExpand : S.of(context).tooltipCollapse,
); );
} }
} }
@ -204,6 +200,8 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
final ValueChanged<List<IsoValue>> onIsoValuesSelecred; final ValueChanged<List<IsoValue>> onIsoValuesSelecred;
final ValueChanged<List<NdValue>> onNdValuesSelected; final ValueChanged<List<NdValue>> onNdValuesSelected;
final ValueChanged<List<ShutterSpeedValue>> onShutterSpeedValuesSelected; final ValueChanged<List<ShutterSpeedValue>> onShutterSpeedValuesSelected;
final VoidCallback onCopy;
final VoidCallback onDelete;
const _AnimatedEquipmentListTiles({ const _AnimatedEquipmentListTiles({
required AnimationController controller, required AnimationController controller,
@ -212,6 +210,8 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
required this.onIsoValuesSelecred, required this.onIsoValuesSelecred,
required this.onNdValuesSelected, required this.onNdValuesSelected,
required this.onShutterSpeedValuesSelected, required this.onShutterSpeedValuesSelected,
required this.onCopy,
required this.onDelete,
}) : super(listenable: controller); }) : super(listenable: controller);
Animation<double> get _progress => listenable as Animation<double>; Animation<double> get _progress => listenable as Animation<double>;
@ -222,11 +222,14 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
alignment: Alignment.topCenter, alignment: Alignment.topCenter,
size: Size( size: Size(
double.maxFinite, double.maxFinite,
_progress.value * Dimens.grid56 * 4, _progress.value * Dimens.grid56 * 5,
), ),
// https://github.com/gskinnerTeam/flutter-folio/pull/62
child: Opacity( child: Opacity(
opacity: _progress.value, opacity: _progress.value,
child: EquipmentListTiles( child: Column(
children: [
EquipmentListTiles(
selectedApertureValues: equipmentData.apertureValues, selectedApertureValues: equipmentData.apertureValues,
selectedIsoValues: equipmentData.isoValues, selectedIsoValues: equipmentData.isoValues,
selectedNdValues: equipmentData.ndValues, selectedNdValues: equipmentData.ndValues,
@ -236,6 +239,27 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
onNdValuesSelected: onNdValuesSelected, onNdValuesSelected: onNdValuesSelected,
onShutterSpeedValuesSelected: onShutterSpeedValuesSelected, onShutterSpeedValuesSelected: onShutterSpeedValuesSelected,
), ),
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
trailing: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: onCopy,
icon: const Icon(Icons.copy),
tooltip: S.of(context).tooltipCopy,
),
IconButton(
onPressed: onDelete,
icon: const Icon(Icons.delete),
tooltip: S.of(context).tooltipDelete,
),
],
),
),
],
),
), ),
); );
} }

View file

@ -34,10 +34,7 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
IconButton( IconButton(
onPressed: _addProfile, onPressed: _addProfile,
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
), tooltip: S.of(context).tooltipAdd,
IconButton(
onPressed: Navigator.of(context).pop,
icon: const Icon(Icons.close),
), ),
], ],
slivers: profilesCount == 1 slivers: profilesCount == 1
@ -69,6 +66,7 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
data: profile, data: profile,
onExpand: () => _keepExpandedAt(index), onExpand: () => _keepExpandedAt(index),
onUpdate: _updateProfileAt, onUpdate: _updateProfileAt,
onCopy: () => _addProfile(profile),
onDelete: () => _removeProfileAt(profile), onDelete: () => _removeProfileAt(profile),
), ),
); );
@ -81,13 +79,13 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
); );
} }
void _addProfile() { void _addProfile([EquipmentProfile? copyFrom]) {
showDialog<String>( showDialog<String>(
context: context, context: context,
builder: (_) => const EquipmentProfileNameDialog(), builder: (_) => const EquipmentProfileNameDialog(),
).then((value) { ).then((name) {
if (value != null) { if (name != null) {
EquipmentProfileProvider.of(context).addProfile(value); EquipmentProfileProvider.of(context).addProfile(name, copyFrom);
} }
}); });
} }

View file

@ -117,6 +117,7 @@ class _CalibrationUnit extends StatelessWidget {
IconButton( IconButton(
onPressed: onReset, onPressed: onReset,
icon: const Icon(Icons.sync), icon: const Icon(Icons.sync),
tooltip: S.of(context).tooltipResetToZero,
), ),
], ],
) )

View file

@ -85,6 +85,9 @@ class _DialogFilterState<T> extends State<DialogFilter<T>> {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
icon: Icon(_hasAnyUnselected ? Icons.select_all : Icons.deselect), icon: Icon(_hasAnyUnselected ? Icons.select_all : Icons.deselect),
onPressed: _toggleAll, onPressed: _toggleAll,
tooltip: _hasAnyUnselected
? S.of(context).tooltipSelectAll
: S.of(context).tooltipDesecelectAll,
), ),
), ),
const Spacer(), const Spacer(),

View file

@ -35,12 +35,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
return ScaffoldMessenger( return ScaffoldMessenger(
child: SliverScreen( child: SliverScreen(
title: S.of(context).settings, title: S.of(context).settings,
appBarActions: [
IconButton(
onPressed: Navigator.of(context).pop,
icon: const Icon(Icons.close),
),
],
slivers: [ slivers: [
SliverList( SliverList(
delegate: SliverChildListDelegate( delegate: SliverChildListDelegate(

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
class SliverScreen extends StatelessWidget { class SliverScreen extends StatelessWidget {
@ -8,7 +9,7 @@ class SliverScreen extends StatelessWidget {
const SliverScreen({ const SliverScreen({
required this.title, required this.title,
required this.appBarActions, this.appBarActions = const [],
required this.slivers, required this.slivers,
super.key, super.key,
}); });
@ -36,7 +37,15 @@ class SliverScreen extends StatelessWidget {
), ),
), ),
), ),
actions: appBarActions, actions: [
...appBarActions,
if (Navigator.of(context).canPop())
IconButton(
onPressed: Navigator.of(context).pop,
icon: const Icon(Icons.close),
tooltip: S.of(context).tooltipClose,
),
],
), ),
...slivers, ...slivers,
], ],