라이브 만들기

- 메뉴판 설정 추가
This commit is contained in:
klaus 2024-03-07 02:29:38 +09:00
parent d7d43bc7be
commit 2e24a298ff
8 changed files with 450 additions and 4 deletions

View File

@ -53,6 +53,7 @@ import kr.co.vividnext.sodalive.live.room.LiveRoomViewModel
import kr.co.vividnext.sodalive.live.room.create.LiveRoomCreateViewModel import kr.co.vividnext.sodalive.live.room.create.LiveRoomCreateViewModel
import kr.co.vividnext.sodalive.live.room.detail.LiveRoomDetailViewModel import kr.co.vividnext.sodalive.live.room.detail.LiveRoomDetailViewModel
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationMessageViewModel import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationMessageViewModel
import kr.co.vividnext.sodalive.live.room.menu.MenuApi
import kr.co.vividnext.sodalive.live.room.tag.LiveTagRepository import kr.co.vividnext.sodalive.live.room.tag.LiveTagRepository
import kr.co.vividnext.sodalive.live.room.tag.LiveTagViewModel import kr.co.vividnext.sodalive.live.room.tag.LiveTagViewModel
import kr.co.vividnext.sodalive.live.room.update.LiveRoomEditViewModel import kr.co.vividnext.sodalive.live.room.update.LiveRoomEditViewModel
@ -151,6 +152,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
single { ApiBuilder().build(get(), CanApi::class.java) } single { ApiBuilder().build(get(), CanApi::class.java) }
single { ApiBuilder().build(get(), AuthApi::class.java) } single { ApiBuilder().build(get(), AuthApi::class.java) }
single { ApiBuilder().build(get(), UserApi::class.java) } single { ApiBuilder().build(get(), UserApi::class.java) }
single { ApiBuilder().build(get(), MenuApi::class.java) }
single { ApiBuilder().build(get(), LiveApi::class.java) } single { ApiBuilder().build(get(), LiveApi::class.java) }
single { ApiBuilder().build(get(), TermsApi::class.java) } single { ApiBuilder().build(get(), TermsApi::class.java) }
single { ApiBuilder().build(get(), EventApi::class.java) } single { ApiBuilder().build(get(), EventApi::class.java) }
@ -234,7 +236,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
private val repositoryModule = module { private val repositoryModule = module {
factory { UserRepository(get()) } factory { UserRepository(get()) }
factory { TermsRepository(get()) } factory { TermsRepository(get()) }
factory { LiveRepository(get(), get()) } factory { LiveRepository(get(), get(), get()) }
factory { EventRepository(get()) } factory { EventRepository(get()) }
factory { LiveRecommendRepository(get()) } factory { LiveRecommendRepository(get()) }
factory { AuthRepository(get()) } factory { AuthRepository(get()) }

View File

@ -15,6 +15,7 @@ import kr.co.vividnext.sodalive.live.room.detail.GetRoomDetailResponse
import kr.co.vividnext.sodalive.live.room.donation.DeleteLiveRoomDonationMessage import kr.co.vividnext.sodalive.live.room.donation.DeleteLiveRoomDonationMessage
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationRequest import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationRequest
import kr.co.vividnext.sodalive.live.room.kick_out.LiveRoomKickOutRequest import kr.co.vividnext.sodalive.live.room.kick_out.LiveRoomKickOutRequest
import kr.co.vividnext.sodalive.live.room.menu.MenuApi
import kr.co.vividnext.sodalive.user.CreatorFollowRequestRequest import kr.co.vividnext.sodalive.user.CreatorFollowRequestRequest
import kr.co.vividnext.sodalive.user.UserApi import kr.co.vividnext.sodalive.user.UserApi
import okhttp3.MultipartBody import okhttp3.MultipartBody
@ -23,7 +24,8 @@ import java.util.TimeZone
class LiveRepository( class LiveRepository(
private val api: LiveApi, private val api: LiveApi,
private val userApi: UserApi private val userApi: UserApi,
private val menuApi: MenuApi
) { ) {
fun roomList( fun roomList(
dateString: String? = null, dateString: String? = null,
@ -230,4 +232,9 @@ class LiveRepository(
request: CancelLiveReservationRequest, request: CancelLiveReservationRequest,
token: String token: String
) = api.cancelReservation(request, authHeader = token) ) = api.cancelReservation(request, authHeader = token)
fun getAllMenu(creatorId: Long, token: String) = menuApi.getAllMenu(
creatorId = creatorId,
authHeader = token
)
} }

View File

@ -14,5 +14,8 @@ data class CreateLiveRoomRequest(
@SerializedName("beginDateTimeString") val beginDateTimeString: String? = null, @SerializedName("beginDateTimeString") val beginDateTimeString: String? = null,
@SerializedName("timezone") val timezone: String, @SerializedName("timezone") val timezone: String,
@SerializedName("type") val type: LiveRoomType, @SerializedName("type") val type: LiveRoomType,
@SerializedName("password") val password: String? = null @SerializedName("password") val password: String? = null,
@SerializedName("menuPanId") val menuPanId: Long = 0,
@SerializedName("menuPan") val menuPan: String = "",
@SerializedName("isActiveMenuPan") val isActiveMenuPan: Boolean = false
) )

View File

@ -9,6 +9,7 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
@ -127,6 +128,8 @@ class LiveRoomCreateActivity : BaseActivity<ActivityLiveRoomCreateBinding>(
viewModel.setTimeNow( viewModel.setTimeNow(
intent.getBooleanExtra(Constants.EXTRA_LIVE_TIME_NOW, true) intent.getBooleanExtra(Constants.EXTRA_LIVE_TIME_NOW, true)
) )
viewModel.getAllMenuPreset()
} }
@SuppressLint("SetTextI18n", "ClickableViewAccessibility") @SuppressLint("SetTextI18n", "ClickableViewAccessibility")
@ -295,6 +298,22 @@ class LiveRoomCreateActivity : BaseActivity<ActivityLiveRoomCreateBinding>(
} }
false false
} }
binding.ivSwitch.setOnClickListener {
viewModel.toggleIsActivateMenu()
}
binding.llSelectMenu1.setOnClickListener {
viewModel.selectMenuPreset(LiveRoomCreateViewModel.SelectedMenu.MENU_1)
}
binding.llSelectMenu2.setOnClickListener {
viewModel.selectMenuPreset(LiveRoomCreateViewModel.SelectedMenu.MENU_2)
}
binding.llSelectMenu3.setOnClickListener {
viewModel.selectMenuPreset(LiveRoomCreateViewModel.SelectedMenu.MENU_3)
}
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ -348,6 +367,15 @@ class LiveRoomCreateActivity : BaseActivity<ActivityLiveRoomCreateBinding>(
} }
) )
compositeDisposable.add(
binding.etMenu.textChanges().skip(1)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
viewModel.menu = it.toString()
}
)
viewModel.toastLiveData.observe(this) { viewModel.toastLiveData.observe(this) {
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() } it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
} }
@ -573,6 +601,44 @@ class LiveRoomCreateActivity : BaseActivity<ActivityLiveRoomCreateBinding>(
else -> binding.rlPrice.isSelected = true else -> binding.rlPrice.isSelected = true
} }
} }
viewModel.isActivateMenuLiveData.observe(this) {
if (it) {
binding.llEditMenu.visibility = View.VISIBLE
binding.ivSwitch.setImageResource(R.drawable.btn_toggle_on_big)
} else {
binding.llEditMenu.visibility = View.GONE
binding.ivSwitch.setImageResource(R.drawable.btn_toggle_off_big)
}
}
viewModel.selectedMenuLiveData.observe(this) {
deselectAllMenuPreset()
when(it) {
LiveRoomCreateViewModel.SelectedMenu.MENU_2 -> selectMenuPresetButton(
binding.ivSelectMenu2,
binding.llSelectMenu2,
binding.tvSelectMenu2
)
LiveRoomCreateViewModel.SelectedMenu.MENU_3 -> selectMenuPresetButton(
binding.ivSelectMenu3,
binding.llSelectMenu3,
binding.tvSelectMenu3
)
else -> selectMenuPresetButton(
binding.ivSelectMenu1,
binding.llSelectMenu1,
binding.tvSelectMenu1
)
}
}
viewModel.menuLiveData.observe(this) {
binding.etMenu.setText(it)
}
} }
} }
@ -613,4 +679,69 @@ class LiveRoomCreateActivity : BaseActivity<ActivityLiveRoomCreateBinding>(
R.font.gmarket_sans_bold R.font.gmarket_sans_bold
) )
} }
private fun deselectAllMenuPreset() {
binding.ivSelectMenu1.visibility = View.GONE
binding.ivSelectMenu2.visibility = View.GONE
binding.ivSelectMenu3.visibility = View.GONE
binding.llSelectMenu1.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b)
binding.tvSelectMenu1.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_3bb9f1
)
)
if (viewModel.menuList.size > 0) {
binding.llSelectMenu2.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b)
binding.tvSelectMenu2.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_3bb9f1
)
)
} else {
binding.llSelectMenu2.setBackgroundResource(R.drawable.bg_round_corner_6_7_777777)
binding.tvSelectMenu2.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_555555
)
)
}
if (viewModel.menuList.size > 1) {
binding.llSelectMenu3.setBackgroundResource(R.drawable.bg_round_corner_6_7_13181b)
binding.tvSelectMenu3.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_3bb9f1
)
)
} else {
binding.llSelectMenu3.setBackgroundResource(R.drawable.bg_round_corner_6_7_777777)
binding.tvSelectMenu3.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_555555
)
)
}
}
private fun selectMenuPresetButton(
ivSelectRoulette: ImageView,
llSelectRoulette: LinearLayout,
tvSelectRoulette: TextView
) {
ivSelectRoulette.visibility = View.VISIBLE
llSelectRoulette.setBackgroundResource(R.drawable.bg_round_corner_6_7_3bb9f1)
tvSelectRoulette.setTextColor(
ContextCompat.getColor(
applicationContext,
R.color.color_eeeeee
)
)
}
} }

View File

@ -11,6 +11,7 @@ import kr.co.vividnext.sodalive.base.BaseViewModel
import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.live.LiveRepository import kr.co.vividnext.sodalive.live.LiveRepository
import kr.co.vividnext.sodalive.live.room.LiveRoomType import kr.co.vividnext.sodalive.live.room.LiveRoomType
import kr.co.vividnext.sodalive.live.room.menu.GetMenuResponse
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.asRequestBody
@ -22,6 +23,10 @@ class LiveRoomCreateViewModel(
private val repository: LiveRepository private val repository: LiveRepository
) : BaseViewModel() { ) : BaseViewModel() {
enum class SelectedMenu {
MENU_1, MENU_2, MENU_3
}
private val _roomTypeLiveData = MutableLiveData(LiveRoomType.OPEN) private val _roomTypeLiveData = MutableLiveData(LiveRoomType.OPEN)
val roomTypeLiveData: LiveData<LiveRoomType> val roomTypeLiveData: LiveData<LiveRoomType>
get() = _roomTypeLiveData get() = _roomTypeLiveData
@ -58,6 +63,18 @@ class LiveRoomCreateViewModel(
val isAdultLiveData: LiveData<Boolean> val isAdultLiveData: LiveData<Boolean>
get() = _isAdultLiveData get() = _isAdultLiveData
private val _selectedMenuLiveData = MutableLiveData<SelectedMenu>()
val selectedMenuLiveData: LiveData<SelectedMenu>
get() = _selectedMenuLiveData
private val _isActivateMenuLiveData = MutableLiveData(false)
val isActivateMenuLiveData: LiveData<Boolean>
get() = _isActivateMenuLiveData
private val _menuLiveData = MutableLiveData("")
val menuLiveData: LiveData<String>
get() = _menuLiveData
lateinit var getRealPathFromURI: (Uri) -> String? lateinit var getRealPathFromURI: (Uri) -> String?
var title = "" var title = ""
@ -70,6 +87,10 @@ class LiveRoomCreateViewModel(
var coverImagePath: String? = null var coverImagePath: String? = null
var password: String? = null var password: String? = null
private var menuId = 0L
var menu = ""
val menuList = mutableListOf<GetMenuResponse>()
fun setRoomType(roomType: LiveRoomType) { fun setRoomType(roomType: LiveRoomType) {
if (_roomTypeLiveData.value!! != roomType) { if (_roomTypeLiveData.value!! != roomType) {
_roomTypeLiveData.postValue(roomType) _roomTypeLiveData.postValue(roomType)
@ -115,7 +136,18 @@ class LiveRoomCreateViewModel(
password password
} else { } else {
null null
} },
menuPanId = if (_isActivateMenuLiveData.value!!) {
menuId
} else {
0
},
menuPan = if (_isActivateMenuLiveData.value!!) {
menu
} else {
""
},
isActiveMenuPan = _isActivateMenuLiveData.value!!
) )
val requestJson = Gson().toJson(request) val requestJson = Gson().toJson(request)
@ -207,6 +239,11 @@ class LiveRoomCreateViewModel(
return false return false
} }
if (_isActivateMenuLiveData.value!! && menu.isBlank()) {
_toastLiveData.postValue("메뉴판은 빈칸일 수 없습니다.")
return false
}
return true return true
} }
@ -252,4 +289,82 @@ class LiveRoomCreateViewModel(
) )
) )
} }
fun selectMenuPreset(selectedMenuPreset: SelectedMenu) {
if (
menuList.isEmpty() &&
(
selectedMenuPreset == SelectedMenu.MENU_2 ||
selectedMenuPreset == SelectedMenu.MENU_3
)
) {
_toastLiveData.value = "메뉴 1을 먼저 설정하세요"
return
}
if (menuList.size == 1 && selectedMenuPreset == SelectedMenu.MENU_3) {
_toastLiveData.value = "메뉴 1과 메뉴 2를 먼저 설정하세요"
return
}
if (_selectedMenuLiveData.value != selectedMenuPreset) {
_selectedMenuLiveData.value = selectedMenuPreset
if (menuList.size > selectedMenuPreset.ordinal) {
val menuPreset = menuList[selectedMenuPreset.ordinal]
_menuLiveData.value = menuPreset.menu
menu = menuPreset.menu
menuId = menuPreset.id
} else {
_menuLiveData.value = ""
menu = ""
menuId = 0
}
}
}
fun toggleIsActivateMenu() {
_isActivateMenuLiveData.value = !_isActivateMenuLiveData.value!!
}
fun getAllMenuPreset() {
_isLoading.value = true
compositeDisposable.add(
repository.getAllMenu(
creatorId = SharedPreferenceManager.userId,
token = "Bearer ${SharedPreferenceManager.token}"
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
if (it.success) {
val data = it.data
menuList.clear()
menuList.addAll(data ?: listOf())
selectMenuPreset(SelectedMenu.MENU_1)
Logger.e("data: $data")
} else {
if (it.message != null) {
_toastLiveData.postValue(it.message)
} else {
_toastLiveData.postValue(
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
)
}
}
_isLoading.value = false
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
}
)
)
}
} }

View File

@ -0,0 +1,8 @@
package kr.co.vividnext.sodalive.live.room.menu
import com.google.gson.annotations.SerializedName
data class GetMenuResponse(
@SerializedName("id") val id: Long,
@SerializedName("menu") val menu: String
)

View File

@ -0,0 +1,15 @@
package kr.co.vividnext.sodalive.live.room.menu
import io.reactivex.rxjava3.core.Single
import kr.co.vividnext.sodalive.common.ApiResponse
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query
interface MenuApi {
@GET("/live/room/menu/all")
fun getAllMenu(
@Query("creatorId") creatorId: Long,
@Header("Authorization") authHeader: String
): Single<ApiResponse<List<GetMenuResponse>>>
}

View File

@ -111,6 +111,7 @@
android:id="@+id/et_title" android:id="@+id/et_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="13.3dp"
android:background="@drawable/edittext_underline" android:background="@drawable/edittext_underline"
android:fontFamily="@font/gmarket_sans_medium" android:fontFamily="@font/gmarket_sans_medium"
android:hint="라이브 제목을 입력해주세요." android:hint="라이브 제목을 입력해주세요."
@ -175,6 +176,7 @@
android:id="@+id/et_notice" android:id="@+id/et_notice"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="200dp"
android:layout_marginTop="13.3dp"
android:background="@drawable/bg_round_corner_6_7_222222" android:background="@drawable/bg_round_corner_6_7_222222"
android:fontFamily="@font/gmarket_sans_medium" android:fontFamily="@font/gmarket_sans_medium"
android:gravity="top" android:gravity="top"
@ -192,6 +194,169 @@
tools:ignore="LabelFor" /> tools:ignore="LabelFor" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="33.3dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_bold"
android:text="메뉴"
android:textColor="@color/color_eeeeee"
android:textSize="16.7sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:fontFamily="@font/gmarket_sans_medium"
android:lineSpacingExtra="5sp"
android:text="메뉴를 활성화 하시겠습니까?"
android:textColor="@color/color_eeeeee"
android:textSize="13.3sp" />
<ImageView
android:id="@+id/iv_switch"
android:layout_width="33.3dp"
android:layout_height="20dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:contentDescription="@null"
android:src="@drawable/btn_toggle_off_big" />
</RelativeLayout>
<LinearLayout
android:id="@+id/ll_edit_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="13.3dp"
android:orientation="vertical"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/ll_select_menu_1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/bg_round_corner_6_7_13181b"
android:gravity="center"
android:paddingVertical="14.3dp">
<ImageView
android:id="@+id/iv_select_menu_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6.7dp"
android:contentDescription="@null"
android:src="@drawable/ic_select_check"
android:visibility="gone" />
<TextView
android:id="@+id/tv_select_menu_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_bold"
android:text="메뉴 1"
android:textColor="@color/color_3bb9f1"
android:textSize="14.7sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_select_menu_2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="13.3dp"
android:layout_weight="1"
android:background="@drawable/bg_round_corner_6_7_777777"
android:gravity="center"
android:paddingVertical="14.3dp">
<ImageView
android:id="@+id/iv_select_menu_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6.7dp"
android:contentDescription="@null"
android:src="@drawable/ic_select_check"
android:visibility="gone" />
<TextView
android:id="@+id/tv_select_menu_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_bold"
android:text="메뉴 2"
android:textColor="@color/color_555555"
android:textSize="14.7sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_select_menu_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="13.3dp"
android:layout_weight="1"
android:background="@drawable/bg_round_corner_6_7_777777"
android:gravity="center"
android:paddingVertical="14.3dp">
<ImageView
android:id="@+id/iv_select_menu_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6.7dp"
android:contentDescription="@null"
android:src="@drawable/ic_select_check"
android:visibility="gone" />
<TextView
android:id="@+id/tv_select_menu_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_bold"
android:text="메뉴 3"
android:textColor="@color/color_555555"
android:textSize="14.7sp" />
</LinearLayout>
</LinearLayout>
<EditText
android:id="@+id/et_menu"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="13.3dp"
android:background="@drawable/bg_round_corner_6_7_222222"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="top"
android:hint="메뉴판을 작성해주세요."
android:importantForAutofill="no"
android:inputType="textMultiLine"
android:overScrollMode="always"
android:padding="20dp"
android:scrollbarStyle="insideInset"
android:scrollbars="vertical"
android:textColor="@color/color_eeeeee"
android:textColorHint="@color/color_777777"
android:textCursorDrawable="@drawable/edit_text_cursor"
android:textSize="13.3sp"
tools:ignore="LabelFor" />
</LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"