-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature/calendar2] 커스텀뷰 캘린더 #7
base: develop
Are you sure you want to change the base?
Changes from 4 commits
d7a2254
0f90dc1
a207ee3
0460e15
b8196fa
537e18f
0a93ca8
66a42f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -5,7 +5,7 @@ plugins { | |||||
} | ||||||
|
||||||
android { | ||||||
compileSdkVersion 30 | ||||||
compileSdkVersion 31 | ||||||
buildToolsVersion "30.0.3" | ||||||
|
||||||
defaultConfig { | ||||||
|
@@ -25,39 +25,39 @@ android { | |||||
} | ||||||
} | ||||||
compileOptions { | ||||||
sourceCompatibility JavaVersion.VERSION_1_8 | ||||||
targetCompatibility JavaVersion.VERSION_1_8 | ||||||
sourceCompatibility(JavaVersion.VERSION_1_8) | ||||||
targetCompatibility(JavaVersion.VERSION_1_8) | ||||||
} | ||||||
kotlinOptions { | ||||||
jvmTarget = '1.8' | ||||||
jvmTarget = JavaVersion.VERSION_1_8 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
buildFeatures { | ||||||
viewBinding = true | ||||||
viewBinding true | ||||||
} | ||||||
} | ||||||
|
||||||
dependencies { | ||||||
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" | ||||||
implementation 'androidx.core:core-ktx:1.5.0' | ||||||
implementation 'androidx.appcompat:appcompat:1.3.0' | ||||||
implementation 'com.google.android.material:material:1.3.0' | ||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' | ||||||
testImplementation 'junit:junit:4.+' | ||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2' | ||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' | ||||||
implementation 'com.github.bumptech.glide:glide:4.11.0' | ||||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' | ||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8" | ||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1" | ||||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02' | ||||||
implementation 'androidx.core:core-ktx:1.6.0' | ||||||
implementation 'androidx.appcompat:appcompat:1.3.1' | ||||||
implementation 'com.google.android.material:material:1.4.0' | ||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.1' | ||||||
testImplementation 'junit:junit:4.13.2' | ||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3' | ||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' | ||||||
implementation 'com.github.bumptech.glide:glide:4.12.0' | ||||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' | ||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3" | ||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0" | ||||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-rc01' | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 벌써 rc 나왔구나 코루틴 사용하기 더 편해지겠누 |
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' | ||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0' | ||||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' | ||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.1' | ||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1" | ||||||
def activity_version = "1.2.0" | ||||||
def fragment_version = "1.3.0" | ||||||
def activity_version = "1.3.1" | ||||||
def fragment_version = "1.3.6" | ||||||
implementation "androidx.activity:activity-ktx:$activity_version" | ||||||
implementation "androidx.fragment:fragment-ktx:$fragment_version" | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,65 @@ | ||||||||||||||||||||||||||||||||||||
package com.teamcatchme.calendar_customview | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
import android.content.Context | ||||||||||||||||||||||||||||||||||||
import android.graphics.* | ||||||||||||||||||||||||||||||||||||
import android.util.AttributeSet | ||||||||||||||||||||||||||||||||||||
import android.util.Log | ||||||||||||||||||||||||||||||||||||
import android.view.View | ||||||||||||||||||||||||||||||||||||
import androidx.core.content.res.ResourcesCompat | ||||||||||||||||||||||||||||||||||||
import com.teamcatchme.catchmesample.R | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
class CalendarItemView @JvmOverloads | ||||||||||||||||||||||||||||||||||||
constructor( | ||||||||||||||||||||||||||||||||||||
context: Context, | ||||||||||||||||||||||||||||||||||||
attrs: AttributeSet? = null, | ||||||||||||||||||||||||||||||||||||
defStyleAttr: Int = 0, | ||||||||||||||||||||||||||||||||||||
private val date: Int? = null, | ||||||||||||||||||||||||||||||||||||
private val catchuList: Array<Int> = arrayOf(), | ||||||||||||||||||||||||||||||||||||
private val isPrevious: Boolean = false | ||||||||||||||||||||||||||||||||||||
) : | ||||||||||||||||||||||||||||||||||||
Comment on lines
+11
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
우선 생성자 형식은 저런데 뷰의 생성자에 저런 인자들이 들어가도 되나 나도 자세히 몰라서 확인해봐야할 듯 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오키 일단 해보고 우리 리얼 레포에 PR날리기 전까지 나도 확인해보겠음!! |
||||||||||||||||||||||||||||||||||||
View(context, attrs, defStyleAttr) { | ||||||||||||||||||||||||||||||||||||
private var paint: Paint = Paint() | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private fun drawDateRect(canvas: Canvas, date: Int) { | ||||||||||||||||||||||||||||||||||||
paint.textSize = 36f | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 실제에서는 이건 dp로 맞춰줘야할 것 같습니다. |
||||||||||||||||||||||||||||||||||||
if (isPrevious) paint.color = Color.GRAY | ||||||||||||||||||||||||||||||||||||
canvas.drawText( | ||||||||||||||||||||||||||||||||||||
date.toString(), | ||||||||||||||||||||||||||||||||||||
(width / 2).toFloat(), | ||||||||||||||||||||||||||||||||||||
((height / 2) - ((paint.descent() + paint.ascent()) / 2)), | ||||||||||||||||||||||||||||||||||||
paint | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
private fun drawDateWithCatchuRect(canvas: Canvas, date: Int, catchuList: Array<Int>) { | ||||||||||||||||||||||||||||||||||||
paint.textSize = 30f | ||||||||||||||||||||||||||||||||||||
paint.color = Color.GRAY | ||||||||||||||||||||||||||||||||||||
val contextResources = context.resources | ||||||||||||||||||||||||||||||||||||
val catchuDrawable = | ||||||||||||||||||||||||||||||||||||
ResourcesCompat.getDrawable(contextResources, R.drawable.ic_cachu1, null); | ||||||||||||||||||||||||||||||||||||
val catchuBitmap = drawableToBitmap(requireNotNull(catchuDrawable)) | ||||||||||||||||||||||||||||||||||||
canvas.drawBitmap( | ||||||||||||||||||||||||||||||||||||
requireNotNull(catchuBitmap), | ||||||||||||||||||||||||||||||||||||
(width / 2 - catchuBitmap.width / 2).toFloat(), | ||||||||||||||||||||||||||||||||||||
0f, | ||||||||||||||||||||||||||||||||||||
null | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
requireNotNull 같은 단정문이 있으면 익셉션이 터지기 때문에 방어로직을 하나 가져야할 것 같아 |
||||||||||||||||||||||||||||||||||||
canvas.drawText( | ||||||||||||||||||||||||||||||||||||
date.toString(), | ||||||||||||||||||||||||||||||||||||
(width / 2).toFloat(), | ||||||||||||||||||||||||||||||||||||
(catchuBitmap.height + 28).toFloat(), | ||||||||||||||||||||||||||||||||||||
paint | ||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||
// 누르면 프라그먼트 뿅 하게 리스너 추가하기 | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
override fun onDraw(canvas: Canvas?) { | ||||||||||||||||||||||||||||||||||||
super.onDraw(canvas) | ||||||||||||||||||||||||||||||||||||
paint.textAlign = Paint.Align.CENTER | ||||||||||||||||||||||||||||||||||||
if (canvas == null) return; | ||||||||||||||||||||||||||||||||||||
if (date != null) { | ||||||||||||||||||||||||||||||||||||
if (catchuList.isNotEmpty()) drawDateWithCatchuRect(canvas, date, catchuList) | ||||||||||||||||||||||||||||||||||||
else drawDateRect(canvas, date) | ||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
이런식으로 밀고갈 수 있을 것 같아 |
||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,55 @@ | ||||||||||||||
package com.teamcatchme.calendar_customview | ||||||||||||||
|
||||||||||||||
import android.content.Context | ||||||||||||||
import android.util.AttributeSet | ||||||||||||||
import android.util.Log | ||||||||||||||
import android.view.ViewGroup | ||||||||||||||
import android.widget.LinearLayout | ||||||||||||||
import androidx.core.view.children | ||||||||||||||
import java.util.* | ||||||||||||||
|
||||||||||||||
class CalendarView @JvmOverloads | ||||||||||||||
constructor( | ||||||||||||||
context: Context, | ||||||||||||||
attrs: AttributeSet? = null, | ||||||||||||||
defStyleAttr: Int = 0 | ||||||||||||||
) : ViewGroup(context, attrs, defStyleAttr) { | ||||||||||||||
fun drawCalendar(dateObject: Date) { | ||||||||||||||
val dateCalendar = Calendar.getInstance() | ||||||||||||||
dateCalendar.time = dateObject | ||||||||||||||
dateCalendar.set(Calendar.DATE, 1) | ||||||||||||||
val year = dateCalendar.get(Calendar.YEAR) | ||||||||||||||
val month = dateCalendar.get(Calendar.MONTH) + 1 | ||||||||||||||
val firstDayOfMonth = dateCalendar.get(Calendar.DAY_OF_WEEK) - 1 | ||||||||||||||
val lastDateOfMonth = dateCalendar.getActualMaximum(Calendar.DATE) | ||||||||||||||
Comment on lines
+23
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 변수명 굳 |
||||||||||||||
dateCalendar.set(Calendar.MONTH, month - 2) | ||||||||||||||
val lastDateOfLastMonth = dateCalendar.getActualMaximum(Calendar.DATE) | ||||||||||||||
if (firstDayOfMonth != 6) { | ||||||||||||||
for (blank in (lastDateOfLastMonth - firstDayOfMonth)..lastDateOfLastMonth) { | ||||||||||||||
addView(CalendarItemView(context = context, date = blank, isPrevious = true)) | ||||||||||||||
} | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
} | ||||||||||||||
for (date in 1..lastDateOfMonth) { | ||||||||||||||
if (date % 2 == 0) addView( | ||||||||||||||
CalendarItemView( | ||||||||||||||
context = context, | ||||||||||||||
date = date, | ||||||||||||||
catchuList = arrayOf(1, 2, 3) | ||||||||||||||
) | ||||||||||||||
) | ||||||||||||||
else addView(CalendarItemView(context = context, date = date)) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
override fun onLayout(p0: Boolean, p1: Int, p2: Int, p3: Int, p4: Int) { | ||||||||||||||
val iWidth = (width / 7).toFloat() | ||||||||||||||
val iHeight = (width / 7).toFloat() | ||||||||||||||
var index = 0 | ||||||||||||||
children.forEach { view -> | ||||||||||||||
val left = (index % 7) * iWidth | ||||||||||||||
val top = (index / 7) * iHeight | ||||||||||||||
view.layout(left.toInt(), top.toInt(), (left + iWidth).toInt(), (top + iHeight).toInt()) | ||||||||||||||
index++ | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.teamcatchme.calendar_customview | ||
|
||
import androidx.appcompat.app.AppCompatActivity | ||
import android.os.Bundle | ||
import com.teamcatchme.catchmesample.R | ||
import com.teamcatchme.catchmesample.databinding.ActivityCustomCalendarBinding | ||
|
||
class CustomCalendarActivity : AppCompatActivity() { | ||
lateinit var binding: ActivityCustomCalendarBinding | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
binding = ActivityCustomCalendarBinding.inflate(layoutInflater) | ||
setContentView(binding.root) | ||
initCalendar() | ||
} | ||
|
||
private fun initCalendar() { | ||
val calendarAdapter = CustomCalendarAdapter(this) | ||
binding.viewpagerCustomCalendar.apply { | ||
adapter = calendarAdapter | ||
setCurrentItem(CustomCalendarAdapter.START_POSITION, true) | ||
} | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.teamcatchme.calendar_customview | ||
|
||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.FragmentActivity | ||
import androidx.viewpager2.adapter.FragmentStateAdapter | ||
import java.util.* | ||
|
||
class CustomCalendarAdapter(fragmentActivity: FragmentActivity) : | ||
FragmentStateAdapter(fragmentActivity) { | ||
|
||
private var startTime: Calendar = Calendar.getInstance() | ||
|
||
override fun getItemCount(): Int = Int.MAX_VALUE | ||
|
||
override fun createFragment(position: Int): Fragment { | ||
val millsId = getItemId(position) | ||
return CustomCalendarFragment(millsId) | ||
} | ||
|
||
override fun getItemId(position: Int): Long { | ||
val start = startTime.clone() as Calendar | ||
start.add(Calendar.MONTH, position - START_POSITION) | ||
return start.timeInMillis | ||
} | ||
|
||
companion object { | ||
const val START_POSITION = Int.MAX_VALUE / 2 | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package com.teamcatchme.calendar_customview | ||
|
||
import android.os.Bundle | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import androidx.fragment.app.Fragment | ||
import com.teamcatchme.catchmesample.databinding.FragmentCustomCalendarBinding | ||
import java.util.* | ||
|
||
class CustomCalendarFragment(private val millsId: Long) : Fragment() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 프래그먼트 생성자는 무조건 빈 걸로 둬야한다고 하네요! 알아두시면 좋을 것 같습니다 그래서 정적 패토리 패턴을 쓰라고 했던거 ㅇㅇ |
||
private var _binding: FragmentCustomCalendarBinding? = null | ||
private val binding: FragmentCustomCalendarBinding | ||
get() = requireNotNull(_binding) | ||
|
||
override fun onCreateView( | ||
inflater: LayoutInflater, | ||
container: ViewGroup?, | ||
savedInstanceState: Bundle? | ||
): View { | ||
_binding = FragmentCustomCalendarBinding.inflate(inflater, container, false) | ||
initView() | ||
return binding.root | ||
} | ||
|
||
private fun initView() { | ||
val date = Date(millsId) | ||
binding.text.text = date.toString() | ||
binding.calendarView.drawCalendar(date) | ||
} | ||
|
||
override fun onDestroyView() { | ||
super.onDestroyView() | ||
_binding = null | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
package com.teamcatchme.calendar_customview | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import android.graphics.Bitmap | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import android.graphics.Canvas | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import android.graphics.drawable.BitmapDrawable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import android.graphics.drawable.Drawable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fun drawableToBitmap(drawable: Drawable): Bitmap? { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (drawable is BitmapDrawable) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return drawable.bitmap | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
val bitmap = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Bitmap.createBitmap( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
drawable.intrinsicWidth, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
drawable.intrinsicHeight, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Bitmap.Config.ARGB_8888 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
val canvas = Canvas(bitmap) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
drawable.draw(canvas) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return bitmap | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
이런식으로도 변형 가능(이건 그냥 내 스타일이어서 취사 선택 해주시길 바람!) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:app="http://schemas.android.com/apk/res-auto" | ||
xmlns:tools="http://schemas.android.com/tools" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" | ||
tools:context="com.teamcatchme.calendar_customview.CustomCalendarActivity"> | ||
|
||
<androidx.viewpager2.widget.ViewPager2 | ||
android:id="@+id/viewpager_custom_calendar" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" /> | ||
|
||
</androidx.constraintlayout.widget.ConstraintLayout> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:app="http://schemas.android.com/apk/res-auto" | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent"> | ||
|
||
<TextView | ||
android:id="@+id/text" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
app:layout_constraintTop_toTopOf="parent" /> | ||
|
||
<com.teamcatchme.calendar_customview.CalendarView | ||
android:id="@+id/calendar_view" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
app:layout_constraintTop_toBottomOf="@id/text" /> | ||
</androidx.constraintlayout.widget.ConstraintLayout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
버전 11로 올리기!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
왁 큰일날뻔!! 감사형광등~