Compare commits
No commits in common. "81faf3f7ee07d3d169c945f5eb45700e7578fcfa" and "b876695adc886b4ae04b8409165a7ebc6f23ed2f" have entirely different histories.
81faf3f7ee
...
b876695adc
|
@ -40,8 +40,8 @@ android {
|
|||
applicationId "kr.co.vividnext.sodalive"
|
||||
minSdk 23
|
||||
targetSdk 33
|
||||
versionCode 92
|
||||
versionName "1.14.1"
|
||||
versionCode 74
|
||||
versionName "1.11.3"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -51,7 +51,6 @@ android {
|
|||
|
||||
buildConfigField 'String', 'BASE_URL', '"https://api.sodalive.net"'
|
||||
buildConfigField 'String', 'BOOTPAY_APP_ID', '"64c35be1d25985001dc50c87"'
|
||||
buildConfigField 'String', 'BOOTPAY_APP_HECTO_ID', '"664c1707b18b225deca4b429"'
|
||||
buildConfigField 'String', 'AGORA_APP_ID', '"e34e40046e9847baba3adfe2b8ffb4f6"'
|
||||
buildConfigField 'String', 'AGORA_APP_CERTIFICATE', '"15cadeea4ba94ff7b091c9a10f4bf4a6"'
|
||||
}
|
||||
|
@ -63,7 +62,6 @@ android {
|
|||
|
||||
buildConfigField 'String', 'BASE_URL', '"https://test-api.sodalive.net"'
|
||||
buildConfigField 'String', 'BOOTPAY_APP_ID', '"6242a7772701800023f68b2e"'
|
||||
buildConfigField 'String', 'BOOTPAY_APP_HECTO_ID', '"667fca5d3bab7404f831c3e4"'
|
||||
buildConfigField 'String', 'AGORA_APP_ID', '"b96574e191a9430fa54c605528aa3ef7"'
|
||||
buildConfigField 'String', 'AGORA_APP_CERTIFICATE', '"ae18ade3afcf4086bd4397726eb0654c"'
|
||||
}
|
||||
|
@ -154,9 +152,4 @@ dependencies {
|
|||
|
||||
// google in-app-purchase
|
||||
implementation "com.android.billingclient:billing-ktx:6.2.0"
|
||||
|
||||
// ROOM
|
||||
kapt "androidx.room:room-compiler:2.5.0"
|
||||
implementation "androidx.room:room-ktx:2.5.0"
|
||||
implementation "androidx.room:room-runtime:2.5.0"
|
||||
}
|
||||
|
|
|
@ -39,13 +39,6 @@
|
|||
android:maxSdkVersion="32"
|
||||
tools:ignore="ScopedStorage" />
|
||||
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -145,20 +138,6 @@
|
|||
<activity android:name=".audio_content.series.detail.SeriesDetailActivity" />
|
||||
<activity android:name=".audio_content.series.content.SeriesContentAllActivity" />
|
||||
|
||||
<activity android:name=".mypage.alarm.AlarmListActivity" />
|
||||
<activity android:name=".mypage.alarm.AddAlarmActivity" />
|
||||
<activity android:name=".mypage.alarm.select_audio_content.AlarmSelectAudioContentActivity" />
|
||||
<activity
|
||||
android:name=".mypage.alarm.AlarmActivity"
|
||||
android:exported="true"
|
||||
android:showWhenLocked="true"
|
||||
android:turnScreenOn="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.example.alarmapp.ALARM_ACTION" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
|
||||
android:theme="@style/Theme.AppCompat.DayNight" />
|
||||
|
@ -186,21 +165,6 @@
|
|||
</service>
|
||||
<!-- [END firebase_service] -->
|
||||
|
||||
<!-- 부팅 시 알람 재설정을 위한 리시버 -->
|
||||
<receiver
|
||||
android:name=".mypage.alarm.receiver.AlarmBootReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".mypage.alarm.receiver.AlarmReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- [START fcm_default_channel] -->
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||
|
|
|
@ -40,25 +40,12 @@ class AudioContentAdapter(
|
|||
binding.tvLikeCount.text = item.likeCount.moneyFormat()
|
||||
binding.tvCommentCount.text = item.commentCount.moneyFormat()
|
||||
|
||||
binding.tvPrice.visibility = View.GONE
|
||||
binding.tvOwned.visibility = View.GONE
|
||||
binding.tvRented.visibility = View.GONE
|
||||
binding.tvSoldOut.visibility = View.GONE
|
||||
|
||||
binding.tvScheduledToOpen.visibility = if (item.isScheduledToOpen) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
if (item.isOwned) {
|
||||
binding.tvOwned.visibility = View.VISIBLE
|
||||
} else if (item.isRented) {
|
||||
binding.tvRented.visibility = View.VISIBLE
|
||||
} else if (item.isSoldOut) {
|
||||
binding.tvSoldOut.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.tvPrice.visibility = View.VISIBLE
|
||||
if (item.price < 1) {
|
||||
binding.tvPrice.text = "무료"
|
||||
binding.tvPrice.setCompoundDrawables(null, null, null, null)
|
||||
|
@ -71,7 +58,6 @@ class AudioContentAdapter(
|
|||
0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener { onClickItem(item.contentId) }
|
||||
}
|
||||
|
|
|
@ -34,11 +34,9 @@ class AudioContentOrderFragment(
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (SharedPreferenceManager.userId == 17958L) {
|
||||
binding.tvKeepDate.text = "(이용기간 1년)"
|
||||
binding.ivKeepCan.visibility = View.GONE
|
||||
binding.ivRentalCan.visibility = View.GONE
|
||||
} else {
|
||||
binding.tvKeepDate.text = "(서비스 종료시까지)"
|
||||
binding.ivKeepCan.visibility = View.VISIBLE
|
||||
binding.ivRentalCan.visibility = View.VISIBLE
|
||||
}
|
||||
|
|
|
@ -48,11 +48,10 @@ class AudioContentOrderListViewModel(
|
|||
{
|
||||
if (it.success && it.data != null) {
|
||||
_totalCount.value = it.data.totalCount
|
||||
page += 1
|
||||
if (it.data.items.isNotEmpty()) {
|
||||
page += 1
|
||||
_orderList.postValue(it.data.items)
|
||||
} else {
|
||||
_orderList.postValue(listOf())
|
||||
isLast = true
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -153,11 +153,6 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||
override fun setupView() {
|
||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||
|
||||
binding.tvServiceDate.text = if (SharedPreferenceManager.userId == 17958L) {
|
||||
"※ 이용기간 : 대여(15일) | 소장(이용 기간 1년)"
|
||||
} else {
|
||||
"※ 이용기간 : 대여(15일) | 소장(서비스 종료시까지)"
|
||||
}
|
||||
binding.toolbar.tvBack.text = "콘텐츠 등록"
|
||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||
binding.llTheme.setOnClickListener {
|
||||
|
@ -204,8 +199,6 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||
binding.llPriceFree.setOnClickListener { viewModel.setPriceFree(true) }
|
||||
binding.llPreviewYes.setOnClickListener { viewModel.setGeneratePreview(true) }
|
||||
binding.llPreviewNo.setOnClickListener { viewModel.setGeneratePreview(false) }
|
||||
binding.llLimited.setOnClickListener { viewModel.setLimited(true) }
|
||||
binding.llNotLimited.setOnClickListener { viewModel.setLimited(false) }
|
||||
binding.llRentalAndKeep.setOnClickListener { viewModel.setIsOnlyRental(false) }
|
||||
binding.llOnlyRental.setOnClickListener { viewModel.setIsOnlyRental(true) }
|
||||
binding.llCommentNo.setOnClickListener { viewModel.setAvailableComment(false) }
|
||||
|
@ -364,24 +357,6 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||
}
|
||||
)
|
||||
|
||||
compositeDisposable.add(
|
||||
binding.etLimited.textChanges().skip(1)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
val limited = it.toString().toIntOrNull()
|
||||
if (limited != null) {
|
||||
viewModel.limited = limited.toInt()
|
||||
} else {
|
||||
viewModel.limited = 0
|
||||
if (it.isNotBlank()) {
|
||||
binding.etLimited.setText(it.substring(0, it.length - 1))
|
||||
binding.etLimited.setSelection(it.length - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
compositeDisposable.add(
|
||||
binding.etPreviewStartTime.textChanges().skip(1)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
@ -428,14 +403,6 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.isLimitedLiveData.observe(this) {
|
||||
if (it) {
|
||||
checkLimited()
|
||||
} else {
|
||||
checkNotLimited()
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.isGeneratePreviewLiveData.observe(this) {
|
||||
if (it) {
|
||||
checkGeneratePreview()
|
||||
|
@ -560,18 +527,6 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||
viewModel.reservationTimeLiveData.observe(this) {
|
||||
binding.tvReservationTime.text = it
|
||||
}
|
||||
|
||||
viewModel.isShowConfigLimitedLiveData.observe(this) {
|
||||
if (it) {
|
||||
binding.llConfigLimited.visibility = View.VISIBLE
|
||||
binding.tvConfigLimitedTitle.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.llConfigLimited.visibility = View.GONE
|
||||
binding.tvConfigLimitedTitle.visibility = View.GONE
|
||||
binding.etLimited.visibility = View.GONE
|
||||
binding.etLimited.setText("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkActiveNow() {
|
||||
|
@ -679,53 +634,6 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||
binding.llConfigPreview.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun checkNotLimited() {
|
||||
binding.ivNotLimited.visibility = View.VISIBLE
|
||||
binding.tvNotLimited.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_eeeeee
|
||||
)
|
||||
)
|
||||
binding.llNotLimited.setBackgroundResource(R.drawable.bg_round_corner_6_7_3bb9f1)
|
||||
|
||||
binding.ivLimited.visibility = View.GONE
|
||||
binding.tvLimited.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_3bb9f1
|
||||
)
|
||||
)
|
||||
binding.llLimited.setBackgroundResource(
|
||||
R.drawable.bg_round_corner_6_7_13181b
|
||||
)
|
||||
binding.etLimited.visibility = View.GONE
|
||||
binding.etLimited.setText("")
|
||||
}
|
||||
|
||||
private fun checkLimited() {
|
||||
binding.ivLimited.visibility = View.VISIBLE
|
||||
binding.tvLimited.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_eeeeee
|
||||
)
|
||||
)
|
||||
binding.llLimited.setBackgroundResource(R.drawable.bg_round_corner_6_7_3bb9f1)
|
||||
|
||||
binding.ivNotLimited.visibility = View.GONE
|
||||
binding.tvNotLimited.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_3bb9f1
|
||||
)
|
||||
)
|
||||
binding.llNotLimited.setBackgroundResource(
|
||||
R.drawable.bg_round_corner_6_7_13181b
|
||||
)
|
||||
binding.etLimited.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun checkGeneratePreview() {
|
||||
binding.ivPreviewYes.visibility = View.VISIBLE
|
||||
binding.tvPreviewYes.setTextColor(
|
||||
|
|
|
@ -50,14 +50,6 @@ class AudioContentUploadViewModel(
|
|||
val isPriceFreeLiveData: LiveData<Boolean>
|
||||
get() = _isPriceFreeLiveData
|
||||
|
||||
private val _isLimitedLiveData = MutableLiveData(false)
|
||||
val isLimitedLiveData: LiveData<Boolean>
|
||||
get() = _isLimitedLiveData
|
||||
|
||||
private val _isShowConfigLimitedLiveData = MutableLiveData(false)
|
||||
val isShowConfigLimitedLiveData: LiveData<Boolean>
|
||||
get() = _isShowConfigLimitedLiveData
|
||||
|
||||
private val _isGeneratePreviewLiveData = MutableLiveData(true)
|
||||
val isGeneratePreviewLiveData: LiveData<Boolean>
|
||||
get() = _isGeneratePreviewLiveData
|
||||
|
@ -80,7 +72,6 @@ class AudioContentUploadViewModel(
|
|||
var detail = ""
|
||||
var tags = ""
|
||||
var price = 0
|
||||
var limited = 0
|
||||
var releaseDate = ""
|
||||
var releaseTime = ""
|
||||
var theme: GetAudioContentThemeResponse? = null
|
||||
|
@ -102,14 +93,7 @@ class AudioContentUploadViewModel(
|
|||
|
||||
if (isPriceFree) {
|
||||
_isOnlyRentalLiveData.postValue(false)
|
||||
_isShowConfigLimitedLiveData.postValue(false)
|
||||
_isLimitedLiveData.postValue(false)
|
||||
limited = 0
|
||||
_isGeneratePreviewLiveData.postValue(true)
|
||||
} else {
|
||||
if (!_isOnlyRentalLiveData.value!!) {
|
||||
_isShowConfigLimitedLiveData.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,26 +101,8 @@ class AudioContentUploadViewModel(
|
|||
_isGeneratePreviewLiveData.value = isGeneratePreview
|
||||
}
|
||||
|
||||
fun setLimited(isLimited: Boolean) {
|
||||
_isLimitedLiveData.value = isLimited
|
||||
|
||||
if (!isLimited) {
|
||||
limited = 0
|
||||
}
|
||||
}
|
||||
|
||||
fun setIsOnlyRental(isOnlyRental: Boolean) {
|
||||
_isOnlyRentalLiveData.postValue(isOnlyRental)
|
||||
|
||||
if (isOnlyRental) {
|
||||
_isShowConfigLimitedLiveData.postValue(false)
|
||||
_isLimitedLiveData.postValue(false)
|
||||
limited = 0
|
||||
} else {
|
||||
if (!_isPriceFreeLiveData.value!!) {
|
||||
_isShowConfigLimitedLiveData.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setActiveReservation(isActiveReservation: Boolean) {
|
||||
|
@ -154,17 +120,6 @@ class AudioContentUploadViewModel(
|
|||
detail = detail,
|
||||
tags = tags,
|
||||
price = price,
|
||||
limited = if (
|
||||
price > 0 &&
|
||||
limited > 0 &&
|
||||
_isLimitedLiveData.value!! &&
|
||||
_isShowConfigLimitedLiveData.value!! &&
|
||||
!_isPriceFreeLiveData.value!!
|
||||
) {
|
||||
limited
|
||||
} else {
|
||||
null
|
||||
},
|
||||
releaseDate = if (_isActiveReservationLiveData.value!!) {
|
||||
"$releaseDate $releaseTime"
|
||||
} else {
|
||||
|
@ -188,8 +143,6 @@ class AudioContentUploadViewModel(
|
|||
}
|
||||
)
|
||||
|
||||
Logger.e("test - $request")
|
||||
|
||||
val requestJson = Gson().toJson(request)
|
||||
|
||||
val coverImage = if (coverImageUri != null) {
|
||||
|
|
|
@ -7,7 +7,6 @@ data class CreateAudioContentRequest(
|
|||
@SerializedName("detail") val detail: String,
|
||||
@SerializedName("tags") val tags: String,
|
||||
@SerializedName("price") val price: Int,
|
||||
@SerializedName("limited") val limited: Int? = null,
|
||||
@SerializedName("releaseDate") val releaseDate: String?,
|
||||
@SerializedName("timezone") val timezone: String,
|
||||
@SerializedName("themeId") val themeId: Long,
|
||||
|
|
|
@ -19,7 +19,6 @@ object Constants {
|
|||
const val EXTRA_CAN = "extra_can"
|
||||
const val EXTRA_DATA = "extra_data"
|
||||
const val EXTRA_TERMS = "extra_terms"
|
||||
const val EXTRA_PRIVACY = "extra_privacy"
|
||||
const val EXTRA_EVENT = "extra_event"
|
||||
const val EXTRA_SERIES = "extra_series"
|
||||
const val EXTRA_NOTICE = "extra_notice"
|
||||
|
@ -53,7 +52,6 @@ object Constants {
|
|||
const val EXTRA_AUDIO_CONTENT_COMMENT = "audio_content_comment"
|
||||
const val EXTRA_AUDIO_CONTENT_LOADING = "audio_content_loading"
|
||||
const val EXTRA_AUDIO_CONTENT_CREATOR_ID = "audio_content_creator_id"
|
||||
const val EXTRA_AUDIO_CONTENT_CREATOR_NICKNAME = "audio_content_creator_nickname"
|
||||
const val EXTRA_AUDIO_CONTENT_CURATION_ID = "extra_audio_content_curation_id"
|
||||
const val EXTRA_AUDIO_CONTENT_CURATION_TITLE = "extra_audio_content_curation_title"
|
||||
const val EXTRA_AUDIO_CONTENT_NEXT_ACTION = "audio_content_next_action"
|
||||
|
@ -67,6 +65,4 @@ object Constants {
|
|||
const val EXTRA_COMMUNITY_POST_ID = "community_post_id"
|
||||
const val EXTRA_COMMUNITY_CREATOR_ID = "community_creator_id"
|
||||
const val EXTRA_COMMUNITY_POST_COMMENT = "community_post_comment_id"
|
||||
|
||||
const val EXTRA_ALARM_ID = "alarm_id"
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.common
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
class Converter {
|
||||
@TypeConverter
|
||||
fun fromString(value: String): List<String> {
|
||||
val listType = object : TypeToken<List<String>>() {}.type
|
||||
return Gson().fromJson(value, listType)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromList(list: List<String>): String {
|
||||
return Gson().toJson(list)
|
||||
}
|
||||
}
|
|
@ -75,9 +75,6 @@ import kr.co.vividnext.sodalive.message.text.TextMessageWriteViewModel
|
|||
import kr.co.vividnext.sodalive.message.voice.VoiceMessageViewModel
|
||||
import kr.co.vividnext.sodalive.message.voice.VoiceMessageWriteViewModel
|
||||
import kr.co.vividnext.sodalive.mypage.MyPageViewModel
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.AlarmListApi
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.AlarmListRepository
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.AlarmListViewModel
|
||||
import kr.co.vividnext.sodalive.mypage.auth.AuthApi
|
||||
import kr.co.vividnext.sodalive.mypage.auth.AuthRepository
|
||||
import kr.co.vividnext.sodalive.mypage.can.CanApi
|
||||
|
@ -165,7 +162,6 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
|||
.build()
|
||||
}
|
||||
|
||||
single { ApiBuilder().build(get(), AlarmListApi::class.java) }
|
||||
single { ApiBuilder().build(get(), CanApi::class.java) }
|
||||
single { ApiBuilder().build(get(), CanTempApi::class.java) }
|
||||
single { ApiBuilder().build(get(), AuthApi::class.java) }
|
||||
|
@ -255,7 +251,6 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
|||
viewModel { CreatorCommunityModifyViewModel(get()) }
|
||||
viewModel { CanCouponViewModel(get()) }
|
||||
viewModel { CanChargeIapViewModel(get()) }
|
||||
viewModel { AlarmListViewModel(get()) }
|
||||
}
|
||||
|
||||
private val repositoryModule = module {
|
||||
|
@ -282,7 +277,6 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
|||
factory { UserProfileFantalkAllViewModel(get(), get()) }
|
||||
factory { RouletteRepository(get()) }
|
||||
factory { CreatorCommunityRepository(get()) }
|
||||
factory { AlarmListRepository(get()) }
|
||||
}
|
||||
|
||||
private val moduleList = listOf(
|
||||
|
|
|
@ -81,10 +81,7 @@ data class GetAudioContentListItem(
|
|||
@SerializedName("commentCount") val commentCount: Int,
|
||||
@SerializedName("isPin") val isPin: Boolean,
|
||||
@SerializedName("isAdult") val isAdult: Boolean,
|
||||
@SerializedName("isScheduledToOpen") val isScheduledToOpen: Boolean,
|
||||
@SerializedName("isRented") val isRented: Boolean,
|
||||
@SerializedName("isOwned") val isOwned: Boolean,
|
||||
@SerializedName("isSoldOut") val isSoldOut: Boolean
|
||||
@SerializedName("isScheduledToOpen") val isScheduledToOpen: Boolean
|
||||
)
|
||||
|
||||
data class GetCreatorActivitySummary(
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.appcompat.widget.PopupMenu
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.load
|
||||
import coil.transform.BlurTransformation
|
||||
import coil.transform.CircleCropTransformation
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import kr.co.vividnext.sodalive.R
|
||||
|
@ -28,6 +27,7 @@ import kr.co.vividnext.sodalive.audio_content.AudioContentActivity
|
|||
import kr.co.vividnext.sodalive.audio_content.AudioContentAdapter
|
||||
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
||||
import kr.co.vividnext.sodalive.audio_content.series.SeriesListAdapter
|
||||
import kr.co.vividnext.sodalive.audio_content.series.SeriesListAllActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.upload.AudioContentUploadActivity
|
||||
|
@ -831,16 +831,6 @@ class UserProfileActivity : BaseActivity<ActivityUserProfileBinding>(
|
|||
crossfade(true)
|
||||
placeholder(R.drawable.ic_place_holder)
|
||||
transformations(RoundedCornersTransformation(4.7f.dpToPx()))
|
||||
|
||||
if (!item.existOrdered && item.price > 0) {
|
||||
transformations(
|
||||
BlurTransformation(
|
||||
this@UserProfileActivity,
|
||||
25f,
|
||||
2.5f
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
layout.tvLikeCount.text = "${item.likeCount}"
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creator_community
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.transform.BlurTransformation
|
||||
import coil.transform.CircleCropTransformation
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import kr.co.vividnext.sodalive.R
|
||||
|
@ -19,7 +17,6 @@ class CreatorCommunityAdapter(
|
|||
val items = mutableListOf<GetCommunityPostListResponse>()
|
||||
|
||||
inner class ViewHolder(
|
||||
private val context: Context,
|
||||
private val binding: ItemCreatorCommunityBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(item: GetCommunityPostListResponse) {
|
||||
|
@ -36,16 +33,6 @@ class CreatorCommunityAdapter(
|
|||
crossfade(true)
|
||||
placeholder(R.drawable.ic_place_holder)
|
||||
transformations(RoundedCornersTransformation(4.7f.dpToPx()))
|
||||
|
||||
if (!item.existOrdered && item.price > 0) {
|
||||
transformations(
|
||||
BlurTransformation(
|
||||
context,
|
||||
25f,
|
||||
2.5f
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.tvLikeCount.text = "${item.likeCount}"
|
||||
|
@ -56,7 +43,6 @@ class CreatorCommunityAdapter(
|
|||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
parent.context,
|
||||
ItemCreatorCommunityBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
|
|
|
@ -4,7 +4,6 @@ import io.reactivex.rxjava3.core.Single
|
|||
import kr.co.vividnext.sodalive.audio_content.comment.ModifyCommentRequest
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PostCommunityPostLikeRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PurchasePostRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.comment.CreateCommunityPostCommentRequest
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
|
@ -22,7 +21,6 @@ interface CreatorCommunityApi {
|
|||
@POST("/creator-community")
|
||||
@Multipart
|
||||
fun createCommunityPost(
|
||||
@Part audioFile: MultipartBody.Part?,
|
||||
@Part postImage: MultipartBody.Part?,
|
||||
@Part("request") request: RequestBody,
|
||||
@Header("Authorization") authHeader: String
|
||||
|
@ -93,10 +91,4 @@ interface CreatorCommunityApi {
|
|||
@Query("timezone") timezone: String,
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<GetCommunityPostListResponse>>
|
||||
|
||||
@POST("/creator-community/purchase")
|
||||
fun purchaseCommunityPost(
|
||||
@Body request: PurchasePostRequest,
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<GetCommunityPostListResponse>>
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package kr.co.vividnext.sodalive.explorer.profile.creator_community
|
|||
|
||||
import kr.co.vividnext.sodalive.audio_content.comment.ModifyCommentRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PostCommunityPostLikeRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.PurchasePostRequest
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.comment.CreateCommunityPostCommentRequest
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
|
@ -75,12 +74,10 @@ class CreatorCommunityRepository(private val api: CreatorCommunityApi) {
|
|||
)
|
||||
|
||||
fun createCommunityPost(
|
||||
audioFile: MultipartBody.Part?,
|
||||
postImage: MultipartBody.Part?,
|
||||
request: RequestBody,
|
||||
token: String
|
||||
) = api.createCommunityPost(
|
||||
audioFile = audioFile,
|
||||
postImage = postImage,
|
||||
request = request,
|
||||
authHeader = token
|
||||
|
@ -101,9 +98,4 @@ class CreatorCommunityRepository(private val api: CreatorCommunityApi) {
|
|||
timezone = TimeZone.getDefault().id,
|
||||
authHeader = token
|
||||
)
|
||||
|
||||
fun purchaseCommunityPost(postId: Long, token: String) = api.purchaseCommunityPost(
|
||||
request = PurchasePostRequest(postId = postId, timezone = TimeZone.getDefault().id),
|
||||
authHeader = token
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,14 +8,11 @@ data class GetCommunityPostListResponse(
|
|||
@SerializedName("creatorNickname") val creatorNickname: String,
|
||||
@SerializedName("creatorProfileUrl") val creatorProfileUrl: String,
|
||||
@SerializedName("imageUrl") val imageUrl: String?,
|
||||
@SerializedName("audioUrl") val audioUrl: String?,
|
||||
@SerializedName("content") val content: String,
|
||||
@SerializedName("price") val price: Int,
|
||||
@SerializedName("date") val date: String,
|
||||
@SerializedName("isCommentAvailable") val isCommentAvailable: Boolean,
|
||||
@SerializedName("isAdult") val isAdult: Boolean,
|
||||
@SerializedName("isLike") var isLike: Boolean,
|
||||
@SerializedName("existOrdered") val existOrdered: Boolean,
|
||||
@SerializedName("likeCount") val likeCount: Int,
|
||||
@SerializedName("commentCount") val commentCount: Int,
|
||||
@SerializedName("firstComment") val firstComment: GetCommunityPostCommentListItem?,
|
||||
|
|
|
@ -15,7 +15,6 @@ import kr.co.vividnext.sodalive.common.Constants
|
|||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||
import kr.co.vividnext.sodalive.databinding.ActivityCreatorCommunityAllBinding
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.comment.CreatorCommunityCommentFragment
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.player.CreatorCommunityMediaPlayerManager
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.modify.CreatorCommunityModifyActivity
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import org.koin.android.ext.android.inject
|
||||
|
@ -28,7 +27,6 @@ class CreatorCommunityAllActivity : BaseActivity<ActivityCreatorCommunityAllBind
|
|||
|
||||
private lateinit var loadingDialog: LoadingDialog
|
||||
private lateinit var adapter: CreatorCommunityAllAdapter
|
||||
private lateinit var mediaPlayerManager: CreatorCommunityMediaPlayerManager
|
||||
|
||||
private var creatorId: Long = 0
|
||||
|
||||
|
@ -47,10 +45,6 @@ class CreatorCommunityAllActivity : BaseActivity<ActivityCreatorCommunityAllBind
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mediaPlayerManager = CreatorCommunityMediaPlayerManager(this) {
|
||||
adapter.updateUI()
|
||||
}
|
||||
|
||||
creatorId = intent.getLongExtra(Constants.EXTRA_COMMUNITY_CREATOR_ID, 0)
|
||||
if (creatorId <= 0) {
|
||||
Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
|
||||
|
@ -62,23 +56,12 @@ class CreatorCommunityAllActivity : BaseActivity<ActivityCreatorCommunityAllBind
|
|||
viewModel.getCommunityPostList()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
mediaPlayerManager.pauseContent()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
mediaPlayerManager.stopContent()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||
binding.toolbar.tvBack.text = "커뮤니티"
|
||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||
|
||||
adapter = CreatorCommunityAllAdapter(
|
||||
screenWidth = screenWidth,
|
||||
onClickLike = { viewModel.communityPostLike(it) },
|
||||
writeComment = { postId, parentId, comment ->
|
||||
viewModel.registerComment(
|
||||
|
@ -128,20 +111,6 @@ class CreatorCommunityAllActivity : BaseActivity<ActivityCreatorCommunityAllBind
|
|||
reason = it
|
||||
)
|
||||
}.show(screenWidth)
|
||||
},
|
||||
onClickAudioContentPlayOrPause = { mediaPlayerManager.toggleContent(it) },
|
||||
isAudioContentPlaying = { mediaPlayerManager.isPlayingContent(it) },
|
||||
onClickPurchaseContent = { postId, can, onSuccess ->
|
||||
PurchaseCommunityPostDialog(
|
||||
activity = this@CreatorCommunityAllActivity,
|
||||
layoutInflater = layoutInflater,
|
||||
can = can,
|
||||
confirmButtonClick = {
|
||||
viewModel.purchaseCommunityPost(postId) {
|
||||
onSuccess(it)
|
||||
}
|
||||
}
|
||||
).show(screenWidth)
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ import android.text.style.ClickableSpan
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -21,25 +19,17 @@ import coil.transform.CircleCropTransformation
|
|||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.databinding.ItemCreatorCommunityAllBinding
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostCommentListItem
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostListResponse
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.player.CreatorCommunityContentItem
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.extensions.loadUrl
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class CreatorCommunityAllAdapter(
|
||||
private val screenWidth: Int,
|
||||
private val onClickLike: (Long) -> Unit,
|
||||
private val writeComment: (Long, Long?, String) -> Unit,
|
||||
private val showCommentBottomSheetDialog: (Long) -> Unit,
|
||||
private val onClickModify: (Long) -> Unit,
|
||||
private val onClickDelete: (Long) -> Unit,
|
||||
private val onClickReport: (Long) -> Unit,
|
||||
private val onClickAudioContentPlayOrPause: (CreatorCommunityContentItem) -> Unit,
|
||||
private val isAudioContentPlaying: (Long) -> Boolean,
|
||||
private val onClickPurchaseContent:
|
||||
(Long, Int, onSuccess: (GetCommunityPostListResponse) -> Unit) -> Unit
|
||||
private val onClickReport: (Long) -> Unit
|
||||
) : RecyclerView.Adapter<CreatorCommunityAllAdapter.ViewHolder>() {
|
||||
|
||||
val items = mutableListOf<GetCommunityPostListResponse>()
|
||||
|
@ -48,7 +38,7 @@ class CreatorCommunityAllAdapter(
|
|||
private val context: Context,
|
||||
private val binding: ItemCreatorCommunityAllBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
@SuppressLint("NotifyDataSetChanged", "SetTextI18n")
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun bind(item: GetCommunityPostListResponse, index: Int) {
|
||||
binding.tvDate.text = item.date
|
||||
binding.tvNickname.text = item.creatorNickname
|
||||
|
@ -58,43 +48,19 @@ class CreatorCommunityAllAdapter(
|
|||
transformations(CircleCropTransformation())
|
||||
}
|
||||
|
||||
if (item.price > 0) {
|
||||
if (item.existOrdered) {
|
||||
setContent(item, index)
|
||||
setNoticeAndClickableUrl(binding.tvContent, item.content)
|
||||
binding.tvContent.setOnClickListener {
|
||||
items[index] = items[index].copy(
|
||||
isExpand = !item.isExpand,
|
||||
)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
binding.tvContent.maxLines = if (item.isExpand) {
|
||||
Int.MAX_VALUE
|
||||
} else {
|
||||
binding.llLike.visibility = View.GONE
|
||||
binding.ivContent.visibility = View.GONE
|
||||
binding.llComment.visibility = View.GONE
|
||||
binding.ivSeeMore.visibility = View.GONE
|
||||
binding.ivPlayOrPause.visibility = View.GONE
|
||||
binding.llLockPost.visibility = View.VISIBLE
|
||||
|
||||
val lockPostWidth = (screenWidth - 42f.dpToPx()).toInt()
|
||||
val lp = binding.llLockPost.layoutParams as LinearLayout.LayoutParams
|
||||
lp.width = lockPostWidth
|
||||
lp.height = lockPostWidth
|
||||
binding.llLockPost.layoutParams = lp
|
||||
|
||||
binding.tvPurchase.text = "${item.price}캔으로 게시글 보기"
|
||||
binding.tvPurchase.setOnClickListener {
|
||||
onClickPurchaseContent(item.postId, item.price) { post ->
|
||||
items[index] = post
|
||||
setContent(post, index)
|
||||
}
|
||||
3
|
||||
}
|
||||
|
||||
setNoticeAndClickableUrl(binding.tvContent, item.content, item.isExpand, index)
|
||||
}
|
||||
} else {
|
||||
setContent(item, index)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setContent(item: GetCommunityPostListResponse, index: Int) {
|
||||
binding.llLockPost.visibility = View.GONE
|
||||
binding.llLike.visibility = View.VISIBLE
|
||||
binding.llComment.visibility = View.VISIBLE
|
||||
binding.ivSeeMore.visibility = View.VISIBLE
|
||||
binding.ivSeeMore.setOnClickListener {
|
||||
showOptionMenu(
|
||||
context = context,
|
||||
|
@ -104,76 +70,55 @@ class CreatorCommunityAllAdapter(
|
|||
)
|
||||
}
|
||||
|
||||
if (item.audioUrl != null && item.imageUrl != null) {
|
||||
binding.ivPlayOrPause.visibility = View.VISIBLE
|
||||
binding.ivPlayOrPause.setImageResource(
|
||||
if (isAudioContentPlaying(item.postId)) {
|
||||
R.drawable.btn_audio_content_pause
|
||||
binding.ivLike.setImageResource(
|
||||
if (item.isLike) {
|
||||
R.drawable.ic_audio_content_heart_pressed
|
||||
} else {
|
||||
R.drawable.btn_audio_content_play
|
||||
R.drawable.ic_audio_content_heart_normal
|
||||
}
|
||||
)
|
||||
binding.ivPlayOrPause.setOnClickListener {
|
||||
onClickAudioContentPlayOrPause(
|
||||
CreatorCommunityContentItem(
|
||||
item.postId,
|
||||
item.audioUrl
|
||||
|
||||
binding.tvLike.text = "${item.likeCount}"
|
||||
binding.llLike.setOnClickListener {
|
||||
val isLike = !item.isLike
|
||||
|
||||
items[index] = items[index].copy(
|
||||
isLike = !item.isLike,
|
||||
likeCount = if (isLike) item.likeCount + 1 else item.likeCount - 1
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
binding.ivPlayOrPause.visibility = View.GONE
|
||||
binding.ivPlayOrPause.setOnClickListener {}
|
||||
notifyDataSetChanged()
|
||||
|
||||
onClickLike(item.postId)
|
||||
}
|
||||
|
||||
setImageContent(binding.ivContent, item.imageUrl)
|
||||
setContentLike(item.isLike, item.likeCount, item.postId, index)
|
||||
setNoticeAndClickableUrl(binding.tvContent, item.content, item.isExpand, index)
|
||||
setContentComment(
|
||||
item.postId,
|
||||
item.commentCount,
|
||||
item.isCommentAvailable,
|
||||
comment = item.firstComment
|
||||
)
|
||||
}
|
||||
|
||||
private fun setImageContent(ivContent: ImageView, imageUrl: String?) {
|
||||
ivContent.visibility = View.VISIBLE
|
||||
if (imageUrl != null) {
|
||||
ivContent.visibility = View.VISIBLE
|
||||
ivContent.loadUrl(imageUrl) {
|
||||
if (item.imageUrl != null) {
|
||||
binding.ivContent.visibility = View.VISIBLE
|
||||
binding.ivContent.loadUrl(item.imageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
}
|
||||
} else {
|
||||
ivContent.visibility = View.GONE
|
||||
}
|
||||
binding.ivContent.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun setContentComment(
|
||||
postId: Long,
|
||||
commentCount: Int,
|
||||
isCommentAvailable: Boolean,
|
||||
comment: GetCommunityPostCommentListItem?
|
||||
) {
|
||||
if (isCommentAvailable) {
|
||||
if (item.isCommentAvailable) {
|
||||
binding.llComment.visibility = View.VISIBLE
|
||||
binding.tvCommentCount.text = "$commentCount"
|
||||
binding.tvCommentCount.text = "${item.commentCount}"
|
||||
} else {
|
||||
binding.llComment.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (commentCount > 0 && comment != null) {
|
||||
binding.ivCommentProfile.load(comment.profileUrl) {
|
||||
if (item.commentCount > 0) {
|
||||
binding.ivCommentProfile.load(item.firstComment!!.profileUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
binding.tvCommentText.text = comment.comment
|
||||
binding.tvCommentText.text = item.firstComment.comment
|
||||
binding.tvCommentText.visibility = View.VISIBLE
|
||||
binding.rlInputComment.visibility = View.GONE
|
||||
|
||||
binding.llComment.setOnClickListener { showCommentBottomSheetDialog(postId) }
|
||||
binding.llComment.setOnClickListener { showCommentBottomSheetDialog(item.postId) }
|
||||
} else {
|
||||
binding.tvCommentText.visibility = View.GONE
|
||||
binding.rlInputComment.visibility = View.VISIBLE
|
||||
|
@ -184,45 +129,16 @@ class CreatorCommunityAllAdapter(
|
|||
}
|
||||
|
||||
binding.ivCommentSend.setOnClickListener {
|
||||
val inputComment = binding.etComment.text.toString()
|
||||
val comment = binding.etComment.text.toString()
|
||||
binding.etComment.setText("")
|
||||
writeComment(postId, null, inputComment)
|
||||
writeComment(item.postId, null, comment)
|
||||
}
|
||||
|
||||
binding.llComment.setOnClickListener {}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setContentLike(isLike: Boolean, likeCount: Int, postId: Long, index: Int) {
|
||||
binding.ivLike.setImageResource(
|
||||
if (isLike) {
|
||||
R.drawable.ic_audio_content_heart_pressed
|
||||
} else {
|
||||
R.drawable.ic_audio_content_heart_normal
|
||||
}
|
||||
)
|
||||
|
||||
binding.tvLike.text = "$likeCount"
|
||||
binding.llLike.setOnClickListener {
|
||||
items[index] = items[index].copy(
|
||||
isLike = !isLike,
|
||||
likeCount = if (!isLike) likeCount + 1 else likeCount - 1
|
||||
)
|
||||
notifyDataSetChanged()
|
||||
|
||||
onClickLike(postId)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setNoticeAndClickableUrl(
|
||||
textView: TextView,
|
||||
text: String,
|
||||
isExpand: Boolean,
|
||||
index: Int
|
||||
) {
|
||||
textView.visibility = View.VISIBLE
|
||||
private fun setNoticeAndClickableUrl(textView: TextView, text: String) {
|
||||
textView.text = text
|
||||
|
||||
val spannable = SpannableString(text)
|
||||
|
@ -243,19 +159,6 @@ class CreatorCommunityAllAdapter(
|
|||
|
||||
textView.text = spannable
|
||||
textView.movementMethod = LinkMovementMethod.getInstance()
|
||||
|
||||
textView.setOnClickListener {
|
||||
items[index] = items[index].copy(
|
||||
isExpand = !isExpand,
|
||||
)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
textView.maxLines = if (isExpand) {
|
||||
Int.MAX_VALUE
|
||||
} else {
|
||||
3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,9 +212,4 @@ class CreatorCommunityAllAdapter(
|
|||
|
||||
popup.show()
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun updateUI() {
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,41 +220,4 @@ class CreatorCommunityAllViewModel(
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun purchaseCommunityPost(postId: Long, onSuccess: (GetCommunityPostListResponse) -> Unit) {
|
||||
if (!_isLoading.value!!) {
|
||||
_isLoading.value = true
|
||||
compositeDisposable.add(
|
||||
repository
|
||||
.purchaseCommunityPost(
|
||||
postId = postId,
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
if (it.success && it.data != null) {
|
||||
onSuccess(it.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("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creator_community.all
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import kr.co.vividnext.sodalive.databinding.DialogPurchaseCommunityPostBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
class PurchaseCommunityPostDialog(
|
||||
activity: Activity,
|
||||
layoutInflater: LayoutInflater,
|
||||
can: Int,
|
||||
confirmButtonClick: () -> Unit,
|
||||
) {
|
||||
|
||||
private val alertDialog: AlertDialog
|
||||
val dialogView = DialogPurchaseCommunityPostBinding.inflate(layoutInflater)
|
||||
|
||||
init {
|
||||
val dialogBuilder = AlertDialog.Builder(activity)
|
||||
dialogBuilder.setView(dialogView.root)
|
||||
|
||||
alertDialog = dialogBuilder.create()
|
||||
alertDialog.setCancelable(false)
|
||||
alertDialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
|
||||
dialogView.tvCan.text = "${can.moneyFormat()}캔으로 보기"
|
||||
dialogView.tvCan.setOnClickListener {
|
||||
alertDialog.dismiss()
|
||||
confirmButtonClick()
|
||||
}
|
||||
dialogView.tvCancel.setOnClickListener { alertDialog.dismiss() }
|
||||
}
|
||||
|
||||
fun show(width: Int) {
|
||||
alertDialog.show()
|
||||
|
||||
val lp = WindowManager.LayoutParams()
|
||||
lp.copyFrom(alertDialog.window?.attributes)
|
||||
lp.width = width - (26.7f.dpToPx()).toInt()
|
||||
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||
|
||||
alertDialog.window?.attributes = lp
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creator_community.all
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class PurchasePostRequest(
|
||||
@SerializedName("postId") val postId: Long,
|
||||
@SerializedName("timezone") val timezone: String,
|
||||
@SerializedName("container") val container: String = "aos",
|
||||
)
|
|
@ -1,113 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creator_community.all.player
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioAttributes
|
||||
import android.media.MediaPlayer
|
||||
import android.net.Uri
|
||||
import android.widget.Toast
|
||||
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
||||
import java.io.IOException
|
||||
|
||||
data class CreatorCommunityContentItem(val contentId: Long, val url: String)
|
||||
|
||||
class CreatorCommunityMediaPlayerManager(
|
||||
private val context: Context,
|
||||
private val updateUI: () -> Unit
|
||||
) {
|
||||
private var mediaPlayer: MediaPlayer? = null
|
||||
private var currentPlayingContentId: Long? = null
|
||||
private var isPaused: Boolean = false
|
||||
|
||||
fun pauseContent() {
|
||||
mediaPlayer?.pause()
|
||||
isPaused = true
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun resumeContent() {
|
||||
pauseAudioContentService()
|
||||
mediaPlayer?.start()
|
||||
isPaused = false
|
||||
updateUI()
|
||||
}
|
||||
|
||||
fun stopContent() {
|
||||
mediaPlayer?.let {
|
||||
it.stop()
|
||||
it.release()
|
||||
mediaPlayer = null
|
||||
}
|
||||
currentPlayingContentId = null
|
||||
isPaused = false
|
||||
updateUI()
|
||||
}
|
||||
|
||||
fun toggleContent(creatorCommunityContentItem: CreatorCommunityContentItem) {
|
||||
if (currentPlayingContentId == creatorCommunityContentItem.contentId) {
|
||||
if (mediaPlayer?.isPlaying == true) {
|
||||
pauseContent()
|
||||
} else {
|
||||
resumeContent()
|
||||
}
|
||||
} else {
|
||||
playContent(creatorCommunityContentItem)
|
||||
}
|
||||
}
|
||||
|
||||
fun isPlayingContent(contentId: Long): Boolean {
|
||||
return currentPlayingContentId == contentId && mediaPlayer?.isPlaying == true
|
||||
}
|
||||
|
||||
private fun playContent(creatorCommunityContentItem: CreatorCommunityContentItem) {
|
||||
pauseAudioContentService()
|
||||
|
||||
if (currentPlayingContentId == creatorCommunityContentItem.contentId && isPaused) {
|
||||
resumeContent()
|
||||
return
|
||||
}
|
||||
|
||||
stopContent()
|
||||
|
||||
mediaPlayer = MediaPlayer().apply {
|
||||
setAudioAttributes(
|
||||
AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
||||
.build()
|
||||
)
|
||||
|
||||
try {
|
||||
setDataSource(context, Uri.parse(creatorCommunityContentItem.url))
|
||||
prepareAsync() // 비동기적으로 준비
|
||||
setOnPreparedListener {
|
||||
start()
|
||||
updateUI() // 준비 완료 후 UI 업데이트
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(context, "콘텐츠를 재생하지 못했습니다.\n다시 시도해 주세요", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
setOnCompletionListener {
|
||||
currentPlayingContentId = null
|
||||
updateUI() // 재생 완료 후 UI 업데이트
|
||||
}
|
||||
}
|
||||
|
||||
currentPlayingContentId = creatorCommunityContentItem.contentId
|
||||
isPaused = false
|
||||
updateUI()
|
||||
}
|
||||
|
||||
private fun pauseAudioContentService() {
|
||||
context.startService(
|
||||
Intent(
|
||||
context,
|
||||
AudioContentPlayService::class.java
|
||||
).apply {
|
||||
action = AudioContentPlayService.MusicAction.PAUSE.name
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import com.google.gson.annotations.SerializedName
|
|||
|
||||
data class CreateCommunityPostRequest(
|
||||
@SerializedName("content") val content: String,
|
||||
@SerializedName("price") val price: Int,
|
||||
@SerializedName("isAdult") val isAdult: Boolean,
|
||||
@SerializedName("isCommentAvailable") val isCommentAvailable: Boolean
|
||||
)
|
||||
|
|
|
@ -24,11 +24,10 @@ import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
|||
import kr.co.vividnext.sodalive.databinding.ActivityCreatorCommunityWriteBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.io.File
|
||||
|
||||
class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWriteBinding>(
|
||||
ActivityCreatorCommunityWriteBinding::inflate
|
||||
), RecordingVoiceFragment.OnAudioRecordedListener {
|
||||
) {
|
||||
|
||||
private val viewModel: CreatorCommunityWriteViewModel by inject()
|
||||
|
||||
|
@ -50,12 +49,8 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
|||
placeholder(R.drawable.ic_place_holder)
|
||||
transformations(RoundedCornersTransformation(8f.dpToPx()))
|
||||
}
|
||||
|
||||
viewModel.setImageUri(fileUri)
|
||||
|
||||
binding.llRecordAudio.visibility = View.VISIBLE
|
||||
viewModel.imageUri = fileUri
|
||||
} else {
|
||||
binding.llRecordAudio.visibility = View.GONE
|
||||
Toast.makeText(
|
||||
this,
|
||||
"잘못된 파일입니다.\n다시 선택해 주세요.",
|
||||
|
@ -63,7 +58,6 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
|||
).show()
|
||||
}
|
||||
} else if (resultCode == ImagePicker.RESULT_ERROR) {
|
||||
binding.llRecordAudio.visibility = View.GONE
|
||||
Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
@ -79,29 +73,12 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
|||
bindData()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
deleteAudioFile()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun deleteAudioFile() {
|
||||
if (viewModel.audioFile != null && viewModel.audioFile!!.exists()) {
|
||||
viewModel.audioFile?.delete()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||
|
||||
binding.toolbar.tvBack.text = "게시글 등록"
|
||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||
|
||||
binding.tvRecordAudio.setOnClickListener {
|
||||
val fragment = RecordingVoiceFragment()
|
||||
fragment.isCancelable = false
|
||||
fragment.show(supportFragmentManager, fragment.tag)
|
||||
}
|
||||
|
||||
binding.ivPhotoPicker.setOnClickListener {
|
||||
ImagePicker.with(this)
|
||||
.crop()
|
||||
|
@ -124,8 +101,6 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
|||
|
||||
binding.llCommentNo.setOnClickListener { viewModel.setAvailableComment(false) }
|
||||
binding.llCommentYes.setOnClickListener { viewModel.setAvailableComment(true) }
|
||||
binding.llPricePaid.setOnClickListener { viewModel.setPriceFree(false) }
|
||||
binding.llPriceFree.setOnClickListener { viewModel.setPriceFree(true) }
|
||||
binding.tvCancel.setOnClickListener { finish() }
|
||||
binding.tvUpload.setOnClickListener {
|
||||
viewModel.createCommunityPost { finish() }
|
||||
|
@ -165,24 +140,6 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
|||
}
|
||||
)
|
||||
|
||||
compositeDisposable.add(
|
||||
binding.etPrice.textChanges().skip(1)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
val price = it.toString().toIntOrNull()
|
||||
if (price != null) {
|
||||
viewModel.price = price.toInt()
|
||||
} else {
|
||||
viewModel.price = 0
|
||||
if (it.isNotBlank()) {
|
||||
binding.etPrice.setText(it.substring(0, it.length - 1))
|
||||
binding.etPrice.setSelection(it.length - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
viewModel.toastLiveData.observe(this) {
|
||||
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
|
||||
}
|
||||
|
@ -238,22 +195,6 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.isPriceFreeLiveData.observe(this) {
|
||||
if (it) {
|
||||
checkPriceFree()
|
||||
} else {
|
||||
checkPricePaid()
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.isShowPriceUiLiveData.observe(this) {
|
||||
binding.llPrice.visibility = if (it) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
if (SharedPreferenceManager.isAuth) {
|
||||
binding.llAgeAll.setOnClickListener {
|
||||
viewModel.setAdult(false)
|
||||
|
@ -304,60 +245,4 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPriceFree() {
|
||||
viewModel.price = 0
|
||||
binding.etPrice.setText("0")
|
||||
binding.rlPrice.visibility = View.GONE
|
||||
|
||||
binding.ivPriceFree.visibility = View.VISIBLE
|
||||
binding.tvPriceFree.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_eeeeee
|
||||
)
|
||||
)
|
||||
binding.llPriceFree.setBackgroundResource(R.drawable.bg_round_corner_6_7_3bb9f1)
|
||||
|
||||
binding.ivPricePaid.visibility = View.GONE
|
||||
binding.tvPricePaid.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_3bb9f1
|
||||
)
|
||||
)
|
||||
binding.llPricePaid.setBackgroundResource(
|
||||
R.drawable.bg_round_corner_6_7_13181b
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkPricePaid() {
|
||||
binding.rlPrice.visibility = View.VISIBLE
|
||||
|
||||
binding.ivPricePaid.visibility = View.VISIBLE
|
||||
binding.tvPricePaid.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_eeeeee
|
||||
)
|
||||
)
|
||||
binding.llPricePaid.setBackgroundResource(R.drawable.bg_round_corner_6_7_3bb9f1)
|
||||
|
||||
binding.ivPriceFree.visibility = View.GONE
|
||||
binding.tvPriceFree.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
applicationContext,
|
||||
R.color.color_3bb9f1
|
||||
)
|
||||
)
|
||||
binding.llPriceFree.setBackgroundResource(
|
||||
R.drawable.bg_round_corner_6_7_13181b
|
||||
)
|
||||
}
|
||||
|
||||
override fun onAudioRecorded(file: File) {
|
||||
deleteAudioFile()
|
||||
binding.tvRecordAudio.text = file.name
|
||||
viewModel.audioFile = file
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@ import okhttp3.RequestBody.Companion.toRequestBody
|
|||
import okio.BufferedSink
|
||||
import java.io.File
|
||||
|
||||
class CreatorCommunityWriteViewModel(
|
||||
private val repository: CreatorCommunityRepository
|
||||
class CreatorCommunityWriteViewModel(private val repository: CreatorCommunityRepository
|
||||
): BaseViewModel() {
|
||||
private val _toastLiveData = MutableLiveData<String?>()
|
||||
val toastLiveData: LiveData<String?>
|
||||
|
@ -37,20 +36,10 @@ class CreatorCommunityWriteViewModel(
|
|||
val isAvailableCommentLiveData: LiveData<Boolean>
|
||||
get() = _isAvailableCommentLiveData
|
||||
|
||||
private val _isPriceFreeLiveData = MutableLiveData(true)
|
||||
val isPriceFreeLiveData: LiveData<Boolean>
|
||||
get() = _isPriceFreeLiveData
|
||||
|
||||
private val _isShowPriceUiLiveData = MutableLiveData(false)
|
||||
val isShowPriceUiLiveData: LiveData<Boolean>
|
||||
get() = _isShowPriceUiLiveData
|
||||
|
||||
lateinit var getRealPathFromURI: (Uri) -> String?
|
||||
|
||||
var price = 0
|
||||
var content = ""
|
||||
var audioFile: File? = null
|
||||
private var imageUri: Uri? = null
|
||||
var imageUri: Uri? = null
|
||||
|
||||
fun setAdult(isAdult: Boolean) {
|
||||
_isAdultLiveData.postValue(isAdult)
|
||||
|
@ -60,22 +49,12 @@ class CreatorCommunityWriteViewModel(
|
|||
_isAvailableCommentLiveData.postValue(isAvailableComment)
|
||||
}
|
||||
|
||||
fun setPriceFree(isPriceFree: Boolean) {
|
||||
_isPriceFreeLiveData.postValue(isPriceFree)
|
||||
}
|
||||
|
||||
fun setImageUri(uri: Uri) {
|
||||
this.imageUri = uri
|
||||
_isShowPriceUiLiveData.postValue(true)
|
||||
}
|
||||
|
||||
fun createCommunityPost(onSuccess: () -> Unit) {
|
||||
if (!_isLoading.value!! && validateData()) {
|
||||
_isLoading.postValue(true)
|
||||
|
||||
val request = CreateCommunityPostRequest(
|
||||
content = content,
|
||||
price = price,
|
||||
isAdult = _isAdultLiveData.value!!,
|
||||
isCommentAvailable = _isAvailableCommentLiveData.value!!
|
||||
)
|
||||
|
@ -111,37 +90,8 @@ class CreatorCommunityWriteViewModel(
|
|||
null
|
||||
}
|
||||
|
||||
val multipartAudioFile = if (audioFile != null) {
|
||||
MultipartBody.Part.createFormData(
|
||||
"audioFile",
|
||||
audioFile!!.name,
|
||||
body = object : RequestBody() {
|
||||
override fun contentType(): MediaType {
|
||||
return "audio/*".toMediaType()
|
||||
}
|
||||
|
||||
override fun writeTo(sink: BufferedSink) {
|
||||
audioFile!!.inputStream().use { inputStream ->
|
||||
val buffer = ByteArray(512)
|
||||
var bytesRead: Int
|
||||
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
||||
sink.write(buffer, 0, bytesRead)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun contentLength(): Long {
|
||||
return audioFile!!.length()
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
compositeDisposable.add(
|
||||
repository.createCommunityPost(
|
||||
audioFile = multipartAudioFile,
|
||||
postImage = postImage,
|
||||
request = requestJson.toRequestBody("text/plain".toMediaType()),
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
|
@ -181,23 +131,6 @@ class CreatorCommunityWriteViewModel(
|
|||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
if (!isPriceFreeLiveData.value!!) {
|
||||
if (price < 5) {
|
||||
_toastLiveData.postValue("최소금액은 5캔 입니다.")
|
||||
return false
|
||||
}
|
||||
|
||||
if (imageUri == null) {
|
||||
_toastLiveData.postValue("유료 게시글 등록을 위해서는 이미지가 필요합니다.")
|
||||
return false
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
_toastLiveData.postValue("가격은 숫자만 입력 가능 합니다.")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,300 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.explorer.profile.creator_community.write
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.media.MediaPlayer
|
||||
import android.media.MediaRecorder
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.Toast
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.databinding.FragmentRecordingVoiceBinding
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.Locale
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class RecordingVoiceFragment : BottomSheetDialogFragment() {
|
||||
|
||||
private var listener: OnAudioRecordedListener? = null
|
||||
private var mediaRecorder: MediaRecorder? = null
|
||||
private var mediaPlayer: MediaPlayer? = null
|
||||
private var fileNameMedia = ""
|
||||
|
||||
private lateinit var binding: FragmentRecordingVoiceBinding
|
||||
|
||||
private var startTime: Long = 0L
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
interface OnAudioRecordedListener {
|
||||
fun onAudioRecorded(file: File)
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
if (context is OnAudioRecordedListener) {
|
||||
listener = context
|
||||
} else {
|
||||
throw RuntimeException("$context must implement OnAudioRecordedListener")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val dialog = super.onCreateDialog(savedInstanceState)
|
||||
|
||||
dialog.setOnShowListener {
|
||||
val d = it as BottomSheetDialog
|
||||
val bottomSheet = d.findViewById<FrameLayout>(
|
||||
com.google.android.material.R.id.design_bottom_sheet
|
||||
)
|
||||
if (bottomSheet != null) {
|
||||
val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
|
||||
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
bottomSheetBehavior.isDraggable = false
|
||||
}
|
||||
}
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentRecordingVoiceBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.ivClose.setOnClickListener {
|
||||
deleteAudioFile()
|
||||
dismiss()
|
||||
}
|
||||
binding.ivRecordStart.setOnClickListener {
|
||||
fileNameMedia = requireActivity().filesDir.path +
|
||||
"/record_community_voice_${System.currentTimeMillis()}.m4a"
|
||||
|
||||
val fileMedia = File(fileNameMedia)
|
||||
if (!fileMedia.exists()) {
|
||||
try {
|
||||
fileMedia.createNewFile()
|
||||
startRecording()
|
||||
} catch (e: IOException) {
|
||||
Toast.makeText(requireActivity(), R.string.retry, Toast.LENGTH_LONG).show()
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivRecordStop.setOnClickListener { stopRecording() }
|
||||
binding.ivRecordPlay.setOnClickListener { startPlaying() }
|
||||
binding.ivRecordPause.setOnClickListener { stopPlaying() }
|
||||
|
||||
binding.tvDelete.setOnClickListener {
|
||||
deleteAudioFile()
|
||||
|
||||
binding.ivRecordStart.visibility = View.VISIBLE
|
||||
binding.llRetryOrComplete.visibility = View.GONE
|
||||
binding.rlRecordPlay.visibility = View.GONE
|
||||
binding.soundVisualizer.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.tvRetryRecord.setOnClickListener {
|
||||
deleteAudioFile()
|
||||
|
||||
binding.ivRecordStart.visibility = View.VISIBLE
|
||||
binding.llRetryOrComplete.visibility = View.GONE
|
||||
binding.rlRecordPlay.visibility = View.GONE
|
||||
binding.soundVisualizer.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.tvComplete.setOnClickListener {
|
||||
listener?.onAudioRecorded(file = File(fileNameMedia))
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetach() {
|
||||
super.onDetach()
|
||||
listener = null
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
releaseMediaPlayer()
|
||||
releaseMediaRecorder()
|
||||
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun deleteAudioFile() {
|
||||
if (fileNameMedia.isNotBlank()) {
|
||||
val fileMedia = File(fileNameMedia)
|
||||
if (fileMedia.exists()) {
|
||||
fileMedia.delete()
|
||||
}
|
||||
fileNameMedia = ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun startRecording() {
|
||||
releaseMediaRecorder()
|
||||
|
||||
// safety check, don't start a new recording if one is already going
|
||||
mediaRecorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
MediaRecorder(requireContext())
|
||||
} else {
|
||||
MediaRecorder()
|
||||
}.apply {
|
||||
setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
|
||||
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
|
||||
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
|
||||
setAudioChannels(2)
|
||||
setAudioSamplingRate(48000)
|
||||
setAudioEncodingBitRate(256000)
|
||||
setOutputFile(fileNameMedia)
|
||||
}
|
||||
|
||||
try {
|
||||
mediaRecorder!!.prepare()
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), R.string.retry, Toast.LENGTH_LONG).show()
|
||||
return
|
||||
}
|
||||
|
||||
mediaRecorder!!.start()
|
||||
binding.ivRecordStart.visibility = View.GONE
|
||||
binding.ivRecordStop.visibility = View.VISIBLE
|
||||
|
||||
startCountDownTimer()
|
||||
}
|
||||
|
||||
private fun releaseMediaRecorder() {
|
||||
if (mediaRecorder != null) {
|
||||
// stop recording and free up resources
|
||||
mediaRecorder!!.stop()
|
||||
mediaRecorder!!.reset()
|
||||
mediaRecorder!!.release()
|
||||
|
||||
mediaRecorder = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopRecording() {
|
||||
releaseMediaRecorder()
|
||||
stopCountDownTimer()
|
||||
|
||||
binding.ivRecordStop.visibility = View.GONE
|
||||
binding.rlRecordPlay.visibility = View.VISIBLE
|
||||
binding.llRetryOrComplete.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun startPlaying() {
|
||||
if (mediaPlayer == null) {
|
||||
mediaPlayer = MediaPlayer()
|
||||
mediaPlayer!!.reset()
|
||||
|
||||
mediaPlayer!!.setOnCompletionListener {
|
||||
releaseMediaPlayer()
|
||||
stopCountDownTimer()
|
||||
|
||||
binding.tvDelete.visibility = View.VISIBLE
|
||||
binding.ivRecordPlay.visibility = View.VISIBLE
|
||||
binding.llRetryOrComplete.visibility = View.VISIBLE
|
||||
binding.ivRecordPause.visibility = View.GONE
|
||||
binding.soundVisualizer.visibility = View.GONE
|
||||
}
|
||||
|
||||
mediaPlayer!!.setOnPreparedListener {
|
||||
binding.soundVisualizer.visibility = View.VISIBLE
|
||||
binding.soundVisualizer.setAudioSessionId(mediaPlayer!!.audioSessionId)
|
||||
it.start()
|
||||
|
||||
startCountDownTimer()
|
||||
}
|
||||
|
||||
try {
|
||||
mediaPlayer!!.setDataSource(fileNameMedia)
|
||||
mediaPlayer!!.prepare()
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(requireActivity(), R.string.retry, Toast.LENGTH_LONG).show()
|
||||
return
|
||||
}
|
||||
|
||||
binding.tvDelete.visibility = View.GONE
|
||||
binding.ivRecordPlay.visibility = View.GONE
|
||||
binding.llRetryOrComplete.visibility = View.GONE
|
||||
binding.ivRecordPause.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopPlaying() {
|
||||
releaseMediaPlayer()
|
||||
stopCountDownTimer()
|
||||
|
||||
binding.tvDelete.visibility = View.VISIBLE
|
||||
binding.ivRecordPlay.visibility = View.VISIBLE
|
||||
binding.llRetryOrComplete.visibility = View.VISIBLE
|
||||
binding.ivRecordPause.visibility = View.GONE
|
||||
binding.soundVisualizer.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun releaseMediaPlayer() {
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer!!.release()
|
||||
mediaPlayer = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun startCountDownTimer() {
|
||||
startTime = System.currentTimeMillis()
|
||||
|
||||
handler.post(object : Runnable {
|
||||
override fun run() {
|
||||
// 현재 시간에서 시작 시간을 빼서 경과 시간 계산
|
||||
val elapsedMilliseconds = System.currentTimeMillis() - startTime
|
||||
val centisecondsElapsed = (elapsedMilliseconds / 10.0).roundToInt()
|
||||
|
||||
// 경과한 시간에서 분, 초, 센티초 계산
|
||||
val minutes = centisecondsElapsed / 6000
|
||||
val seconds = (centisecondsElapsed % 6000) / 100
|
||||
val centiseconds = centisecondsElapsed % 100
|
||||
|
||||
val time = String.format(
|
||||
Locale.getDefault(),
|
||||
"%02d:%02d.%02d",
|
||||
minutes,
|
||||
seconds,
|
||||
centiseconds
|
||||
)
|
||||
binding.tvTimer.text = time
|
||||
|
||||
if (minutes >= 3) {
|
||||
stopRecording()
|
||||
}
|
||||
|
||||
// 10밀리초(1센티초)마다 실행
|
||||
handler.postDelayed(this, 10)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun stopCountDownTimer() {
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
startTime = 0
|
||||
binding.tvTimer.text = "00:00.00"
|
||||
}
|
||||
}
|
|
@ -796,21 +796,6 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
|||
binding.ivEdit.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.ivShare.setOnClickListener {
|
||||
viewModel.shareRoomLink(
|
||||
response.roomId,
|
||||
response.isPrivateRoom,
|
||||
response.password
|
||||
) {
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
intent.type = "text/plain"
|
||||
intent.putExtra(Intent.EXTRA_TEXT, it)
|
||||
|
||||
val shareIntent = Intent.createChooser(intent, "라이브 공유")
|
||||
startActivity(shareIntent)
|
||||
}
|
||||
}
|
||||
|
||||
if (response.creatorId == SharedPreferenceManager.userId) {
|
||||
binding.llViewUsers.visibility = View.VISIBLE
|
||||
binding.llViewUsers.setOnClickListener { roomProfileDialog.show() }
|
||||
|
|
|
@ -3,12 +3,6 @@ package kr.co.vividnext.sodalive.live.room
|
|||
import android.net.Uri
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.google.firebase.dynamiclinks.ShortDynamicLink
|
||||
import com.google.firebase.dynamiclinks.ktx.androidParameters
|
||||
import com.google.firebase.dynamiclinks.ktx.dynamicLinks
|
||||
import com.google.firebase.dynamiclinks.ktx.iosParameters
|
||||
import com.google.firebase.dynamiclinks.ktx.shortLinkAsync
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.google.gson.Gson
|
||||
import com.orhanobut.logger.Logger
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
|
@ -253,43 +247,6 @@ class LiveRoomViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
fun shareRoomLink(
|
||||
roomId: Long,
|
||||
isPrivateRoom: Boolean,
|
||||
password: String?,
|
||||
onSuccess: (String) -> Unit
|
||||
) {
|
||||
_isLoading.value = true
|
||||
Firebase.dynamicLinks.shortLinkAsync(ShortDynamicLink.Suffix.SHORT) {
|
||||
link = Uri.parse("https://sodalive.net/?room_id=$roomId")
|
||||
domainUriPrefix = "https://sodalive.page.link"
|
||||
androidParameters { }
|
||||
iosParameters("kr.co.vividnext.sodalive") {
|
||||
appStoreId = "6461721697"
|
||||
}
|
||||
}.addOnSuccessListener {
|
||||
val uri = it.shortLink
|
||||
if (uri != null) {
|
||||
val message = if (isPrivateRoom) {
|
||||
"${SharedPreferenceManager.nickname}님이 귀하를 " +
|
||||
"소다라이브의 비공개라이브에 초대하였습니다.\n" +
|
||||
"※ 라이브 참여: $uri\n" +
|
||||
"(입장 비밀번호 : $password)"
|
||||
} else {
|
||||
"${SharedPreferenceManager.nickname}님이 귀하를 " +
|
||||
"소다라이브의 공개라이브에 초대하였습니다.\n" +
|
||||
"※ 라이브 참여: $uri"
|
||||
}
|
||||
|
||||
onSuccess(message)
|
||||
}
|
||||
}.addOnFailureListener {
|
||||
_toastLiveData.postValue("공유링크를 생성하지 못했습니다.\n다시 시도해 주세요.")
|
||||
}.addOnCompleteListener {
|
||||
_isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
fun creatorFollow(creatorId: Long, roomId: Long, isGetUserProfile: Boolean = false) {
|
||||
_isLoading.value = true
|
||||
compositeDisposable.add(
|
||||
|
|
|
@ -131,22 +131,10 @@ class RouletteSettingsViewModel(private val repository: RouletteRepository) : Ba
|
|||
return false
|
||||
}
|
||||
|
||||
if (option.percentage.isBlank()) {
|
||||
_toastLiveData.value = "옵션의 확률은 빈칸일 수 없습니다."
|
||||
_isLoading.value = false
|
||||
return false
|
||||
}
|
||||
|
||||
if (option.percentage.toFloat() <= 0f) {
|
||||
_toastLiveData.value = "옵션의 확률은 0%보다 커야합니다."
|
||||
_isLoading.value = false
|
||||
return false
|
||||
}
|
||||
|
||||
totalPercentage += option.percentage.toFloat()
|
||||
}
|
||||
|
||||
if (totalPercentage > 100.1f || totalPercentage <= 99.99f) {
|
||||
if (totalPercentage != 100.0f) {
|
||||
_toastLiveData.value = "확률이 100%가 아닙니다"
|
||||
_isLoading.value = false
|
||||
return false
|
||||
|
|
|
@ -95,7 +95,7 @@ class VoiceMessageWriteFragment(
|
|||
dismiss()
|
||||
}
|
||||
})
|
||||
.setDeniedMessage("오디오 녹음 권한을 거부하시면 음성 메시지를 이용하실 수 없습니다.")
|
||||
.setDeniedMessage("오디오 녹음 권한을 거부하시면 음성 속닥을 이용하실 수 없습니다.")
|
||||
.setPermissions(Manifest.permission.RECORD_AUDIO)
|
||||
.check()
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
|
|||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||
import kr.co.vividnext.sodalive.live.reservation_status.LiveReservationStatusActivity
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.AlarmListActivity
|
||||
import kr.co.vividnext.sodalive.mypage.auth.Auth
|
||||
import kr.co.vividnext.sodalive.mypage.auth.AuthVerifyRequest
|
||||
import kr.co.vividnext.sodalive.mypage.auth.BootpayResponse
|
||||
|
@ -115,10 +114,6 @@ class MyPageFragment : BaseFragment<FragmentMyBinding>(FragmentMyBinding::inflat
|
|||
)
|
||||
}
|
||||
|
||||
if (SharedPreferenceManager.userId == 17958L) {
|
||||
binding.llCan.visibility = View.GONE
|
||||
} else {
|
||||
binding.llCan.visibility = View.VISIBLE
|
||||
binding.llTotalCan.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(
|
||||
|
@ -136,7 +131,6 @@ class MyPageFragment : BaseFragment<FragmentMyBinding>(FragmentMyBinding::inflat
|
|||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.rlCoupon.setOnClickListener {
|
||||
startActivity(
|
||||
|
@ -147,15 +141,6 @@ class MyPageFragment : BaseFragment<FragmentMyBinding>(FragmentMyBinding::inflat
|
|||
)
|
||||
}
|
||||
|
||||
binding.rlAlarm.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(
|
||||
requireActivity(),
|
||||
AlarmListActivity::class.java
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
binding.llReservationLive.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.CheckBox
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
import kr.co.vividnext.sodalive.databinding.ActivityAddAlarmBinding
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.select_audio_content.AlarmSelectAudioContentActivity
|
||||
import java.util.Calendar
|
||||
|
||||
class AddAlarmActivity : BaseActivity<ActivityAddAlarmBinding>(
|
||||
ActivityAddAlarmBinding::inflate
|
||||
) {
|
||||
private val alarmViewModel: AlarmViewModel by viewModels()
|
||||
|
||||
private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
|
||||
private lateinit var dayCheckBoxes: List<CheckBox>
|
||||
|
||||
private var alarmId: Int = 0
|
||||
private var selectedContentId: Long = 0
|
||||
private var selectedContentTitle = ""
|
||||
private var selectedContentCreatorNickname = ""
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
activityResultLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
this.selectedContentId = it.data?.getLongExtra(
|
||||
Constants.EXTRA_AUDIO_CONTENT_ID,
|
||||
0
|
||||
) ?: 0
|
||||
|
||||
this.selectedContentTitle = it.data?.getStringExtra(
|
||||
Constants.EXTRA_AUDIO_CONTENT_TITLE
|
||||
) ?: ""
|
||||
|
||||
this.selectedContentCreatorNickname = it.data?.getStringExtra(
|
||||
Constants.EXTRA_AUDIO_CONTENT_CREATOR_NICKNAME
|
||||
) ?: ""
|
||||
|
||||
binding.tvContentTitle.text = selectedContentTitle
|
||||
}
|
||||
}
|
||||
|
||||
alarmId = intent.getIntExtra(Constants.EXTRA_ALARM_ID, -1)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
dayCheckBoxes = listOf(
|
||||
binding.chkSun,
|
||||
binding.chkMon,
|
||||
binding.chkTue,
|
||||
binding.chkWed,
|
||||
binding.chkThu,
|
||||
binding.chkFri,
|
||||
binding.chkSat
|
||||
)
|
||||
|
||||
if (alarmId != -1) {
|
||||
alarmViewModel.getAlarmById(alarmId).observe(this) { alarm ->
|
||||
alarm?.let {
|
||||
binding.etAlarmTitle.setText(it.title)
|
||||
|
||||
val calendar = Calendar.getInstance().apply { timeInMillis = it.time }
|
||||
binding.timePicker.hour = calendar.get(Calendar.HOUR_OF_DAY)
|
||||
binding.timePicker.minute = calendar.get(Calendar.MINUTE)
|
||||
dayCheckBoxes.forEach { checkBox ->
|
||||
checkBox.isChecked = it.days.contains(checkBox.text.toString())
|
||||
}
|
||||
binding.tvContentTitle.text = it.contentTitle
|
||||
|
||||
selectedContentId = it.contentId
|
||||
selectedContentTitle = it.contentTitle
|
||||
selectedContentCreatorNickname = it.contentCreatorNickname
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.rlSelectAlarmContent.setOnClickListener {
|
||||
activityResultLauncher.launch(
|
||||
Intent(
|
||||
applicationContext,
|
||||
AlarmSelectAudioContentActivity::class.java
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
binding.tvSave.setOnClickListener { saveAlarm() }
|
||||
|
||||
binding.toolbar.tvBack.text = "알람 설정"
|
||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||
binding.tvCancel.setOnClickListener { finish() }
|
||||
}
|
||||
|
||||
private fun saveAlarm() {
|
||||
if (!validate()) return
|
||||
|
||||
val hour = binding.timePicker.hour
|
||||
val minute = binding.timePicker.minute
|
||||
val alarmTitle = binding.etAlarmTitle.text.toString()
|
||||
val selectedDays = dayCheckBoxes.filter { it.isChecked }.map { it.text.toString() }
|
||||
|
||||
val alarmTime = getAdjustedTimeInMillis(hour, minute, selectedDays)
|
||||
val alarm = Alarm(
|
||||
id = if (alarmId == -1) 0 else alarmId,
|
||||
title = alarmTitle,
|
||||
time = alarmTime,
|
||||
contentId = selectedContentId,
|
||||
contentTitle = selectedContentTitle,
|
||||
contentCreatorNickname = selectedContentCreatorNickname,
|
||||
days = selectedDays.toList(),
|
||||
)
|
||||
|
||||
if (alarmId > 0) {
|
||||
alarmViewModel.update(alarm)
|
||||
} else {
|
||||
alarmViewModel.insert(alarm)
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun getAdjustedTimeInMillis(hour: Int, minute: Int, selectedDays: List<String>): Long {
|
||||
val alarmTimeInMillis = getTimeInMillis(hour, minute)
|
||||
return if (selectedDays.isEmpty() && alarmTimeInMillis <= System.currentTimeMillis()) {
|
||||
getTimeInMillis(hour + 24, minute) // 다음 날로 설정
|
||||
} else {
|
||||
alarmTimeInMillis
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTimeInMillis(hour: Int, minute: Int): Long {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour)
|
||||
calendar.set(Calendar.MINUTE, minute)
|
||||
calendar.set(Calendar.SECOND, 0)
|
||||
calendar.set(Calendar.MILLISECOND, 0)
|
||||
return calendar.timeInMillis
|
||||
}
|
||||
|
||||
private fun validate(): Boolean {
|
||||
if (
|
||||
selectedContentId <= 0 ||
|
||||
selectedContentTitle.isBlank() ||
|
||||
selectedContentCreatorNickname.isBlank()
|
||||
) {
|
||||
Toast.makeText(applicationContext, "알람 콘텐츠를 선택하세요", Toast.LENGTH_LONG).show()
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
import android.media.MediaPlayer
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.lifecycle.Observer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailViewModel
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||
import kr.co.vividnext.sodalive.databinding.ActivityAlarmBinding
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.AlarmDatabase
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class AlarmActivity : BaseActivity<ActivityAlarmBinding>(
|
||||
ActivityAlarmBinding::inflate
|
||||
) {
|
||||
|
||||
private val contentViewModel: AudioContentDetailViewModel by inject()
|
||||
|
||||
private lateinit var mediaPlayer: MediaPlayer
|
||||
private lateinit var loadingDialog: LoadingDialog
|
||||
|
||||
private lateinit var audioManager: AudioManager
|
||||
private var originalVolume: Int = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
setTurnScreenOn(true)
|
||||
setShowWhenLocked(true)
|
||||
} else {
|
||||
window.addFlags(
|
||||
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
||||
or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
||||
or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
|
||||
or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
|
||||
)
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
initAudioManagerAndSaveOriginalVolume()
|
||||
bindData()
|
||||
getAlarm()
|
||||
}
|
||||
|
||||
private fun getAlarm() {
|
||||
val alarmId = intent.getIntExtra(Constants.EXTRA_ALARM_ID, -1)
|
||||
val alarmDao = AlarmDatabase.getDatabase(applicationContext).alarmDao()
|
||||
val alarmLiveData = alarmDao.getAlarmById(alarmId)
|
||||
|
||||
val observer = object : Observer<Alarm> {
|
||||
override fun onChanged(value: Alarm) {
|
||||
getContent(value.contentId)
|
||||
setAlarmData(value)
|
||||
alarmLiveData.removeObserver(this)
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
alarmLiveData.observeForever(observer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initAudioManagerAndSaveOriginalVolume() {
|
||||
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
originalVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||
}
|
||||
|
||||
private fun setVolume(volume: Int) {
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0)
|
||||
}
|
||||
|
||||
private fun setAlarmData(alarm: Alarm) {
|
||||
binding.tvTitle.text = alarm.title
|
||||
binding.tvTime.text = SimpleDateFormat("hh:mm", Locale.getDefault())
|
||||
.format(alarm.time)
|
||||
binding.tvDate.text = SimpleDateFormat("MM월 dd일", Locale.getDefault())
|
||||
.format(alarm.time)
|
||||
}
|
||||
|
||||
private fun getContent(contentId: Long) {
|
||||
contentViewModel.getAudioContentDetail(contentId) {}
|
||||
}
|
||||
|
||||
private fun bindData() {
|
||||
contentViewModel.isLoading.observe(this) {
|
||||
if (it) {
|
||||
loadingDialog.show(screenWidth, "")
|
||||
} else {
|
||||
loadingDialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
contentViewModel.audioContentLiveData.observe(this) {
|
||||
initMediaPlayer(it.contentUrl)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||
binding.ivStopAlarm.setOnClickListener { finish() }
|
||||
|
||||
onBackPressedDispatcher.addCallback(
|
||||
this,
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun initMediaPlayer(alarmUrl: String) {
|
||||
setVolume(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
|
||||
mediaPlayer = MediaPlayer()
|
||||
mediaPlayer.isLooping = true
|
||||
mediaPlayer.setDataSource(alarmUrl)
|
||||
mediaPlayer.prepareAsync()
|
||||
mediaPlayer.setOnPreparedListener { mp -> mp.start() }
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
setVolume(originalVolume)
|
||||
if (mediaPlayer.isPlaying) {
|
||||
mediaPlayer.stop()
|
||||
}
|
||||
mediaPlayer.release()
|
||||
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.databinding.ItemAlarmBinding
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class AlarmAdapter(
|
||||
private val updateAlarm: (Alarm) -> Unit,
|
||||
private val deleteAlarm: (Alarm) -> Unit,
|
||||
private val onClick: (Int) -> Unit
|
||||
) : ListAdapter<Alarm, AlarmAdapter.AlarmViewHolder>(AlarmDiffCallback()) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlarmViewHolder {
|
||||
return AlarmViewHolder(
|
||||
ItemAlarmBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: AlarmViewHolder, position: Int) {
|
||||
val alarm = getItem(position)
|
||||
holder.bind(alarm)
|
||||
}
|
||||
|
||||
inner class AlarmViewHolder(
|
||||
private val binding: ItemAlarmBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(alarm: Alarm) {
|
||||
binding.tvTitle.text = alarm.title
|
||||
binding.tvAmpm.text = SimpleDateFormat("a", Locale.getDefault())
|
||||
.format(alarm.time)
|
||||
binding.tvTime.text = SimpleDateFormat("hh:mm", Locale.getDefault())
|
||||
.format(alarm.time)
|
||||
binding.tvDays.text = if (alarm.days.isNotEmpty()) {
|
||||
alarm.getDaysText()
|
||||
} else {
|
||||
SimpleDateFormat("MM월 dd일 (E)", Locale.getDefault())
|
||||
.format(alarm.time)
|
||||
}
|
||||
|
||||
binding.tvContentTitle.text = alarm.contentTitle
|
||||
binding.tvCreatorNickname.text = alarm.contentCreatorNickname
|
||||
|
||||
binding.ivEnable.setImageResource(
|
||||
if (alarm.isEnabled) {
|
||||
R.drawable.btn_toggle_on_big
|
||||
} else {
|
||||
R.drawable.btn_toggle_off_big
|
||||
}
|
||||
)
|
||||
|
||||
binding.ivEnable.setOnClickListener {
|
||||
alarm.isEnabled = !alarm.isEnabled
|
||||
updateAlarm(alarm)
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener { onClick(alarm.id) }
|
||||
binding.root.setOnLongClickListener {
|
||||
deleteAlarm(alarm)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AlarmDiffCallback : DiffUtil.ItemCallback<Alarm>() {
|
||||
override fun areItemsTheSame(oldItem: Alarm, newItem: Alarm): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: Alarm, newItem: Alarm): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,251 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlarmManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.gun0912.tedpermission.PermissionListener
|
||||
import com.gun0912.tedpermission.normal.TedPermission
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.base.SodaDialog
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||
import kr.co.vividnext.sodalive.databinding.ActivityAlarmListBinding
|
||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class AlarmListActivity : BaseActivity<ActivityAlarmListBinding>(
|
||||
ActivityAlarmListBinding::inflate
|
||||
) {
|
||||
|
||||
private val alarmViewModel: AlarmViewModel by viewModels()
|
||||
private val viewModel: AlarmListViewModel by inject()
|
||||
|
||||
private lateinit var alarmAdapter: AlarmAdapter
|
||||
private lateinit var loadingDialog: LoadingDialog
|
||||
|
||||
private lateinit var requestOverlayPermissionLauncher: ActivityResultLauncher<Intent>
|
||||
private lateinit var requestExactAlarmPermissionLauncher: ActivityResultLauncher<Intent>
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
checkAndRequestOverlayPermission()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
checkAndRequestExactAlarmPermission()
|
||||
}
|
||||
|
||||
checkPermissions()
|
||||
bindData()
|
||||
}
|
||||
|
||||
private fun checkAndRequestOverlayPermission() {
|
||||
requestOverlayPermissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
if (!Settings.canDrawOverlays(this)) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"알람서비스를 이용하시려면 다른 앱 위에 표시 권한을 허용하셔야 합니다.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
if (!Settings.canDrawOverlays(this)) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"알람서비스를 이용하시려면 다른 앱 위에 표시 권한을 허용하셔야 합니다.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
val intent = Intent(
|
||||
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
||||
Uri.parse("package:$packageName")
|
||||
)
|
||||
requestOverlayPermissionLauncher.launch(intent)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
private fun checkAndRequestExactAlarmPermission() {
|
||||
requestExactAlarmPermissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
if (!alarmManager.canScheduleExactAlarms()) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
"알람서비스를 이용하시려면 권한을 허용하셔야 합니다.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
if (!alarmManager.canScheduleExactAlarms()) {
|
||||
val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM)
|
||||
requestExactAlarmPermissionLauncher.launch(intent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||
|
||||
binding.tvBack.text = "소다로 살다 (알람 등록)"
|
||||
binding.tvBack.setOnClickListener { finish() }
|
||||
binding.ivPlus.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(
|
||||
applicationContext,
|
||||
AddAlarmActivity::class.java
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
alarmAdapter = AlarmAdapter(
|
||||
updateAlarm = {
|
||||
alarmViewModel.update(it)
|
||||
adapterRefresh()
|
||||
},
|
||||
deleteAlarm = { showDeleteConfirm(it) },
|
||||
onClick = {
|
||||
startActivity(
|
||||
Intent(applicationContext, AddAlarmActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_ALARM_ID, it)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
binding.rvAlarm.layoutManager = LinearLayoutManager(this)
|
||||
binding.rvAlarm.adapter = alarmAdapter
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun adapterRefresh() {
|
||||
alarmAdapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun bindData() {
|
||||
alarmViewModel.allAlarms.observe(this) { alarms ->
|
||||
alarms?.let {
|
||||
alarmAdapter.submitList(it)
|
||||
binding.scrollView.visibility =
|
||||
if (it.isEmpty()) View.GONE else View.VISIBLE
|
||||
binding.tvEmptyAlarms.visibility =
|
||||
if (it.isEmpty()) View.VISIBLE else View.GONE
|
||||
|
||||
|
||||
viewModel.getSlotQuantityAndPrice()
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.toastLiveData.observe(this) {
|
||||
Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
viewModel.isLoading.observe(this) {
|
||||
if (it) {
|
||||
loadingDialog.show(screenWidth, "")
|
||||
} else {
|
||||
loadingDialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.maxAlarmSlotLiveData.observe(this) {
|
||||
if (it > 0 && alarmAdapter.itemCount >= it) {
|
||||
binding.ivPlus.visibility = View.GONE
|
||||
binding.llBuyExtraSlot.visibility = View.VISIBLE
|
||||
binding.tvInfinity.visibility = if (it - 3 >= 2) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
binding.llBuyExtraSlot.setOnClickListener { showBuyConfirm() }
|
||||
} else {
|
||||
binding.ivPlus.visibility = View.VISIBLE
|
||||
binding.llBuyExtraSlot.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.extraSlotPriceLiveData.observe(this) {
|
||||
binding.tvPrice.text = it.moneyFormat()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPermissions() {
|
||||
val permissions = mutableListOf<String>()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
permissions.add(Manifest.permission.USE_FULL_SCREEN_INTENT)
|
||||
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
|
||||
if (permissions.isNotEmpty()) {
|
||||
TedPermission.create()
|
||||
.setPermissionListener(object : PermissionListener {
|
||||
override fun onPermissionGranted() {
|
||||
}
|
||||
|
||||
override fun onPermissionDenied(deniedPermissions: MutableList<String>?) {
|
||||
finish()
|
||||
}
|
||||
})
|
||||
.setDeniedMessage(
|
||||
"권한을 거부하시면 알람서비스를 이용하실 수 없습니다."
|
||||
)
|
||||
.setPermissions(*permissions.toTypedArray())
|
||||
.check()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDeleteConfirm(alarm: Alarm) {
|
||||
SodaDialog(
|
||||
this,
|
||||
layoutInflater,
|
||||
title = "알림",
|
||||
desc = "알람을 삭제하시겠습니까?",
|
||||
confirmButtonTitle = "삭제",
|
||||
confirmButtonClick = {
|
||||
alarmViewModel.delete(alarm)
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
"알람이 삭제되었습니다.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
adapterRefresh()
|
||||
},
|
||||
cancelButtonTitle = "취소",
|
||||
).show(screenWidth)
|
||||
}
|
||||
|
||||
private fun showBuyConfirm() {
|
||||
SodaDialog(
|
||||
this,
|
||||
layoutInflater,
|
||||
title = "알림",
|
||||
desc = "추가 슬롯을 구매하시겠습니까?",
|
||||
confirmButtonTitle = "구매",
|
||||
confirmButtonClick = { viewModel.buyExtraSlot() },
|
||||
cancelButtonTitle = "취소",
|
||||
).show(screenWidth)
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.POST
|
||||
|
||||
interface AlarmListApi {
|
||||
@GET("/alarm")
|
||||
fun getSlotQuantityAndPrice(
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<GetSlotQuantityAndPriceResponse>>
|
||||
|
||||
@POST("/alarm/buy-slot/aos")
|
||||
fun buyExtraSlot(@Header("Authorization") authHeader: String): Single<ApiResponse<Any>>
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
class AlarmListRepository(private val api: AlarmListApi) {
|
||||
fun getSlotQuantityAndPrice(token: String) = api.getSlotQuantityAndPrice(authHeader = token)
|
||||
|
||||
fun buyExtraSlot(token: String) = api.buyExtraSlot(authHeader = token)
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.orhanobut.logger.Logger
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
|
||||
class AlarmListViewModel(private val repository: AlarmListRepository) : BaseViewModel() {
|
||||
private val _toastLiveData = MutableLiveData<String?>()
|
||||
val toastLiveData: LiveData<String?>
|
||||
get() = _toastLiveData
|
||||
|
||||
private var _isLoading = MutableLiveData(false)
|
||||
val isLoading: LiveData<Boolean>
|
||||
get() = _isLoading
|
||||
|
||||
private var _maxAlarmSlotLiveData = MutableLiveData(3)
|
||||
val maxAlarmSlotLiveData: LiveData<Int>
|
||||
get() = _maxAlarmSlotLiveData
|
||||
|
||||
private var _extraSlotPriceLiveData = MutableLiveData(0)
|
||||
val extraSlotPriceLiveData: LiveData<Int>
|
||||
get() = _extraSlotPriceLiveData
|
||||
|
||||
fun getSlotQuantityAndPrice() {
|
||||
_isLoading.value = true
|
||||
compositeDisposable.add(
|
||||
repository.getSlotQuantityAndPrice("Bearer ${SharedPreferenceManager.token}")
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
_isLoading.value = false
|
||||
if (it.success && it.data != null) {
|
||||
if (it.data.slotQuantity >= 3) {
|
||||
_maxAlarmSlotLiveData.value = 0
|
||||
} else {
|
||||
_maxAlarmSlotLiveData.value = 3 + it.data.slotQuantity
|
||||
}
|
||||
|
||||
_extraSlotPriceLiveData.value = it.data.price
|
||||
} else {
|
||||
if (it.message != null) {
|
||||
_toastLiveData.postValue(it.message)
|
||||
} else {
|
||||
_toastLiveData.postValue(
|
||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
_isLoading.value = false
|
||||
it.message?.let { message -> Logger.e(message) }
|
||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun buyExtraSlot() {
|
||||
_isLoading.value = true
|
||||
compositeDisposable.add(
|
||||
repository.buyExtraSlot("Bearer ${SharedPreferenceManager.token}")
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
_isLoading.value = false
|
||||
if (it.success) {
|
||||
getSlotQuantityAndPrice()
|
||||
} else {
|
||||
if (it.message != null) {
|
||||
_toastLiveData.postValue(it.message)
|
||||
} else {
|
||||
_toastLiveData.postValue(
|
||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
_isLoading.value = false
|
||||
it.message?.let { message -> Logger.e(message) }
|
||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.AlarmDao
|
||||
|
||||
class AlarmRepository(private val alarmDao: AlarmDao) {
|
||||
val allAlarms = alarmDao.getAllAlarms()
|
||||
|
||||
suspend fun insert(alarm: Alarm): Alarm {
|
||||
return withContext(Dispatchers.IO) {
|
||||
alarmDao.insertAndReturnAlarm(alarm)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun update(alarm: Alarm) {
|
||||
withContext(Dispatchers.IO) {
|
||||
alarmDao.updateAlarm(alarm)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun delete(alarm: Alarm) {
|
||||
withContext(Dispatchers.IO) {
|
||||
alarmDao.deleteAlarm(alarm)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun truncate() {
|
||||
withContext(Dispatchers.IO) {
|
||||
alarmDao.truncateTable()
|
||||
}
|
||||
}
|
||||
|
||||
fun getAlarmById(id: Int): LiveData<Alarm> {
|
||||
return alarmDao.getAlarmById(id)
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.AlarmDatabase
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.scheduler.AlarmScheduler
|
||||
|
||||
class AlarmViewModel(application: Application) : AndroidViewModel(application) {
|
||||
private val repository: AlarmRepository
|
||||
private val scheduler: AlarmScheduler
|
||||
|
||||
init {
|
||||
val alarmDao = AlarmDatabase.getDatabase(application).alarmDao()
|
||||
repository = AlarmRepository(alarmDao)
|
||||
scheduler = AlarmScheduler(application)
|
||||
}
|
||||
|
||||
var allAlarms = repository.allAlarms.asLiveData()
|
||||
|
||||
fun insert(alarm: Alarm) = viewModelScope.launch {
|
||||
val insertedUser = repository.insert(alarm)
|
||||
if (insertedUser.isEnabled) {
|
||||
scheduler.setAlarm(insertedUser)
|
||||
}
|
||||
}
|
||||
|
||||
fun update(alarm: Alarm) = viewModelScope.launch {
|
||||
repository.update(alarm)
|
||||
scheduler.cancelAlarm(alarm)
|
||||
|
||||
if (alarm.isEnabled) {
|
||||
scheduler.setAlarm(alarm)
|
||||
}
|
||||
}
|
||||
|
||||
fun delete(alarm: Alarm) = viewModelScope.launch {
|
||||
repository.delete(alarm)
|
||||
scheduler.cancelAlarm(alarm)
|
||||
}
|
||||
|
||||
fun truncate() = viewModelScope.launch {
|
||||
repository.truncate()
|
||||
}
|
||||
|
||||
fun getAlarmById(id: Int): LiveData<Alarm> {
|
||||
return repository.getAlarmById(id)
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class GetSlotQuantityAndPriceResponse(
|
||||
@SerializedName("slotQuantity") val slotQuantity: Int,
|
||||
@SerializedName("price") val price: Int
|
||||
)
|
|
@ -1,20 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.db
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "alarms")
|
||||
data class Alarm(
|
||||
@PrimaryKey(autoGenerate = true) val id: Int = 0,
|
||||
val title: String,
|
||||
var time: Long,
|
||||
val days: List<String>,
|
||||
val contentId: Long,
|
||||
val contentTitle: String,
|
||||
val contentCreatorNickname: String,
|
||||
var isEnabled: Boolean = true
|
||||
) {
|
||||
fun getDaysText(): String {
|
||||
return if (days.size == 7) "매일" else days.joinToString(", ")
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.db
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Update
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface AlarmDao {
|
||||
@Query("SELECT * FROM alarms WHERE id = :id")
|
||||
fun getAlarmById(id: Int): LiveData<Alarm>
|
||||
|
||||
@Query("SELECT * FROM alarms")
|
||||
fun getAllAlarms(): Flow<List<Alarm>>
|
||||
|
||||
@Query("DELETE FROM alarms")
|
||||
fun deleteAllAlarms()
|
||||
|
||||
@Query("DELETE FROM sqlite_sequence WHERE name = 'alarms'")
|
||||
fun resetAutoIncrement()
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertAlarm(alarm: Alarm): Long
|
||||
|
||||
@Update
|
||||
fun updateAlarm(alarm: Alarm)
|
||||
|
||||
@Delete
|
||||
fun deleteAlarm(alarm: Alarm)
|
||||
|
||||
@Transaction
|
||||
fun insertAndReturnAlarm(alarm: Alarm): Alarm {
|
||||
val id = insertAlarm(alarm)
|
||||
return alarm.copy(id = id.toInt())
|
||||
}
|
||||
|
||||
@Transaction
|
||||
fun truncateTable() {
|
||||
deleteAllAlarms()
|
||||
resetAutoIncrement()
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import kr.co.vividnext.sodalive.common.Converter
|
||||
|
||||
@Database(entities = [Alarm::class], version = 1)
|
||||
@TypeConverters(Converter::class)
|
||||
abstract class AlarmDatabase : RoomDatabase() {
|
||||
abstract fun alarmDao(): AlarmDao
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var INSTANCE: AlarmDatabase? = null
|
||||
|
||||
fun getDatabase(context: Context): AlarmDatabase {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val instance = Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
AlarmDatabase::class.java,
|
||||
"alarm_database"
|
||||
).build()
|
||||
INSTANCE = instance
|
||||
instance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.AlarmDatabase
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.scheduler.AlarmScheduler
|
||||
|
||||
class AlarmBootReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
||||
val alarmDao = AlarmDatabase.getDatabase(context).alarmDao()
|
||||
val scheduler = AlarmScheduler(context)
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
alarmDao.getAllAlarms().collect { alarms ->
|
||||
alarms.forEach { alarm ->
|
||||
scheduler.setAlarm(alarm)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.lifecycle.Observer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.AlarmActivity
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.AlarmDatabase
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.scheduler.AlarmScheduler
|
||||
import java.util.Calendar
|
||||
|
||||
class AlarmReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val alarmId = intent.getIntExtra(Constants.EXTRA_ALARM_ID, -1)
|
||||
|
||||
if (alarmId > 0) {
|
||||
val alarmIntent = Intent(context, AlarmActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_ALARM_ID, alarmId)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TOP or
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
}
|
||||
|
||||
val alarmDao = AlarmDatabase.getDatabase(context).alarmDao()
|
||||
val alarmLiveData = alarmDao.getAlarmById(alarmId)
|
||||
|
||||
val observer = object : Observer<Alarm> {
|
||||
override fun onChanged(value: Alarm) {
|
||||
val scheduler = AlarmScheduler(context)
|
||||
if (value.days.isNotEmpty()) {
|
||||
scheduler.setAlarm(value)
|
||||
} else {
|
||||
scheduler.cancelAlarm(value)
|
||||
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = value.time
|
||||
calendar.add(Calendar.DAY_OF_YEAR, 1)
|
||||
|
||||
value.time = calendar.timeInMillis
|
||||
value.isEnabled = false
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
alarmDao.updateAlarm(value)
|
||||
}
|
||||
}
|
||||
alarmLiveData.removeObserver(this)
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
alarmLiveData.observeForever(observer)
|
||||
}
|
||||
}
|
||||
|
||||
context.startActivity(alarmIntent)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.scheduler
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.db.Alarm
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.receiver.AlarmReceiver
|
||||
import java.util.Calendar
|
||||
|
||||
class AlarmScheduler(private val context: Context) {
|
||||
fun setAlarm(alarm: Alarm) {
|
||||
if (alarm.days.isEmpty()) {
|
||||
setOneTimeAlarm(alarm)
|
||||
} else {
|
||||
setRepeatingAlarm(alarm)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setOneTimeAlarm(alarm: Alarm) {
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
|
||||
val alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
|
||||
intent.putExtra(Constants.EXTRA_ALARM_ID, alarm.id)
|
||||
createPendingIntent(requestCode = alarm.id, intent)
|
||||
}
|
||||
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = alarm.time
|
||||
|
||||
// 현재 시간보다 이전이면 내일 해당 시간으로 설정
|
||||
if (calendar.timeInMillis <= System.currentTimeMillis()) {
|
||||
calendar.add(Calendar.DAY_OF_YEAR, 1)
|
||||
}
|
||||
|
||||
val info = AlarmManager.AlarmClockInfo(calendar.timeInMillis, alarmIntent)
|
||||
alarmManager.setAlarmClock(info, alarmIntent)
|
||||
}
|
||||
|
||||
private fun setRepeatingAlarm(alarm: Alarm) {
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
|
||||
alarm.days.forEach { day ->
|
||||
val requestCode = alarm.id * 10 + getDayOfWeek(day)
|
||||
val alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
|
||||
intent.putExtra(Constants.EXTRA_ALARM_ID, alarm.id)
|
||||
createPendingIntent(requestCode, intent)
|
||||
}
|
||||
|
||||
val calendar = getNextAlarmTime(day, alarm.time)
|
||||
|
||||
// 현재 시간이 설정된 알람 시간보다 늦으면 다음 주에 울리도록 설정
|
||||
if (calendar.timeInMillis <= System.currentTimeMillis()) {
|
||||
calendar.add(Calendar.WEEK_OF_YEAR, 1)
|
||||
}
|
||||
|
||||
val info = AlarmManager.AlarmClockInfo(calendar.timeInMillis, alarmIntent)
|
||||
alarmManager.setAlarmClock(info, alarmIntent)
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelAlarm(alarm: Alarm) {
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
|
||||
if (alarm.days.isEmpty()) {
|
||||
val alarmIntent = createPendingIntent(
|
||||
requestCode = alarm.id,
|
||||
intent = Intent(context, AlarmReceiver::class.java)
|
||||
)
|
||||
alarmManager.cancel(alarmIntent)
|
||||
} else {
|
||||
alarm.days.forEach { day ->
|
||||
val requestCode = alarm.id * 10 + getDayOfWeek(day)
|
||||
val alarmIntent = createPendingIntent(
|
||||
requestCode,
|
||||
Intent(context, AlarmReceiver::class.java)
|
||||
)
|
||||
alarmManager.cancel(alarmIntent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPendingIntent(requestCode: Int, intent: Intent): PendingIntent {
|
||||
val flags = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
} else {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, requestCode, intent, flags)
|
||||
}
|
||||
|
||||
private fun getNextAlarmTime(day: String, timeInMillis: Long): Calendar {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = timeInMillis
|
||||
calendar.set(Calendar.DAY_OF_WEEK, getDayOfWeek(day))
|
||||
return calendar
|
||||
}
|
||||
|
||||
private fun getDayOfWeek(day: String): Int {
|
||||
return when (day) {
|
||||
"일" -> Calendar.SUNDAY
|
||||
"월" -> Calendar.MONDAY
|
||||
"화" -> Calendar.TUESDAY
|
||||
"수" -> Calendar.WEDNESDAY
|
||||
"목" -> Calendar.THURSDAY
|
||||
"금" -> Calendar.FRIDAY
|
||||
"토" -> Calendar.SATURDAY
|
||||
else -> Calendar.MONDAY
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.select_audio_content
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderListViewModel
|
||||
import kr.co.vividnext.sodalive.audio_content.order.OrderType
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||
import kr.co.vividnext.sodalive.databinding.ActivityAlarmSelectAudioContentBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class AlarmSelectAudioContentActivity : BaseActivity<ActivityAlarmSelectAudioContentBinding>(
|
||||
ActivityAlarmSelectAudioContentBinding::inflate
|
||||
) {
|
||||
private val viewModel: AudioContentOrderListViewModel by inject()
|
||||
|
||||
private lateinit var loadingDialog: LoadingDialog
|
||||
private lateinit var adapter: AlarmSelectAudioContentAdapter
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
bindData()
|
||||
viewModel.getAudioContentOrderList { finish() }
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||
binding.toolbar.tvBack.text = "콘텐츠 선택"
|
||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||
|
||||
adapter = AlarmSelectAudioContentAdapter {
|
||||
val resultIntent = Intent().apply {
|
||||
putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it.contentId)
|
||||
putExtra(Constants.EXTRA_AUDIO_CONTENT_TITLE, it.title)
|
||||
putExtra(Constants.EXTRA_AUDIO_CONTENT_CREATOR_NICKNAME, it.creatorNickname)
|
||||
}
|
||||
setResult(RESULT_OK, resultIntent)
|
||||
finish()
|
||||
}
|
||||
|
||||
binding.rvOrderList.layoutManager = LinearLayoutManager(
|
||||
applicationContext,
|
||||
LinearLayoutManager.VERTICAL,
|
||||
false
|
||||
)
|
||||
|
||||
binding.rvOrderList.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
super.getItemOffsets(outRect, view, parent, state)
|
||||
|
||||
outRect.left = 13.3f.dpToPx().toInt()
|
||||
outRect.right = 13.3f.dpToPx().toInt()
|
||||
|
||||
when (parent.getChildAdapterPosition(view)) {
|
||||
0 -> {
|
||||
outRect.top = 13.3f.dpToPx().toInt()
|
||||
outRect.bottom = 6.7f.dpToPx().toInt()
|
||||
}
|
||||
|
||||
adapter.itemCount - 1 -> {
|
||||
outRect.top = 6.7f.dpToPx().toInt()
|
||||
outRect.bottom = 13.3f.dpToPx().toInt()
|
||||
}
|
||||
|
||||
else -> {
|
||||
outRect.top = 6.7f.dpToPx().toInt()
|
||||
outRect.bottom = 6.7f.dpToPx().toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
binding.rvOrderList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
|
||||
val lastVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager?)!!
|
||||
.findLastCompletelyVisibleItemPosition()
|
||||
val itemTotalCount = recyclerView.adapter!!.itemCount - 1
|
||||
|
||||
// 스크롤이 끝에 도달했는지 확인
|
||||
if (!recyclerView.canScrollVertically(1) &&
|
||||
lastVisibleItemPosition == itemTotalCount
|
||||
) {
|
||||
viewModel.getAudioContentOrderList {}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
binding.rvOrderList.adapter = adapter
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun bindData() {
|
||||
viewModel.toastLiveData.observe(this) {
|
||||
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
|
||||
}
|
||||
|
||||
viewModel.isLoading.observe(this) {
|
||||
if (it) {
|
||||
loadingDialog.show(screenWidth, "")
|
||||
} else {
|
||||
loadingDialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.orderList.observe(this) { items ->
|
||||
val keepItems = items.filter { it.orderType == OrderType.KEEP }
|
||||
|
||||
if (viewModel.page == 2) {
|
||||
adapter.items.clear()
|
||||
}
|
||||
|
||||
adapter.items.addAll(keepItems)
|
||||
adapter.notifyDataSetChanged()
|
||||
|
||||
if (adapter.items.count() + keepItems.size > 0) {
|
||||
binding.rvOrderList.visibility = View.VISIBLE
|
||||
binding.tvEmptyOrderList.visibility = View.GONE
|
||||
} else {
|
||||
binding.rvOrderList.visibility = View.GONE
|
||||
binding.tvEmptyOrderList.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package kr.co.vividnext.sodalive.mypage.alarm.select_audio_content
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.load
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.audio_content.order.GetAudioContentOrderListItem
|
||||
import kr.co.vividnext.sodalive.audio_content.order.OrderType
|
||||
import kr.co.vividnext.sodalive.databinding.ItemAudioContentOrderListBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||
|
||||
class AlarmSelectAudioContentAdapter(
|
||||
private val onItemClick: (GetAudioContentOrderListItem) -> Unit
|
||||
) : RecyclerView.Adapter<AlarmSelectAudioContentAdapter.ViewHolder>() {
|
||||
|
||||
var items = mutableSetOf<GetAudioContentOrderListItem>()
|
||||
|
||||
inner class ViewHolder(
|
||||
private val binding: ItemAudioContentOrderListBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(item: GetAudioContentOrderListItem) {
|
||||
binding.ivCover.load(item.coverImageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.ic_place_holder)
|
||||
transformations(RoundedCornersTransformation(5.3f.dpToPx()))
|
||||
}
|
||||
|
||||
binding.tvTitle.text = item.title
|
||||
binding.tvTheme.text = item.themeStr
|
||||
binding.tvDuration.text = item.duration
|
||||
binding.tvCreatorNickname.text = item.creatorNickname
|
||||
binding.tvLikeCount.text = item.likeCount.moneyFormat()
|
||||
binding.tvCommentCount.text = item.commentCount.moneyFormat()
|
||||
|
||||
binding.root.setOnClickListener { onItemClick(item) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
ItemAudioContentOrderListBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(items.toList()[position])
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
}
|
|
@ -36,12 +36,6 @@ interface CanApi {
|
|||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<Any>>
|
||||
|
||||
@POST("/charge/verify/hecto")
|
||||
fun verifyChargeHecto(
|
||||
@Body request: VerifyRequest,
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<Any>>
|
||||
|
||||
@GET("/can")
|
||||
fun getCans(
|
||||
@Header("Authorization") authHeader: String
|
||||
|
|
|
@ -22,11 +22,6 @@ class CanRepository(private val api: CanApi) {
|
|||
token: String
|
||||
) = api.verifyCharge(request, authHeader = token)
|
||||
|
||||
fun verifyHecto(
|
||||
request: VerifyRequest,
|
||||
token: String
|
||||
) = api.verifyChargeHecto(request, authHeader = token)
|
||||
|
||||
fun getCans(token: String) = api.getCans(authHeader = token)
|
||||
|
||||
fun getCanStatus(token: String) = api.getCanStatus(authHeader = token)
|
||||
|
|
|
@ -13,7 +13,6 @@ import com.google.gson.Gson
|
|||
import com.orhanobut.logger.Logger
|
||||
import kr.co.bootpay.android.Bootpay
|
||||
import kr.co.bootpay.android.events.BootpayEventListener
|
||||
import kr.co.bootpay.android.models.BootUser
|
||||
import kr.co.bootpay.android.models.Payload
|
||||
import kr.co.vividnext.sodalive.BuildConfig
|
||||
import kr.co.vividnext.sodalive.R
|
||||
|
@ -33,7 +32,7 @@ class CanPaymentActivity : BaseActivity<ActivityCanPaymentBinding>(
|
|||
ActivityCanPaymentBinding::inflate
|
||||
) {
|
||||
enum class PaymentMethod(val method: String) {
|
||||
CARD("카드"), BANK("계좌이체"), PHONE("휴대폰")
|
||||
CARD("디지털카드"), BANK("디지털계좌이체"), PHONE("휴대폰")
|
||||
}
|
||||
|
||||
private val viewModel: CanPaymentViewModel by inject()
|
||||
|
@ -159,25 +158,14 @@ class CanPaymentActivity : BaseActivity<ActivityCanPaymentBinding>(
|
|||
}
|
||||
|
||||
private fun requestPayment(chargeId: Long) {
|
||||
var username = SharedPreferenceManager.nickname
|
||||
|
||||
if (username.length > 10) {
|
||||
username = "${username.take(6)}..."
|
||||
}
|
||||
|
||||
val user = BootUser()
|
||||
.setId("${SharedPreferenceManager.userId}")
|
||||
.setUsername(username)
|
||||
|
||||
val payload = Payload()
|
||||
.setApplicationId(BuildConfig.BOOTPAY_APP_HECTO_ID)
|
||||
.setApplicationId(BuildConfig.BOOTPAY_APP_ID)
|
||||
.setOrderId("$chargeId")
|
||||
.setOrderName(canResponse!!.title)
|
||||
.setPrice(canResponse!!.price.toDouble())
|
||||
.setTaxFree(0.toDouble())
|
||||
.setPg("세틀뱅크")
|
||||
.setPg("웰컴페이먼츠")
|
||||
.setMethod(viewModel.paymentMethodLiveData.value!!.method)
|
||||
.setUser(user)
|
||||
|
||||
Bootpay.init(this, this)
|
||||
.setPayload(payload)
|
||||
|
@ -219,7 +207,7 @@ class CanPaymentActivity : BaseActivity<ActivityCanPaymentBinding>(
|
|||
val bootpayResponse = Gson().fromJson(data, BootpayResponse::class.java)
|
||||
val request = VerifyRequest(bootpayResponse.data.receiptId, bootpayResponse.data.orderId)
|
||||
|
||||
viewModel.verifyHecto(
|
||||
viewModel.verify(
|
||||
request,
|
||||
onSuccess = {
|
||||
Toast.makeText(applicationContext, "캔이 충전되었습니다", Toast.LENGTH_LONG).show()
|
||||
|
|
|
@ -151,7 +151,7 @@ class CanPaymentTempActivity : BaseActivity<ActivityCanPaymentBinding>(
|
|||
.setUsername(SharedPreferenceManager.nickname)
|
||||
|
||||
val payload = Payload()
|
||||
.setApplicationId(BuildConfig.BOOTPAY_APP_HECTO_ID)
|
||||
.setApplicationId(BuildConfig.BOOTPAY_APP_ID)
|
||||
.setOrderId("$chargeId")
|
||||
.setOrderName(title)
|
||||
.setPrice((can * 110).toDouble())
|
||||
|
|
|
@ -87,36 +87,6 @@ class CanPaymentViewModel(private val repository: CanRepository) : BaseViewModel
|
|||
)
|
||||
}
|
||||
|
||||
fun verifyHecto(request: VerifyRequest, onSuccess: () -> Unit, onFailure: (String) -> Unit) {
|
||||
_isLoading.value = true
|
||||
compositeDisposable.add(
|
||||
repository.verifyHecto(
|
||||
request = request,
|
||||
"Bearer ${SharedPreferenceManager.token}"
|
||||
).subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
_isLoading.value = false
|
||||
if (it.success) {
|
||||
onSuccess()
|
||||
} else {
|
||||
if (it.message != null) {
|
||||
onFailure(it.message)
|
||||
} else {
|
||||
onFailure("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
_isLoading.value = false
|
||||
it.message?.let { message -> Logger.e(message) }
|
||||
onFailure("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun setPaymentMethod(paymentMethod: CanPaymentActivity.PaymentMethod) {
|
||||
_paymentMethodLiveData.value = paymentMethod
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Intent
|
|||
import android.graphics.Paint
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.viewModels
|
||||
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
|
||||
import kr.co.vividnext.sodalive.BuildConfig
|
||||
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
||||
|
@ -15,7 +14,6 @@ import kr.co.vividnext.sodalive.common.Constants
|
|||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.databinding.ActivitySettingsBinding
|
||||
import kr.co.vividnext.sodalive.mypage.alarm.AlarmViewModel
|
||||
import kr.co.vividnext.sodalive.settings.event.EventActivity
|
||||
import kr.co.vividnext.sodalive.settings.notice.NoticeActivity
|
||||
import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsActivity
|
||||
|
@ -52,7 +50,6 @@ class SettingsActivity : BaseActivity<ActivitySettingsBinding>(ActivitySettingsB
|
|||
}
|
||||
|
||||
private val viewModel: SettingsViewModel by inject()
|
||||
private val alarmViewModel: AlarmViewModel by viewModels()
|
||||
|
||||
private lateinit var loadingDialog: LoadingDialog
|
||||
|
||||
|
@ -97,13 +94,13 @@ class SettingsActivity : BaseActivity<ActivitySettingsBinding>(ActivitySettingsB
|
|||
|
||||
binding.rlTerms.setOnClickListener {
|
||||
val intent = Intent(applicationContext, TermsActivity::class.java)
|
||||
intent.putExtra(Constants.EXTRA_TERMS, Constants.EXTRA_TERMS)
|
||||
intent.putExtra(Constants.EXTRA_TERMS, "terms")
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.rlPrivacyPolicy.setOnClickListener {
|
||||
val intent = Intent(applicationContext, TermsActivity::class.java)
|
||||
intent.putExtra(Constants.EXTRA_TERMS, Constants.EXTRA_PRIVACY)
|
||||
intent.putExtra(Constants.EXTRA_TERMS, "privacy")
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
|
@ -151,7 +148,6 @@ class SettingsActivity : BaseActivity<ActivitySettingsBinding>(ActivitySettingsB
|
|||
|
||||
viewModel.logout {
|
||||
SharedPreferenceManager.clear()
|
||||
alarmViewModel.truncate()
|
||||
finishAffinity()
|
||||
startActivity(Intent(applicationContext, SplashActivity::class.java))
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ class TermsActivity : BaseActivity<ActivityTermsBinding>(ActivityTermsBinding::i
|
|||
super.onCreate(savedInstanceState)
|
||||
bindData()
|
||||
|
||||
val terms = intent.getStringExtra(Constants.EXTRA_TERMS) ?: Constants.EXTRA_TERMS
|
||||
if (terms == Constants.EXTRA_PRIVACY) {
|
||||
val terms = intent.getStringExtra(Constants.EXTRA_TERMS) ?: "terms"
|
||||
if (terms == "privacy") {
|
||||
viewModel.getPrivacyPolicy()
|
||||
} else {
|
||||
viewModel.getTermsOfService()
|
||||
|
|
|
@ -2,13 +2,10 @@ package kr.co.vividnext.sodalive.splash
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.media.MediaPlayer
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.SurfaceHolder
|
||||
import android.widget.ImageView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.os.bundleOf
|
||||
import com.google.firebase.dynamiclinks.PendingDynamicLinkData
|
||||
|
@ -18,7 +15,6 @@ import com.google.firebase.remoteconfig.ktx.get
|
|||
import com.google.firebase.remoteconfig.ktx.remoteConfig
|
||||
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
|
||||
import kr.co.vividnext.sodalive.BuildConfig
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.base.SodaDialog
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
|
@ -29,74 +25,24 @@ import kr.co.vividnext.sodalive.onboarding.OnBoardingActivity
|
|||
import kr.co.vividnext.sodalive.user.login.LoginActivity
|
||||
|
||||
@SuppressLint("CustomSplashScreen")
|
||||
class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding::inflate),
|
||||
SurfaceHolder.Callback2 {
|
||||
class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding::inflate) {
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private val remoteConfig = Firebase.remoteConfig
|
||||
|
||||
private var mediaPlayer: MediaPlayer? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val lp = binding.ivText.layoutParams as ConstraintLayout.LayoutParams
|
||||
lp.topMargin = screenHeight * 302 / 2337
|
||||
binding.ivText.layoutParams = lp
|
||||
|
||||
val lp2 = binding.ivText2.layoutParams as ConstraintLayout.LayoutParams
|
||||
lp2.bottomMargin = screenHeight * 195 / 2337
|
||||
binding.ivText2.layoutParams = lp2
|
||||
|
||||
setupRemoteConfig()
|
||||
binding.surfaceView.holder.addCallback(this)
|
||||
}
|
||||
|
||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||
val uri = Uri.parse("android.resource://$packageName/${R.raw.video}")
|
||||
mediaPlayer = MediaPlayer().apply {
|
||||
setDataSource(this@SplashActivity, uri)
|
||||
setDisplay(holder)
|
||||
setOnPreparedListener {
|
||||
start()
|
||||
handler.postDelayed({
|
||||
binding.surfaceView.background = null
|
||||
}, 100)
|
||||
}
|
||||
setOnCompletionListener { fetchAndroidLatestVersion() }
|
||||
prepareAsync()
|
||||
}
|
||||
}
|
||||
|
||||
override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
|
||||
}
|
||||
|
||||
override fun surfaceDestroyed(p0: SurfaceHolder) {
|
||||
mediaPlayer?.release()
|
||||
mediaPlayer = null
|
||||
}
|
||||
|
||||
override fun surfaceRedrawNeeded(p0: SurfaceHolder) {
|
||||
}
|
||||
|
||||
private fun setLayoutParams(
|
||||
imageView: ImageView,
|
||||
start: Int = 0,
|
||||
end: Int = 0,
|
||||
top: Int = 0,
|
||||
bottom: Int = 0
|
||||
) {
|
||||
val lp = imageView.layoutParams as ConstraintLayout.LayoutParams
|
||||
|
||||
if (top > 0) {
|
||||
lp.topMargin = screenHeight * top / 2337
|
||||
}
|
||||
|
||||
if (bottom > 0) {
|
||||
lp.bottomMargin = screenHeight * bottom / 2337
|
||||
}
|
||||
|
||||
if (start > 0) {
|
||||
lp.leftMargin = screenWidth * start / 1080
|
||||
}
|
||||
|
||||
if (end > 0) {
|
||||
lp.rightMargin = screenWidth * end / 1080
|
||||
}
|
||||
|
||||
imageView.layoutParams = lp
|
||||
fetchAndroidLatestVersion()
|
||||
}
|
||||
|
||||
private fun setupRemoteConfig() {
|
||||
|
|
|
@ -98,13 +98,13 @@ class SignUpActivity : BaseActivity<ActivitySignupBinding>(ActivitySignupBinding
|
|||
|
||||
binding.tvTermsOfService.setOnClickListener {
|
||||
val intent = Intent(applicationContext, TermsActivity::class.java)
|
||||
intent.putExtra(Constants.EXTRA_TERMS, Constants.EXTRA_TERMS)
|
||||
intent.putExtra("terms", "terms")
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
binding.tvPrivacyPolicy.setOnClickListener {
|
||||
val intent = Intent(applicationContext, TermsActivity::class.java)
|
||||
intent.putExtra(Constants.EXTRA_TERMS, Constants.EXTRA_PRIVACY)
|
||||
intent.putExtra("terms", "privacy")
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@android:color/white" android:state_checked="true" />
|
||||
<item android:color="@color/color_bbbbbb" android:state_checked="false" />
|
||||
</selector>
|
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 2.2 MiB |
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 3.3 MiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 3.9 KiB |
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_checked="true">
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@color/color_3bb9f1" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_checked="false">
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<corners android:radius="26.7dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_3bb9f1" />
|
||||
</shape>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<corners android:radius="6.7dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_3bb9f1" />
|
||||
</shape>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="5dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_555555" />
|
||||
</shape>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/color_222222" />
|
||||
<corners
|
||||
android:topLeftRadius="13.3dp"
|
||||
android:topRightRadius="13.3dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_222222" />
|
||||
</shape>
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="@color/color_35c2ff"
|
||||
android:startColor="@color/color_97aeff"
|
||||
android:type="linear" />
|
||||
</shape>
|
|
@ -4,7 +4,7 @@
|
|||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="#ebecf3"
|
||||
android:endColor="#e8eaf1"
|
||||
android:startColor="@color/color_a0e2ff"
|
||||
android:endColor="@color/color_ecfaff"
|
||||
android:angle="90" />
|
||||
</shape>
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
<?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"
|
||||
android:background="@color/black"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/detail_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TimePicker
|
||||
android:id="@+id/time_picker"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:theme="@style/TimePickerStyle"
|
||||
android:timePickerMode="spinner"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/bg_top_round_corner_13_3_222222"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/time_picker">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="13.3dp"
|
||||
android:paddingVertical="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chk_sun"
|
||||
style="@style/AlarmDayCheckBox"
|
||||
android:text="일" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chk_mon"
|
||||
style="@style/AlarmDayCheckBox"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="월" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chk_tue"
|
||||
style="@style/AlarmDayCheckBox"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="화" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chk_wed"
|
||||
style="@style/AlarmDayCheckBox"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="수" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chk_thu"
|
||||
style="@style/AlarmDayCheckBox"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="목" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chk_fri"
|
||||
style="@style/AlarmDayCheckBox"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="금" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/chk_sat"
|
||||
style="@style/AlarmDayCheckBox"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="토" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginVertical="21dp"
|
||||
android:background="@color/color_555555" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_alarm_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_7_transparent_555555"
|
||||
android:hint="알람 이름 입력"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text"
|
||||
android:paddingHorizontal="13.3dp"
|
||||
android:paddingVertical="17dp"
|
||||
android:textColor="@color/white"
|
||||
android:textColorHint="@color/color_909090"
|
||||
android:textSize="14.7sp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_select_alarm_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="21dp"
|
||||
android:paddingVertical="13.3dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="RelativeOverlap">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="콘텐츠"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="14.7sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_content_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="콘텐츠를 선택해주세요"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_forward" />
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/color_555555" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="21dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_round_corner_6_7_transparent_3bb9f1"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="16dp"
|
||||
android:text="취소"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_save"
|
||||
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_3bb9f1"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="16dp"
|
||||
android:text="저장"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18.3sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/gradient_alarm"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="53sp"
|
||||
tools:text="6:10" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="19dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14.7sp"
|
||||
tools:text="7월 25일" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="19dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14.7sp"
|
||||
tools:text="라이브 방송 알람" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_stop_alarm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="189dp"
|
||||
android:contentDescription="@null"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_alarm_stop" />
|
||||
</LinearLayout>
|
|
@ -1,139 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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"
|
||||
android:background="@color/black"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="51.7dp"
|
||||
android:background="@color/black"
|
||||
android:paddingHorizontal="13.3dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:drawablePadding="6.7dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:minHeight="48dp"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="18.3sp"
|
||||
app:drawableStartCompat="@drawable/ic_back"
|
||||
tools:ignore="RelativeOverlap"
|
||||
tools:text="소다라이브" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_plus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_plus_no_bg"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:lineSpacingExtra="4sp"
|
||||
android:text="※ 소장중인 콘텐츠만 알람 콘텐츠로 설정할 수 있습니다. 알람 설정 전 콘텐츠 마켓에서 원하는 콘텐츠를 먼저 구매(소장)하세요. "
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="13.5sp" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_alarm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingHorizontal="13.3dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_buy_extra_slot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginVertical="26.7dp"
|
||||
android:background="@drawable/bg_round_corner_5_3_222222"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="16dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="3dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/color_80d8ff"
|
||||
android:textSize="14.7sp"
|
||||
app:drawableRightCompat="@drawable/ic_can"
|
||||
tools:text="30" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text=" 으로"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="14.7sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_infinity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text=" 무제한"
|
||||
android:textColor="@color/color_ff5c49"
|
||||
android:textSize="14.7sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text=" 슬롯 구매하기"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="14.7sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_empty_alarms"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="center"
|
||||
android:text="알람이 없습니다"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="18sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
|
@ -1,30 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/detail_toolbar" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_order_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingVertical="13.3dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_empty_order_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="center"
|
||||
android:text="소장중인 콘텐츠가 없습니다.\n콘텐츠 마켓에서 원하는 알람 콘텐츠를 먼저 구매(소장)하세요."
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:textSize="18sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
|
@ -508,7 +508,6 @@
|
|||
android:background="@color/color_232323" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_service_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
|
@ -535,104 +534,6 @@
|
|||
android:textSize="13.3sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_config_limited_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:lineSpacingExtra="5sp"
|
||||
android:text="한정판 설정"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="16.7sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_config_limited"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_not_limited"
|
||||
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_not_limited"
|
||||
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_not_limited"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="무제한"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="14.7sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_limited"
|
||||
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_13181b"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="14.3dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_limited"
|
||||
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_limited"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="한정판"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="14.7sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_limited"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:background="@drawable/bg_round_corner_6_7_222222"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:hint="한정판 개수를 입력하세요"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberSigned"
|
||||
android:padding="13.3dp"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textColorHint="@color/color_777777"
|
||||
android:textCursorDrawable="@drawable/edit_text_cursor"
|
||||
android:textSize="13.3sp"
|
||||
android:theme="@style/EditTextStyle"
|
||||
android:visibility="gone"
|
||||
tools:ignore="LabelFor" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_config_preview"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -94,63 +94,6 @@
|
|||
android:textSize="13.3sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_record_audio"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="24dp"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="오디오 녹음"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="16.7sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_record_audio"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:background="@drawable/bg_round_corner_5_3_13181b_3bb9f1"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="8dp"
|
||||
android:text="녹음"
|
||||
android:textColor="@color/color_80d8ff"
|
||||
android:textSize="16.7sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:text="※ "
|
||||
android:textColor="@color/color_777777"
|
||||
android:textSize="13.3sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:text="오디오 녹음은 최대 3분입니다"
|
||||
android:textColor="@color/color_777777"
|
||||
android:textSize="13.3sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -380,129 +323,6 @@
|
|||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_price"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:lineSpacingExtra="5sp"
|
||||
android:text="가격 설정"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="16.7sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_config_price"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_price_free"
|
||||
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_price_free"
|
||||
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_price_free"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="무료"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="14.7sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_price_paid"
|
||||
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_13181b"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="14.3dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_price_paid"
|
||||
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_price_paid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="유료"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="14.7sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_price"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:background="@drawable/bg_live_room_price_select"
|
||||
android:baselineAligned="false"
|
||||
android:visibility="gone">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_price"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_toStartOf="@+id/tv_can"
|
||||
android:background="@null"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberDecimal"
|
||||
android:maxLength="5"
|
||||
android:paddingVertical="16.7dp"
|
||||
android:text="0"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textCursorDrawable="@drawable/edit_text_cursor"
|
||||
android:textSize="13.3sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_can"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="13.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:text="캔"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="13.3sp" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -242,16 +242,6 @@
|
|||
android:textSize="12sp"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/bg_round_corner_5_3_transparent_bbbbbb"
|
||||
android:contentDescription="@null"
|
||||
android:padding="4dp"
|
||||
android:src="@drawable/ic_share" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_edit"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -264,14 +264,11 @@
|
|||
android:layout_marginTop="16.7dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:text="
|
||||
- 회사명 : 주식회사 소다라이브\n\n
|
||||
- 대표자 : 이재형\n\n
|
||||
- 주소 : 경기도 성남시 분당구 황새울로335번길 10, 5층 563A호\n\n
|
||||
- 사업자등록번호 : 870-81-03220\n\n
|
||||
- 통신판매업신고 : 제2024-성남분당B-1012호\n\n
|
||||
- 고객센터 : 02.2055.1477(이용시간 10:00~19:00)\n\n
|
||||
- 대표 이메일 : sodalive.official@gmail.com
|
||||
"
|
||||
- 회사명 : 주식회사 소다라이브\n
|
||||
- 대표자 : 이재형\n
|
||||
- 주소 : 경기도 성남시 분당구 황새울로335번길 10, 5층 563A호 (서현동, 멜로즈 프라자)\n
|
||||
- 사업자등록번호 : 870-81-03220\n
|
||||
- 고객센터 : 02.2055.1477"
|
||||
android:textColor="@color/color_777777"
|
||||
android:textSize="11sp" />
|
||||
|
||||
|
|
|
@ -1,12 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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"
|
||||
android:background="@drawable/gradient_splash">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/surface_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/gradient_splash" />
|
||||
</RelativeLayout>
|
||||
<ImageView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/splash_bg"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/splash_text"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_text2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/splash_text_2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
<?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="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/bg_round_corner_10_13181b">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text="게시글 보기"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="18.3sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_desc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="center"
|
||||
android:text="게시글을\n확인하시겠습니까?"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16.7dp"
|
||||
android:layout_marginTop="35dp"
|
||||
android:layout_marginBottom="16.7dp"
|
||||
android:gravity="center"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_desc">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="13.3dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_round_corner_10_13181b_3bb9f1"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:paddingVertical="16dp"
|
||||
android:text="취소"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_can"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2"
|
||||
android:background="@drawable/bg_round_corner_10_3bb9f1"
|
||||
android:paddingVertical="16dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18.3sp"
|
||||
tools:text="100캔으로 보기" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -321,23 +321,6 @@
|
|||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="16.7dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:text="
|
||||
- 회사명 : 주식회사 소다라이브\n\n
|
||||
- 대표자 : 이재형\n\n
|
||||
- 주소 : 경기도 성남시 분당구 황새울로335번길 10, 5층 563A호\n\n
|
||||
- 사업자등록번호 : 870-81-03220\n\n
|
||||
- 통신판매업신고 : 제2024-성남분당B-1012호\n\n
|
||||
- 고객센터 : 02.2055.1477(이용시간 10:00~19:00)\n\n
|
||||
- 대표 이메일 : sodalive.official@gmail.com"
|
||||
android:textColor="@color/color_777777"
|
||||
android:textSize="11sp" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
|
|
@ -85,11 +85,10 @@
|
|||
android:textSize="13.3sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_keep_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_light"
|
||||
android:text="(이용기간 1년)"
|
||||
android:text="(서비스 종료시까지)"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
|
|
@ -159,7 +159,6 @@
|
|||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/ll_can"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="26.7dp"
|
||||
|
@ -220,43 +219,6 @@
|
|||
app:drawableStartCompat="@drawable/ic_coin_w" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_alarm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:background="@drawable/bg_round_corner_6_7_13181b"
|
||||
android:paddingHorizontal="13.3dp"
|
||||
android:paddingVertical="20dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_alarm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="5.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text="소다로 살다 (알람 등록)"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@+id/tv_alarm"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_alarm_clock" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_forward" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_coupon"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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"
|
||||
android:background="@color/color_222222">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:paddingHorizontal="26.7dp"
|
||||
android:paddingTop="26.7dp"
|
||||
android:text="음성녹음"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18.3sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:paddingHorizontal="26.7dp"
|
||||
android:paddingTop="26.7dp"
|
||||
android:src="@drawable/ic_close_white"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="81dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/iv_close">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_timer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="00:00.00"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="33.3sp" />
|
||||
|
||||
<com.gauravk.audiovisualizer.visualizer.WaveVisualizer
|
||||
android:id="@+id/sound_visualizer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:visibility="gone"
|
||||
app:avColor="@color/av_deep_orange"
|
||||
app:avDensity="0.8"
|
||||
app:avSpeed="normal"
|
||||
app:avType="fill" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_record_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="52.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_record" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_record_stop"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="52.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_record_stop"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_record_play"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_record_play"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginTop="90dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_record_play" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_record_pause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginTop="90dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_record_pause"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_delete"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="60dp"
|
||||
android:layout_toEndOf="@+id/iv_record_play"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:text="삭제"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="15.3sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_retry_or_complete"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="26.7dp"
|
||||
android:layout_marginBottom="13.3dp"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_retry_record"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_round_corner_10_13181b_3bb9f1"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text="다시 녹음"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_complete"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginStart="13.3dp"
|
||||
android:layout_weight="2"
|
||||
android:background="@drawable/bg_round_corner_10_3bb9f1"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text="녹음 완료"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18.3sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -196,7 +196,7 @@
|
|||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:text="다시 녹음"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
android:textColor="@color/color_9970ff"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/black"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_909090"
|
||||
android:textSize="12sp"
|
||||
tools:text="모닝콜" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="13.3dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_ampm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_d2d2d2"
|
||||
android:textSize="14sp"
|
||||
tools:text="오전" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="33.3sp"
|
||||
tools:text="10:00" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_days"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_toStartOf="@+id/iv_enable"
|
||||
android:layout_toEndOf="@+id/ll_time"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="end"
|
||||
android:text="월, 수, 금"
|
||||
android:textColor="@color/color_909090"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_enable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/btn_toggle_on_big" />
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="13.3dp"
|
||||
android:background="@drawable/bg_round_corner_5_3_222222"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="13.3dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_creator_nickname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_909090"
|
||||
android:textSize="12sp"
|
||||
tools:text="설린" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_content_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16.7dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="14.7sp"
|
||||
tools:text="[야함끝판왕/리얼플🔞] 강제로 절정까지 가버리는 연상녀💦" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/color_555555" />
|
||||
</LinearLayout>
|
|
@ -168,56 +168,6 @@
|
|||
app:layout_constraintTop_toTopOf="@+id/iv_cover"
|
||||
tools:text="300" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_owned"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_2_6_b1ef2c"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:paddingHorizontal="5.3dp"
|
||||
android:paddingVertical="2.7dp"
|
||||
android:text="소장중"
|
||||
android:textColor="@color/color_111111"
|
||||
android:textSize="13.3sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/iv_cover"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/iv_cover"
|
||||
tools:ignore="RelativeOverlap" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_rented"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_2_6_660fd4"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:paddingHorizontal="5.3dp"
|
||||
android:paddingVertical="2.7dp"
|
||||
android:text="대여중"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13.3sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/iv_cover"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/iv_cover"
|
||||
tools:ignore="RelativeOverlap" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_sold_out"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_2_6_transparent_d2d2d2"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:paddingHorizontal="5.3dp"
|
||||
android:paddingVertical="3.3dp"
|
||||
android:text="Sold Out"
|
||||
android:textColor="@color/color_d2d2d2"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/iv_cover"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/iv_cover" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
android:layout_width="53.3dp"
|
||||
android:layout_height="53.3dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@null" />
|
||||
</RelativeLayout>
|
||||
|
||||
|
|
|
@ -57,8 +57,7 @@
|
|||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="8.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_seemore_vertical"
|
||||
android:visibility="gone" />
|
||||
android:src="@drawable/ic_seemore_vertical" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
|
@ -72,33 +71,16 @@
|
|||
android:maxLines="3"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="13.3sp"
|
||||
android:visibility="gone"
|
||||
tools:text="너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!너무 조하유 앞으로도 좋은 라이브 많이 들려주세요!" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="13.3dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_play_or_pause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/btn_audio_content_play"
|
||||
android:visibility="visible" />
|
||||
</RelativeLayout>
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_like"
|
||||
|
@ -110,7 +92,6 @@
|
|||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="13.3dp"
|
||||
android:paddingVertical="5.3dp"
|
||||
android:visibility="gone"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<ImageView
|
||||
|
@ -228,34 +209,4 @@
|
|||
tools:text="너무 좋아요!!! 너무 좋아요!!! 너무 좋아요!!! 너무 좋아요!!! 너무 좋아요!!! 너무 좋아요!!!" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_lock_post"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="318dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:background="@drawable/bg_round_corner_5_3_333333"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_lock_bb" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_purchase"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="26.7dp"
|
||||
android:background="@drawable/bg_round_corner_26_7_transparent_3bb9f1"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:paddingHorizontal="21dp"
|
||||
android:paddingVertical="11dp"
|
||||
android:textColor="@color/color_3bb9f1"
|
||||
tools:text="5캔으로 게시물 보기" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 25 KiB |