Skip to content

Commit

Permalink
✨feat!: implementation of all functionalities (#59)
Browse files Browse the repository at this point in the history
* ✨feat: implementation of all functionalities (#58)

* refactor: change types

* feat: datasources and repo using by Upload and checkFile (#39)

* feat: get and view files added (#41)

* feat: go to folder & view files in subfolder (#41)

* feat: upload in location state

* feat: views folders create in the file

* fix: error state location & refactor all states files - generate sync provider (#42)

* feat: added create new directory (#45)

* feat!: file download and notification download added (#46)

* feat: rename file added (#48) & create handler erros for download file (#49)

* feat: create controllers for file move (#50)

* feat: create states for file move/moving (#50)

* feat!: file move added (#50)

* feat: view file move in the files view (#50)

* feat: add controllers for (#51) - shareListWithWho & shareFile

* feat!: added share file (#52) & share list with who (#51) - refactoring

* 🎨feat: size file text added in list files

* 💄feat(style): list view files change style

Delete card styles
Change route storage for share

* 💄feat: change UI for stateCrossAxis

* ✨feat: controllers for share list added

* ✨feat!: view share list with me added

* 🎨refactor: Improve structure - format exports providers & mappers

* 🐛fix: no show error message when using share file

Only shown when a user needs to be confirmed

* ✨feat: controllers & models added for account password

* ✨feat!: account password change added (#40)

* 🥅feat(catchErrors): generate CustomsErros and showSnackbar for view errors

* ✨feat: controllers & models for unShareFile added

* ✨feat: unShareFileAdded (#56) & using (#54)

* ✨feat!: file delete added (#57) & using (#54)

* ♻️refactor: state for more vert turn off

#55 change name folders widgets

* 💄feat(style): update the UI buttons

* ♻️refactor(http): add network security & include messages (#49)
  • Loading branch information
SantiagoGaonaC authored Oct 24, 2023
1 parent 5d4a796 commit e74f6cc
Show file tree
Hide file tree
Showing 65 changed files with 2,902 additions and 258 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### 0.1.10 (2023-10-24)

### 0.1.9 (2023-10-16)

### 0.1.8 (2023-10-13)

### 0.1.7 (2023-10-13)
Expand Down
2 changes: 2 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ android {
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}

buildTypes {
Expand All @@ -65,5 +66,6 @@ flutter {
}

dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
8 changes: 8 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- For Images-->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEOS" /> <!-- For video-->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- For Audio-->
<application
android:label="login_mobile"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true"
android:networkSecurityConfig="@xml/network_security_config"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
Expand Down
Binary file modified android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions android/app/src/main/res/xml/network_security_config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">capyfile1.bucaramanga.upb.edu.co</domain>
</domain-config>
</network-security-config>
16 changes: 10 additions & 6 deletions lib/config/router/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:login_mobile/features/auth/auth.dart';
import 'package:login_mobile/features/auth/presentation/providers/auth_provider.dart';
import 'package:login_mobile/features/auth/presentation/screens/account_password.dart';
import 'package:login_mobile/features/drive/files_drive.dart';
import 'app_router_notifier.dart';

Expand Down Expand Up @@ -30,13 +31,17 @@ final goRouterProvider = Provider((ref) {

///* CapyDriveScreen Routes
GoRoute(
path: '/',
path: '/files',
builder: (context, state) => const CapyDriveScreen(),
),
GoRoute(
path: '/storage',
builder: (context, state) => const StorageScreen(),
path: '/share',
builder: (context, state) => const ShareScreen(),
),
GoRoute(
path: '/account/password',
builder: (context, state) => const AccountPasswordScreen(),
)
],
redirect: (context, state) {
final isGoingTo = state.matchedLocation;
Expand All @@ -58,12 +63,11 @@ final goRouterProvider = Provider((ref) {
if (isGoingTo == '/login' ||
isGoingTo == '/register' ||
isGoingTo == '/check-auth-status') {
return '/';
return '/files';
}
}

return null;
},

);
});
});
10 changes: 0 additions & 10 deletions lib/features/auth/domain/entities/folder.dart

This file was deleted.

14 changes: 1 addition & 13 deletions lib/features/auth/domain/entities/user.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
class User {
//final String uuid;
String? username;
//final int statusCode;
//final String? message;
final String token;

//TODO?: add required
User({
//required this.uuid,
required this.username,
//required this.statusCode,
//required this.message,
required this.token,
});
}
// id
// username
// isActive bool
// roles
// token
}
4 changes: 0 additions & 4 deletions lib/features/auth/infrastructure/mappers/user_mapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ class UserMapper {

static User userJsonToEntity(Map<String, dynamic> json) {
return User(
//TODO: setup new user model with new fields returned from Proxy...
//uuid: json['uuid'],
username: json['username'],
//statusCode: json['statusCode'],
//message: json['message'],
token: json['token']
);
}
Expand Down
6 changes: 1 addition & 5 deletions lib/features/auth/presentation/providers/auth_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,21 @@ class AuthNotifier extends StateNotifier<AuthState> {
_verifyToken(biometricToken);
return;
}

//Después intentamos con el token temporal
final tempToken =
await keyValueStorageService.getValue<String>('tempToken');

// Independientemente de si tempToken es nulo o no, ejecutamos el logout
// y ajustamos el estado.
// Ya que tempToken indica usuario temporal!
state = state.copyWith(hasBiometric: false);
logout();

// Luego, si tempToken no es nulo, puedes verificarlo o hacer
// cualquier lógica adicional si es necesario.
if (tempToken != null) {
return;
//_verifyToken(tempToken);
// [Lógica adicional aquí si tempToken existe, de momento no]
}

//Si llegamos hasta aquí, no hay token.
// [Posiblemente lógica adicional aquí si no hay token]
}
Expand Down Expand Up @@ -184,7 +181,6 @@ class AuthNotifier extends StateNotifier<AuthState> {
await keyValueStorageService.removeKey('username');
await keyValueStorageService.removeKey('tempToken');
}

state = state.copyWith(
user: null,
errorMessage: errorMessage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import 'package:login_mobile/features/auth/presentation/providers/auth_provider.
import 'package:login_mobile/features/shared/infrastructure/inputs/repeat_password.dart';
import 'package:login_mobile/features/shared/shared.dart';

final registerFormProvider =
StateNotifierProvider.autoDispose<RegisterFormNotifier, RegisterFormState>(
(ref) {
final registerUserCallback = ref.watch(authProvider.notifier).registerUser;
return RegisterFormNotifier(registerUserCallback: registerUserCallback);
});

class RegisterFormState {
final bool isPosting;
final bool isFormPosted;
Expand Down Expand Up @@ -73,17 +80,16 @@ class RegisterFormNotifier extends StateNotifier<RegisterFormState> {
}

onRepeatPasswordChanged(String value) {
if(value != state.password.value){
if (value != state.password.value) {
value = "no";
}
final newRepeatPassword = RepeatPassword.dirty(value);
state = state.copyWith(
repeatPassword: newRepeatPassword,
isValid: Formz.validate(
repeatPassword: newRepeatPassword,
isValid: Formz.validate(
[newRepeatPassword, state.username, state.password]));
}


onFormSubmitted() async {
_touchEveryField();
if (!state.isValid) {
Expand All @@ -96,10 +102,7 @@ class RegisterFormNotifier extends StateNotifier<RegisterFormState> {
state = state.copyWith(isPosting: false);
}



_touchEveryField() {

final username = Username.dirty(state.username.value);
final password = Password.dirty(state.password.value);
final repeatpassword = RepeatPassword.dirty(state.repeatPassword.value);
Expand All @@ -109,13 +112,5 @@ class RegisterFormNotifier extends StateNotifier<RegisterFormState> {
password: password,
repeatPassword: repeatpassword,
isValid: Formz.validate([username, password, repeatpassword]));

}
}

final registerFormProvider =
StateNotifierProvider.autoDispose<RegisterFormNotifier, RegisterFormState>(
(ref) {
final registerUserCallback = ref.watch(authProvider.notifier).registerUser;
return RegisterFormNotifier(registerUserCallback: registerUserCallback);
});
134 changes: 134 additions & 0 deletions lib/features/auth/presentation/providers/share_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:login_mobile/features/auth/infrastructure/infrastructure.dart';
import 'package:login_mobile/features/drive/domain/entities/file.dart';
import 'package:login_mobile/features/drive/domain/repositories/file_repository.dart';
import 'package:login_mobile/features/drive/presentation/providers/files_upload_repository_provider.dart';

final shareProvider = StateNotifierProvider<ShareNotifier, ShareState>((ref) {
final fileRepository = ref.watch(filesRepositoryProvider);
return ShareNotifier(fileRepository: fileRepository);
});

class ShareNotifier extends StateNotifier<ShareState> {
final FilesRepository fileRepository;

ShareNotifier({required this.fileRepository}) : super(ShareState.initial());

shareFile(String fileUUID, String otherUsername) async {
state = state.copyWith(isSharing: true);
try {
await fileRepository.shareFile(fileUUID, otherUsername);
state = state.copyWith(isSharing: false, isShared: true);
getShareListWithWho(fileUUID);
} on CustomError catch (e) {
state = state.copyWith(
isSharing: false, isShared: false, errorMessage: e.message);
} catch (e) {
state = state.copyWith(
isSharing: false,
isShared: false,
errorMessage: 'Invalid user or user not found');
}
}

shareListWithWho(String fileUUID) async {
state = state.copyWith(isLoading: true);
try {
final shareListWithWho = await fileRepository.shareListWithWho(fileUUID);
state = state.copyWith(isLoading: false, fileUUID: fileUUID);
return shareListWithWho;
} on CustomError catch (e) {
state = state.copyWith(
isLoading: false, errorMessage: e.message, fileUUID: fileUUID);
} catch (e) {
state = state.copyWith(
isLoading: false,
errorMessage: 'Error when using ShareListWithWho $e',
fileUUID: fileUUID);
}
}

Future<List<String>> getShareListWithWho(String fileUUID) async {
final response = await fileRepository.shareListWithWho(fileUUID);
final shareListWithWho = response.usernames;
state =
state.copyWith(shareListWithWho: shareListWithWho, errorMessage: '');
return shareListWithWho;
}

Future<bool> unShareFile(String fileUUID, String otherUsername) async {
try {
final response =
await fileRepository.unShareFile(fileUUID, otherUsername);
if (response) {
removeUserFromShareList(otherUsername);
state = state.copyWith(errorMessage: '');
return true;
} else {
state = state.copyWith(
errorMessage: 'Error when using unShareFile, response is false');
}
return false;
} on CustomError catch (e) {
state = state.copyWith(errorMessage: e.message);
return false;
} catch (e) {
state = state.copyWith(errorMessage: 'Error when using unShareFile $e');
return false;
}
}

void removeUserFromShareList(String username) {
final updatedList = List<String>.from(state.shareListWithWho);
updatedList.remove(username);
state = state.copyWith(shareListWithWho: updatedList);
}
}

class ShareState {
final bool isLoading;
final bool isSharing;
final bool isShared;
final String errorMessage;
final String? fileUUID;
final List<String> shareListWithWho;

ShareState({
this.isLoading = false,
this.isSharing = false,
this.isShared = false,
this.errorMessage = '',
this.fileUUID,
this.shareListWithWho = const [],
});

factory ShareState.initial() {
return ShareState(
isLoading: false,
isSharing: false,
isShared: false,
errorMessage: '',
fileUUID: null,
shareListWithWho: [],
);
}

ShareState copyWith({
bool? isLoading,
bool? isSharing,
bool? isShared,
String? errorMessage,
String? fileUUID,
List<String>? shareListWithWho,
List<File>? filesShareList,
}) {
return ShareState(
isLoading: isLoading ?? this.isLoading,
isSharing: isSharing ?? this.isSharing,
isShared: isShared ?? this.isShared,
errorMessage: errorMessage ?? this.errorMessage,
fileUUID: fileUUID ?? this.fileUUID,
shareListWithWho: shareListWithWho ?? this.shareListWithWho,
);
}
}
Loading

0 comments on commit e74f6cc

Please sign in to comment.