From 398b9678a288797740946acc7721fa2c3ebf5234 Mon Sep 17 00:00:00 2001 From: bunju20 <85238126+bunju20@users.noreply.github.com> Date: Mon, 19 Feb 2024 01:56:10 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20print=20=ED=95=A8=EC=88=98=EB=93=A4?= =?UTF-8?q?=20=EC=A7=80=EC=9B=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/views/home/widget/study_chart.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/views/home/widget/study_chart.dart b/lib/views/home/widget/study_chart.dart index 7f9fef2..6fb5855 100644 --- a/lib/views/home/widget/study_chart.dart +++ b/lib/views/home/widget/study_chart.dart @@ -47,8 +47,6 @@ class ChartTitleWidgets { fontSize: 13, ); if (value == 0 || value == maxYValue) { - print(maxYValue); - print(value); return Text('${value.toInt()}', style: style, textAlign: TextAlign.left); } return Container(); From 8ab5daed30bb57f73a8db099a9084ed458e79c00 Mon Sep 17 00:00:00 2001 From: bunju20 <85238126+bunju20@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:51:16 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EB=AC=B8=EB=8B=A8=20=EA=B5=90?= =?UTF-8?q?=EC=A0=95=20=EB=B2=84=ED=8A=BC=EC=97=90=20=EB=8C=80=EB=B3=B8?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A7=90=ED=95=98=EA=B8=B0=20=EC=9E=87?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Podfile.lock | 4 +- lib/views/paragraph/analyze_screen.dart | 186 ++++++++++++++++++ lib/views/paragraph/create_script_screen.dart | 122 ++++++++++++ .../study/widget/study_main_body_widget.dart | 6 +- lib/views/word/word_screen.dart | 5 +- 5 files changed, 316 insertions(+), 7 deletions(-) create mode 100644 lib/views/paragraph/analyze_screen.dart create mode 100644 lib/views/paragraph/create_script_screen.dart diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8c7380d..969ba14 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -938,7 +938,7 @@ SPEC CHECKSUMS: FirebaseFirestore: 21be9ea244830f6cac15464550c2975c43f9dffc FirebaseFirestoreInternal: 7ac1e0c5b4e75aeb898dfe4b1d6d77abbac9eca3 FirebaseSharedSwift: 19b3f709993d6fa1d84941d41c01e3c4c11eab93 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4 flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef @@ -966,4 +966,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 0b2c97823421f8b156b8e4753a469ac167670df8 -COCOAPODS: 1.15.2 +COCOAPODS: 1.14.3 diff --git a/lib/views/paragraph/analyze_screen.dart b/lib/views/paragraph/analyze_screen.dart new file mode 100644 index 0000000..d53608a --- /dev/null +++ b/lib/views/paragraph/analyze_screen.dart @@ -0,0 +1,186 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; +import 'package:speech_to_text/speech_to_text.dart' as stt; +import 'package:permission_handler/permission_handler.dart'; +import 'package:earlips/viewModels/script/analyze_viewmodel.dart'; +import '../../utilities/app_routes.dart'; + + + +class AnalyzeScreen extends StatefulWidget { + @override + _AnalyzeScreenState createState() => _AnalyzeScreenState(); +} + +class _AnalyzeScreenState extends State { + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + child: Scaffold( + appBar: AppBar( + title: Text('발음 및 빠르기 분석'), + centerTitle: true, + ), + body: SingleChildScrollView( + child: Column( + children: [ + Container( + alignment: Alignment.center, + width: Get.width - 40, + height: Get.height * 0.2, + margin: EdgeInsets.all(20.0), + padding: EdgeInsets.all(10.0), // 내부 여백을 추가합니다. + decoration: BoxDecoration( + color: Colors.white, // 배경색을 지정합니다. + borderRadius: BorderRadius.circular(15.0), // 테두리 둥글기를 지정합니다. + border: Border.all(color: Colors.white), // 테두리 색상을 지정합니다. 필요에 따라 변경 가능합니다. + ), + child: _TopText(), + ), + Stack( + children: [ + Container( + alignment: Alignment.center, + width: Get.width - 40, + height: Get.height * 0.5, + margin: EdgeInsets.all(20.0), + padding: EdgeInsets.all(10.0), // 내부 여백을 추가합니다. + decoration: BoxDecoration( + color: Colors.white, // 배경색을 지정합니다. + borderRadius: BorderRadius.circular(15.0), // 테두리 둥글기를 지정합니다. + border: Border.all(color: Colors.white), // 테두리 색상을 지정합니다. 필요에 따라 변경 가능합니다. + ), + child: TextStylingWidget(), + ), + + ], + ), + ], + ), + ), + floatingActionButton: Container( + width: Get.width, + alignment: Alignment.bottomCenter, + + child: FloatingActionButton( + onPressed: () { + Get.toNamed(Routes.HOME); + }, + child: Icon(Icons.home), // 홈 아이콘 사용 + tooltip: '홈으로', // 롱 프레스 시 표시되는 텍스트 + ), + ), + ), + ); + } +} + +class TextStylingWidget extends StatelessWidget { + final AnalyzeViewModel model = Get.put(AnalyzeViewModel()); + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: RichText( + text: TextSpan( + children: _buildTextSpans(), + style: TextStyle(color: Colors.black, fontSize: 16), + ), + textAlign: TextAlign.start, + ), + ); + } + + List _buildTextSpans() { + List spans = []; + int globalWordIndex = 0; // 전체 단어에 대한 인덱스를 추적합니다. + + for (int i = 0; i < model.userSenten.length; i++) { + final List words = model.userSenten[i].split(' '); + List wordSpans = []; + + for (String word in words) { + final bool isWrongWord = model.wrongWordIndexes.contains(globalWordIndex); + wordSpans.add(TextSpan( + text: "$word ", + style: TextStyle( + color: isWrongWord ? Colors.red : Colors.black, + ), + )); + globalWordIndex++; // 각 단어를 처리할 때마다 전체 단어 인덱스를 증가시킵니다. + } + + spans.add(TextSpan( + children: wordSpans, + style: TextStyle( + decoration: model.wrongFastIndexes.contains(i) ? TextDecoration.underline : TextDecoration.none, + ), + )); + spans.add(TextSpan(text: "\n")); // 문장 사이에 줄바꿈 추가 + } + + return spans; + } + +} + +class _TopText extends StatelessWidget { + const _TopText({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // 발음이 틀린 글씨에 대한 설명 + RichText( + text: TextSpan( + style: TextStyle(fontSize: 16, color: Colors.black), + children: [ + TextSpan(text: '발음이 틀린 글씨는 빨간색으로 표시됩니다 ex)'), + // 예시에 적용할 스타일 + TextSpan( + text: '강아지는 ', + style: TextStyle(color: Colors.red), + ), + TextSpan( + text: '뛴다', + ), + ], + ), + ), + Padding( + padding: EdgeInsets.only(top: 20), + ), + // 문장의 빠르기에 대한 설명 + RichText( + text: TextSpan( + style: TextStyle(fontSize: 16, color: Colors.black), + children: [ + TextSpan(text: '문장의 빠르기가 빠르거나 느리면 밑줄이 표시됩니다. ex)'), + // 예시에 적용할 스타일 + TextSpan( + text: '강아지는 ', + style: TextStyle(decoration: TextDecoration.underline), + ), + TextSpan( + text: '뛴다', + style: TextStyle(decoration: TextDecoration.underline), + ), + ], + ), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/views/paragraph/create_script_screen.dart b/lib/views/paragraph/create_script_screen.dart new file mode 100644 index 0000000..ae0c745 --- /dev/null +++ b/lib/views/paragraph/create_script_screen.dart @@ -0,0 +1,122 @@ +import 'package:earlips/utilities/style/color_styles.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:earlips/viewModels/script/create_script_viewmodel.dart'; +import 'package:get/get.dart'; + +class CreateScriptPage extends StatelessWidget { + const CreateScriptPage({super.key}); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (_) => CreateScriptViewModel(), + child: Consumer( + builder: (context, model, child) => Scaffold( + appBar: AppBar( + title: const Text('문단교정'), + centerTitle: true, + actions: [ + TextButton( + onPressed: model.complete, + child: const Text( + '완료', + style: TextStyle( + color: Colors.black, + fontSize: 20, + ), + ), + ), + ], + ), + body: Stack( + // Stack 위젯을 사용하여 Positioned를 올바르게 배치합니다. + children: [ + Column( + // 기존의 Column 구조를 Stack 내에 배치합니다. + children: [ + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.all(10.0), + child: TextField( + controller: model.writedTextController, + expands: true, + maxLines: null, + decoration: InputDecoration( + hintText: '대본을 입력하세요...', + fillColor: Colors.white, + filled: true, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(15.0), + borderSide: BorderSide.none, + ), + ), + textAlignVertical: TextAlignVertical.top, + ), + ), + ), + Expanded( + flex: 1, + child: Padding( + padding: const EdgeInsets.fromLTRB(25, 20, 25, 100), + child: Container( + padding: const EdgeInsets.all(20.0), + width: Get.width * 0.8, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(15.0), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 1, + blurRadius: 6, + offset: const Offset(0, 3), + ), + ], + ), + child: SingleChildScrollView( + child: Text( + model.voicedTextController.text, + style: const TextStyle(fontSize: 16), + ), + ), + ), + ), + ), + ], + ), + Positioned( + // Positioned 위젯으로 사용자 정의 FloatingActionButton을 배치합니다. + bottom: 20, + left: 0, + right: 0, + child: Align( + alignment: Alignment.bottomCenter, + child: Ink( + decoration: BoxDecoration( + color: model.isRecording ? Colors.red : Colors.blue, + borderRadius: BorderRadius.circular(40), + ), + child: InkWell( + borderRadius: BorderRadius.circular(40), + onTap: model.toggleRecording, + child: Padding( + padding: const EdgeInsets.all(20), + child: Icon( + model.isRecording ? Icons.stop : Icons.mic, + size: 30, + color: Colors.white, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/views/study/widget/study_main_body_widget.dart b/lib/views/study/widget/study_main_body_widget.dart index d0e8c7a..bdb3d10 100644 --- a/lib/views/study/widget/study_main_body_widget.dart +++ b/lib/views/study/widget/study_main_body_widget.dart @@ -3,6 +3,7 @@ import 'package:earlips/views/study/widget/study_card_widget.dart'; import 'package:earlips/views/word/word_screen.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:earlips/views/paragraph/create_script_screen.dart'; class StudyNainBodyWidget extends StatelessWidget { const StudyNainBodyWidget({super.key}); @@ -69,10 +70,7 @@ class StudyNainBodyWidget extends StatelessWidget { subtitle: "대본 입력 및 발음 테스트", imagePath: "assets/images/study/4.png", onTap: () { - Get.to(() => const WordScreen( - title: "문단 교정", - type: 3, - )); + Get.to(() => CreateScriptPage()); }, imgSize: 85, ), diff --git a/lib/views/word/word_screen.dart b/lib/views/word/word_screen.dart index f3f9c59..b2ad2ac 100644 --- a/lib/views/word/word_screen.dart +++ b/lib/views/word/word_screen.dart @@ -5,6 +5,7 @@ import 'package:earlips/views/word/widget/word_list_widget.dart'; import 'package:earlips/views/word/widget/word_youtube_widget.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:earlips/views/paragraph/create_script_screen.dart'; class WordScreen extends StatelessWidget { final String title; @@ -80,7 +81,9 @@ class WordScreen extends StatelessWidget { child: YoutubeWordPlayer(), ); } else { - return Container(); + return Container( + child: CreateScriptPage(), + ); } }, ), From a1a791655b1000bc2b4e6c3619869300a3af5bc0 Mon Sep 17 00:00:00 2001 From: bunju20 <85238126+bunju20@users.noreply.github.com> Date: Mon, 19 Feb 2024 04:12:45 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix=20:=20=EB=8C=80=EB=B3=B8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/views/script/learning_session_screen.dart | 76 ++++++++++++++----- 1 file changed, 56 insertions(+), 20 deletions(-) diff --git a/lib/views/script/learning_session_screen.dart b/lib/views/script/learning_session_screen.dart index 8d2a93e..0dad5a1 100644 --- a/lib/views/script/learning_session_screen.dart +++ b/lib/views/script/learning_session_screen.dart @@ -46,31 +46,38 @@ class LearningSessionScreen extends StatelessWidget { color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [ - // 그림자 설정 BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 1, + color: Colors.grey.withOpacity(0.15), + spreadRadius: 0.1, blurRadius: 10, - offset: Offset(0, 2), + offset: const Offset(0, 2), ), ], ), - child: ListTile( - contentPadding: const EdgeInsets.all(20), - title: Text( - session.title, - style: const TextStyle( - fontSize: 24.0, - fontWeight: FontWeight.bold, - ), - ), - subtitle: Padding( - padding: const EdgeInsets.only(top: 10.0), - child: Text(DateFormat('yyyy/MM/dd').format(session.createdDate)), + child: Container( + alignment: Alignment.centerLeft, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SmallCard(name: DateFormat('yyyy/MM/dd').format(session.createdDate)), + ListTile( + contentPadding: const EdgeInsets.only(left: 20, right: 20, bottom: 30), + title: Container( + alignment: Alignment.center, + child: Text( + session.title, + style: const TextStyle( + fontSize: 24.0, + fontWeight: FontWeight.bold, + ), + ), + ), + onTap: () { + // Todo: 세부 대본 학습 페이지로 이동하도록 구현 + }, + ), + ], ), - onTap: () { - // Todo: 세부 대본 학습 페이지로 이동하도록 구현 - }, ), ); }, @@ -82,4 +89,33 @@ class LearningSessionScreen extends StatelessWidget { ), ); } -} \ No newline at end of file +} + + +class _SmallCard extends StatelessWidget { + final String name; + + const _SmallCard({super.key, required this.name}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(left: 10.0, top: 10.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4.0), + color: const Color(0xFF1FA9DC), + ), + alignment: Alignment.center, + width: Get.height * 0.1, + height: 24, + child: Text( + name, + style: const TextStyle( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + ); + } +}