Skip to content

Commit

Permalink
Merge pull request #50 from seochan99/feature/translate
Browse files Browse the repository at this point in the history
✨ Feat : 다국어 및 리펙토링 적용
  • Loading branch information
bunju20 authored Feb 21, 2024
2 parents ae55e6a + 6544ef0 commit 1a067bb
Show file tree
Hide file tree
Showing 60 changed files with 1,112 additions and 875 deletions.
Binary file added assets/images/home/Chart-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/images/home/Chart_new.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
298 changes: 294 additions & 4 deletions lib/languages.dart

Large diffs are not rendered by default.

14 changes: 4 additions & 10 deletions lib/main_app.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:earlips/languages.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:get/get.dart';
import 'package:earlips/bindings/root_binding.dart';
Expand All @@ -21,15 +21,9 @@ class MainApp extends StatelessWidget {

return GetMaterialApp(
title: "earlips",
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('ko', 'KR'),
Locale('en', 'US'),
],
translations: Languages(),
locale: Get.deviceLocale,
fallbackLocale: const Locale('en', 'US'),
theme: ThemeData(
useMaterial3: true,
fontFamily: 'Pretendard',
Expand Down
8 changes: 4 additions & 4 deletions lib/services/auth/auth_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ class AuthService {
} catch (error) {
// 에러 발생시 에러 메시지 출력
Get.snackbar(
"구글 로그인 실패",
"구글 로그인에 실패했습니다. 다시 시도해주세요.",
'google_login_fail_title'.tr,
'google_login_fail_content'.tr,
snackPosition: SnackPosition.TOP,
);
}
Expand All @@ -100,8 +100,8 @@ class AuthService {
} catch (error) {
// 에러 발생시 에러 메시지 출력
Get.snackbar(
"회원 탈퇴 실패",
"회원 탈퇴에 실패했습니다. 다시 시도해주세요.",
'signout_fail_title'.tr,
'signout_fail_content'.tr,
snackPosition: SnackPosition.TOP,
);
}
Expand Down
1 change: 0 additions & 1 deletion lib/utilities/style/color_styles.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class ColorSystem {
static const Color white = Color(0xFFFFFFFF);
static const Color green = Color(0xFF63DC68);
static const Color green2 = Color(0xFFD5E9AA);

static const Color yellow = Color(0xFFFFC100);
static const Color red = Color(0xFFFB5D5D);
static const Color background = Color(0xFFF0F4F8);
Expand Down
12 changes: 7 additions & 5 deletions lib/utilities/validators/auth_validators.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import 'package:get/get_utils/src/extensions/internacionalization.dart';

class AuthValidators {
// Email Validator
static String? emailValidator(String? value) {
if (value == null || value.isEmpty) {
return '이메일 주소를 입력해주세요';
return 'email_address'.tr;
}
// Email 정규식
final RegExp emailRegex = RegExp(
r'^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$',
);

if (!emailRegex.hasMatch(value)) {
return '올바른 이메일 주소를 입력해주세요';
return 'email_address_input'.tr;
}
return null;
}
Expand All @@ -19,12 +21,12 @@ class AuthValidators {
// 대충.. 10자리 이상, 문자와 숫자가 섞여있어야 함
static String? passwordValidator(String? value) {
if (value == null || value.isEmpty) {
return '비밀번호를 입력해주세요';
return 'password_input'.tr;
} else if (value.length < 10) {
return '비밀번호는 10자리 이상이어야 합니다';
return 'password_input_2'.tr;
} else if (!RegExp(r'^(?=.*?[a-zA-Z])(?=.*?[0-9]).{10,}$')
.hasMatch(value)) {
return '비밀번호는 문자와 숫자가 섞여있어야 합니다';
return 'password_input_3'.tr;
}
return null;
}
Expand Down
16 changes: 4 additions & 12 deletions lib/viewModels/Paragraph/learning_session_screen_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -1,42 +1,34 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:get/get_state_manager/src/simple/get_controllers.dart';



class LearningSessionScreenViewModel extends GetxController {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;

final RxBool isLoading = false.obs; // 로딩 상태 관리
final RxList<Paragraph> paragraphs = <Paragraph>[].obs; // Paragraph 객체 리스트

// Firestore에서 paragraphs 컬렉션의 데이터를 가져오는 함수
Future<void> fetchParagraphs() async {
final uid = _auth.currentUser?.uid; // 사용자 UID 가져오기
try {
isLoading(true); // 로딩 시작
final QuerySnapshot paragraphSnapshot = await _firestore
.collection('paragraph') // 사용자의 paragraph 컬렉션에 접근
.limit(5) // 예제로 5개의 문서만 가져오기
.get();

final List<Paragraph> fetchedParagraphs = paragraphSnapshot.docs
.map((doc) {
final List<Paragraph> fetchedParagraphs =
paragraphSnapshot.docs.map((doc) {
// doc.data() 호출 결과를 Map<String, dynamic>으로 타입 캐스팅
final data = doc.data() as Map<String, dynamic>?;
// Null-safety를 고려하여, 필드에 접근하기 전에 null 체크
final title = data?['title'] as String? ?? ''; // title이 없으면 빈 문자열 할당
final text = data?['text'] as String? ?? ''; // text가 없으면 빈 문자열 할당
return Paragraph(title: title, text: text);
})
.toList();

}).toList();

paragraphs.value = fetchedParagraphs; // 상태 업데이트
} catch (e) {
print("Error fetching paragraphs: $e"); // 오류 처리
} catch (_) {
} finally {
isLoading(false); // 로딩 종료
}
Expand Down
7 changes: 5 additions & 2 deletions lib/viewModels/auth/email_login_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,11 @@ class EmailLoginViewModel extends GetxController {
// 로그인 성공시 홈화면으로 이동
Get.offAllNamed('/');
} on FirebaseAuthException catch (_) {
Get.snackbar('로그인 실패', "로그인에 실패했습니다. 다시 시도해주세요.",
snackPosition: SnackPosition.TOP);
Get.snackbar(
'login_fail_snackar_title'.tr,
'login_fail_snackar_message'.tr,
snackPosition: SnackPosition.TOP,
);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/viewModels/auth/email_signup_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ class EmailSignupViewModel extends GetxController {
Get.back();
} on FirebaseAuthException catch (_) {
Get.snackbar(
"회원가입 실패",
"회원가입에 실패했습니다. 다시 시도해주세요.",
"signup_fail_title".tr,
"signup_fail_content".tr,
snackPosition: SnackPosition.TOP,
);
}
Expand Down
2 changes: 0 additions & 2 deletions lib/viewModels/record/record_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,13 @@ class RecordViewModel extends GetxController {

final filePath =
'${directory.path}/${DateTime.now().millisecondsSinceEpoch}.aac';
print(filePath);
try {
await _audioRecorder.startRecorder(
toFile: filePath,
codec: Codec.aacADTS,
);

isRecording.value = true;
print('Recording started');
} catch (_) {}
}

Expand Down
7 changes: 0 additions & 7 deletions lib/viewModels/root/root_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:get/get_rx/src/rx_types/rx_types.dart';

import 'package:get/get_state_manager/src/simple/get_controllers.dart';
import 'package:earlips/utilities/app_routes.dart';


class RootViewModel extends GetxController {
late final RxInt _selectedIndex;

Expand All @@ -15,7 +10,6 @@ class RootViewModel extends GetxController {
void onInit() {
super.onInit();
_selectedIndex = 0.obs;

}

void changeIndex(int index) {
Expand All @@ -25,5 +19,4 @@ class RootViewModel extends GetxController {
void onTapBed() {
Get.toNamed(Routes.HOME);
}

}
10 changes: 3 additions & 7 deletions lib/viewModels/script/analyze_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:http/http.dart' as http;
import 'dart:convert'; // JSON 데이터를 다루기 위해 필요

class AnalyzeViewModel with ChangeNotifier {
List<String> userWord = [];
List<String> userSenten = [];
Expand All @@ -10,17 +8,15 @@ class AnalyzeViewModel with ChangeNotifier {

void updateData(Map<String, dynamic> data) {
userWord = List<String>.from(data['user_word'] as List<dynamic>? ?? []);
userSenten = List<String>.from(data['user_sentence'] as List<dynamic>? ?? []);
userSenten =
List<String>.from(data['user_sentence'] as List<dynamic>? ?? []);
wrongWordIndexes = List<int>.from(data['wrong'] as List<dynamic>? ?? []);
wrongFastIndexes = (data['speed'] as List<dynamic>? ?? []).map((e) {

if (e is double) {
return e;
} else if (e is int) {
return e.toDouble();
} else {
// 로그 출력 또는 오류 처리
print("Warning: Invalid type in 'speed' list, defaulting to 0.0");
return 0.0; // 기본값
}
}).toList();
Expand Down
53 changes: 15 additions & 38 deletions lib/viewModels/script/create_script_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ class CreateScriptViewModel extends ChangeNotifier {
bool get isLoggedIn => FirebaseAuth.instance.currentUser != null;
final FirebaseAuth _auth = FirebaseAuth.instance;



bool handDone = false;
TextEditingController writedTextController =
TextEditingController(); // 사용자 입력을 위한 컨트롤러
Expand Down Expand Up @@ -74,20 +72,16 @@ class CreateScriptViewModel extends ChangeNotifier {
final path = await _audioRecorder!.stopRecorder();
audioFilePath = path!;
_isRecording = false;
print('Recording stopped, file path: $path');
return path; // 녹음이 중지된 파일의 경로를 반환합니다.
} catch (e) {
print('Error stopping recorder: $e');
return null;
}
}

Future<void> sendTextAndAudio() async {

String url = '${dotenv.env['API_URL']!}/script';
String textToSend = writedTextController.text;
if (audioFilePath.isEmpty) {
print('Audio file is not available.');
return;
}

Expand All @@ -101,7 +95,6 @@ class CreateScriptViewModel extends ChangeNotifier {
if (response.statusCode == 200) {
final respStr = await response.stream.bytesToString();
final jsonResponse = json.decode(respStr);
print('Server response: $respStr');
if (jsonResponse != null) {
final analyzeViewModel = Get.find<AnalyzeViewModel>();

Expand All @@ -114,24 +107,14 @@ class CreateScriptViewModel extends ChangeNotifier {
'speed': jsonResponse['speed'],
});

Get.to(() => AnalyzeScreen()); // AnalyzeScreen으로 이동
} else {
print('Received null or invalid data from the server.');
}
} else {
print(
'Failed to send data and audio. Status code: ${response.statusCode}');
}
} catch (e) {
print(e.toString());
}
Get.to(() => const AnalyzeScreen()); // AnalyzeScreen으로 이동
} else {}
} else {}
} catch (_) {}
if (!isLoggedIn) {
print('User is not logged in.');
}else {
print('User is logged in.');
} else {
saveDataToFirestore();
}

}

void _handleStatus(String status) {
Expand Down Expand Up @@ -163,7 +146,6 @@ class CreateScriptViewModel extends ChangeNotifier {
Future<void> startListening() async {
bool available = await speechToText.initialize();
if (!available) {
print("The user has denied the use of speech recognition.");
return;
}
speechToText.listen(
Expand All @@ -184,18 +166,17 @@ class CreateScriptViewModel extends ChangeNotifier {
}

void complete() async {
print("완료버튼 눌렀습니다.");
await sendTextAndAudio(); // 비동기 호출로 수정
}

Future<void> saveDataToFirestore() async {
final uid = _auth.currentUser?.uid;
if (!isLoggedIn) {
print("User is not logged in.");
return;
}
final textToSend = writedTextController.text;
final title = textToSend.length > 5 ? textToSend.substring(0, 5) + '...' : textToSend;
final title =
textToSend.length > 5 ? '${textToSend.substring(0, 5)}...' : textToSend;
final dateFormat = Timestamp.now(); // 현재 시간을 Timestamp 형태로 저장

final documentReference = FirebaseFirestore.instance
Expand All @@ -204,18 +185,14 @@ class CreateScriptViewModel extends ChangeNotifier {
.collection('paragraph')
.doc(); // 새 문서 ID를 자동 생성

await documentReference.set({
'dateFormat': dateFormat,
'text': textToSend,
'title': title,
}).then((_) {
print("Data saved to Firestore successfully.");
print(dateFormat);
print(textToSend);
print(uid);
}).catchError((error) {
print("Failed to save data to Firestore: $error");
});
await documentReference
.set({
'dateFormat': dateFormat,
'text': textToSend,
'title': title,
})
.then((_) {})
.catchError((_) {});
}

@override
Expand Down
Loading

0 comments on commit 1a067bb

Please sign in to comment.