rollback to material + app usage init
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
|
||||||
<application
|
<application
|
||||||
android:label="Task Tracker"
|
android:label="Task Tracker"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import 'package:uuid/uuid.dart';
|
|||||||
import 'theme_provider.dart';
|
import 'theme_provider.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'User.dart' as User;
|
import 'User.dart' as User;
|
||||||
class Category{
|
|
||||||
|
|
||||||
|
class Category {
|
||||||
Category(this.category_id, this.name, this.color, this.productive);
|
Category(this.category_id, this.name, this.color, this.productive);
|
||||||
|
|
||||||
String category_id;
|
String category_id;
|
||||||
@@ -24,7 +24,6 @@ class Category{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TaskType {
|
class TaskType {
|
||||||
|
|
||||||
TaskType(this.id, this.name, this.category, {this.relatedProject, this.cat});
|
TaskType(this.id, this.name, this.category, {this.relatedProject, this.cat});
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
@@ -39,13 +38,16 @@ class TaskType{
|
|||||||
static String colRelatedProject = "related_project";
|
static String colRelatedProject = "related_project";
|
||||||
|
|
||||||
static String getDisplayName(TaskType taskType) {
|
static String getDisplayName(TaskType taskType) {
|
||||||
return (taskType.name + ((taskType.relatedProject != null) ? ' [${taskType.relatedProject!.name}]' : ''));
|
return (taskType.name +
|
||||||
|
((taskType.relatedProject != null)
|
||||||
|
? ' [${taskType.relatedProject!.name}]'
|
||||||
|
: ''));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Activity {
|
class Activity {
|
||||||
|
Activity(this.taskType, this.startTime, this.endTime,
|
||||||
Activity(this.taskType, this.startTime, this.endTime, {this.metadata,DateTime? tEndTime,DateTime? tStartTime}){
|
{this.metadata, DateTime? tEndTime, DateTime? tStartTime}) {
|
||||||
trueStartTime = tStartTime ?? startTime;
|
trueStartTime = tStartTime ?? startTime;
|
||||||
trueEndTime = tEndTime ?? endTime;
|
trueEndTime = tEndTime ?? endTime;
|
||||||
}
|
}
|
||||||
@@ -56,13 +58,13 @@ class Activity{
|
|||||||
DateTime endTime;
|
DateTime endTime;
|
||||||
String? metadata;
|
String? metadata;
|
||||||
|
|
||||||
Activity.fromJson(Map<String,dynamic> json): taskType=json['taskType'], startTime=json['sTime'], endTime=json['eTime'];
|
Activity.fromJson(Map<String, dynamic> json)
|
||||||
|
: taskType = json['taskType'],
|
||||||
|
startTime = json['sTime'],
|
||||||
|
endTime = json['eTime'];
|
||||||
|
|
||||||
Map<String, dynamic> toJson()=>{
|
Map<String, dynamic> toJson() =>
|
||||||
'taskType': taskType,
|
{'taskType': taskType, 'sTime': startTime, 'eTime': endTime};
|
||||||
'sTime':startTime,
|
|
||||||
'eTime':endTime
|
|
||||||
};
|
|
||||||
|
|
||||||
static String colType = "type";
|
static String colType = "type";
|
||||||
static String colStartTime = "s_time";
|
static String colStartTime = "s_time";
|
||||||
@@ -88,7 +90,8 @@ class InitialData{
|
|||||||
static List<Category> getCategories(String username) {
|
static List<Category> getCategories(String username) {
|
||||||
List<Category> cats = [
|
List<Category> cats = [
|
||||||
Category(username + 'Relax', 'Relax', '#555555', false),
|
Category(username + 'Relax', 'Relax', '#555555', false),
|
||||||
Category(username+'Daily Activities','Daily Activities', '#009955',false),
|
Category(
|
||||||
|
username + 'Daily Activities', 'Daily Activities', '#009955', false),
|
||||||
Category(username + 'Study', 'Study', '#00FF00', true),
|
Category(username + 'Study', 'Study', '#00FF00', true),
|
||||||
Category(username + 'Play', 'Play', '#FF0000', false),
|
Category(username + 'Play', 'Play', '#FF0000', false),
|
||||||
Category(username + 'Work', 'Work', '#00AAFF', true),
|
Category(username + 'Work', 'Work', '#00AAFF', true),
|
||||||
@@ -99,7 +102,6 @@ class InitialData{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Queries {
|
class Queries {
|
||||||
Queries(this.link, this.data);
|
Queries(this.link, this.data);
|
||||||
|
|
||||||
@@ -111,7 +113,8 @@ class Queries{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Project {
|
class Project {
|
||||||
Project(this.name, this.category, this.steps,this.eta, this.deadline,{this.cat});
|
Project(this.name, this.category, this.steps, this.eta, this.deadline,
|
||||||
|
{this.cat});
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
String getName() => name.replaceAll(User.username, "");
|
String getName() => name.replaceAll(User.username, "");
|
||||||
@@ -131,7 +134,13 @@ class Project{
|
|||||||
class ProjectStep {
|
class ProjectStep {
|
||||||
ProjectStep(this.stepName, this.eta, this.progress);
|
ProjectStep(this.stepName, this.eta, this.progress);
|
||||||
|
|
||||||
ProjectStep.fromJson(Map<String,dynamic> json): stepName=json['name'], eta=json['eta'], progress=json['progress'], finishedDate=(json['finishedDate']!=null) ? DateTime.parse(json['finishedDate']) : null;
|
ProjectStep.fromJson(Map<String, dynamic> json)
|
||||||
|
: stepName = json['name'],
|
||||||
|
eta = json['eta'],
|
||||||
|
progress = json['progress'],
|
||||||
|
finishedDate = (json['finishedDate'] != null)
|
||||||
|
? DateTime.parse(json['finishedDate'])
|
||||||
|
: null;
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
'name': stepName,
|
'name': stepName,
|
||||||
@@ -147,7 +156,6 @@ class ProjectStep{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Journal {
|
class Journal {
|
||||||
|
|
||||||
Journal(this.id, this.day, {this.title, this.description});
|
Journal(this.id, this.day, {this.title, this.description});
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
@@ -160,7 +168,8 @@ class Journal{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Todo {
|
class Todo {
|
||||||
Todo(this.id, this.category,this.metadata, this.dueDate, {this.notificationTime, this.task});
|
Todo(this.id, this.category, this.metadata, this.dueDate,
|
||||||
|
{this.notificationTime, this.task});
|
||||||
|
|
||||||
String id;
|
String id;
|
||||||
String category;
|
String category;
|
||||||
@@ -175,7 +184,6 @@ class Todo{
|
|||||||
static String colNotificationTime = 'notification_time';
|
static String colNotificationTime = 'notification_time';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Settings {
|
class Settings {
|
||||||
static Future<String> UUID() async {
|
static Future<String> UUID() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
@@ -200,6 +208,7 @@ class Settings{
|
|||||||
static String notification_key = "notification_interval";
|
static String notification_key = "notification_interval";
|
||||||
static String adaptive_notification_key = "adaptive_notification";
|
static String adaptive_notification_key = "adaptive_notification";
|
||||||
static String untracked_unprod_key = "untracked_unproductive";
|
static String untracked_unprod_key = "untracked_unproductive";
|
||||||
|
static String auto_log_key = "auto_log";
|
||||||
|
|
||||||
static Future<int> getNotificationInterval() async {
|
static Future<int> getNotificationInterval() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
@@ -219,7 +228,15 @@ class Settings{
|
|||||||
prefs.setInt(notification_key, value);
|
prefs.setInt(notification_key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<String> notificationOptions = <String>['Off','1 hour', '2 hour', '3 hour', '4 hour', '5 hour', '6 hour'];
|
static List<String> notificationOptions = <String>[
|
||||||
|
'Off',
|
||||||
|
'1 hour',
|
||||||
|
'2 hour',
|
||||||
|
'3 hour',
|
||||||
|
'4 hour',
|
||||||
|
'5 hour',
|
||||||
|
'6 hour'
|
||||||
|
];
|
||||||
static bool adaptiveNotificationAvailable() {
|
static bool adaptiveNotificationAvailable() {
|
||||||
List<String> dates = [];
|
List<String> dates = [];
|
||||||
if (User.activities.length < 10) {
|
if (User.activities.length < 10) {
|
||||||
@@ -267,9 +284,28 @@ class Settings{
|
|||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<bool> getAutoLog() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
bool _value = true;
|
||||||
|
if (prefs.containsKey(auto_log_key)) {
|
||||||
|
_value = await prefs.getBool(auto_log_key) ?? true;
|
||||||
|
} else {
|
||||||
|
prefs.setBool(auto_log_key, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
static Future<void> setUntrackedUnproductive(bool value) async {
|
static Future<void> setUntrackedUnproductive(bool value) async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
prefs.setBool(untracked_unprod_key, value);
|
prefs.setBool(untracked_unprod_key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> setAutoLog(bool value) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setBool(auto_log_key, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final settings = Settings();
|
final settings = Settings();
|
||||||
@@ -11,10 +11,11 @@ class BehaviourSettings extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _BehaviourSettingsState extends State<BehaviourSettings> {
|
class _BehaviourSettingsState extends State<BehaviourSettings> {
|
||||||
|
|
||||||
bool untracked_unprod = true;
|
bool untracked_unprod = true;
|
||||||
|
bool autoUsage = true;
|
||||||
|
|
||||||
@override void initState() {
|
@override
|
||||||
|
void initState() {
|
||||||
// TODO: implement initState
|
// TODO: implement initState
|
||||||
super.initState();
|
super.initState();
|
||||||
init();
|
init();
|
||||||
@@ -22,9 +23,8 @@ class _BehaviourSettingsState extends State<BehaviourSettings> {
|
|||||||
|
|
||||||
void init() async {
|
void init() async {
|
||||||
untracked_unprod = await Settings.getUntrackedUnproductive();
|
untracked_unprod = await Settings.getUntrackedUnproductive();
|
||||||
setState(() {
|
autoUsage = await Settings.getAutoLog();
|
||||||
|
setState(() {});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditingController untrackedGapSettings = TextEditingController();
|
TextEditingController untrackedGapSettings = TextEditingController();
|
||||||
@@ -41,32 +41,34 @@ class _BehaviourSettingsState extends State<BehaviourSettings> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
title: Text("Count untracked time as unproductive"),
|
title: Text("Count untracked time as unproductive"),
|
||||||
subtitle: Text("Not tracking = Not productive"),
|
subtitle: Text("Not tracking = Not productive"),
|
||||||
trailing: Switch.adaptive(value: untracked_unprod, onChanged: (val){
|
trailing: Switch.adaptive(
|
||||||
|
value: untracked_unprod,
|
||||||
|
onChanged: (val) {
|
||||||
untracked_unprod = val;
|
untracked_unprod = val;
|
||||||
setState(() {
|
setState(() {
|
||||||
Settings.setUntrackedUnproductive(val);
|
Settings.setUntrackedUnproductive(val);
|
||||||
});
|
});
|
||||||
setState(() {
|
setState(() {});
|
||||||
|
|
||||||
});
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
//TODO
|
//TODO
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text("Untracked Delay Threshold"),
|
title: Text("Untracked Delay Threshold"),
|
||||||
subtitle: Text("Makes it easier to fill in the gaps"),
|
subtitle: Text("Makes it easier to fill in the gaps"),
|
||||||
trailing:
|
trailing: Row(
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if(untrackedGapValue> 0)InkWell(onTap: (){
|
if (untrackedGapValue > 0)
|
||||||
untrackedGapSettings.text = (untrackedGapValue-1).toString();
|
InkWell(
|
||||||
setState(() {
|
onTap: () {
|
||||||
|
untrackedGapSettings.text =
|
||||||
});
|
(untrackedGapValue - 1).toString();
|
||||||
|
setState(() {});
|
||||||
},
|
},
|
||||||
child : Container(margin: EdgeInsets.all(10),child: Text('-')),),
|
child: Container(
|
||||||
|
margin: EdgeInsets.all(10), child: Text('-')),
|
||||||
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 25,
|
width: 25,
|
||||||
height: 30,
|
height: 30,
|
||||||
@@ -76,25 +78,35 @@ class _BehaviourSettingsState extends State<BehaviourSettings> {
|
|||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
inputFormatters: <TextInputFormatter>[
|
inputFormatters: <TextInputFormatter>[
|
||||||
FilteringTextInputFormatter.digitsOnly
|
FilteringTextInputFormatter.digitsOnly
|
||||||
],),
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
InkWell(onTap: (){
|
InkWell(
|
||||||
untrackedGapSettings.text = (untrackedGapValue+1).toString();
|
onTap: () {
|
||||||
setState(() {
|
untrackedGapSettings.text =
|
||||||
|
(untrackedGapValue + 1).toString();
|
||||||
});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: Container(margin:EdgeInsets.all(10),child: Text('+')),
|
child: Container(
|
||||||
|
margin: EdgeInsets.all(10), child: Text('+')),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text("Automatically add tasks from Usage Data"),
|
||||||
|
subtitle: Text("Requires App Usage access"),
|
||||||
|
trailing: Switch.adaptive(
|
||||||
|
value: autoUsage,
|
||||||
|
onChanged: (val) {
|
||||||
|
autoUsage = val;
|
||||||
|
Settings.setAutoLog(val);
|
||||||
|
|
||||||
],
|
setState(() {});
|
||||||
)
|
}),
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
);
|
)),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
792
lib/User.dart
792
lib/User.dart
File diff suppressed because it is too large
Load Diff
874
lib/main.dart
874
lib/main.dart
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
|||||||
|
import 'package:app_usage/app_usage.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:tasktracker/Data.dart';
|
import 'package:tasktracker/Data.dart';
|
||||||
|
import 'DebugHelper.dart';
|
||||||
import 'User.dart' as Users;
|
import 'User.dart' as Users;
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'theme_provider.dart';
|
import 'theme_provider.dart';
|
||||||
@@ -30,6 +32,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
final provider = Provider.of<ThemeProvider>(context, listen: false);
|
final provider = Provider.of<ThemeProvider>(context, listen: false);
|
||||||
provider.toggleTheme(value);
|
provider.toggleTheme(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
// TODO: implement initState
|
// TODO: implement initState
|
||||||
@@ -38,14 +41,16 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
NotificationManager.RescheduleNotifications();
|
NotificationManager.RescheduleNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void notificationSelected(String? payload) {
|
void notificationSelected(String? payload) {
|
||||||
if (payload != null) {
|
if (payload != null) {
|
||||||
if (payload.toLowerCase().contains("activity")) {
|
if (payload.toLowerCase().contains("activity")) {
|
||||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewActivity())).then((value) => {Users.refreshUserData()});
|
Navigator.of(context)
|
||||||
|
.push(MaterialPageRoute(builder: (context) => NewActivity()))
|
||||||
|
.then((value) => {Users.refreshUserData()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init() async {
|
void init() async {
|
||||||
await initSettings();
|
await initSettings();
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
@@ -53,19 +58,23 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
// print(loginResponse.body);
|
// print(loginResponse.body);
|
||||||
|
|
||||||
if (!prefs.containsKey("password") || !prefs.containsKey("username")) {
|
if (!prefs.containsKey("password") || !prefs.containsKey("username")) {
|
||||||
Navigator.of(context).pushNamedAndRemoveUntil('/welcome', (route) => false);
|
Navigator.of(context)
|
||||||
|
.pushNamedAndRemoveUntil('/welcome', (route) => false);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
http.Response loginResponse = await Users.login(
|
http.Response loginResponse = await Users.login(
|
||||||
prefs.getString("username") ?? '',
|
prefs.getString("username") ?? '',
|
||||||
prefs.getString("password") ?? '');
|
prefs.getString("password") ?? '');
|
||||||
print(loginResponse.body);
|
print(loginResponse.body);
|
||||||
if (loginResponse.body.toLowerCase().contains("success")) { //Login Success
|
if (loginResponse.body.toLowerCase().contains("success")) {
|
||||||
|
//Login Success
|
||||||
Continue();
|
Continue();
|
||||||
} else { //Login Failed
|
} else {
|
||||||
|
//Login Failed
|
||||||
LoginFailed();
|
LoginFailed();
|
||||||
}
|
}
|
||||||
} catch (error) { //Login Failed
|
} catch (error) {
|
||||||
|
//Login Failed
|
||||||
LoginFailed();
|
LoginFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,8 +100,11 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(colors: [Colors.lightBlue, Colors.blue],stops: [0,1],begin: Alignment.topLeft, end: Alignment.bottomRight)
|
gradient: LinearGradient(
|
||||||
),
|
colors: [Colors.lightBlue, Colors.blue],
|
||||||
|
stops: [0, 1],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight)),
|
||||||
// color: Colors.redAccent,
|
// color: Colors.redAccent,
|
||||||
padding: EdgeInsets.all(80),
|
padding: EdgeInsets.all(80),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -106,11 +118,15 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
SpinKitPouringHourGlass(color: Colors.white),
|
SpinKitPouringHourGlass(color: Colors.white),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
DefaultTextStyle(style: TextStyle(fontSize: 15,color: Colors.white,fontStyle: FontStyle.italic),
|
DefaultTextStyle(
|
||||||
child: Text('If you lie to me, That means you lie to yourself\n\n -This app (2022)',))
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: Colors.white,
|
||||||
|
fontStyle: FontStyle.italic),
|
||||||
|
child: Text(
|
||||||
|
'If you lie to me, That means you lie to yourself\n\n -This app (2022)',
|
||||||
|
))
|
||||||
// Text('Loading', style:TextStyle(color: Colors.grey, fontSize: 20,fontStyle: FontStyle.italic))
|
// Text('Loading', style:TextStyle(color: Colors.grey, fontSize: 20,fontStyle: FontStyle.italic))
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
app_usage:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: app_usage
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ dependencies:
|
|||||||
google_sign_in: ^5.2.3
|
google_sign_in: ^5.2.3
|
||||||
font_awesome_flutter: ^10.0.0
|
font_awesome_flutter: ^10.0.0
|
||||||
restart_app: ^1.1.0
|
restart_app: ^1.1.0
|
||||||
|
app_usage: ^2.1.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user