Files
IIITB_Menu/lib/models/globalModel.dart
2024-11-04 16:42:36 +05:30

208 lines
5.8 KiB
Dart

// ignore_for_file: unnecessary_this, file_names, library_prefixes
import "dart:convert";
import "package:iiitb_menu/constants.dart";
import 'dart:io';
import "package:flutter/material.dart";
import "package:crypto/crypto.dart";
import "package:http/http.dart";
import "package:intl/intl.dart";
import "package:shared_preferences/shared_preferences.dart";
class GlobalModel extends ChangeNotifier {
late Map<dynamic, dynamic> mainData;
DateTime currentDate = DateTime.now();
String menuTime = breakfast;
DataStatus menuAvailable = DataStatus.Loading;
GlobalModel() {
// print("In constructor");
GlobalModel.loadData2().then((value) {
mainData = value;
if (this.mainData["dates"].keys.contains(this.date)) {
this.menuAvailable = DataStatus.Loaded;
} else {
this.menuAvailable = DataStatus.NotFound;
}
notifyListeners();
});
}
updateCall() async {
this.menuAvailable = DataStatus.Loading;
notifyListeners();
this.mainData = await GlobalModel.updateLocal();
if (this.mainData["dates"].keys.contains(this.date)) {
this.menuAvailable = DataStatus.Loaded;
} else {
this.menuAvailable = DataStatus.NotFound;
}
notifyListeners();
}
static Future<String> getLatestHash() async {
try {
Response hashRequest = await get(Uri.parse(hashLink));
if (hashRequest.statusCode == 200) {
return hashRequest.body.replaceAll("\n", "");
} else {
return "";
}
} on (ClientException, SocketException, HttpException) catch (exce) {
print("Unable to download hash");
print(exce);
return "";
}
}
static Future<String> getLatestData() async {
try {
Response dataRequest = await get(Uri.parse(dataLink));
return dataRequest.body;
} on SocketException catch (exce) {
print("Unable to download any data");
print(exce);
return "";
}
}
static Future<Map> updateLocal() async {
// Set main data and return the data to be used in constructor
String remoteHash = await GlobalModel.getLatestHash();
final SharedPreferences prefs = await SharedPreferences.getInstance();
String? rawData = prefs.getString(storageKey);
rawData ??= "";
String rawHash = md5.convert(utf8.encode(rawData)).toString();
if (remoteHash != rawHash) {
print("Local data is out of date, updating local");
print("Old Hash: $rawHash");
print("New Hash: $remoteHash");
// Donwload new data and save it.
rawData = await getLatestData();
Map returnData = jsonDecode(rawData);
prefs.setString(storageKey, rawData);
return returnData;
} else {
// return the same data
print("Local data is up to date");
return jsonDecode(rawData);
}
}
static Future<Map> loadData2() async {
/* New flow for fetching data:
Get cached data into a var
if theres nothing:
get data
generate hash and store both the data and hash
else:
return the current data
Move the download and get hash part to new method - done
create a new method for updating the current data.
This checks for update and saves new data to sharedprefs if necessary,
*/
late Map returnData;
final SharedPreferences prefs = await SharedPreferences.getInstance();
String? rawData;
rawData = prefs.getString(storageKey);
if (rawData != null) {
print("Some data found");
returnData = jsonDecode(rawData);
return returnData;
} else {
print("Data Not Found");
return GlobalModel.updateLocal();
}
}
static Future<Map> loadData() async {
late Map returnData;
final SharedPreferences prefs = await SharedPreferences.getInstance();
String? rawData;
String rawHash;
rawData = prefs.getString(storageKey);
// print(rawData);
if (rawData != null) {
// print("data found");
rawHash = md5.convert(utf8.encode(rawData)).toString();
// print("Hash of Raw Data:");
// print(rawHash);
returnData = jsonDecode(rawData);
} else {
print("Data Not Found");
returnData = {};
rawHash = "";
}
String remoteHash = await GlobalModel.getLatestHash();
print("Remote Hash: $remoteHash");
if (remoteHash == "") {
} else if (remoteHash == rawHash) {
print("Remote hash $remoteHash is same as local hash $rawHash");
} else {
print("Remote hash $remoteHash is NOT the same as local hash $rawHash");
print("Getting data from remote");
rawData = await getLatestData();
if (rawData == "") {
return {};
}
returnData = jsonDecode(rawData);
prefs.setString(storageKey, rawData);
}
return returnData;
}
String get date {
return DateFormat("dd-MM-yyyy").format(this.currentDate);
}
void incrDate() {
this.currentDate = this.currentDate.add(const Duration(days: 1));
this.isMenuAvailable();
notifyListeners();
}
void decrDate() {
this.currentDate = this.currentDate.add(const Duration(days: -1));
this.isMenuAvailable();
notifyListeners();
}
void setMenuTime(int time) {
switch (time) {
case 0:
this.menuTime = breakfast;
notifyListeners();
break;
case 1:
this.menuTime = lunch;
notifyListeners();
break;
case 2:
this.menuTime = snak;
notifyListeners();
break;
case 3:
this.menuTime = dinner;
notifyListeners();
break;
default:
}
}
void isMenuAvailable() {
if (this.mainData["dates"].keys.contains(this.date)) {
this.menuAvailable = DataStatus.Loaded;
} else {
this.menuAvailable = DataStatus.NotFound;
}
}
void setDateToADay([DateTime? aDay]) {
this.currentDate = aDay ?? DateTime.now();
this.isMenuAvailable();
notifyListeners();
}
}