added placeholder for empty custom films list

This commit is contained in:
Vadim 2024-10-26 12:55:55 +02:00
parent 68cecf5391
commit 45d7728c85
5 changed files with 145 additions and 116 deletions

View file

@ -95,7 +95,6 @@ class FilmsProviderState extends State<FilmsProvider> {
setState(() {}); setState(() {});
} }
// TODO: add delete button to UI
void deleteCustomFilm(FilmExponential film) { void deleteCustomFilm(FilmExponential film) {
customFilms.remove(film.id); customFilms.remove(film.id);
_discardSelectedIfNotIncluded(); _discardSelectedIfNotIncluded();
@ -170,12 +169,7 @@ class Films extends InheritedModel<_FilmsModelAspect> {
@override @override
bool updateShouldNotifyDependent(Films oldWidget, Set<_FilmsModelAspect> dependencies) { bool updateShouldNotifyDependent(Films oldWidget, Set<_FilmsModelAspect> dependencies) {
if (dependencies.contains(_FilmsModelAspect.customFilmsList)) {}
if (dependencies.contains(_FilmsModelAspect.selected)) {
return selected != oldWidget.selected;
} else {
// TODO: reduce unnecessary notifications // TODO: reduce unnecessary notifications
return true; return true;
} }
} }
}

View file

@ -4,6 +4,7 @@ import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/providers/films_provider.dart'; import 'package:lightmeter/providers/films_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/film_edit/flow_film_edit.dart'; import 'package:lightmeter/screens/film_edit/flow_film_edit.dart';
import 'package:lightmeter/screens/shared/sliver_placeholder/widget_sliver_placeholder.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart'; import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
@ -17,6 +18,14 @@ class FilmsScreen extends StatefulWidget {
class _FilmsScreenState extends State<FilmsScreen> with SingleTickerProviderStateMixin { class _FilmsScreenState extends State<FilmsScreen> with SingleTickerProviderStateMixin {
late final tabController = TabController(length: 2, vsync: this); late final tabController = TabController(length: 2, vsync: this);
@override
void initState() {
super.initState();
tabController.addListener(() {
setState(() {});
});
}
@override @override
void dispose() { void dispose() {
tabController.dispose(); tabController.dispose();
@ -50,22 +59,19 @@ class _FilmsScreenState extends State<FilmsScreen> with SingleTickerProviderStat
), ),
], ],
slivers: [ slivers: [
SliverFillRemaining( if (tabController.index == 0)
child: TabBarView(
controller: tabController,
children: [
_FilmsListBuilder( _FilmsListBuilder(
films: Films.predefinedFilmsOf(context).toList(), films: Films.predefinedFilmsOf(context).toList(),
onFilmSelected: FilmsProvider.of(context).toggleFilm, onFilmSelected: FilmsProvider.of(context).toggleFilm,
), )
else if (tabController.index == 1 && Films.customFilmsOf(context).isNotEmpty)
_FilmsListBuilder<FilmExponential>( _FilmsListBuilder<FilmExponential>(
films: Films.customFilmsOf(context).toList(), films: Films.customFilmsOf(context).toList(),
onFilmSelected: FilmsProvider.of(context).toggleFilm, onFilmSelected: FilmsProvider.of(context).toggleFilm,
onFilmEdit: _editFilm, onFilmEdit: _editFilm,
), )
], else
), SliverPlaceholder(onTap: _addFilm),
),
], ],
); );
} }
@ -98,16 +104,20 @@ class _FilmsListBuilder<T extends Film> extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView.builder( return SliverList.builder(
padding: const EdgeInsets.all(Dimens.paddingM).add(EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom)),
itemCount: films.length, itemCount: films.length,
itemBuilder: (_, index) => Card( itemBuilder: (_, index) => Padding(
padding: EdgeInsets.fromLTRB(
Dimens.paddingM,
index == 0 ? Dimens.paddingM : 0,
Dimens.paddingM,
index == films.length - 1 ? Dimens.paddingM + MediaQuery.paddingOf(context).bottom : 0.0,
),
child: Card(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only( borderRadius: BorderRadius.vertical(
topLeft: index == 0 ? const Radius.circular(Dimens.borderRadiusL) : Radius.zero, top: index == 0 ? const Radius.circular(Dimens.borderRadiusL) : Radius.zero,
topRight: index == 0 ? const Radius.circular(Dimens.borderRadiusL) : Radius.zero, bottom: index == films.length - 1 ? const Radius.circular(Dimens.borderRadiusL) : Radius.zero,
bottomLeft: index == films.length - 1 ? const Radius.circular(Dimens.borderRadiusL) : Radius.zero,
bottomRight: index == films.length - 1 ? const Radius.circular(Dimens.borderRadiusL) : Radius.zero,
), ),
), ),
child: Padding( child: Padding(
@ -131,6 +141,7 @@ class _FilmsListBuilder<T extends Film> extends StatelessWidget {
), ),
), ),
), ),
),
); );
} }
} }

View file

@ -4,7 +4,7 @@ import 'package:lightmeter/providers/equipment_profile_provider.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/widget_container_equipment_profile.dart'; import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/widget_container_equipment_profile.dart';
import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_name_dialog/widget_dialog_equipment_profile_name.dart'; import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_name_dialog/widget_dialog_equipment_profile_name.dart';
import 'package:lightmeter/screens/shared/icon_placeholder/widget_icon_placeholder.dart'; import 'package:lightmeter/screens/shared/sliver_placeholder/widget_sliver_placeholder.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart'; import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
@ -37,12 +37,7 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
), ),
], ],
slivers: profilesCount == 1 slivers: profilesCount == 1
? [ ? [SliverPlaceholder(onTap: _addProfile)]
SliverFillRemaining(
hasScrollBody: false,
child: _EquipmentProfilesListPlaceholder(onTap: _addProfile),
),
]
: [ : [
SliverList( SliverList(
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
@ -131,32 +126,3 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
} }
} }
} }
class _EquipmentProfilesListPlaceholder extends StatelessWidget {
final VoidCallback onTap;
const _EquipmentProfilesListPlaceholder({required this.onTap});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: Dimens.sliverAppBarExpandedHeight),
child: FractionallySizedBox(
widthFactor: 1 / 1.618,
child: Center(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(Dimens.paddingL),
child: IconPlaceholder(
icon: Icons.add_outlined,
text: S.of(context).tapToAdd,
),
),
),
),
),
);
}
}

View file

@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/shared/icon_placeholder/widget_icon_placeholder.dart';
import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart';
class SliverPlaceholder extends StatelessWidget {
final VoidCallback onTap;
const SliverPlaceholder({required this.onTap});
@override
Widget build(BuildContext context) {
final sliverScreenBottomHeight =
context.findAncestorWidgetOfExactType<SliverScreen>()?.bottom?.preferredSize.height ?? 0.0;
return SliverFillRemaining(
hasScrollBody: false,
child: Padding(
padding: EdgeInsets.only(bottom: Dimens.sliverAppBarExpandedHeight - sliverScreenBottomHeight),
child: FractionallySizedBox(
widthFactor: 1 / 1.618,
child: Center(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(Dimens.paddingL),
child: IconPlaceholder(
icon: Icons.add_outlined,
text: S.of(context).tapToAdd,
),
),
),
),
),
),
);
}
}

View file

@ -25,17 +25,41 @@ class SliverScreen extends StatelessWidget {
bottom: false, bottom: false,
child: CustomScrollView( child: CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
SliverAppBar.large( _AppBar(
title: title,
appBarActions: appBarActions,
bottom: bottom,
),
...slivers,
],
),
),
);
}
}
class _AppBar extends StatelessWidget {
final Widget title;
final List<Widget> appBarActions;
final PreferredSizeWidget? bottom;
const _AppBar({
required this.title,
this.appBarActions = const [],
this.bottom,
super.key,
});
@override
Widget build(BuildContext context) {
return SliverAppBar.large(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
expandedHeight: Dimens.sliverAppBarExpandedHeight + (bottom?.preferredSize.height ?? 0.0), expandedHeight: Dimens.sliverAppBarExpandedHeight + (bottom?.preferredSize.height ?? 0.0),
flexibleSpace: FlexibleSpaceBar( flexibleSpace: FlexibleSpaceBar(
centerTitle: false, centerTitle: false,
titlePadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM), titlePadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
title: DefaultTextStyle( title: DefaultTextStyle(
style: Theme.of(context) style: Theme.of(context).textTheme.headlineSmall!.copyWith(color: Theme.of(context).colorScheme.onSurface),
.textTheme
.headlineSmall!
.copyWith(color: Theme.of(context).colorScheme.onSurface),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
child: _Title( child: _Title(
@ -55,11 +79,6 @@ class SliverScreen extends StatelessWidget {
tooltip: S.of(context).tooltipClose, tooltip: S.of(context).tooltipClose,
), ),
], ],
),
...slivers,
],
),
),
); );
} }
} }