parsing of todo, retaining state over multiple sessions.
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:nextcloud_reminder/repeating_task.dart';
 | 
					import 'package:nextcloud_reminder/repeating_task.dart';
 | 
				
			||||||
 | 
					import 'package:nextcloud_reminder/types/tasks.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AddTaskWidget extends StatefulWidget {
 | 
					class AddTaskWidget extends StatefulWidget {
 | 
				
			||||||
  const AddTaskWidget({super.key, this.restorationId, required this.onSave});
 | 
					  const AddTaskWidget({super.key, this.restorationId, required this.onSave});
 | 
				
			||||||
@@ -123,7 +124,7 @@ class _AddTaskWidgetState extends State<AddTaskWidget> with RestorationMixin {
 | 
				
			|||||||
                      const SnackBar(content: Text('Task added.')),
 | 
					                      const SnackBar(content: Text('Task added.')),
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                    widget.onSave(RepeatingTask(
 | 
					                    widget.onSave(RepeatingTask(
 | 
				
			||||||
                        title: _titleController.text, begin: _beginDate.value, repeat: _repeat,));
 | 
					                        task: Task(title: _titleController.text, begin: _beginDate.value), repeat: _repeat,));
 | 
				
			||||||
                    Navigator.pop(context);
 | 
					                    Navigator.pop(context);
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,12 @@
 | 
				
			|||||||
 | 
					import 'dart:io';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:nextcloud_reminder/addReminder.dart';
 | 
					import 'package:nextcloud_reminder/addReminder.dart';
 | 
				
			||||||
 | 
					import 'package:nextcloud_reminder/parser/todotxt.dart';
 | 
				
			||||||
import 'package:nextcloud_reminder/repeating_task.dart';
 | 
					import 'package:nextcloud_reminder/repeating_task.dart';
 | 
				
			||||||
import 'package:nextcloud_reminder/table.dart';
 | 
					import 'package:nextcloud_reminder/table.dart';
 | 
				
			||||||
 | 
					import 'package:nextcloud_reminder/types/tasks.dart';
 | 
				
			||||||
 | 
					import 'package:path_provider/path_provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HomeWidget extends StatefulWidget {
 | 
					class HomeWidget extends StatefulWidget {
 | 
				
			||||||
  const HomeWidget({super.key, required this.title});
 | 
					  const HomeWidget({super.key, required this.title});
 | 
				
			||||||
@@ -21,9 +26,60 @@ class HomeWidget extends StatefulWidget {
 | 
				
			|||||||
  State<HomeWidget> createState() => _HomeWidgetState();
 | 
					  State<HomeWidget> createState() => _HomeWidgetState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _HomeWidgetState extends State<HomeWidget> {
 | 
					class _HomeWidgetState extends State<HomeWidget> with WidgetsBindingObserver {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final ScrollTable _checkboxes = ScrollTable(title: "TODOs");
 | 
					  final ScrollTable _checkboxes = ScrollTable(title: "TODOs");
 | 
				
			||||||
  int _counter = 1;
 | 
					  int _counter = 1;
 | 
				
			||||||
 | 
					  late final Directory appDocDirectory;
 | 
				
			||||||
 | 
					  late final File todotxt = File('${appDocDirectory.path}/todo.txt');
 | 
				
			||||||
 | 
					  final List<Task> tasks = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void _loadTodos() {
 | 
				
			||||||
 | 
					    for (var element in tasks) {
 | 
				
			||||||
 | 
					      debugPrint("loaded: ${element.toString()}");
 | 
				
			||||||
 | 
					      _checkboxes.addTask(RepeatingTask(task: element));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void initLazy() async {
 | 
				
			||||||
 | 
					    appDocDirectory = (await getApplicationDocumentsDirectory());
 | 
				
			||||||
 | 
					    if (await todotxt.exists()) {
 | 
				
			||||||
 | 
					      var data = await todotxt.readAsLines();
 | 
				
			||||||
 | 
					      debugPrint(data.toString());
 | 
				
			||||||
 | 
					      tasks.addAll(TodoParser.parse(data));
 | 
				
			||||||
 | 
					      _loadTodos();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      debugPrint("no todo file found at ${todotxt.path}");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void initState() {
 | 
				
			||||||
 | 
					    super.initState();
 | 
				
			||||||
 | 
					    WidgetsBinding.instance.addObserver(this);
 | 
				
			||||||
 | 
					    initLazy();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void dispose() {
 | 
				
			||||||
 | 
					    WidgetsBinding.instance.removeObserver(this);
 | 
				
			||||||
 | 
					    super.dispose();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  void didChangeAppLifecycleState(AppLifecycleState state) {
 | 
				
			||||||
 | 
					    if (state == AppLifecycleState.paused || state == AppLifecycleState.inactive) {
 | 
				
			||||||
 | 
					      // App is in the background, save any unsaved data
 | 
				
			||||||
 | 
					      debugPrint("save to disk");
 | 
				
			||||||
 | 
					      saveData();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  void saveData() async {
 | 
				
			||||||
 | 
					    //TODO: better update lines instead of blindly overwriting.
 | 
				
			||||||
 | 
					    String data = tasks.map((t) => t.toString()).join("\n");
 | 
				
			||||||
 | 
					    debugPrint("Saving:\n$data");
 | 
				
			||||||
 | 
					    await todotxt.writeAsString(data);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void _addDummyTask() {
 | 
					  void _addDummyTask() {
 | 
				
			||||||
    setState(() {
 | 
					    setState(() {
 | 
				
			||||||
@@ -32,13 +88,14 @@ class _HomeWidgetState extends State<HomeWidget> {
 | 
				
			|||||||
      // so that the display can reflect the updated values. If we changed
 | 
					      // so that the display can reflect the updated values. If we changed
 | 
				
			||||||
      // stuff without calling setState(), then the build method would not be
 | 
					      // stuff without calling setState(), then the build method would not be
 | 
				
			||||||
      // called again, and so nothing would appear to happen.
 | 
					      // called again, and so nothing would appear to happen.
 | 
				
			||||||
      _checkboxes.addTask(RepeatingTask(title: "Dummy Task #$_counter", begin: DateTime.now(), repeat: _counter++));
 | 
					      _checkboxes.addTask(RepeatingTask(task: Task(title: "Dummy Task #$_counter", begin: DateTime.now()), repeat: _counter++));
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void _addTask(RepeatingTask? t) {
 | 
					  void _addTask(RepeatingTask? t) {
 | 
				
			||||||
    if (t != null) {
 | 
					    if (t != null) {
 | 
				
			||||||
      setState(() {
 | 
					      setState(() {
 | 
				
			||||||
        _checkboxes.addTask(t!);
 | 
					        _checkboxes.addTask(t!);
 | 
				
			||||||
 | 
					        tasks.add(t.task);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										79
									
								
								lib/parser/todotxt.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								lib/parser/todotxt.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:petitparser/petitparser.dart';
 | 
				
			||||||
 | 
					import 'package:nextcloud_reminder/types/tasks.dart';
 | 
				
			||||||
 | 
					import 'package:tuple/tuple.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TodoParser {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static final _definition = TodoTxtEvaluatorDefinition();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static final _todoParser = _definition.build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<Task> parse(List<String> input) {
 | 
				
			||||||
 | 
					    final List<Task> ret = [];
 | 
				
			||||||
 | 
					    for (var element in input) {
 | 
				
			||||||
 | 
					      var parsed = _todoParser.parse(element);
 | 
				
			||||||
 | 
					      if (parsed.isSuccess) {
 | 
				
			||||||
 | 
					        ret.add(parsed.value);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        debugPrint(parsed.message);
 | 
				
			||||||
 | 
					        debugPrint(element);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TodoTxtEvaluatorDefinition extends TodoTxtDefinition {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Parser todoLine() => super.todoLine().map((value) =>
 | 
				
			||||||
 | 
					      //parser gives the following structure:
 | 
				
			||||||
 | 
					      //0: completed? (null | true)
 | 
				
			||||||
 | 
					      //1: priority? (null | uppercase letter)
 | 
				
			||||||
 | 
					      //2: range? (null | [begin-date, (null | end-date)]
 | 
				
			||||||
 | 
					      //3: description: Tuple5<original text, list<projects>, list<contexts>, map<meta>, text without meta>
 | 
				
			||||||
 | 
					      Task( title: value[3].item5,
 | 
				
			||||||
 | 
					            done: value[0] ?? false,
 | 
				
			||||||
 | 
					            priority: value[1],
 | 
				
			||||||
 | 
					            begin: (value[2] == null ? null : value[2][0]),
 | 
				
			||||||
 | 
					            end: (value[2] == null ? null : value[2][1]),
 | 
				
			||||||
 | 
					            projects: value[3].item2,
 | 
				
			||||||
 | 
					            contexts: value[3].item3,
 | 
				
			||||||
 | 
					            meta: value[3].item4,
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TodoTxtDefinition extends GrammarDefinition {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Tuple5<String,List<String>,List<String>, Map<String,String>, String> _extract_project_and_context(String input) {
 | 
				
			||||||
 | 
					    final projectPattern = RegExp(r'\+([^ ]+)');
 | 
				
			||||||
 | 
					    final contextPattern = RegExp(r'@([^ ]+)');
 | 
				
			||||||
 | 
					    final metaPattern = RegExp(r'([^ ]+):([^ ]+)');
 | 
				
			||||||
 | 
					    var projects = projectPattern.allMatches(input).map((Match m) => m[1]!);
 | 
				
			||||||
 | 
					    var contexts = contextPattern.allMatches(input).map((Match m) => m[1]!);
 | 
				
			||||||
 | 
					    var meta = metaPattern.allMatches(input).map((Match m) => MapEntry(m[1]!, m[2]!));
 | 
				
			||||||
 | 
					    var cleanInput = input//.replaceAll(projectPattern, '')
 | 
				
			||||||
 | 
					                          //.replaceAll(contextPattern, '')
 | 
				
			||||||
 | 
					                          .replaceAll(metaPattern, '');
 | 
				
			||||||
 | 
					    return Tuple5(input, List.of(projects), List.of(contexts), Map.fromEntries(meta), cleanInput.trim());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Parser start() => ref0(todoLine).end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Parser todoLine() => ref0(completed).trim().optional()
 | 
				
			||||||
 | 
					                     & ref0(priority).trim().optional()
 | 
				
			||||||
 | 
					                     & (ref0(date).trim() & ref0(date).trim().optional()).optional() // completion date + optional creation date
 | 
				
			||||||
 | 
					                     & any().plus().flatten().map(_extract_project_and_context)
 | 
				
			||||||
 | 
					  ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Parser completed() => char('x').map((_) => true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Parser priority() => (char('(') & pattern('A-Z') & char(')')).map((values) => values[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Parser date() => (digit().plus().flatten() & char('-') & digit().plus().flatten() & char('-') & digit().plus().flatten())
 | 
				
			||||||
 | 
					                   .map((values) => DateTime(int.parse(values[0]),int.parse(values[2]),int.parse(values[4])));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:nextcloud_reminder/task_item.dart';
 | 
					import 'package:nextcloud_reminder/task_item.dart';
 | 
				
			||||||
 | 
					import 'package:nextcloud_reminder/types/tasks.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RepeatingTask extends StatefulWidget {
 | 
					class RepeatingTask extends StatefulWidget {
 | 
				
			||||||
  const RepeatingTask({super.key, required this.title, required this.begin, this.repeat=1});
 | 
					  const RepeatingTask({super.key, required this.task, this.repeat=1});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final String title;
 | 
					  final Task task;
 | 
				
			||||||
  final DateTime begin;
 | 
					 | 
				
			||||||
  final int repeat;
 | 
					  final int repeat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
@@ -14,14 +14,10 @@ class RepeatingTask extends StatefulWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class _RepeatingTaskState extends State<RepeatingTask> {
 | 
					class _RepeatingTaskState extends State<RepeatingTask> {
 | 
				
			||||||
  late List<TaskItem> _occurrences;
 | 
					  late List<TaskItem> _occurrences;
 | 
				
			||||||
  late DateTime _first_occurence;
 | 
					 | 
				
			||||||
  late String _title;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initState() {
 | 
					  void initState() {
 | 
				
			||||||
    super.initState();
 | 
					    super.initState();
 | 
				
			||||||
    _title = widget.title;
 | 
					 | 
				
			||||||
    _first_occurence = widget.begin;
 | 
					 | 
				
			||||||
    _occurrences = List<TaskItem>.generate(10, (index) => TaskItem(done: index % widget.repeat == 0 ? false : null));
 | 
					    _occurrences = List<TaskItem>.generate(10, (index) => TaskItem(done: index % widget.repeat == 0 ? false : null));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@ class _ScrollTableState extends State<ScrollTable> {
 | 
				
			|||||||
          height: 60.0,
 | 
					          height: 60.0,
 | 
				
			||||||
          color: Colors.white,
 | 
					          color: Colors.white,
 | 
				
			||||||
          margin: const EdgeInsets.all(4.0),
 | 
					          margin: const EdgeInsets.all(4.0),
 | 
				
			||||||
          child: Text(t.title, style: Theme
 | 
					          child: Text(t.task.title, style: Theme
 | 
				
			||||||
              .of(context)
 | 
					              .of(context)
 | 
				
			||||||
              .textTheme
 | 
					              .textTheme
 | 
				
			||||||
              .labelMedium),
 | 
					              .labelMedium),
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								lib/types/tasks.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								lib/types/tasks.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					class Task {
 | 
				
			||||||
 | 
					  final bool done;
 | 
				
			||||||
 | 
					  final DateTime? begin;
 | 
				
			||||||
 | 
					  final DateTime? end;
 | 
				
			||||||
 | 
					  final String title;
 | 
				
			||||||
 | 
					  final List<String> contexts;
 | 
				
			||||||
 | 
					  final List<String> projects;
 | 
				
			||||||
 | 
					  final Map<String,String> meta;
 | 
				
			||||||
 | 
					  final String? priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Task({
 | 
				
			||||||
 | 
					    required this.title,
 | 
				
			||||||
 | 
					    this.done = false,
 | 
				
			||||||
 | 
					    this.contexts = const [],
 | 
				
			||||||
 | 
					    this.projects = const [],
 | 
				
			||||||
 | 
					    this.meta = const {},
 | 
				
			||||||
 | 
					    this.priority,
 | 
				
			||||||
 | 
					    this.begin,
 | 
				
			||||||
 | 
					    this.end,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return (done ? "x " : "")
 | 
				
			||||||
 | 
					         + (priority == null ? "" : "(${priority!}) ")
 | 
				
			||||||
 | 
					         + (begin == null ? "" : "${begin!.year}-${begin!.month}-${begin!.day} ")
 | 
				
			||||||
 | 
					         + (end == null ? "" : "${end!.year}-${end!.month}-${end!.day} ")
 | 
				
			||||||
 | 
					         + ("$title ")
 | 
				
			||||||
 | 
					         + meta.entries.map((entry) => "${entry.key}:${entry.value}").join(" ")
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
import FlutterMacOS
 | 
					import FlutterMacOS
 | 
				
			||||||
import Foundation
 | 
					import Foundation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import path_provider_macos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
 | 
					func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
 | 
				
			||||||
 | 
					  PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										113
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								pubspec.lock
									
									
									
									
									
								
							@@ -50,6 +50,20 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.3.1"
 | 
					    version: "1.3.1"
 | 
				
			||||||
 | 
					  ffi:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: ffi
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.0.1"
 | 
				
			||||||
 | 
					  file:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: file
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "6.1.4"
 | 
				
			||||||
  flutter:
 | 
					  flutter:
 | 
				
			||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description: flutter
 | 
					    description: flutter
 | 
				
			||||||
@@ -102,6 +116,83 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.8.2"
 | 
					    version: "1.8.2"
 | 
				
			||||||
 | 
					  path_provider:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path_provider
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.0.11"
 | 
				
			||||||
 | 
					  path_provider_android:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path_provider_android
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.0.22"
 | 
				
			||||||
 | 
					  path_provider_ios:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path_provider_ios
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.0.11"
 | 
				
			||||||
 | 
					  path_provider_linux:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path_provider_linux
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.1.7"
 | 
				
			||||||
 | 
					  path_provider_macos:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path_provider_macos
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.0.6"
 | 
				
			||||||
 | 
					  path_provider_platform_interface:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path_provider_platform_interface
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.0.5"
 | 
				
			||||||
 | 
					  path_provider_windows:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: path_provider_windows
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.1.3"
 | 
				
			||||||
 | 
					  petitparser:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: petitparser
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "5.1.0"
 | 
				
			||||||
 | 
					  platform:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: platform
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "3.1.0"
 | 
				
			||||||
 | 
					  plugin_platform_interface:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: plugin_platform_interface
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.1.3"
 | 
				
			||||||
 | 
					  process:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: process
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "4.2.4"
 | 
				
			||||||
  sky_engine:
 | 
					  sky_engine:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description: flutter
 | 
					    description: flutter
 | 
				
			||||||
@@ -149,6 +240,13 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "0.4.12"
 | 
					    version: "0.4.12"
 | 
				
			||||||
 | 
					  tuple:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: tuple
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "2.0.1"
 | 
				
			||||||
  vector_math:
 | 
					  vector_math:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -156,5 +254,20 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.1.2"
 | 
					    version: "2.1.2"
 | 
				
			||||||
 | 
					  win32:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: win32
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "3.1.3"
 | 
				
			||||||
 | 
					  xdg_directories:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: xdg_directories
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "0.2.0+2"
 | 
				
			||||||
sdks:
 | 
					sdks:
 | 
				
			||||||
  dart: ">=2.18.6 <3.0.0"
 | 
					  dart: ">=2.18.6 <3.0.0"
 | 
				
			||||||
 | 
					  flutter: ">=3.0.0"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,9 @@ dependencies:
 | 
				
			|||||||
  # The following adds the Cupertino Icons font to your application.
 | 
					  # The following adds the Cupertino Icons font to your application.
 | 
				
			||||||
  # Use with the CupertinoIcons class for iOS style icons.
 | 
					  # Use with the CupertinoIcons class for iOS style icons.
 | 
				
			||||||
  cupertino_icons: ^1.0.2
 | 
					  cupertino_icons: ^1.0.2
 | 
				
			||||||
 | 
					  path_provider: ^2.0.11
 | 
				
			||||||
 | 
					  petitparser: ^5.1.0
 | 
				
			||||||
 | 
					  tuple: ^2.0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user