Skip to content

Commit

Permalink
feat: Event Type Filter for Events History
Browse files Browse the repository at this point in the history
  • Loading branch information
bdlukaa committed Sep 7, 2024
1 parent 3e415ad commit 48e162e
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 121 deletions.
4 changes: 2 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ class _UnityAppState extends State<UnityApp>
if (settings.name == '/events') {
final data = settings.arguments! as Map;
final event = data['event'] as Event;
final upcomingEvents =
(data['upcoming'] as Iterable<Event>?) ?? [];
final upcomingEvents = (data['upcoming'] as Iterable<Event>?) ??
List.empty(growable: true);
final videoPlayer = data['videoPlayer'] as UnityVideoPlayer?;

return MaterialPageRoute(
Expand Down
134 changes: 134 additions & 0 deletions lib/screens/events_browser/event_type_filter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* This file is a part of Bluecherry Client (https://github.com/bluecherrydvr/unity).
*
* Copyright 2022 Bluecherry, LLC
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import 'package:auto_size_text/auto_size_text.dart';
import 'package:bluecherry_client/models/event.dart';
import 'package:bluecherry_client/providers/events_provider.dart';
import 'package:bluecherry_client/widgets/misc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';

class EventTypeFilterTile extends StatefulWidget {
const EventTypeFilterTile({super.key});

@override
State<EventTypeFilterTile> createState() => _EventTypeFilterTileState();
}

class _EventTypeFilterTileState extends State<EventTypeFilterTile> {
final _eventTypeFilterTileKey = GlobalKey();

@override
Widget build(BuildContext context) {
final loc = AppLocalizations.of(context);
final eventsProvider = context.watch<EventsProvider>();
final theme = Theme.of(context);

return ListTile(
key: _eventTypeFilterTileKey,
dense: true,
title: Text(
loc.eventType,
style: const TextStyle(fontWeight: FontWeight.bold),
),
trailing: AutoSizeText(
() {
final type = eventsProvider.eventTypeFilter;
// For some reason I can not use a switch here
if (type == EventType.motion.index) {
return loc.motion;
} else if (type == EventType.continuous.index) {
return loc.continuous;
} else {
return 'All';
}
}(),
maxLines: 1,
),
onTap: () async {
final box = _eventTypeFilterTileKey.currentContext!.findRenderObject()
as RenderBox;

showMenu(
context: context,
position: RelativeRect.fromRect(
box.localToGlobal(
Offset.zero,
ancestor: Navigator.of(context).context.findRenderObject(),
) &
box.size,
Offset.zero & MediaQuery.of(context).size,
),
constraints: BoxConstraints(
minWidth: box.size.width - 8,
maxWidth: box.size.width - 8,
),
items: <PopupMenuEntry>[
PopupMenuLabel(
label: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 6.0,
),
child: Text(
loc.eventType,
maxLines: 1,
style: theme.textTheme.labelSmall,
),
),
),
const PopupMenuDivider(),
_buildMenuItem(
value: -1,
child: const Text('All'),
),
_buildMenuItem(
value: EventType.motion.index,
child: Text(loc.motion),
),
_buildMenuItem(
value: EventType.continuous.index,
child: Text(loc.continuous),
),
],
);
},
);
}

PopupMenuItem _buildMenuItem({required Widget child, required int value}) {
final eventsProvider = context.read<EventsProvider>();
final selected = eventsProvider.eventTypeFilter == value;

return CheckedPopupMenuItem(
value: value,
padding: const EdgeInsets.symmetric(horizontal: 20.0),
checked: selected,
// enabled: !selected,
onTap: () {
eventsProvider.eventTypeFilter = value;
},
child: Align(
alignment: AlignmentDirectional.centerEnd,
child: child,
),
);
}
}
24 changes: 14 additions & 10 deletions lib/screens/events_browser/events_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,27 @@ class EventsScreenState<T extends StatefulWidget> extends State<T> {
final hasDrawer = Scaffold.hasDrawer(context);

return LayoutBuilder(builder: (context, consts) {
final events =
(eventsProvider.loadedEvents?.filteredEvents ?? List.empty())
.where((event) {
final typeFilter = eventsProvider.eventTypeFilter;
if (typeFilter == -1) return true;
return event.type.index == typeFilter;
});
if (hasDrawer || consts.maxWidth < kMobileBreakpoint.width) {
return EventsScreenMobile(
events: eventsProvider.loadedEvents?.filteredEvents ?? [],
loadedServers: eventsProvider.loadedEvents?.events.keys ?? [],
events: events,
loadedServers:
eventsProvider.loadedEvents?.events.keys ?? List.empty(),
refresh: fetch,
invalid: eventsProvider.loadedEvents?.invalidResponses ?? [],
invalid:
eventsProvider.loadedEvents?.invalidResponses ?? List.empty(),
);
}

return Material(
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
EventsScreenSidebar(
fetch: fetch,
),
EventsScreenSidebar(fetch: fetch),
Expanded(
child: Card(
margin: EdgeInsets.zero,
Expand All @@ -109,10 +116,7 @@ class EventsScreenState<T extends StatefulWidget> extends State<T> {
topStart: Radius.circular(12.0),
),
),
child: EventsScreenDesktop(
events:
eventsProvider.loadedEvents?.filteredEvents ?? List.empty(),
),
child: EventsScreenDesktop(events: events),
),
),
]),
Expand Down
16 changes: 2 additions & 14 deletions lib/screens/events_browser/sidebar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'package:bluecherry_client/providers/events_provider.dart';
import 'package:bluecherry_client/providers/home_provider.dart';
import 'package:bluecherry_client/providers/server_provider.dart';
import 'package:bluecherry_client/screens/events_browser/date_time_filter.dart';
import 'package:bluecherry_client/screens/events_browser/event_type_filter.dart';
import 'package:bluecherry_client/screens/events_browser/filter.dart';
import 'package:bluecherry_client/screens/layouts/device_grid.dart';
import 'package:bluecherry_client/widgets/misc.dart';
Expand Down Expand Up @@ -76,20 +77,7 @@ class _EventsScreenSidebarState extends State<EventsScreenSidebar>
),
const Divider(),
const EventsDateTimeFilter(),
// const SubHeader('Minimum level', height: 24.0),
// DropdownButton<EventsMinLevelFilter>(
// isExpanded: true,
// value: levelFilter,
// items: EventsMinLevelFilter.values.map((level) {
// return DropdownMenuItem(
// value: level,
// child: Text(level.name.uppercaseFirst),
// );
// }).toList(),
// onChanged: (v) => setState(
// () => levelFilter = v ?? levelFilter,
// ),
// ),
const EventTypeFilterTile(),
const SizedBox(height: 8.0),
FilledButton(
onPressed: isLoading ? null : widget.fetch,
Expand Down
97 changes: 2 additions & 95 deletions lib/screens/events_timeline/desktop/timeline_sidebar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
*/

import 'package:auto_size_text/auto_size_text.dart';
import 'package:bluecherry_client/models/event.dart';
import 'package:bluecherry_client/providers/events_provider.dart';
import 'package:bluecherry_client/screens/events_browser/event_type_filter.dart';
import 'package:bluecherry_client/screens/events_browser/filter.dart';
import 'package:bluecherry_client/utils/date.dart';
import 'package:bluecherry_client/utils/methods.dart';
Expand All @@ -46,14 +46,10 @@ class TimelineSidebar extends StatefulWidget {
}

class _TimelineSidebarState extends State<TimelineSidebar> with Searchable {
final _eventTypeFilterTileKey = GlobalKey();

@override
Widget build(BuildContext context) {
final loc = AppLocalizations.of(context);
final eventsProvider = context.watch<EventsProvider>();
final theme = Theme.of(context);

return Card(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadiusDirectional.vertical(
Expand Down Expand Up @@ -119,99 +115,10 @@ class _TimelineSidebarState extends State<TimelineSidebar> with Searchable {
}
},
),
ListTile(
key: _eventTypeFilterTileKey,
dense: true,
title: Text(
loc.eventType,
style: const TextStyle(fontWeight: FontWeight.bold),
),
trailing: AutoSizeText(
() {
final type = eventsProvider.eventTypeFilter;
// For some reason I can not use a switch here
if (type == EventType.motion.index) {
return loc.motion;
} else if (type == EventType.continuous.index) {
return loc.continuous;
} else {
return 'All';
}
}(),
maxLines: 1,
),
onTap: () async {
final box = _eventTypeFilterTileKey.currentContext!
.findRenderObject() as RenderBox;

showMenu(
context: context,
position: RelativeRect.fromRect(
box.localToGlobal(
Offset.zero,
ancestor:
Navigator.of(context).context.findRenderObject(),
) &
box.size,
Offset.zero & MediaQuery.of(context).size,
),
constraints: BoxConstraints(
minWidth: box.size.width - 8,
maxWidth: box.size.width - 8,
),
items: <PopupMenuEntry>[
PopupMenuLabel(
label: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 6.0,
),
child: Text(
loc.eventType,
maxLines: 1,
style: theme.textTheme.labelSmall,
),
),
),
const PopupMenuDivider(),
_buildMenuItem(
value: -1,
child: const Text('All'),
),
_buildMenuItem(
value: EventType.motion.index,
child: Text(loc.motion),
),
_buildMenuItem(
value: EventType.continuous.index,
child: Text(loc.continuous),
),
],
);
},
),
const EventTypeFilterTile(),
]);
},
),
);
}

PopupMenuItem _buildMenuItem({required Widget child, required int value}) {
final eventsProvider = context.read<EventsProvider>();
final selected = eventsProvider.eventTypeFilter == value;

return CheckedPopupMenuItem(
value: value,
padding: const EdgeInsets.symmetric(horizontal: 20.0),
checked: selected,
// enabled: !selected,
onTap: () {
eventsProvider.eventTypeFilter = value;
},
child: Align(
alignment: AlignmentDirectional.centerEnd,
child: child,
),
);
}
}

0 comments on commit 48e162e

Please sign in to comment.