Merge branch 'master' into othmane6
continuous-integration/drone/push Build is failing Details

pull/7/head^2
Othmane BENJELLOUN 2 years ago
commit 1eb9d648e9

@ -12,6 +12,8 @@ steps:
- name: build-apk - name: build-apk
image: ghcr.io/cirruslabs/flutter:3.13.9 image: ghcr.io/cirruslabs/flutter:3.13.9
commands: commands:
- flutter clean
- dart run build_runner build
- flutter build apk - flutter build apk
- sfm_apk=sfm_$(date +"%Y_%m_%d_%H_%M_%S").apk - sfm_apk=sfm_$(date +"%Y_%m_%d_%H_%M_%S").apk
- cp ./build/app/outputs/flutter-apk/app-release.apk $sfm_apk - cp ./build/app/outputs/flutter-apk/app-release.apk $sfm_apk

4
.gitignore vendored

@ -14,6 +14,10 @@
# Firebase # Firebase
.firebase/ .firebase/
# ObjectBox
objectbox-model.json
objectbox.g.dart
# IntelliJ related # IntelliJ related
*.iml *.iml
*.ipr *.ipr

@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited. # This file should be version controlled and should not be manually edited.
version: version:
revision: "d211f42860350d914a5ad8102f9ec32764dc6d06" revision: "db7ef5bf9f59442b0e200a90587e8fa5e0c6336a"
channel: "stable" channel: "stable"
project_type: app project_type: app
@ -13,11 +13,11 @@ project_type: app
migration: migration:
platforms: platforms:
- platform: root - platform: root
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
- platform: linux - platform: linux
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
# User provided section # User provided section

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

@ -1,10 +1,15 @@
import 'package:smartfit_app_mobile/modele/activity_saver.dart';
import 'package:smartfit_app_mobile/modele/helper.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
import 'package:smartfit_app_mobile/common_widget/container/workout_row/workout_row_generic.dart'; import 'package:smartfit_app_mobile/common_widget/container/workout_row/workout_row_generic.dart';
import 'package:smartfit_app_mobile/common_widget/container/workout_row/workout_row_walking.dart'; import 'package:smartfit_app_mobile/common_widget/container/workout_row/workout_row_walking.dart';
import 'package:smartfit_app_mobile/modele/activity.dart'; import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart'; import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart'; import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -16,12 +21,14 @@ class ListActivityWidget extends StatefulWidget {
} }
class _ListActivityWidget extends State<ListActivityWidget> { class _ListActivityWidget extends State<ListActivityWidget> {
final ApiWrapper api = ApiWrapper();
final InfoMessage infoManager = InfoMessage();
final ListActivityUtile _utile = ListActivityUtile(); final ListActivityUtile _utile = ListActivityUtile();
final ManagerFile managerFile = ManagerFile(); final ManagerFile managerFile = ManagerFile();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
void onClick(ActivityOfUser activityObj) async { Future<void> onClick(ActivityOfUser activityObj) async {
if (!Provider.of<User>(context, listen: false) if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity .managerSelectedActivity
.fileNotSelected(activityObj.fileUuid)) { .fileNotSelected(activityObj.fileUuid)) {
@ -33,19 +40,20 @@ class _ListActivityWidget extends State<ListActivityWidget> {
} }
Tuple2<bool, String> result = Tuple2<bool, String> result =
await _utile.getContentActivity(context, activityObj); await _utile.getContentActivity(context, activityObj, infoManager);
if (!result.item1) { if (!result.item1) {
return; return;
} }
// TODO: Hein?
Provider.of<User>(context, listen: false).removeActivity(activityObj); Provider.of<User>(context, listen: false).removeActivity(activityObj);
Provider.of<User>(context, listen: false).insertActivity(0, activityObj); Provider.of<User>(context, listen: false).insertActivity(0, activityObj);
} }
void onDelete(ActivityOfUser activityObj) async { // TODO: Understand :(
if (await _utile.deleteFileOnBDD( Future<void> onDelete(ActivityOfUser activityObj) async {
Provider.of<User>(context, listen: false).token, if (await api.deleteFile(Provider.of<User>(context, listen: false).token,
activityObj.fileUuid)) { activityObj.fileUuid, infoManager)) {
if (!Provider.of<User>(context, listen: false) if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity .managerSelectedActivity
.fileNotSelected(activityObj.fileUuid)) { .fileNotSelected(activityObj.fileUuid)) {
@ -53,6 +61,11 @@ class _ListActivityWidget extends State<ListActivityWidget> {
.managerSelectedActivity .managerSelectedActivity
.removeSelectedActivity(activityObj.fileUuid); .removeSelectedActivity(activityObj.fileUuid);
} }
if (!Helper.isPlatformWeb()) {
ActivitySaver actSaver = await ActivitySaver.create();
actSaver.deleteActivity(activityObj.fileUuid);
localDB.removeActivity(activityObj.fileUuid);
}
Provider.of<User>(context, listen: false).removeActivity(activityObj); Provider.of<User>(context, listen: false).removeActivity(activityObj);
} }
} }
@ -65,41 +78,62 @@ class _ListActivityWidget extends State<ListActivityWidget> {
return Material( return Material(
color: Colors.transparent, color: Colors.transparent,
child: ListView.builder( child: Column(
padding: EdgeInsets.zero, children: [
physics: const NeverScrollableScrollPhysics(), Visibility(
shrinkWrap: true, visible: infoManager.isVisible,
itemCount: Provider.of<User>(context, listen: true).listActivity.length, child: Text(infoManager.message,
itemBuilder: (context, index) { style: TextStyle(color: infoManager.messageColor))),
ActivityOfUser activityObj = ListView.builder(
Provider.of<User>(context, listen: true).listActivity[index]; padding: EdgeInsets.zero,
Map<String, dynamic> activityMap; physics: const NeverScrollableScrollPhysics(),
// -- Si categorie == marche shrinkWrap: true,
if (activityObj.category == managerFile.marche) { itemCount:
activityMap = activityObj.toMapWalking(); Provider.of<User>(context, listen: true).listActivity.length,
return InkWell( itemBuilder: (context, index) {
onTap: () {}, ActivityOfUser activityObj =
child: WorkoutRowWalking( Provider.of<User>(context, listen: true).listActivity[index];
wObj: activityMap, Map<String, dynamic> activityMap;
onDelete: () => onDelete(activityObj), // -- Si categorie == marche
onClick: () => onClick(activityObj), if (activityObj.category == managerFile.marche) {
isSelected: isSelected(activityObj), activityMap = activityObj.toMapWalking();
), return InkWell(
); onTap: () {},
} else { child: WorkoutRowWalking(
// -- Default -- // wObj: activityMap,
activityMap = activityObj.toMapGeneric(); onDelete: () async {
return InkWell( await onDelete(activityObj);
onTap: () {}, setState(() {});
child: WorkoutRowGeneric( },
wObj: activityMap, onClick: () async {
onDelete: () => onDelete(activityObj), await onClick(activityObj);
onClick: () => onClick(activityObj), setState(() {});
isSelected: isSelected(activityObj), },
), isSelected: isSelected(activityObj),
); ),
} );
}, } else {
// -- Default -- //
activityMap = activityObj.toMapGeneric();
return InkWell(
onTap: () {},
child: WorkoutRowGeneric(
wObj: activityMap,
onDelete: () async {
await onDelete(activityObj);
setState(() {});
},
onClick: () async {
await onClick(activityObj);
setState(() {});
},
isSelected: isSelected(activityObj),
),
);
}
},
),
],
), ),
); );
} }

@ -10,6 +10,7 @@ class VolumesList extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var media = MediaQuery.of(context).size; var media = MediaQuery.of(context).size;
// TODO: True message with variables and context aware
if (volume["nbActivity"] == 0) { if (volume["nbActivity"] == 0) {
return const Text("Aucune activité ces x jours/mois/années"); return const Text("Aucune activité ces x jours/mois/années");
} }

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/main.dart';
class ProfileSwitch extends StatefulWidget {
final String title;
final String description;
final String iconFilename;
const ProfileSwitch(this.title, this.description, this.iconFilename,
{super.key});
@override
State<ProfileSwitch> createState() => _ProfileSwitchState();
}
class _ProfileSwitchState extends State<ProfileSwitch> {
bool switchValue = localDB.getSaveLocally();
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
decoration: BoxDecoration(
color: TColor.white,
borderRadius: BorderRadius.circular(15),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 2)]),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
widget.title,
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 8,
),
SizedBox(
height: 30,
child:
Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
Image.asset("assets/img/${widget.iconFilename}",
height: 28, width: 28, fit: BoxFit.contain),
const SizedBox(
width: 15,
),
Expanded(
child: Text(
widget.description,
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
),
Switch(
value: switchValue,
activeColor: Colors.orange,
onChanged: (bool value) {
setState(() {
switchValue = value;
localDB.setSaveLocally(switchValue);
});
}),
]))
]));
}
}

@ -1,10 +1,27 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/modele/local_db/db_impl.dart';
import 'package:smartfit_app_mobile/modele/local_db/get_web_db.dart'
if (dart.library.io) 'package:smartfit_app_mobile/modele/local_db/get_native_db.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/view/login/signup_view.dart'; import 'package:smartfit_app_mobile/view/login/signup_view.dart';
import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart';
late DbImpl localDB;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb) {
DbImpl tmp = getDbImpl();
localDB = await tmp.create();
await localDB.init();
localDB.initConfig();
}
void main() {
runApp(ChangeNotifierProvider( runApp(ChangeNotifierProvider(
create: (context) => User(), child: const MyApp())); create: (context) => User(), child: const MyApp()));
} }
@ -14,6 +31,28 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget viewToDisplay = const SignUpView();
// Skip sign-up + fill provider if user already connected
if (!kIsWeb) {
if (localDB.hasUser()) {
final User user = localDB.getUser();
final userActivities = localDB.getAllActivities();
context.watch<User>().username = user.username;
context.watch<User>().email = user.email;
context.watch<User>().token = user.token;
context.watch<User>().listActivity = userActivities;
stdout.write("===== USER =====\n");
stdout.write("Username: ${user.username}\n");
stdout.write("Email: ${user.email}\n");
stdout.write("Token: ${user.token}\n");
viewToDisplay = const MainTabView();
}
}
return MaterialApp( return MaterialApp(
title: 'SmartFit', title: 'SmartFit',
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
@ -35,9 +74,7 @@ class MyApp extends StatelessWidget {
// tested with just a hot reload. // tested with just a hot reload.
primaryColor: TColor.primaryColor1, primaryColor: TColor.primaryColor1,
fontFamily: "Poppins"), fontFamily: "Poppins"),
home: const SignUpView(), home: viewToDisplay,
//home: const TestPage(),
//home: const ProfileView(),
); );
} }
} }

@ -0,0 +1,43 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:path/path.dart' as p;
import "package:path_provider/path_provider.dart";
import 'package:smartfit_app_mobile/main.dart';
class ActivitySaver {
String saveDirectory = "activities";
late final Directory applicationDocumentsDir;
ActivitySaver._create(this.applicationDocumentsDir);
Uint8List getActivity(String uuid) {
String filename = localDB.getActivityFilenameByUuid(uuid);
final file =
File(p.join(applicationDocumentsDir.path, saveDirectory, filename));
return file.readAsBytesSync();
}
Future<void> saveActivity(Uint8List activityFile, String filename) async {
stdout.write("Creating activity file...\n");
final file = await File(
p.join(applicationDocumentsDir.path, saveDirectory, filename))
.create(recursive: true); // To create dir if not exists
file.writeAsBytesSync(activityFile);
stdout.write("Activity file created\n");
}
void deleteActivity(String uuid) {
String filename = localDB.getActivityFilenameByUuid(uuid);
final file =
File(p.join(applicationDocumentsDir.path, saveDirectory, filename));
file.deleteSync();
}
static Future<ActivitySaver> create() async {
stdout.write("Activity Saver: Created\n");
final appDir = await getApplicationDocumentsDirectory();
return ActivitySaver._create(appDir);
}
}

@ -1,22 +1,115 @@
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart'; import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart'; import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:smartfit_app_mobile/modele/local_db/request_local.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart'; import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
import 'package:email_validator/email_validator.dart'; import 'package:email_validator/email_validator.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
import 'dart:convert'; import 'dart:convert';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'dart:io';
class ApiWrapper { class ApiWrapper {
IDataStrategy api = RequestApi(); late IDataStrategy api;
String noConnectionMessage =
"It seems like you are lost far away in the universe, no connection found :)";
// HELPERS
// TODO: Change check online for flutterWeb
Future<bool> isOnline() async {
try {
final result = await InternetAddress.lookup('example.com')
.timeout(const Duration(seconds: 2));
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
} on SocketException catch (_) {
return false;
} on UnsupportedError catch (_) {
return true;
}
return true;
}
Future<void> init() async {
// TODO: Fait à la pisse en despi (je voulais juste dormir)
if (kIsWeb) {
api = RequestApi();
return;
}
if (await isOnline()) {
stdout.write("(API) ");
api = RequestApi();
} else if (!kIsWeb && localDB.getSaveLocally()) {
stdout.write("(LOCAL) ");
api = RequestLocal();
} else {
stdout.write("(API OFFLINE) ");
api = RequestApi();
}
}
bool handleOffline(InfoMessage infoManager) {
if (api is RequestLocal) {
infoManager.displayMessage(noConnectionMessage, true);
return true;
}
return false;
}
// BOTH (ONLINE + OFFLINE)
Future<Tuple2> getUserInfo(String token) async {
await init();
Tuple2 res = await api.getInfoUser(token);
stdout.write("getUserInfo: ${res.item1}\n");
return res;
}
Future<Tuple2> getFile(
String token, String fileUuid, InfoMessage infoManager) async {
await init();
Tuple2 res = await api.getFile(token, fileUuid);
if (!res.item1) {
infoManager.displayMessage(noConnectionMessage, true);
}
stdout.write("getFile: ${res.item1}\n");
return res;
}
Future<Tuple2> getFiles(String token, InfoMessage infoManager) async {
await init();
Tuple2 res = await api.getFiles(token);
if (!res.item1) {
infoManager.displayMessage(noConnectionMessage, true);
}
Future<bool> modifyUserInfo(String infoToModify, String value, String token, stdout.write("getFiles: ${res.item1}\n");
return res;
}
// ONLINE
Future<bool> updateUserInfo(String infoToModify, String value, String token,
InfoMessage infoManager) async { InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return false;
if (infoToModify == 'email' && EmailValidator.validate(value) || if (infoToModify == 'email' && EmailValidator.validate(value) ||
infoToModify == 'password' || infoToModify == 'password' ||
infoToModify == 'username') { infoToModify == 'username') {
Tuple2<bool, String> res = Tuple2<bool, String> res =
await api.modifAttribut(token, infoToModify, value); await api.modifAttribut(token, infoToModify, value);
if (res.item1 == true) {
stdout.write("updateUserInfo: ${res.item1}\n");
if (res.item1) {
infoManager.displayMessage( infoManager.displayMessage(
"${infoToModify.capitalize()} modified succesfully !", false); "${infoToModify.capitalize()} modified succesfully !", false);
return true; return true;
@ -34,17 +127,84 @@ class ApiWrapper {
Future<Tuple2<bool, String>> login( Future<Tuple2<bool, String>> login(
String password, String email, InfoMessage infoManager) async { String password, String email, InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return const Tuple2(false, "offline");
String hash = sha256.convert(utf8.encode(password)).toString(); String hash = sha256.convert(utf8.encode(password)).toString();
Tuple2<bool, String> res = await api.connexion(email, hash); Tuple2<bool, String> res = await api.connexion(email, hash);
stdout.write("login: ${res.item1}\n");
if (res.item1) { if (res.item1) {
return Tuple2(true, res.item2); // return token return Tuple2(true, res.item2);
} else { } else {
infoManager.displayMessage( infoManager.displayMessage(
"Authentification failed! Enter your actual password carefully.", "Authentification failed! Enter your actual password carefully.",
true); true);
return const Tuple2(false, "An error occured during connexion!"); return const Tuple2(false, "An error occured during connexion!");
} // need to be better }
}
Future<Tuple2<bool, String>> deleteUser(
String token, InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return const Tuple2(false, "offline");
Tuple2<bool, String> res = await api.deleteUser(token);
stdout.write("deleteUser: ${res.item1}\n");
return res;
}
Future<Tuple2<bool, String>> createUser(String email, String hash,
String username, InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return const Tuple2(false, "offline");
Tuple2<bool, String> res = await api.postUser(email, hash, username);
stdout.write("createUser: ${res.item1}\n");
return res;
}
Future<Tuple2<bool, String>> uploadFile(
String token, File file, InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return const Tuple2(false, "offline");
Tuple2<bool, String> res = await api.uploadFile(token, file);
stdout.write("uploadFile: ${res.item1}\n");
return res;
}
Future<Tuple2<bool, String>> uploadFileByte(
String token,
Uint8List contentFile,
String filename,
String category,
DateTime date,
ActivityInfo activityInfo,
InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return const Tuple2(false, "offline");
Tuple2<bool, String> res = await api.uploadFileByte(
token, contentFile, filename, category, date, activityInfo);
if (!res.item1) infoManager.displayMessage(noConnectionMessage, true);
stdout.write("uploadFileByte: ${res.item1}\n");
return res;
}
Future<bool> deleteFile(
String token, String fileUuid, InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return false;
bool res = await api.deleteFile(token, fileUuid);
if (!res) infoManager.displayMessage(noConnectionMessage, true);
stdout.write("deleteFile: $res\n");
return res;
} }
} }

@ -15,11 +15,13 @@ abstract class IDataStrategy {
// Get Token validate // Get Token validate
Future<Tuple2<bool, String>> connexion(String email, String hash); Future<Tuple2<bool, String>> connexion(String email, String hash);
// Get all files for user // Get all files for user (LOCAL OK)
Future<Tuple2> getFiles(String token); Future<Tuple2> getFiles(String token);
// Upload file on BDD // Upload file on BDD
Future<Tuple2<bool, String>> uploadFile(String token, File file); Future<Tuple2<bool, String>> uploadFile(String token, File file);
// Upload file as bytes
Future<Tuple2<bool, String>> uploadFileByte( Future<Tuple2<bool, String>> uploadFileByte(
String token, String token,
Uint8List contentFile, Uint8List contentFile,
@ -28,21 +30,16 @@ abstract class IDataStrategy {
DateTime date, DateTime date,
ActivityInfo activityInfo); ActivityInfo activityInfo);
// Get one file by id // Get one file by id (LOCAL OK)
Future<Tuple2> getFile(String token, String fileUuid); Future<Tuple2> getFile(String token, String fileUuid);
// Delete one file on BDD // Delete one file on BDD
Future<Tuple2<bool, String>> deleteFile(String token, String fileUuid); Future<bool> deleteFile(String token, String fileUuid);
// Get info on user (LOCAL OK)
Future<Tuple2> getInfoUser(String token); Future<Tuple2> getInfoUser(String token);
/* -> Modification attribut
// Update email
Future<void> updateEmail(String token, String email);
// Update username
Future<void> updateUsername(String token, String username);
*/
// Update email, password, username
Future<Tuple2<bool, String>> modifAttribut( Future<Tuple2<bool, String>> modifAttribut(
String token, String nameAttribut, String newValue); String token, String nameAttribut, String newValue);
} }

@ -19,85 +19,105 @@ class RequestApi implements IDataStrategy {
var request = http.Request('GET', url); var request = http.Request('GET', url);
request.headers.addAll(<String, String>{'Authorization': token}); request.headers.addAll(<String, String>{'Authorization': token});
var streamedResponse = await request.send(); try {
final response = await http.Response.fromStream(streamedResponse); var streamedResponse = await request.send();
// !! Crée un fichier comme ca avec les bytes !! final response = await http.Response.fromStream(streamedResponse);
//File("//").writeAsBytes(response.bodyBytes);
if (response.statusCode == 200) { if (response.statusCode == 200) {
return Tuple2(true, response.bodyBytes); return Tuple2(true, response.bodyBytes);
} }
if ((response.statusCode == 401)) { if ((response.statusCode == 401)) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
} }
if ((response.statusCode == 404)) { if ((response.statusCode == 404)) {
return const Tuple2(false, "404 - NOT FOUND"); return const Tuple2(false, "404 - NOT FOUND");
}
// When Network Off
} on SocketException {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@override @override
Future<Tuple2<bool, String>> deleteFile(String token, String fileUuid) async { Future<bool> deleteFile(String token, String fileUuid) async {
final response = await http.delete( try {
Uri.parse('$urlApi/user/files/$fileUuid'), final response = await http.delete(
headers: <String, String>{'Authorization': token}); Uri.parse('$urlApi/user/files/$fileUuid'),
headers: <String, String>{'Authorization': token});
if (response.statusCode == 200) { if (response.statusCode == 200) {
return const Tuple2(true, "Successful"); return true;
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return false;
}
if (response.statusCode == 404) {
return false;
}
} on SocketException catch (_) {
return false;
} }
if (response.statusCode == 404) { return false;
return const Tuple2(false, "404 - NOT FOUND");
}
return const Tuple2(false, "Fail");
} }
@override @override
Future<Tuple2<bool, String>> deleteUser(String token) async { Future<Tuple2<bool, String>> deleteUser(String token) async {
final response = await http.delete(Uri.parse('$urlApi/user'), try {
headers: <String, String>{'Authorization': token}); final response = await http.delete(Uri.parse('$urlApi/user'),
if (response.statusCode == 200) { headers: <String, String>{'Authorization': token});
return const Tuple2<bool, String>(true, "Successful"); if (response.statusCode == 200) {
} else if (response.statusCode == 401) { return const Tuple2<bool, String>(true, "Successful");
return const Tuple2<bool, String>( } else if (response.statusCode == 401) {
false, "401 UNAUTHORIZED - Mauvais ou pas de token"); return const Tuple2<bool, String>(
} else if (response.statusCode == 404) { false, "401 UNAUTHORIZED - Mauvais ou pas de token");
return const Tuple2<bool, String>( } else if (response.statusCode == 404) {
false, "404 NOT FOUND - Pas de compte lié"); return const Tuple2<bool, String>(
false, "404 NOT FOUND - Pas de compte lié");
}
} on SocketException catch (_) {
return const Tuple2<bool, String>(false, "No connection");
} }
return const Tuple2<bool, String>(false, "Fail"); return const Tuple2<bool, String>(false, "Fail");
} }
@override @override
Future<Tuple2> getFiles(String token) async { Future<Tuple2> getFiles(String token) async {
final response = await http.get(Uri.parse('$urlApi/user/files'), try {
headers: <String, String>{'Authorization': token}); final response = await http.get(Uri.parse('$urlApi/user/files'),
headers: <String, String>{'Authorization': token});
if (response.statusCode == 200) { if (response.statusCode == 200) {
return Tuple2(true, return Tuple2(true,
(json.decode(response.body) as List).cast<Map<String, dynamic>>()); (json.decode(response.body) as List).cast<Map<String, dynamic>>());
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@override @override
Future<Tuple2<bool, String>> connexion(String email, String hash) async { Future<Tuple2<bool, String>> connexion(String email, String hash) async {
final response = try {
await http.get(Uri.parse('$urlApi/user/login/$email/$hash')); final response =
if (response.statusCode == 200) { await http.get(Uri.parse('$urlApi/user/login/$email/$hash'));
Map<String, dynamic> json = jsonDecode(response.body); if (response.statusCode == 200) {
return Tuple2<bool, String>(true, json['token'].toString()); Map<String, dynamic> json = jsonDecode(response.body);
} return Tuple2<bool, String>(true, json['token'].toString());
if (response.statusCode == 401) { }
return const Tuple2<bool, String>(false, "UNAUTHORIZED"); if (response.statusCode == 401) {
} return const Tuple2<bool, String>(false, "UNAUTHORIZED");
if (response.statusCode == 404) { }
return const Tuple2<bool, String>(false, "Not found the email"); if (response.statusCode == 404) {
return const Tuple2<bool, String>(false, "Not found the email");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@ -107,19 +127,23 @@ class RequestApi implements IDataStrategy {
String email, String hash, String username) async { String email, String hash, String username) async {
var body = {"email": email, "hash": hash, "username": username}; var body = {"email": email, "hash": hash, "username": username};
var header = {"Content-Type": "application/json"}; var header = {"Content-Type": "application/json"};
final response = await http.post(Uri.parse('$urlApi/user'), try {
headers: header, body: jsonEncode(body)); final response = await http.post(Uri.parse('$urlApi/user'),
headers: header, body: jsonEncode(body));
if (response.statusCode == 200) { if (response.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(response.body); Map<String, dynamic> json = jsonDecode(response.body);
return Tuple2(true, json['token'].toString()); return Tuple2(true, json['token'].toString());
} }
if (response.statusCode == 400) { if (response.statusCode == 400) {
return const Tuple2(false, "400 BAD REQUEST - Json mal formaté"); return const Tuple2(false, "400 BAD REQUEST - Json mal formaté");
} }
if (response.statusCode == 409) { if (response.statusCode == 409) {
return const Tuple2( return const Tuple2(
false, "409 CONFLICT - Déja un compte avec cet email"); false, "409 CONFLICT - Déja un compte avec cet email");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }
@ -127,25 +151,28 @@ class RequestApi implements IDataStrategy {
@override @override
Future<Tuple2<bool, String>> modifAttribut( Future<Tuple2<bool, String>> modifAttribut(
String token, String nameAttribut, String newValue) async { String token, String nameAttribut, String newValue) async {
final response = await http.put(Uri.parse('$urlApi/user/$nameAttribut'), try {
headers: <String, String>{ final response = await http.put(Uri.parse('$urlApi/user/$nameAttribut'),
'Authorization': token, headers: <String, String>{
"Content-Type": "application/json" 'Authorization': token,
}, "Content-Type": "application/json"
body: jsonEncode(<String, String>{nameAttribut: newValue})); },
body: jsonEncode(<String, String>{nameAttribut: newValue}));
if (response.statusCode == 200) {
//Map<String, dynamic> json = jsonDecode(response.body); if (response.statusCode == 200) {
return const Tuple2(true, "200 - OK"); //Map<String, dynamic> json = jsonDecode(response.body);
} return const Tuple2(true, "200 - OK");
if (response.statusCode == 400) { }
return const Tuple2(false, "400 - BAD REQUEST"); if (response.statusCode == 400) {
} return const Tuple2(false, "400 - BAD REQUEST");
if (response.statusCode == 401) { }
return const Tuple2(false, "400 - UNAUTHORIZED"); if (response.statusCode == 401) {
} else { return const Tuple2(false, "400 - UNAUTHORIZED");
return const Tuple2(false, "Fail"); }
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail");
} }
// -- Priviligié uploadFileByte -- // // -- Priviligié uploadFileByte -- //
@ -169,19 +196,23 @@ class RequestApi implements IDataStrategy {
request.fields["SmartFit_Category"] = categoryActivity; request.fields["SmartFit_Category"] = categoryActivity;
request.fields["SmartFit_Date"] = dateActivity; request.fields["SmartFit_Date"] = dateActivity;
final response = await request.send(); try {
final response = await request.send();
if (response.statusCode == 200) { if (response.statusCode == 200) {
return const Tuple2(true, "Successful"); return const Tuple2(true, "Successful");
} }
if (response.statusCode == 400) { if (response.statusCode == 400) {
return const Tuple2(false, "400 - BAD REQUEST"); return const Tuple2(false, "400 - BAD REQUEST");
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
} }
if (response.statusCode == 409) { if (response.statusCode == 409) {
return const Tuple2(false, "409 - CONFLICT"); return const Tuple2(false, "409 - CONFLICT");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail "); return const Tuple2(false, "Fail ");
} }
@ -209,38 +240,45 @@ class RequestApi implements IDataStrategy {
request.fields["SmartFit_Date"] = date.toString(); request.fields["SmartFit_Date"] = date.toString();
request.fields["info"] = activityInfo.toJson(); request.fields["info"] = activityInfo.toJson();
final response = await request.send(); try {
final response = await request.send();
if (response.statusCode == 200) { if (response.statusCode == 200) {
return const Tuple2(true, "Successful"); return const Tuple2(true, "Successful");
} }
if (response.statusCode == 400) { if (response.statusCode == 400) {
return const Tuple2(false, "400 - BAD REQUEST"); return const Tuple2(false, "400 - BAD REQUEST");
} }
if (response.statusCode == 401) { if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED"); return const Tuple2(false, "401 - UNAUTHORIZED");
} }
if (response.statusCode == 409) { if (response.statusCode == 409) {
return const Tuple2(false, "409 - CONFLICT"); return const Tuple2(false, "409 - CONFLICT");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
return const Tuple2(false, "Fail "); return const Tuple2(false, "Fail ");
} }
@override @override
Future<Tuple2> getInfoUser(String token) async { Future<Tuple2> getInfoUser(String token) async {
final response = await http.get(Uri.parse('$urlApi/user/info'), try {
headers: <String, String>{'Authorization': token}); final response = await http.get(Uri.parse('$urlApi/user/info'),
headers: <String, String>{'Authorization': token});
if (response.statusCode == 200) { if (response.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(response.body); Map<String, dynamic> json = jsonDecode(response.body);
return Tuple2(true, json); return Tuple2(true, json);
} }
if (response.statusCode == 400) { if (response.statusCode == 400) {
return const Tuple2(false, "400 - BAD REQUEST"); return const Tuple2(false, "400 - BAD REQUEST");
}
if (response.statusCode == 401) {
return const Tuple2(false, "401 - UNAUTHORIZED");
}
} on SocketException catch (_) {
return const Tuple2(false, "No connection");
} }
if (response.statusCode == 401) { return const Tuple2(false, "Fail");
return const Tuple2(false, "401 - UNAUTHORIZED");
}
return const Tuple2(false, "Fail ");
} }
} }

@ -0,0 +1,10 @@
import 'package:flutter/foundation.dart';
class Helper {
static bool isPlatformWeb() {
if (kIsWeb) {
return true;
}
return false;
}
}

@ -0,0 +1,95 @@
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/local_db/db_impl.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
class DbDummy implements DbImpl {
DbDummy._create();
DbDummy();
@override
Future<DbDummy> create() async {
return DbDummy._create();
}
@override
Future<void> init() {
throw Exception();
}
// ==== USER ====
@override
void addUser(String username, String email, String token) {
throw Exception();
}
@override
User getUser() {
throw Exception();
}
@override
bool hasUser() {
throw Exception();
}
@override
void deleteUser() {
throw Exception();
}
@override
void setUserMail(String email) {
throw Exception();
}
@override
void setUserName(String username) {
throw Exception();
}
@override
void setUserToken(String token) {
throw Exception();
}
// ==== ACTIVITY ====
@override
void addActivity(String uuid, String filename, String category, String info) {
throw Exception();
}
@override
void removeActivity(String uuid) {
throw Exception();
}
@override
void removeAllActivities() {
throw Exception();
}
@override
String getActivityFilenameByUuid(String uuid) {
throw Exception();
}
@override
List<ActivityOfUser> getAllActivities() {
throw Exception();
}
// ==== CONFIG ====
@override
void initConfig() {
throw Exception();
}
@override
void setSaveLocally(bool saveLocally) {
throw Exception();
}
@override
bool getSaveLocally() {
throw Exception();
}
}

@ -0,0 +1,31 @@
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/activity.dart';
abstract class DbImpl {
DbImpl._create();
Future<DbImpl> create();
Future<void> init();
// ==== USER ====
void addUser(String username, String email, String token);
User getUser();
bool hasUser();
void deleteUser();
void setUserMail(String email);
void setUserName(String username);
void setUserToken(String token);
// ==== ACTIVITY ====
void addActivity(String uuid, String filename, String category, String info);
void removeActivity(String uuid);
void removeAllActivities();
String getActivityFilenameByUuid(String uuid);
List<ActivityOfUser> getAllActivities();
// ==== CONFIG ====
void initConfig();
void setSaveLocally(bool saveLocally);
bool getSaveLocally();
}

@ -0,0 +1,7 @@
import 'package:smartfit_app_mobile/modele/local_db/db_impl.dart';
import 'package:smartfit_app_mobile/modele/local_db/objectbox.dart';
DbImpl getDbImpl() {
DbImpl db = ObjectBox();
return db;
}

@ -0,0 +1,7 @@
import 'package:smartfit_app_mobile/modele/local_db/db_impl.dart';
import 'package:smartfit_app_mobile/modele/local_db/db_dummy.dart';
DbImpl getDbImpl() {
DbImpl db = DbDummy();
return db;
}

@ -0,0 +1,33 @@
import 'package:objectbox/objectbox.dart';
@Entity()
class User {
@Id()
int id = 0;
String username;
String email;
String token;
User(this.id, this.username, this.email, this.token);
}
@Entity()
class Activity {
int id;
@Unique()
String uuid;
String filename;
String category;
String info;
Activity(this.id, this.uuid, this.filename, this.category, this.info);
}
@Entity()
class Config {
@Id()
int id = 0;
bool saveLocally;
Config(this.id, this.saveLocally);
}

@ -0,0 +1,156 @@
import 'dart:convert';
import 'dart:io';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/objectbox.g.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:smartfit_app_mobile/modele/local_db/model.dart' as db;
import 'package:smartfit_app_mobile/modele/local_db/db_impl.dart';
class ObjectBox implements DbImpl {
late final Store store;
late final Box userBox;
late final Box activityBox;
late final Box configBox;
late final Directory applicationDocumentDir;
ObjectBox._create(this.store);
ObjectBox();
@override
Future<ObjectBox> create() async {
final docsDir = await getApplicationDocumentsDirectory();
final store = await openStore(directory: p.join(docsDir.path, "database"));
return ObjectBox._create(store);
}
@override
Future<void> init() async {
applicationDocumentDir = await getApplicationDocumentsDirectory();
userBox = store.box<db.User>();
activityBox = store.box<db.Activity>();
configBox = store.box<db.Config>();
}
// ===== USER =====
@override
bool hasUser() {
return !userBox.isEmpty();
}
@override
User getUser() {
db.User userRes = userBox.get(1);
return User.create(userRes.username, userRes.email, userRes.token);
}
@override
void setUserMail(String email) {
db.User user = userBox.get(1);
user.email = email;
userBox.put(user);
}
@override
void setUserName(String username) {
db.User user = userBox.get(1);
user.username = username;
userBox.put(user);
}
@override
void setUserToken(String token) {
db.User user = userBox.get(1);
user.token = token;
userBox.put(user);
}
@override
void deleteUser() {
userBox.removeAll();
}
@override
void addUser(String username, String email, String token) {
userBox.put(db.User(0, username, email, token));
}
// ===== Activity =====
@override
void addActivity(String uuid, String filename, String category, String info) {
db.Activity act =
db.Activity(0, uuid, filename, category, jsonEncode(info));
try {
activityBox.put(act);
} on ObjectBoxException {
print("Activity already exists");
} catch (e) {
print("Unknown exception");
}
}
// TODO: try catch
@override
void removeActivity(String uuid) {
final Query query = activityBox.query(Activity_.uuid.equals(uuid)).build();
final db.Activity act = query.findFirst();
activityBox.remove(act.id);
}
@override
String getActivityFilenameByUuid(String uuid) {
final Query query = activityBox.query(Activity_.uuid.equals(uuid)).build();
final db.Activity act = query.findFirst();
return act.filename;
}
@override
void removeAllActivities() {
activityBox.removeAll();
}
// ===== FIT Files =====
@override
List<ActivityOfUser> getAllActivities() {
List<dynamic> activityDBList = activityBox.getAll();
List<ActivityOfUser> userActivityList = List.empty(growable: true);
for (db.Activity act in activityDBList) {
ActivityInfo actInfo = ActivityInfo.fromJson(jsonDecode(act.info));
userActivityList
.add(ActivityOfUser(actInfo, act.category, act.uuid, act.filename));
}
return userActivityList;
}
// ===== Config =====
@override
void initConfig() {
db.Config config = db.Config(0, true);
configBox.put(config);
}
@override
void setSaveLocally(bool saveLocally) {
db.Config config = configBox.get(1);
config.saveLocally = saveLocally;
configBox.put(config);
stdout.write("(Config) setSaveLocally: $saveLocally\n");
}
@override
bool getSaveLocally() {
db.Config config = configBox.get(1);
stdout.write("(Config) getSaveLocally: ${config.saveLocally}\n");
return config.saveLocally;
}
}

@ -0,0 +1,89 @@
import 'dart:convert';
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/activity_saver.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:tuple/tuple.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'dart:io';
import 'dart:typed_data';
import 'package:smartfit_app_mobile/main.dart';
class RequestLocal implements IDataStrategy {
@override
Future<Tuple2> getInfoUser(String token) async {
final User user = localDB.getUser();
Map<String, String> json = {"email": user.email, "username": user.username};
return Tuple2(true, jsonEncode(json));
}
// need to save file on request_api.upload() beforehand.
@override
Future<Tuple2> getFile(String token, String fileUuid) async {
ActivitySaver actSaver = await ActivitySaver.create();
Uint8List fileBytes = actSaver.getActivity(fileUuid);
return Tuple2(true, fileBytes);
}
@override
Future<Tuple2> getFiles(String token) async {
final List<ActivityOfUser> activities = localDB.getAllActivities();
List<Map<String, dynamic>> jsonList = List.empty(growable: true);
for (ActivityOfUser act in activities) {
Map<String, dynamic> json = {
"uuid": act.fileUuid,
"filename": act.nameFile,
"category": act.category,
"info": act.activityInfo
};
jsonList.add(json);
}
return Tuple2(true, jsonEncode(activities));
}
@override
Future<Tuple2<bool, String>> modifAttribut(
String token, String nameAttribut, String newValue) async {
return const Tuple2(false, "not implemented");
}
@override
Future<Tuple2<bool, String>> postUser(
String email, String hash, String username) async {
return const Tuple2(false, "not implemented");
}
@override
Future<Tuple2<bool, String>> deleteUser(String token) async {
return const Tuple2(false, "not implemented");
}
@override
Future<Tuple2<bool, String>> connexion(String email, String hash) async {
return const Tuple2(false, "not implemented");
}
@override
Future<Tuple2<bool, String>> uploadFile(String token, File file) async {
return const Tuple2(false, "not implemented");
}
@override
Future<Tuple2<bool, String>> uploadFileByte(
String token,
Uint8List contentFile,
String nameFile,
String category,
DateTime date,
ActivityInfo activityInfo) async {
return const Tuple2(false, "not implemented");
}
@override
Future<bool> deleteFile(String token, String fileUuid) async {
throw Exception("Not Implemented");
}
}

@ -9,6 +9,10 @@ class User extends ChangeNotifier {
List<ActivityOfUser> listActivity = List.empty(growable: true); List<ActivityOfUser> listActivity = List.empty(growable: true);
ManagerSelectedActivity managerSelectedActivity = ManagerSelectedActivity(); ManagerSelectedActivity managerSelectedActivity = ManagerSelectedActivity();
User();
User.create(String username, String email, String token);
void addActivity(ActivityOfUser activity) { void addActivity(ActivityOfUser activity) {
listActivity.add(activity); listActivity.add(activity);
notifyListeners(); notifyListeners();

@ -1,3 +1,8 @@
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
import 'package:smartfit_app_mobile/modele/activity_saver.dart';
import 'package:smartfit_app_mobile/modele/helper.dart';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
@ -6,21 +11,21 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/activity.dart'; import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart'; import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart'; import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
class ListActivityUtile { class ListActivityUtile {
final IDataStrategy _strategy = RequestApi(); final ApiWrapper api = ApiWrapper();
final ManagerFile _managerFile = ManagerFile(); final ManagerFile _managerFile = ManagerFile();
Future<Tuple2<bool, String>> getContentActivity( Future<Tuple2<bool, String>> getContentActivity(BuildContext context,
BuildContext context, ActivityOfUser activityOfUser) async { ActivityOfUser activityOfUser, InfoMessage infoManager) async {
Tuple2 result = await _strategy.getFile( Tuple2 result = await api.getFile(
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
activityOfUser.fileUuid); activityOfUser.fileUuid,
infoManager);
if (result.item1 == false) { if (result.item1 == false) {
return Tuple2(result.item1, result.item2); return Tuple2(result.item1, result.item2);
} }
@ -28,6 +33,17 @@ class ListActivityUtile {
activityOfUser.contentActivity = activityOfUser.contentActivity =
List.from(_managerFile.convertByteIntoCSV(result.item2)); List.from(_managerFile.convertByteIntoCSV(result.item2));
// TODO: Not sure this line as an utility
// localDB.saveActivityFile(activityOfUser.contentActivity);
// TODO: Check if file exists, right now it overwrites each time
// TODO: Make ActivitySaver member of the class
if (!Helper.isPlatformWeb() && localDB.getSaveLocally()) {
ActivitySaver actSaver = await ActivitySaver.create();
actSaver.saveActivity(result.item2,
localDB.getActivityFilenameByUuid(activityOfUser.fileUuid));
}
if (!Provider.of<User>(context, listen: false) if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity .managerSelectedActivity
.addSelectedActivity(activityOfUser)) { .addSelectedActivity(activityOfUser)) {
@ -37,15 +53,15 @@ class ListActivityUtile {
} }
Future<Tuple2<bool, String>> getFiles( Future<Tuple2<bool, String>> getFiles(
String token, BuildContext context) async { String token, BuildContext context, InfoMessage infoManager) async {
bool notZero = false; bool notZero = false;
Tuple2 result = await _strategy Tuple2 result = await api.getFiles(
.getFiles(Provider.of<User>(context, listen: false).token); Provider.of<User>(context, listen: false).token, infoManager);
if (result.item1 == false) { if (result.item1 == false) {
return Tuple2(result.item1, result.item2); return Tuple2(result.item1, result.item2);
} }
for (Map<String, dynamic> element in result.item2) { for (var element in result.item2) {
if (!notZero) { if (!notZero) {
Provider.of<User>(context, listen: false).listActivity.clear(); Provider.of<User>(context, listen: false).listActivity.clear();
notZero = true; notZero = true;
@ -56,75 +72,76 @@ class ListActivityUtile {
element["category"].toString(), element["category"].toString(),
element["uuid"].toString(), element["uuid"].toString(),
element["filename"].toString())); element["filename"].toString()));
// Save to local db
if (!kIsWeb)
localDB.addActivity(element["uuid"], element["filename"],
element["category"], jsonEncode(element["info"]));
} }
return const Tuple2(true, "Yeah"); return const Tuple2(true, "Yeah");
} }
Future<Tuple2<bool, String>> _addFile( Future<Tuple2<bool, String>> addFile(Uint8List bytes, String filename,
Uint8List bytes, String filename, String token) async { String token, InfoMessage infoManager) async {
// -- Transormer le fit en CSV // -- Transormer le fit en CSV
Tuple4<bool, List<List<String>>, ActivityInfo, String> resultData = Tuple4<bool, List<List<String>>, ActivityInfo, String> resultData =
_managerFile.convertBytesFitFileIntoCSVListAndGetInfo(bytes); _managerFile.convertBytesFitFileIntoCSVListAndGetInfo(bytes);
String csvString = const ListToCsvConverter().convert(resultData.item2); String csvString = const ListToCsvConverter().convert(resultData.item2);
Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString)); Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString));
// --- Save Local
// --- Api Tuple2<bool, String> result = await api.uploadFileByte(
/*
ManagerFile x = ManagerFile();
await File("${await x.localPath}\\test.csv").writeAsString(csvString);
print("${await x.localPath}\\test.csv");*/
Tuple2<bool, String> result = await _strategy.uploadFileByte(
token, token,
byteCSV, byteCSV,
filename, filename,
resultData.item4, resultData.item4, // category
resultData.item3.startTime, resultData.item3.startTime, // activityInfo
resultData.item3); resultData.item3,
// resultData.item4 == category infoManager);
// resultData.item3 == ActivityInfo
if (result.item1 == false) { if (result.item1 == false) {
return Tuple2(false, result.item2); return Tuple2(false, result.item2);
} }
return const Tuple2(true, "Yeah");
}
Future<bool> deleteFileOnBDD(String token, String fileUuid) async { // Save on local storage if plateform not browser
Tuple2<bool, String> result = await _strategy.deleteFile(token, fileUuid); if (!Helper.isPlatformWeb() && localDB.getSaveLocally()) {
if (!result.item1) { ActivitySaver actSaver = await ActivitySaver.create();
return false; actSaver.saveActivity(byteCSV, filename);
} }
return true;
return const Tuple2(true, "Yeah");
} }
// --- Ne marche pas sous window !! Jsp linux (mettre en format mobile) -- // // --- Ne marche pas sous windows !! Jsp linux (mettre en format mobile) -- //
void addFileWeb(Uint8List? bytes, String token, String filename, Future<void> addFileWeb(Uint8List? bytes, String token, String filename,
BuildContext context) async { BuildContext context, InfoMessage infoManager) async {
if (bytes == null) { if (bytes == null) {
return; return;
} }
Tuple2<bool, String> resultAdd = await _addFile(bytes, filename, token); Tuple2<bool, String> resultAdd =
await addFile(bytes, filename, token, infoManager);
if (!resultAdd.item1) { if (!resultAdd.item1) {
//print("Message error"); //print("Message error");
return; return;
} }
Tuple2<bool, String> resultGet = await getFiles(token, context); Tuple2<bool, String> resultGet =
await getFiles(token, context, infoManager);
if (!resultGet.item1) { if (!resultGet.item1) {
//print("Message error"); //print("Message error");
return; return;
} }
} }
Future<void> addFileMobile( Future<void> addFileMobile(String path, String token, String filename,
String path, String token, String filename, BuildContext context) async { BuildContext context, InfoMessage infoManager) async {
Tuple2<bool, String> resultAdd = Tuple2<bool, String> resultAdd = await addFile(
await _addFile(await File(path).readAsBytes(), filename, token); await File(path).readAsBytes(), filename, token, infoManager);
if (!resultAdd.item1) { if (!resultAdd.item1) {
//print("Message error"); //print("Message error");
return; return;
} }
Tuple2<bool, String> resultGet = await getFiles(token, context); // TODO: What is that ?
Tuple2<bool, String> resultGet =
await getFiles(token, context, infoManager);
if (!resultGet.item1) { if (!resultGet.item1) {
//print("Message error"); //print("Message error");
return; return;

@ -1,10 +0,0 @@
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
class ProfileUtil {
final IDataStrategy _dataStrategy = RequestApi();
void modifyDataUser(String token, String attribut, String newUsername) {
_dataStrategy.modifAttribut(token, attribut, newUsername);
}
}

@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/container/list/list_activity_widget.dart'; import 'package:smartfit_app_mobile/common_widget/container/list/list_activity_widget.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart'; import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart';
class MobileListActivity extends StatefulWidget { class MobileListActivity extends StatefulWidget {
@ -15,6 +16,7 @@ class MobileListActivity extends StatefulWidget {
class _MobileListActivity extends State<MobileListActivity> { class _MobileListActivity extends State<MobileListActivity> {
final ListActivityUtile _utile = ListActivityUtile(); final ListActivityUtile _utile = ListActivityUtile();
final InfoMessage infoManager = InfoMessage();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -27,7 +29,7 @@ class _MobileListActivity extends State<MobileListActivity> {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15), padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
Row( Row(
@ -41,9 +43,13 @@ class _MobileListActivity extends State<MobileListActivity> {
fontWeight: FontWeight.w700), fontWeight: FontWeight.w700),
), ),
TextButton( TextButton(
onPressed: () => _utile.getFiles( onPressed: () async {
Provider.of<User>(context, listen: false).token, await _utile.getFiles(
context), Provider.of<User>(context, listen: false).token,
context,
infoManager);
setState(() {});
},
child: Text("Get activity", child: Text("Get activity",
style: TextStyle( style: TextStyle(
color: TColor.gray, color: TColor.gray,
@ -54,16 +60,18 @@ class _MobileListActivity extends State<MobileListActivity> {
FilePickerResult? result = FilePickerResult? result =
await FilePicker.platform.pickFiles(); await FilePicker.platform.pickFiles();
if (result != null && result.files.isNotEmpty) { if (result != null && result.files.isNotEmpty) {
// ignore: use_build_context_synchronously await _utile.addFileMobile(
_utile.addFileMobile(
result.files.single.path!, result.files.single.path!,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
result.files.first.name, result.files.first.name,
context); context,
infoManager);
setState(() {});
} else { } else {
// msg d'erreur // msg d'erreur
// User canceled the picker // User canceled the picker
} }
setState(() {});
}, },
child: Text( child: Text(
"Ajouter", "Ajouter",
@ -75,6 +83,10 @@ class _MobileListActivity extends State<MobileListActivity> {
) )
], ],
), ),
Visibility(
visible: infoManager.isVisible,
child: Text(infoManager.message,
style: TextStyle(color: infoManager.messageColor))),
Provider.of<User>(context, listen: true).listActivity.isEmpty Provider.of<User>(context, listen: true).listActivity.isEmpty
? Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

@ -1,12 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common_widget/container/list/list_activity_widget.dart'; import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart'; import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart';
import 'package:smartfit_app_mobile/common_widget/container/list/list_activity_widget.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
class WebListActivity extends StatefulWidget { class WebListActivity extends StatefulWidget {
@ -18,8 +16,8 @@ class WebListActivity extends StatefulWidget {
class _WebListActivityState extends State<WebListActivity> { class _WebListActivityState extends State<WebListActivity> {
FilePickerResult? result; FilePickerResult? result;
IDataStrategy strategy = RequestApi();
final ListActivityUtile _utile = ListActivityUtile(); final ListActivityUtile _utile = ListActivityUtile();
final InfoMessage infoManager = InfoMessage();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -31,7 +29,7 @@ class _WebListActivityState extends State<WebListActivity> {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15), padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
Row( Row(
@ -45,9 +43,13 @@ class _WebListActivityState extends State<WebListActivity> {
fontWeight: FontWeight.w700), fontWeight: FontWeight.w700),
), ),
TextButton( TextButton(
onPressed: () => _utile.getFiles( onPressed: () async {
Provider.of<User>(context, listen: false).token, await _utile.getFiles(
context), Provider.of<User>(context, listen: false).token,
context,
infoManager);
setState(() {});
},
child: Text("Get activity", child: Text("Get activity",
style: TextStyle( style: TextStyle(
color: TColor.gray, color: TColor.gray,
@ -58,31 +60,17 @@ class _WebListActivityState extends State<WebListActivity> {
FilePickerResult? result = FilePickerResult? result =
await FilePicker.platform.pickFiles(); await FilePicker.platform.pickFiles();
if (result != null && result.files.isNotEmpty) { if (result != null && result.files.isNotEmpty) {
_utile.addFileWeb( await _utile.addFileWeb(
result.files.first.bytes, result.files.first.bytes,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
result.files.first.name, result.files.first.name,
context); context,
infoManager);
} else { } else {
print("Picker"); print("Picker");
// msg d'erreur // msg d'erreur
// User canceled the picker // User canceled the picker
} }
/*
html.FileUploadInputElement uploadInput =
html.FileUploadInputElement();
uploadInput.click();
uploadInput.onChange.listen((e) {
final files = uploadInput.files;
if (files != null && files.isNotEmpty) {
addFileWeb(
files[0],
Provider.of<User>(context, listen: false)
.token); // Lecture du fichier sélectionné
}
});*/
}, },
child: Text( child: Text(
"Ajouter", "Ajouter",
@ -94,6 +82,10 @@ class _WebListActivityState extends State<WebListActivity> {
) )
], ],
), ),
Visibility(
visible: infoManager.isVisible,
child: Text(infoManager.message,
style: TextStyle(color: infoManager.messageColor))),
Provider.of<User>(context, listen: true).listActivity.isEmpty Provider.of<User>(context, listen: true).listActivity.isEmpty
? Column( ? Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

@ -1,10 +1,12 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/modele/utile/login_user.dart';
import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/button/round_button.dart'; import 'package:smartfit_app_mobile/common_widget/button/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/text_field/round_text_field.dart'; import 'package:smartfit_app_mobile/common_widget/text_field/round_text_field.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:smartfit_app_mobile/modele/utile/login_user.dart';
import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
class MobileLoginView extends StatefulWidget { class MobileLoginView extends StatefulWidget {
@ -164,7 +166,9 @@ class _MobileLoginView extends State<MobileLoginView> {
"Impossible de récupéré les données de l'utilisateur - {$infoUser.item2}"); "Impossible de récupéré les données de l'utilisateur - {$infoUser.item2}");
} else { } else {
util.fillUser(context, infoUser.item2, result.item2); util.fillUser(context, infoUser.item2, result.item2);
if (!kIsWeb)
localDB.addUser(infoUser.item2["username"],
infoUser.item2["email"], result.item2);
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(

@ -228,59 +228,6 @@ class _MobileSignUpView extends State<MobileSignUpView> {
SizedBox( SizedBox(
height: media.width * 0.04, height: media.width * 0.04,
), ),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/google.png",
width: 20,
height: 20,
),
),
),
SizedBox(
width: media.width * 0.04,
),
GestureDetector(
onTap: () {},
child: Container(
width: 50,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: TColor.white,
border: Border.all(
width: 1,
color: TColor.gray.withOpacity(0.4),
),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(
"assets/img/suunto.png",
width: 35,
height: 35,
),
),
)
],
),
SizedBox(
height: media.width * 0.04,
),
TextButton( TextButton(
onPressed: () { onPressed: () {
Navigator.push( Navigator.push(

@ -1,10 +1,12 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:smartfit_app_mobile/modele/utile/login_user.dart';
import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/button/round_button.dart'; import 'package:smartfit_app_mobile/common_widget/button/round_button.dart';
import 'package:smartfit_app_mobile/common_widget/text_field/round_text_field.dart'; import 'package:smartfit_app_mobile/common_widget/text_field/round_text_field.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:smartfit_app_mobile/modele/utile/login_user.dart';
import 'package:smartfit_app_mobile/view/main_tab/main_tab_view.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
class WebLoginView extends StatefulWidget { class WebLoginView extends StatefulWidget {
@ -150,6 +152,7 @@ class _WebLoginView extends State<WebLoginView> {
RoundButton( RoundButton(
title: "Se connecter", title: "Se connecter",
onPressed: () async { onPressed: () async {
// TODO: utiliser la vrai validation
if (!emailValidate || !passwordValidate) { if (!emailValidate || !passwordValidate) {
_printMsgError("Les champs renseigné ne sont pas valide"); _printMsgError("Les champs renseigné ne sont pas valide");
return; return;
@ -168,6 +171,9 @@ class _WebLoginView extends State<WebLoginView> {
"Impossible de récupéré les données de l'utilisateur - {$infoUser.item2}"); "Impossible de récupéré les données de l'utilisateur - {$infoUser.item2}");
} else { } else {
util.fillUser(context, infoUser.item2, result.item2); util.fillUser(context, infoUser.item2, result.item2);
if (!kIsWeb)
localDB.addUser(infoUser.item2["username"],
infoUser.item2["email"], result.item2);
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(

@ -1,3 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/common_widget/container/profile/profile_switch.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common/colo_extension.dart';
@ -8,17 +10,20 @@ import 'package:smartfit_app_mobile/common_widget/container/profile/profile_othe
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
class ProfileViewAllPlatforme extends StatefulWidget { class ProfileViewAllPlatforme extends StatefulWidget {
const ProfileViewAllPlatforme(this.positive, this.accountArr, this.otherArr, final bool offlineSave;
{super.key});
final bool positive;
final List accountArr; final List accountArr;
final List otherArr; final List otherArr;
const ProfileViewAllPlatforme(
this.offlineSave, this.accountArr, this.otherArr,
{super.key});
@override @override
State<ProfileViewAllPlatforme> createState() => _ProfileViewAllPlatforme(); State<ProfileViewAllPlatforme> createState() => _ProfileViewAllPlatforme();
} }
class _ProfileViewAllPlatforme extends State<ProfileViewAllPlatforme> { class _ProfileViewAllPlatforme extends State<ProfileViewAllPlatforme> {
bool isNative = !kIsWeb;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String username = context.watch<User>().username; String username = context.watch<User>().username;
@ -54,6 +59,16 @@ class _ProfileViewAllPlatforme extends State<ProfileViewAllPlatforme> {
const SizedBox( const SizedBox(
height: 25, height: 25,
), ),
// TODO: Download/Delete (local) all users files on toggle ?
// TODO: Display size of download in Mo
Visibility(
visible: isNative,
child: const ProfileSwitch("Offline mode",
"Save your files locally", "local_save.png"),
),
const SizedBox(
height: 25,
),
ProfileOther(widget.otherArr) ProfileOther(widget.otherArr)
], ],
), ),

@ -1,3 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart'; import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
@ -110,7 +112,7 @@ class _MobileChangeEmailViewState extends State<MobileChangeEmailView> {
RoundButton( RoundButton(
title: "Confirmer", title: "Confirmer",
onPressed: () async { onPressed: () async {
bool res = await api.modifyUserInfo( bool res = await api.updateUserInfo(
'email', 'email',
controllerTextEmail.text, controllerTextEmail.text,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
@ -118,6 +120,8 @@ class _MobileChangeEmailViewState extends State<MobileChangeEmailView> {
if (res) { if (res) {
Provider.of<User>(context, listen: false).email = Provider.of<User>(context, listen: false).email =
controllerTextEmail.text; controllerTextEmail.text;
if (!kIsWeb)
localDB.setUserMail(controllerTextEmail.text);
} }
setState(() {}); setState(() {});
}), }),

@ -111,7 +111,7 @@ class _MobileChangePasswordViewState extends State<MobileChangePasswordView> {
if (res.item1) { if (res.item1) {
if (controllerNewPasswd.text == if (controllerNewPasswd.text ==
controllerNewPasswd2.text) { controllerNewPasswd2.text) {
await api.modifyUserInfo( await api.updateUserInfo(
'password', 'password',
sha256 sha256
.convert(utf8 .convert(utf8

@ -1,3 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart'; import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
@ -109,7 +111,7 @@ class _MobileChangeUsernameViewState extends State<MobileChangeUsernameView> {
RoundButton( RoundButton(
title: "Confirmer", title: "Confirmer",
onPressed: () async { onPressed: () async {
bool res = await api.modifyUserInfo( bool res = await api.updateUserInfo(
'username', 'username',
controllerTextUsername.text, controllerTextUsername.text,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
@ -117,6 +119,9 @@ class _MobileChangeUsernameViewState extends State<MobileChangeUsernameView> {
if (res) { if (res) {
Provider.of<User>(context, listen: false) Provider.of<User>(context, listen: false)
.username = controllerTextUsername.text; .username = controllerTextUsername.text;
if (!kIsWeb)
localDB
.setUserName(controllerTextUsername.text);
} }
setState(() {}); setState(() {});
}), }),

@ -1,3 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart'; import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
@ -108,7 +110,7 @@ class _WebChangeEmailViewState extends State<WebChangeEmailView> {
RoundButton( RoundButton(
title: "Confirmer", title: "Confirmer",
onPressed: () async { onPressed: () async {
bool res = await apiWrapper.modifyUserInfo( bool res = await apiWrapper.updateUserInfo(
'email', 'email',
controllerTextEmail.text, controllerTextEmail.text,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
@ -116,6 +118,8 @@ class _WebChangeEmailViewState extends State<WebChangeEmailView> {
if (res) { if (res) {
Provider.of<User>(context, listen: false).email = Provider.of<User>(context, listen: false).email =
controllerTextEmail.text; controllerTextEmail.text;
if (!kIsWeb)
localDB.setUserMail(controllerTextEmail.text);
} }
setState(() {}); setState(() {});
}), }),

@ -114,7 +114,7 @@ class _WebChangePasswordViewState extends State<WebChangePasswordView> {
if (res.item1) { if (res.item1) {
if (controllerNewPasswd.text == if (controllerNewPasswd.text ==
controllerNewPasswd2.text) { controllerNewPasswd2.text) {
await api.modifyUserInfo( await api.updateUserInfo(
'password', 'password',
sha256 sha256
.convert(utf8 .convert(utf8

@ -1,3 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/main.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -110,7 +112,7 @@ class _WebChangeUsernameViewState extends State<WebChangeUsernameView> {
RoundButton( RoundButton(
title: "Confirmer", title: "Confirmer",
onPressed: () async { onPressed: () async {
bool res = await api.modifyUserInfo( bool res = await api.updateUserInfo(
'username', 'username',
controllerTextUsername.text, controllerTextUsername.text,
Provider.of<User>(context, listen: false).token, Provider.of<User>(context, listen: false).token,
@ -118,6 +120,9 @@ class _WebChangeUsernameViewState extends State<WebChangeUsernameView> {
if (res) { if (res) {
Provider.of<User>(context, listen: false) Provider.of<User>(context, listen: false)
.username = controllerTextUsername.text; .username = controllerTextUsername.text;
if (!kIsWeb)
localDB
.setUserName(controllerTextUsername.text);
} }
setState(() {}); setState(() {});
}), }),

@ -56,6 +56,10 @@ dependencies:
tuple: ^2.0.2 tuple: ^2.0.2
crypto: ^3.0.3 crypto: ^3.0.3
responsive_builder: ^0.7.0 responsive_builder: ^0.7.0
universal_html: ^2.2.4
objectbox: ^2.3.1
objectbox_flutter_libs: any
path: ^1.8.3
flutter_map: ^5.0.0 flutter_map: ^5.0.0
latlong2: ^0.9.0 latlong2: ^0.9.0
units_converter: ^2.1.1 units_converter: ^2.1.1
@ -70,6 +74,8 @@ dev_dependencies:
# package. See that file for information about deactivating specific lint # package. See that file for information about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^2.0.0 flutter_lints: ^2.0.0
build_runner: ^2.4.7
objectbox_generator: any
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec

Loading…
Cancel
Save