diff --git a/STML/README.md b/STML/README.md index a498a0fe..3aa705b0 100644 --- a/STML/README.md +++ b/STML/README.md @@ -1 +1,21 @@ -STML Application for Spring 2025 Teams C & D \ No newline at end of file +Short Term Memory Loss (STML) Application for Spring 2025 Teams C & D + +Application Name: MemoryMinder + +Team C +Zachary Kombet +Dhivya Mani +Negussie Mekonnen +Sandrine Mukendi +Babawale Olatunji +Quentin Rawls +Samrawit Yimenu + +Team D - MemoryCare +Selamawit Asfha +Alexandra George +Ashanti Holt +Carlson Igwacho +Dylan Pollock +Aadil Shekh +Nnenna Ukpong \ No newline at end of file diff --git a/STML/stml_application/README.md b/STML/stml_application/README.md index 5340b7ef..d740f945 100644 --- a/STML/stml_application/README.md +++ b/STML/stml_application/README.md @@ -1,23 +1,72 @@ -# stml_application +## MemoryMinder - STML for Team C/D Spring 2025 +# MemoryMinder: Short-Term Memory Loss ​(STML) Application -A new Flutter project. +What is STML? +- The inability to recall information or events that recently occurred​ -## Getting Started +Purpose of App​ +- To improve the quality of life for persons with STML. ​ + +- Assist caregivers (non-medical or geriatric assistant professionals) such as relatives, friends, etc., with helping individuals with STML​ + +Main users for the application:​ +- Caregiver ​ +- Care recipient ​ + +# Requirements for Spring 2025 +Req 12​ - IN CURRENT APP +The application shall provide a help button in the STML user mode. [Discuss feature set]​ + +Req 20 (Nice to Have​) - NOT FUNCTIONING AS EXPECTED IN CURRENT APP +The application shall have a default language option of English and support additional multi language options. Note: minimum additional language – Spanish. ​ + +Req 29 ​- IN CURRENT APP +The application will provide a “Return me Home” function that enables the Admin/Caregiver the ability to “set” the home geo-location for the STML user in the STML user profile. In the STML user mode, the “Return me Home” function will provide option for walking or driving instructions from current STML user location to the STML home geo-location. The intent of this requirement it to provide the STML user with a very simple method to get directions home if they have become disoriented during a walk or local drive. The feature should also notify the Admin/Caregiver of the current location of the STML user. ​ + +Look into ESRI geo-nav app. Make call to server ​ + +Req 30​ - IN CURRENT APP +The application will integrate with wearables – FitBit and Applewatch to share STML user health data with their admin/caregiver.​ + +Req 31​ - IN CURRENT APP +The application will alert the Admin/Caregiver and warn the STML user when sensitive PII information is identified in transcribed notes, such as, Potential triggers include: “My Social Security Number is,” “My Bank Account Number is,” “My Medicare number is,” “My credit card number is” Note: the development team needs to research and identify specific words or phrases that may indicate potential for the STML user to be victim of entitlement fraud activity. ​ + +Req 32 ​(Nice to Have)​ - IN CURRENT APP +The application will utilize AI to assess STML user transcribed notes of potential scams to alert the Admin/Caregiver Note: the development team needs to research and identify specific words or phrases that may indicate potential for the STML user to be victim of scam activity. ​ + +Tech support scams ​ +Criminals pose as tech support representatives and offer to fix computer issues. They may gain remote access to the victim's device and sensitive information. Potential STML user triggers: “What’s wrong with my iPad or computer””What do you need me to do?””How much does it cost?” ​ + +Grandparent scams ​ +Criminals pose as a relative, usually a grandchild, and claim to be in financial need.”What do you need me to do?””How much do you need me to send?” ​ + +Government impersonation scams ​ +Criminals pose as government employees and threaten to arrest or prosecute victims unless they provide funds. “What did I do wrong?” ”What do I need to pay?” ​ + +Sweepstakes/lottery scams ​ +Criminals claim to work for charitable organizations or that the victim has won a lottery or sweepstakes. They may ask the victim to pay a fee to collect the winnings. ”What do I need to pay?””How much do I need to send?” ​ -This project is a starting point for a Flutter application. +Req 33 ​(Nice to Have)​ - IN CURRENT APP +Google “Resources for dementia caregivers.” Integrate with admin/caregiver and STML user (as applicable) functionality to enable customization by location to as many of these resources and services as possible. ​ -A few resources to get you started if this is your first Flutter project: +Req 34 (Nice to Have)​ - NOT IN CURRENT APP +The application shall have the ability to connect to any existing camera devices and be able to send camera data to caregiver; privacy settings ​ -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) +NOTE: Current code base stems from Fall 23 – CogniOpen​ -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. -------------------------------------------- -Dementia Resources Feature Requirements -------------------------------------------- +## Getting Started +Refer to Team C/D documentation for further insight. All available documentation is located here: +https://umgc-cappms.azurewebsites.net/previousprojects + +Spring 2025 Team C - Minder +Spring 2025 Team D - MemoryMinder + + +## To assist with running the app please do the following: +# ------------------------------------------- +# Dementia Resources Feature Requirements +# ------------------------------------------- Add the following to .env file: #!!!!!!!!!!!!!!!!!!!! @@ -31,9 +80,9 @@ To get API key - https://developers.google.com/custom-search/v1/introduction#ide To set up search engine: https://programmablesearchengine.google.com/about/ ------------------------------------------------------- -Fitbit Integration - iOS App Only For Now (03/23/2025) ------------------------------------------------------- +# ------------------------------------------------------ +# Fitbit Integration - iOS App Only For Now (03/23/2025) +# ------------------------------------------------------ 1. Create a Fitbit Developer Account here: https://dev.fitbit.com/ 2. Sign in and Agree to the Developer Terms of Service 3. Go to: https://dev.fitbit.com/apps and click "Register a new app" @@ -63,3 +112,36 @@ FITBIT_CLIENT_SECRET= 11. Click on the project Runner and select Runner under Targets, go to Info and scroll down to URL Types - Add this to URL Identifier: com.stml and this to URL Schemes: stmlapp 12. Close the Xcode project and you should be all setup! + + +# ------------------------------------------------------ +# RETURNMEHOME FUNCTIONALITY REQUIREMENTS +# ------------------------------------------------------ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +RETURNMEHOME FUNCTIONALITY REQUIREMENTS +Running the ReturnMeHome function requires the use of a proxy server to route API requests due to Cross Origin Resource Sharing headers + +If the user has node.js installed, they can run the following commands in the server directory from the CLI +#!!!!!!!!!!!!!!!!!!!! +npm init -y +npm install express request cors +#!!!!!!!!!!!!!!!!!!!! +From there, ensure the server.js file contains the code that lives inside this repo + +From the terminal within the server directory use the following command to run the server: +node server.js + +That server needs to be running to route requests properly to the google api endpoint + +# ------------------------------------------------------ +# Known Issues +# ------------------------------------------------------ +The Safety Zone of the Return Me Home feature only works on iOS as of 03/29/25 at 10:15 AM EST +https://github.com/umgc/spring2025/pull/286 + +The Language Localization feature was actively worked on but unable to be featured within the last presented demo for the Spring 2025 STML teams +https://github.com/umgc/spring2025/pull/284 + +Due to time and resources this requirement was omitted +Req 34 (Nice to Have)​ - NOT IN CURRENT APP +The application shall have the ability to connect to any existing camera devices and be able to send camera data to caregiver; privacy settings ​ \ No newline at end of file diff --git a/STML/stml_application/lib/main.dart b/STML/stml_application/lib/main.dart index dba6a656..2cc0cdf0 100644 --- a/STML/stml_application/lib/main.dart +++ b/STML/stml_application/lib/main.dart @@ -4,18 +4,18 @@ import 'package:flutter/material.dart'; import 'package:memoryminder/src/features/account_creation_and_login/presentation/eula_screen.dart'; import 'package:memoryminder/src/features/account_creation_and_login/presentation/welcome_screen.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/service/notification_service.dart'; +import 'package:memoryminder/src/features/caregiver_task_management/presentation/caregiver_task_screen.dart'; +import 'package:memoryminder/src/features/common/service/s3_connection.dart'; import 'package:memoryminder/src/utils/logger.dart'; import 'package:memoryminder/src/features/stml_user_dashboard/presentation/stml_user_dashboard.dart'; import 'package:memoryminder/src/features/account_creation_and_login/presentation/login_screen.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:memoryminder/src/camera_manager.dart'; import 'package:memoryminder/src/data_service.dart'; -import 'package:memoryminder/src/s3_connection.dart'; import 'package:memoryminder/src/utils/directory_manager.dart'; import 'package:memoryminder/src/utils/permission_manager.dart'; import 'package:memoryminder/src/features/account_creation_and_login/presentation/registration_screen.dart'; import 'package:firebase_core/firebase_core.dart'; -import 'package:memoryminder/features/caregiver_task_management/caregiver_task_screen.dart'; import 'package:memoryminder/src/features/wearable-integration/health_dashboard.dart'; import 'package:memoryminder/src/features/wearable-integration/fitbit_login.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -48,7 +48,7 @@ class MyApp extends StatelessWidget { initialRoute: '/loginScreen', // The initial screen when the application starts routes: { - '/welcomeScreen': (context) => WelcomeScreem(), + '/welcomeScreen': (context) => WelcomeScreen(), '/loginScreen': (context) => LoginScreen(), '/registrationScreen': (context) => RegistrationScreen(), '/eulaScreen': (context) => EulaScreen(), diff --git a/STML/stml_application/lib/screens/caregiver_task_screen.dart b/STML/stml_application/lib/screens/caregiver_task_screen.dart deleted file mode 100644 index 984769a4..00000000 --- a/STML/stml_application/lib/screens/caregiver_task_screen.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'package:flutter/material.dart'; -import '../models/task_model.dart'; -import '../services/task_service.dart'; - -class CaregiverTaskScreen extends StatefulWidget { - @override - _CaregiverTaskScreenState createState() => _CaregiverTaskScreenState(); -} - -class _CaregiverTaskScreenState extends State { - final TaskService _taskService = TaskService(); - final TextEditingController _taskController = TextEditingController(); - - @override - Widget build(BuildContext context) { - final tasks = _taskService.getTasks(); - - return Scaffold( - appBar: AppBar( - title: Text('Caregiver - Task Management'), - ), - body: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: TextField( - controller: _taskController, - decoration: InputDecoration( - labelText: 'Task Name', - suffixIcon: IconButton( - icon: Icon(Icons.add), - onPressed: () { - final task = Task( - id: DateTime.now().toString(), - taskName: _taskController.text, - assignedTo: 'STML User 1', - caregiverId: 'Caregiver 1', - dueDate: DateTime.now().add(Duration(days: 1)), - status: 'Pending', - notes: 'Sample task', - ); - _taskService.addTask(task); - setState(() {}); - _taskController.clear(); - }, - ), - ), - ), - ), - Expanded( - child: ListView.builder( - itemCount: tasks.length, - itemBuilder: (context, index) { - final task = tasks[index]; - return ListTile( - title: Text(task.taskName), - subtitle: Text('Due: ${task.dueDate} - Status: ${task.status}'), - trailing: IconButton( - icon: Icon(Icons.delete), - onPressed: () { - _taskService.deleteTask(task.id); - setState(() {}); - }, - ), - ); - }, - ), - ), - ], - ), - ); - } -} diff --git a/STML/stml_application/lib/src/aws_video_response.dart b/STML/stml_application/lib/src/aws_video_response.dart deleted file mode 100644 index 1a6183f3..00000000 --- a/STML/stml_application/lib/src/aws_video_response.dart +++ /dev/null @@ -1,62 +0,0 @@ -// Author: David Bright -// Date: 2023-10-10 -// Description: These classes are used to individually access the responses -// in the AWS Rekognition Object Label Response -// Last modified by: Zach Bowman -// Last modified on: 2023-11-02 - -import 'package:memoryminder/src/utils/file_manager.dart'; -import 'package:flutter/material.dart'; - -class AWSVideoResponse { - String name; - double confidence; - int timestamp; - ResponseBoundingBox boundingBox; - String referenceVideoFilePath; - String address; - String parents; - - Image exampleImage = Image.network( - "https://cdn.pixabay.com/photo/2014/06/03/19/38/road-sign-361514_1280.png"); - - AWSVideoResponse.overloaded( - this.name, - this.confidence, - this.timestamp, - this.boundingBox, - this.referenceVideoFilePath, - this.address, - this.parents); - - //pull thumbnail image from the local file - Future getImage() async { - return await FileManager.getThumbnail( - FileManager.mostRecentVideoPath, timestamp); - } - - //reset thumbnail image with a new thumbnail from updated timestamp - void setImage(int timeStampNew) async { - exampleImage = await FileManager.getThumbnail( - FileManager.mostRecentVideoPath, timeStampNew); - } -} - -//Bounding Box coordinates - in double percentage (i.e., 0.1 for left means 10% of the pixel width from the left side for the initial box coordinate) -class ResponseBoundingBox { - double left; - double top; - double width; - double height; - - ResponseBoundingBox( - {required this.left, - required this.top, - required this.width, - required this.height}); - - @override - String toString() { - return 'ResponseBoundingBox{left: $left, top: $top, width: $width, height: $height}'; - } -} diff --git a/STML/stml_application/lib/src/camera_manager.dart b/STML/stml_application/lib/src/camera_manager.dart index b4e183d1..1758a373 100644 --- a/STML/stml_application/lib/src/camera_manager.dart +++ b/STML/stml_application/lib/src/camera_manager.dart @@ -7,16 +7,16 @@ import 'dart:io'; import 'package:camera/camera.dart'; import 'package:memoryminder/src/data_service.dart'; -import 'package:memoryminder/src/database/model/video.dart'; +import 'package:memoryminder/src/features/common/model/video.dart'; import 'package:memoryminder/src/utils/directory_manager.dart'; import 'package:memoryminder/src/utils/file_manager.dart'; import 'package:memoryminder/src/utils/format_utils.dart'; import 'package:memoryminder/src/utils/logger.dart'; import 'package:memoryminder/src/utils/permission_manager.dart'; -import 'package:memoryminder/src/video_processor.dart'; import "package:flutter/material.dart"; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:memoryminder/src/video_processor.dart'; /// Camera manager class to handle camera functionality. class CameraManager { diff --git a/STML/stml_application/lib/src/custom_label_response.dart b/STML/stml_application/lib/src/custom_label_response.dart deleted file mode 100644 index 7a831c35..00000000 --- a/STML/stml_application/lib/src/custom_label_response.dart +++ /dev/null @@ -1,40 +0,0 @@ -// Author: David Bright -// Date: 2023-10-25 -// Description: These classes are used to individually access the responses -// in the AWS Rekognition Custom Label Response -// Last modified by: Ben Sutter -// Last modified on: 2023-11-03 - -import 'package:flutter/material.dart'; - -//class to work with the Custom Label Response from AWS Rekognition. -class CustomLabelResponse { - String name; - double confidence; - ResponseBoundingBox? boundingBox; - Image exampleImage = - const Image(image: AssetImage("assets/test_images/eyeglass-green.jpg")); - - CustomLabelResponse(this.name, this.confidence); - - CustomLabelResponse.overloaded(this.name, this.confidence, this.boundingBox); -} - -//class for the bounding box information in the Response object. -class ResponseBoundingBox { - double left; - double top; - double width; - double height; - - ResponseBoundingBox( - {required this.left, - required this.top, - required this.width, - required this.height}); - - @override - String toString() { - return 'ResponseBoundingBox{left: $left, top: $top, width: $width, height: $height}'; - } -} diff --git a/STML/stml_application/lib/src/data_service.dart b/STML/stml_application/lib/src/data_service.dart index c6464d61..ad85e83c 100644 --- a/STML/stml_application/lib/src/data_service.dart +++ b/STML/stml_application/lib/src/data_service.dart @@ -1,23 +1,18 @@ import 'dart:io'; -import 'package:memoryminder/src/aws_video_response.dart'; +import 'package:memoryminder/src/features/common/controller/photo_controller.dart'; +import 'package:memoryminder/src/features/common/controller/video_controller.dart'; +import 'package:memoryminder/src/features/common/model/media.dart'; +import 'package:memoryminder/src/features/common/model/photo.dart'; +import 'package:memoryminder/src/features/common/model/video.dart'; +import 'package:memoryminder/src/features/common/model/video_response.dart'; +import 'package:memoryminder/src/features/common/repository/photo_repository.dart'; +import 'package:memoryminder/src/features/common/repository/video_repository.dart'; +import 'package:memoryminder/src/features/common/repository/video_response_repository.dart'; import 'package:memoryminder/src/features/sensitive_information_detection/application/audio_controller.dart'; -import 'package:memoryminder/src/database/controller/photo_controller.dart'; -import 'package:memoryminder/src/database/controller/significant_object_controller.dart'; -import 'package:memoryminder/src/database/controller/video_controller.dart'; -import 'package:memoryminder/src/database/controller/video_response_controller.dart'; import 'package:memoryminder/src/features/sensitive_information_detection/domain/audio.dart'; -import 'package:memoryminder/src/database/model/media.dart'; -import 'package:memoryminder/src/database/model/photo.dart'; -import 'package:memoryminder/src/database/model/significant_object.dart'; -import 'package:memoryminder/src/database/model/video.dart'; import 'package:memoryminder/src/utils/format_utils.dart'; -import 'package:memoryminder/src/database/model/video_response.dart'; import 'package:memoryminder/src/features/sensitive_information_detection/data/audio_repository.dart'; -import 'package:memoryminder/src/database/repository/photo_repository.dart'; -import 'package:memoryminder/src/database/repository/significant_object_repository.dart'; -import 'package:memoryminder/src/database/repository/video_repository.dart'; -import 'package:memoryminder/src/database/repository/video_response_repository.dart'; import 'package:memoryminder/src/utils/logger.dart'; class DataService { @@ -28,7 +23,6 @@ class DataService { late List mediaList = []; late List responseList = []; - late List significantObjectList = []; bool hasBeenInitialized = false; Future initializeData() async { @@ -36,6 +30,7 @@ class DataService { } // Used to show local database and objects +// Used to show local database and objects Future loadMedia() async { final audios = await AudioRepository.instance.readAll(); final photos = await PhotoRepository.instance.readAll(); @@ -80,16 +75,7 @@ class DataService { FormatUtils.logBigMessage("VIDEO RESPONSES END"); } - significantObjectList = - await SignificantObjectRepository.instance.readAll(); - if (significantObjectList.isNotEmpty) { - FormatUtils.logBigMessage("SIGNIFICANT OBJECT START"); - for (var object in significantObjectList) { - print("Object # ${object.toJson()}"); - } - FormatUtils.logBigMessage("SIGNIFICANT OBJECT END"); - } FormatUtils.logBigMessage("LOCAL DATABASE OBJECTS END"); hasBeenInitialized = true; @@ -122,45 +108,7 @@ class DataService { // |---------------------- VIDEO RESPONSE OPERATIONS ------------------------| // |-------------------------------------------------------------------------| - Future addVideoResponses(List rekogResponses) async { - try { - for (AWSVideoResponse rekResponse in rekogResponses) { - final response = await VideoResponseController.addVideoResponse( - title: rekResponse.name, - referenceVideoFilePath: rekResponse.referenceVideoFilePath, - confidence: rekResponse.confidence, - left: rekResponse.boundingBox.left, - top: rekResponse.boundingBox.top, - width: rekResponse.boundingBox.width, - height: rekResponse.boundingBox.height, - timestamp: rekResponse.timestamp, - address: rekResponse.address, - parents: rekResponse.parents, - ); - if (response != null) {} - } - - await refreshResponses(); - //return response; - } catch (e) { - appLogger.severe('Data Service -- Error removing video response'); - //return null; - } - } - - Future removeVideoResponse(int id) async { - try { - final audio = await VideoResponseController.removeVideoResponse(id); - if (audio != null) { - await refreshResponses(); - } - return audio; - } catch (e) { - appLogger.severe('Data Service -- Error removing video response', e); - return null; - } - } // |-------------------------------------------------------------------------| // |--------------------------- AUDIO OPERATIONS ----------------------------| @@ -449,84 +397,9 @@ class DataService { } } - // |-------------------------------------------------------------------------| - // |-------------------- SIGNIFICANT OBJECT OPERATIONS ----------------------| - // |-------------------------------------------------------------------------| - Future addSignificantObject({ - String? objectLabel, - String? customLabel, - required int timestamp, - required double left, - required double top, - required double width, - required double height, - required File imageFile, - }) async { - try { - final significantObject = - await SignificantObjectController.addSignificantObject( - objectLabel: objectLabel, - customLabel: customLabel, - timestamp: timestamp, - left: left, - top: top, - width: width, - height: height, - imageFile: imageFile, - ); - if (significantObject != null) { - await refreshMedia(); - } - return significantObject; - } catch (e) { - appLogger.severe('Data Service -- Error adding significant object: $e'); - return null; - } - } - - Future updateSignificantObjectLabels({ - required int id, - String? objectLabel, - String? customLabel, - }) async { - try { - final significantObject = - await SignificantObjectController.updateSignificantObjectLabels( - id: id, - objectLabel: objectLabel, - customLabel: customLabel, - ); - - if (significantObject != null) { - await refreshMedia(); - } - - return significantObject; - } catch (e) { - appLogger.severe( - 'Data Service -- Error updating significant object labels: $e'); - return null; - } - } - - Future removeSignificantObject(int id) async { - try { - final significantObject = - await SignificantObjectController.removeSignificantObject(id); - - if (significantObject != null) { - await refreshMedia(); - } - - return significantObject; - } catch (e) { - appLogger.severe('Data Service -- Error removing significant object: $e'); - return null; - } - } // |-------------------------------------------------------------------------| // |--------------------------- OTHER OPERATIONS ----------------------------| diff --git a/STML/stml_application/lib/src/database/controller/significant_object_controller.dart b/STML/stml_application/lib/src/database/controller/significant_object_controller.dart deleted file mode 100644 index 0680c709..00000000 --- a/STML/stml_application/lib/src/database/controller/significant_object_controller.dart +++ /dev/null @@ -1,93 +0,0 @@ -import 'dart:io'; - -import 'package:memoryminder/src/database/model/significant_object.dart'; -import 'package:memoryminder/src/database/repository/significant_object_repository.dart'; -import 'package:memoryminder/src/utils/directory_manager.dart'; -import 'package:memoryminder/src/utils/file_manager.dart'; -import 'package:memoryminder/src/utils/logger.dart'; - -const String significantObjectType = 'significant_object'; - -class SignificantObjectController { - SignificantObjectController._(); - - static Future addSignificantObject({ - String? objectLabel, - String? customLabel, - required int timestamp, - required double left, - required double top, - required double width, - required double height, - required File imageFile, - }) async { - try { - String imageFileExtension = - FileManager().getFileExtensionFromFile(imageFile); - String imageFileName = FileManager().generateFileName( - significantObjectType, - DateTime.now(), - imageFileExtension, - ); - SignificantObject newObject = SignificantObject( - objectLabel: objectLabel, - customLabel: customLabel, - timestamp: timestamp, - imageFileName: imageFileName, - left: left, - top: top, - width: width, - height: height, - ); - SignificantObject createdObject = - await SignificantObjectRepository.instance.create(newObject); - await FileManager.addFileToFilesystem( - imageFile, - DirectoryManager.instance.significantObjectsDirectory.path, - imageFileName, - ); - return createdObject; - } catch (e) { - appLogger - .severe('SignificantObject Controller -- Error adding object: $e'); - return null; - } - } - - static Future updateSignificantObjectLabels({ - required int id, - String? objectLabel, - String? customLabel, - }) async { - try { - final existingObject = - await SignificantObjectRepository.instance.read(id); - final updatedObject = existingObject.copy( - objectLabel: objectLabel ?? existingObject.objectLabel, - customLabel: customLabel ?? existingObject.customLabel, - ); - await SignificantObjectRepository.instance.update(updatedObject); - return updatedObject; - } catch (e) { - appLogger.severe( - 'SignificantObject Controller -- Error updating object labels: $e'); - return null; - } - } - - static Future removeSignificantObject(int id) async { - try { - final existingObject = - await SignificantObjectRepository.instance.read(id); - await SignificantObjectRepository.instance.delete(id); - final imageFilePath = - '${DirectoryManager.instance.significantObjectsDirectory.path}/${existingObject.imageFileName}'; - await FileManager.removeFileFromFilesystem(imageFilePath); - return existingObject; - } catch (e) { - appLogger - .severe('SignificantObject Controller -- Error removing object: $e'); - return null; - } - } -} diff --git a/STML/stml_application/lib/src/database/model/significant_object.dart b/STML/stml_application/lib/src/database/model/significant_object.dart deleted file mode 100644 index 96ad5b3d..00000000 --- a/STML/stml_application/lib/src/database/model/significant_object.dart +++ /dev/null @@ -1,80 +0,0 @@ -import 'package:memoryminder/src/database/repository/significant_object_repository.dart'; - -class SignificantObject { - final int? id; - final String? objectLabel; - final String? customLabel; - final int timestamp; - final String imageFileName; - final double left; - final double top; - final double width; - final double height; - - SignificantObject({ - this.id, - this.objectLabel, - this.customLabel, - required this.timestamp, - required this.imageFileName, - required this.left, - required this.top, - required this.width, - required this.height, - }); - - SignificantObject copy({ - int? id, - String? objectLabel, - String? customLabel, - int? timestamp, - String? imageFileName, - double? left, - double? top, - double? width, - double? height, - }) => - SignificantObject( - id: id ?? this.id, - objectLabel: objectLabel ?? this.objectLabel, - customLabel: customLabel ?? this.customLabel, - timestamp: timestamp ?? this.timestamp, - imageFileName: imageFileName ?? this.imageFileName, - left: left ?? this.left, - top: top ?? this.top, - width: width ?? this.width, - height: height ?? this.height, - ); - - Map toJson() { - return { - SignificantObjectFields.id: id, - SignificantObjectFields.objectLabel: objectLabel, - SignificantObjectFields.customLabel: customLabel, - SignificantObjectFields.timestamp: timestamp, - SignificantObjectFields.imageFileName: imageFileName, - SignificantObjectFields.left: left, - SignificantObjectFields.top: top, - SignificantObjectFields.width: width, - SignificantObjectFields.height: height, - }; - } - - static SignificantObject fromJson(Map json) { - try { - return SignificantObject( - id: json[SignificantObjectFields.id] as int?, - objectLabel: json[SignificantObjectFields.objectLabel] as String?, - customLabel: json[SignificantObjectFields.customLabel] as String?, - timestamp: json[SignificantObjectFields.timestamp] as int, - imageFileName: json[SignificantObjectFields.imageFileName] as String, - left: json[SignificantObjectFields.left] as double, - top: json[SignificantObjectFields.top] as double, - width: json[SignificantObjectFields.width] as double, - height: json[SignificantObjectFields.height] as double, - ); - } catch (e) { - throw FormatException('Error parsing JSON for SignificantObject: $e'); - } - } -} diff --git a/STML/stml_application/lib/src/database/repository/significant_object_repository.dart b/STML/stml_application/lib/src/database/repository/significant_object_repository.dart deleted file mode 100644 index db7e7f0d..00000000 --- a/STML/stml_application/lib/src/database/repository/significant_object_repository.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'package:memoryminder/src/database/app_database.dart'; -import 'package:memoryminder/src/database/model/significant_object.dart'; - -const String tableSignificantObjects = 'significant_objects'; - -class SignificantObjectFields { - static final List values = [ - id, - objectLabel, - customLabel, - timestamp, - imageFileName, - left, - top, - width, - height, - ]; - - static const String id = '_id'; - static const String objectLabel = 'object_label'; - static const String customLabel = 'custom_label'; - static const String timestamp = 'timestamp'; - static const String imageFileName = 'image_file_name'; - static const String left = 'left'; - static const String top = 'top'; - static const String width = 'width'; - static const String height = 'height'; -} - -class SignificantObjectRepository { - static final SignificantObjectRepository instance = - SignificantObjectRepository._init(); - - SignificantObjectRepository._init(); - - Future create(SignificantObject object) async { - final db = await AppDatabase.instance.database; - - final id = await db.insert(tableSignificantObjects, object.toJson()); - - return object.copy(id: id); - } - - Future delete(int id) async { - final db = await AppDatabase.instance.database; - - return await db.delete( - tableSignificantObjects, - where: '${SignificantObjectFields.id} = ?', - whereArgs: [id], - ); - } - - Future read(int id) async { - final db = await AppDatabase.instance.database; - - final maps = await db.query( - tableSignificantObjects, - where: '${SignificantObjectFields.id} = ?', - whereArgs: [id], - ); - - if (maps.isNotEmpty) { - return SignificantObject.fromJson(maps.first); - } else { - throw Exception('ID $id not found'); - } - } - - Future> readAll() async { - final db = await AppDatabase.instance.database; - - const orderBy = '${SignificantObjectFields.id} ASC'; - final result = await db.query(tableSignificantObjects, orderBy: orderBy); - - return result.map((json) => SignificantObject.fromJson(json)).toList(); - } - - Future update(SignificantObject object) async { - final db = await AppDatabase.instance.database; - - return db.update( - tableSignificantObjects, - object.toJson(), - where: '${SignificantObjectFields.id} = ?', - whereArgs: [object.id], - ); - } -} diff --git a/STML/stml_application/lib/src/features/account_creation_and_login/presentation/login_screen.dart b/STML/stml_application/lib/src/features/account_creation_and_login/presentation/login_screen.dart index 5d5ba93f..108e9889 100644 --- a/STML/stml_application/lib/src/features/account_creation_and_login/presentation/login_screen.dart +++ b/STML/stml_application/lib/src/features/account_creation_and_login/presentation/login_screen.dart @@ -32,9 +32,9 @@ class _LoginScreenState extends State { ); if (didAuthenticate) { - Navigator.pushReplacement( + Navigator.pushReplacement( context, - MaterialPageRoute(builder: (context) => HomeScreen()), + MaterialPageRoute(builder: (context) => STMLUserDashboardScreen()), ); } else { ScaffoldMessenger.of(context).showSnackBar( @@ -56,10 +56,10 @@ class _LoginScreenState extends State { }); try { - await _auth.signInWithEmailAndPassword( + /* await _auth.signInWithEmailAndPassword( email: _emailController.text.trim(), password: _passwordController.text.trim(), - ); + );*/ Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => CaregiverDashboardScreen()), diff --git a/STML/stml_application/lib/src/features/account_creation_and_login/presentation/welcome_screen.dart b/STML/stml_application/lib/src/features/account_creation_and_login/presentation/welcome_screen.dart index e8bab85e..33d77d85 100644 --- a/STML/stml_application/lib/src/features/account_creation_and_login/presentation/welcome_screen.dart +++ b/STML/stml_application/lib/src/features/account_creation_and_login/presentation/welcome_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:memoryminder/src/features/account_creation_and_login/presentation/eula_screen.dart'; import 'package:memoryminder/src/features/account_creation_and_login/presentation/login_screen.dart'; -class WelcomeScreem extends StatelessWidget { +class WelcomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/app_bar.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/app_bar.dart index e997970b..53263ed1 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/app_bar.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/app_bar.dart @@ -1,7 +1,6 @@ -import 'dart:async'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; -import 'package:memoryminder/ui/profile_screen.dart'; +import 'package:memoryminder/src/features/account_creation_and_login/presentation/login_screen.dart'; class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { final String? title; @@ -64,32 +63,21 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { ], ), -// Widgets on the right side of the AppBar + // Widgets on the right side of the AppBar actions: [ -// First page icon to navigate back IconButton( icon: const Icon( - Icons.settings, + Icons.logout, color: Colors.white70, ), onPressed: () { Navigator.push( context, - MaterialPageRoute(builder: (context) => ProfileScreen()), + MaterialPageRoute(builder: (context) => LoginScreen()), ); }, ), -// First page icon to navigate back - /* IconButton( - icon: const Icon( - Icons.first_page, - color: Colors.black87, - ), - onPressed: () { - Navigator.pop(context); - }, - ),*/ ], ); } @@ -105,6 +93,4 @@ String _currentDate() { return formatter.format(now); } -// This centers the title -/////////////////////////// diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/care_recipient_profile.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/care_recipient_profile.dart index c9a4e730..413dfe4c 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/care_recipient_profile.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/care_recipient_profile.dart @@ -1,11 +1,12 @@ // ignore_for_file: avoid_print, prefer_const_constructors // Imported libraries and packages +import 'package:memoryminder/src/features/account_creation_and_login/presentation/login_screen.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/add_care_recipient.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/app_bar.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart'; -import 'package:memoryminder/src/features/dementia-resources/dementia_resources.dart'; -import 'package:memoryminder/ui/response_screen.dart'; +import 'package:memoryminder/src/features/caregiver_task_management/presentation/caregiver_task_screen.dart'; +import 'package:memoryminder/src/features/dementia-resources/presentation/dementia_resources.dart'; import 'package:memoryminder/src/utils/ui_utils.dart'; import 'package:flutter/material.dart'; @@ -95,7 +96,7 @@ class CareRecipientProfileScreenState extends State icon: Icon(Icons.task, size: iconSize, color: Color.fromARGB(255, 2, 63, 129)), text: 'Tasks', - screen: CaregiverDashboardScreen(), + screen: CaregiverTaskScreen(), keyName: "TaskButtonKey", ), _buildElevatedButton( @@ -103,7 +104,7 @@ class CareRecipientProfileScreenState extends State icon: Icon(Icons.maps_home_work, size: iconSize, color: Color.fromARGB(255, 2, 63, 129)), text: 'Location', - screen: ResponseScreen(), + screen: LoginScreen(), keyName: "LocationButtonKey", ), _buildElevatedButton( @@ -122,6 +123,15 @@ class CareRecipientProfileScreenState extends State screen: DementiaResourcesScreen(loc: careRecipientLocation), keyName: "DementiaResourcesButtonKey", ), + _buildElevatedButton( + context: context, + icon: Icon(Icons.language, + size: iconSize, color: Color.fromARGB(255, 2, 63, 129)), + text: 'Language Preferences', + screen: LoginScreen(), + keyName: "LanguagePreferencesButtonKey", + ), + ], ), ), diff --git a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart index 26949d01..60b9c60e 100644 --- a/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart +++ b/STML/stml_application/lib/src/features/caregiver-dashboard/presentation/caregiver-dashboard.dart @@ -10,10 +10,8 @@ import 'package:memoryminder/src/features/caregiver-dashboard/presentation/care_ import 'package:memoryminder/src/features/caregiver-dashboard/service/manage_care_recipient_service.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/service/notification_service.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/service/notification_stream_service.dart'; -import 'package:memoryminder/ui/profile_screen.dart'; import 'package:memoryminder/src/utils/ui_utils.dart'; import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; // Main HomeScreen widget which is a stateless widget. class CaregiverDashboardScreen extends StatefulWidget { diff --git a/STML/stml_application/lib/features/caregiver_task_management/caregiver_task_model.dart b/STML/stml_application/lib/src/features/caregiver_task_management/model/caregiver_task_model.dart similarity index 100% rename from STML/stml_application/lib/features/caregiver_task_management/caregiver_task_model.dart rename to STML/stml_application/lib/src/features/caregiver_task_management/model/caregiver_task_model.dart diff --git a/STML/stml_application/lib/models/task_model.dart b/STML/stml_application/lib/src/features/caregiver_task_management/model/task_model.dart similarity index 100% rename from STML/stml_application/lib/models/task_model.dart rename to STML/stml_application/lib/src/features/caregiver_task_management/model/task_model.dart diff --git a/STML/stml_application/lib/features/caregiver_task_management/caregiver_task_screen.dart b/STML/stml_application/lib/src/features/caregiver_task_management/presentation/caregiver_task_screen.dart similarity index 98% rename from STML/stml_application/lib/features/caregiver_task_management/caregiver_task_screen.dart rename to STML/stml_application/lib/src/features/caregiver_task_management/presentation/caregiver_task_screen.dart index d1d0d985..f78d0ed1 100644 --- a/STML/stml_application/lib/features/caregiver_task_management/caregiver_task_screen.dart +++ b/STML/stml_application/lib/src/features/caregiver_task_management/presentation/caregiver_task_screen.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:memoryminder/src/features/caregiver-dashboard/presentation/app_bar.dart'; import 'package:memoryminder/src/utils/ui_utils.dart'; -import 'caregiver_task_service.dart'; -import 'caregiver_task_model.dart'; +import '../service/caregiver_task_service.dart'; +import '../model/caregiver_task_model.dart'; class CaregiverTaskScreen extends StatefulWidget { @override diff --git a/STML/stml_application/lib/features/caregiver_task_management/caregiver_task_service.dart b/STML/stml_application/lib/src/features/caregiver_task_management/service/caregiver_task_service.dart similarity index 93% rename from STML/stml_application/lib/features/caregiver_task_management/caregiver_task_service.dart rename to STML/stml_application/lib/src/features/caregiver_task_management/service/caregiver_task_service.dart index 88b7683b..7e9fb2b5 100644 --- a/STML/stml_application/lib/features/caregiver_task_management/caregiver_task_service.dart +++ b/STML/stml_application/lib/src/features/caregiver_task_management/service/caregiver_task_service.dart @@ -1,5 +1,5 @@ import 'dart:collection'; -import 'caregiver_task_model.dart'; +import '../model/caregiver_task_model.dart'; class CaregiverTaskService { final List _tasks = []; diff --git a/STML/stml_application/lib/services/task_service.dart b/STML/stml_application/lib/src/features/caregiver_task_management/service/task_service.dart similarity index 93% rename from STML/stml_application/lib/services/task_service.dart rename to STML/stml_application/lib/src/features/caregiver_task_management/service/task_service.dart index 664a713e..3c39d714 100644 --- a/STML/stml_application/lib/services/task_service.dart +++ b/STML/stml_application/lib/src/features/caregiver_task_management/service/task_service.dart @@ -1,4 +1,4 @@ -import '../models/task_model.dart'; +import '../model/task_model.dart'; class TaskService { final List _tasks = []; diff --git a/STML/stml_application/lib/src/features/common/controller/audio_controller.dart b/STML/stml_application/lib/src/features/common/controller/audio_controller.dart new file mode 100644 index 00000000..7a9ca98e --- /dev/null +++ b/STML/stml_application/lib/src/features/common/controller/audio_controller.dart @@ -0,0 +1,168 @@ +import 'dart:io'; + +import 'package:memoryminder/src/address.dart'; +import 'package:memoryminder/src/features/common/model/media_type.dart'; +import 'package:memoryminder/src/features/common/repository/audio_repository.dart'; +import 'package:memoryminder/src/features/sensitive_information_detection/domain/audio.dart'; +import 'package:memoryminder/src/utils/constants.dart'; +import 'package:memoryminder/src/utils/directory_manager.dart'; +import 'package:memoryminder/src/utils/file_manager.dart'; + +class AudioController { + AudioController._(); + + static Future addSeedAudio({ + String? title, + String? description, + List? tags, + required File audioFile, + File? transcriptFile, + String? summary, + }) async { + try { + DateTime timestamp = DateTime.now(); + String physicalAddress = defaultAddress; + String audioFileExtension = + FileManager().getFileExtensionFromFile(audioFile); + String audioFileName = FileManager().generateFileName( + MediaType.audio.name, + timestamp, + audioFileExtension, + ); + int audioFileSize = FileManager.calculateFileSizeInBytes(audioFile); + String? transcriptFileName; + if (transcriptFile != null) { + String transcriptFileExtension = + FileManager().getFileExtensionFromFile(transcriptFile); + transcriptFileName = FileManager().generateFileName( + transcriptType, + timestamp, + transcriptFileExtension, + ); + await FileManager.addFileToFilesystem( + transcriptFile, + DirectoryManager.instance.transcriptsDirectory.path, + transcriptFileName, + ); + } + + Audio newAudio = Audio( + title: title, + description: description, + tags: tags, + timestamp: timestamp, + physicalAddress: physicalAddress, + audioFileName: audioFileName, + storageSize: audioFileSize, + isFavorited: false, + transcriptFileName: transcriptFileName, + summary: summary, + ); + + Audio createdAudio = await AudioRepository.instance.create(newAudio); + await FileManager.addFileToFilesystem( + audioFile, + DirectoryManager.instance.audiosDirectory.path, + audioFileName, + ); + return createdAudio; + } catch (e) { + print('Audio Controller -- Error adding audio: $e'); + return null; + } + } + + static Future addAudio({ + String? title, + String? description, + List? tags, + required File audioFile, + File? transcriptFile, + String? summary, + }) async { + try { + DateTime timestamp = DateTime.now(); + String physicalAddress = ""; + await Address.whereIAm().then((String address) { + physicalAddress = address; + }); + String audioFileName = FileManager.getFileName(audioFile.path); + int audioFileSize = FileManager.calculateFileSizeInBytes(audioFile); + String? transcriptFileName; + if (transcriptFile != null) { + transcriptFileName = FileManager.getFileName(transcriptFile.path); + } + + Audio newAudio = Audio( + title: title, + description: description, + tags: tags, + timestamp: timestamp, + physicalAddress: physicalAddress, + audioFileName: audioFileName, + storageSize: audioFileSize, + isFavorited: false, + transcriptFileName: transcriptFileName, + summary: summary, + ); + Audio createdAudio = await AudioRepository.instance.create(newAudio); + return createdAudio; + } catch (e) { + print('Audio Controller -- Error adding audio: $e'); + return null; + } + } + + static Future updateAudio({ + required int id, + String? title, + String? description, + bool? isFavorited, + List? tags, + File? transcriptFile, + String? summary, + }) async { + try { + final existingAudio = await AudioRepository.instance.read(id); + String? updatedTranscriptFileName; + if (transcriptFile != null) { + updatedTranscriptFileName = + FileManager.getFileName(transcriptFile.path); + } + + final updatedAudio = existingAudio.copy( + title: title ?? existingAudio.title, + description: description ?? existingAudio.description, + isFavorited: isFavorited ?? existingAudio.isFavorited, + tags: tags ?? existingAudio.tags, + transcriptFileName: updatedTranscriptFileName, + summary: summary ?? existingAudio.summary, + ); + + await AudioRepository.instance.update(updatedAudio); + return updatedAudio; + } catch (e) { + print('Audio Controller -- Error updating audio: $e'); + return null; + } + } + + static Future removeAudio(int id) async { + try { + final existingAudio = await AudioRepository.instance.read(id); + await AudioRepository.instance.delete(id); + final audioFilePath = + '${DirectoryManager.instance.audiosDirectory.path}/${existingAudio.audioFileName}'; + await FileManager.removeFileFromFilesystem(audioFilePath); + if (existingAudio.transcriptFileName != null) { + final transcriptFilePath = + '${DirectoryManager.instance.transcriptsDirectory.path}/${existingAudio.transcriptFileName}'; + await FileManager.removeFileFromFilesystem(transcriptFilePath); + } + return existingAudio; + } catch (e) { + print('Audio Controller -- Error removing audio: $e'); + return null; + } + } +} diff --git a/STML/stml_application/lib/src/database/controller/photo_controller.dart b/STML/stml_application/lib/src/features/common/controller/photo_controller.dart similarity index 86% rename from STML/stml_application/lib/src/database/controller/photo_controller.dart rename to STML/stml_application/lib/src/features/common/controller/photo_controller.dart index 08f2587d..5b75a618 100644 --- a/STML/stml_application/lib/src/database/controller/photo_controller.dart +++ b/STML/stml_application/lib/src/features/common/controller/photo_controller.dart @@ -1,13 +1,12 @@ import 'dart:io'; import 'package:memoryminder/src/address.dart'; -import 'package:memoryminder/src/database/model/media_type.dart'; -import 'package:memoryminder/src/database/model/photo.dart'; -import 'package:memoryminder/src/database/repository/photo_repository.dart'; +import 'package:memoryminder/src/features/common/model/media_type.dart'; +import 'package:memoryminder/src/features/common/model/photo.dart'; +import 'package:memoryminder/src/features/common/repository/photo_repository.dart'; import 'package:memoryminder/src/utils/constants.dart'; import 'package:memoryminder/src/utils/directory_manager.dart'; import 'package:memoryminder/src/utils/file_manager.dart'; -import 'package:memoryminder/src/utils/logger.dart'; class PhotoController { PhotoController._(); @@ -47,7 +46,7 @@ class PhotoController { ); return createdPhoto; } catch (e) { - appLogger.severe('Photo Controller -- Error adding photo: $e'); + print('Photo Controller -- Error adding photo: $e'); return null; } } @@ -80,7 +79,7 @@ class PhotoController { Photo createdPhoto = await PhotoRepository.instance.create(newPhoto); return createdPhoto; } catch (e) { - appLogger.severe('Photo Controller -- Error adding photo: $e'); + print('Photo Controller -- Error adding photo: $e'); return null; } } @@ -103,7 +102,7 @@ class PhotoController { await PhotoRepository.instance.update(updatedPhoto); return updatedPhoto; } catch (e) { - appLogger.severe('Photo Controller -- Error updating photo: $e'); + print('Photo Controller -- Error updating photo: $e'); return null; } } @@ -117,7 +116,7 @@ class PhotoController { await FileManager.removeFileFromFilesystem(photoFilePath); return existingPhoto; } catch (e) { - appLogger.severe('Photo Controller -- Error removing photo: $e'); + print('Photo Controller -- Error removing photo: $e'); return null; } } diff --git a/STML/stml_application/lib/src/database/controller/video_controller.dart b/STML/stml_application/lib/src/features/common/controller/video_controller.dart similarity index 90% rename from STML/stml_application/lib/src/database/controller/video_controller.dart rename to STML/stml_application/lib/src/features/common/controller/video_controller.dart index 98653f21..d0c59685 100644 --- a/STML/stml_application/lib/src/database/controller/video_controller.dart +++ b/STML/stml_application/lib/src/features/common/controller/video_controller.dart @@ -1,13 +1,13 @@ import 'dart:io'; + import 'package:memoryminder/src/address.dart'; -import 'package:memoryminder/src/database/model/media_type.dart'; -import 'package:memoryminder/src/database/model/video.dart'; -import 'package:memoryminder/src/database/repository/video_repository.dart'; +import 'package:memoryminder/src/features/common/model/media_type.dart'; +import 'package:memoryminder/src/features/common/model/video.dart'; +import 'package:memoryminder/src/features/common/repository/video_repository.dart'; import 'package:memoryminder/src/utils/constants.dart'; import 'package:memoryminder/src/utils/directory_manager.dart'; import 'package:memoryminder/src/utils/file_manager.dart'; -import 'package:memoryminder/src/utils/logger.dart'; class VideoController { VideoController._(); @@ -66,7 +66,7 @@ class VideoController { return createdVideo; } catch (e) { - appLogger.severe('Video Controller -- Error adding video: $e'); + print('Video Controller -- Error adding video: $e'); return null; } } @@ -109,7 +109,7 @@ class VideoController { Video createdVideo = await VideoRepository.instance.create(newVideo); return createdVideo; } catch (e) { - appLogger.severe('Video Controller -- Error adding video: $e'); + print('Video Controller -- Error adding video: $e'); return null; } } @@ -132,7 +132,7 @@ class VideoController { await VideoRepository.instance.update(updatedVideo); return updatedVideo; } catch (e) { - appLogger.severe('Video Controller -- Error updating video: $e'); + print('Video Controller -- Error updating video: $e'); return null; } } @@ -152,7 +152,7 @@ class VideoController { } return existingVideo; } catch (e) { - appLogger.severe('Video Controller -- Error removing video: $e'); + print('Video Controller -- Error removing video: $e'); return null; } } diff --git a/STML/stml_application/lib/src/database/controller/video_response_controller.dart b/STML/stml_application/lib/src/features/common/controller/video_response_controller.dart similarity index 85% rename from STML/stml_application/lib/src/database/controller/video_response_controller.dart rename to STML/stml_application/lib/src/features/common/controller/video_response_controller.dart index 19c9afcd..e37ccb0f 100644 --- a/STML/stml_application/lib/src/database/controller/video_response_controller.dart +++ b/STML/stml_application/lib/src/features/common/controller/video_response_controller.dart @@ -1,9 +1,8 @@ import 'package:memoryminder/src/address.dart'; -import 'package:memoryminder/src/database/model/video_response.dart'; -import 'package:memoryminder/src/database/repository/video_response_repository.dart'; +import 'package:memoryminder/src/features/common/model/video_response.dart'; +import 'package:memoryminder/src/features/common/repository/video_response_repository.dart'; import 'package:memoryminder/src/utils/directory_manager.dart'; import 'package:memoryminder/src/utils/file_manager.dart'; -import 'package:memoryminder/src/utils/logger.dart'; import 'package:path/path.dart' as path; const String videoResponseType = 'video_response'; @@ -47,8 +46,7 @@ class VideoResponseController { return createdResponse; } catch (e) { - appLogger - .severe('Video Response Controller -- Error adding response: $e'); + print('Video Response Controller -- Error adding response: $e'); return null; } } @@ -79,8 +77,7 @@ class VideoResponseController { await VideoResponseRepository.instance.update(updatedResponse); return updatedResponse; } catch (e) { - appLogger - .severe('Video Response Controller -- Error updating response: $e'); + print('Video Response Controller -- Error updating response: $e'); return null; } } @@ -94,8 +91,7 @@ class VideoResponseController { await FileManager.removeFileFromFilesystem(imageFilePath); return existingResponse; } catch (e) { - appLogger - .severe('Video Response Controller -- Error removing response: $e'); + print('Video Response Controller -- Error removing response: $e'); return null; } } diff --git a/STML/stml_application/lib/src/database/app_database.dart b/STML/stml_application/lib/src/features/common/database/app_database.dart similarity index 71% rename from STML/stml_application/lib/src/database/app_database.dart rename to STML/stml_application/lib/src/features/common/database/app_database.dart index 669da34f..1e1caa0e 100644 --- a/STML/stml_application/lib/src/database/app_database.dart +++ b/STML/stml_application/lib/src/features/common/database/app_database.dart @@ -1,15 +1,17 @@ -import 'package:memoryminder/src/database/app_seed_data.dart'; -import 'package:memoryminder/src/database/model/media.dart'; -import 'package:memoryminder/src/features/sensitive_information_detection/data/audio_repository.dart'; -import 'package:memoryminder/src/database/repository/photo_repository.dart'; -import 'package:memoryminder/src/database/repository/significant_object_repository.dart'; -import 'package:memoryminder/src/database/repository/video_repository.dart'; -import 'package:memoryminder/src/database/repository/video_response_repository.dart'; +import 'package:memoryminder/src/features/common/database/app_seed_data.dart'; +import 'package:memoryminder/src/features/common/model/PhotoFields.dart'; +import 'package:memoryminder/src/features/common/model/VideoFields.dart'; +import 'package:memoryminder/src/features/common/model/media.dart'; +import 'package:memoryminder/src/features/common/repository/audio_repository.dart'; +import 'package:memoryminder/src/features/common/repository/video_response_repository.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; class AppDatabase { static const tableLocations = 'locations'; + static const tableVideos = 'videos'; + static const tablePhotos = 'photos'; + static final AppDatabase instance = AppDatabase._init(); static Database? _database; @@ -54,8 +56,7 @@ class AppDatabase { ${mediaColumns.join(',\n')}, ${AudioFields.audioFileName} $textType, ${AudioFields.transcriptFileName} $textNullableType, - ${AudioFields.summary} $textNullableType, - ${AudioFields.s3Url} $textNullableType + ${AudioFields.summary} $textNullableType ) '''); @@ -101,19 +102,7 @@ class AppDatabase { ) '''); - await db.execute(''' - CREATE TABLE $tableSignificantObjects ( - ${SignificantObjectFields.id} $idType, - ${SignificantObjectFields.objectLabel} $textNullableType, - ${SignificantObjectFields.customLabel} $textNullableType, - ${SignificantObjectFields.timestamp} $integerType, - ${SignificantObjectFields.imageFileName} $textType, - ${SignificantObjectFields.left} $floatType, - ${SignificantObjectFields.top} $floatType, - ${SignificantObjectFields.width} $floatType, - ${SignificantObjectFields.height} $floatType - ) - '''); + final appSeedData = AppSeedData(); appSeedData.loadAppSeedData(); diff --git a/STML/stml_application/lib/src/database/app_seed_data.dart b/STML/stml_application/lib/src/features/common/database/app_seed_data.dart similarity index 90% rename from STML/stml_application/lib/src/database/app_seed_data.dart rename to STML/stml_application/lib/src/features/common/database/app_seed_data.dart index 2bc25a6f..11d71531 100644 --- a/STML/stml_application/lib/src/database/app_seed_data.dart +++ b/STML/stml_application/lib/src/features/common/database/app_seed_data.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:memoryminder/src/data_service.dart'; import 'package:memoryminder/src/utils/file_manager.dart'; -import 'package:memoryminder/src/utils/logger.dart'; class AppSeedData { void loadAppSeedData() async { @@ -27,7 +26,7 @@ class AppSeedData { summary: 'This is a nature recording of birds singing.'); FileManager.unloadAssetFile('bird.mp3'); } catch (e) { - appLogger.severe('Error loading seed data photo: $e'); + print('Error loading seed data photo: $e'); } } @@ -44,7 +43,7 @@ class AppSeedData { ); FileManager.unloadAssetFile('cat.png'); } catch (e) { - appLogger.severe('Error loading seed data photo: $e'); + print('Error loading seed data photo: $e'); } } @@ -66,7 +65,7 @@ class AppSeedData { FileManager.unloadAssetFile('dog.mp4'); FileManager.unloadAssetFile('dog.png'); } catch (e) { - appLogger.severe('Error loading seed data video: $e'); + print('Error loading seed data video: $e'); } } } diff --git a/STML/stml_application/lib/src/features/common/model/PhotoFields.dart b/STML/stml_application/lib/src/features/common/model/PhotoFields.dart new file mode 100644 index 00000000..1459fa33 --- /dev/null +++ b/STML/stml_application/lib/src/features/common/model/PhotoFields.dart @@ -0,0 +1,10 @@ +import 'package:memoryminder/src/features/common/model/media.dart'; + +class PhotoFields extends MediaFields { + static final List values = [ + ...MediaFields.values, + photoFileName, + ]; + + static const String photoFileName = 'photo_file_name'; +} \ No newline at end of file diff --git a/STML/stml_application/lib/src/features/common/model/VideoFields.dart b/STML/stml_application/lib/src/features/common/model/VideoFields.dart new file mode 100644 index 00000000..dbe8dea8 --- /dev/null +++ b/STML/stml_application/lib/src/features/common/model/VideoFields.dart @@ -0,0 +1,14 @@ +import 'package:memoryminder/src/features/common/model/media.dart'; + +class VideoFields extends MediaFields { + static final List values = [ + ...MediaFields.values, + videoFileName, + thumbnailFileName, + duration, + ]; + + static const String videoFileName = 'video_file_name'; + static const String thumbnailFileName = 'thumbnail_file_name'; + static const String duration = 'duration'; +} diff --git a/STML/stml_application/lib/src/database/model/location.dart b/STML/stml_application/lib/src/features/common/model/location.dart similarity index 100% rename from STML/stml_application/lib/src/database/model/location.dart rename to STML/stml_application/lib/src/features/common/model/location.dart diff --git a/STML/stml_application/lib/src/database/model/media.dart b/STML/stml_application/lib/src/features/common/model/media.dart similarity index 95% rename from STML/stml_application/lib/src/database/model/media.dart rename to STML/stml_application/lib/src/features/common/model/media.dart index ea1c4f6d..c2ca48b8 100644 --- a/STML/stml_application/lib/src/database/model/media.dart +++ b/STML/stml_application/lib/src/features/common/model/media.dart @@ -1,4 +1,5 @@ -import 'package:memoryminder/src/database/model/media_type.dart'; + +import 'package:memoryminder/src/features/common/model/media_type.dart'; abstract class MediaFields { static final List values = [ diff --git a/STML/stml_application/lib/src/database/model/media_type.dart b/STML/stml_application/lib/src/features/common/model/media_type.dart similarity index 100% rename from STML/stml_application/lib/src/database/model/media_type.dart rename to STML/stml_application/lib/src/features/common/model/media_type.dart diff --git a/STML/stml_application/lib/src/database/model/photo.dart b/STML/stml_application/lib/src/features/common/model/photo.dart similarity index 92% rename from STML/stml_application/lib/src/database/model/photo.dart rename to STML/stml_application/lib/src/features/common/model/photo.dart index 4f49592e..676434c7 100644 --- a/STML/stml_application/lib/src/database/model/photo.dart +++ b/STML/stml_application/lib/src/features/common/model/photo.dart @@ -1,10 +1,11 @@ -import 'package:memoryminder/src/database/model/media.dart'; -import 'package:memoryminder/src/database/model/media_type.dart'; -import 'package:memoryminder/src/database/repository/photo_repository.dart'; +import 'package:memoryminder/src/features/common/model/media.dart'; +import 'package:memoryminder/src/features/common/model/media_type.dart'; +import 'package:memoryminder/src/features/common/model/PhotoFields.dart'; import 'package:memoryminder/src/utils/directory_manager.dart'; import 'package:memoryminder/src/utils/file_manager.dart'; import 'package:flutter/widgets.dart'; + class Photo extends Media { final String photoFileName; diff --git a/STML/stml_application/lib/src/database/model/video.dart b/STML/stml_application/lib/src/features/common/model/video.dart similarity index 93% rename from STML/stml_application/lib/src/database/model/video.dart rename to STML/stml_application/lib/src/features/common/model/video.dart index 023931f6..86b098e2 100644 --- a/STML/stml_application/lib/src/database/model/video.dart +++ b/STML/stml_application/lib/src/features/common/model/video.dart @@ -1,9 +1,10 @@ -import 'package:memoryminder/src/database/model/media.dart'; -import 'package:memoryminder/src/database/model/media_type.dart'; -import 'package:memoryminder/src/database/repository/video_repository.dart'; +import 'package:memoryminder/src/features/common/model/media.dart'; +import 'package:memoryminder/src/features/common/model/media_type.dart'; import 'package:memoryminder/src/utils/directory_manager.dart'; import 'package:memoryminder/src/utils/file_manager.dart'; import 'package:flutter/widgets.dart'; +import 'package:memoryminder/src/features/common/model/VideoFields.dart'; + class Video extends Media { final String videoFileName; diff --git a/STML/stml_application/lib/src/database/model/video_response.dart b/STML/stml_application/lib/src/features/common/model/video_response.dart similarity index 100% rename from STML/stml_application/lib/src/database/model/video_response.dart rename to STML/stml_application/lib/src/features/common/model/video_response.dart diff --git a/STML/stml_application/lib/ui/profile_screen.dart b/STML/stml_application/lib/src/features/common/presentation/profile_screen.dart similarity index 100% rename from STML/stml_application/lib/ui/profile_screen.dart rename to STML/stml_application/lib/src/features/common/presentation/profile_screen.dart diff --git a/STML/stml_application/lib/src/features/common/repository/audio_repository.dart b/STML/stml_application/lib/src/features/common/repository/audio_repository.dart new file mode 100644 index 00000000..fe44fc3f --- /dev/null +++ b/STML/stml_application/lib/src/features/common/repository/audio_repository.dart @@ -0,0 +1,80 @@ + +import 'package:memoryminder/src/features/common/database/app_database.dart'; +import 'package:memoryminder/src/features/common/model/media.dart'; +import 'package:memoryminder/src/features/sensitive_information_detection/domain/audio.dart'; + +const String tableAudios = 'audios'; +const String transcriptType = 'transcript'; + +class AudioFields extends MediaFields { + static final List values = [ + ...MediaFields.values, + audioFileName, + transcriptFileName, + summary, + ]; + + static const String audioFileName = 'audio_file_name'; + static const String transcriptFileName = 'transcript_file_name'; + static const String summary = 'summary'; +} + +class AudioRepository { + static final AudioRepository instance = AudioRepository._init(); + + AudioRepository._init(); + + Future