Flutter TableCalendar . SharedPreferences - flutter

I want to save the table calendar data.
First of all, I succeeded in creating data for each date, but I don't know how to use sharedPreferences.
I don't know what it is even if I googled it and applied it in various ways.
https://medium.flutterdevs.com/display-dynamic-events-at-calendar-in-flutter-22b69b29daf6
I think the code that's closest to the answer is this person's method
If you apply it and make some changes, you will encounter various bugs.
I spent almost a week on this for three hours. It's so hard that I just want to solve it today.
I have to work out, and I have a lot of other assignments
Because of the desire to keep solving this problem, it doesn't get out of the chair.
My personality is getting dirty after meeting a problem that hasn't been solved for a week.
I beg you.
class DiaryService extends ChangeNotifier {
DateTime focusedDay = DateTime.now();
DateTime selectedDay = DateTime.now();
TextEditingController createFieldController = TextEditingController();
TextEditingController updateFieldController = TextEditingController();
List<Diary> diaryList = [];
Map<DateTime, List<Diary>> diaryMap = {};
List<Diary> getByDate(DateTime date) {
return diaryMap[date] ?? [];
}
void create(String text, DateTime selectedDate) {
diaryList.add(Diary(text: text, createdAt: DateTime.now(), selectedDate:
selectedDate));
diaryMap[selectedDate] = diaryList.where((element) {
return element.selectedDate == selectedDate;
}).toList();
print(selectedDate.day);
notifyListeners();
}
void update(DateTime createdAt, String newContent) {
int t = diaryList.indexWhere((element) => element.createdAt == createdAt);
diaryList.removeWhere((element) => element.createdAt == createdAt);
diaryList.insert(t, Diary(text: newContent, createdAt: createdAt,
selectedDate: selectedDay));
addListInMap();
notifyListeners();
}
void delete(DateTime createdAt) {
diaryList.removeWhere((element) => element.createdAt == createdAt);
addListInMap();
print(getByDate);
print(diaryMap);
notifyListeners();
}
void addListInMap() {
diaryMap[selectedDay] = diaryList.where((element) => element.selectedDate
== selectedDay).toList();
}
void encodeData() async {
String dd = Diary.encode(diaryList);
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("diaryList", dd);
notifyListeners();
}
Future<List<Diary>> decodeData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String getData = prefs.getString("diaryList") ?? "[]";
print(getData);
diaryList = Diary.decode(getData);
notifyListeners();
return diaryList;
}
}

Related

How to persist value from range slider in shared preferences?

I need to persist value from range slider to shared preferences, when user leaves page with sliders, it will still save value, not without resetting to default settings (default is 1).
I am trying to make things like that:
#override
void initState() {
// _loadSlider();
super.initState();
}
#override
void dispose() {
_debounce?.cancel();
super.dispose();
}
var _currentRangeValues = const RangeValues(1, 16);
void _loadSlider() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
_currentRangeValues = (prefs.getStringList('sliderGain') ??
[
_currentRangeValues.start.round().toString(),
_currentRangeValues.end.toString()
]) as RangeValues;
});
}
// change slider value to value
void _changeSlider(RangeValues value) {
setState(() {
_currentRangeValues = value;
});
}
// store slider value
void _storeSlider() async {
final prefs = await SharedPreferences.getInstance();
prefs.setStringList('sliderGain', [
_currentRangeValues.start.round().toString(),
_currentRangeValues.end.round().toString()
]);
}
But I'm getting an error
RangeValues is not subtype of type List
How to resolve this issue?
I found what the issue was about my slider and attempts to save data from it to sharedprefernces. So it needs to convert to List after declaring the range value variable. After that, I made small changes in the code and put data from the declared list into the get string, and after that everything worked. Thanks to the previous commenter for the tip.
void _loadSlider() async {
final prefs = await SharedPreferences.getInstance();
List<String> valuesString = [currentRange.start.round().toString(), currentRange.end.round().toString() ];
setState(() {
valuesString = (prefs.getStringList('sliderGain') ??
[
valuesString.toString()
]);
print(valuesString);
});
}

displaying only the current user data

I protected data_service with current user to only display the current user's habits.
data_service.dart:
class DataService {...
late final Database db;
Users? _user;
late final StreamData<Map<int, Habit>> habits;
Future<void> init() async {
db = await HabitsDb.connectToDb();
habits = StreamData(initialValue: await _getAllHabits(), broadcast: true);
}
String get userEmail => AuthService.firebase().currentUser!.email;
Future<Map<int, Habit>> _getAllHabits() async {
getOrCreateUser(email: userEmail); //issue
final habits = await _getAllHabitsFromDb();
final map = Map<int, Habit>();
final currentUser = _user;
print(currentUser);
for (final habit in habits) {
if (currentUser != null) {
print(currentUser.id);
print(habit.userId);
if (habit.userId == currentUser.id) {
map[habit.id] = habit;
}
}
//map[habit.userId] = currentUser?.id;
}
return map;
}
Future<List<Habit>> _getAllHabitsFromDb() async {
final habitsMap = await HabitsDb.getAllHabits(db);
final habitsList = habitsMap.map((e) => Habit.fromDb(e)).toList();
return habitsList;
}
Future<Users> getOrCreateUser({
required String email,
bool setAsCurrentUser = true,
}) async {
try {
//we found the user
final user = await getUser(email: email);
if (setAsCurrentUser) {
_user = user;
}
print(_user?.email);
return user;
} on CouldNotFindUser {
//we didn't find the user
final createdUser = await createUser(email: email);
if (setAsCurrentUser) {
_user = createdUser;
}
return createdUser;
} catch (e) {
rethrow;
}
}
...}
in main class:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final dataService = DataService();
await dataService.init();
GetIt.I.registerSingleton(dataService);
... }
StreamData class:
class StreamData<T> {
List<Habit> _notes = [];
User? _user;
late final StreamController<T> _controller;
Stream<T> get stream => _controller.stream;
late T _value;
T get value => _value;
StreamData({required T initialValue, bool broadcast = true}) {
if (broadcast) {
_controller = StreamController<T>.broadcast();
} else {
_controller = StreamController<T>();
}
_value = initialValue;
}
the problem is that the line getOrCreateUser(email: userEmail); is only called once and it does not work when I switch user and I need to Hot Restart to fix it. I think using Futurebuilder will fix it. but if yes, how do I use it when there is a need to call dataService.init at the beginning of the main?
Since your getOrCreateUser function is declared as async, you'll want to use await when you call it in _getAllHabits:
await getOrCreateUser(email: userEmail)
This ensures the getOrCreateUser code has completed before the rest of the code in _getAllHabits (that depends on the result of getOrCreateUser) executes.

How do I get a query from another file to return a bool?

I am integrating the following system into my to-do app:
Every time the user opens the app, it should check whether the date stored in Cloud Firestore has been exceeded.
If this is the case, all To-Dos of the user should be reset to false.
This is the date in Cloud Firestore I’m looking for:
This function should check if the date has been exceeded:
Future<bool> checkTime() async{
DateTime now = DateTime.now();
var query = users.where('Startdatum', isLessThanOrEqualTo: now);
query = query.where('userID', isEqualTo: userID);
final querySnapshot = await query.get();
return querySnapshot.size > 0;
}
And this function should reset all To-Dos to false:
Future allFalse() async{
return await users.doc(userID).get().then((DocumentSnapshot doc) {
var updateMap = new Map();
var toDos = doc['Level'];
for (var item in toDos.keys) {
updateMap[item] = false;
}
doc.reference.update({'Level' : updateMap});
});
}
I created both functions in a separate file (database), as you can see here:
class DatabaseService {
String userID;
DatabaseService(this.userID);
final CollectionReference users =
FirebaseFirestore.instance.collection('users');
Future allFalse() async {
return await users.doc(userID).get().then((DocumentSnapshot doc) {
var updateMap = new Map();
var toDos = doc['Level'];
for (var item in toDos.keys) {
updateMap[item] = false;
}
doc.reference.update({'Level': updateMap});
});
}
Future<bool> checkTime() async {
DateTime now = DateTime.now();
var query = users.where('Startdatum', isLessThanOrEqualTo: now);
query = query.where('userID', isEqualTo: userID);
final querySnapshot = await query.get();
return querySnapshot.size > 0;
}
}
I create an if condition in in inite State that includes checkTime. If checkTime returns true, the Future returns allFalse, which sets all To-Dos to false.
class _UebersichtState extends State<Uebersicht> {
User? user;
late DatabaseService database;
Future<void> connect() async{
final FirebaseAuth auth = FirebaseAuth.instance;
UserCredential result = await auth.signInAnonymously();
user = result.user;
database = DatabaseService(user!.uid);
}
#override
void initState() {
// TODO: implement initState
super.initState();
connect();
Future.delayed(Duration(seconds: 3), () async{
if(await database.checkTime()) {
return await database.allFalse();}
else print('Still time left');
});
}
I used a delay because the connect () function has to be executed first, it initializes database.
When I start the app, no error appears, but the To-Dos are not reset either.
Today we have the 21. 12. 2021 and in Cloud Firestore is 14. 12. 21 deposited.
The function allFalse works, it resets the To-Dos all.
It must be the function checkTime, which does not return a bool in the if condition. I just replaced it with if (0 == 0) and that triggers allFalse.
Can someone help me?
This is just a guess, but I believe this is the problem:
query = query.where('userID', isEqualTo: userID);
The above line would only work if your document had a field userID and said field was equal to your UID, but from what I could gather, you identify the UID by the name of the documents, if that is the case, this should work?
Future<bool> checkTime() async {
CollectionReference users = FirebaseFirestore.instance.collection('users');
final now = DateTime.now();
final doc = await users.doc(userID).get();
final stufenzeit = (doc.data() as Map<String, dynamic>)['Stufenzeit'] as Map<String, dynamic>;
final storedDate = (stufenSetit['Startdatum'] as TimeStamp).toDate();
return now.compareTo(storedDate) > 0;
}
There's probably also a way to do it with queries, but I am not so well versed on those to be completely honest.

How do I make Flutter Widget disappear after certain time (in days)?

I have few widgets on home screen, one of them is there only if user save some data, from that moment
I want to count 7 days and if nothing else happen widget will be deleted.
I tried something like this:
//When user save data to widget
_saveTime() async {
SharedPreferences pref = await SharedPreferences.getInstance();
pref.setString(
'StoreTime', DateTime.now().add(Duration(days: 8)).toString());
}
Then in the Home page
...
bool _thirdMenu;
String _difDays = '';
#override
initState() {
super.initState();
_thirdMenu = true;
WidgetsBinding.instance.addObserver(this);
_init();
}
_init() async {
SharedPreferences pref = await SharedPreferences.getInstance();
String oldTimePref = pref.getString('StoreTime') ?? '1969-07-20 20:18:04Z';
DateTime oldTime = DateTime.parse(oldTimePref);
DateTime newTime = DateTime.now();
var difference = oldTime.difference(newTime);
if (difference.inDays > 0) {
setState(() {
_thirdMenu = true;
_difDays = difference.inDays.toString();
});
} else {
setState(() {
_thirdMenu = false;
});
}
}
Not working, time stay the same and widget still showing...
If you want to work with days, I think you can work without hours and minutes.
You can isolate the days and check without using time difference.
int oldDay = oldTime.day;
int today = newTime.day;
if(today - oldDay >= 7) {
setState(() {
_thirdMenu = false;
});
} else {
setState(() {
_thirdMenu = true;
});
}

How to save a list with SharedPreferences?

I tried to save a List (which is called test)with two variables with SharedPreferences. I tried the code below, but I get some errors. Does anybody see the mistake i made? (I think it´s kind of an easy to fix mistake, but I´m a beginner and can´t find it ;)
int counter1 = 0;
int counter2 = 20;
String nameKey = "eins";
var test = [counter1, counter2];
#override
void initState() {
super.initState();
}
Future<bool> save() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
return await preferences.setIntList(nameKey, test);
}
Future<List<int>> load() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
return preferences.getIntList(nameKey);
}
set() {
load().then((value) {
setState(() {
test = value;
});
});
}
Thanks in advance :)
Future<List<String>> load() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
return preferences.getStringList(nameKey);
}