diff --git a/lib/Activities.dart b/lib/Activities.dart index 59af4d7..67771a8 100644 --- a/lib/Activities.dart +++ b/lib/Activities.dart @@ -17,64 +17,132 @@ class Activities extends StatefulWidget { late ProgressDialog progressDialog; class _ActivitiesState extends State { + TextEditingController searchController = TextEditingController(); + FocusNode _focus = FocusNode(); + bool searching = false; + + void _onFocusChange() { + print("FOCUS CHANGED! : ${_focus.hasFocus}"); + + if(!_focus.hasFocus){ + searching=false; + setState(() { + + }); + } + } + @override void initState() { // TODO: implement initState super.initState(); - + _focus.addListener(_onFocusChange); UpdateList(); } + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + _focus.removeListener(_onFocusChange); + _focus.dispose(); + } + @override Widget build(BuildContext context) { progressDialog = ProgressDialog(context: context); return Scaffold( floatingActionButton: FloatingActionButton.extended( onPressed: () { - Navigator.of(context) - .push(MaterialPageRoute(builder: (context) => NewActivity())) - .then((value) => UpdateList()); + Navigator.of(context).push(MaterialPageRoute(builder: (context) => NewActivity())).then((value) => UpdateList()); }, label: Text("New Activity"), icon: Icon(Icons.add)), appBar: AppBar( - title: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row(children: [ - Icon(Icons.task, color: Theme.of(context).primaryColor), - SizedBox(width: 10), - Text('Activities') - ]), - (selecting) - ? Row(children: [ - InkWell( - onTap: () { - DeleteSelectedTasks(); - }, - child: Icon( - Icons.delete, - size: 30, - )), - SizedBox( - width: 20, - ), - InkWell( - onTap: () { - setState(() { - selecting = false; - }); - }, - child: Icon(Icons.close, size: 30), - ) - ]) - : Container(), - ], - )), + title: (searching) + ? Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: TextField(onChanged: (text){setState(() { + + });},controller: searchController, focusNode: _focus, decoration: InputDecoration( + filled: true, + ),), + ), + InkWell( + onTap: (){searching=false; + searchController.clear(); + setState(() { + + });}, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Icon(Icons.cancel), + ), + ) + ], + ) + : Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row(children: [Icon(Icons.task, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Activities')]), + (selecting) + ? Row(children: [ + InkWell( + onTap: () { + DeleteSelectedTasks(); + }, + child: Icon( + Icons.delete, + size: 30, + )), + SizedBox( + width: 20, + ), + InkWell( + onTap: () { + setState(() { + selecting = false; + }); + }, + child: Icon(Icons.close, size: 30), + ) + ]) + : Row( + children: [ + InkWell( + onTap: () { + searching = true; + _focus.requestFocus(); + setState(() { + + }); + }, + child: Icon( + Icons.search, + size: 30, + )), + SizedBox( + width: 20, + ), + InkWell( + onTap: () { + setState(() async { + await User.refreshUserData(); + UpdateList(); + }); + }, + child: Icon(Icons.refresh, size: 30), + ) + ], + ), + ], + )), drawer: navDrawer(context, 2), body: Container( - padding: EdgeInsets.all(10), + padding: EdgeInsets.all(0), child: SingleChildScrollView( child: Column( children: PrintTasks(), @@ -102,12 +170,12 @@ class _ActivitiesState extends State { Map totalMinutes = {}; for (var element in User.activities) { String thisDate = dFormat.format(element.startTime); - int thisMinutes= element.endTime.difference(element.startTime).inMinutes; - if(totalMinutes.containsKey(thisDate)){ - if((totalMinutes[thisDate]??0) < thisMinutes){ + int thisMinutes = element.endTime.difference(element.startTime).inMinutes; + if (totalMinutes.containsKey(thisDate)) { + if ((totalMinutes[thisDate] ?? 0) < thisMinutes) { totalMinutes[thisDate] = thisMinutes; } - }else{ + } else { totalMinutes.putIfAbsent(thisDate, () => thisMinutes); } @@ -127,6 +195,14 @@ class _ActivitiesState extends State { } print(productivtyActs); for (var element in User.activities) { + if(searching){ + if(element.metadata!.toLowerCase().contains(searchController.text.toLowerCase()) || element.taskType.name.toLowerCase().contains(searchController.text.toLowerCase())){ + //Good to go + }else{ + continue; + } + } + String thisDate = dFormat.format(element.startTime); if (thisDate != lastDate) { int prodActs = productivtyActs[thisDate] ?? 0; @@ -138,11 +214,9 @@ class _ActivitiesState extends State { if (element.taskType.cat == null) { print('Got some null cat : ${element.taskType.name}'); } else { - Color color = - HexColor.fromHex(element.taskType.cat?.color ?? '#000000'); + Color color = HexColor.fromHex(element.taskType.cat?.color ?? '#000000'); bool productive = element.taskType.cat?.productive ?? true; - Widget task = ActivityCard(context, name, element.startTime, - element.endTime, productive, color, element, totalMinutes[thisDate] ?? 0); + Widget task = ActivityCard(context, name, element.startTime, element.endTime, productive, color, element, totalMinutes[thisDate] ?? 0); _tasks.add(task); } } @@ -153,27 +227,55 @@ class _ActivitiesState extends State { Widget DateSeperator(date, prodActs, unprodActs) { double prodPercentage = (prodActs / (prodActs + unprodActs)) * 100; return Padding( - padding: const EdgeInsets.fromLTRB(10, 20, 10, 0), + padding: const EdgeInsets.fromLTRB(0, 20, 10, 0), child: Column( children: [ Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - date, - style: TextStyle(fontSize: 18), + Row( + children: [ + Icon(Icons.remove_circle_outline), + SizedBox( + width: 10, + ), + Text( + date, + style: TextStyle(fontSize: 18), + ), + ], ), - Row(children: [ - Row( - children: [ - Container(child:Align(child:Text(MinutesToTimeString(prodActs)), alignment: Alignment.center,),width: (prodPercentage) * 1.7, height: 25,decoration: BoxDecoration(color: Colors.green,borderRadius: BorderRadius.horizontal(left: Radius.circular(10))),), - Container(child:Align(child:Text(MinutesToTimeString(unprodActs)), alignment: Alignment.center,),width: (100-prodPercentage)* 1.7,height: 25,decoration: BoxDecoration(color: Colors.red,borderRadius: BorderRadius.horizontal(right: Radius.circular(10))),), - ], - ), - SizedBox(width: 10,), - Text(prodPercentage.toStringAsFixed(1) + "%",style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold,fontSize: 20)) - ],) + Row( + children: [ + Row( + children: [ + Container( + child: Align( + child: FittedBox(fit: BoxFit.fitWidth,child: Text(MinutesToTimeString(prodActs),)), + alignment: Alignment.center, + ), + width: (prodPercentage) * 1.7, + height: 25, + decoration: BoxDecoration(color: Colors.green, borderRadius: BorderRadius.horizontal(left: Radius.circular(10))), + ), + Container( + child: Align( + child: Text(MinutesToTimeString(unprodActs)), + alignment: Alignment.center, + ), + width: (100 - prodPercentage) * 1.7, + height: 25, + decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.horizontal(right: Radius.circular(10))), + ), + ], + ), + SizedBox( + width: 10, + ), + Text(prodPercentage.toStringAsFixed(1) + "%", style: TextStyle(color: Colors.green, fontWeight: FontWeight.bold, fontSize: 20)) + ], + ) // CustomPaint( // painter: MyPlayerBar(100, prodPercentage.toInt(), // background: Colors.green, fill: Colors.deepOrange), @@ -195,20 +297,14 @@ class _ActivitiesState extends State { } bool selecting = false; - Widget ActivityCard(BuildContext context, String name, DateTime sTime, - DateTime eTime, bool productive, Color color, Activity activity,int totalMinutes) { + Widget ActivityCard(BuildContext context, String name, DateTime sTime, DateTime eTime, bool productive, Color color, Activity activity, int totalMinutes) { DateFormat dateFormat = DateFormat("HH:mm"); int thisMinutes = (activity.endTime.difference(activity.startTime).inMinutes); int timePercentage = ((thisMinutes / totalMinutes) * 100).toInt(); - // print("$thisMinutes / $totalMinutes"); - bool containsMetadata = ((activity.metadata ?? 'null') != 'null') && - ((activity.metadata ?? '').isNotEmpty); + // print("$thisMinutes / $totalMinutes"); + bool containsMetadata = ((activity.metadata ?? 'null') != 'null') && ((activity.metadata ?? '').isNotEmpty); var _timeSpan = eTime.difference(sTime); - String timeSpan = - ((_timeSpan.inHours > 0) ? _timeSpan.inHours.toString() + 'h ' : '') + - ((_timeSpan.inMinutes % 60 > 0) - ? (_timeSpan.inMinutes % 60).toString() + 'm' - : ''); + String timeSpan = ((_timeSpan.inHours > 0) ? _timeSpan.inHours.toString() + 'h ' : '') + ((_timeSpan.inMinutes % 60 > 0) ? (_timeSpan.inMinutes % 60).toString() + 'm' : ''); return Row(children: [ // Container(), (selecting) @@ -219,84 +315,77 @@ class _ActivitiesState extends State { OnItemSelected(activity); setState(() {}); }) - : Container(), + : Container(padding: EdgeInsets.fromLTRB(10, 0, 5, 0), child: SizedBox(width: 1, height: 100, child: Container(color: Colors.white))), Expanded( child: Column(children: [ - Card( + Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 5, 0), + child: Card( - // color: color, - elevation: 20, - shadowColor: color, - child: InkWell( - onTap: () { - //Open Respective Category - if (selecting) { - OnItemSelected(activity); - } - setState(() {}); - }, - onLongPress: () { - print('gonna delete'); - selecting = !selecting; - selectedActivities = [activity]; - setState(() {}); - }, - child: Container( - padding: EdgeInsets.all(15), - child: Column( - children: [ - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row(children: [ - Text(name + " [$timeSpan]", - style: TextStyle( fontSize: 17)), - if (containsMetadata) - Icon(Icons.arrow_forward_outlined, size: 20,), - if (containsMetadata) - Text(activity.metadata ?? '',overflow: TextOverflow.clip,) - ]), - - // Icon(Icons.analytics, color: color, size: 20,), + // color: color, + elevation: 20, + shadowColor: color, + child: InkWell( + onTap: () { + //Open Respective Category + if (selecting) { + OnItemSelected(activity); + } + setState(() {}); + }, + onLongPress: () { + print('gonna delete'); + selecting = !selecting; + selectedActivities = [activity]; + setState(() {}); + }, + child: Container( + padding: EdgeInsets.all(15), + child: Column( + children: [ + Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Row(children: [ + Text(name + " [$timeSpan]", style: TextStyle(fontSize: 17)), + if (containsMetadata) + Icon( + Icons.arrow_forward_outlined, + size: 20, + ), + if (containsMetadata) + Text( + activity.metadata ?? '', + overflow: TextOverflow.ellipsis, + ) ]), - SizedBox( - height: 5, - ), - Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(dateFormat.format(sTime) + - " - " + - dateFormat.format(eTime)), - SizedBox( - width: 20, - ), - Container( - padding: EdgeInsets.symmetric( - horizontal: 10, vertical: 2), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: (productive) - ? Colors.green - : Colors.red), - child: Text( - activity.taskType.cat?.name ?? 'n/a')) - // Icon(Icons.circle, - // color: (productive) - // ? Colors.green - // : Colors.red) - ]) - ], - )))), + + // Icon(Icons.analytics, color: color, size: 20,), + ]), + SizedBox( + height: 5, + ), + Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(dateFormat.format(sTime) + " - " + dateFormat.format(eTime)), + SizedBox( + width: 20, + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: (productive) ? Colors.green : Colors.red), + child: Text(activity.taskType.cat?.name ?? 'n/a')) + // Icon(Icons.circle, + // color: (productive) + // ? Colors.green + // : Colors.red) + ]) + ], + )))), + ), Container( margin: EdgeInsets.fromLTRB(15, 0, 15, 10), height: 2, - child:Row(children: [ - Expanded(flex:timePercentage ,child: Container(color:color)), - Expanded(flex:100-timePercentage,child:Container()) - ],)), + child: Row( + children: [Expanded(flex: timePercentage, child: Container(color: color)), Expanded(flex: 100 - timePercentage, child: Container())], + )), ]), ), ]); @@ -311,8 +400,7 @@ class _ActivitiesState extends State { } void DeleteSelectedTasks() async { - progressDialog.show( - max: 100, msg: 'Deleteing ${selectedActivities.length} Activities'); + progressDialog.show(max: 100, msg: 'Deleteing ${selectedActivities.length} Activities'); selectedActivities.forEach((element) async { await User.UserOperations.deleteActivity(element, bulk: true); }); @@ -328,7 +416,4 @@ class _ActivitiesState extends State { } } - - - List selectedActivities = []; diff --git a/lib/Categories.dart b/lib/Categories.dart index 613e016..bc8f5eb 100644 --- a/lib/Categories.dart +++ b/lib/Categories.dart @@ -122,7 +122,6 @@ class _CategoriesState extends State { Expanded( child: Column(children: [ Card( - // color: color, elevation:20, shadowColor: color, diff --git a/lib/Data.dart b/lib/Data.dart index 557c159..08956aa 100644 --- a/lib/Data.dart +++ b/lib/Data.dart @@ -1,5 +1,9 @@ +import 'dart:async'; + import 'package:shared_preferences/shared_preferences.dart'; import 'package:uuid/uuid.dart'; +import 'theme_provider.dart'; +import 'package:provider/provider.dart'; class Category{ Category(this.category_id, this.name, this.color, this.productive); @@ -80,8 +84,9 @@ class Queries{ } -class Settings{ + +class Settings{ static Future UUID() async{ final prefs = await SharedPreferences.getInstance(); if(prefs.containsKey('uuid')){ @@ -93,4 +98,11 @@ class Settings{ return Future.value(_uuid); } } -} \ No newline at end of file + + + static Future setTheme(int value) async{ + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt("theme", value); + } +} +final settings = Settings(); \ No newline at end of file diff --git a/lib/Settings/AppearanceSettings.dart b/lib/Settings/AppearanceSettings.dart new file mode 100644 index 0000000..2f68ecb --- /dev/null +++ b/lib/Settings/AppearanceSettings.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:tasktracker/Settings/Settings.dart'; +import 'package:tasktracker/Data.dart'; +import 'package:tasktracker/theme_provider.dart'; +import 'package:provider/provider.dart'; +class AppearanceSettings extends StatefulWidget { + const AppearanceSettings({Key? key}) : super(key: key); + + @override + _AppearanceSettingsState createState() => _AppearanceSettingsState(); +} + +class _AppearanceSettingsState extends State { + + @override + Widget build(BuildContext context) { + final themeProvider= Provider.of(context); + + return Scaffold( + appBar: AppBar(title: Text('Appearance Settings')), + body: SafeArea( + child: Container( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + SizedBox(height: 10,), + Padding( + padding: const EdgeInsets.all(5.0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Dark Mode",style: TextStyle(fontSize: 18)), + Switch.adaptive(value: themeProvider.isDarkMode, onChanged: (value){ + final provider = Provider.of(context, listen: false); + provider.toggleTheme(value); + Settings.setTheme(value ? 0:1); + }) + ], + ), + ), + Divider(), + ], + ), + ), + ) + ); + } +} \ No newline at end of file diff --git a/lib/Settings/NotificationSettings.dart b/lib/Settings/NotificationSettings.dart new file mode 100644 index 0000000..42e3b5a --- /dev/null +++ b/lib/Settings/NotificationSettings.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +class NotificationSettings extends StatefulWidget { + const NotificationSettings({Key? key}) : super(key: key); + + @override + _NotificationSettingsState createState() => _NotificationSettingsState(); +} + +class _NotificationSettingsState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text("Notification Settings")), + body: SafeArea( + child: Column( + children: [ + SizedBox( + height: 10, + ), + ListTile( + title: Text("New Activity Notification"), + trailing: InkWell(onTap:(){},child: Text("1 hour")), + subtitle: Text("Notify you to track activities of past time"), + ), + Divider(), + ListTile( + title: Text("Suggestion Notifications"), trailing:Switch.adaptive(value: true, onChanged: (val){}), + subtitle: Text("Notifies you about suggestions according to your data"), + + ) + ], + ), + ), + ); + } +} diff --git a/lib/Settings/Settings.dart b/lib/Settings/Settings.dart new file mode 100644 index 0000000..0c86dbc --- /dev/null +++ b/lib/Settings/Settings.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:tasktracker/Settings/AppearanceSettings.dart'; +import 'package:tasktracker/Settings/NotificationSettings.dart'; +import 'package:tasktracker/main.dart'; + +class SettingsPage extends StatefulWidget { + const SettingsPage({Key? key}) : super(key: key); + + @override + _SettingsPageState createState() => _SettingsPageState(); +} + +class _SettingsPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Settings')), + body: Column( + mainAxisSize: MainAxisSize.max, + children: [ + SettingItem('Appearance', ()=>Navigator.of(context).push(MaterialPageRoute(builder: (context)=> const AppearanceSettings()))), + Divider(), + SettingItem('Notifications', ()=>Navigator.of(context).push(MaterialPageRoute(builder: (context)=> const NotificationSettings()))), + ], + ) + ); + } + + +} + + +Widget SettingItem(String name, Function onTap){ + return InkWell( + onTap: ()=>onTap(), + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Text(name, style: TextStyle(fontSize: 18)), + Icon(Icons.arrow_forward,size: 20,) + ], + ), + ) + ); +} \ No newline at end of file diff --git a/lib/User.dart b/lib/User.dart index 76a7acc..037edf3 100644 --- a/lib/User.dart +++ b/lib/User.dart @@ -23,6 +23,7 @@ List taskTypes = []; List activities=[]; bool offline = true; bool registered = false; +bool refreshing = true; Future login(String _username, String password) async { final prefs = await SharedPreferences.getInstance(); @@ -64,6 +65,7 @@ Future initUserData() async { bool userDataInitiated =false; Future refreshUserData() async{ ShowProgress("Loading data"); + refreshing = true; // categories= await GetCategories(true); // taskTypes= await GetTaskTypes(true); // activities= await GetActivities(true); @@ -71,6 +73,7 @@ Future refreshUserData() async{ await updateTasksList(); await updateActList(); userDataInitiated=true; + refreshing = false; HideProgress(); } diff --git a/lib/main.dart b/lib/main.dart index 87b0c9a..cdf959a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,12 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; import 'package:tasktracker/Categories.dart'; import 'package:tasktracker/Welcome.dart'; import 'package:tasktracker/splash.dart'; +import 'package:tasktracker/theme_provider.dart'; +import 'Settings/Settings.dart'; import 'package:wakelock/wakelock.dart'; import 'Data.dart'; import 'NewTask.dart'; @@ -69,21 +72,28 @@ class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData(accentColor: Colors.redAccent, brightness: Brightness.dark, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'), - //home: const MyHomePage(), - initialRoute: '/splash', - routes: { - '/splash': (context) => const SplashScreen(), - '/welcome': (context) => const WelcomePage(), - '/': (context) => const MyHomePage(), - '/Tasks': (context) => const Tasks(), - '/Categories': (context) => const Categories(), - '/Activities': (context) => const Activities() - }); - } + Widget build(BuildContext context) => ChangeNotifierProvider( + create: (context)=>ThemeProvider(), + builder: (context, _){ + final themeProvider = Provider.of(context); + + return MaterialApp( + title: 'Task Tracker', + themeMode: themeProvider.themeMode, + theme: ThemeData(accentColor: Colors.redAccent,brightness: Brightness.light, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'), + darkTheme: ThemeData(accentColor: Colors.redAccent,brightness: Brightness.dark, primaryColor: Colors.amber, fontFamily: 'Noto-Sans'), + //home: const MyHomePage(), + initialRoute: '/splash', + routes: { + '/splash': (context) => const SplashScreen(), + '/welcome': (context) => const WelcomePage(), + '/': (context) => const MyHomePage(), + '/Tasks': (context) => const Tasks(), + '/Categories': (context) => const Categories(), + '/Activities': (context) => const Activities(), + '/Settings':(context) => const SettingsPage() + }); + }); } List days = []; @@ -129,7 +139,7 @@ class _MyHomePageState extends State { void initState() { // TODO: implement initState super.initState(); - User.refreshUserData().then((val) => LoadStats()); + // User.refreshUserData().then((val) => LoadStats()); // showOfflineSnack(); LoadStats(); // progressDialog = ProgressDialog(context: context); @@ -153,17 +163,18 @@ class _MyHomePageState extends State { firstDay = null; lastDay = null; String lastDate = ""; + days=[]; for (var element in User.activities) { if (lastDay == null) { lastDay = element.endTime; } if (taskTypeRange == null) { print("$lastDay - $firstDay"); - taskTypeRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 1)), end: lastDay!); + taskTypeRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 0)), end: lastDay!); } if (catsRange == null) { print("$lastDay - $firstDay"); - catsRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 1)), end: lastDay!); + catsRange = DateTimeRange(start: lastDay!.subtract(const Duration(days: 0)), end: lastDay!); } firstDay = element.startTime; String thisDate = dFormat.format(element.startTime); @@ -237,7 +248,9 @@ class _MyHomePageState extends State { Color barCol = HexColor.fromHex(key.color); dailyData.add(CatMapData(key.name, value, barCol)); }); - + dailyData.sort((a,b){ + return a.name.toLowerCase().compareTo(b.name.toLowerCase()); + }); for (var element in days) { // if(productivtyActs.containsKey(element) && unproductivtyActs.containsKey(element)){ int prodActs = (productivtyActs[element] ?? 0); @@ -252,11 +265,16 @@ class _MyHomePageState extends State { taskTypesData.add(TaskTypeMapData(key.name, value, HexColor.fromHex(key.cat!.color))); }); + taskTypesData.sort((a,b){ + return a.time.compareTo(b.time); + }); + catBriefMap.forEach((key, value) { print(key.name + " : $value"); Color barCol = HexColor.fromHex(key.color); catsData.add(CatMapData(key.name, value, barCol)); }); + catsData.sort((a,b)=> a.time.compareTo(b.time)); }); } } @@ -281,7 +299,23 @@ class _MyHomePageState extends State { }, label: Text("New Activity"), icon: Icon(Icons.add)), - appBar: AppBar(title: Row(children: [Icon(Icons.article_outlined, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Summary')])), + appBar: AppBar(title: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row(children: [Icon(Icons.article_outlined, color: Theme.of(context).primaryColor), SizedBox(width: 10), Text('Summary')]), + Row(children: [ + InkWell( + onTap: () { + setState(() { + LoadStats(); + }); + }, + child: Icon(Icons.refresh, size: 30), + ) + ],) + ], + )), drawer: navDrawer(context, 0), body: SafeArea( child: SingleChildScrollView( @@ -362,6 +396,12 @@ class _MyHomePageState extends State { dataSource: productivityData.reversed.toList(), xValueMapper: (ProductivityMapData sales, _) => sales.day, yValueMapper: (ProductivityMapData sales, _) => sales.productivity, + dataLabelMapper: (ProductivityMapData sales, _) => sales.productivity.toStringAsFixed(1) + "%", + dataLabelSettings: DataLabelSettings( + overflowMode: OverflowMode.hide, + showZeroValue: false, + isVisible: true + ), color: Colors.green) ]), ) @@ -616,7 +656,12 @@ Drawer navDrawer(BuildContext context, int pageIndex) { selected: (pageIndex == 5), title: Text('Settings'), leading: Icon(Icons.settings, color: Colors.blueGrey), - onTap: () {}, + onTap: () { + if (pageIndex == 5) { + return; + } + Navigator.of(context).pushNamed('/Settings'); + }, ), ListTile( selected: (pageIndex == 6), diff --git a/lib/splash.dart b/lib/splash.dart index 09d32f7..b111a16 100644 --- a/lib/splash.dart +++ b/lib/splash.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:tasktracker/Data.dart'; import 'User.dart' as Users; import 'package:http/http.dart' as http; import 'package:sn_progress_dialog/sn_progress_dialog.dart'; - +import 'theme_provider.dart'; +import 'package:provider/provider.dart'; late ProgressDialog progressDialog; class SplashScreen extends StatefulWidget { const SplashScreen({Key? key}) : super(key: key); @@ -13,6 +15,18 @@ class SplashScreen extends StatefulWidget { } class _SplashScreenState extends State { + Future initSettings() async{ + final prefs = await SharedPreferences.getInstance(); + bool value = true; + if(prefs.containsKey("theme")){ + value = ((await prefs.getInt("theme"))==0); + }else{ + await prefs.setInt("theme", 0); + } + print('Dark theme is : $value'); + final provider = Provider.of(context, listen: false); + provider.toggleTheme(value); + } @override void initState() { // TODO: implement initState @@ -23,6 +37,7 @@ class _SplashScreenState extends State { } void init() async { + await initSettings(); final prefs = await SharedPreferences.getInstance(); // http.Response loginResponse = await Users.login('Test1', 'password'); // print(loginResponse.body); diff --git a/lib/theme_provider.dart b/lib/theme_provider.dart new file mode 100644 index 0000000..b447126 --- /dev/null +++ b/lib/theme_provider.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class ThemeProvider extends ChangeNotifier{ + ThemeMode themeMode = ThemeMode.dark; + + bool get isDarkMode => themeMode == ThemeMode.dark; + + void toggleTheme(bool isOn){ + themeMode = isOn ? ThemeMode.dark : ThemeMode.light; + notifyListeners(); + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 92230df..c0bd609 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -212,6 +212,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" path: dependency: transitive description: @@ -289,6 +296,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.2" shared_preferences: dependency: "direct main" description: @@ -405,7 +419,7 @@ packages: name: syncfusion_flutter_charts url: "https://pub.dartlang.org" source: hosted - version: "19.4.53" + version: "19.4.54" syncfusion_flutter_core: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 631705e..5cc8063 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: flutter: sdk: flutter + provider: ^6.0.2 cupertino_icons: ^1.0.2 uuid: ^3.0.5 wakelock: ^0.6.1+1