Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _i1;

import '../../../_features/books/models/library_book.dart' as _i2;

abstract class LibraryBookLocation implements _i1.SerializableModel {
Expand Down Expand Up @@ -66,6 +67,17 @@ abstract class LibraryBookLocation implements _i1.SerializableModel {
String toString() {
return _i1.SerializationManager.encode(this);
}

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is LibraryBookLocation &&
other.id == id &&
other.location == location;
}

@override
int get hashCode => Object.hash(id, location);
}

class _Undefined {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ class _CheckForUpdatesPageState extends State<CheckForUpdatesPage> {
),
),

bottomNavigationBar: const BottomNavBarNoFilterButton(),
bottomNavigationBar: GenericBottomNavBarWithActions(),
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import 'package:gap/gap.dart';
import 'package:school_data_hub_flutter/common/theme/app_colors.dart';
import 'package:school_data_hub_flutter/common/widgets/bottom_nav_bar_layouts.dart';

class BottomNavBarNoFilterButton extends StatelessWidget {
const BottomNavBarNoFilterButton({super.key});
class GenericBottomNavBarWithActions extends StatelessWidget {
final List<Widget>? actions;
GenericBottomNavBarWithActions({this.actions, super.key});

@override
Widget build(BuildContext context) {
Expand All @@ -28,6 +29,8 @@ class BottomNavBarNoFilterButton extends StatelessWidget {
Navigator.pop(context);
},
),
if (actions != null)
for (var action in actions!) ...[const Gap(15), action],
const Gap(15),
],
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:school_data_hub_flutter/app_utils/create_and_crop_image_file.dart';
import 'package:school_data_hub_flutter/common/theme/app_colors.dart';
Expand All @@ -22,7 +23,16 @@ class UnencryptedImageInCard extends HookWidget {

@override
Widget build(BuildContext context) {
final refreshState = useState(0);
final randomPart = useMemoized(() => UniqueKey().toString(), []);
final imageFuture = useMemoized(
() => cachedPublicImageOrDownloadPublicImage(
path: path,
cacheKey: cacheKey,
),
[path, cacheKey, refreshState.value],
);

return SizedBox(
height: size,
width: (21 / 30) * size,
Expand All @@ -31,18 +41,18 @@ class UnencryptedImageInCard extends HookWidget {
onLongPress: () async {
final File? file = await createAndCropImageFile(context);
if (file == null) return;

await di<DefaultCacheManager>().removeFile(cacheKey);
await di<BookManager>().updateBookImage(
file: file,
isbn: int.tryParse(cacheKey)!,
);
refreshState.value++;
},
child: WidgetZoom(
heroAnimationTag: '$cacheKey$randomPart',
zoomWidget: FutureBuilder<Image>(
future: cachedPublicImageOrDownloadPublicImage(
path: path,
cacheKey: cacheKey,
),
future: imageFuture,
builder: (context, snapshot) {
Widget child;
if (snapshot.connectionState == ConnectionState.waiting) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:logging/logging.dart';
import 'package:school_data_hub_client/school_data_hub_client.dart';
import 'package:school_data_hub_flutter/core/models/datetime_extensions.dart';
import 'package:school_data_hub_flutter/common/services/notification_service.dart';
import 'package:school_data_hub_flutter/common/theme/app_colors.dart';
import 'package:school_data_hub_flutter/common/widgets/generic_components/generic_sliver_list.dart';
import 'package:school_data_hub_flutter/common/widgets/generic_components/generic_sliver_search_app_bar.dart';
import 'package:school_data_hub_flutter/core/models/datetime_extensions.dart';
import 'package:school_data_hub_flutter/core/session/hub_session_manager.dart';
import 'package:school_data_hub_flutter/features/_attendance/domain/attendance_helper_functions.dart';
import 'package:school_data_hub_flutter/features/_attendance/domain/attendance_manager.dart';
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:school_data_hub_client/school_data_hub_client.dart';
import 'package:school_data_hub_flutter/common/domain/filters/filters_state_manager.dart';
import 'package:school_data_hub_flutter/features/_schoolday_events/domain/models/schoolday_event_enums.dart';
Expand Down Expand Up @@ -157,6 +158,39 @@ class SchooldayEventFilterManager {
}
}

if (activeFilters[SchooldayEventFilter.duringBreak]!) {
if (schooldayEvent.eventTime == null) {
continue;
}
final eventTimeOfDay = TimeOfDay(
hour: int.parse(schooldayEvent.eventTime!.split(':')[0]),
minute: int.parse(schooldayEvent.eventTime!.split(':')[1]),
);
if (eventTimeOfDay.isAfter(const TimeOfDay(hour: 10, minute: 29)) &&
eventTimeOfDay.isBefore(const TimeOfDay(hour: 11, minute: 20))) {
isMatched = true;
complementaryFilter = true;
} else if (!complementaryFilter) {
isMatched = false;
}
}
if (activeFilters[SchooldayEventFilter.notDuringBreak]!) {
if (schooldayEvent.eventTime == null) {
continue;
}
final eventTimeOfDay = TimeOfDay(
hour: int.parse(schooldayEvent.eventTime!.split(':')[0]),
minute: int.parse(schooldayEvent.eventTime!.split(':')[1]),
);
if (eventTimeOfDay.isBefore(const TimeOfDay(hour: 10, minute: 29)) ||
eventTimeOfDay.isAfter(const TimeOfDay(hour: 11, minute: 20))) {
isMatched = true;
complementaryFilter = true;
} else if (!complementaryFilter) {
isMatched = false;
}
}

//- The behavior of this first filter group should be
//- excluding for the next filter group
//- let's tidy up the list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ enum SchooldayEventFilter {
admonitionInfo,
transitionAdvice,
processed,
duringBreak,
notDuringBreak,
}

Map<SchooldayEventFilter, bool> initialSchooldayEventFilterValues = {
Expand All @@ -61,4 +63,6 @@ Map<SchooldayEventFilter, bool> initialSchooldayEventFilterValues = {
SchooldayEventFilter.admonitionInfo: false,
SchooldayEventFilter.transitionAdvice: false,
SchooldayEventFilter.processed: false,
SchooldayEventFilter.duringBreak: false,
SchooldayEventFilter.notDuringBreak: false,
};
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ class SchooldayEventFilterBottomSheet extends WatchingWidget {
activeSchooldayEventFilters[SchooldayEventFilter.learningSupportInfo]!;
bool valueAdmonitionInfo =
activeSchooldayEventFilters[SchooldayEventFilter.admonitionInfo]!;

bool valueDuringBreak =
activeSchooldayEventFilters[SchooldayEventFilter.duringBreak]!;
bool valueNotDuringBreak =
activeSchooldayEventFilters[SchooldayEventFilter.notDuringBreak]!;
return Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15, top: 5),
child: Column(
Expand Down Expand Up @@ -184,6 +187,42 @@ class SchooldayEventFilterBottomSheet extends WatchingWidget {
);
},
),
ThemedFilterChip(
label: '🕒',
selected: valueDuringBreak,
onSelected: (val) {
_schooldayEventFilterManager.setFilter(
schooldayEventFilters: [
(
filter: SchooldayEventFilter.duringBreak,
value: val,
),
(
filter: SchooldayEventFilter.notDuringBreak,
value: !val,
),
],
);
},
),
ThemedFilterChip(
label: '✏️',
selected: valueNotDuringBreak,
onSelected: (val) {
_schooldayEventFilterManager.setFilter(
schooldayEventFilters: [
(
filter: SchooldayEventFilter.notDuringBreak,
value: val,
),
(
filter: SchooldayEventFilter.duringBreak,
value: !val,
),
],
);
},
),
],
),
const Gap(10),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_settings_ui/flutter_settings_ui.dart';
import 'package:gap/gap.dart';
import 'package:school_data_hub_flutter/common/widgets/dialogs/confirmation_dialog.dart';
import 'package:school_data_hub_flutter/core/session/hub_session_helper.dart';
import 'package:school_data_hub_flutter/core/session/hub_session_manager.dart';
import 'package:school_data_hub_flutter/features/user/presentation/change_password/change_password_page.dart';
import 'package:watch_it/watch_it.dart';
Expand Down Expand Up @@ -57,31 +54,6 @@ class SettingsAccountSection extends AbstractSettingsSection with WatchItMixin {
trailing: null,
),

SettingsTile.navigation(
leading: GestureDetector(
onTap: () async {
bool? confirm = await confirmationDialog(
context: context,
title: 'Achtung!',
message: 'Ausloggen und alle Daten löschen?',
);
if (confirm == true && context.mounted) {
SessionHelper.logoutAndDeleteAllInstanceData();
}
return;
},
child: const Row(
children: [
Icon(Icons.logout),
Gap(5),
Icon(Icons.delete_forever_outlined),
],
),
),
title: const Text('Ausloggen und Daten löschen'),
value: const Text('App wird zurückgesetzt!'),
//onPressed:
),
SettingsTile.navigation(
leading: const Icon(Icons.attach_money_rounded),
title: const Text('Guthaben'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,28 +153,6 @@ class SettingsSessionSection extends AbstractSettingsSection with WatchItMixin {
trailing: null,
),

SettingsTile.navigation(
onPressed: (context) async {
final confirm = await confirmationDialog(
context: context,
title: 'Ausloggen',
message: 'Wirklich ausloggen?\n\nDaten bleiben erhalten!',
);
if (confirm == true && context.mounted) {
di<HubSessionManager>().signOutDevice();

_notificationService.showSnackBar(
NotificationType.success,
'Erfolgreich ausgeloggt!',
);
}
},
leading: const Icon(Icons.logout),
title: const Text('Ausloggen'),
description: const Text('Daten bleiben erhalten'),

//onPressed:
),
SettingsTile.navigation(
leading: const Icon(Icons.perm_identity_rounded),
title: const Text('Lokale Daten vom:'),
Expand Down Expand Up @@ -287,13 +265,13 @@ class SettingsSessionSection extends AbstractSettingsSection with WatchItMixin {
},
child: const Row(
children: [
Icon(Icons.logout),
Icon(Icons.image),
Gap(5),
Icon(Icons.delete_forever_outlined),
],
),
),
title: const Text('Lokal gespeicherte Bilder löschen'),
title: const Text('Bilder-Cache löschen'),

//onPressed:
),
Expand Down Expand Up @@ -322,6 +300,28 @@ class SettingsSessionSection extends AbstractSettingsSection with WatchItMixin {
value: const Text('App wird zurückgesetzt!'),
//onPressed:
),
SettingsTile.navigation(
onPressed: (context) async {
final confirm = await confirmationDialog(
context: context,
title: 'Ausloggen',
message: 'Wirklich ausloggen?\n\nDaten bleiben erhalten!',
);
if (confirm == true && context.mounted) {
di<HubSessionManager>().signOutDevice();

_notificationService.showSnackBar(
NotificationType.success,
'Erfolgreich ausgeloggt!',
);
}
},
leading: const Icon(Icons.logout),
title: const Text('Ausloggen'),
description: const Text('Daten bleiben erhalten'),

//onPressed:
),
],
);
}
Expand Down
Loading