Skip to content

Commit

Permalink
Merge pull request #22 from RedCommander735/6-select-item-on-longpress
Browse files Browse the repository at this point in the history
[FEATURE] Select item on long press
  • Loading branch information
RedCommander735 authored Aug 25, 2024
2 parents cc8c3bd + e33dc79 commit d06231a
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 158 deletions.
64 changes: 51 additions & 13 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import 'package:dynamic_color/dynamic_color.dart';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:spritverbrauch/src/add_item.dart';
import 'package:spritverbrauch/src/components/alert_dialog.dart';
import 'package:spritverbrauch/src/settings/filter_model.dart';

import 'package:spritverbrauch/src/listview/item_list_model.dart';
import 'package:spritverbrauch/src/listview/item_list_view.dart';
import 'package:spritverbrauch/src/overview.dart';
import 'package:spritverbrauch/src/add_item.dart';
import 'package:spritverbrauch/src/settings/filter.dart';

import 'package:provider/provider.dart';
Expand Down Expand Up @@ -76,28 +78,64 @@ class _SpritpreiseState extends State<Spritpreise> {
useMaterial3: true,
),
themeMode: ThemeMode.system,
home: const Main(),
home: Main(),
);
});
}
}

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

@override
State<Main> createState() => _MainState();
}

class _MainState extends State<Main> {
@override
Widget build(BuildContext context) {
ItemListModel itemListModel = Provider.of<ItemListModel>(context, listen: false);
return Scaffold(
floatingActionButton: Builder(
builder: (context) => FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AddItem()),
);
floatingActionButton: SpeedDial(
icon: Icons.add,
activeIcon: Icons.close,
openCloseDial: itemListModel.openCloseDial,
closeManually: true,
renderOverlay: false,
spaceBetweenChildren: 4,
childPadding: const EdgeInsets.all(10),
spacing: 3,
onPress: () {
if (!itemListModel.multiselect) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AddItem()),
);
}
},
onClose: () => itemListModel.multiselect = false,
children: [
SpeedDialChild(
child: const Icon(Icons.delete_forever),
backgroundColor: Colors.red,
foregroundColor: Colors.white,
onTap: () {
Popup.showAlert(
context: context,
title: itemListModel.selected > 1 ? '${itemListModel.selected} Eintrage löschen?' : 'Eintrag löschen?',
content: itemListModel.selected > 1
? 'Bist du dir sicher, dass du die ausgewählten Einträge löschen willst?'
: 'Bist du dir sicher, dass du den ausgewählten Einträg löschen willst?',
onConfirm: () {
itemListModel.remove(List.from(itemListModel.getSelected));
itemListModel.deselectAll();
},
)),
);
},
shape: const CircleBorder(),
)
],
),
body: SafeArea(
child: DefaultTabController(
length: 2,
Expand Down
43 changes: 43 additions & 0 deletions lib/src/components/alert_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';

class Popup {
static showAlert(
{required BuildContext context,
required String title,
required String content,
String? snackBarText,
required void Function() onConfirm,
void Function()? onDeny}) {
showDialog<void>(
context: context,
builder: (context) => AlertDialog(
title: Text(title),
content: Text(content),
actions: [
TextButton(
child: const Text('Abbrechen'),
onPressed: () {
if (onDeny != null) onDeny();
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('Bestätigen'),
onPressed: () {
if (snackBarText != null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(snackBarText),
showCloseIcon: true,
));
}

onConfirm();

Navigator.of(context).pop();
},
),
],
),
);
}
}
84 changes: 64 additions & 20 deletions lib/src/listview/item_list_model.dart
Original file line number Diff line number Diff line change
@@ -1,52 +1,96 @@
import 'dart:collection';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:spritverbrauch/src/utils/sqlite_service.dart';

class ItemListModel extends ChangeNotifier {

late SqliteService _sqliteService;
bool _sqliteInitialized = false;

List<ListItem> _items = [];
int _hiddenEntries = 0;
DateTime? _start;
DateTime? _end;

bool _multiselect = false;
ValueNotifier<bool> openCloseDial = ValueNotifier(false);
int selected = 0;

UnmodifiableListView<ListItem> get items => UnmodifiableListView(_items);
int get hiddenEntries => _hiddenEntries;

bool get multiselect => _multiselect;

set multiselect(bool enabled) {
if (!enabled) {
deselectAll();
} else {
openCloseDial.value = true;
}
_multiselect = enabled;
}

void load() async {
final sqlitesevice = SqliteService();
final list = await sqlitesevice.getItems();
if (!_sqliteInitialized) {
_sqliteService = SqliteService();
_sqliteInitialized = true;
}
final list = await _sqliteService.getItems();
_items = list;

notifyListeners();
}

void loadFiltered({DateTime? start, DateTime? end}) async {
_start = start;
_end = end;
final sqlitesevice = SqliteService();
final list = await sqlitesevice.getItems();
final listFiltered = await sqlitesevice.getItemsFiltered(start ?? DateTime(1970), end ?? DateTime.now());
final list = await _sqliteService.getItems();
final listFiltered = await _sqliteService.getItemsFiltered(start ?? DateTime(1970), end ?? DateTime.now());
_items = listFiltered;
_hiddenEntries = list.length - listFiltered.length;

notifyListeners();
}


void add(ListItem item) {
final sqlitesevice = SqliteService();
sqlitesevice.createItem(item);
_sqliteService.createItem(item);
_items.add(item);

notifyListeners();
}

void remove(List<ListItem> passedItems) {
for (var item in passedItems) {
_sqliteService.deleteItem(item.id);
_items.remove(item);
}
}

List<ListItem> get getSelected {
return UnmodifiableListView(_items.where((element) => element.selected));
}

void select(List<ListItem> passedItems) {
for (var item in passedItems) {
item.selected = !item.selected;

if (item.selected) {
selected += 1;
} else {
selected -= 1;
}

if (selected < 1) {
_multiselect = false;
openCloseDial.value = false;
}
}

void remove(ListItem item) {
final sqlitesevice = SqliteService();
sqlitesevice.deleteItem(item.id).then((value) => {
if (value > 0) {loadFiltered(start: _start, end: _end)}});
notifyListeners();
}

void deselectAll() {
for (ListItem item in _items) {
item.selected = false;
}
selected = 0;
notifyListeners();
}
}
8 changes: 2 additions & 6 deletions lib/src/listview/item_list_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:spritverbrauch/src/listview/item_list_model.dart';
import 'package:spritverbrauch/src/listview/list_item.dart';
import 'package:spritverbrauch/src/utils/sqlite_service.dart';

class ItemListView extends StatelessWidget {
const ItemListView({super.key});
Expand All @@ -14,12 +13,9 @@ class ItemListView extends StatelessWidget {
return ListView.separated(
itemCount: items.length,
itemBuilder: (context, index) {
return ListEntry(item: items[index]);
return ListEntry(items: items, item: items[index]);
},
separatorBuilder: (context, build) => const Padding(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Divider(height: 1),
),
separatorBuilder: (context, build) => const Divider(height: 1),
);
});
}
Expand Down
Loading

0 comments on commit d06231a

Please sign in to comment.