LCOV - code coverage report
Current view: top level - lib/pages/automation/widgets - sync_tab.dart Coverage Total Hit
Test: lcov.info Lines: 0.0 % 133 0
Test Date: 2026-11-14 15:08:11 Functions: - 0 0

            Line data    Source code
       1              : // Copyright 2023 The terCAD team. All rights reserved.
       2              : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.
       3              : 
       4              : import 'package:app_finance/_classes/herald/app_design.dart';
       5              : import 'package:app_finance/_classes/herald/app_locale.dart';
       6              : import 'package:app_finance/_classes/herald/app_sync.dart';
       7              : import 'package:app_finance/_classes/storage/app_data.dart';
       8              : import 'package:app_finance/_configs/custom_color_scheme.dart';
       9              : import 'package:app_finance/_configs/theme_helper.dart';
      10              : import 'package:app_finance/_ext/build_context_ext.dart';
      11              : import 'package:app_finance/design/form/simple_input.dart';
      12              : import 'package:app_finance/design/wrapper/row_widget.dart';
      13              : import 'package:app_finance/design/wrapper/table_widget.dart';
      14              : import 'package:app_finance/design/wrapper/text_wrapper.dart';
      15              : import 'package:app_finance/design/generic/loading_widget.dart';
      16              : import 'package:app_finance/pages/_interfaces/interface_page_inject.dart';
      17              : import 'package:material_ui/material_ui.dart';
      18              : import 'package:flutter/services.dart';
      19              : import 'package:provider/provider.dart';
      20              : 
      21              : class SyncTab extends StatefulWidget {
      22              :   final FnPageCallback callback;
      23              : 
      24            0 :   const SyncTab({
      25              :     super.key,
      26              :     required this.callback,
      27              :   });
      28              : 
      29            0 :   @override
      30            0 :   SyncTabState createState() => SyncTabState();
      31              : }
      32              : 
      33              : class SyncTabState extends State<SyncTab> {
      34              :   final _controller = TextEditingController();
      35              :   final _scroll = ScrollController();
      36              :   late AppSync sync;
      37              :   late AppData dataProvider;
      38              :   List<String> request = [];
      39              :   bool loading = false;
      40              : 
      41            0 :   @override
      42              :   void initState() {
      43            0 :     widget.callback((
      44            0 :       buildButton: (_, __) => ThemeHelper.emptyBox,
      45              :       buttonName: '',
      46            0 :       title: AppLocale.labels.syncHeadline,
      47              :     ));
      48            0 :     super.initState();
      49              :   }
      50              : 
      51            0 :   @override
      52              :   void dispose() {
      53            0 :     _controller.dispose();
      54            0 :     sync.unfollow(runtimeType);
      55            0 :     super.dispose();
      56              :   }
      57              : 
      58            0 :   void ping(Uint8List id) {
      59            0 :     final uuid = String.fromCharCodes(id);
      60            0 :     if (sync.getPeers().where((e) => e.id == uuid).isEmpty) {
      61            0 :       setState(() => request.add(uuid));
      62              :     }
      63            0 :     ScaffoldMessenger.of(context).showSnackBar(
      64            0 :       SnackBar(content: Text(AppLocale.labels.pongStatus(uuid))),
      65              :     );
      66              :   }
      67              : 
      68            0 :   void synchronize() {
      69            0 :     setState(() => loading = true);
      70            0 :     dataProvider.getList(AppDataType.goals).forEach((o) => sync.send(o.toStream()));
      71            0 :     dataProvider.getList(AppDataType.bills).forEach((o) => sync.send(o.toStream()));
      72            0 :     dataProvider.getList(AppDataType.invoice).forEach((o) => sync.send(o.toStream()));
      73            0 :     dataProvider.getList(AppDataType.budgets).forEach((o) => sync.send(o.toStream()));
      74            0 :     dataProvider.getList(AppDataType.accounts).forEach((o) => sync.send(o.toStream()));
      75            0 :     dataProvider.getList(AppDataType.currencies).forEach((o) => sync.send(o.toStream()));
      76            0 :     dataProvider.getList(AppDataType.payments).forEach((o) => sync.send(o.toStream()));
      77            0 :     setState(() => loading = false);
      78            0 :     ScaffoldMessenger.of(context).showSnackBar(
      79            0 :       SnackBar(content: Text(AppLocale.labels.peerSent)),
      80              :     );
      81              :   }
      82              : 
      83            0 :   @override
      84              :   Widget build(BuildContext context) {
      85            0 :     final textTheme = context.textTheme;
      86            0 :     final indent = ThemeHelper.getIndent();
      87            0 :     return Consumer<AppSync>(builder: (context, appSync, _) {
      88            0 :       sync = appSync..followBinary(runtimeType, ping);
      89            0 :       dataProvider = Provider.of<AppData>(context, listen: false);
      90            0 :       final data = sync.getPeers();
      91            0 :       return LayoutBuilder(builder: (context, constraints) {
      92            0 :         double width = ThemeHelper.getWidth(context, 4, constraints);
      93            0 :         if (ThemeHelper.isNavRight(context, constraints)) {
      94            0 :           width -= ThemeHelper.barHeight;
      95              :         }
      96            0 :         return SingleChildScrollView(
      97            0 :           controller: _scroll,
      98            0 :           child: Padding(
      99            0 :             padding: EdgeInsets.all(indent),
     100            0 :             child: Column(
     101            0 :               mainAxisAlignment: AppDesign.getAlignment<MainAxisAlignment>(),
     102            0 :               children: [
     103            0 :                 RowWidget(
     104              :                   maxWidth: width,
     105              :                   alignment: MainAxisAlignment.spaceBetween,
     106              :                   indent: indent,
     107              :                   chunk: const [null, 85],
     108            0 :                   children: [
     109            0 :                     [
     110            0 :                       Text(
     111            0 :                         AppLocale.labels.peerId,
     112            0 :                         style: textTheme.bodyLarge,
     113              :                       ),
     114            0 :                       Container(
     115            0 :                         padding: EdgeInsets.all(indent),
     116            0 :                         color: context.colorScheme.fieldBackground,
     117            0 :                         child: SelectableText(
     118            0 :                           sync.getUuid() ?? AppLocale.labels.pearDisabled,
     119            0 :                           style: textTheme.bodyLarge,
     120            0 :                           onTap: () {
     121            0 :                             Clipboard.setData(ClipboardData(text: sync.getUuid() ?? ''));
     122            0 :                             ScaffoldMessenger.of(context).showSnackBar(
     123            0 :                               SnackBar(content: Text(AppLocale.labels.copiedToClipboard)),
     124              :                             );
     125              :                           },
     126              :                         ),
     127              :                       ),
     128              :                     ],
     129            0 :                     [
     130            0 :                       Text(
     131            0 :                         sync.isActive() ? AppLocale.labels.peerOnline : AppLocale.labels.peerClosed,
     132            0 :                         style: textTheme.bodyLarge,
     133              :                       ),
     134            0 :                       Align(
     135              :                         alignment: Alignment.topRight,
     136            0 :                         child: Switch(
     137            0 :                           value: sync.isActive(),
     138            0 :                           onChanged: (value) => setState(() => value ? sync.enable() : sync.disable()),
     139              :                         ),
     140              :                       ),
     141              :                     ],
     142              :                   ],
     143              :                 ),
     144              :                 ThemeHelper.hIndent2x,
     145            0 :                 if (sync.isActive())
     146            0 :                   loading
     147            0 :                       ? Row(
     148              :                           crossAxisAlignment: CrossAxisAlignment.center,
     149            0 :                           children: [
     150            0 :                             Text(AppLocale.labels.pearLoading),
     151            0 :                             LoadingWidget(isLoading: loading, size: const Size(48, 48)),
     152              :                           ],
     153              :                         )
     154            0 :                       : SizedBox(
     155              :                           width: double.infinity,
     156            0 :                           child: FloatingActionButton(
     157              :                             heroTag: 'sync_tab_sync',
     158            0 :                             onPressed: synchronize,
     159            0 :                             tooltip: AppLocale.labels.peerSync,
     160            0 :                             child: Text(AppLocale.labels.peerSync),
     161              :                           ),
     162              :                         ),
     163            0 :                 ThemeHelper.hIndent4x,
     164            0 :                 TableWidget(
     165              :                   width: width,
     166            0 :                   shadowColor: context.colorScheme.onSurface.withValues(alpha: 0.1),
     167              :                   chunk: const [80, null, 80, 90],
     168            0 :                   data: [
     169            0 :                     [
     170            0 :                       Center(child: Text(AppLocale.labels.peerAction)),
     171            0 :                       TextWrapper(AppLocale.labels.peerDevice),
     172            0 :                       TextWrapper(AppLocale.labels.peerStatus),
     173            0 :                       Center(child: Text(AppLocale.labels.peerAction)),
     174              :                     ],
     175            0 :                     ...List.generate(data.length, (index) {
     176            0 :                       String status = switch (data[index].status) {
     177            0 :                         true => AppLocale.labels.peerOnline,
     178            0 :                         false => AppLocale.labels.peerClosed,
     179            0 :                         _ => AppLocale.labels.peerOffline,
     180              :                       };
     181            0 :                       return <Widget>[
     182            0 :                         ElevatedButton(
     183            0 :                           onPressed: () => sync.del(data[index].id),
     184            0 :                           child: Text(AppLocale.labels.peerDelete),
     185              :                         ),
     186            0 :                         TextWrapper(data[index].id),
     187            0 :                         TextWrapper(status),
     188            0 :                         data[index].status == true
     189            0 :                             ? ElevatedButton(
     190            0 :                                 onPressed: () => sync.ping(data[index].id),
     191            0 :                                 child: Text(AppLocale.labels.peerPing),
     192              :                               )
     193            0 :                             : ElevatedButton(
     194            0 :                                 onPressed: () => sync.trace(data[index].id),
     195            0 :                                 child: Text(AppLocale.labels.peerConnectBtn),
     196              :                               ),
     197              :                       ];
     198              :                     }),
     199            0 :                     ...List.generate(request.length, (index) {
     200            0 :                       return <Widget>[
     201            0 :                         ElevatedButton(
     202            0 :                           onPressed: () => setState(() => request.remove(request[index])),
     203            0 :                           child: Text(AppLocale.labels.peerDelete),
     204              :                         ),
     205            0 :                         TextWrapper(request[index]),
     206            0 :                         TextWrapper(AppLocale.labels.peerPending),
     207            0 :                         ElevatedButton(
     208            0 :                           onPressed: () => setState(() {
     209            0 :                             sync.add(request[index]);
     210            0 :                             request.remove(request[index]);
     211              :                           }),
     212            0 :                           child: Text(AppLocale.labels.peerAccept),
     213              :                         ),
     214              :                       ];
     215              :                     }),
     216              :                   ],
     217              :                 ),
     218            0 :                 if (sync.isActive()) ...[
     219              :                   ThemeHelper.hIndent4x,
     220            0 :                   Text(
     221            0 :                     AppLocale.labels.peerOtherId,
     222            0 :                     style: textTheme.bodyLarge,
     223              :                   ),
     224            0 :                   SimpleInput(controller: _controller),
     225              :                   ThemeHelper.hIndent2x,
     226            0 :                   SizedBox(
     227              :                     width: double.infinity,
     228            0 :                     child: FloatingActionButton(
     229              :                       heroTag: 'sync_tab_add',
     230            0 :                       onPressed: () => sync.add(_controller.text),
     231            0 :                       tooltip: AppLocale.labels.peerConnect,
     232            0 :                       child: Text(AppLocale.labels.peerConnect),
     233              :                     ),
     234              :                   ),
     235              :                 ],
     236            0 :                 ThemeHelper.formEndBox,
     237              :               ],
     238              :             ),
     239              :           ),
     240              :         );
     241              :       });
     242              :     });
     243              :   }
     244              : }
        

Generated by: LCOV version 2.0-1