From 30a5513246b72452f0bdd7557fac4a9c9919ee9c Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Tue, 25 Jun 2024 22:24:37 +0900 Subject: [PATCH 01/20] =?UTF-8?q?feat:=20bmi=5Fcalculator=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 - dart_240529.md | 223 ------------------ dart_240530.md | 12 - .../bmi_calculator/lib/main/main_screen.dart | 120 ++++++++++ .../lib/result/result_screen.dart | 74 ++++++ 5 files changed, 194 insertions(+), 246 deletions(-) delete mode 100644 README.md delete mode 100644 dart_240529.md delete mode 100644 dart_240530.md create mode 100644 project/bmi_calculator/lib/main/main_screen.dart create mode 100644 project/bmi_calculator/lib/result/result_screen.dart diff --git a/README.md b/README.md deleted file mode 100644 index 84fcdbb..0000000 --- a/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# TIL - -Today I Learned - -오늘 학습한 내용을 정리하는 것 - - -## 샘플 -- https://github.com/namjunemy/TIL -- https://github.com/milooy/TIL -- https://github.com/YutoMizutani/til diff --git a/dart_240529.md b/dart_240529.md deleted file mode 100644 index 98fbf64..0000000 --- a/dart_240529.md +++ /dev/null @@ -1,223 +0,0 @@ -print('처음으로 하는 커밋'); - -SDK 파일 못 찾을 때 : 다운로드 받은 경로 안에서 찾는다 - -- …flutter_windows_3.19.0-stable\flutter\bin\cache\dart-sdk - -lib 폴더 생성 → main.dart 파일 생성 → print(’Hello World’); - -- lib 폴더 생성 → main.dart 파일 생성 → print(’Hello World’); -- void 는 리턴타입이 없다 { } 중괄호는 바로 옆에 붙인다 - -- top-level print() function 탑레벨 함수 - - ![Untitled](assets/images/240529_01.png) - - (아무데서나 쓸수 있다) 초기화가 나중에 된다 언제? 사용될 때 초기화가 된다 - - - void hello() { } 이렇게 top 레벨 함수를 만들 수 있다 - - 다른 파일에서도 import 해서 함수 접근 가능하다 -- Type Casting - - - ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/efd8d9ac-afe7-49f6-96a7-722835fcf93c/10dfdad7-3fc7-4e3d-957d-e6cc033fd5d0/Untitled.png) - - - 타입 캐스팅 → as type으로 가능 -- Dynamic - - ![Untitled](assets/images/240529_02.png) - - - 타입이 맞지 않는 값을 넣으면? type safe 기능으로 에러를 발생시킨다 - - (안전한 코드 사용가능) - - 타입 생략하지 말자 - - 그러나 주의 할 경우가 있는데… - - ![Untitled](assets/images/240529_03.png) - - ![Untitled](assets/images/240529_04.png) - - ![Untitled](assets/images/240529_05.png) - - - be careful ⇒ dynamic은 타입이 없기 때문에 numbers(int i, int j) 의 int 타입을 삭제한다면, 위와 같은 변수 값을 변경해도 에러를 발생시키지 않는다!! - - - dynamic - 런타임 타임에 타입이 설정됨 / 실행 이 후에 변경이 가능 할 수 있다. 런타임에 변경될 수 있는 코드는 쓰지말자 / 타입으로 보지 않는다 / 클래스가 아님 - - object - 컴파일 타임에 타입이 설정됨 / 모든 타입을 담을 수 있는 타입 / 클래스 - - ![Untitled](assets/images/240529_06.png) - - ![Untitled](assets/images/240529_07.png) - - - 역시나 마찬가지로 i 의 타입을 삭제한다면, 다이나믹 타입이 되어 bool + String도 에러를 발생시키지 않는다. - -- Final or const - - Note : 인스턴스 변수는 final이 될 수 있지만, const는 될 수 없다 - - ![Untitled](assets/images/240529_08.png) - - - const : 컴파일 타임에 초기화 / 시간이 더 빠르고 메모리 관리 용이 / 런타임에 수정 불가 - - final : 런타임 타임에 초기화 - - ### `final` - - - **초기화 시점**: `final` 변수는 런타임에 한 번만 값을 할당받을 수 있습니다. - - **변경 불가**: 값이 할당된 후에는 값을 변경할 수 없습니다. - - **사용 예시**: 주로 한 번 설정되면 변하지 않는 값에 사용됩니다. - - **초기화 지연**: `final` 변수는 선언 시점에서 바로 초기화하지 않고, 나중에 초기화할 수 있습니다. - - ```dart - void main() { - final int a = 10; - // a = 20; // 오류: 이미 초기화된 final 변수의 값을 변경할 수 없습니다. - - final b; - b = 20; // 가능: 한 번만 초기화하는 것이 허용됩니다. - // b = 30; // 오류: 이미 초기화된 final 변수의 값을 변경할 수 없습니다. - } - ``` - - ### `const` - - - **컴파일 타임 상수**: `const` 변수는 컴파일 타임에 상수 값이어야 합니다. 즉, 변수가 선언될 때 그 값이 이미 결정되어 있어야 합니다. - - **변경 불가**: 값이 할당된 후에는 값을 변경할 수 없습니다. - - **사용 예시**: 컴파일 타임에 변하지 않는 값에 사용됩니다. - - **전역 사용**: `const`는 클래스 수준에서 전역적으로 사용할 수 있으며, 런타임에 반복적으로 생성되는 값을 최소화하는 데 유용합니다. - - ### 요약 - - - `final`: 런타임 상수, 선언 후 값을 변경할 수 없으며, 런타임에 한 번만 할당될 수 있음. - - `const`: 컴파일 타임 상수, 선언 시점에서 값을 초기화해야 하며, 불변 객체를 만듦. - - 이러한 차이로 인해 `final`은 주로 실행 중에 초기화되지만 변경되지 않는 변수에 사용되고, `const`는 애플리케이션 전반에서 불변해야 하는 상수 값을 정의할 때 사용됩니다. - - ```dart - void main() { - const int a = 10; - // a = 20; // 오류: const 변수의 값을 변경할 수 없습니다. - - const b = 20; // const 변수는 선언과 동시에 초기화되어야 합니다. - - // const c; // 오류: const 변수는 선언 시점에서 초기화되어야 합니다. - - final d = [1, 2, 3]; - const e = [1, 2, 3]; - - // d.add(4); // 가능: final 변수의 값 자체는 불변이지만, 객체 내부의 값은 변경할 수 있습니다. - // e.add(4); // 오류: const로 선언된 리스트는 변경할 수 없습니다. - } - ``` - -- complie time or runtime time 차이점은? - - 컴파일 → 기계가 알아들 을 수 있는 언어로 변환하는 과정 (코딩 중 나는 에러 : 컴파일 에러) - - 런타임 → 실행한 이 후 - -- Null safety - - 초기화 되지 않는 nullable 함수의 초기값은 null 입니다. 숫자 유형이 있는 변수도 초기에는 null 입니다. 숫자도 Dart의 다른 모든 것과 마찬가지로 객체이기 때문입니다. - - ```dart - int? lineCount; - assert(lineCount == null); - ``` - - - assert 함수!! - - production 코드에서는 assert() 함수 호출을 무시한다. 꼭 디버깅 모드에서만 사용 해야 한다 (During developmemt) - - - Null 안전을 통해 Dart 컴파일러는 컴파일 타임에 이러한 잠재적인 오류를 감지한다. - - Null 안전을 사용하면 Null을 허용하지 않는 변수를 사용하기 전에 초기화를 해야한다 - - ```dart - int lineCount = 0; - ``` - - - 선언된 지역 변수를 초기화할 필요는 없지만 사용하기 전에 값을 할당해야 합니다. 예를 들어, 다음 코드는 `lineCount`전달될 때 Dart가 null이 아닌 것을 감지할 수 있기 때문에 유효합니다 - - ```dart - int lineCount; - - if (weLikeToCount) { - lineCount = countLines(); - } else { - lineCount = 0; - } - - print(lineCount); - ``` - -- 상수 vs 변수 - - 변수 값을 바꿀 수 없도록 해야 에러를 최소로 발생시킬 수 있다 - -- Late variables - - ```dart - late String description; - - void main() { - description = 'Feijoada!'; - print(description); - } - ``` - - - 선언 후 초기화되는 null을 허용하지 않는 변수를 선언합니다. - - 변수를 느리게 초기화합니다. - - 하지만 가능하면 사용하지 않도록 한다. 왜? 값이 초기화 할당이 안되었을 때 , runtime 에러 발생 합니다. -- Operator(연산자) - - String내 $ {} 로 쓸 수 있다(변수등..) - - - 후위 증가 연산자 i++ / 전위 증가 연산자 ++i - - i = 0; - - print(i++); ⇒ 0 - - print(i); ⇒ 1 - - print(++i); ⇒ 2 - - - ### 후위 증가 연산자 (`i++`) - - - **이름**: 후위 증가 연산자 (post-increment operator) - - **동작**: 먼저 현재 값을 사용한 후에 변수를 증가시킵니다. - - **사용 예시**: - - ```dart - void main() { - int i = 3; - int a = i++; // a에는 i의 현재 값인 3이 할당되고, 그 후에 i가 4로 증가합니다. - print(a); // 출력: 3 - print(i); // 출력: 4 - } - ``` - - ### 전위 증가 연산자 (`++i`) - - - **이름**: 전위 증가 연산자 (pre-increment operator) - - **동작**: 먼저 변수를 증가시킨 후에 증가된 값을 사용합니다. - - **사용 예시**: - - ```dart - void main() { - int i = 3; - int a = ++i; // i가 먼저 4로 증가한 후에, a에 증가된 값인 4가 할당됩니다. - print(a); // 출력: 4 - print(i); // 출력: 4 - } - ``` - - - 삼항 연산자 - - ```dart - bool isPublic = true; - - var visibility = isPublic? ‘public’ : ‘private’; - ``` - - - ?? ⇒ null 이면 뒤의 값을 넣는다 - - ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/efd8d9ac-afe7-49f6-96a7-722835fcf93c/b0bd1662-7eb9-4236-a127-f60c6c82cf4b/Untitled.png) - - - IDE상에서 문서를 작성할 때 /// 를 쓴다 \ No newline at end of file diff --git a/dart_240530.md b/dart_240530.md deleted file mode 100644 index 270f7a4..0000000 --- a/dart_240530.md +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:math'; - -void main() { - //imuutable - 불변 - //const []; - 이미 메모리에 올라가있으면 다음에 부를때 재사용이 가능하다 - - int Function(String) myFunc = (String text) => text.length; - - List list = ['apples', 'bananas', 'oranges']; - print(list.map((e) => e.toUpperCase())); - print(list.map(myFunc)); -} \ No newline at end of file diff --git a/project/bmi_calculator/lib/main/main_screen.dart b/project/bmi_calculator/lib/main/main_screen.dart new file mode 100644 index 0000000..1c5f398 --- /dev/null +++ b/project/bmi_calculator/lib/main/main_screen.dart @@ -0,0 +1,120 @@ +import 'package:bmi_calculator/result/result_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class MainScreen extends StatefulWidget { + const MainScreen({super.key}); + + @override + State createState() => _MainScreenState(); +} + +class _MainScreenState extends State { + final _formKey = GlobalKey(); + final _heightController = TextEditingController(); + final _weightController = TextEditingController(); + + @override + void dispose() { + _heightController.dispose(); + _weightController.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + + load(); + } + + Future save() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setDouble('height', double.tryParse(_heightController.text) ?? 0); + await prefs.setDouble('weight', double.tryParse(_weightController.text) ?? 0); + } + + Future load() async { + final SharedPreferences prefs = await SharedPreferences.getInstance(); + final double? height = prefs.getDouble('height'); + final double? weight = prefs.getDouble('weight'); + + if (height != null && weight != null) { + _heightController.text = '$height'; + _weightController.text = '$weight'; + print('키 : $height, 몸무게 : $weight'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('비만도계산기'), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextFormField( + controller: _weightController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: '몸무게', + ), + keyboardType: TextInputType.number, + validator: (value) { + if (value == null || value.isEmpty) { + return '몸무게를 입력해주세요'; + } + + return null; + }, + onChanged: (value) => save(), + ), + const SizedBox(height: 8), + TextFormField( + controller: _heightController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: '키', + ), + keyboardType: TextInputType.number, + validator: (value) { + if (value == null || value.isEmpty) { + return '키를 입력해주세요'; + } + + return null; + }, + onChanged: (value) => save(), + ), + const SizedBox(height: 8), + ElevatedButton( + onPressed: () { + if (_formKey.currentState?.validate() == false) { + return; + } + + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ResultScreen( + height: double.parse(_heightController.text), + weight: double.parse(_weightController.text), + ), + ), + ); + }, + child: const Text('결과'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/project/bmi_calculator/lib/result/result_screen.dart b/project/bmi_calculator/lib/result/result_screen.dart new file mode 100644 index 0000000..aafe70f --- /dev/null +++ b/project/bmi_calculator/lib/result/result_screen.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; + +class ResultScreen extends StatelessWidget { + final double height; + final double weight; + + const ResultScreen({ + required this.height, + required this.weight, + super.key, + }); + + String _calcBmi(double bmi) { + String result = '저체중'; + if (bmi >= 35) { + result = '고도 비만'; + } else if (bmi >= 30) { + result = '2단계 비만'; + } else if (bmi >= 25) { + result = '1단계 비만'; + } else if (bmi >= 23) { + result = '과체중'; + } else if (bmi >= 18.5) { + result = '정상'; + } + return result; + } + + Widget _buildIcon(double bmi) { + Icon icon = const Icon( + Icons.sentiment_dissatisfied, + color: Colors.green, + size: 100, + ); + if (bmi >= 23) { + icon = const Icon( + Icons.sentiment_very_dissatisfied, + color: Colors.green, + size: 100, + ); + } else if (bmi >= 18.5) { + icon = const Icon( + Icons.sentiment_satisfied, + color: Colors.green, + size: 100, + ); + } + return icon; + } + + @override + Widget build(BuildContext context) { + final double bmi = weight / ((height / 100.0) * (height / 100.0)); + return Scaffold( + appBar: AppBar( + title: const Text('결과'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + _calcBmi(bmi), + style: const TextStyle( + fontSize: 36, + ), + ), + _buildIcon(bmi), + ], + ), + ), + ); + } +} From f782c75640fc743e213853b171565e7dc332a4b5 Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Thu, 4 Jul 2024 00:09:53 +0900 Subject: [PATCH 02/20] feat : 240703 TIL --- dart_240618.md | 4 ++-- dart_240626.md | 44 ++++++++++++++++++++++++++++++++++++++ dart_240628.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ dart_240703.md | 13 ++++++++++++ shortCut.md | 14 ++++++++++++- 5 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 dart_240626.md create mode 100644 dart_240628.md create mode 100644 dart_240703.md diff --git a/dart_240618.md b/dart_240618.md index 8ba6259..6fedc35 100644 --- a/dart_240618.md +++ b/dart_240618.md @@ -137,8 +137,8 @@ Employee 타입 leader가 필드에 있었네?;; } ``` -이렇게 되어 있고, Department.fromJson 메서드는 이 JSON 데어티를 가져와서 -Employee.fromJson 메서드에 전달하여 Employee 객체로 역직렬화 되는것이다. +이렇게 되어 있고, Department.fromJson 메서드는 이 JSON 데이터를 가져와서 +Employee.fromJson 생성자에 전달하여 Employee 객체로 역직렬화 되는것이다. 테스트코드 형태를 equals 로 비교하면 띄어쓰기라던지 있으면 비교가 잘 안되니까 Map 형태로 바꿔서 비교하는것이 더 나을거 같다 \ No newline at end of file diff --git a/dart_240626.md b/dart_240626.md new file mode 100644 index 0000000..716d731 --- /dev/null +++ b/dart_240626.md @@ -0,0 +1,44 @@ +## Model class +- 클래스 별도 기능을 가지지 않는다 +- 데이터 소스를 앱에서 필요한 형태로 바꿔주는 역할 +- 모델 객체 클래스의 속성에 대한 데이터를 조회할 수 있는 클래스 + +## 권장 폴더 구조 +- data + - data_source + - model + - repository + +## subString, subList, take + - 셋팅 해놓은 숫자 이하로 값이 들어오면 에러발생 한다 + - take는 안전하게 뒤에 세팅한 숫자만큼 가져올 수 있다 +## final + - 매개변수에도 final을 붙일 수 있지만, 병적이라 하지말자 + +## List.unmodifiable + - repository에서 return 보낼대 캡슐화를 보낼때 List는 unmodifiable로 내보내면 + 수정불가 + +## dynamic + - 다이나믹을 리턴할때 한번 더 map을 이용해서 리턴하는것이 안전하다 + +## 블랙박스 테스트 + - 사용자관점에서 입력값과 출력값이 예상대로 나오는지에 대해서만 테스트 + - 내용이나, 로직등을 테스트 하지 않는다 + - 경계값 분석(-1, 0, 1) , 상태전이 + +## 단위 테스트 (Unit Test) + - +## unit8list + - 바이트데이터의 array + +## class + - 클래스 내에서 클래스를 생성하지 말자(다른 클래스는 생성자로 받으면 된다) + - 한 클래스는 한개의 책임만 가지자 + - +## Test Double + - 의존성을 가장 낮추고 테스트가 가능하게 만드는 것 + - stub, spy등 모든것은 mock으로 볼 수 있다(2007년 마이크로소프트) + +## interface +- 목 객체를 diff --git a/dart_240628.md b/dart_240628.md new file mode 100644 index 0000000..727b934 --- /dev/null +++ b/dart_240628.md @@ -0,0 +1,57 @@ +data_source: 데이터 소스와 직접적으로 상호작용하는 로직을 포함합니다. 예를 들어, API 호출이나 데이터베이스 쿼리 등이 이에 해당합니다. + +dto (Data Transfer Object): 네트워크 요청이나 응답에서 사용되는 객체를 정의합니다. 주로 API로부터 받은 데이터의 구조를 정의하는 데 사용됩니다. + +mapper: 한 형태의 객체를 다른 형태로 변환하는 로직을 담당합니다. 예를 들어, dto를 앱 내부에서 사용하는 model 객체로 변환하는 기능을 포함할 수 있습니다. + +model: 애플리케이션 내부에서 사용하는 데이터 모델을 정의합니다. 이는 비즈니스 로직에 사용되는 주요 데이터 구조입니다. + +repository: 데이터 소스와 애플리케이션 사이의 중간자 역할을 합니다. 데이터를 가져오고, 캐싱하고, 변환하는 등의 작업을 수행합니다. + +```dart +enum ContentType { article, image, video, unknown } + +abstract class Content { + int? id; + String? title; + String? content; + String? url; + String? caption; + DateTime? createdAt; + ContentType type; + + Content({ + this.id, + this.title, + this.content, + this.url, + this.caption, + this.createdAt, + required this.type, + }); + + factory Content.fromJson(Map json) { + switch (json['type']) { + case 'article': + return ArticleContent.fromJson(json); + case 'image': + return ImageContent.fromJson(json); + case 'video': + return VideoContent.fromJson(json); + default: + return UnknownContent.fromJson(json); + } + } +} + +``` + +위 코드는 어느 폴더에 있는게 가장 어울릴까? + +enum은 애플리케이션의 다양한 부분에서 사용될 수 있으며, 그 위치는 enum이 어떤 목적으로 사용되는지에 따라 달라집니다. 예를 들어: + +API 응답에서 특정 값을 나타내기 위해 사용되는 enum은 dto 폴더에 위치하는 것이 적절할 수 있습니다. + +애플리케이션 내부의 비즈니스 로직에서 사용되는 enum은 model 폴더에 더 적합할 수 있습니다. + +데이터 소스의 종류를 구분하는 enum은 data_source 폴더에 속할 수 있습니다. diff --git a/dart_240703.md b/dart_240703.md new file mode 100644 index 0000000..4b3a4c1 --- /dev/null +++ b/dart_240703.md @@ -0,0 +1,13 @@ +* dto를 사용하지 않을때 모델에서 사용하는 방법중에 @jsonKey(name: xxx) 가 있다. +* 이건 들어오는 이름 대신에 내가 임의로 사용하는 이름으로 변경해서 쓰겠다 할때 사용한다. + +jsonSeializable과 equtable을 함께 사용한다 + +URL 고수준 : 개발자가 사용하기 쉬운 수준 +바이너리 데이터 : 2진 데이터 + +소켓 : 이쪽을 통해서 통신을 한다 +TCP/IP : IP 기즌으로 통신한다 + +cookie 같은건 모바일에선 sharedPreference 등으로 대체 + diff --git a/shortCut.md b/shortCut.md index c68c663..1c8b79e 100644 --- a/shortCut.md +++ b/shortCut.md @@ -4,4 +4,16 @@ - Ctrl + h = 상속관계를 나타냄 - alt + j = 다중문자 선택 - android - help - find action - Regex 클릭하고 - //.*\n (모든 주석과 Enter까지 선택) - Replace All 하면 삭제 -- \ No newline at end of file + +- 에뮬레이터 실행 중이 아닌데 실행이 되고 있다면 .lock 파일을 지우면 실행되는것 같다 +- /Android/sdk/platform-tools/adb 를 환경변수에 등록하면 adb devices 하면 에뮬레이터 목록을 볼 수 있다. + + +- flutter create . : 현재 프로젝트에 플러터 프로젝트를 만든다 +- 예전버전이라서 지금과 호환이 안되면 + .idea을 삭제하고 / + 그래도 안되면 pubspec.yaml에 dart 버전을 현재 버전으로 바꿔주고 + Pub outdated : 현재버전과 yaml에 있는 버전을 비교해서 보여준다 + (flutter pub upgrade major-version) + pusbspec.lock : 현재 라이브러리의 실제 버전을 기술 해놓았다 + 에뮬레이터에 이미 설치되어 있다면 삭제를 하고 다시 설치해보자- \ No newline at end of file From c5f3c24d5318eda69b037506c83d1851485e839a Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Thu, 4 Jul 2024 22:34:16 +0900 Subject: [PATCH 03/20] feat : 240704 TIL --- dart_240628.md | 2 ++ dart_240704.md | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 dart_240704.md diff --git a/dart_240628.md b/dart_240628.md index 727b934..794277f 100644 --- a/dart_240628.md +++ b/dart_240628.md @@ -55,3 +55,5 @@ API 응답에서 특정 값을 나타내기 위해 사용되는 enum은 dto 폴 애플리케이션 내부의 비즈니스 로직에서 사용되는 enum은 model 폴더에 더 적합할 수 있습니다. 데이터 소스의 종류를 구분하는 enum은 data_source 폴더에 속할 수 있습니다. + +json to dart 라이브러리 / \ No newline at end of file diff --git a/dart_240704.md b/dart_240704.md new file mode 100644 index 0000000..6621b56 --- /dev/null +++ b/dart_240704.md @@ -0,0 +1,35 @@ +* 서버에서 받을 때 쿼리파라미터로 받아오면 필터링해서 들어온다 + 용도에 따라서 받아올지를 골라서 사용해야 한다 (id는 쿼리파라미터로 잘 쓰지는 않는다) +* DTO는 copywith 가 없으니 final을 사용하지 않아도 된다 있다면 붙여도 되고! +* Uint8List 만 받을 수 있으면 파일로 다운해도 부담이 없다 +* pubspec.lock 파일은 버전관리를 안해도 된다 + 전력적으로 버전관리를 해야해서 하는 경우는 있지만, 크게 관리 안해도 된다 +* ### 주석에 자세한 설명을 하면 관리에 있어서 훨씬 편하다 + 테스트를 여기에 넣어서 나중에 테스트코드를 그대로 사용하기도 한다 +* example 이란 이름보단 내용과 관련된 이름으로 하는게 더 의미 있다 +* 같이 하나만 받는 경우는 값이 없을 경우(터지는 경우)를 생각해서 처리를 하는 것이 필요하다 + + +Result 패턴 +* 기본 : 예외는 try-catch +* Result 패턴 : 성공 or 실패 처리에 유용한 패턴 +* .success + .error +* result는 상속이나 구현을 제한한다 + - 향상성 enum 객체처럼 사용 but 동등성 비교는 안된다 + + +freezed + - json serializable + equatable + 터미널에서 실행법 + - + - dart pub add freezed_annotation + dart pub add dev:build_runner + dart pub add dev:freezed +# if using freezed to generate fromJson/toJson, also add: +dart pub add json_annotation +dart pub add dev:json_serializable + +* List 같은 경우에는 초기값을 넣어줘야해서 @Default([])를 맨 앞에 넣어줘야한다 +* 안드로이드 help - find - watch : build 계속 리빌드 하기 싫을때 해놓으면 자동으로 반영된다 +* fromjson, tojson From 8700fcbd0d5763d09fabd18157e94151c2b09554 Mon Sep 17 00:00:00 2001 From: hugedreamhd Date: Sat, 6 Jul 2024 23:32:14 +0900 Subject: [PATCH 04/20] =?UTF-8?q?fix:=20=EB=8B=A4=ED=98=95=EC=84=B1=20TIL?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20/=20Result=20TIL=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dart_240611.md | 14 ++++- dart_240612.md | 157 +++++++++++++++++++++++++++++++++++++++++++++++++ dart_240703.md | 3 +- dart_240704.md | 1 + 4 files changed, 171 insertions(+), 4 deletions(-) diff --git a/dart_240611.md b/dart_240611.md index f768402..e68fd44 100644 --- a/dart_240611.md +++ b/dart_240611.md @@ -6,7 +6,11 @@ - abstract 클래스 - 사물의 어떤 큰 특징들을 보고 만드는 편 +- 상속을 통해 기능을 재사용하고자 할 때 사용한다 +- 필드와 메서드를 포함 할 수 있고, 상속받은 클래스들이 일부 메서드를 구현하도록 강제한다 - abstract class 만 사용하자 +- 'is - a' 관계를 나타낼 때 사용한다. 'Medic' 은 'Unit' 이다 : OK! + (but Unit은 Medic이다: NO! 유닛이 메딕만 있는것이 아니다) - 추상 클래스에서는 {}을 넣지 않고 메서드를 쓴다 (); 요렇게 끝내면 됨 - 추상 클래스는 인스턴스화 금지(안된다잉) - 추상 클래스는 메서도가 없어도 괜찮다(group만을 만드려고 그러는 경우가 있다) @@ -17,9 +21,13 @@ abstract 클래스 interface - 다중 구현이 가능하다 -- 인터페이스 안에서는 프로퍼티 정의 해놓으면(getter/setter) 상속 받은데서 getter/setter 오버라이드를 해야되는데 번거롭다 +- 클래스가 구현 해야 할 메서드의 목록을 제공한다 +- 'can-do' 관계를 나타낼 때 사용한다. 'Medic'은 'Healable' 능력을 가지고(할 수)있다 +- 인터페이스 안에서는 프로퍼티 정의 해놓으면(getter/setter) +- 상속 받은데서 getter/setter 오버라이드를 해야되는데 번거롭다 - 그래서 주로 메서드를 정의 해놓는 편이 나을것이다 - 인터페이스 안에는 다 미정의 되어 있는 기능 - 보통 독립적인 기능들이 모여있다(사람이라면 말하기,걷기등..) -- abstract interface class 만 사용하자(implements 만 사용하자 공식문서에는 그렇게 되어있다구!!) -- \ No newline at end of file +- 인터페이스는 메서드 시그니처만을 정의한다 +- abstract interface class 만 사용하자 +- (implements 만 사용하자 공식문서에는 그렇게 되어있다구!!) diff --git a/dart_240612.md b/dart_240612.md index 5d527dc..698820a 100644 --- a/dart_240612.md +++ b/dart_240612.md @@ -2,6 +2,163 @@ - 다형성을 알고 나면 개발이 즐거워진다(제발) - 다형성 - 공통메소드를 통합 - 공통성은 없는데 메소드(기능)만 동일하게 가지고 있으면 interface에서 구현한다 +- +- +- 스타크래프트 게임을 예로 들어 크게 +- **유닛(Unit)**과 **건물(Structure)**로 분류할 수 있습니다. 또한 테란(Terran), 저그(Zerg), 프로토스(Protoss) 종족으로도 나눌 수 있으며, +- 테란의 경우 **바이오닉(Bionic)**과 **기계 유닛(Mechanic)**으로도 나눌 수 있습니다. + +유닛과 건물의 공통 기능과 특정 기능 +유닛과 건물은 공통 기능과 특정 기능을 가지고 있습니다. 공통 기능은 각각의 클래스에서 별도로 정의하기보다는, +상위 클래스에서 정의해 놓고 하위 클래스에서 필요할 때 메서드를 재정의(@override)하여 사용하는 것이 더 효율적입니다. +예를 들어, 테란의 메딕 유닛은 바이오닉(Bionic)이고 유닛(Unit)이며 테란 종족(Terran)입니다. +메딕은 다른 유닛과 공통적인 기능과 특정 기능을 모두 가지고 있습니다. + +공통 기능과 특정 기능의 예 +메딕의 공통 기능으로는 이동(move), 멈춤(hold), 체력(HP), 마력(MP) 등이 있으며, +특정 기능으로는 회복(Healable) 기능이 있습니다. +공통적인 기능은 특정 유닛에 국한되지 않기 때문에 인터페이스에서 선언하고, +이를 통해 각 클래스에서 필요할 때 구현하는 것이 효율적입니다. + + +메서드 오버라이딩(Method Overriding): + +상위 클래스나 인터페이스에서 정의한 메서드를 하위 클래스에서 재정의하여, +동일한 이름의 메서드가 클래스마다 다르게 동작할 수 있게 합니다. +예를 들어, Unit 클래스의 move() 메서드는 Medic와 Marine에서 서로 다른 방식으로 동작할 수 있습니다. + + +인터페이스 구현(Interface Implementation): + +여러 클래스가 같은 인터페이스를 구현하여 동일한 메서드를 각각 다르게 정의할 수 있습니다. +예를 들어, Healable 인터페이스의 heal() 메서드는 Medic와 Protoss High Templar에서 각각 다르게 구현될 수 있습니다. + + +객체의 동적 바인딩(Dynamic Binding): + +실행 시간에 객체의 실제 타입에 따라 호출되는 메서드가 결정됩니다. +예를 들어, Unit 타입의 변수에 Medic 객체를 할당하면, Unit 타입을 통해 Medic의 move() 메서드를 호출할 수 있습니다. + + +다형성을 통한 유연성: + +다형성을 통해 코드의 유연성을 높일 수 있으며, 이는 새로운 클래스나 기능을 추가할 때 기존 코드를 수정하지 않고도 기능을 확장할 수 있게 합니다. +예를 들어, 새로운 유닛을 추가할 때 Unit 인터페이스를 구현하기만 하면 기존 코드에서 이 새로운 유닛을 사용할 수 있습니다. + +- 추상 클래스와 인터페이스의 차이점 +* 추상 클래스의 특징 +추상 클래스는 상속을 통해 기본 기능을 정의하고 하위 클래스에서 이를 구체적으로 구현하게 합니다. +추상 클래스를 상속(extends)받으면, 상위 클래스의 모든 메서드를 재정의(@override)하거나 기본적으로 제공된 기능을 사용하게 됩니다. +상속받은 하위 클래스에서 특정 기능만 필요할 때도 불필요한 기능까지 포함해야 할 수 있습니다. +* 인터페이스의 특징 +인터페이스는 클래스가 구현해야 할 메서드의 목록을 정의합니다. 인터페이스는 특정 기능을 제공하는 데 초점을 맞춥니다. +인터페이스를 구현(implements)하면 필요한 기능만 선택적으로 구현할 수 있어 유연성을 높일 수 있습니다. +다중 인터페이스를 통해 여러 기능을 조합하여 사용할 수 있으며, 이는 상속의 단점을 보완합니다. +왜 인터페이스가 더 적합한가? +추상 클래스를 사용하면 상위 클래스의 모든 기능을 상속받아야 하므로, 하위 클래스에서 필요하지 않은 기능까지 포함될 수 있습니다. +반면, 인터페이스는 필요한 기능만을 선언하고 이를 선택적으로 구현할 수 있기 때문에 유연성과 확장성을 더욱 높일 수 있습니다. + +따라서, 추상 클래스를 사용하는 것보다 인터페이스를 선언하여 필요한 기능만 선택적으로 구현하는 것이 더 적합합니다. +인터페이스는 다양한 클래스가 동일한 기능을 구현할 수 있게 하여 코드의 재사용성을 높이고, 시스템을 보다 유연하게 설계할 수 있게 합니다. + + +```dart +// 추상 클래스: 기본 기능 정의 +abstract class Unit { + int hp; + int mp; + + void move(); + void hold(); +} + +// 인터페이스: 특정 능력 정의 +abstract interface class Healable { + void heal(); +} + +abstract interface class Attackable { + void attack(); +} + +// 인터페이스: 종족 정의 +abstract interface class Terran { + void color(); +} + +// 유닛: 메딕 +class Medic implements Unit, Healable, Terran { + @override + int hp = 60; + + @override + int mp = 100; + + @override + void move() { + print("Medic is moving"); + } + + @override + void hold() { + print("Medic is holding position"); + } + + @override + void heal() { + print("Medic is healing"); + } + + @override + void color() { + print("Medic's color is blue"); + } +} + +// 유닛: 마린 +class Marine implements Unit, Attackable, Terran { + @override + int hp = 40; + + @override + int mp = 0; + + @override + void move() { + print("Marine is moving"); + } + + @override + void hold() { + print("Marine is holding position"); + } + + @override + void color() { + print("Marine's color is blue"); + } + + // 유닛을 제어하는 함수 + void commandUnit(Unit unit) { + unit.move(); + unit.hold(); + } + + void main() { + Unit medic = Medic(); + Unit marine = Marine(); + + commandUnit(medic); // Medic is moving + commandUnit(marine); // Marine is moving + } +} + +``` + + + 이건 다른 유닛들도 implements 할 수 있다는 말이 된다 + 그리고 메딕만의 특정기능은 class Medic 내에서 구현 할 수 있으며 + - 인스턴스 생성할때 공통 기능때문에 같은 interface로 묶을 수 있다 - 추상적인 선언 = new 상세정의 - 여러 인터페이스를 쉼표(,)로 받을 수 있다 diff --git a/dart_240703.md b/dart_240703.md index 4b3a4c1..a117628 100644 --- a/dart_240703.md +++ b/dart_240703.md @@ -7,7 +7,8 @@ URL 고수준 : 개발자가 사용하기 쉬운 수준 바이너리 데이터 : 2진 데이터 소켓 : 이쪽을 통해서 통신을 한다 -TCP/IP : IP 기즌으로 통신한다 +TCP/IP : IP 기준으로 통신한다 cookie 같은건 모바일에선 sharedPreference 등으로 대체 +base64? \ No newline at end of file diff --git a/dart_240704.md b/dart_240704.md index 6621b56..5b7f3f7 100644 --- a/dart_240704.md +++ b/dart_240704.md @@ -17,6 +17,7 @@ Result 패턴 .error * result는 상속이나 구현을 제한한다 - 향상성 enum 객체처럼 사용 but 동등성 비교는 안된다 +* 버그를 줄이는 목적 : 에러 발생시 오류 패턴 방지 (프로그램이 종료되거나 하면 안된다) freezed From fd7caf03475f36f20243e4912c6e351c6e01e994 Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Sun, 7 Jul 2024 16:48:02 +0900 Subject: [PATCH 05/20] =?UTF-8?q?fix=20:=20240705=20=EC=84=A4=EA=B3=84?= =?UTF-8?q?=EC=9B=90=EC=B9=99=20TIL=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dart_240628.md | 25 ++++++++----- dart_240704.md | 95 ++++++++++++++++++++++++++++++++++++++++++---- dart_240705.md | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 18 deletions(-) create mode 100644 dart_240705.md diff --git a/dart_240628.md b/dart_240628.md index 794277f..8e631a1 100644 --- a/dart_240628.md +++ b/dart_240628.md @@ -1,12 +1,17 @@ -data_source: 데이터 소스와 직접적으로 상호작용하는 로직을 포함합니다. 예를 들어, API 호출이나 데이터베이스 쿼리 등이 이에 해당합니다. +data_source: 데이터 소스와 직접적으로 상호작용하는 로직을 포함합니다. + 예를 들어, API 호출이나 데이터베이스 쿼리 등이 이에 해당합니다. -dto (Data Transfer Object): 네트워크 요청이나 응답에서 사용되는 객체를 정의합니다. 주로 API로부터 받은 데이터의 구조를 정의하는 데 사용됩니다. +dto (Data Transfer Object): 네트워크 요청이나 응답에서 사용되는 객체를 정의합니다. + 주로 API로부터 받은 데이터의 구조를 정의하는 데 사용됩니다. -mapper: 한 형태의 객체를 다른 형태로 변환하는 로직을 담당합니다. 예를 들어, dto를 앱 내부에서 사용하는 model 객체로 변환하는 기능을 포함할 수 있습니다. +mapper: 한 형태의 객체를 다른 형태로 변환하는 로직을 담당합니다. + 예를 들어, dto를 앱 내부에서 사용하는 model 객체로 변환하는 기능을 포함할 수 있습니다. -model: 애플리케이션 내부에서 사용하는 데이터 모델을 정의합니다. 이는 비즈니스 로직에 사용되는 주요 데이터 구조입니다. +model: 애플리케이션 내부에서 사용하는 데이터 모델을 정의합니다. + 이는 비즈니스 로직에 사용되는 주요 데이터 구조입니다. -repository: 데이터 소스와 애플리케이션 사이의 중간자 역할을 합니다. 데이터를 가져오고, 캐싱하고, 변환하는 등의 작업을 수행합니다. +repository: 데이터 소스와 애플리케이션 사이의 중간자 역할을 합니다. + 데이터를 가져오고, 캐싱하고, 변환하는 등의 작업을 수행합니다. ```dart enum ContentType { article, image, video, unknown } @@ -48,12 +53,12 @@ abstract class Content { 위 코드는 어느 폴더에 있는게 가장 어울릴까? -enum은 애플리케이션의 다양한 부분에서 사용될 수 있으며, 그 위치는 enum이 어떤 목적으로 사용되는지에 따라 달라집니다. 예를 들어: - +enum은 애플리케이션의 다양한 부분에서 사용될 수 있으며, 그 위치는 enum이 어떤 목적으로 사용되는지에 따라 달라집니다. 예를 들어: API 응답에서 특정 값을 나타내기 위해 사용되는 enum은 dto 폴더에 위치하는 것이 적절할 수 있습니다. - 애플리케이션 내부의 비즈니스 로직에서 사용되는 enum은 model 폴더에 더 적합할 수 있습니다. - 데이터 소스의 종류를 구분하는 enum은 data_source 폴더에 속할 수 있습니다. -json to dart 라이브러리 / \ No newline at end of file +json to dart 라이브러리 사용시, +json_serializable을 사용하면, json_serializable은 json 데이터를 dart 객체로 변환하는 데 사용되는 코드를 생성합니다. +이를 통해 json 데이터를 dart 객체로 변환하고, dart 객체를 json 데이터로 변환하는 코드를 쉽게 작성할 수 있습니다. + diff --git a/dart_240704.md b/dart_240704.md index 6621b56..1e75e40 100644 --- a/dart_240704.md +++ b/dart_240704.md @@ -16,20 +16,99 @@ Result 패턴 * .success .error * result는 상속이나 구현을 제한한다 - - 향상성 enum 객체처럼 사용 but 동등성 비교는 안된다 + - 향상성 enum 객체처럼 사용 but 동등성 비교는 안된다 + +result 클래스는 범용적으로 쓰려고 만드는 거라서 이름을 특수하게 짓지 않아도 된다 +result.when / reslut.map 은 쓰지말고 switch로 변환하도록 하자 - lagacy 코드를 줄이기 위해서 +if문에 예외가 1개인 경우에는 else를 사용하지 않아도 된다 + +enum에 설정해 놓은 대로 에러를 처리하지 않고 +extention을 이용해서 에러를 각 언어에 맞게 처리를 하는것이 더 좋다 + +1. Enum을 사용한 에러 처리 + 기존 방식으로 에러를 enum으로 정의하면, 에러 유형을 고정된 집합으로 관리할 수 있습니다. + 그러나 이는 유연성이 부족하고 각 에러에 대한 구체적인 처리가 어렵습니다. 예를 들어: + +```dart +enum ErrorType { + networkError, + validationError, + unknownError, +} + +// 에러 처리 +void handleError(ErrorType error) { + switch (error) { + case ErrorType.networkError: + print("Network error occurred"); + break; + case ErrorType.validationError: + print("Validation error occurred"); + break; + case ErrorType.unknownError: + print("An unknown error occurred"); + break; + } +} +``` +2. Extension을 사용한 에러 처리 + Extension을 사용하면 enum의 각 값에 대해 메서드를 정의할 수 있어서, + 더 구체적이고 유연하게 에러를 처리할 수 있습니다. + 또한, 각 에러 유형에 대해 맞춤형 메시지나 행동을 추가할 수 있습니다. 예를 들어: + +```dart + +enum ErrorType { + networkError, + validationError, + unknownError, +} + +// ErrorType에 대한 Extension 정의 +extension ErrorTypeExtension on ErrorType { + String get errorMessage { + switch (this) { + case ErrorType.networkError: + return "Network error occurred. Please check your internet connection."; + case ErrorType.validationError: + return "Validation error occurred. Please check the input values."; + case ErrorType.unknownError: + return "An unknown error occurred. Please try again later."; + } + } + + void handle() { +// 각 에러 유형에 맞는 처리를 정의 + print(errorMessage); +// 추가적으로, 각 에러에 대한 로그 저장, 사용자 알림 등도 가능 + } +} + +// 에러 처리 +void handleError(ErrorType error) { + error.handle(); +} +``` +요약 +Enum을 사용한 에러 처리는 단순하지만 유연성이 떨어짐. +Extension을 사용한 에러 처리는 각 에러 유형에 대해 구체적인 메시지와 동작을 정의할 수 있어서 더 유연하고 관리하기 쉽다. +이 방식은 특히 다양한 에러 처리 시나리오가 필요한 경우에 유용합니다. 각 에러에 대한 처리 로직을 enum 정의에 포함시키지 않고, +확장 메서드로 정의하여 코드의 가독성과 유지 보수성을 높일 수 있습니다. + freezed - - json serializable + equatable - 터미널에서 실행법 - - - - dart pub add freezed_annotation + - json serializable + equatable + copywith + toString + hashCode + == + fromJson + toJson + - 종합 세트 같은 느낌이다..! + + - 터미널에서 실행법 + dart pub add freezed_annotation dart pub add dev:build_runner dart pub add dev:freezed # if using freezed to generate fromJson/toJson, also add: -dart pub add json_annotation -dart pub add dev:json_serializable + dart pub add json_annotation + dart pub add dev:json_serializable * List 같은 경우에는 초기값을 넣어줘야해서 @Default([])를 맨 앞에 넣어줘야한다 * 안드로이드 help - find - watch : build 계속 리빌드 하기 싫을때 해놓으면 자동으로 반영된다 -* fromjson, tojson +* fromjson, tojson 같은 경우에는 json_serializable을 사용하면 된다 \ No newline at end of file diff --git a/dart_240705.md b/dart_240705.md new file mode 100644 index 0000000..ab66a59 --- /dev/null +++ b/dart_240705.md @@ -0,0 +1,100 @@ +typedef : 타입 재정의를 할때 사용한다 +- typedef PhotoResultError = Error, PhotoRepositoryError>; + +static 있는 클래스는 abstract를 붙이는게 더 낫다 (인스턴스를 만들지 않기 위해서) +아무일도 하지 않는 클래스라서 abstract를 붙이는 것이 더 좋다 + +```dart + abstract class PhotoRepository { + Future fetchPhotos(); +} +``` + +key 같은 경우는 직접 올리지 말자 / 로컬 파일로 관리하면 좋다 +- 플러터에서는 flutter_dotenv 패키지를 이용해서 하면 편하다 + +final int _max = 9223372036854775807 + 1 이 최대값인데 +여기에 + 1을 하면 - 9223372036854775808 이런값이 나온다 (기본상식 - 벵글벵글 돈다) + +재귀 호출 - 자기 자신을 계속 호출해서 메모리에 쌓이다가 + return 을 받으면 한번에 다 돌려줘서 터지는? 경우가 있어서 주의해야 한다 + +꼬리 재귀 - 재귀 호출을 하면서 계속해서 메모리에 쌓이는 것을 방지하기 위해서 + return을 받으면서 계속해서 돌려주는 방식으로 메모리를 적게 사용할 수 있다 + dart는 꼬리 재귀를 지원하지 않는다 + +좋은 코드를 위해 의식해야 하는 6가지 코드 원칙 + +- DRY : Don't Repeat Yourself (중복을 피하라) + 1. 중복 코드를 제거하자(메소드로 분리하자) + +- PIE : Program to an Intetly, and Expressively (명확하고 표현력 있게 프로그래밍 하라) + 1. 코드를 읽는 사람이 이해하기 쉽게 작성 + 2. 쉬운 이름을 사용하자 + 3. 컨벤션을 따르자 + 4. 매직 넘버에 이름을 붙이자(숫자를 직접 사용하지 말고 이름을 붙여서 사용) + +- SRP : Single Responsibility Principle (단일 책임 원칙) + 1. 클래스는 하나의 책임만 가져야 한다 (단일 책임 원칙) + 2. 에러 수정 시 다른 클래스에 영향을 주지 않도록 한다, 그 클래스만 수정하면 되게 하자 + 3. 클래스 분리가 너무 많아도 오히려 관리가 어려울 수 있다 (적당히) + +- OCP : Open/Closed Principle (개방-폐쇄 원칙) + 1. 확장에는 열려있고 변경에는 닫혀 있어야 한다 (개방-폐쇄 원칙) + 2. 새로운 기능이 추가되어도 기존 코드를 수정하지 않고 확장할 수 있게 하자 + 3. 인터페이스를 사용하면 쉽게 확장이 가능하다 + 4. 상속을 사용하면 확장이 어렵다 + 5. String 상속 금지이므로 확장이 어렵다 + 6. Iterable, Comparator 등을 사용하면 확장이 쉽다 + +- SDP : Stable Dependencies Principle (안정된 의존성 원칙) + 1. 안정된 클래스는 변경되지 않아야 한다 + 2. 안정된 클래스는 다른 클래스에 의존하면 안된다 + 3. 안정된 클래스는 인터페이스에 의존해야 한다 + 4. 안정된 클래스는 구체 클래스에 의존하면 안된다 + +- ADP : Acyclic Dependencies Principle (비순환 의존성 원칙) + 1. 의존성 비순환 원칙은 순환 의존성을 피해야 한다 + 2. 순환 의존성은 코드를 이해하기 어렵게 만든다 + 3. 순환 의존성은 테스트하기 어렵게 만든다 + 4. 순환 의존성은 코드를 변경하기 어렵게 만든다 + 5. 순환 의존성은 코드를 확장하기 어렵게 만든다 + 6. 순환 의존성은 코드를 재사용하기 어렵게 만든다 + + + +설계원칙 : SOLID +- 단일 책임 원칙(Single Responsibility Principle) +- 개방-폐쇄 원칙(Open-Closed Principle) +- 리스코프 치환 원칙(Liskov Substitution Principle) +- 인터페이스 분리 원칙(Interface Segregation Principle) +- 의존 역전 원칙(Dependency Inversion Principle) + +상속 = 확장 / 변경 = 수정 +1. 단일책임원칙 : 클래스는 하나의 책임만 가져야 한다 - 외부 객체는 생성자로 주입받아라 + (Slime, goblin, Character 클래스를 분리하자) +2. 개방폐쇄원칙 : 확장에는 열려있고 변경에는 닫혀 있어야 한다 - (Slime, goblin 각각 공격하지 말고 Character로 공격하게 하자) + 인터페이스를 파라미터로 받으면 수정하지 않아도 기능 확장(적용)이 가능하다 +3. 리스코프치환원칙 : 자식클래스는 부모클래스에서 가능한 행위를 수행할 수 있어야 한다 (is - a 원칙) + (Slime, goblin이 Character를 상속받아서 공격을 할 수 있게 하자) +4. 인터페이스분리원칙 : 클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안된다 + (인터페이스 1개에 모든 기능을 넣지 말고, 기능별로 나눠서 사용하자[attackble, moveable, flyable, runable, swimable, jumpable]) +5. 의존관계 역전원칙 : 추상화에 의존해야 하며 구체화에 의존하면 안된다 + (메딕 캐릭터가 특정 객체를 파라미터로 받지 말고 인터페이스를 받아서 사용하게 하자[Healable interface 구현체를 받도록 하는것]) + + + +디자인 패턴 +- software design pattern : 소프트웨어 설계시 특정 문맥에서 공통적으로 자주 발생하는 문제에 대해 재사용 가능한 해결책 +- 디자인 패턴의 장점 : 코드의 재사용성, 코드의 유지보수성, 코드의 가독성, 유연성, 확장성 +- 디자인 패턴의 종류 : 생성 패턴, 구조 패턴, 행위 패턴 + - 생성 패턴 : 객체 생성에 관련된 패턴(싱글턴 패턴, 팩토리 패턴, 빌더 패턴 등등) + 1. 싱글턴 패턴 : 객체를 하나만 생성하고, 이후에 생성된 객체를 리턴하는 패턴(1개의 인스턴스가 공유된다) + 2. 팩토리 패턴 : 객체를 생성하는 인터페이스를 정의하고, 이를 구현한 클래스에서 객체를 생성하는 패턴 + - 구조 패턴 : 클래스나 객체를 조합해 더 큰 구조를 만드는 패턴 (데커레이터 패턴, 퍼사드 패턴 등등) + 1. 데커레이터 패턴 : 객체에 추가적인 요소를 동적으로 추가하는 패턴 + 2. 퍼사드 패턴 : 복잡한 서브시스템을 간단하게 제공하는 인터페이스를 제공하는 패턴(Repository 패턴) + 3. 이터레이터 패턴 : 반복 구조 객체를 통해 요소를 순차적으로 접근하는 패턴 + - 행위 패턴 : 객체나 클래스 사이의 알고리즘과 책임 분배에 관련된 패턴 (전략패턴, 이터레이터 패턴, 옵서버 패턴 등등) + 1. 전략 패턴 : + 2. 옵서버 패턴 : 객체의 상태 변화를 관찰하는 객체를 등록하고, 상태 변화가 있을 때 메서드를 호출하는 패턴(발행/구독 모델) \ No newline at end of file From 7358dbaa3d2bf4f4e37d74ee346b31bf923202d3 Mon Sep 17 00:00:00 2001 From: hugedreamhd Date: Sun, 7 Jul 2024 22:34:13 +0900 Subject: [PATCH 06/20] =?UTF-8?q?fix:=20=EC=84=A4=EA=B3=84=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0,=20=EB=94=94=EC=9E=90=EC=9D=B8=ED=8C=A8=ED=84=B4=20TI?= =?UTF-8?q?L=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dart_240705.md | 68 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/dart_240705.md b/dart_240705.md index ab66a59..7aad0c7 100644 --- a/dart_240705.md +++ b/dart_240705.md @@ -1,20 +1,57 @@ -typedef : 타입 재정의를 할때 사용한다 -- typedef PhotoResultError = Error, PhotoRepositoryError>; - -static 있는 클래스는 abstract를 붙이는게 더 낫다 (인스턴스를 만들지 않기 위해서) -아무일도 하지 않는 클래스라서 abstract를 붙이는 것이 더 좋다 - +typedef : 기존 타입을 새로운 이름으로 재정의하여 코드의 가독성을 높이고 + 재사용성을 개선하는 데 사용됩니다. ```dart + typedef PhotoResultError = Error, PhotoRepositoryError>; + abstract class PhotoRepository { Future fetchPhotos(); } ``` +이 코드는 PhotoRepository 클래스에서 fetchPhotos 메서드가 +PhotoResultError 타입의 Future를 반환하도록 정의되어 있습니다. +PhotoResultError는 List와 PhotoRepositoryError를 사용하는 Error 타입의 별칭입니다. + + +만약 static만 있는 클래스라면 인스턴스화 할 필요가 없으므로 +의미를 더 명확하게 하기 위해 abstract 를 붙이는 것이 더 낫다. +코드의 가독성을 높이고 유지보수성을 높이는데 기여한다. +abstract를 붙이고 인스턴화를 시도하면 컴파일 에러가 발생한다. + +```dart +abstract class UtilityClass { + // Static method + static void utilityMethod() { + print('This is a utility method.'); + } +} + +void main() { + // UtilityClass instance = UtilityClass(); // This line would cause a compile-time error. + UtilityClass.utilityMethod(); // Correct usage +} + +``` + +```dart +void main() { + int maxInt = 9223372036854775807; // 2^63 - 1 + int overflowInt = maxInt + 1; + + print("Max Int: $maxInt"); + print("Overflow Int: $overflowInt"); // Should output: -9223372036854775808 +} +--------------------------------- + +Max Int: 9223372036854775807 +Overflow Int: -9223372036854775808 +``` +이 범위에서 최대값에 1을 더하면 메모리에서 비트가 넘치면서, +2진수로 표현할 때 첫 번째 비트가 최솟값을 나타내는 비트로 바뀌게 됩니다. 따라서, +9223372036854775807 + 1 은 −9223372036854775808가 됩니다. 이 현상을 오버플로우라고 합니다. key 같은 경우는 직접 올리지 말자 / 로컬 파일로 관리하면 좋다 - 플러터에서는 flutter_dotenv 패키지를 이용해서 하면 편하다 -final int _max = 9223372036854775807 + 1 이 최대값인데 -여기에 + 1을 하면 - 9223372036854775808 이런값이 나온다 (기본상식 - 벵글벵글 돈다) 재귀 호출 - 자기 자신을 계속 호출해서 메모리에 쌓이다가 return 을 받으면 한번에 다 돌려줘서 터지는? 경우가 있어서 주의해야 한다 @@ -51,7 +88,7 @@ final int _max = 9223372036854775807 + 1 이 최대값인데 1. 안정된 클래스는 변경되지 않아야 한다 2. 안정된 클래스는 다른 클래스에 의존하면 안된다 3. 안정된 클래스는 인터페이스에 의존해야 한다 - 4. 안정된 클래스는 구체 클래스에 의존하면 안된다 + 4. 안정된 클래스는 구체 클래스에 의존하면 안된다(생성자가 변하거나 할 수 있으니까) - ADP : Acyclic Dependencies Principle (비순환 의존성 원칙) 1. 의존성 비순환 원칙은 순환 의존성을 피해야 한다 @@ -95,6 +132,13 @@ final int _max = 9223372036854775807 + 1 이 최대값인데 1. 데커레이터 패턴 : 객체에 추가적인 요소를 동적으로 추가하는 패턴 2. 퍼사드 패턴 : 복잡한 서브시스템을 간단하게 제공하는 인터페이스를 제공하는 패턴(Repository 패턴) 3. 이터레이터 패턴 : 반복 구조 객체를 통해 요소를 순차적으로 접근하는 패턴 - - 행위 패턴 : 객체나 클래스 사이의 알고리즘과 책임 분배에 관련된 패턴 (전략패턴, 이터레이터 패턴, 옵서버 패턴 등등) - 1. 전략 패턴 : - 2. 옵서버 패턴 : 객체의 상태 변화를 관찰하는 객체를 등록하고, 상태 변화가 있을 때 메서드를 호출하는 패턴(발행/구독 모델) \ No newline at end of file + - 행위 패턴 : 객체나 클래스 사이의 알고리즘과 책임 분배에 관련된 패턴 (Strategy Pattern(전략패턴), 이터레이터 패턴, 옵서버 패턴 등등) + 1. 전략 패턴 : 객체의 상태 변화를 관찰하고, 상태가 변경될 때 자동으로 알림을 받아서 업데이트할 수 있도록 하는 디자인 패턴입니다. + 이 패턴은 일대다(one-to-many) 의존성을 정의합니다. + 2. 옵서버 패턴 : 옵저버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. + 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 발행/구독 모델로 알려져 있기도 하다. (예: 콜백함수) + 3. 이터레이터 패턴 : 컬렉션(예: 리스트, 맵, 집합 등) 요소를 하나씩 순차적으로 접근하는 방법을 제공하는 디자인 패턴입니다. + 이 패턴을 사용하면 컬렉션의 내부 구조를 노출하지 않고도 그 요소들을 탐색할 수 있습니다. + - Iterable과 Iterator의 구조 + - Iterable: 컬렉션을 반복할 수 있는 인터페이스로, iterator라는 getter를 제공합니다. 이 getter는 Iterator를 반환합니다. + - Iterator: Iterable 컬렉션의 요소를 탐색하기 위한 인터페이스로, moveNext() 메서드를 통해 다음 요소로 이동하고, current를 통해 현재 요소에 접근할 수 있습니다. \ No newline at end of file From 70086b9328603c0817daab1a8e0deb6549d40f83 Mon Sep 17 00:00:00 2001 From: hugedreamhd Date: Sun, 7 Jul 2024 22:46:03 +0900 Subject: [PATCH 07/20] =?UTF-8?q?fix:=20=EC=84=A4=EA=B3=84=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0,=20=EB=94=94=EC=9E=90=EC=9D=B8=ED=8C=A8=ED=84=B4=20TI?= =?UTF-8?q?L=20=EC=88=98=EC=A0=95=5F01?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dart_240705.md | 216 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 145 insertions(+), 71 deletions(-) diff --git a/dart_240705.md b/dart_240705.md index 7aad0c7..f83e735 100644 --- a/dart_240705.md +++ b/dart_240705.md @@ -1,19 +1,20 @@ -typedef : 기존 타입을 새로운 이름으로 재정의하여 코드의 가독성을 높이고 - 재사용성을 개선하는 데 사용됩니다. +typedef : 기존 타입을 새로운 이름으로 재정의하여 코드의 가독성을 높이고 +재사용성을 개선하는 데 사용됩니다. + ```dart typedef PhotoResultError = Error, PhotoRepositoryError>; - - abstract class PhotoRepository { + +abstract class PhotoRepository { Future fetchPhotos(); } ``` -이 코드는 PhotoRepository 클래스에서 fetchPhotos 메서드가 -PhotoResultError 타입의 Future를 반환하도록 정의되어 있습니다. -PhotoResultError는 List와 PhotoRepositoryError를 사용하는 Error 타입의 별칭입니다. +이 코드는 PhotoRepository 클래스에서 fetchPhotos 메서드가 +PhotoResultError 타입의 Future를 반환하도록 정의되어 있습니다. +PhotoResultError는 List와 PhotoRepositoryError를 사용하는 Error 타입의 별칭입니다. -만약 static만 있는 클래스라면 인스턴스화 할 필요가 없으므로 -의미를 더 명확하게 하기 위해 abstract 를 붙이는 것이 더 낫다. +만약 static만 있는 클래스라면 인스턴스화 할 필요가 없으므로 +의미를 더 명확하게 하기 위해 abstract 를 붙이는 것이 더 낫다. 코드의 가독성을 높이고 유지보수성을 높이는데 기여한다. abstract를 붙이고 인스턴화를 시도하면 컴파일 에러가 발생한다. @@ -39,68 +40,75 @@ void main() { print("Max Int: $maxInt"); print("Overflow Int: $overflowInt"); // Should output: -9223372036854775808 -} ---------------------------------- - -Max Int: 9223372036854775807 -Overflow Int: -9223372036854775808 +}------------------------ +-- +-- +-- +-- +- + +Max +Int: 9223372036854775807 +Overflow +Int: - +9223372036854775808 ``` -이 범위에서 최대값에 1을 더하면 메모리에서 비트가 넘치면서, + +이 범위에서 최대값에 1을 더하면 메모리에서 비트가 넘치면서, 2진수로 표현할 때 첫 번째 비트가 최솟값을 나타내는 비트로 바뀌게 됩니다. 따라서, 9223372036854775807 + 1 은 −9223372036854775808가 됩니다. 이 현상을 오버플로우라고 합니다. key 같은 경우는 직접 올리지 말자 / 로컬 파일로 관리하면 좋다 -- 플러터에서는 flutter_dotenv 패키지를 이용해서 하면 편하다 +- 플러터에서는 flutter_dotenv 패키지를 이용해서 하면 편하다 -재귀 호출 - 자기 자신을 계속 호출해서 메모리에 쌓이다가 - return 을 받으면 한번에 다 돌려줘서 터지는? 경우가 있어서 주의해야 한다 +재귀 호출 - 자기 자신을 계속 호출해서 메모리에 쌓이다가 +return 을 받으면 한번에 다 돌려줘서 터지는? 경우가 있어서 주의해야 한다 꼬리 재귀 - 재귀 호출을 하면서 계속해서 메모리에 쌓이는 것을 방지하기 위해서 - return을 받으면서 계속해서 돌려주는 방식으로 메모리를 적게 사용할 수 있다 - dart는 꼬리 재귀를 지원하지 않는다 +return을 받으면서 계속해서 돌려주는 방식으로 메모리를 적게 사용할 수 있다 +dart는 꼬리 재귀를 지원하지 않는다 좋은 코드를 위해 의식해야 하는 6가지 코드 원칙 - DRY : Don't Repeat Yourself (중복을 피하라) - 1. 중복 코드를 제거하자(메소드로 분리하자) - + 1. 중복 코드를 제거하자(메소드로 분리하자) + - PIE : Program to an Intetly, and Expressively (명확하고 표현력 있게 프로그래밍 하라) - 1. 코드를 읽는 사람이 이해하기 쉽게 작성 - 2. 쉬운 이름을 사용하자 - 3. 컨벤션을 따르자 - 4. 매직 넘버에 이름을 붙이자(숫자를 직접 사용하지 말고 이름을 붙여서 사용) + 1. 코드를 읽는 사람이 이해하기 쉽게 작성 + 2. 쉬운 이름을 사용하자 + 3. 컨벤션을 따르자 + 4. 매직 넘버에 이름을 붙이자(숫자를 직접 사용하지 말고 이름을 붙여서 사용) - SRP : Single Responsibility Principle (단일 책임 원칙) - 1. 클래스는 하나의 책임만 가져야 한다 (단일 책임 원칙) - 2. 에러 수정 시 다른 클래스에 영향을 주지 않도록 한다, 그 클래스만 수정하면 되게 하자 - 3. 클래스 분리가 너무 많아도 오히려 관리가 어려울 수 있다 (적당히) + 1. 클래스는 하나의 책임만 가져야 한다 (단일 책임 원칙) + 2. 에러 수정 시 다른 클래스에 영향을 주지 않도록 한다, 그 클래스만 수정하면 되게 하자 + 3. 클래스 분리가 너무 많아도 오히려 관리가 어려울 수 있다 (적당히) - OCP : Open/Closed Principle (개방-폐쇄 원칙) - 1. 확장에는 열려있고 변경에는 닫혀 있어야 한다 (개방-폐쇄 원칙) - 2. 새로운 기능이 추가되어도 기존 코드를 수정하지 않고 확장할 수 있게 하자 - 3. 인터페이스를 사용하면 쉽게 확장이 가능하다 - 4. 상속을 사용하면 확장이 어렵다 - 5. String 상속 금지이므로 확장이 어렵다 - 6. Iterable, Comparator 등을 사용하면 확장이 쉽다 + 1. 확장에는 열려있고 변경에는 닫혀 있어야 한다 (개방-폐쇄 원칙) + 2. 새로운 기능이 추가되어도 기존 코드를 수정하지 않고 확장할 수 있게 하자 + 3. 인터페이스를 사용하면 쉽게 확장이 가능하다 + 4. 상속을 사용하면 확장이 어렵다 + 5. String 상속 금지이므로 확장이 어렵다 + 6. Iterable, Comparator 등을 사용하면 확장이 쉽다 - SDP : Stable Dependencies Principle (안정된 의존성 원칙) - 1. 안정된 클래스는 변경되지 않아야 한다 - 2. 안정된 클래스는 다른 클래스에 의존하면 안된다 - 3. 안정된 클래스는 인터페이스에 의존해야 한다 - 4. 안정된 클래스는 구체 클래스에 의존하면 안된다(생성자가 변하거나 할 수 있으니까) - -- ADP : Acyclic Dependencies Principle (비순환 의존성 원칙) - 1. 의존성 비순환 원칙은 순환 의존성을 피해야 한다 - 2. 순환 의존성은 코드를 이해하기 어렵게 만든다 - 3. 순환 의존성은 테스트하기 어렵게 만든다 - 4. 순환 의존성은 코드를 변경하기 어렵게 만든다 - 5. 순환 의존성은 코드를 확장하기 어렵게 만든다 - 6. 순환 의존성은 코드를 재사용하기 어렵게 만든다 - - + 1. 안정된 클래스는 변경되지 않아야 한다 + 2. 안정된 클래스는 다른 클래스에 의존하면 안된다 + 3. 안정된 클래스는 인터페이스에 의존해야 한다 + 4. 안정된 클래스는 구체 클래스에 의존하면 안된다(생성자가 변하거나 할 수 있으니까) + +- ADP : Acyclic Dependencies Principle (비순환 의존성 원칙) + 1. 의존성 비순환 원칙은 순환 의존성을 피해야 한다 + 2. 순환 의존성은 코드를 이해하기 어렵게 만든다 + 3. 순환 의존성은 테스트하기 어렵게 만든다 + 4. 순환 의존성은 코드를 변경하기 어렵게 만든다 + 5. 순환 의존성은 코드를 확장하기 어렵게 만든다 + 6. 순환 의존성은 코드를 재사용하기 어렵게 만든다 설계원칙 : SOLID + - 단일 책임 원칙(Single Responsibility Principle) - 개방-폐쇄 원칙(Open-Closed Principle) - 리스코프 치환 원칙(Liskov Substitution Principle) @@ -108,37 +116,103 @@ key 같은 경우는 직접 올리지 말자 / 로컬 파일로 관리하면 좋 - 의존 역전 원칙(Dependency Inversion Principle) 상속 = 확장 / 변경 = 수정 + 1. 단일책임원칙 : 클래스는 하나의 책임만 가져야 한다 - 외부 객체는 생성자로 주입받아라 - (Slime, goblin, Character 클래스를 분리하자) + (Slime, goblin, Character 클래스를 분리하자) 2. 개방폐쇄원칙 : 확장에는 열려있고 변경에는 닫혀 있어야 한다 - (Slime, goblin 각각 공격하지 말고 Character로 공격하게 하자) 인터페이스를 파라미터로 받으면 수정하지 않아도 기능 확장(적용)이 가능하다 3. 리스코프치환원칙 : 자식클래스는 부모클래스에서 가능한 행위를 수행할 수 있어야 한다 (is - a 원칙) - (Slime, goblin이 Character를 상속받아서 공격을 할 수 있게 하자) -4. 인터페이스분리원칙 : 클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안된다 - (인터페이스 1개에 모든 기능을 넣지 말고, 기능별로 나눠서 사용하자[attackble, moveable, flyable, runable, swimable, jumpable]) + (Slime, goblin이 Character를 상속받아서 공격을 할 수 있게 하자) +4. 인터페이스분리원칙 : 클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안된다 + (인터페이스 1개에 모든 기능을 넣지 말고, 기능별로 나눠서 + 사용하자[attackble, moveable, flyable, runable, swimable, jumpable]) 5. 의존관계 역전원칙 : 추상화에 의존해야 하며 구체화에 의존하면 안된다 (메딕 캐릭터가 특정 객체를 파라미터로 받지 말고 인터페이스를 받아서 사용하게 하자[Healable interface 구현체를 받도록 하는것]) - - 디자인 패턴 + - software design pattern : 소프트웨어 설계시 특정 문맥에서 공통적으로 자주 발생하는 문제에 대해 재사용 가능한 해결책 - 디자인 패턴의 장점 : 코드의 재사용성, 코드의 유지보수성, 코드의 가독성, 유연성, 확장성 - 디자인 패턴의 종류 : 생성 패턴, 구조 패턴, 행위 패턴 - - 생성 패턴 : 객체 생성에 관련된 패턴(싱글턴 패턴, 팩토리 패턴, 빌더 패턴 등등) - 1. 싱글턴 패턴 : 객체를 하나만 생성하고, 이후에 생성된 객체를 리턴하는 패턴(1개의 인스턴스가 공유된다) + - 생성 패턴 : 객체 생성에 관련된 패턴(싱글턴 패턴, 팩토리 패턴, 빌더 패턴 등등) + 1. 싱글턴 패턴 : 객체를 하나만 생성하고, 이후에 생성된 객체를 리턴하는 패턴(1개의 인스턴스가 공유된다) + 캐시나 공유데이터, 처리의 효율화에 등에 사용하는 패턴* + +*** 싱글턴 패턴에서 팩토리 생성자가 필요한 이유? + +* 단일 인스턴스 보장: + +팩토리 생성자는 객체의 생성과정을 완전히 제어할 수 있습니다. 팩토리 생성자를 사용하면 클래스의 기존 인스턴스가 반환되도록 할 수 있습니다. +이는 새 인스턴스를 생성하지 않고, 이미 존재하는 인스턴스를 반환하여 메모리 사용을 최적화하고 상태의 일관성을 유지합니다. + +* 지연 초기화(lazy initialization): + +팩토리 생성자는 클래스가 처음 요청될 때까지 인스턴스를 생성하지 않는 지연 초기화를 지원할 수 있습니다. +이렇게 하면 불필요한 메모리 소비를 방지하고 성능을 개선할 수 있습니다. + +* 상속과 다형성 지원: + +팩토리 생성자를 사용하면 상속된 클래스에서도 싱글턴 패턴을 구현할 수 있습니다. +이를 통해 다형성을 지원하는 동시에 싱글턴 인스턴스를 관리할 수 있습니다. + +* 의존성 주입 및 초기화 논리 포함 가능: + +팩토리 생성자는 인스턴스를 반환할 때 특정 초기화 로직을 포함하거나 의존성을 주입할 수 있는 유연성을 제공합니다. +다트에서 팩토리 생성자를 사용한 싱글턴 패턴 예제 + + ```dart + + +class Singleton { +// Singleton 인스턴스를 저장할 정적 변수 + static final Singleton _instance = Singleton._internal(); + +// 프라이빗 생성자 (internal 사용은 명시적이진 않지만, 관례적으로 내부 생성자를 의미) + Singleton._internal(); + +// 팩토리 생성자 + factory Singleton() { + return _instance; + } + +// Singleton 클래스의 다른 메서드들 + void doSomething() { + print("Singleton instance is working!"); + } +} + +void main() { + Singleton s1 = Singleton(); + Singleton s2 = Singleton(); + + print(s1 == s2); // true + s1.doSomething(); +} + + + ``` + +정적 변수 _instance: 싱글턴 인스턴스를 저장하는 정적 변수를 선언합니다. 이 변수는 클래스 수준에서 단 하나만 존재합니다. +프라이빗 생성자 Singleton._internal(): 외부에서 직접 호출할 수 없는 프라이빗 생성자를 정의하여, 클래스의 인스턴스가 직접 생성되지 않도록 합니다. +팩토리 생성자: factory 키워드를 사용하여 팩토리 생성자를 정의합니다. 이 생성자는 인스턴스가 요청될 때마다 기존의 _instance를 반환합니다. +메서드 doSomething: 싱글턴 클래스가 수행할 수 있는 예제 메서드를 정의했습니다. +메인 함수: 두 개의 Singleton 인스턴스를 요청했을 때, 동일한 인스턴스임을 확인할 수 있습니다. print(s1 == s2)는 true를 출력합니다. + 2. 팩토리 패턴 : 객체를 생성하는 인터페이스를 정의하고, 이를 구현한 클래스에서 객체를 생성하는 패턴 - - 구조 패턴 : 클래스나 객체를 조합해 더 큰 구조를 만드는 패턴 (데커레이터 패턴, 퍼사드 패턴 등등) - 1. 데커레이터 패턴 : 객체에 추가적인 요소를 동적으로 추가하는 패턴 - 2. 퍼사드 패턴 : 복잡한 서브시스템을 간단하게 제공하는 인터페이스를 제공하는 패턴(Repository 패턴) - 3. 이터레이터 패턴 : 반복 구조 객체를 통해 요소를 순차적으로 접근하는 패턴 - - 행위 패턴 : 객체나 클래스 사이의 알고리즘과 책임 분배에 관련된 패턴 (Strategy Pattern(전략패턴), 이터레이터 패턴, 옵서버 패턴 등등) - 1. 전략 패턴 : 객체의 상태 변화를 관찰하고, 상태가 변경될 때 자동으로 알림을 받아서 업데이트할 수 있도록 하는 디자인 패턴입니다. - 이 패턴은 일대다(one-to-many) 의존성을 정의합니다. - 2. 옵서버 패턴 : 옵저버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. - 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 발행/구독 모델로 알려져 있기도 하다. (예: 콜백함수) - 3. 이터레이터 패턴 : 컬렉션(예: 리스트, 맵, 집합 등) 요소를 하나씩 순차적으로 접근하는 방법을 제공하는 디자인 패턴입니다. - 이 패턴을 사용하면 컬렉션의 내부 구조를 노출하지 않고도 그 요소들을 탐색할 수 있습니다. - - Iterable과 Iterator의 구조 - - Iterable: 컬렉션을 반복할 수 있는 인터페이스로, iterator라는 getter를 제공합니다. 이 getter는 Iterator를 반환합니다. - - Iterator: Iterable 컬렉션의 요소를 탐색하기 위한 인터페이스로, moveNext() 메서드를 통해 다음 요소로 이동하고, current를 통해 현재 요소에 접근할 수 있습니다. \ No newline at end of file + +- 구조 패턴 : 클래스나 객체를 조합해 더 큰 구조를 만드는 패턴 (데커레이터 패턴, 퍼사드 패턴 등등) + 1. 데커레이터 패턴 : 객체에 추가적인 요소를 동적으로 추가하는 패턴 + 2. 퍼사드 패턴 : 복잡한 서브시스템을 간단하게 제공하는 인터페이스를 제공하는 패턴(Repository 패턴) + 3. 이터레이터 패턴 : 반복 구조 객체를 통해 요소를 순차적으로 접근하는 패턴 +- 행위 패턴 : 객체나 클래스 사이의 알고리즘과 책임 분배에 관련된 패턴 (Strategy Pattern(전략패턴), 이터레이터 패턴, 옵서버 패턴 등등) + 1. 전략 패턴 : 객체의 상태 변화를 관찰하고, 상태가 변경될 때 자동으로 알림을 받아서 업데이트할 수 있도록 하는 디자인 패턴입니다. + 이 패턴은 일대다(one-to-many) 의존성을 정의합니다. + 2. 옵서버 패턴 : 옵저버 패턴(observer pattern)은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 + 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. + 주로 분산 이벤트 핸들링 시스템을 구현하는 데 사용된다. 발행/구독 모델로 알려져 있기도 하다. (예: 콜백함수) + 3. 이터레이터 패턴 : 컬렉션(예: 리스트, 맵, 집합 등) 요소를 하나씩 순차적으로 접근하는 방법을 제공하는 디자인 패턴입니다. + 이 패턴을 사용하면 컬렉션의 내부 구조를 노출하지 않고도 그 요소들을 탐색할 수 있습니다. + - Iterable과 Iterator의 구조 + - Iterable: 컬렉션을 반복할 수 있는 인터페이스로, iterator라는 getter를 제공합니다. 이 getter는 Iterator를 반환합니다. + - Iterator: Iterable 컬렉션의 요소를 탐색하기 위한 인터페이스로, moveNext() 메서드를 통해 다음 요소로 이동하고, current를 통해 현재 요소에 + 접근할 수 있습니다. \ No newline at end of file From 1b4fa84b6d41b9919e2a9e76a5fce242c40ba1ad Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Wed, 10 Jul 2024 21:10:40 +0900 Subject: [PATCH 08/20] =?UTF-8?q?feat:=20flutter=2001=20=EA=B3=BC=EC=A0=9C?= =?UTF-8?q?=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ingridentItem/model/ingredient.dart | 16 +++ .../component/Ingredient_item.dart | 64 +++++++++ .../presentation/main_screen.dart | 35 +++++ .../lib/01_widget/landmark_card/landmark.dart | 22 ++++ .../lib/flutter_learn_01.md | 15 +++ project/stop_watch/lib/stop_watch_screen.dart | 123 ++++++++++++++++++ 6 files changed, 275 insertions(+) create mode 100644 project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.dart create mode 100644 project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart create mode 100644 project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/main_screen.dart create mode 100644 project/learn_flutter_togerther/lib/01_widget/landmark_card/landmark.dart create mode 100644 project/learn_flutter_togerther/lib/flutter_learn_01.md create mode 100644 project/stop_watch/lib/stop_watch_screen.dart diff --git a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.dart b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.dart new file mode 100644 index 0000000..d2632e2 --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.dart @@ -0,0 +1,16 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'ingredient.freezed.dart'; + +part 'ingredient.g.dart'; + +@freezed +class Ingredient with _$Ingredient { + const factory Ingredient({ + required String name, + required String imageUrl, + required String weight, + }) = _Ingredient; + + factory Ingredient.fromJson(Map json) => _$IngredientFromJson(json); +} \ No newline at end of file diff --git a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart new file mode 100644 index 0000000..14a3acb --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; + +import '../../model/ingredient.dart'; + +class IngredientItem extends StatelessWidget { + final Ingredient ingredient; + + const IngredientItem({ + super.key, + required this.ingredient, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), + child: Container( + width: double.infinity, + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.grey[350], + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(15), + child: Image.network( + ingredient.imageUrl, + ), + ), + const SizedBox( + width: 25, + ), + Text( + style: const TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + ), + ingredient.name, + ), + const Spacer(), + Text( + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, + color: Colors.black26 + ), + ingredient.weight, + + ), + ], + ), + ), + ), + ), + ], + ); + } +} diff --git a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/main_screen.dart b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/main_screen.dart new file mode 100644 index 0000000..ee95058 --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/main_screen.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +import '../model/ingredient.dart'; +import 'component/Ingredient_item.dart'; + +class MainScreen extends StatefulWidget { + const MainScreen({super.key}); + + + @override + State createState() => _MainScreenState(); +} +class _MainScreenState extends State { + final ingredient = const Ingredient( + name: 'Apple', + imageUrl: + 'https://media.istockphoto.com/id/184276818/ko/%EC%82%AC%EC%A7%84/%EB%A0%88%EB%93%9C-%EC%82%AC%EA%B3%BC%EB%82%98%EB%AC%B4.jpg?s=2048x2048&w=is&k=20&c=ha7OqiGpi8QruIPKcU6rix1-KN_fm210KTHjTFRb4Xk=', + weight: '500g', + ); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: Column( + children: [ + const Text('여기는 mainScreen'), + IngredientItem( + ingredient: ingredient, + ), + ], + ), + ); + } +} diff --git a/project/learn_flutter_togerther/lib/01_widget/landmark_card/landmark.dart b/project/learn_flutter_togerther/lib/01_widget/landmark_card/landmark.dart new file mode 100644 index 0000000..e192758 --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/landmark_card/landmark.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +class LandmarkCard extends StatelessWidget { + const LandmarkCard({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Image.network('https://picsum.photos/250?image=9'), + Text(''), + Row( + children: [ + + ], + ), + ], + ), + ); + } +} diff --git a/project/learn_flutter_togerther/lib/flutter_learn_01.md b/project/learn_flutter_togerther/lib/flutter_learn_01.md new file mode 100644 index 0000000..29ceb00 --- /dev/null +++ b/project/learn_flutter_togerther/lib/flutter_learn_01.md @@ -0,0 +1,15 @@ + stateless widget에서 +gesturedetector, inkwell 같은 걸로 활용하지 말자 + - 재사용성이 떨어지고, 화면 이동은 되고, + +=> .call 메서드를 통해서 이벤트를 돌려주자 + +rule!! +1. 데이터가 바꿨어? 생성자를 통해서 데이터를 입력 +2. 이벤트가 발생했어? .call 메서드를 통해서 이벤트를 돌려줘 + +stateless에서 상태를 가지게 되면, + +test 코드 +1. MaterialApp - Scaffold - body - widget 까지는 필요하다 +2. widget을 테스트할때는 widget을 테스트하는게 아니라, widget을 통해서 이벤트를 돌려주는 것을 테스트해야 한다 \ No newline at end of file diff --git a/project/stop_watch/lib/stop_watch_screen.dart b/project/stop_watch/lib/stop_watch_screen.dart new file mode 100644 index 0000000..95a45db --- /dev/null +++ b/project/stop_watch/lib/stop_watch_screen.dart @@ -0,0 +1,123 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +class StopWatchScreen extends StatefulWidget { + const StopWatchScreen({super.key}); + + @override + State createState() => _StopWatchScreenState(); +} + +class _StopWatchScreenState extends State { + Timer? _timer; + + int _time = 0; + bool _isRunning = false; + + List _lapTimes = []; + + void _clickButton() { + _isRunning = !_isRunning; + + if (_isRunning) { + _start(); + } else { + _pause(); + } + } + + void _start() { + _timer = Timer.periodic(Duration(milliseconds: 10), (timer) { + setState(() { + _time++; + }); + }); + } + + void _pause() { + _timer?.cancel(); + } + + @override + void dispose() { + _timer?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + int sec = _time ~/ 100; + String hundredth = '${_time % 100}'.padLeft(2,'0'); + + return Scaffold( + appBar: AppBar( + title: const Text('stop watch'), + ), + body: Column( + children: [ + const SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + '$sec', + style: TextStyle(fontSize: 50), + ), + Text('$hundredth'), + ], + ), + SizedBox( + width: 100, + height: 200, + child: ListView( + children: [ + Text('111'), + Text('111'), + Text('111'), + Text('111'), + Text('111'), + Text('111'), + Text('111'), + Text('111'), + Text('111'), + ], + ), + ), + const Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FloatingActionButton( + backgroundColor: Colors.orange, + onPressed: () {}, + child: const Icon(Icons.refresh), + ), + FloatingActionButton( + onPressed: () { + setState(() { + _clickButton(); + }); + }, + child: _isRunning + ? const Icon(Icons.pause) + : const Icon(Icons.play_arrow), + ), + FloatingActionButton( + backgroundColor: Colors.green, + onPressed: () {}, + child: const Icon(Icons.add), + ), + ], + ), + const SizedBox( + height: 30, + ), + ], + ), + ); + } +} From 80b7b4661331be55eac571241cb4b8a9b427b8b2 Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Thu, 11 Jul 2024 01:02:48 +0900 Subject: [PATCH 09/20] =?UTF-8?q?feat:=20flutter=2001=20=EA=B3=BC=EC=A0=9C?= =?UTF-8?q?=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/creator_profile_item.dart | 0 .../presentation/main_screen.dart | 20 ++ .../model/ingredient.freezed.dart | 188 ++++++++++++++++++ .../ingridentItem/model/ingredient.g.dart | 21 ++ 4 files changed, 229 insertions(+) create mode 100644 project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/component/creator_profile_item.dart create mode 100644 project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/main_screen.dart create mode 100644 project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.freezed.dart create mode 100644 project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.g.dart diff --git a/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/component/creator_profile_item.dart b/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/component/creator_profile_item.dart new file mode 100644 index 0000000..e69de29 diff --git a/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/main_screen.dart b/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/main_screen.dart new file mode 100644 index 0000000..2269303 --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/main_screen.dart @@ -0,0 +1,20 @@ +import 'package:flutter/cupertino.dart'; + +class CreatorProfile extends StatelessWidget { + const CreatorProfile({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Container( + child: Row( + children: [ + + ], + ), + ) + ], + ); + } +} diff --git a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.freezed.dart b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.freezed.dart new file mode 100644 index 0000000..2ede3ce --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.freezed.dart @@ -0,0 +1,188 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'ingredient.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +Ingredient _$IngredientFromJson(Map json) { + return _Ingredient.fromJson(json); +} + +/// @nodoc +mixin _$Ingredient { + String get name => throw _privateConstructorUsedError; + String get imageUrl => throw _privateConstructorUsedError; + String get weight => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $IngredientCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $IngredientCopyWith<$Res> { + factory $IngredientCopyWith( + Ingredient value, $Res Function(Ingredient) then) = + _$IngredientCopyWithImpl<$Res, Ingredient>; + @useResult + $Res call({String name, String imageUrl, String weight}); +} + +/// @nodoc +class _$IngredientCopyWithImpl<$Res, $Val extends Ingredient> + implements $IngredientCopyWith<$Res> { + _$IngredientCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? imageUrl = null, + Object? weight = null, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + imageUrl: null == imageUrl + ? _value.imageUrl + : imageUrl // ignore: cast_nullable_to_non_nullable + as String, + weight: null == weight + ? _value.weight + : weight // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$IngredientImplCopyWith<$Res> + implements $IngredientCopyWith<$Res> { + factory _$$IngredientImplCopyWith( + _$IngredientImpl value, $Res Function(_$IngredientImpl) then) = + __$$IngredientImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String name, String imageUrl, String weight}); +} + +/// @nodoc +class __$$IngredientImplCopyWithImpl<$Res> + extends _$IngredientCopyWithImpl<$Res, _$IngredientImpl> + implements _$$IngredientImplCopyWith<$Res> { + __$$IngredientImplCopyWithImpl( + _$IngredientImpl _value, $Res Function(_$IngredientImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? imageUrl = null, + Object? weight = null, + }) { + return _then(_$IngredientImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + imageUrl: null == imageUrl + ? _value.imageUrl + : imageUrl // ignore: cast_nullable_to_non_nullable + as String, + weight: null == weight + ? _value.weight + : weight // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$IngredientImpl implements _Ingredient { + const _$IngredientImpl( + {required this.name, required this.imageUrl, required this.weight}); + + factory _$IngredientImpl.fromJson(Map json) => + _$$IngredientImplFromJson(json); + + @override + final String name; + @override + final String imageUrl; + @override + final String weight; + + @override + String toString() { + return 'Ingredient(name: $name, imageUrl: $imageUrl, weight: $weight)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IngredientImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.imageUrl, imageUrl) || + other.imageUrl == imageUrl) && + (identical(other.weight, weight) || other.weight == weight)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, name, imageUrl, weight); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$IngredientImplCopyWith<_$IngredientImpl> get copyWith => + __$$IngredientImplCopyWithImpl<_$IngredientImpl>(this, _$identity); + + @override + Map toJson() { + return _$$IngredientImplToJson( + this, + ); + } +} + +abstract class _Ingredient implements Ingredient { + const factory _Ingredient( + {required final String name, + required final String imageUrl, + required final String weight}) = _$IngredientImpl; + + factory _Ingredient.fromJson(Map json) = + _$IngredientImpl.fromJson; + + @override + String get name; + @override + String get imageUrl; + @override + String get weight; + @override + @JsonKey(ignore: true) + _$$IngredientImplCopyWith<_$IngredientImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.g.dart b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.g.dart new file mode 100644 index 0000000..0ff2eec --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/model/ingredient.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ingredient.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$IngredientImpl _$$IngredientImplFromJson(Map json) => + _$IngredientImpl( + name: json['name'] as String, + imageUrl: json['imageUrl'] as String, + weight: json['weight'] as String, + ); + +Map _$$IngredientImplToJson(_$IngredientImpl instance) => + { + 'name': instance.name, + 'imageUrl': instance.imageUrl, + 'weight': instance.weight, + }; From e98e723012e32c004b8031c836f6725e4149b40d Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 07:34:51 +0900 Subject: [PATCH 10/20] =?UTF-8?q?feat:=20240711=20foodRecipe=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=5FbigButton?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/creator_profile_item.dart | 8 + .../component/Ingredient_item.dart | 1 + .../component/recipe_card_item.dart | 38 ++++ .../presentation/main_screen_recipe.dart | 14 ++ .../02_material_design/model/food_recipe.dart | 17 ++ .../model/food_recipe.freezed.dart | 188 ++++++++++++++++++ .../model/food_recipe.g.dart | 21 ++ .../presentation/component/big_button.dart | 37 ++++ .../component/sign_in/sign_in_screen.dart | 19 ++ .../component/sign_up/sign_up_screen.dart | 122 ++++++++++++ .../component/ui/color_styles.dart | 30 +++ .../component/ui/text_styles.dart | 115 +++++++++++ .../presentation/component/ui/theme.dart | 0 .../presentation/component/ui/util.dart | 0 .../presentation/main_food_recipe.dart | 16 ++ 15 files changed, 626 insertions(+) create mode 100644 project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/component/recipe_card_item.dart create mode 100644 project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/main_screen_recipe.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/color_styles.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/text_styles.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/theme.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/util.dart create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/main_food_recipe.dart diff --git a/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/component/creator_profile_item.dart b/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/component/creator_profile_item.dart index e69de29..414787a 100644 --- a/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/component/creator_profile_item.dart +++ b/project/learn_flutter_togerther/lib/01_widget/creatorprofile/presentation/component/creator_profile_item.dart @@ -0,0 +1,8 @@ +class CreatorProfileItem extends StatelessWidget { + const CreatorProfileItem({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart index 14a3acb..792ce52 100644 --- a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart +++ b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart @@ -33,6 +33,7 @@ class IngredientItem extends StatelessWidget { ingredient.imageUrl, ), ), + const SizedBox( width: 25, ), diff --git a/project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/component/recipe_card_item.dart b/project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/component/recipe_card_item.dart new file mode 100644 index 0000000..23b87a8 --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/component/recipe_card_item.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +class RecipeCardItem extends StatelessWidget { + const RecipeCardItem({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Column( + children: [ + Stack( + children: [ + // ClipRRect( + // borderRadius: BorderRadius.circular(15), + ClipRRect( + borderRadius: BorderRadius.circular(15), + child: Container( + width: double.infinity, + height: 200, + color: Colors.grey, + ), + ), + Positioned( + top: 10, + right: 100, + child: Container( + width: 50, + height: 50, + color: Colors.black26, + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/main_screen_recipe.dart b/project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/main_screen_recipe.dart new file mode 100644 index 0000000..9c483cb --- /dev/null +++ b/project/learn_flutter_togerther/lib/01_widget/recipeCardWidget/presentation/main_screen_recipe.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +class MainScreenRecipe extends StatelessWidget { + const MainScreenRecipe({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Text('Main Screen Recipe'), + ), + ); + } +} diff --git a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart new file mode 100644 index 0000000..7798b43 --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart @@ -0,0 +1,17 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'food_recipe.freezed.dart'; + +part 'food_recipe.g.dart'; + +@freezed +class FoodRecipe with _$FoodRecipe { + const factory FoodRecipe({ + required String name, + required String email, + required String password, + + }) = _FoodRecipe; + + factory FoodRecipe.fromJson(Map json) => _$FoodRecipeFromJson(json); +} \ No newline at end of file diff --git a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart new file mode 100644 index 0000000..be91222 --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart @@ -0,0 +1,188 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'food_recipe.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +FoodRecipe _$FoodRecipeFromJson(Map json) { + return _FoodRecipe.fromJson(json); +} + +/// @nodoc +mixin _$FoodRecipe { + String get name => throw _privateConstructorUsedError; + String get email => throw _privateConstructorUsedError; + String get password => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $FoodRecipeCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $FoodRecipeCopyWith<$Res> { + factory $FoodRecipeCopyWith( + FoodRecipe value, $Res Function(FoodRecipe) then) = + _$FoodRecipeCopyWithImpl<$Res, FoodRecipe>; + @useResult + $Res call({String name, String email, String password}); +} + +/// @nodoc +class _$FoodRecipeCopyWithImpl<$Res, $Val extends FoodRecipe> + implements $FoodRecipeCopyWith<$Res> { + _$FoodRecipeCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? email = null, + Object? password = null, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$FoodRecipeImplCopyWith<$Res> + implements $FoodRecipeCopyWith<$Res> { + factory _$$FoodRecipeImplCopyWith( + _$FoodRecipeImpl value, $Res Function(_$FoodRecipeImpl) then) = + __$$FoodRecipeImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String name, String email, String password}); +} + +/// @nodoc +class __$$FoodRecipeImplCopyWithImpl<$Res> + extends _$FoodRecipeCopyWithImpl<$Res, _$FoodRecipeImpl> + implements _$$FoodRecipeImplCopyWith<$Res> { + __$$FoodRecipeImplCopyWithImpl( + _$FoodRecipeImpl _value, $Res Function(_$FoodRecipeImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? email = null, + Object? password = null, + }) { + return _then(_$FoodRecipeImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$FoodRecipeImpl implements _FoodRecipe { + const _$FoodRecipeImpl( + {required this.name, required this.email, required this.password}); + + factory _$FoodRecipeImpl.fromJson(Map json) => + _$$FoodRecipeImplFromJson(json); + + @override + final String name; + @override + final String email; + @override + final String password; + + @override + String toString() { + return 'FoodRecipe(name: $name, email: $email, password: $password)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FoodRecipeImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.email, email) || other.email == email) && + (identical(other.password, password) || + other.password == password)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, name, email, password); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$FoodRecipeImplCopyWith<_$FoodRecipeImpl> get copyWith => + __$$FoodRecipeImplCopyWithImpl<_$FoodRecipeImpl>(this, _$identity); + + @override + Map toJson() { + return _$$FoodRecipeImplToJson( + this, + ); + } +} + +abstract class _FoodRecipe implements FoodRecipe { + const factory _FoodRecipe( + {required final String name, + required final String email, + required final String password}) = _$FoodRecipeImpl; + + factory _FoodRecipe.fromJson(Map json) = + _$FoodRecipeImpl.fromJson; + + @override + String get name; + @override + String get email; + @override + String get password; + @override + @JsonKey(ignore: true) + _$$FoodRecipeImplCopyWith<_$FoodRecipeImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart new file mode 100644 index 0000000..7d8dfc8 --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'food_recipe.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$FoodRecipeImpl _$$FoodRecipeImplFromJson(Map json) => + _$FoodRecipeImpl( + name: json['name'] as String, + email: json['email'] as String, + password: json['password'] as String, + ); + +Map _$$FoodRecipeImplToJson(_$FoodRecipeImpl instance) => + { + 'name': instance.name, + 'email': instance.email, + 'password': instance.password, + }; diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart new file mode 100644 index 0000000..0479d6a --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/component/ui/color_styles.dart'; + +class BigButton extends StatefulWidget { + final void Function() onTap; + + final String title; + + const BigButton({ + super.key, + required this.title, + required this.onTap, + }); + + @override + State createState() => _BigButtonState(); +} + +class _BigButtonState extends State { + final bool _isPressed = false; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: widget.onTap, + child: Container( + width: double.infinity, + height: 50, + child: Text('Sign In'), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: _isPressed ? ColorStyles.gray4 : ColorStyles.primary100, + ), + ), + ); + } +} diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart new file mode 100644 index 0000000..950982a --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +import '../big_button.dart'; + +class SignInScreen extends StatelessWidget { + const SignInScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: BigButton( + title: 'Sign In', + onTap: () {}, + ), + ), + ); + } +} diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart new file mode 100644 index 0000000..308246a --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; + +class SignUpScreen extends StatelessWidget { + const SignUpScreen({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 60, + ), + Text( + 'Hello', + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + ), + ), + Text( + 'Welcome Back!', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + SizedBox( + height: 40, + ), + Text('Email'), + SizedBox( + height: 10, + ), + TextField( + decoration: InputDecoration( + hintText: 'Enter Email', + hintStyle: TextStyle( + color: Colors.grey, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + ), + ), + ), + ), + SizedBox( + height: 40, + ), + Text('Enter Password'), + SizedBox( + height: 10, + ), + TextField( + decoration: InputDecoration( + hintText: 'Enter Password', + hintStyle: TextStyle( + color: Colors.grey, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Colors.grey, + ), + ), + ), + ), + SizedBox( + height: 20, + ), + Text('Forgot Password?'), + SizedBox( + height: 20, + ), + Container( + height: 70, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.green, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Sign in', + style: TextStyle( + color: Colors.white, + ), + ), + SizedBox( + width: 50, + ), + Icon( + Icons.arrow_forward, + color: Colors.white, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/color_styles.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/color_styles.dart new file mode 100644 index 0000000..fd33a72 --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/color_styles.dart @@ -0,0 +1,30 @@ +import 'dart:ui'; + +abstract class ColorStyles { + static const Color black = Color(0xFF000000); + static const Color gray1 = Color(0xFF484848); + static const Color gray2 = Color(0xFF797979); + static const Color gray3 = Color(0xFFA9A9A9); + static const Color gray4 = Color(0xFFD9D9D9); + static const Color white = Color(0xFFFFFFFF); + + static const Color primary100 = Color(0xFF129575); + static const Color primary80 = Color(0xFF71B1A1); + static const Color primary60 = Color(0xFFAFD3CA); + static const Color primary40 = Color(0xFFDBEBE7); + static const Color primary20 = Color(0xFFF6FAF9); + + static const Color secondary100 = Color(0xFFFF9C00); + static const Color secondary80 = Color(0xFFFFA61A); + static const Color secondary60 = Color(0xFFFFBA4D); + static const Color secondary40 = Color(0xFFFFCE80); + static const Color secondary20 = Color(0xFFFFE1B3); + + static const Color error = Color(0xFFE94A59); + static const Color warning = Color(0xFF995E00); + + static const Color success = Color(0xFF31B057); + static const Color success10 = Color(0xFFEAF7EE); + + static const Color rating = Color(0xFFFFAD30); +} diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/text_styles.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/text_styles.dart new file mode 100644 index 0000000..ff82728 --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/text_styles.dart @@ -0,0 +1,115 @@ +import 'dart:ui'; + +abstract class TextStyles { + static TextStyle tittleTextBold = TextStyle( + fontFamily: 'Poppins', + fontSize: 50, + fontWeight: FontWeight.bold, + height: 75 / 50, + letterSpacing: 0, + ); + + static TextStyle headerTextBold = TextStyle( + fontFamily: 'Poppins', + fontSize: 30, + fontWeight: FontWeight.bold, + height: 45 / 30, + letterSpacing: 0, + ); + + static TextStyle largeTextBold = TextStyle( + fontFamily: 'Poppins', + fontSize: 20, + fontWeight: FontWeight.bold, + height: 30 / 20, + letterSpacing: 0, + ); + + static TextStyle mediumTextBold = TextStyle( + fontFamily: 'Poppins', + fontSize: 18, + fontWeight: FontWeight.bold, + height: 27 / 18, + letterSpacing: 0, + ); + + static TextStyle normalTextBold = TextStyle( + fontFamily: 'Poppins', + fontSize: 16, + fontWeight: FontWeight.bold, + height: 24 / 16, + letterSpacing: 0, + ); + + static TextStyle smallTextBold = TextStyle( + fontFamily: 'Poppins', + fontSize: 14, + fontWeight: FontWeight.bold, + height: 21 / 14, + letterSpacing: 0, + ); + + static TextStyle smallerTextBold = TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.bold, + height: 17 / 11, + letterSpacing: 0, + ); + + static TextStyle tittleTextRegular = TextStyle( + fontFamily: 'Poppins', + fontSize: 50, + fontWeight: FontWeight.normal, + height: 75 / 50, + letterSpacing: 0, + ); + + static TextStyle headerTextRegular = TextStyle( + fontFamily: 'Poppins', + fontSize: 30, + fontWeight: FontWeight.normal, + height: 45 / 30, + letterSpacing: 0, + ); + + static TextStyle largeTextRegular = TextStyle( + fontFamily: 'Poppins', + fontSize: 20, + fontWeight: FontWeight.normal, + height: 30 / 20, + letterSpacing: 0, + ); + + static TextStyle mediumTextRegular = TextStyle( + fontFamily: 'Poppins', + fontSize: 18, + fontWeight: FontWeight.normal, + height: 27 / 18, + letterSpacing: 0, + ); + + static TextStyle normalTextRegular = TextStyle( + fontFamily: 'Poppins', + fontSize: 16, + fontWeight: FontWeight.normal, + height: 24 / 16, + letterSpacing: 0, + ); + + static TextStyle smallTextRegular = TextStyle( + fontFamily: 'Poppins', + fontSize: 14, + fontWeight: FontWeight.normal, + height: 21 / 14, + letterSpacing: 0, + ); + + static TextStyle smallerTextRegular = TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.normal, + height: 17 / 11, + letterSpacing: 0, + ); +} diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/theme.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/theme.dart new file mode 100644 index 0000000..e69de29 diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/util.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/util.dart new file mode 100644 index 0000000..e69de29 diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/main_food_recipe.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/main_food_recipe.dart new file mode 100644 index 0000000..cca4444 --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/main_food_recipe.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +import 'component/sign_up/sign_up_screen.dart'; + +class MainFoodRecipe extends StatelessWidget { + const MainFoodRecipe({super.key}); + + @override + Widget build(BuildContext context) { + return const Scaffold( + body: Center( + child: SignUpScreen(), + ), + ); + } +} From 8344867954094b7d93bbdbf8caf012f8864d5cc7 Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 07:39:11 +0900 Subject: [PATCH 11/20] =?UTF-8?q?feat:=20240711=20foodRecipe=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=5FSign=20in=20page=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/sign_in/sign_in_screen.dart | 19 ------------------- .../component/sign_up/sign_up_screen.dart | 2 ++ 2 files changed, 2 insertions(+), 19 deletions(-) delete mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart deleted file mode 100644 index 950982a..0000000 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_in/sign_in_screen.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../big_button.dart'; - -class SignInScreen extends StatelessWidget { - const SignInScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: BigButton( - title: 'Sign In', - onTap: () {}, - ), - ), - ); - } -} diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index 308246a..711f4c4 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/component/big_button.dart'; class SignUpScreen extends StatelessWidget { const SignUpScreen({super.key}); @@ -89,6 +90,7 @@ class SignUpScreen extends StatelessWidget { SizedBox( height: 20, ), + BigButton(title: 'Sign in', onTap: () {}), Container( height: 70, decoration: BoxDecoration( From 043f8093a22aaab5bf0e70d419b598333734a6b7 Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 08:04:44 +0900 Subject: [PATCH 12/20] =?UTF-8?q?feat:=20240711=20foodRecipe=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=5FSign=20up=20page=20=EB=82=B4=20sign=20in=20containe?= =?UTF-8?q?r=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/component/big_button.dart | 22 +++++++++++++--- .../component/sign_up/sign_up_screen.dart | 25 ------------------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart index 0479d6a..5947b54 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/ui/color_styles.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/component/ui/text_styles.dart'; class BigButton extends StatefulWidget { + //data final void Function() onTap; final String title; @@ -17,7 +19,8 @@ class BigButton extends StatefulWidget { } class _BigButtonState extends State { - final bool _isPressed = false; + //ui + bool _isPressed = false; @override Widget build(BuildContext context) { @@ -25,12 +28,25 @@ class _BigButtonState extends State { onTap: widget.onTap, child: Container( width: double.infinity, - height: 50, - child: Text('Sign In'), + height: 70, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: _isPressed ? ColorStyles.gray4 : ColorStyles.primary100, ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: Text( + widget.title, + ), + ), + SizedBox( + width: 35, + ), + Icon(Icons.arrow_forward), + ], + ), ), ); } diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index 711f4c4..0fb8d2a 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -91,31 +91,6 @@ class SignUpScreen extends StatelessWidget { height: 20, ), BigButton(title: 'Sign in', onTap: () {}), - Container( - height: 70, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.green, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Sign in', - style: TextStyle( - color: Colors.white, - ), - ), - SizedBox( - width: 50, - ), - Icon( - Icons.arrow_forward, - color: Colors.white, - ), - ], - ), - ), ], ), ), From 6980f54daf1ac7cccd6767cc4e8d7257b3a8806d Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 08:25:09 +0900 Subject: [PATCH 13/20] =?UTF-8?q?fix:=20240711=20foodRecipe=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=5FTextStyles.mediumTextRegular=20=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../asset/faceBookIconButton.png | Bin 0 -> 2947 bytes .../asset/googleIconButton.png | Bin 0 -> 3162 bytes .../02_material_design/model/food_recipe.dart | 2 +- .../model/food_recipe.freezed.dart | 36 +++++++++--------- .../model/food_recipe.g.dart | 4 +- .../presentation/component/big_button.dart | 11 ++++++ 6 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 project/learn_flutter_togerther/asset/faceBookIconButton.png create mode 100644 project/learn_flutter_togerther/asset/googleIconButton.png diff --git a/project/learn_flutter_togerther/asset/faceBookIconButton.png b/project/learn_flutter_togerther/asset/faceBookIconButton.png new file mode 100644 index 0000000000000000000000000000000000000000..6895df826c81dcc1cfc52c7e6cdb6c82a087828a GIT binary patch literal 2947 zcmV-}3w-p6P)<5xBC2D&+8^R7#%^1WQGw%|nq|ffA{z`_lHQSeBph*!3K9#p~z2Kizkd>Z>B*&QzfgVUFX-S2Yn_aCP9ofgA#hCOD~#BS}J!9XsZ%TenUVIWjWhq9eM_FSvK_UdZn)Sg;`EeQRrLK;kc5 zx)d&7zFc#iM3YdPQ8N;3Ro3&*%paHBoHuWt`|#mICzHu|Po6w+JkN8VKYt#zfex`_ zQCq05KPq*kocZ>9am3rP+r!|74Gj%pHk%DdJX5q4kn0q8h<{-8M$rW8IZLI31{^bQ zTr}>^ojcb}r_U$$(Sk0Q=#_Mi3gh|bf}wnoKByO?ucb91u?0#g{_6gZqhXHwvB z3WR&S#|OQX0q+Z4^XJdkDf&34n0j)V@3~9`m?pX}*REajOup_bB+(d?Vt%aM_;I(c&)imI}&!DuW6G4n|5{{8#kSg~To zd$?VsenOCVaP;jXM~-|L7%W`4FiWB_|Ffv#%krfxqP0kiX5;)Nu@q%$VRDq*6=M7Q z`}86hsv*+N8-AYfo;djR|nig+lS56jD$U zE|f(IFL-PiBlve!V}J;6-nw;b`qZgYUs1b5A{BH%c;(8K5E2@Wj*hDK_V!3?=O`_X z2sJWCiOUYT%d4lS=PeMsSJfz>Oa21sdjm_B%cb(}-MemETboOp!BSwF(?YPGyIg`G zvJMRi63V53O9a$?%@Qj>zu$#2O;fb7glZaSH;^W=#q}Jv<(tL@Q*xLi#SuGv`0$%A zOAA+s#XENFc#{mma;2qI3TS#NvnIQ7i-Z*+A`T4$zKnVC8&xNOL~dq^IZPwPAuVJg z36`Ch9tF|Pw2}Et`<5w0f@wW)R|5oYq)2lrQmpN=M5RSg_G#yexyVLToj|4@cVxD$ zE{aR$uZ??6VE*?Fud}KbMDwZ^WEZHF7L5-2j>PT4y{;+~qqoM(A~p`TK`E&ewks*x zJa9*0JKkVcmOX!~L9BpNqEd)R3$#d+!vg~Y4%Io=U@Y9a(5%BHVc^2(jCInD4eEox z{!VRsrB$UDH0Zn$NXE~*-pg%kc;>d^pr-^oMR6nLl-VM!9bvGUL+&(~2lI@Yu4GOZ zqoDrv$6u?Rzif+$t)#6usBD?qT3TGeku6OQ)5Agba~kP{~|B{{*z~_ z8o=7CQ*j^?_H<2&$#vqyi4gu~S%*W6l$s4JZhXPjBr&cOFe$Zk+KxpsQw`$Gg68U9!hfc>ahyU=-$EwEzv?@#)9n9yqrBI;-&fTJ*J2^qhV8`D5P7GTF4yp=1;n+q4eisC18!kI zIb5#c(UPg2=55I=R^@;kwha$LP87w`3dKb$70BUoAWCRDj1;*Rw_9_)RM51fO~HFv zmWaq}$#s}>nD-RvQjb6dNoHfY=qY1A%*}%wwQ_kiQX5TOS0ZA_VW#4-w9jWt0XbZa zjeBpIUJuzk*sx+ooG8*pGG(_^iBF52{qCJTs$=V`dGnCZw(((?bN+X{{wj=-KUFkn z_H;}#JoLI`N7E2Ic~BLg1>E`IZ#!qK_uaocRkcBdE1RFVPbICTP=S;D* zY8ozHyr|>1NSlN{XbanHAhb`*m}NTX3`9G)zTdcUV+V@osTu~S-rl`?J8}3IpsxWq z9N=)xhkGZGB{%X*6UMyMClBOuI-O=zOfWb&c<;uI8+%lZ15@#z63xRPwM-@xkQQTB zhB?Qj#_ORo7`w<982&@CrsC@F@Ba+j#s8=p1w{Gnef#!(#J;l6kkY^wXV!_LY;zu_ z_Qf0okD-PTi`1GmYjlhjBjS!8J-V;ff?Kefyx-N;)q~R#pCSx@Toz*NgS%O9J%Be> zha%>2Sh#Gowa+=w+}!NL0O!4rIqi3McOQjUWKS(DRp`S5Y&1 z1=cR<#d@rt65^t9t78`#iN}Ca27Q6+3{rC#R={8vY`=bsfoOhNQ34!jeE&QcFm&e3 znGa8&K0R)BN18DV^<)$t6;*qCdm!P&b{p|<`)JKF=S?o-EisZVe7ibki`ttY;iA!{ z4U{vGM7O~c06N9(GNw`m3jrmxTd?8j%85=5*-~@0( zp@U38tPUSGk*zK`OU^qI0?fU$c>CEAJN%dVVy4DV1Zd4knY<(0JKo#%?YcrJl`9n# zryI(`bLY<4#3sf}Pxn_!IQ5R>pb;I_CIR9koMA!uh-1e?l>-i%#6a7i69NiT_m9W7 zw)ID|k%XcT0lYN9(9lq@cJ1204koo}u?a8OSrG*)GL9NYl>yisMa=0eIG*L4L6u2} zQC3p9x374-EhN^A2OzcU5EZNaVhbi2>t^h^;mZK@?|A?_IorYxV}QaFlaQ8 zbym8qX25hDj((Uh13-fHNb4OQs&lS@dXVyAx@FP+^3?b|*&(8n=002ovPDHLkV1gQnt$Y9g literal 0 HcmV?d00001 diff --git a/project/learn_flutter_togerther/asset/googleIconButton.png b/project/learn_flutter_togerther/asset/googleIconButton.png new file mode 100644 index 0000000000000000000000000000000000000000..c510290b9339f622a36b7dcc1a03ca59786145ac GIT binary patch literal 3162 zcmV-g45jmlP)30O$HHSpR)XOCRC(R-h-s9LLeG8X~N6 z?#7K9oedi{xIsS4W^^jJ59{gs=(qG8+mo)rx>sL%MUNw6f0!R-mX-%G+3LB+jvezC zEm|bIckd1}XUv$vdS+m!PoHi&cKrBphxaVU@(Mnqyu)@h&u&lOu}$=W7YEi0`sLgG z?r9LRiI<~=qxT$Xbkt#onRovDd8fR*oSk52O#SG6(9y8{D_5>K7cXA)?YwNzc9<3w z6`4NpTll7r)Yk!Aym&DQm-Xw{XAszDg0sEjNRrSUJ9aqJrcE(;G| zcJQ8q5#G18wK+F#-0;Va9UG>Fg@r!L+_`hdDJ?A(=4Y#~xOVND&+m;MJ=*7eWo4yD z;!mDD=}(+E(QutalTe#cy%KB{HuEo-KQ6gBeE4wp=FOWP zfex`_VOuC~KB{H(J@f5)QAFFZ+r!}cBSwtylgXq<;+di?k6fp?L;Sr!Z}gd9GiRxE z(0~)n8yAhc!-frW6NyBuwYAk9HEI+G#sy~t9q6-`B+!oE(b3UkozBiqr=Xx9>~MQ~ zJBf6dvM%!=B_zxvQmK?j!Y53akisj@Y4)Gxx)I$?OWPV1Bkf|&#VRT)VjwV%5srhy zadajQ4#z=wjQ99pEFOUOJzXP5jx;IySkRYpdIjHenJO?%OkXZsxDX5SO#i4Q(avhgSf;ndL+nv&;{ntpFeKy+__6J59c6%2C}Be0{{l934J+w z{rdIS*R5Ok8v5o#;!@-^IG+LoQea9d5b>09*`Cwk;;!?S3Mvrg7#cPNqp>)|EJkA2 ztXcDTNlD4exE(7G5hNZQeQERN&AYq+W5$e0l4#8TB#NYT`4Wq0BhsqbIDbhjMVVTd z93^*^*t)v9EoEh8J0CW&1f>evdHa?vTYlsQXlZFNlE^8DB1W`HlP%UUy`eTHz&#fV zB?hGshmvriEaIpTW5XE1=VXupB0Oi_ym^T|d-m+7c85d?bbx>E+&Lc->Yq7tMrvwm zLam*lv^XNv$Q&guJLE2}wQJWd1+lASkOI178Km!VELkp>%Bxqex>Z$GE^P)&ff-IK z!DjAq34+KvG$cqUmjW&kQ1^qDSOxmM9m+I8(Z&*LXrSFdn$#9IbJ&(|8W&8-VU83> zY}2MqOCFRK9w5doSg>FT8HDA^NU6S{=_$dQ>_#mT7KDg6Gz?f7^Ww`gL;#7L!xVFv zMv6mP$V3vXJ25i~s-0;g^O^Q7Q-}o9p}<`O5IB<}&8bMSw%=t{S_EaEcCMO>Y($0# zbn0&uFO25Jq%2rgX;bOfE^B zx7?ZqI~K_c+FC{S{Z8cY0g+R0i(G6>=YRN<_-LibyswKad|K`Y)Cr-IoIx->5$au_ zSYW3j1IEApB=X|3X`-Vb@w^V9%&Qwjp51WY2-jVpQCc)Q=sQxk3-`K`54^Hcr1l%x ziH(9>fAJYOwzf+?VY`yT%>#E7w&M+E<-q6fs~gezZT+f}7Vob~KA|G52szCCFV(rO z!9=hQ_aFOqrbX07VFDt%US#`zkvIJG^_#<8B1~dm-k(kf0QHopd&!0^(#8=6o7v}1 zgLyE|sOfU!^xK;=pGm}T52xqor)s+LKLVxolbs^hYS?K2?iZn zhE6x|XN51x;k+zMg9MQy9p8<2{57=&=4AYY9unZK19}mU) z-yNmW(tK8)NOUiD{%6(Q@>bNpC-wj7I%1h#K0(YF?rPpeluQsv7!Wp@FgLN&A!gk^rsJv54=WKYCep|M+ z&yzp5SDMFLowsDop|$rUn#6wd7pF7wrW6&(;!hVzF0gHg=&`I(T6(~(>?enFHay}9 znO*(UjI0(A`@O$^U$*`C6?yl17hy*(AC+Av{wS*(z9Y%Pzh%_<;TKCKSCGR|(^5|q z<9YFA{vLrwv8?*Lvb5@3{i;(k=}oC!^ncm-)k%^oxOvbG z1Xr9uYQw4P>KaUkHB;R!+2^yl;;E`7vSQYAQZlNf*RrDvMoaCZFUSu*^P~&}*%X!) zGvaVrGIl0oC77eTC93v(xOg7>z!%I#QGWBnTV_6=zTRlwaUdQUS1F&JSS7Qke8~`< z4+OTfxz{+606qyelh}@?A$am2d4v-FAYj|lQJ+?Z*V4vN_geOZ@Z`Y;14nXRmL4*w zdz4uWdeQvQiDwh59?S9L$Lkzs)JT&I5#Yo#oUFPIa}Ec=aVDh6)ooLdY2u;CVXX*) zkIE1M`g)euAtQa12F7v)uhSpkw`Eq#yfcM;I-!F=I3RQ15@$m8qLEXwc_GpkF*44rJr$J z8hAZS24fdlf#E+CYbvg~y1Ku%wYB|91}PxQFRfm^`Ze~IeTI~Jwm7p)7-gIB0ObV( zgo6-cs3F86K6&zF6Qjk5xUE~at{!Z`Em%!{xpL*owQx(ND8ktABq7Era5o9Ad+^4Z zP{eK=RxStHI>k9qQBjeC0nYmr=5(sIwstFaRL>8Fr3!txfz8e{%a<>&RbqoV%M(Bb zr+L;cscStpPg&xkacg218HvY$QU-m2>kLwJ7*@bw7i_;4VjwCWRFnV*8s9$#1~eQx zbZFP!y?a}O-H~AoLp>RVM@3arQ{!nkvE4>A+&)~h=oC0`;DF0`ON^w8qZkvjMeR+H zaMkGA2HrD}#I(T^06N9(cTDwt6n5R7pdJ|A0+Ne`g@qncim=zz)Re-Klu}|PZEQ$Z zg0p}d3KL`sVomsP5ZUU2v*f&^A;8=_tGAyWvBQ6vuV!lWM1as9eB7(->$QbV5L3 zn*PyGZd-pe8%Zeo;FXn?c?}H>-qfj6Jv*4xro|?_$IhxKP?2%eII0Z5<|txLC&BR~ z=M0K;LX47{>b-qM^X+>O+Yzn9XK*$N9n#5*dHfzPaJ~a`x%2Yn%Smcth6*dOD#no? zRI<nrGLeF~Ri} z`h`KGp02anZRrK~;&AxGL@)p(*o-9qE8xc%giX%lbqXCa%Ki_@%07*qoM6N<$f}y|+ ANdN!< literal 0 HcmV?d00001 diff --git a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart index 7798b43..a753144 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.dart @@ -7,7 +7,7 @@ part 'food_recipe.g.dart'; @freezed class FoodRecipe with _$FoodRecipe { const factory FoodRecipe({ - required String name, + required String title, required String email, required String password, diff --git a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart index be91222..2c65b3d 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.freezed.dart @@ -20,7 +20,7 @@ FoodRecipe _$FoodRecipeFromJson(Map json) { /// @nodoc mixin _$FoodRecipe { - String get name => throw _privateConstructorUsedError; + String get title => throw _privateConstructorUsedError; String get email => throw _privateConstructorUsedError; String get password => throw _privateConstructorUsedError; @@ -36,7 +36,7 @@ abstract class $FoodRecipeCopyWith<$Res> { FoodRecipe value, $Res Function(FoodRecipe) then) = _$FoodRecipeCopyWithImpl<$Res, FoodRecipe>; @useResult - $Res call({String name, String email, String password}); + $Res call({String title, String email, String password}); } /// @nodoc @@ -52,14 +52,14 @@ class _$FoodRecipeCopyWithImpl<$Res, $Val extends FoodRecipe> @pragma('vm:prefer-inline') @override $Res call({ - Object? name = null, + Object? title = null, Object? email = null, Object? password = null, }) { return _then(_value.copyWith( - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable as String, email: null == email ? _value.email @@ -81,7 +81,7 @@ abstract class _$$FoodRecipeImplCopyWith<$Res> __$$FoodRecipeImplCopyWithImpl<$Res>; @override @useResult - $Res call({String name, String email, String password}); + $Res call({String title, String email, String password}); } /// @nodoc @@ -95,14 +95,14 @@ class __$$FoodRecipeImplCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? name = null, + Object? title = null, Object? email = null, Object? password = null, }) { return _then(_$FoodRecipeImpl( - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable + title: null == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable as String, email: null == email ? _value.email @@ -120,13 +120,13 @@ class __$$FoodRecipeImplCopyWithImpl<$Res> @JsonSerializable() class _$FoodRecipeImpl implements _FoodRecipe { const _$FoodRecipeImpl( - {required this.name, required this.email, required this.password}); + {required this.title, required this.email, required this.password}); factory _$FoodRecipeImpl.fromJson(Map json) => _$$FoodRecipeImplFromJson(json); @override - final String name; + final String title; @override final String email; @override @@ -134,7 +134,7 @@ class _$FoodRecipeImpl implements _FoodRecipe { @override String toString() { - return 'FoodRecipe(name: $name, email: $email, password: $password)'; + return 'FoodRecipe(title: $title, email: $email, password: $password)'; } @override @@ -142,7 +142,7 @@ class _$FoodRecipeImpl implements _FoodRecipe { return identical(this, other) || (other.runtimeType == runtimeType && other is _$FoodRecipeImpl && - (identical(other.name, name) || other.name == name) && + (identical(other.title, title) || other.title == title) && (identical(other.email, email) || other.email == email) && (identical(other.password, password) || other.password == password)); @@ -150,7 +150,7 @@ class _$FoodRecipeImpl implements _FoodRecipe { @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, name, email, password); + int get hashCode => Object.hash(runtimeType, title, email, password); @JsonKey(ignore: true) @override @@ -168,7 +168,7 @@ class _$FoodRecipeImpl implements _FoodRecipe { abstract class _FoodRecipe implements FoodRecipe { const factory _FoodRecipe( - {required final String name, + {required final String title, required final String email, required final String password}) = _$FoodRecipeImpl; @@ -176,7 +176,7 @@ abstract class _FoodRecipe implements FoodRecipe { _$FoodRecipeImpl.fromJson; @override - String get name; + String get title; @override String get email; @override diff --git a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart index 7d8dfc8..e2b8d55 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/model/food_recipe.g.dart @@ -8,14 +8,14 @@ part of 'food_recipe.dart'; _$FoodRecipeImpl _$$FoodRecipeImplFromJson(Map json) => _$FoodRecipeImpl( - name: json['name'] as String, + title: json['title'] as String, email: json['email'] as String, password: json['password'] as String, ); Map _$$FoodRecipeImplToJson(_$FoodRecipeImpl instance) => { - 'name': instance.name, + 'title': instance.title, 'email': instance.email, 'password': instance.password, }; diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart index 5947b54..2c5e84a 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart @@ -26,6 +26,16 @@ class _BigButtonState extends State { Widget build(BuildContext context) { return GestureDetector( onTap: widget.onTap, + onTapDown: (_) { + setState(() { + _isPressed = true; + }); + }, + onTapUp: (_) { + setState(() { + _isPressed = false; + }); + }, child: Container( width: double.infinity, height: 70, @@ -39,6 +49,7 @@ class _BigButtonState extends State { Center( child: Text( widget.title, + style: TextStyles.mediumTextRegular ), ), SizedBox( From 515fa832806b3459401bbd8690f3b772bdc307ee Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 10:25:47 +0900 Subject: [PATCH 14/20] fix: 240711 snsLogin ui --- .../presentation/component/big_button.dart | 5 +---- .../component/sign_up/sign_up_screen.dart | 14 ++++++++++++++ .../presentation/component/sns_login_items.dart | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart index 2c5e84a..4f9cdd5 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart @@ -49,12 +49,9 @@ class _BigButtonState extends State { Center( child: Text( widget.title, - style: TextStyles.mediumTextRegular + //style: TextStyles.mediumTextRegular ), ), - SizedBox( - width: 35, - ), Icon(Icons.arrow_forward), ], ), diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index 0fb8d2a..777c0bd 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -91,6 +91,20 @@ class SignUpScreen extends StatelessWidget { height: 20, ), BigButton(title: 'Sign in', onTap: () {}), + SizedBox( + height: 10, + ), + Container( + height: 10.0, + color: Colors.grey, + ), +Container( + child: Row( + children: [ + Container(), + ], + ), +) ], ), ), diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart new file mode 100644 index 0000000..639596d --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class SnsLoginItems extends StatelessWidget { + const SnsLoginItems({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + child: Row( + children: [ + SizedBox(width: 50,height: 50,), + SizedBox(width: 50, height: 50,), + ], + ), + ); + } +} From 7873479fc9418a2ae950fd85aee5d1cf4860d37e Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 10:47:02 +0900 Subject: [PATCH 15/20] fix: 240711 Text('Don'have an acount?) --- .../asset/{ => images}/faceBookIconButton.png | Bin .../asset/{ => images}/googleIconButton.png | Bin .../component/sign_up/sign_up_screen.dart | 18 ++++++++---------- 3 files changed, 8 insertions(+), 10 deletions(-) rename project/learn_flutter_togerther/asset/{ => images}/faceBookIconButton.png (100%) rename project/learn_flutter_togerther/asset/{ => images}/googleIconButton.png (100%) diff --git a/project/learn_flutter_togerther/asset/faceBookIconButton.png b/project/learn_flutter_togerther/asset/images/faceBookIconButton.png similarity index 100% rename from project/learn_flutter_togerther/asset/faceBookIconButton.png rename to project/learn_flutter_togerther/asset/images/faceBookIconButton.png diff --git a/project/learn_flutter_togerther/asset/googleIconButton.png b/project/learn_flutter_togerther/asset/images/googleIconButton.png similarity index 100% rename from project/learn_flutter_togerther/asset/googleIconButton.png rename to project/learn_flutter_togerther/asset/images/googleIconButton.png diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index 777c0bd..cd01a9e 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/big_button.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/component/sns_login_items.dart'; class SignUpScreen extends StatelessWidget { const SignUpScreen({super.key}); @@ -92,19 +93,16 @@ class SignUpScreen extends StatelessWidget { ), BigButton(title: 'Sign in', onTap: () {}), SizedBox( - height: 10, + height: 20, ), Container( - height: 10.0, - color: Colors.grey, + height: 1.0, + color: Colors.grey[300], + ), + SizedBox( + height: 20, ), -Container( - child: Row( - children: [ - Container(), - ], - ), -) + SnsLoginItems(), ], ), ), From ce8aacdee9946f39db51271b7ec4d0258f421c3a Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 11:20:49 +0900 Subject: [PATCH 16/20] =?UTF-8?q?feat:=20240711=20ui=EB=9E=91=20data=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=ED=95=84=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/sign_up/sign_up_screen.dart | 78 +++++++++++++------ .../component/sns_login_items.dart | 17 +++- 2 files changed, 69 insertions(+), 26 deletions(-) diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index cd01a9e..d866a4b 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -13,96 +13,126 @@ class SignUpScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( + const SizedBox( height: 60, ), - Text( + const Text( 'Hello', style: TextStyle( fontSize: 35, fontWeight: FontWeight.bold, ), ), - Text( + const Text( 'Welcome Back!', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, ), ), - SizedBox( + const SizedBox( height: 40, ), - Text('Email'), - SizedBox( + const Text('Email'), + const SizedBox( height: 10, ), TextField( decoration: InputDecoration( hintText: 'Enter Email', - hintStyle: TextStyle( + hintStyle: const TextStyle( color: Colors.grey, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.grey, ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.grey, ), ), ), ), - SizedBox( + const SizedBox( height: 40, ), - Text('Enter Password'), - SizedBox( + const Text('Enter Password'), + const SizedBox( height: 10, ), TextField( decoration: InputDecoration( hintText: 'Enter Password', - hintStyle: TextStyle( + hintStyle: const TextStyle( color: Colors.grey, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.grey, ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.grey, ), ), ), ), - SizedBox( + const SizedBox( height: 20, ), - Text('Forgot Password?'), - SizedBox( + const Text('Forgot Password?'), + const SizedBox( height: 20, ), BigButton(title: 'Sign in', onTap: () {}), - SizedBox( + const SizedBox( height: 20, ), - Container( - height: 1.0, - color: Colors.grey[300], + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + height: 1.0, + color: Colors.grey[300], + ), + const Text( + ' Or Sign in With ', + style: TextStyle( + color: Colors.grey, + ), + ), + Container( + height: 1.0, + color: Colors.grey[300], + ), + ], ), - SizedBox( + const SizedBox( height: 20, ), - SnsLoginItems(), + const SnsLoginItems(), + Container( + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('''Don'have an acount?'''), + SizedBox( + width: 10, + ), + Text( + 'Sign up', + style: TextStyle(color: Colors.amberAccent), + ) + ], + ), + ) ], ), ), diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart index 639596d..a4cedef 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sns_login_items.dart @@ -7,9 +7,22 @@ class SnsLoginItems extends StatelessWidget { Widget build(BuildContext context) { return Container( child: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox(width: 50,height: 50,), - SizedBox(width: 50, height: 50,), + Container( + child: Image.asset( + 'asset/images/googleIconButton.png', + ), + width: 50, + height: 50, + ), + Container( + child: Image.asset( + 'asset/images/faceBookIconButton.png', + ), + width: 50, + height: 50, + ), ], ), ); From 30320b96814d4653b9688ca9be3ae5c4eaf33b05 Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 15:37:10 +0900 Subject: [PATCH 17/20] =?UTF-8?q?feat:=20240711=20TextStyle,=20ColorStyle?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20import=20=EC=82=AD=EC=A0=9C=20=ED=9B=84?= =?UTF-8?q?=20sign=5Fup=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B0=8F=20big=5F?= =?UTF-8?q?button=20=ED=8C=8C=EC=9D=BC=20=EC=A0=81=EC=9A=A9=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/component/big_button.dart | 20 ++++++++++------ .../component/sign_up/sign_up_screen.dart | 24 +++++++++++++------ .../presentation/component/ui/theme.dart | 0 .../presentation/component/ui/util.dart | 0 .../{component => }/ui/color_styles.dart | 2 +- .../{component => }/ui/text_styles.dart | 4 +++- 6 files changed, 34 insertions(+), 16 deletions(-) delete mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/theme.dart delete mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/util.dart rename project/learn_flutter_togerther/lib/02_material_design/presentation/{component => }/ui/color_styles.dart (96%) rename project/learn_flutter_togerther/lib/02_material_design/presentation/{component => }/ui/text_styles.dart (98%) diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart index 4f9cdd5..156d030 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:learn_flutter_togerther/02_material_design/presentation/component/ui/color_styles.dart'; -import 'package:learn_flutter_togerther/02_material_design/presentation/component/ui/text_styles.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/ui/color_styles.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/ui/text_styles.dart'; class BigButton extends StatefulWidget { //data @@ -47,12 +47,18 @@ class _BigButtonState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Center( - child: Text( - widget.title, - //style: TextStyles.mediumTextRegular - ), + child: Text(widget.title, + style: TextStyles.mediumTextRegular.copyWith( + color: ColorStyles.white, + )), + ), + SizedBox( + width: 30, + ), + Icon( + Icons.arrow_forward, + color: ColorStyles.white, ), - Icon(Icons.arrow_forward), ], ), ), diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index d866a4b..a88a0fe 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/big_button.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/sns_login_items.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/ui/color_styles.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/ui/text_styles.dart'; + class SignUpScreen extends StatelessWidget { const SignUpScreen({super.key}); @@ -99,17 +102,17 @@ class SignUpScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - height: 1.0, + height: 3.0, color: Colors.grey[300], ), const Text( ' Or Sign in With ', style: TextStyle( - color: Colors.grey, + color: ColorStyles.gray4, ), ), Container( - height: 1.0, + height: 3.0, color: Colors.grey[300], ), ], @@ -119,17 +122,24 @@ class SignUpScreen extends StatelessWidget { ), const SnsLoginItems(), Container( - child: const Row( + child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text('''Don'have an acount?'''), + Text( + '''Don't have an account?''', + style: TextStyles.smallerTextRegular.copyWith( + color: ColorStyles.primary100, + ), + ), SizedBox( width: 10, ), Text( 'Sign up', - style: TextStyle(color: Colors.amberAccent), - ) + style: TextStyles.smallerTextRegular.copyWith( + color: ColorStyles.primary100, + ), + ), ], ), ) diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/theme.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/theme.dart deleted file mode 100644 index e69de29..0000000 diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/util.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/util.dart deleted file mode 100644 index e69de29..0000000 diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/color_styles.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/ui/color_styles.dart similarity index 96% rename from project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/color_styles.dart rename to project/learn_flutter_togerther/lib/02_material_design/presentation/ui/color_styles.dart index fd33a72..05c2ab2 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/color_styles.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/ui/color_styles.dart @@ -1,4 +1,4 @@ -import 'dart:ui'; +import 'package:flutter/material.dart'; abstract class ColorStyles { static const Color black = Color(0xFF000000); diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/text_styles.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/ui/text_styles.dart similarity index 98% rename from project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/text_styles.dart rename to project/learn_flutter_togerther/lib/02_material_design/presentation/ui/text_styles.dart index ff82728..f850f95 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/ui/text_styles.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/ui/text_styles.dart @@ -1,4 +1,6 @@ -import 'dart:ui'; + + +import 'package:flutter/material.dart'; abstract class TextStyles { static TextStyle tittleTextBold = TextStyle( From e4529297a932e6563546179897adcad90203ae9e Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Fri, 12 Jul 2024 23:29:21 +0900 Subject: [PATCH 18/20] =?UTF-8?q?fix:=20240711=20textfield=20=EB=A5=BC=20d?= =?UTF-8?q?ata=EC=AA=BD=EC=9C=BC=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/Ingredient_item.dart | 10 ++-- .../presentation/component/big_button.dart | 14 ++--- .../component/sign_up/sign_up_screen.dart | 53 ++++++------------- .../component/textField_item.dart | 50 +++++++++++++++++ 4 files changed, 77 insertions(+), 50 deletions(-) create mode 100644 project/learn_flutter_togerther/lib/02_material_design/presentation/component/textField_item.dart diff --git a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart index 792ce52..8a40848 100644 --- a/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart +++ b/project/learn_flutter_togerther/lib/01_widget/ingridentItem/presentation/component/Ingredient_item.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; - import '../../model/ingredient.dart'; class IngredientItem extends StatelessWidget { @@ -33,7 +32,6 @@ class IngredientItem extends StatelessWidget { ingredient.imageUrl, ), ), - const SizedBox( width: 25, ), @@ -47,12 +45,10 @@ class IngredientItem extends StatelessWidget { const Spacer(), Text( style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, - color: Colors.black26 - ), + fontSize: 20, + fontWeight: FontWeight.normal, + color: Colors.black26), ingredient.weight, - ), ], ), diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart index 156d030..08326a1 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/big_button.dart @@ -3,9 +3,9 @@ import 'package:learn_flutter_togerther/02_material_design/presentation/ui/color import 'package:learn_flutter_togerther/02_material_design/presentation/ui/text_styles.dart'; class BigButton extends StatefulWidget { - //data final void Function() onTap; + //data final String title; const BigButton({ @@ -47,13 +47,15 @@ class _BigButtonState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Center( - child: Text(widget.title, - style: TextStyles.mediumTextRegular.copyWith( - color: ColorStyles.white, - )), + child: Text( + widget.title, + style: TextStyles.mediumTextBold.copyWith( + color: ColorStyles.white, + ), + ), ), SizedBox( - width: 30, + width: 40, ), Icon( Icons.arrow_forward, diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index a88a0fe..1fe05d0 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/big_button.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/sns_login_items.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/component/textField_item.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/ui/color_styles.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/ui/text_styles.dart'; - class SignUpScreen extends StatelessWidget { const SignUpScreen({super.key}); @@ -19,46 +19,20 @@ class SignUpScreen extends StatelessWidget { const SizedBox( height: 60, ), - const Text( - 'Hello', - style: TextStyle( - fontSize: 35, - fontWeight: FontWeight.bold, - ), + Text( + 'Hello,', + style: TextStyles.headerTextBold, ), - const Text( + Text( 'Welcome Back!', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), + style: TextStyles.headerTextRegular ), const SizedBox( height: 40, ), - const Text('Email'), - const SizedBox( - height: 10, - ), - TextField( - decoration: InputDecoration( - hintText: 'Enter Email', - hintStyle: const TextStyle( - color: Colors.grey, - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide( - color: Colors.grey, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide( - color: Colors.grey, - ), - ), - ), + + Container( + child: const TextfieldItem(), ), const SizedBox( height: 40, @@ -90,11 +64,16 @@ class SignUpScreen extends StatelessWidget { const SizedBox( height: 20, ), - const Text('Forgot Password?'), + Text( + 'Forgot Password?', + style: TextStyles.smallerTextRegular.copyWith( + color: ColorStyles.secondary100, + ), + ), const SizedBox( height: 20, ), - BigButton(title: 'Sign in', onTap: () {}), + BigButton(title: 'Sign In', onTap: () {}), const SizedBox( height: 20, ), diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/textField_item.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/textField_item.dart new file mode 100644 index 0000000..6b00558 --- /dev/null +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/textField_item.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/ui/color_styles.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/ui/text_styles.dart'; + +class TextfieldItem extends StatefulWidget { + const TextfieldItem({super.key}); + + @override + State createState() => _TextfieldItemState(); +} + +class _TextfieldItemState extends State { + @override + Widget build(BuildContext context) { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Email', + style: TextStyles.smallTextRegular, + ), + const SizedBox( + height: 10, + ), + TextField( + decoration: InputDecoration( + hintText: 'Enter Email', + hintStyle: TextStyles.smallerTextRegular.copyWith( + color: ColorStyles.gray4, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + ], + ), + ); + } +} From a44e6b4f537135081f40d5124dc05c30ae6eb61f Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Sat, 13 Jul 2024 00:02:04 +0900 Subject: [PATCH 19/20] =?UTF-8?q?fix:=20240711=20InputTextField=EB=A1=9C?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20&&=20=EC=83=9D=EC=84=B1=EC=9E=90=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=B4=20inputTitle,=20hintText=EB=A5=BC=20widget=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{textField_item.dart => input_text.dart} | 22 +++++++---- .../component/sign_up/sign_up_screen.dart | 39 ++++++------------- 2 files changed, 26 insertions(+), 35 deletions(-) rename project/learn_flutter_togerther/lib/02_material_design/presentation/component/{textField_item.dart => input_text.dart} (73%) diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/textField_item.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/input_text.dart similarity index 73% rename from project/learn_flutter_togerther/lib/02_material_design/presentation/component/textField_item.dart rename to project/learn_flutter_togerther/lib/02_material_design/presentation/component/input_text.dart index 6b00558..14c7a66 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/textField_item.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/input_text.dart @@ -2,22 +2,30 @@ import 'package:flutter/material.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/ui/color_styles.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/ui/text_styles.dart'; -class TextfieldItem extends StatefulWidget { - const TextfieldItem({super.key}); +class InputTextField extends StatefulWidget { + //data + final String inputTitle; + final String hintText; + + const InputTextField({ + super.key, + required this.inputTitle, + required this.hintText, + }); @override - State createState() => _TextfieldItemState(); + State createState() => _InputTextFieldState(); } -class _TextfieldItemState extends State { +class _InputTextFieldState extends State { @override Widget build(BuildContext context) { return Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ Text( - 'Email', + widget.inputTitle, style: TextStyles.smallTextRegular, ), const SizedBox( @@ -25,7 +33,7 @@ class _TextfieldItemState extends State { ), TextField( decoration: InputDecoration( - hintText: 'Enter Email', + hintText: widget.hintText, hintStyle: TextStyles.smallerTextRegular.copyWith( color: ColorStyles.gray4, ), diff --git a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart index 1fe05d0..ba249e5 100644 --- a/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart +++ b/project/learn_flutter_togerther/lib/02_material_design/presentation/component/sign_up/sign_up_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/big_button.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/component/sns_login_items.dart'; -import 'package:learn_flutter_togerther/02_material_design/presentation/component/textField_item.dart'; +import 'package:learn_flutter_togerther/02_material_design/presentation/component/input_text.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/ui/color_styles.dart'; import 'package:learn_flutter_togerther/02_material_design/presentation/ui/text_styles.dart'; @@ -23,44 +23,27 @@ class SignUpScreen extends StatelessWidget { 'Hello,', style: TextStyles.headerTextBold, ), - Text( - 'Welcome Back!', - style: TextStyles.headerTextRegular - ), + Text('Welcome Back!', style: TextStyles.headerTextRegular), const SizedBox( height: 40, ), - Container( - child: const TextfieldItem(), + child: InputTextField( + inputTitle: 'Email', + hintText: 'Enter Email', + ), ), const SizedBox( height: 40, ), - const Text('Enter Password'), const SizedBox( height: 10, ), - TextField( - decoration: InputDecoration( - hintText: 'Enter Password', - hintStyle: const TextStyle( - color: Colors.grey, - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide( - color: Colors.grey, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide( - color: Colors.grey, - ), - ), - ), - ), + Container( + child: InputTextField( + inputTitle: 'Enter Password', + hintText: 'Enter password', + )), const SizedBox( height: 20, ), From 0e04ba5bca7fe0d0d97964af9c90b1798b513574 Mon Sep 17 00:00:00 2001 From: Sangin Han Date: Mon, 19 Aug 2024 10:00:09 +0900 Subject: [PATCH 20/20] feat : TIL --- dart_240710.md | 4 +++ flutter_240717.md | 29 ++++++++++++++++ flutter_240724.md | 19 +++++++++++ network_240712.md | 13 ++++++++ project/flutter_240702.md | 58 ++++++++++++++++++++++++++++++++ project/flutter_240731.md | 4 +++ "\354\260\275\354\227\205.md" | 62 +++++++++++++++++++++++++++++++++++ 7 files changed, 189 insertions(+) create mode 100644 dart_240710.md create mode 100644 flutter_240717.md create mode 100644 flutter_240724.md create mode 100644 network_240712.md create mode 100644 project/flutter_240702.md create mode 100644 project/flutter_240731.md create mode 100644 "\354\260\275\354\227\205.md" diff --git a/dart_240710.md b/dart_240710.md new file mode 100644 index 0000000..4b74ae0 --- /dev/null +++ b/dart_240710.md @@ -0,0 +1,4 @@ +- 만약 static, factory를 사용하려면 abstract class를 사용하고 + abstract class를 implements 하는 방식으로 사용하자(이상해 하지마세요) + +- id는 int로 가져가는게 맞나? (String으로 가져가는게 더 좋을 수도 있음) \ No newline at end of file diff --git a/flutter_240717.md b/flutter_240717.md new file mode 100644 index 0000000..fe1b8cb --- /dev/null +++ b/flutter_240717.md @@ -0,0 +1,29 @@ +navigator.of(context).push +- context가 없으면 이동이 안된다(datasource, repository같은 데는 이동이 안돼 + 근데, getX를 하면 이동이 된다) + +데이터돌려받기 - todolist 같은것으로 예시를 보면 + 리스트 페이지 다음화면에서 새로 할일을 쓰고 추가해서 + 앞 화면으로 돌아갔을때 새로 할일이 추가되있어야 하는 경우 + +context.push(Uri(paht : '/', queryParameters: {'age': 10})) + - 10에 해당하는 위치에 dynamic이 아니라 String으로 보내야한다 + - 받는 쪽에서 String으로 되어있다 + - 객체하나 보낼때는 extra로 보내는게 더 편함 + +WEBP 가 PNG보다 훨씬 용량이 작다 + +기기들이 크기가 다양하니 컴포넌트를 높이 정도만 주고, +가로는 double.infinity정도를 주는게 유지보수가 용이하다 + +안드로이드 스튜디오 뉴 터미널에서는 build runner build가 호환이 안된다 + +viewmodel의 액션은 모두다 void 그래서 fetct가 어울림 +getter로만 나간다 +나머지는 다 void로 한쪽으로만 간다 +상태도 뷰모델에 넣는다 + +리액티브 프로그래밍 - 상태가변경되면 자동으로 반영 + 리스너블빌더(listenableBuilder) + + diff --git a/flutter_240724.md b/flutter_240724.md new file mode 100644 index 0000000..5bcc554 --- /dev/null +++ b/flutter_240724.md @@ -0,0 +1,19 @@ + +context.read - 1회성 +context.watch - 반복하는UI 재사용이 가능 +## onPressed 내에서 .watch로 접근하면 에러. read로 사용해야한다 +## consumer로 감싸면 하단에 context.read로 사용해야함 + +그래서 위에 viewModel = xxx 하고 +하단에서 viewModel.xx 로 메서드 호출 + + + +initState - build - microtask +빌드가 한번이라도 호출이 되야 context로 접근이 되면 가져올수 있다 + - Future.microtask() 이용 + +-> viewModel에 생성자에 특정 메서드를 실행하려면 넣어놓으면 된다 +(시작하자마자 바로 실행) + +firebase diff --git a/network_240712.md b/network_240712.md new file mode 100644 index 0000000..f5468c8 --- /dev/null +++ b/network_240712.md @@ -0,0 +1,13 @@ +서브넷이 같으면 네트워크 크기가 같다 +서브넷이 같으면 ip 개수 정해준다 + +iplv4는 전세계인이 사용하기엔 부족하다. 그걸 확장하는게 사설ip +사설ip는 공인ip로 변환해줘야한다 +공인ip는 인터넷에 연결되어있는 ip 공인ip는 유료다 +ap : access point에 따라서 ip는 다를 수 있다 + +curl ifconfig.me ip확인 +wsl을 설치해라 +windows : ipconfig + +mac : netstat -rn | grep defalut | grep en0 \ No newline at end of file diff --git a/project/flutter_240702.md b/project/flutter_240702.md new file mode 100644 index 0000000..dc4014d --- /dev/null +++ b/project/flutter_240702.md @@ -0,0 +1,58 @@ +stateless widget에서 +gesturedetector, inkwell 같은 걸로 활용하지 말자 +- 재사용성이 떨어지고, 화면 이동은 되고, + +=> .call 메서드를 통해서 이벤트를 돌려주자 + +rule!! +1. 데이터가 바꿨어? 생성자를 통해서 데이터를 입력 +2. 이벤트가 발생했어? .call 메서드를 통해서 이벤트를 돌려줘 + +stateless에서 상태를 가지게 되면, + +test 코드 +1. MaterialApp - Scaffold - body - widget 까지는 필요하다 +2. widget을 테스트할때는 widget을 테스트하는게 아니라, widget을 통해서 이벤트를 돌려주는 것을 테스트해야 한다 + +build내에는 로직 호출, 통신 http 같은 코드를 사용하면 안된다 = 매번 로딩을 하기때문에 안됨 +* appbar에서 텍스트를 중심에 놓으려면 center 위젯이 아닌 centerTitle을 사용하면 된다 +* TextField내 onSubmitted는 사용자가 입력하고 제출할때 호출, onChanged는 사용자가 입력이 변경될때마다 호출 +* +* 근데 이 아랫줄은 생각을 좀 해봐야됨 +* final repository = PixabayImageItemRepository();는 변수 선언과 동시에 객체를 생성 및 초기화합니다. + final PixabayRepository _pixabayRepository;는 변수 선언만 하고 초기화는 나중에 이루어집니다. +* 또한 언더스코어(_)로 시작하여 프라이빗 변수임을 나타냅니다. +* changeNotifierProvider는 의존성 주입, 상태관리지만 상태관리에만 집중을 하면 좋을거 같고 +* 의존성 주입은 GetIt으로 하는 것을 추천? 한다 + +Stream +* changeNotifierProvider를 안쓰면 Stream으로 상태관리 가능 +* 데이터를 UI로 자동변환이 되는데, 필요없는 경우에는 Stream을 안써도 된다 +* .listen으로 구독하면 해지를 꼭 해지! +* cold Stream - 구독을 하면 그때부터 데이터를 보냄(하나의 리스너로만 제약) +* - 일반적으로 한 화면에 하나의 데이터를 사용하는 경우 +* +* hot Stream- 계속 데이터를 보내고 있다가 구독하면 보냄 지나간건 보내지 않음(여러 리스너를 허용 .broadcase 생성자 사용) +* viewModel에 여러 화면을 공유한다면 Hot Stream으로 연결해야할 거 같음 + +* 다이얼로그 가 떴다가 사라질때 1회성 이벤트 +* sink - 데이터가 줄줄줄 흐른다(싱크대의 싱크) +* 구독은 initState 밖에 안됨(1회성) +- Future.microtask로 잠깐 시간을 벌어준다 +* 만들일이 있을 때 - yield + +DI +* 인젝터블 패키지를 이용해서 의존성 주입을 편하게 하는 패키지 +* 어노테이션을 이용해서 @Singleton(as: NoteRepository) 이라고 쓰고 빌드하면 필요로 하는곳에 싱글턴으로 들어간다 +* Future 로 사용할 때가 있는데 시간이 오래걸리는 코드들에 필요할때가 있고, 기본은 void로 실행하면 된다 +* interface면 대문자 @Singleton 하고<여기에 인터페이스 넣고> +* viewModel이면 팩토리기에 @injectable만 하면 된다 +* viewModel에는 레파짓토리,데이터소스 만 생성자로 받자 +* 모듈에서 전부다 lazysingleton 으로 하는게 속편함 +* diSetup에서 getIt 모듈 3벌을 만들어서, 메서드만 교체해서 해도 된다(prod,dev,test) + +고급 상태 관리 기술 + + +* git +* 체리픽 \ No newline at end of file diff --git a/project/flutter_240731.md b/project/flutter_240731.md new file mode 100644 index 0000000..49c799f --- /dev/null +++ b/project/flutter_240731.md @@ -0,0 +1,4 @@ +- get it + +* changeNotifierProvider 내 create에는 제네릭을 생략하면 에러가 날 수도 있는데 안나면 생략 가능 +* \ No newline at end of file diff --git "a/\354\260\275\354\227\205.md" "b/\354\260\275\354\227\205.md" new file mode 100644 index 0000000..0baadb3 --- /dev/null +++ "b/\354\260\275\354\227\205.md" @@ -0,0 +1,62 @@ + +## 투자유치 +the vc +- https://thevc.kr/ +- 6개월 뒤에 지원받음 +- 심사역 투자팀 투심위 서류처리(2개월) +- 투자자 독소조항 잘 검토 모르면 네이버 같은 창업관련 자원을 받아서 할 수도 있다 +- 데모데이 : 여러 회사를 투자사로 7분동안 설명을 해서 네트워크를 만들 수 있다 +- 법인 : 정관 + +- 초기 창업 패키지 + +7/25 +- 컴포넌트는 생성자로 데이터를 받아라 +- 상태관리 파일 위치는 같은 화면, 뷰모델이 들어가있는 폴더에 위치하면 된다 + +- flutter pub add firebase-core +- git ignore에 설정 +- google-Services +- GoogleService-info.plist +- firebase 홈페이지에서도 찾을 수 있다 초기화, 플러그인등.. + +7/26 +클린아키텍쳐 +데이터소스 별도 클래스 -> 여러 레파짓토리에서 쓴다 +뷰모델이 화면에 쓰이는 로직이 너무 많다 +유즈케이스에다 만들고 뷰모델은 가져오기만 하는식으로 하자 +폴더구조 - 목적에 맞는 파일들까리 모은데(view, viewModel, ui, uiState) +로버트 C.마틴 - 클린 아키텍쳐 - 소프트웨어 구조와 설계원칙 + +Repository +- data layer에 구현체 +- domain layer에 추상인터페이스 + +- 테스트가 용이하다 - 테스트를 부위별로 할 수 있다 +- domain - model - repository + +get user user case내 result를 사용(viewModel에 바로 접근) +- 데이터만 잘 들어오면 성공이야? +- 데이터는 ok, 화면에서(비즈니스 로직 분기 - 리절트로 성공/실패를 할 수도 있다) + +call() +- _getUserUserCase.call() 생략가능 +- 대신 call이 많으면 알기가 어려움 +- call함수 재정의 - execute()로 대신 사용 가능하다 +- core 폴더는 공통기능/공통관리 + +특강 +- os는 왜 필요할까? +- 연결되어있는 하드웨어를 쓸 수가 없다 +- 자원관리 대상 - 하드웨어 +- cloud 왜 필요할까? +- 편리함, 비용적으로 효율적으로 사용할 수 있으니깡 + +- Iaas = 건물에 물, 전기 있는 상황 +- PaaS = + 가구등 필요한 것들이 있는 상황 +- Saas = 소프트웨어적인(선생님, 학생등을 ) 부분이 있는 상황 +- IDE = Saas서비스(모든 어플리케이션), 웹페이지 +- 어플라이언스 +- EC2 인스턴스 +- 도메인서버-오리진-오리진서버?로 간다 +- \ No newline at end of file