diff --git a/README.md b/README.md index daa78fa..f1c4454 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Splitr is a free and open-source app that lets you create multiple projects, add This is currently a beta version. To get the app, you have to build it yourself with flutter or download the latest beta version [here](https://github.com/BhasherBEL/Splitr/releases). -:warning: Upgrading from version 0.x to 0.y does not guarantee compatibility, and backward compatibility is not assured. Proceed with caution. +:warning: Upgrading from version 0.x to 0.y does not guarantee compatibility. Backward compatibility is NEVER assured. Proceed with caution. ## Screenshots diff --git a/lib/components/pages/project/expenses/item_list.dart b/lib/components/pages/project/expenses/item_list.dart index 434dc6f..2357423 100644 --- a/lib/components/pages/project/expenses/item_list.dart +++ b/lib/components/pages/project/expenses/item_list.dart @@ -47,20 +47,7 @@ class _ItemListState extends State { child: Column( children: [ if (widget.project.provider.hasSync()) - ListTile( - // tileColor: Theme.of(context).splashColor, - subtitle: Text( - "${widget.project.notSyncCount} changes to push", - style: const TextStyle(fontStyle: FontStyle.italic), - ), - trailing: Icon( - Icons.sync, - color: Theme.of(context).textTheme.bodyMedium?.color, - ), - title: DynamicSync(time: widget.project.lastSync), - dense: true, - onTap: sync, - ), + SyncTile(project: widget.project, onTap: sync), Expanded( child: widget.project.items.enabled().isNotEmpty ? ScrollConfiguration( @@ -234,3 +221,59 @@ class NoGlow extends ScrollBehavior { return child; } } + +class SyncTile extends StatefulWidget { + const SyncTile({super.key, required this.project, this.onTap}); + + final Project project; + final Future Function()? onTap; + + @override + State createState() => _SyncTileState(); +} + +class _SyncTileState extends State { + bool isSyncing = false; + + Future onTap() async { + setState(() { + isSyncing = true; + }); + + if (widget.onTap != null) await widget.onTap!(); + + setState(() { + isSyncing = false; + }); + } + + @override + Widget build(BuildContext context) { + print(isSyncing); + return ListTile( + subtitle: Text( + "${widget.project.notSyncCount} changes to push", + style: const TextStyle(fontStyle: FontStyle.italic), + ), + trailing: isSyncing + ? Padding( + padding: const EdgeInsets.only(right: 5), + child: SizedBox( + width: 15, + height: 15, + child: CircularProgressIndicator( + strokeWidth: 2.5, + color: Theme.of(context).textTheme.bodyMedium?.color, + ), + ), + ) + : Icon( + Icons.sync, + color: Theme.of(context).textTheme.bodyMedium?.color, + ), + title: DynamicSync(time: widget.project.lastSync), + dense: true, + onTap: onTap, + ); + } +} diff --git a/lib/model/app_data.dart b/lib/model/app_data.dart index 2e685f1..bb94070 100644 --- a/lib/model/app_data.dart +++ b/lib/model/app_data.dart @@ -55,8 +55,6 @@ class AppData { AppData.projects = await Project.getAllProjects(); - print(AppData.projects); - if (!sharedPreferences.containsKey("firstRun")) { firstRun = AppData.projects.enabled().isEmpty; } else { diff --git a/lib/model/connectors/pocketbase/item_part.dart b/lib/model/connectors/pocketbase/item_part.dart index adb76cd..0f6dce5 100644 --- a/lib/model/connectors/pocketbase/item_part.dart +++ b/lib/model/connectors/pocketbase/item_part.dart @@ -76,21 +76,20 @@ class PocketBaseItemPart { for (RecordModel e in records) { Tuple2 res = fromRecord(e, item); if (res.item1) { - item.itemParts.setPresence(!res.item2.deleted, res.item2); + if (!item.itemParts.contains(res.item2)) item.itemParts.add(res.item2); distUpdated.add(res.item2); await res.item2.conn.save(); } } // Send local new records - for (ItemPart ip in item.itemParts.toList()) { + for (ItemPart ip in item.itemParts) { if (distUpdated.contains(ip)) continue; if (ip.lastUpdate > item.project.lastSync) { RecordModel rm = await collection.updateOrCreate(id: ip.remoteId, body: toJson(ip)); ip.remoteId = rm.id; - item.itemParts.setPresence(!ip.deleted, ip); } } diff --git a/lib/model/item.dart b/lib/model/item.dart index 56477ce..8147442 100644 --- a/lib/model/item.dart +++ b/lib/model/item.dart @@ -1,4 +1,5 @@ import 'package:splitr/model/data.dart'; +import 'package:splitr/utils/extenders/collections.dart'; import 'item_part.dart'; import 'participant.dart'; @@ -98,13 +99,16 @@ class Item extends Data { ItemPart? pip; double fixedTotal = 0; if (itemParts.isNotEmpty) { - for (ItemPart ip in itemParts) { + for (ItemPart ip in itemParts.enabled()) { if (ip.participant == participant) pip = ip; + // print("${ip.participant.pseudo} ${ip.rate}"); totalRate += ip.rate ?? 0; fixedTotal += ip.amount ?? 0; } } + // print('$title - ${pip?.participant.pseudo}: $amount ${pip?.amount} ${pip?.rate} $totalRate $fixedTotal'); + if (pip == null || pip.amount == null && pip.rate == null) { return emitter == participant ? amount : 0; } @@ -114,15 +118,15 @@ class Item extends Data { String toParticipantsString() { List participants = - itemParts.map((e) => e.participant).toList(); + itemParts.enabled().map((e) => e.participant).toList(); - if (itemParts.length < 4) { - return itemParts.map((e) => e.participant.pseudo).join(", "); + if (participants.length < 4) { + return participants.map((e) => e.pseudo).join(", "); } - if (itemParts.length == project.participants.length) return 'All'; + if (participants.length == project.participants.length) return 'All'; List possibilites = [ - itemParts.map((e) => e.participant.pseudo).join(", "), + participants.map((e) => e.pseudo).join(", "), 'All except ${project.participants.where((element) => !participants.contains(element)).map((e) => e.pseudo).join(', ')}', ]; diff --git a/lib/model/project.dart b/lib/model/project.dart index fa02dba..84d4930 100644 --- a/lib/model/project.dart +++ b/lib/model/project.dart @@ -133,7 +133,6 @@ class Project extends Data { tableProjects, columns: ProjectFields.values, ); - print(res); return res.map((e) => fromJson(e)).toSet(); } @@ -164,16 +163,16 @@ class Project extends Data { } Future> sync() async { - // try { - DateTime st = DateTime.now(); - bool res = await provider.sync(); - notSyncCount = 0; - return Tuple2( - res, (DateTime.now().difference(st).inMilliseconds / 1000).toString()); - // } catch (e) { - // print(e); - // return Tuple2(false, e.toString()); - // } + try { + DateTime st = DateTime.now(); + bool res = await provider.sync(); + notSyncCount = 0; + return Tuple2(res, + (DateTime.now().difference(st).inMilliseconds / 1000).toString()); + } catch (e) { + print(e); + return Tuple2(false, e.toString()); + } } Participant? participantByRemoteId(String id) {