Compare commits
156 Commits
78c9b24bb9
...
d13769861d
| Author | SHA1 | Date | |
|---|---|---|---|
| d13769861d | |||
| 5d15f74575 | |||
| 5f445872c8 | |||
| d44853055a | |||
| 4ddee2b1c1 | |||
| 6031638260 | |||
| 39f647d05a | |||
| a1b464e864 | |||
| d657e8827a | |||
| 6cb89ef09f | |||
| 00941d8082 | |||
| cf612fa0c7 | |||
| 6d5018c3fd | |||
| f333d301b8 | |||
| 11c5d57c4e | |||
| f269044c69 | |||
| b1075eee16 | |||
| 5adfecf689 | |||
| f44eacaf52 | |||
| 258f0036a6 | |||
| 4d33d459ee | |||
| 1cdbd92d35 | |||
| 871603f1bb | |||
| 032640b068 | |||
| 2e7c3a5352 | |||
| c78370ec2a | |||
| 6813a74c13 | |||
| 3980673322 | |||
| 0b99235ec2 | |||
| 906881dc9c | |||
| d5b6a3f2d6 | |||
| 4b4e47d17c | |||
| 6e2fcc53a5 | |||
| dfaa3961bf | |||
| 1d002c4045 | |||
| 4e80d91c20 | |||
| 2525811db4 | |||
| 5583004515 | |||
| a4a11b5801 | |||
| 9adc45095b | |||
| c66fdf63db | |||
| 23a98b399c | |||
| 0ddf416b9d | |||
| f0a2e2c46f | |||
| 3bd8061a93 | |||
| b67a3fd0b4 | |||
| e9df2bfa03 | |||
| a75a11c9f6 | |||
| ebd557ff71 | |||
| 0854b76dfa | |||
| 2e7b1ac09e | |||
| 4e15557949 | |||
| e2c7134f61 | |||
| 6f67c4e8e1 | |||
| d8d6509668 | |||
| c9a1417d60 | |||
| 6cb8616c00 | |||
| 26ad8c39dc | |||
| f2f406d581 | |||
| b4ced77d57 | |||
| 5ee57b1b2f | |||
| 57e3edc24e | |||
| fc984cef22 | |||
| 81b6cbe655 | |||
| e838085291 | |||
| 0f6ebbfa76 | |||
| ae081994c3 | |||
| e67251c9ba | |||
| 270d697ce6 | |||
| a050a56c19 | |||
| ab7f837bb4 | |||
| f2e682c3d3 | |||
| 237d112dec | |||
| f8769e97f9 | |||
| 5ef7896f1d | |||
| 4a5627bf36 | |||
| b521b79fe4 | |||
| 35f95aa0f2 | |||
| de042abd79 | |||
| ad1c58bbf5 | |||
| 764ca0f892 | |||
| 1018b6426e | |||
| c74503beca | |||
| 7988b8c63e | |||
| 6ef19d53f4 | |||
| dc00fd0277 | |||
| 96d14356be | |||
| a3fb090593 | |||
| 5a4b833516 | |||
| 82b09f2c63 | |||
| fd6a025de9 | |||
| 99bc5f14f7 | |||
| ddc7b9a76f | |||
| af03d4dafd | |||
| 09bc25f035 | |||
| 072b206035 | |||
| af04ff9bf7 | |||
| 6bd63fc751 | |||
| 4ed6437ce3 | |||
| b356591aba | |||
| 00db1d7bfd | |||
| cc517eb4d3 | |||
| 4a8442cb33 | |||
| 7023324920 | |||
| 3cfab2c57b | |||
| 4caaeff0f0 | |||
| 98a6fb6637 | |||
| 50edf85de5 | |||
| 19b74b2671 | |||
| 7b6d2cd782 | |||
| b457cf0b4d | |||
| 7f27f461f3 | |||
| 3909920a4c | |||
| 5ff35b1da4 | |||
| 90c71026da | |||
| 707107328a | |||
| 958244c9b2 | |||
| adc2f759c4 | |||
| c3c1a83e97 | |||
| 61fa6d5f74 | |||
| 9782462345 | |||
| 480b47ee3d | |||
| 2e528f8c7d | |||
| 7e4202db1b | |||
| 09a8019c66 | |||
| e44bd68152 | |||
| 2066dbc716 | |||
| 73b2eba1f8 | |||
| 101c396ac2 | |||
| 3cf24c2ab6 | |||
| 4e0e6708e6 | |||
| ebe5c342c9 | |||
| 37c1bc06d0 | |||
| 98209d0d5f | |||
| 159a5ae8b3 | |||
| e9afa55aa0 | |||
| e727658b24 | |||
| eb0aa9473f | |||
| 981859de1f | |||
| 1889c6ae10 | |||
| 7e74bd1e4d | |||
| 4d1e859bbf | |||
| 492077ddb2 | |||
| bca527eca0 | |||
| 707dc351ba | |||
| cc55a19e1d | |||
| 8b215e553d | |||
| af1679c92b | |||
| 41c11d763e | |||
| 1efd968b09 | |||
| ede2dc201c | |||
| 2740522f05 | |||
| 6e3edd1e96 | |||
| 0326fa89ea | |||
| dcdf3b21bc | |||
| 748da3ec0c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -60,6 +60,7 @@ captures/
|
|||||||
|
|
||||||
.idea/AndroidProjectSystem.xml
|
.idea/AndroidProjectSystem.xml
|
||||||
.idea/runConfigurations.xml
|
.idea/runConfigurations.xml
|
||||||
|
.idea/deploymentTargetSelector.xml
|
||||||
|
|
||||||
# Keystore files
|
# Keystore files
|
||||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
|
|||||||
18
.idea/deploymentTargetSelector.xml
generated
18
.idea/deploymentTargetSelector.xml
generated
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="deploymentTargetSelector">
|
|
||||||
<selectionStates>
|
|
||||||
<SelectionState runConfigName="app">
|
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
|
||||||
<DropdownSelection timestamp="2025-10-23T14:41:22.468459Z">
|
|
||||||
<Target type="DEFAULT_BOOT">
|
|
||||||
<handle>
|
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=ce0917195d15ab39017e" />
|
|
||||||
</handle>
|
|
||||||
</Target>
|
|
||||||
</DropdownSelection>
|
|
||||||
<DialogSelection />
|
|
||||||
</SelectionState>
|
|
||||||
</selectionStates>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
8
.idea/markdown.xml
generated
Normal file
8
.idea/markdown.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MarkdownSettings">
|
||||||
|
<option name="previewPanelProviderInfo">
|
||||||
|
<ProviderInfo name="Compose (experimental)" className="com.intellij.markdown.compose.preview.ComposePanelProvider" />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
18
AGENTS.md
Normal file
18
AGENTS.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
질문에 대한 답변과 설명은 한국어로 한다.
|
||||||
|
|
||||||
|
## Quality Assurance Guidelines
|
||||||
|
|
||||||
|
### Commit Standards
|
||||||
|
1. Write in Korean.
|
||||||
|
2. Use the present tense in the subject line (e.g., "Add feature" not "Added feature").
|
||||||
|
3. Keep the subject line to 50 characters or less.
|
||||||
|
4. Add a blank line between the subject and body.
|
||||||
|
5. Keep the body to 72 characters or less per line.
|
||||||
|
6. Within a paragraph, only break lines when the text exceeds 72 characters.
|
||||||
|
7. Describe changes to public API features and do not include implementation details such as package-private code.
|
||||||
|
8. Do not mention test code in commit messages.
|
||||||
|
9. Do not use any prefix (such as "fix:", "update:", "docs:", "feat:", etc.) in the subject line.
|
||||||
|
10. Do not start the subject line with a lowercase letter unless the first word is a function name or another identifier that is conventionally lowercase and there is a clear, justifiable reason for the exception. Otherwise, always start with an uppercase letter.
|
||||||
|
11. Do not include tool advertisements, branding, or promotional content in commit messages.
|
||||||
|
12. Use separate git commands to stage files before committing.
|
||||||
|
13. Always validate commits using `work/scripts/check-commit-message-rules.sh` and fix until validation passes.
|
||||||
@@ -63,8 +63,8 @@ android {
|
|||||||
applicationId "kr.co.vividnext.sodalive"
|
applicationId "kr.co.vividnext.sodalive"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 35
|
targetSdk 35
|
||||||
versionCode 204
|
versionCode 218
|
||||||
versionName "1.44.0"
|
versionName "1.48.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -83,6 +83,7 @@ android {
|
|||||||
buildConfigField 'String', 'KAKAO_APP_KEY', '"231cf78acfa8252fca38b9eedf87c5cb"'
|
buildConfigField 'String', 'KAKAO_APP_KEY', '"231cf78acfa8252fca38b9eedf87c5cb"'
|
||||||
buildConfigField 'String', 'GOOGLE_CLIENT_ID', '"983594297130-5hrmkh6vpskeq6v34350kmilf74574h2.apps.googleusercontent.com"'
|
buildConfigField 'String', 'GOOGLE_CLIENT_ID', '"983594297130-5hrmkh6vpskeq6v34350kmilf74574h2.apps.googleusercontent.com"'
|
||||||
buildConfigField 'String', 'APPSCHEME', '"voiceon"'
|
buildConfigField 'String', 'APPSCHEME', '"voiceon"'
|
||||||
|
buildConfigField 'String', 'LINE_CHANNEL_ID', '"2008995539"'
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
URISCHEME : "voiceon",
|
URISCHEME : "voiceon",
|
||||||
APPLINK_HOST : "voiceon.onelink.me",
|
APPLINK_HOST : "voiceon.onelink.me",
|
||||||
@@ -109,6 +110,7 @@ android {
|
|||||||
buildConfigField 'String', 'KAKAO_APP_KEY', '"20cf19413d63bfdfd30e8e6dff933d33"'
|
buildConfigField 'String', 'KAKAO_APP_KEY', '"20cf19413d63bfdfd30e8e6dff933d33"'
|
||||||
buildConfigField 'String', 'GOOGLE_CLIENT_ID', '"758414412471-mosodbj2chno7l1j0iihldh6edmk0gk9.apps.googleusercontent.com"'
|
buildConfigField 'String', 'GOOGLE_CLIENT_ID', '"758414412471-mosodbj2chno7l1j0iihldh6edmk0gk9.apps.googleusercontent.com"'
|
||||||
buildConfigField 'String', 'APPSCHEME', '"voiceon-test"'
|
buildConfigField 'String', 'APPSCHEME', '"voiceon-test"'
|
||||||
|
buildConfigField 'String', 'LINE_CHANNEL_ID', '"2008995582"'
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
URISCHEME : "voiceon-test",
|
URISCHEME : "voiceon-test",
|
||||||
APPLINK_HOST : "voiceon-test.onelink.me",
|
APPLINK_HOST : "voiceon-test.onelink.me",
|
||||||
@@ -234,6 +236,11 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'com.github.orbitalsonic:Sonic-Water-Wave-Animation:2.0.1'
|
implementation 'com.github.orbitalsonic:Sonic-Water-Wave-Animation:2.0.1'
|
||||||
|
|
||||||
|
// Line
|
||||||
|
implementation("com.linecorp.linesdk:linesdk:5.6.1") {
|
||||||
|
exclude group: "org.jetbrains.kotlin", module: "kotlin-android-extensions-runtime"
|
||||||
|
}
|
||||||
|
|
||||||
// ----- Test dependencies -----
|
// ----- Test dependencies -----
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
testImplementation 'org.mockito:mockito-core:5.20.0'
|
testImplementation 'org.mockito:mockito-core:5.20.0'
|
||||||
|
|||||||
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
@@ -243,3 +243,5 @@
|
|||||||
-dontwarn com.yalantis.ucrop**
|
-dontwarn com.yalantis.ucrop**
|
||||||
-keep class com.yalantis.ucrop** { *; }
|
-keep class com.yalantis.ucrop** { *; }
|
||||||
-keep interface com.yalantis.ucrop** { *; }
|
-keep interface com.yalantis.ucrop** { *; }
|
||||||
|
|
||||||
|
-dontwarn com.linecorp.linesdk.BR
|
||||||
|
|||||||
4
app/src/debug/res/values-en/strings.xml
Normal file
4
app/src/debug/res/values-en/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">VoiceOn-Test</string>
|
||||||
|
</resources>
|
||||||
4
app/src/debug/res/values-ja/strings.xml
Normal file
4
app/src/debug/res/values-ja/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">ボイスオン-テスト</string>
|
||||||
|
</resources>
|
||||||
4
app/src/debug/res/values/strings.xml
Normal file
4
app/src/debug/res/values/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">보이스온-테스트</string>
|
||||||
|
</resources>
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.SodaLive"
|
android:theme="@style/Theme.SodaLive"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
|
tools:replace="android:allowBackup"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".main.DeepLinkActivity"
|
android:name=".main.DeepLinkActivity"
|
||||||
@@ -109,6 +110,7 @@
|
|||||||
<activity android:name=".main.MainActivity" />
|
<activity android:name=".main.MainActivity" />
|
||||||
<activity android:name=".user.login.LoginActivity" />
|
<activity android:name=".user.login.LoginActivity" />
|
||||||
<activity android:name=".audio_content.all.AudioContentAllActivity" />
|
<activity android:name=".audio_content.all.AudioContentAllActivity" />
|
||||||
|
<activity android:name=".settings.language.LanguageSettingsActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".user.signup.SignUpActivity"
|
android:name=".user.signup.SignUpActivity"
|
||||||
android:windowSoftInputMode="stateVisible" />
|
android:windowSoftInputMode="stateVisible" />
|
||||||
@@ -160,7 +162,6 @@
|
|||||||
<activity android:name=".live.reservation.all.LiveReservationAllActivity" />
|
<activity android:name=".live.reservation.all.LiveReservationAllActivity" />
|
||||||
<activity android:name=".mypage.service_center.ServiceCenterActivity" />
|
<activity android:name=".mypage.service_center.ServiceCenterActivity" />
|
||||||
<activity android:name=".message.MessageActivity" />
|
<activity android:name=".message.MessageActivity" />
|
||||||
<activity android:name=".onboarding.OnBoardingActivity" />
|
|
||||||
<activity android:name=".mypage.profile.ProfileUpdateActivity" />
|
<activity android:name=".mypage.profile.ProfileUpdateActivity" />
|
||||||
<activity android:name=".mypage.profile.nickname.NicknameUpdateActivity" />
|
<activity android:name=".mypage.profile.nickname.NicknameUpdateActivity" />
|
||||||
<activity android:name=".mypage.profile.password.ModifyPasswordActivity" />
|
<activity android:name=".mypage.profile.password.ModifyPasswordActivity" />
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ import com.kakao.sdk.common.KakaoSdk
|
|||||||
import com.orhanobut.logger.AndroidLogAdapter
|
import com.orhanobut.logger.AndroidLogAdapter
|
||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import kr.co.vividnext.sodalive.BuildConfig
|
import kr.co.vividnext.sodalive.BuildConfig
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.common.ImageLoaderProvider
|
import kr.co.vividnext.sodalive.common.ImageLoaderProvider
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.di.AppDI
|
import kr.co.vividnext.sodalive.di.AppDI
|
||||||
import kr.co.vividnext.sodalive.tracking.FirebaseTracking
|
import kr.co.vividnext.sodalive.tracking.FirebaseTracking
|
||||||
import tech.notifly.Notifly
|
import tech.notifly.Notifly
|
||||||
@@ -36,6 +38,7 @@ class SodaLiveApp : Application(), DefaultLifecycleObserver {
|
|||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||||
|
|
||||||
|
SodaLiveApplicationHolder.init(this)
|
||||||
SharedPreferenceManager.init(applicationContext)
|
SharedPreferenceManager.init(applicationContext)
|
||||||
|
|
||||||
ImageLoaderProvider.init(applicationContext)
|
ImageLoaderProvider.init(applicationContext)
|
||||||
@@ -108,8 +111,13 @@ class SodaLiveApp : Application(), DefaultLifecycleObserver {
|
|||||||
logUtmInFirebase()
|
logUtmInFirebase()
|
||||||
}
|
}
|
||||||
|
|
||||||
DeepLinkResult.Status.NOT_FOUND -> Logger.d("딥링크를 찾을 수 없습니다.")
|
DeepLinkResult.Status.NOT_FOUND -> Logger.d(
|
||||||
DeepLinkResult.Status.ERROR -> Logger.d("딥링크 처리 중 오류 발생: ${deepLinkResult.error}")
|
getString(R.string.deeplink_not_found)
|
||||||
|
)
|
||||||
|
|
||||||
|
DeepLinkResult.Status.ERROR -> Logger.d(
|
||||||
|
getString(R.string.deeplink_error, deepLinkResult.error)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class AudioContentActivity : BaseActivity<ActivityAudioContentBinding>(
|
|||||||
|
|
||||||
private var userId: Long = 0
|
private var userId: Long = 0
|
||||||
private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
|
private lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
|
||||||
|
private val allCategoryLabel by lazy { getString(R.string.audio_content_label_all) }
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
userId = intent.getLongExtra(Constants.EXTRA_USER_ID, 0)
|
userId = intent.getLongExtra(Constants.EXTRA_USER_ID, 0)
|
||||||
@@ -53,7 +54,11 @@ class AudioContentActivity : BaseActivity<ActivityAudioContentBinding>(
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
if (userId <= 0) {
|
if (userId <= 0) {
|
||||||
Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
getString(R.string.screen_audio_content_error_invalid_request),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +69,7 @@ class AudioContentActivity : BaseActivity<ActivityAudioContentBinding>(
|
|||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
binding.toolbar.tvBack.text = "콘텐츠 전체보기"
|
binding.toolbar.tvBack.text = getString(R.string.screen_audio_content_title)
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
audioContentAdapter = AudioContentAdapter {
|
audioContentAdapter = AudioContentAdapter {
|
||||||
@@ -75,7 +80,9 @@ class AudioContentActivity : BaseActivity<ActivityAudioContentBinding>(
|
|||||||
activityResultLauncher.launch(intent)
|
activityResultLauncher.launch(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
categoryAdapter = AudioContentCategoryAdapter {
|
categoryAdapter = AudioContentCategoryAdapter(
|
||||||
|
allCategoryLabel = allCategoryLabel
|
||||||
|
) {
|
||||||
viewModel.selectCategory(it, userId = userId)
|
viewModel.selectCategory(it, userId = userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +266,7 @@ class AudioContentActivity : BaseActivity<ActivityAudioContentBinding>(
|
|||||||
if (it.isNotEmpty()) {
|
if (it.isNotEmpty()) {
|
||||||
binding.rvCategory.visibility = View.VISIBLE
|
binding.rvCategory.visibility = View.VISIBLE
|
||||||
val items = it as MutableList<GetCategoryListResponse>
|
val items = it as MutableList<GetCategoryListResponse>
|
||||||
items.add(0, GetCategoryListResponse(0, "전체"))
|
items.add(0, GetCategoryListResponse(0, allCategoryLabel))
|
||||||
categoryAdapter.addItems(items = items)
|
categoryAdapter.addItems(items = items)
|
||||||
} else {
|
} else {
|
||||||
binding.rvCategory.visibility = View.GONE
|
binding.rvCategory.visibility = View.GONE
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ class AudioContentAdapter(
|
|||||||
} else {
|
} else {
|
||||||
binding.tvPrice.visibility = View.VISIBLE
|
binding.tvPrice.visibility = View.VISIBLE
|
||||||
if (item.price < 1) {
|
if (item.price < 1) {
|
||||||
binding.tvPrice.text = "무료"
|
binding.tvPrice.text =
|
||||||
|
binding.root.context.getString(R.string.audio_content_price_free)
|
||||||
binding.tvPrice.setCompoundDrawables(null, null, null, null)
|
binding.tvPrice.setCompoundDrawables(null, null, null, null)
|
||||||
} else {
|
} else {
|
||||||
binding.tvPrice.text = item.price.moneyFormat()
|
binding.tvPrice.text = item.price.moneyFormat()
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content
|
package kr.co.vividnext.sodalive.audio_content
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.category.CategoryApi
|
import kr.co.vividnext.sodalive.audio_content.category.CategoryApi
|
||||||
import kr.co.vividnext.sodalive.audio_content.detail.PutAudioContentLikeRequest
|
import kr.co.vividnext.sodalive.audio_content.detail.PutAudioContentLikeRequest
|
||||||
import kr.co.vividnext.sodalive.audio_content.donation.AudioContentDonationRequest
|
import kr.co.vividnext.sodalive.audio_content.donation.AudioContentDonationRequest
|
||||||
import kr.co.vividnext.sodalive.audio_content.order.OrderRequest
|
import kr.co.vividnext.sodalive.audio_content.order.OrderRequest
|
||||||
import kr.co.vividnext.sodalive.audio_content.order.OrderType
|
import kr.co.vividnext.sodalive.audio_content.order.OrderType
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.settings.ContentType
|
import kr.co.vividnext.sodalive.settings.ContentType
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
@@ -70,7 +72,10 @@ class AudioContentRepository(
|
|||||||
authHeader = token
|
authHeader = token
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getAudioContentDetail(audioContentId: Long, token: String) = api.getAudioContentDetail(
|
fun getAudioContentDetail(
|
||||||
|
audioContentId: Long,
|
||||||
|
token: String
|
||||||
|
) = api.getAudioContentDetail(
|
||||||
id = audioContentId,
|
id = audioContentId,
|
||||||
timezone = TimeZone.getDefault().id,
|
timezone = TimeZone.getDefault().id,
|
||||||
authHeader = token
|
authHeader = token
|
||||||
@@ -150,7 +155,8 @@ class AudioContentRepository(
|
|||||||
fun getContentRanking(
|
fun getContentRanking(
|
||||||
page: Int,
|
page: Int,
|
||||||
size: Int,
|
size: Int,
|
||||||
sortType: String = "매출",
|
sortType: String = SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.screen_home_sort_revenue),
|
||||||
token: String
|
token: String
|
||||||
) = api.getContentRanking(
|
) = api.getContentRanking(
|
||||||
page = page - 1,
|
page = page - 1,
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import com.google.gson.annotations.SerializedName
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.category.GetCategoryListResponse
|
import kr.co.vividnext.sodalive.audio_content.category.GetCategoryListResponse
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.GetAudioContentListResponse
|
import kr.co.vividnext.sodalive.explorer.profile.GetAudioContentListResponse
|
||||||
|
|
||||||
class AudioContentViewModel(private val repository: AudioContentRepository) : BaseViewModel() {
|
class AudioContentViewModel(private val repository: AudioContentRepository) : BaseViewModel() {
|
||||||
@@ -80,7 +82,8 @@ class AudioContentViewModel(private val repository: AudioContentRepository) : Ba
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +97,10 @@ class AudioContentViewModel(private val repository: AudioContentRepository) : Ba
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
|
)
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
@@ -134,7 +140,8 @@ class AudioContentViewModel(private val repository: AudioContentRepository) : Ba
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +151,10 @@ class AudioContentViewModel(private val repository: AudioContentRepository) : Ba
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class AudioContentAllActivity : BaseActivity<ActivityAudioContentAllBinding>(
|
|||||||
|
|
||||||
private var isFree: Boolean = false
|
private var isFree: Boolean = false
|
||||||
private var isPointOnly: Boolean = false
|
private var isPointOnly: Boolean = false
|
||||||
|
private val allThemeLabel by lazy { getString(R.string.screen_home_theme_all) }
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
isFree = intent.getBooleanExtra(Constants.EXTRA_AUDIO_CONTENT_FREE, false)
|
isFree = intent.getBooleanExtra(Constants.EXTRA_AUDIO_CONTENT_FREE, false)
|
||||||
@@ -56,9 +57,9 @@ class AudioContentAllActivity : BaseActivity<ActivityAudioContentAllBinding>(
|
|||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
binding.toolbar.tvBack.text = when {
|
binding.toolbar.tvBack.text = when {
|
||||||
isPointOnly -> "포인트 대여 전체"
|
isPointOnly -> getString(R.string.screen_audio_content_all_title_point_only)
|
||||||
isFree -> "무료 콘텐츠 전체"
|
isFree -> getString(R.string.screen_audio_content_all_title_free)
|
||||||
else -> "콘텐츠 전체보기"
|
else -> getString(R.string.screen_audio_content_title)
|
||||||
}
|
}
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
@@ -75,9 +76,10 @@ class AudioContentAllActivity : BaseActivity<ActivityAudioContentAllBinding>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTheme() {
|
private fun setupTheme() {
|
||||||
themeAdapter = HomeContentThemeAdapter {
|
themeAdapter = HomeContentThemeAdapter(allThemeLabel) { selectedTheme ->
|
||||||
adapter.addItems(emptyList())
|
adapter.addItems(emptyList())
|
||||||
viewModel.selectTheme(it, isFree = isFree, isPointOnly = isPointOnly)
|
val theme = if (selectedTheme == allThemeLabel) "" else selectedTheme
|
||||||
|
viewModel.selectTheme(theme, isFree = isFree, isPointOnly = isPointOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.rvTheme.layoutManager = LinearLayoutManager(
|
binding.rvTheme.layoutManager = LinearLayoutManager(
|
||||||
@@ -169,7 +171,9 @@ class AudioContentAllActivity : BaseActivity<ActivityAudioContentAllBinding>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.themeListLiveData.observe(this) {
|
viewModel.themeListLiveData.observe(this) {
|
||||||
themeAdapter.addItems(it)
|
val themes = mutableListOf(allThemeLabel)
|
||||||
|
themes.addAll(it)
|
||||||
|
themeAdapter.addItems(themes)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.itemsLiveData.observe(this) { list ->
|
viewModel.itemsLiveData.observe(this) { list ->
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentViewModel
|
import kr.co.vividnext.sodalive.audio_content.AudioContentViewModel
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.home.AudioContentMainItem
|
import kr.co.vividnext.sodalive.home.AudioContentMainItem
|
||||||
|
|
||||||
class AudioContentAllViewModel(
|
class AudioContentAllViewModel(
|
||||||
@@ -35,7 +37,7 @@ class AudioContentAllViewModel(
|
|||||||
private var page = 1
|
private var page = 1
|
||||||
private val size = 20
|
private val size = 20
|
||||||
private var isLast = false
|
private var isLast = false
|
||||||
private var selectedTheme = "전체"
|
private var selectedTheme = ""
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
page = 1
|
page = 1
|
||||||
@@ -46,6 +48,7 @@ class AudioContentAllViewModel(
|
|||||||
isFree: Boolean? = null,
|
isFree: Boolean? = null,
|
||||||
isPointAvailableOnly: Boolean? = null
|
isPointAvailableOnly: Boolean? = null
|
||||||
) {
|
) {
|
||||||
|
val unknownError = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.getAudioContentActiveThemeList(
|
repository.getAudioContentActiveThemeList(
|
||||||
isFree = isFree,
|
isFree = isFree,
|
||||||
@@ -57,15 +60,12 @@ class AudioContentAllViewModel(
|
|||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
if (it.success && it.data != null) {
|
if (it.success && it.data != null) {
|
||||||
val themeList = listOf("전체").union(it.data).toList()
|
_themeListLiveData.postValue(it.data)
|
||||||
_themeListLiveData.postValue(themeList)
|
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownError)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class AudioContentAllViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownError)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -86,6 +86,7 @@ class AudioContentAllViewModel(
|
|||||||
) {
|
) {
|
||||||
if (_isLoading.value == true || isLast) return
|
if (_isLoading.value == true || isLast) return
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
|
val unknownError = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.getAllAudioContents(
|
repository.getAllAudioContents(
|
||||||
@@ -94,11 +95,7 @@ class AudioContentAllViewModel(
|
|||||||
isFree = isFree,
|
isFree = isFree,
|
||||||
isPointAvailableOnly = isPointAvailableOnly,
|
isPointAvailableOnly = isPointAvailableOnly,
|
||||||
sortType = _sortLiveData.value!!,
|
sortType = _sortLiveData.value!!,
|
||||||
theme = if (selectedTheme == "전체") {
|
theme = selectedTheme.ifBlank { null },
|
||||||
null
|
|
||||||
} else {
|
|
||||||
selectedTheme
|
|
||||||
},
|
|
||||||
token = "Bearer ${SharedPreferenceManager.token}"
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
)
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
@@ -115,7 +112,7 @@ class AudioContentAllViewModel(
|
|||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
}, { t ->
|
}, { t ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
_toastLiveData.postValue(t.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(t.message ?: unknownError)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import androidx.media3.common.util.UnstableApi
|
|||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
@@ -32,6 +33,7 @@ class AudioContentNewAllActivity : BaseActivity<ActivityAudioContentNewAllBindin
|
|||||||
|
|
||||||
private lateinit var newContentThemeAdapter: HomeContentThemeAdapter
|
private lateinit var newContentThemeAdapter: HomeContentThemeAdapter
|
||||||
private lateinit var newContentAdapter: AudioContentNewAllAdapter
|
private lateinit var newContentAdapter: AudioContentNewAllAdapter
|
||||||
|
private val allThemeLabel by lazy { getString(R.string.screen_home_theme_all) }
|
||||||
|
|
||||||
private var isFree: Boolean = false
|
private var isFree: Boolean = false
|
||||||
|
|
||||||
@@ -47,16 +49,16 @@ class AudioContentNewAllActivity : BaseActivity<ActivityAudioContentNewAllBindin
|
|||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
binding.toolbar.tvBack.text = if (isFree) {
|
binding.toolbar.tvBack.text = if (isFree) {
|
||||||
"새로운 무료 콘텐츠"
|
getString(R.string.screen_audio_content_new_all_title_free)
|
||||||
} else {
|
} else {
|
||||||
"새로운 단편"
|
getString(R.string.screen_audio_content_new_all_title)
|
||||||
}
|
}
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
binding.tvNotice.text = if (isFree) {
|
binding.tvNotice.text = if (isFree) {
|
||||||
"※ 최근 2주간 등록된 새로운 콘텐츠 입니다."
|
getString(R.string.screen_audio_content_new_all_notice_free)
|
||||||
} else {
|
} else {
|
||||||
"※ 최근 2주간 등록된 새로운 단편 입니다."
|
getString(R.string.screen_audio_content_new_all_notice)
|
||||||
}
|
}
|
||||||
|
|
||||||
setupNewContentTheme()
|
setupNewContentTheme()
|
||||||
@@ -65,10 +67,11 @@ class AudioContentNewAllActivity : BaseActivity<ActivityAudioContentNewAllBindin
|
|||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun setupNewContentTheme() {
|
private fun setupNewContentTheme() {
|
||||||
newContentThemeAdapter = HomeContentThemeAdapter {
|
newContentThemeAdapter = HomeContentThemeAdapter(allThemeLabel) { selectedTheme ->
|
||||||
newContentAdapter.clear()
|
newContentAdapter.clear()
|
||||||
newContentAdapter.notifyDataSetChanged()
|
newContentAdapter.notifyDataSetChanged()
|
||||||
viewModel.selectTheme(it, isFree = isFree)
|
val theme = if (selectedTheme == allThemeLabel) "" else selectedTheme
|
||||||
|
viewModel.selectTheme(theme, isFree = isFree)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.rvNewContentTheme.layoutManager = LinearLayoutManager(
|
binding.rvNewContentTheme.layoutManager = LinearLayoutManager(
|
||||||
@@ -171,7 +174,9 @@ class AudioContentNewAllActivity : BaseActivity<ActivityAudioContentNewAllBindin
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.themeListLiveData.observe(this) {
|
viewModel.themeListLiveData.observe(this) {
|
||||||
newContentThemeAdapter.addItems(it)
|
val themes = mutableListOf(allThemeLabel)
|
||||||
|
themes.addAll(it)
|
||||||
|
newContentThemeAdapter.addItems(themes)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.newContentListLiveData.observe(this) {
|
viewModel.newContentListLiveData.observe(this) {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class AudioContentNewAllAdapter(
|
|||||||
binding.tvCan.text = item.price.moneyFormat()
|
binding.tvCan.text = item.price.moneyFormat()
|
||||||
} else {
|
} else {
|
||||||
binding.ivCan.visibility = View.GONE
|
binding.ivCan.visibility = View.GONE
|
||||||
binding.tvCan.text = "무료"
|
binding.tvCan.text = context.getString(R.string.audio_content_price_free)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.tvTime.text = item.duration
|
binding.tvTime.text = item.duration
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import io.reactivex.rxjava3.schedulers.Schedulers
|
|||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentMainItem
|
import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentMainItem
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AudioContentNewAllViewModel(
|
class AudioContentNewAllViewModel(
|
||||||
private val repository: AudioContentRepository
|
private val repository: AudioContentRepository
|
||||||
@@ -41,15 +43,12 @@ class AudioContentNewAllViewModel(
|
|||||||
fun getNewContentList(isFree: Boolean = false) {
|
fun getNewContentList(isFree: Boolean = false) {
|
||||||
if (!_isLoading.value!! && !isLast) {
|
if (!_isLoading.value!! && !isLast) {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
|
val unknownError = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.getNewContentAllOfTheme(
|
repository.getNewContentAllOfTheme(
|
||||||
isFree = isFree,
|
isFree = isFree,
|
||||||
theme = if (selectedTheme == "전체") {
|
theme = selectedTheme,
|
||||||
""
|
|
||||||
} else {
|
|
||||||
selectedTheme
|
|
||||||
},
|
|
||||||
page = page,
|
page = page,
|
||||||
size = size,
|
size = size,
|
||||||
token = "Bearer ${SharedPreferenceManager.token}"
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
@@ -71,9 +70,7 @@ class AudioContentNewAllViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownError)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +79,7 @@ class AudioContentNewAllViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownError)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -90,6 +87,7 @@ class AudioContentNewAllViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getThemeList() {
|
fun getThemeList() {
|
||||||
|
val unknownError = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.getNewContentThemeList(token = "Bearer ${SharedPreferenceManager.token}")
|
repository.getNewContentThemeList(token = "Bearer ${SharedPreferenceManager.token}")
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
@@ -97,15 +95,12 @@ class AudioContentNewAllViewModel(
|
|||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
if (it.success && it.data != null) {
|
if (it.success && it.data != null) {
|
||||||
val themeList = listOf("전체").union(it.data).toList()
|
_themeListLiveData.postValue(it.data)
|
||||||
_themeListLiveData.postValue(themeList)
|
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownError)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +109,7 @@ class AudioContentNewAllViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownError)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.view.View
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
||||||
import kr.co.vividnext.sodalive.audio_content.main.new_content.AudioContentMainNewContentThemeAdapter
|
import kr.co.vividnext.sodalive.audio_content.main.new_content.AudioContentMainNewContentThemeAdapter
|
||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
@@ -37,7 +38,7 @@ class AudioContentRankingAllActivity : BaseActivity<ActivityAudioContentRankingA
|
|||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
binding.toolbar.tvBack.text = "인기 콘텐츠"
|
binding.toolbar.tvBack.text = getString(R.string.screen_audio_content_ranking_title)
|
||||||
|
|
||||||
adapter = AudioContentRankingAllAdapter {
|
adapter = AudioContentRankingAllAdapter {
|
||||||
val intent = Intent(applicationContext, AudioContentDetailActivity::class.java)
|
val intent = Intent(applicationContext, AudioContentDetailActivity::class.java)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class AudioContentRankingAllAdapter(
|
|||||||
binding.tvNickname.text = item.creatorNickname
|
binding.tvNickname.text = item.creatorNickname
|
||||||
|
|
||||||
if (item.price < 1) {
|
if (item.price < 1) {
|
||||||
binding.tvPrice.text = "무료"
|
binding.tvPrice.text = context.getString(R.string.audio_content_price_free)
|
||||||
binding.tvPrice.setTextColor(ContextCompat.getColor(context, R.color.white))
|
binding.tvPrice.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||||
binding.tvPrice.setCompoundDrawables(null, null, null, null)
|
binding.tvPrice.setCompoundDrawables(null, null, null, null)
|
||||||
binding.tvPrice.setPadding(
|
binding.tvPrice.setPadding(
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentRankingItem
|
import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentRankingItem
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
|
||||||
class AudioContentRankingAllViewModel(
|
class AudioContentRankingAllViewModel(
|
||||||
private val repository: AudioContentRepository
|
private val repository: AudioContentRepository
|
||||||
@@ -37,11 +39,14 @@ class AudioContentRankingAllViewModel(
|
|||||||
private var pageSize = 10
|
private var pageSize = 10
|
||||||
private var isLast = false
|
private var isLast = false
|
||||||
|
|
||||||
private var selectedSort = "매출"
|
private var selectedSort =
|
||||||
|
SodaLiveApplicationHolder.get().getString(R.string.screen_home_sort_revenue)
|
||||||
|
|
||||||
fun getAudioContentRanking() {
|
fun getAudioContentRanking() {
|
||||||
if (!_isLoading.value!! && !isLast && page <= 5) {
|
if (!_isLoading.value!! && !isLast && page <= 5) {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
|
val unknownError =
|
||||||
|
SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.getContentRanking(
|
repository.getContentRanking(
|
||||||
page = page,
|
page = page,
|
||||||
@@ -69,15 +74,13 @@ class AudioContentRankingAllViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownError)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownError)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -85,6 +88,7 @@ class AudioContentRankingAllViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getAudioContentRankingSortType() {
|
fun getAudioContentRankingSortType() {
|
||||||
|
val unknownError = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.getContentRankingSortType(token = "Bearer ${SharedPreferenceManager.token}")
|
repository.getContentRankingSortType(token = "Bearer ${SharedPreferenceManager.token}")
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
@@ -97,15 +101,13 @@ class AudioContentRankingAllViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownError)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownError)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class AudioContentAllByThemeActivity : BaseActivity<ActivityAudioContentAllByThe
|
|||||||
if (themeId <= 0) {
|
if (themeId <= 0) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
"잘못된 요청입니다.\n다시 시도해 주세요.",
|
getString(R.string.screen_audio_content_error_invalid_request_retry),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import io.reactivex.rxjava3.schedulers.Schedulers
|
|||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentViewModel
|
import kr.co.vividnext.sodalive.audio_content.AudioContentViewModel
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AudioContentAllByThemeViewModel(
|
class AudioContentAllByThemeViewModel(
|
||||||
private val repository: AudioContentRepository
|
private val repository: AudioContentRepository
|
||||||
@@ -61,7 +63,8 @@ class AudioContentAllByThemeViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +74,10 @@ class AudioContentAllByThemeViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content.box
|
package kr.co.vividnext.sodalive.audio_content.box
|
||||||
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import kr.co.vividnext.sodalive.R
|
import kr.co.vividnext.sodalive.R
|
||||||
@@ -37,14 +35,14 @@ class AudioContentBoxActivity : BaseActivity<ActivityAudioContentBoxBinding>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
binding.toolbar.tvBack.text = "내 보관함"
|
binding.toolbar.tvBack.text = getString(R.string.screen_audio_content_box_title)
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTabs() {
|
private fun setupTabs() {
|
||||||
val tabs = binding.tabs
|
val tabs = binding.tabs
|
||||||
tabs.addTab(tabs.newTab().setText("구매목록"))
|
tabs.addTab(tabs.newTab().setText(R.string.screen_audio_content_box_tab_orders))
|
||||||
tabs.addTab(tabs.newTab().setText("재생목록"))
|
tabs.addTab(tabs.newTab().setText(R.string.screen_audio_content_box_tab_playlists))
|
||||||
|
|
||||||
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.R
|
|||||||
import kr.co.vividnext.sodalive.databinding.ItemContentCategoryBinding
|
import kr.co.vividnext.sodalive.databinding.ItemContentCategoryBinding
|
||||||
|
|
||||||
class AudioContentCategoryAdapter(
|
class AudioContentCategoryAdapter(
|
||||||
|
private val allCategoryLabel: String,
|
||||||
private val onClick: (Long) -> Unit
|
private val onClick: (Long) -> Unit
|
||||||
) : RecyclerView.Adapter<AudioContentCategoryAdapter.ViewHolder>() {
|
) : RecyclerView.Adapter<AudioContentCategoryAdapter.ViewHolder>() {
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ class AudioContentCategoryAdapter(
|
|||||||
fun bind(item: GetCategoryListResponse) {
|
fun bind(item: GetCategoryListResponse) {
|
||||||
if (
|
if (
|
||||||
item.category == selectedCategory ||
|
item.category == selectedCategory ||
|
||||||
(selectedCategory == "" && item.category == "전체")
|
(selectedCategory.isEmpty() && item.category == allCategoryLabel)
|
||||||
) {
|
) {
|
||||||
binding.tvCategory.setBackgroundResource(
|
binding.tvCategory.setBackgroundResource(
|
||||||
R.drawable.bg_round_corner_16_7_transparent_3bb9f1
|
R.drawable.bg_round_corner_16_7_transparent_3bb9f1
|
||||||
|
|||||||
@@ -99,9 +99,12 @@ class AudioContentCommentAdapter(
|
|||||||
binding.tvCommentNickname.text = item.nickname
|
binding.tvCommentNickname.text = item.nickname
|
||||||
|
|
||||||
binding.tvWriteReply.text = if (item.replyCount > 0) {
|
binding.tvWriteReply.text = if (item.replyCount > 0) {
|
||||||
"답글 ${item.replyCount}개"
|
context.getString(
|
||||||
|
R.string.audio_content_comment_reply_count_format,
|
||||||
|
item.replyCount
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
"답글 쓰기"
|
context.getString(R.string.audio_content_comment_write_reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -106,9 +106,9 @@ class AudioContentCommentListFragment : BaseFragment<FragmentAudioContentComment
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = requireActivity(),
|
activity = requireActivity(),
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "댓글 삭제",
|
title = getString(R.string.audio_content_comment_delete_title),
|
||||||
desc = "삭제하시겠습니까?",
|
desc = getString(R.string.audio_content_comment_delete_message),
|
||||||
confirmButtonTitle = "삭제",
|
confirmButtonTitle = getString(R.string.screen_audio_content_detail_delete),
|
||||||
confirmButtonClick = {
|
confirmButtonClick = {
|
||||||
viewModel.modifyComment(
|
viewModel.modifyComment(
|
||||||
commentId = it,
|
commentId = it,
|
||||||
@@ -116,7 +116,7 @@ class AudioContentCommentListFragment : BaseFragment<FragmentAudioContentComment
|
|||||||
isActive = false
|
isActive = false
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
cancelButtonTitle = "취소",
|
cancelButtonTitle = getString(R.string.cancel),
|
||||||
cancelButtonClick = {}
|
cancelButtonClick = {}
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import com.orhanobut.logger.Logger
|
|||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AudioContentCommentListViewModel(
|
class AudioContentCommentListViewModel(
|
||||||
private val repository: AudioContentCommentRepository
|
private val repository: AudioContentCommentRepository
|
||||||
@@ -27,6 +29,17 @@ class AudioContentCommentListViewModel(
|
|||||||
val totalCommentCount: LiveData<Int>
|
val totalCommentCount: LiveData<Int>
|
||||||
get() = _totalCommentCount
|
get() = _totalCommentCount
|
||||||
|
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
|
private val noChangeMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.audio_content_comment_no_change)
|
||||||
|
|
||||||
|
private val inputRequiredMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(
|
||||||
|
R.string.audio_content_comment_input_required
|
||||||
|
)
|
||||||
|
|
||||||
var page = 1
|
var page = 1
|
||||||
private var isLast = false
|
private var isLast = false
|
||||||
private val size = 10
|
private val size = 10
|
||||||
@@ -59,9 +72,7 @@ class AudioContentCommentListViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
@@ -74,7 +85,7 @@ class AudioContentCommentListViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
@@ -110,16 +121,14 @@ class AudioContentCommentListViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -132,12 +141,12 @@ class AudioContentCommentListViewModel(
|
|||||||
isActive: Boolean? = null
|
isActive: Boolean? = null
|
||||||
) {
|
) {
|
||||||
if (comment == null && isActive == null) {
|
if (comment == null && isActive == null) {
|
||||||
_toastLiveData.postValue("변경사항이 없습니다.")
|
_toastLiveData.postValue(noChangeMessage)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comment != null && comment.isBlank()) {
|
if (comment != null && comment.isBlank()) {
|
||||||
_toastLiveData.postValue("내용을 입력하세요")
|
_toastLiveData.postValue(inputRequiredMessage)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,14 +178,14 @@ class AudioContentCommentListViewModel(
|
|||||||
isLast = false
|
isLast = false
|
||||||
getCommentList(audioContentId)
|
getCommentList(audioContentId)
|
||||||
} else {
|
} else {
|
||||||
val message = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = it.message ?: unknownErrorMessage
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -112,9 +112,9 @@ class AudioContentCommentReplyFragment : BaseFragment<FragmentAudioContentCommen
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = requireActivity(),
|
activity = requireActivity(),
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "댓글 삭제",
|
title = getString(R.string.audio_content_comment_delete_title),
|
||||||
desc = "삭제하시겠습니까?",
|
desc = getString(R.string.audio_content_comment_delete_message),
|
||||||
confirmButtonTitle = "삭제",
|
confirmButtonTitle = getString(R.string.screen_audio_content_detail_delete),
|
||||||
confirmButtonClick = {
|
confirmButtonClick = {
|
||||||
viewModel.modifyComment(
|
viewModel.modifyComment(
|
||||||
commentId = it,
|
commentId = it,
|
||||||
@@ -122,7 +122,7 @@ class AudioContentCommentReplyFragment : BaseFragment<FragmentAudioContentCommen
|
|||||||
isActive = false
|
isActive = false
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
cancelButtonTitle = "취소",
|
cancelButtonTitle = getString(R.string.cancel),
|
||||||
cancelButtonClick = {}
|
cancelButtonClick = {}
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import com.orhanobut.logger.Logger
|
|||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AudioContentCommentReplyViewModel(
|
class AudioContentCommentReplyViewModel(
|
||||||
private val repository: AudioContentCommentRepository
|
private val repository: AudioContentCommentRepository
|
||||||
@@ -23,6 +25,17 @@ class AudioContentCommentReplyViewModel(
|
|||||||
val commentList: LiveData<List<GetAudioContentCommentListItem>>
|
val commentList: LiveData<List<GetAudioContentCommentListItem>>
|
||||||
get() = _commentList
|
get() = _commentList
|
||||||
|
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
|
private val noChangeMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.audio_content_comment_no_change)
|
||||||
|
|
||||||
|
private val inputRequiredMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(
|
||||||
|
R.string.audio_content_comment_input_required
|
||||||
|
)
|
||||||
|
|
||||||
var page = 1
|
var page = 1
|
||||||
private var isLast = false
|
private var isLast = false
|
||||||
private val size = 10
|
private val size = 10
|
||||||
@@ -53,9 +66,7 @@ class AudioContentCommentReplyViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
@@ -68,7 +79,7 @@ class AudioContentCommentReplyViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
@@ -104,16 +115,14 @@ class AudioContentCommentReplyViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -126,12 +135,12 @@ class AudioContentCommentReplyViewModel(
|
|||||||
isActive: Boolean? = null
|
isActive: Boolean? = null
|
||||||
) {
|
) {
|
||||||
if (comment == null && isActive == null) {
|
if (comment == null && isActive == null) {
|
||||||
_toastLiveData.postValue("변경사항이 없습니다.")
|
_toastLiveData.postValue(noChangeMessage)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comment != null && comment.isBlank()) {
|
if (comment != null && comment.isBlank()) {
|
||||||
_toastLiveData.postValue("내용을 입력하세요")
|
_toastLiveData.postValue(inputRequiredMessage)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,14 +172,14 @@ class AudioContentCommentReplyViewModel(
|
|||||||
isLast = false
|
isLast = false
|
||||||
getCommentReplyList(parentCommentId)
|
getCommentReplyList(parentCommentId)
|
||||||
} else {
|
} else {
|
||||||
val message = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = it.message ?: unknownErrorMessage
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.databinding.DialogAudioContentDeleteBinding
|
import kr.co.vividnext.sodalive.databinding.DialogAudioContentDeleteBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
|
|
||||||
@@ -31,7 +32,10 @@ class AudioContentDeleteDialog(
|
|||||||
alertDialog.setCancelable(false)
|
alertDialog.setCancelable(false)
|
||||||
alertDialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
alertDialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
|
|
||||||
dialogView.tvTitle.text = "[$title]을 삭제하시겠습니까?"
|
dialogView.tvTitle.text = activity.getString(
|
||||||
|
R.string.screen_audio_content_detail_delete_confirm_message,
|
||||||
|
title
|
||||||
|
)
|
||||||
dialogView.tvCancel.setOnClickListener {
|
dialogView.tvCancel.setOnClickListener {
|
||||||
alertDialog.dismiss()
|
alertDialog.dismiss()
|
||||||
}
|
}
|
||||||
@@ -43,7 +47,9 @@ class AudioContentDeleteDialog(
|
|||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
"동의하셔야 삭제할 수 있습니다.",
|
activity.getString(
|
||||||
|
R.string.screen_audio_content_detail_delete_consent_required
|
||||||
|
),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import kr.co.vividnext.sodalive.base.SodaDialog
|
|||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.Utils
|
import kr.co.vividnext.sodalive.common.Utils
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentDetailBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentDetailBinding
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.CreatorFollowNotifyFragment
|
import kr.co.vividnext.sodalive.explorer.profile.CreatorFollowNotifyFragment
|
||||||
@@ -94,8 +95,13 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
binding.scrollView.scrollTo(0, 0)
|
binding.scrollView.scrollTo(0, 0)
|
||||||
binding.sbProgress.progress = 0
|
binding.sbProgress.progress = 0
|
||||||
binding.ivPlayOrPause.setImageResource(0)
|
binding.ivPlayOrPause.setImageResource(0)
|
||||||
binding.tvTotalDuration.text = " / 00:00:00"
|
binding.ivPlayOrPause.visibility = View.GONE
|
||||||
binding.tvCurrentDuration.text = "00:00:00"
|
binding.llPreview.visibility = View.GONE
|
||||||
|
binding.tvTotalDuration.text = getString(
|
||||||
|
R.string.screen_audio_content_detail_time_total_default
|
||||||
|
)
|
||||||
|
binding.tvCurrentDuration.text =
|
||||||
|
getString(R.string.screen_audio_content_detail_time_default)
|
||||||
binding.rlPreviewAlert.visibility = View.GONE
|
binding.rlPreviewAlert.visibility = View.GONE
|
||||||
|
|
||||||
audioContentId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
|
audioContentId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
|
||||||
@@ -109,7 +115,11 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
|
||||||
if (audioContentId <= 0) {
|
if (audioContentId <= 0) {
|
||||||
Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
getString(R.string.screen_audio_content_error_invalid_request),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +158,7 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
binding.tvBack.text = "콘텐츠 상세"
|
binding.tvBack.text = getString(R.string.screen_audio_content_detail_title)
|
||||||
binding.tvBack.setOnClickListener { finish() }
|
binding.tvBack.setOnClickListener { finish() }
|
||||||
binding.ivClosePreviewAlert.setOnClickListener { viewModel.toggleShowPreviewAlert() }
|
binding.ivClosePreviewAlert.setOnClickListener { viewModel.toggleShowPreviewAlert() }
|
||||||
binding.ivMenu.setOnClickListener {
|
binding.ivMenu.setOnClickListener {
|
||||||
@@ -292,9 +302,11 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
LayoutInflater.from(this)
|
LayoutInflater.from(this)
|
||||||
) { can, message, _ ->
|
) { can, message, _ ->
|
||||||
if (can <= 0) {
|
if (can <= 0) {
|
||||||
showToast("1캔 이상 후원하실 수 있습니다.")
|
showToast(getString(R.string.screen_audio_content_detail_donation_minimum))
|
||||||
} else if (message.isBlank()) {
|
} else if (message.isBlank()) {
|
||||||
showToast("함께 보낼 메시지를 입력하세요.")
|
showToast(
|
||||||
|
getString(R.string.screen_audio_content_detail_donation_empty_message)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
donation(can, message)
|
donation(can, message)
|
||||||
}
|
}
|
||||||
@@ -355,13 +367,11 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
this@AudioContentDetailActivity,
|
this@AudioContentDetailActivity,
|
||||||
layoutInflater,
|
layoutInflater,
|
||||||
"고정 한도 도달",
|
getString(R.string.screen_audio_content_detail_pin_limit_title),
|
||||||
"이 콘텐츠를 고정하시겠어요? " +
|
getString(R.string.screen_audio_content_detail_pin_limit_message),
|
||||||
"채널에 콘텐츠를 최대 3개까지 고정할 수 있습니다." +
|
getString(R.string.confirm),
|
||||||
"이 콘텐츠를 고정하면 가장 오래된 콘텐츠가 대체됩니다.",
|
|
||||||
"확인",
|
|
||||||
{ viewModel.pinContent(audioContentId) },
|
{ viewModel.pinContent(audioContentId) },
|
||||||
"취소",
|
getString(R.string.cancel),
|
||||||
{}
|
{}
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
}
|
}
|
||||||
@@ -446,7 +456,7 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
title = it.title
|
title = it.translated?.title ?: it.title
|
||||||
setupCreatorArea(it.creator)
|
setupCreatorArea(it.creator)
|
||||||
setupMosaicArea(it.isMosaic)
|
setupMosaicArea(it.isMosaic)
|
||||||
setupPlayArea(it)
|
setupPlayArea(it)
|
||||||
@@ -694,28 +704,31 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.tvUnit.text = if (SharedPreferenceManager.userId == 17958L) {
|
binding.tvUnit.text = if (SharedPreferenceManager.userId == 17958L) {
|
||||||
"원으로"
|
getString(R.string.screen_audio_content_detail_purchase_unit_won)
|
||||||
} else {
|
} else {
|
||||||
"캔으로"
|
getString(R.string.screen_audio_content_detail_purchase_unit_can)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (response.purchaseOption) {
|
when (response.purchaseOption) {
|
||||||
PurchaseOption.BOTH -> {
|
PurchaseOption.BOTH -> {
|
||||||
binding.tvStrPurchaseOrRental.text = " 구매하기"
|
binding.tvStrPurchaseOrRental.text =
|
||||||
|
getString(R.string.screen_audio_content_detail_action_buy)
|
||||||
binding.llPurchase.setBackgroundResource(
|
binding.llPurchase.setBackgroundResource(
|
||||||
R.drawable.bg_round_corner_5_3_3bb9f1
|
R.drawable.bg_round_corner_5_3_3bb9f1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
PurchaseOption.BUY_ONLY -> {
|
PurchaseOption.BUY_ONLY -> {
|
||||||
binding.tvStrPurchaseOrRental.text = " 소장하기"
|
binding.tvStrPurchaseOrRental.text =
|
||||||
|
getString(R.string.screen_audio_content_detail_action_keep)
|
||||||
binding.llPurchase.setBackgroundResource(
|
binding.llPurchase.setBackgroundResource(
|
||||||
R.drawable.bg_round_corner_5_3_59548f
|
R.drawable.bg_round_corner_5_3_59548f
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
PurchaseOption.RENT_ONLY -> {
|
PurchaseOption.RENT_ONLY -> {
|
||||||
binding.tvStrPurchaseOrRental.text = " 대여하기"
|
binding.tvStrPurchaseOrRental.text =
|
||||||
|
getString(R.string.screen_audio_content_detail_action_rental)
|
||||||
binding.llPurchase.setBackgroundResource(
|
binding.llPurchase.setBackgroundResource(
|
||||||
R.drawable.bg_round_corner_5_3_548f7d
|
R.drawable.bg_round_corner_5_3_548f7d
|
||||||
)
|
)
|
||||||
@@ -754,10 +767,14 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
binding.flSoldOut.visibility = View.GONE
|
binding.flSoldOut.visibility = View.GONE
|
||||||
binding.tvSoldOutBig.visibility = View.GONE
|
binding.tvSoldOutBig.visibility = View.GONE
|
||||||
binding.ivPlayOrPause.visibility = View.GONE
|
binding.ivPlayOrPause.visibility = View.GONE
|
||||||
|
binding.llPreview.visibility = View.GONE
|
||||||
binding.ivSeekBackward10.visibility = View.GONE
|
binding.ivSeekBackward10.visibility = View.GONE
|
||||||
binding.ivSeekForward10.visibility = View.GONE
|
binding.ivSeekForward10.visibility = View.GONE
|
||||||
binding.tvPreviewNo.visibility = View.GONE
|
binding.llPreviewNo.visibility = View.GONE
|
||||||
binding.tvTotalDuration.text = " / ${response.duration}"
|
binding.tvTotalDuration.text = getString(
|
||||||
|
R.string.screen_audio_content_detail_total_duration_format,
|
||||||
|
response.duration
|
||||||
|
)
|
||||||
|
|
||||||
isAlertPreview = response.creator.creatorId != SharedPreferenceManager.userId &&
|
isAlertPreview = response.creator.creatorId != SharedPreferenceManager.userId &&
|
||||||
!response.existOrdered &&
|
!response.existOrdered &&
|
||||||
@@ -775,8 +792,13 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
!isAlertPreview ||
|
!isAlertPreview ||
|
||||||
(response.isActivePreview && response.contentUrl.isNotBlank())
|
(response.isActivePreview && response.contentUrl.isNotBlank())
|
||||||
) {
|
) {
|
||||||
binding.ivPlayOrPause.visibility = View.VISIBLE
|
if (isAlertPreview) {
|
||||||
binding.ivPlayOrPause.setOnClickListener {
|
binding.llPreview.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.ivPlayOrPause.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
val playClickAction = View.OnClickListener {
|
||||||
startService(
|
startService(
|
||||||
Intent(
|
Intent(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
@@ -820,13 +842,9 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.ivPlayOrPause.setImageResource(
|
binding.ivPlayOrPause.setImageResource(R.drawable.btn_audio_content_play)
|
||||||
if (!isAlertPreview) {
|
binding.ivPlayOrPause.setOnClickListener(playClickAction)
|
||||||
R.drawable.btn_audio_content_play
|
binding.llPreview.setOnClickListener(playClickAction)
|
||||||
} else {
|
|
||||||
R.drawable.btn_audio_content_preview_play
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isAlertPreview) {
|
if (!isAlertPreview) {
|
||||||
binding.ivSeekForward10.visibility = View.VISIBLE
|
binding.ivSeekForward10.visibility = View.VISIBLE
|
||||||
@@ -855,7 +873,7 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (response.releaseDate == null) {
|
} else if (response.releaseDate == null) {
|
||||||
binding.tvPreviewNo.visibility = View.VISIBLE
|
binding.llPreviewNo.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.ivPoint.visibility = if (response.isAvailableUsePoint) {
|
binding.ivPoint.visibility = if (response.isAvailableUsePoint) {
|
||||||
@@ -894,13 +912,13 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
binding.tvRemainingTime.visibility = View.GONE
|
binding.tvRemainingTime.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.tvTitle.text = response.title
|
binding.tvTitle.text = response.translated?.title ?: response.title
|
||||||
binding.tvDetail.text = response.detail
|
binding.tvDetail.text = response.translated?.detail ?: response.detail
|
||||||
binding.tvDetail.setOnClickListener { viewModel.toggleExpandDetail() }
|
binding.tvDetail.setOnClickListener { viewModel.toggleExpandDetail() }
|
||||||
|
|
||||||
if (response.tag.isNotBlank()) {
|
if (response.tag.isNotBlank()) {
|
||||||
binding.tvTag.visibility = View.VISIBLE
|
binding.tvTag.visibility = View.VISIBLE
|
||||||
binding.tvTag.text = response.tag
|
binding.tvTag.text = response.translated?.tags ?: response.tag
|
||||||
} else {
|
} else {
|
||||||
binding.tvTag.visibility = View.GONE
|
binding.tvTag.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@@ -925,7 +943,7 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
binding.ivLike.setImageResource(R.drawable.ic_audio_content_heart_pressed)
|
binding.ivLike.setImageResource(R.drawable.ic_audio_content_heart_pressed)
|
||||||
} else {
|
} else {
|
||||||
binding.tvLike.text = if (likeCount - 1 < 0) {
|
binding.tvLike.text = if (likeCount - 1 < 0) {
|
||||||
"0"
|
SodaLiveApplicationHolder.get().getString(R.string.common_zero)
|
||||||
} else {
|
} else {
|
||||||
"${likeCount - 1}"
|
"${likeCount - 1}"
|
||||||
}
|
}
|
||||||
@@ -941,7 +959,10 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
intent.type = "text/plain"
|
intent.type = "text/plain"
|
||||||
intent.putExtra(Intent.EXTRA_TEXT, it)
|
intent.putExtra(Intent.EXTRA_TEXT, it)
|
||||||
|
|
||||||
val shareIntent = Intent.createChooser(intent, "오디오 콘텐츠 공유")
|
val shareIntent = Intent.createChooser(
|
||||||
|
intent,
|
||||||
|
getString(R.string.screen_audio_content_detail_share_title)
|
||||||
|
)
|
||||||
startActivity(shareIntent)
|
startActivity(shareIntent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1203,23 +1224,29 @@ class AudioContentDetailActivity : BaseActivity<ActivityAudioContentDetailBindin
|
|||||||
if (this@AudioContentDetailActivity.audioContentId == contentId) {
|
if (this@AudioContentDetailActivity.audioContentId == contentId) {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
if (changeUi != null && changeUi) {
|
if (changeUi != null && changeUi) {
|
||||||
binding.ivPlayOrPause.setImageResource(
|
if (isPlaying != null && isPlaying) {
|
||||||
if (isPlaying != null && isPlaying) {
|
binding.ivPlayOrPause.visibility = View.VISIBLE
|
||||||
R.drawable.btn_audio_content_pause
|
binding.llPreview.visibility = View.GONE
|
||||||
|
binding.ivPlayOrPause.setImageResource(R.drawable.btn_audio_content_pause)
|
||||||
|
} else {
|
||||||
|
if (isAlertPreview) {
|
||||||
|
binding.ivPlayOrPause.visibility = View.GONE
|
||||||
|
binding.llPreview.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
if (isAlertPreview) {
|
binding.ivPlayOrPause.visibility = View.VISIBLE
|
||||||
R.drawable.btn_audio_content_preview_play
|
binding.llPreview.visibility = View.GONE
|
||||||
} else {
|
binding.ivPlayOrPause.setImageResource(R.drawable.btn_audio_content_play)
|
||||||
R.drawable.btn_audio_content_play
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duration != null && duration > 0) {
|
if (duration != null && duration > 0) {
|
||||||
binding.sbProgress.max = duration
|
binding.sbProgress.max = duration
|
||||||
binding.tvTotalDuration.text = " / ${Utils.convertDurationToString(duration)}"
|
binding.tvTotalDuration.text = getString(
|
||||||
|
R.string.screen_audio_content_detail_total_duration_format,
|
||||||
|
Utils.convertDurationToString(duration)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress != null && progress > 0) {
|
if (progress != null && progress > 0) {
|
||||||
|
|||||||
@@ -36,10 +36,11 @@ class AudioContentDetailMenuBottomSheetDialog(
|
|||||||
|
|
||||||
if (isPin) {
|
if (isPin) {
|
||||||
dialog.ivPin.setImageResource(R.drawable.ic_pin_cancel)
|
dialog.ivPin.setImageResource(R.drawable.ic_pin_cancel)
|
||||||
dialog.tvPin.text = "내 채널에 고정 취소"
|
dialog.tvPin.text =
|
||||||
|
getString(R.string.screen_audio_content_detail_pin_cancel)
|
||||||
} else {
|
} else {
|
||||||
dialog.ivPin.setImageResource(R.drawable.ic_pin)
|
dialog.ivPin.setImageResource(R.drawable.ic_pin)
|
||||||
dialog.tvPin.text = "내 채널에 고정"
|
dialog.tvPin.text = getString(R.string.screen_audio_content_detail_pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.llPin.setOnClickListener {
|
dialog.llPin.setOnClickListener {
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content.detail
|
package kr.co.vividnext.sodalive.audio_content.detail
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.audio_content.comment.AudioContentCommentRepository
|
import kr.co.vividnext.sodalive.audio_content.comment.AudioContentCommentRepository
|
||||||
import kr.co.vividnext.sodalive.audio_content.order.OrderType
|
import kr.co.vividnext.sodalive.audio_content.order.OrderType
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.Utils
|
import kr.co.vividnext.sodalive.common.Utils
|
||||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||||
import kr.co.vividnext.sodalive.mypage.auth.AuthRepository
|
import kr.co.vividnext.sodalive.mypage.auth.AuthRepository
|
||||||
@@ -52,7 +55,13 @@ class AudioContentDetailViewModel(
|
|||||||
val isContentPlayLoopLiveData: LiveData<Boolean>
|
val isContentPlayLoopLiveData: LiveData<Boolean>
|
||||||
get() = _isContentPlayLoopLiveData
|
get() = _isContentPlayLoopLiveData
|
||||||
|
|
||||||
fun getAudioContentDetail(audioContentId: Long, onFailure: (() -> Unit)? = null) {
|
private fun getString(@StringRes resId: Int, vararg args: Any) =
|
||||||
|
SodaLiveApplicationHolder.get().getString(resId, *args)
|
||||||
|
|
||||||
|
fun getAudioContentDetail(
|
||||||
|
audioContentId: Long,
|
||||||
|
onFailure: (() -> Unit)? = null
|
||||||
|
) {
|
||||||
if (!isLoading.value!!) {
|
if (!isLoading.value!!) {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
}
|
}
|
||||||
@@ -73,7 +82,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +96,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
@@ -116,7 +125,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +134,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -155,9 +164,13 @@ class AudioContentDetailViewModel(
|
|||||||
getAudioContentDetail(audioContentId = contentId)
|
getAudioContentDetail(audioContentId = contentId)
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
if (orderType == OrderType.RENTAL) {
|
if (orderType == OrderType.RENTAL) {
|
||||||
"대여가 완료되었습니다."
|
getString(
|
||||||
|
R.string.screen_audio_content_detail_order_rental_success
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
"구매가 완료되었습니다."
|
getString(
|
||||||
|
R.string.screen_audio_content_detail_order_keep_success
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -168,7 +181,7 @@ class AudioContentDetailViewModel(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +190,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -201,7 +214,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +224,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -240,7 +253,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +263,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -283,7 +296,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,7 +304,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -327,7 +340,7 @@ class AudioContentDetailViewModel(
|
|||||||
|
|
||||||
if (it.success) {
|
if (it.success) {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"삭제되었습니다."
|
getString(R.string.screen_audio_content_detail_delete_success)
|
||||||
)
|
)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
} else {
|
} else {
|
||||||
@@ -335,7 +348,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -343,7 +356,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -365,7 +378,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"신고가 접수되었습니다."
|
getString(R.string.screen_audio_content_detail_report_submitted)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +387,9 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("신고가 접수되었습니다.")
|
_toastLiveData.postValue(
|
||||||
|
getString(R.string.screen_audio_content_detail_report_submitted)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -404,7 +419,10 @@ class AudioContentDetailViewModel(
|
|||||||
if (it.success) {
|
if (it.success) {
|
||||||
SharedPreferenceManager.can -= can
|
SharedPreferenceManager.can -= can
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"${can.moneyFormat()}캔을 후원하였습니다."
|
getString(
|
||||||
|
R.string.screen_audio_content_detail_donation_success,
|
||||||
|
can.moneyFormat()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
} else {
|
} else {
|
||||||
@@ -412,7 +430,7 @@ class AudioContentDetailViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,7 +438,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -440,14 +458,16 @@ class AudioContentDetailViewModel(
|
|||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
|
|
||||||
if (it.success) {
|
if (it.success) {
|
||||||
_toastLiveData.postValue("고정되었습니다.")
|
_toastLiveData.postValue(
|
||||||
|
getString(R.string.screen_audio_content_detail_pin_success)
|
||||||
|
)
|
||||||
getAudioContentDetail(audioContentId)
|
getAudioContentDetail(audioContentId)
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,7 +475,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -475,14 +495,16 @@ class AudioContentDetailViewModel(
|
|||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
|
|
||||||
if (it.success) {
|
if (it.success) {
|
||||||
_toastLiveData.postValue("해제되었습니다.")
|
_toastLiveData.postValue(
|
||||||
|
getString(R.string.screen_audio_content_detail_unpin_success)
|
||||||
|
)
|
||||||
getAudioContentDetail(audioContentId)
|
getAudioContentDetail(audioContentId)
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -490,7 +512,7 @@ class AudioContentDetailViewModel(
|
|||||||
{
|
{
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(getString(R.string.common_error_unknown))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.view.WindowManager
|
|||||||
import android.widget.RadioButton
|
import android.widget.RadioButton
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.databinding.DialogAudioContentReportBinding
|
import kr.co.vividnext.sodalive.databinding.DialogAudioContentReportBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
|
|
||||||
@@ -37,7 +38,13 @@ class AudioContentReportDialog(
|
|||||||
alertDialog.dismiss()
|
alertDialog.dismiss()
|
||||||
confirmButtonClick(reason)
|
confirmButtonClick(reason)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(activity, "신고 이유를 선택하세요.", Toast.LENGTH_LONG).show()
|
Toast.makeText(
|
||||||
|
activity,
|
||||||
|
activity.getString(
|
||||||
|
R.string.screen_audio_content_detail_report_reason_required
|
||||||
|
),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ data class GetAudioContentDetailResponse(
|
|||||||
@SerializedName("previousContent") val previousContent: OtherContentResponse?,
|
@SerializedName("previousContent") val previousContent: OtherContentResponse?,
|
||||||
@SerializedName("nextContent") val nextContent: OtherContentResponse?,
|
@SerializedName("nextContent") val nextContent: OtherContentResponse?,
|
||||||
@SerializedName("buyerList") val buyerList: List<ContentBuyer>,
|
@SerializedName("buyerList") val buyerList: List<ContentBuyer>,
|
||||||
@SerializedName("isAvailableUsePoint") val isAvailableUsePoint: Boolean
|
@SerializedName("isAvailableUsePoint") val isAvailableUsePoint: Boolean,
|
||||||
|
@SerializedName("translated") val translated: TranslatedContent?
|
||||||
)
|
)
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
@@ -68,3 +69,10 @@ data class ContentBuyer(
|
|||||||
@SerializedName("nickname") val nickname: String,
|
@SerializedName("nickname") val nickname: String,
|
||||||
@SerializedName("profileImageUrl") val profileImageUrl: String
|
@SerializedName("profileImageUrl") val profileImageUrl: String
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
data class TranslatedContent(
|
||||||
|
@SerializedName("title") val title: String?,
|
||||||
|
@SerializedName("detail") val detail: String?,
|
||||||
|
@SerializedName("tags") val tags: String?
|
||||||
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kr.co.vividnext.sodalive.R
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.databinding.ItemAudioContentMainNewContentThemeBinding
|
import kr.co.vividnext.sodalive.databinding.ItemAudioContentMainNewContentThemeBinding
|
||||||
|
|
||||||
class AudioContentMainNewContentThemeAdapter(
|
class AudioContentMainNewContentThemeAdapter(
|
||||||
@@ -24,8 +25,10 @@ class AudioContentMainNewContentThemeAdapter(
|
|||||||
fun bind(theme: String) {
|
fun bind(theme: String) {
|
||||||
if (
|
if (
|
||||||
theme == selectedTheme ||
|
theme == selectedTheme ||
|
||||||
(selectedTheme == "" && theme == "전체") ||
|
(selectedTheme == "" && theme == SodaLiveApplicationHolder.get()
|
||||||
(selectedTheme == "" && theme == "매출")
|
.getString(R.string.audio_content_label_all)) ||
|
||||||
|
(selectedTheme == "" && theme == SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.screen_home_sort_revenue))
|
||||||
) {
|
) {
|
||||||
binding.tvTheme.setBackgroundResource(
|
binding.tvTheme.setBackgroundResource(
|
||||||
R.drawable.bg_round_corner_16_7_transparent_3bb9f1
|
R.drawable.bg_round_corner_16_7_transparent_3bb9f1
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import kr.co.vividnext.sodalive.common.Constants
|
|||||||
import kr.co.vividnext.sodalive.common.ImagePickerCropper
|
import kr.co.vividnext.sodalive.common.ImagePickerCropper
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
import kr.co.vividnext.sodalive.common.RealPathUtil
|
import kr.co.vividnext.sodalive.common.RealPathUtil
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentModifyBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentModifyBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
@@ -42,7 +43,12 @@ class AudioContentModifyActivity : BaseActivity<ActivityAudioContentModifyBindin
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val audioContentId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
|
val audioContentId = intent.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)
|
||||||
if (audioContentId <= 0) {
|
if (audioContentId <= 0) {
|
||||||
Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.screen_audio_content_error_invalid_request),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import com.google.gson.Gson
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
@@ -111,7 +113,8 @@ class AudioContentModifyViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +128,10 @@ class AudioContentModifyViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
|
)
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
@@ -201,7 +207,8 @@ class AudioContentModifyViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,7 +218,8 @@ class AudioContentModifyViewModel(
|
|||||||
_isLoading.postValue(false)
|
_isLoading.postValue(false)
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -221,12 +229,18 @@ class AudioContentModifyViewModel(
|
|||||||
|
|
||||||
private fun validateData(): Boolean {
|
private fun validateData(): Boolean {
|
||||||
if (title != null && title!!.isBlank()) {
|
if (title != null && title!!.isBlank()) {
|
||||||
_toastLiveData.postValue("제목을 입력해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.audio_content_upload_error_title_required)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detail != null && (detail!!.isBlank() || detail!!.length < 5)) {
|
if (detail != null && (detail!!.isBlank() || detail!!.length < 5)) {
|
||||||
_toastLiveData.postValue("내용을 5자 이상 입력해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.audio_content_upload_error_detail_min_length)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content.order
|
package kr.co.vividnext.sodalive.audio_content.order
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
@@ -17,7 +16,6 @@ import kr.co.vividnext.sodalive.databinding.DialogAudioContentOrderConfirmBindin
|
|||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
class AudioContentOrderConfirmDialog(
|
class AudioContentOrderConfirmDialog(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
layoutInflater: LayoutInflater,
|
layoutInflater: LayoutInflater,
|
||||||
@@ -38,6 +36,7 @@ class AudioContentOrderConfirmDialog(
|
|||||||
val dialogView = DialogAudioContentOrderConfirmBinding.inflate(layoutInflater)
|
val dialogView = DialogAudioContentOrderConfirmBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
val context = dialogView.root.context
|
||||||
val dialogBuilder = AlertDialog.Builder(activity)
|
val dialogBuilder = AlertDialog.Builder(activity)
|
||||||
dialogBuilder.setView(dialogView.root)
|
dialogBuilder.setView(dialogView.root)
|
||||||
|
|
||||||
@@ -82,7 +81,10 @@ class AudioContentOrderConfirmDialog(
|
|||||||
dialogView.tvPoint.visibility = View.GONE
|
dialogView.tvPoint.visibility = View.GONE
|
||||||
dialogView.tvPlus.visibility = View.GONE
|
dialogView.tvPlus.visibility = View.GONE
|
||||||
dialogView.ivCan.visibility = View.GONE
|
dialogView.ivCan.visibility = View.GONE
|
||||||
dialogView.tvCan.text = "${(price * 110).moneyFormat()}원"
|
dialogView.tvCan.text = context.getString(
|
||||||
|
R.string.audio_content_order_price_won_format,
|
||||||
|
(price * 110).moneyFormat()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
if (usablePoint > 0) {
|
if (usablePoint > 0) {
|
||||||
dialogView.ivPoint.visibility = View.VISIBLE
|
dialogView.ivPoint.visibility = View.VISIBLE
|
||||||
@@ -111,19 +113,19 @@ class AudioContentOrderConfirmDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SharedPreferenceManager.userId == 17958L) {
|
val noticeResId = when {
|
||||||
dialogView.tvNotice.text = if (orderType == OrderType.RENTAL) {
|
SharedPreferenceManager.userId == 17958L && orderType == OrderType.RENTAL ->
|
||||||
"콘텐츠를 대여하시겠습니까?"
|
R.string.audio_content_order_confirm_notice_rental_simple
|
||||||
} else {
|
|
||||||
"콘텐츠를 소장하시겠습니까?"
|
SharedPreferenceManager.userId == 17958L && orderType == OrderType.KEEP ->
|
||||||
}
|
R.string.audio_content_order_confirm_notice_keep_simple
|
||||||
} else {
|
|
||||||
dialogView.tvNotice.text = if (orderType == OrderType.RENTAL) {
|
orderType == OrderType.RENTAL ->
|
||||||
"콘텐츠를 대여하시겠습니까?\n아래 금액이 차감됩니다."
|
R.string.audio_content_order_confirm_notice_rental
|
||||||
} else {
|
|
||||||
"콘텐츠를 소장하시겠습니까?\n아래 금액이 차감됩니다."
|
else -> R.string.audio_content_order_confirm_notice_keep
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
dialogView.tvNotice.text = dialogView.root.context.getString(noticeResId)
|
||||||
|
|
||||||
dialogView.tvCancel.setOnClickListener {
|
dialogView.tvCancel.setOnClickListener {
|
||||||
alertDialog.dismiss()
|
alertDialog.dismiss()
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content.order
|
package kr.co.vividnext.sodalive.audio_content.order
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.databinding.FragmentAudioContentOrderBinding
|
import kr.co.vividnext.sodalive.databinding.FragmentAudioContentOrderBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||||
@@ -28,23 +28,31 @@ class AudioContentOrderFragment(
|
|||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
val context = requireContext()
|
||||||
if (SharedPreferenceManager.userId == 17958L) {
|
if (SharedPreferenceManager.userId == 17958L) {
|
||||||
binding.tvKeepDate.text = "(이용기간 1년)"
|
binding.tvKeepDate.text =
|
||||||
|
context.getString(R.string.audio_content_order_keep_period_special)
|
||||||
binding.ivKeepCan.visibility = View.GONE
|
binding.ivKeepCan.visibility = View.GONE
|
||||||
binding.ivRentalCan.visibility = View.GONE
|
binding.ivRentalCan.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
binding.tvKeepDate.text = "(서비스 종료시까지)"
|
binding.tvKeepDate.text =
|
||||||
|
context.getString(R.string.audio_content_order_keep_period_default)
|
||||||
binding.ivKeepCan.visibility = View.VISIBLE
|
binding.ivKeepCan.visibility = View.VISIBLE
|
||||||
binding.ivRentalCan.visibility = View.VISIBLE
|
binding.ivRentalCan.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SharedPreferenceManager.userId == 17958L) {
|
if (SharedPreferenceManager.userId == 17958L) {
|
||||||
binding.tvKeep.text = "${(price * 110).moneyFormat()}원"
|
binding.tvKeep.text = context.getString(
|
||||||
binding.tvRental.text = "${(ceil(price * 0.7).toInt() * 110).moneyFormat()}원"
|
R.string.audio_content_order_price_won_format,
|
||||||
|
(price * 110).moneyFormat()
|
||||||
|
)
|
||||||
|
binding.tvRental.text = context.getString(
|
||||||
|
R.string.audio_content_order_price_won_format,
|
||||||
|
(ceil(price * 0.7).toInt() * 110).moneyFormat()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
binding.tvKeep.text = price.moneyFormat()
|
binding.tvKeep.text = price.moneyFormat()
|
||||||
binding.tvRental.text = ceil(price * 0.7).toInt().moneyFormat()
|
binding.tvRental.text = ceil(price * 0.7).toInt().moneyFormat()
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class AudioContentOrderListActivity : BaseActivity<ActivityAudioContentOrderList
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
binding.toolbar.tvBack.text = "콘텐츠 보관함"
|
binding.toolbar.tvBack.text = getString(R.string.screen_audio_content_order_title)
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class AudioContentOrderListFragment : BaseFragment<FragmentAudioContentOrderList
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.totalCount.observe(viewLifecycleOwner) {
|
viewModel.totalCount.observe(viewLifecycleOwner) {
|
||||||
binding.tvTotalCount.text = "$it"
|
binding.tvTotalCount.text = it.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
|
||||||
class AudioContentOrderListViewModel(
|
class AudioContentOrderListViewModel(
|
||||||
@@ -34,6 +36,7 @@ class AudioContentOrderListViewModel(
|
|||||||
private val size = 10
|
private val size = 10
|
||||||
|
|
||||||
fun getAudioContentOrderList(onFailure: (() -> Unit)? = null) {
|
fun getAudioContentOrderList(onFailure: (() -> Unit)? = null) {
|
||||||
|
val unknownError = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
if (_isLoading.value == false) {
|
if (_isLoading.value == false) {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
@@ -59,9 +62,7 @@ class AudioContentOrderListViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownError)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
@@ -73,7 +74,7 @@ class AudioContentOrderListViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownError)
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ class AudioContentPlayerFragment(
|
|||||||
if (mediaController == null) {
|
if (mediaController == null) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
"플레이어를 실행하지 못했습니다.\n다시 시도해 주세요.",
|
getString(R.string.audio_content_player_error_launch_failed),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import android.view.ViewGroup
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import kr.co.vividnext.sodalive.R
|
|
||||||
import kr.co.vividnext.sodalive.databinding.ItemPlaylistListBinding
|
import kr.co.vividnext.sodalive.databinding.ItemPlaylistListBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AudioContentPlaylistListAdapter(
|
class AudioContentPlaylistListAdapter(
|
||||||
private val onClickItem: (Long) -> Unit
|
private val onClickItem: (Long) -> Unit
|
||||||
@@ -20,7 +20,6 @@ class AudioContentPlaylistListAdapter(
|
|||||||
inner class ViewHolder(
|
inner class ViewHolder(
|
||||||
private val binding: ItemPlaylistListBinding
|
private val binding: ItemPlaylistListBinding
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
fun bind(item: GetPlaylistsItem) {
|
fun bind(item: GetPlaylistsItem) {
|
||||||
binding.ivCover.load(item.coverImageUrl) {
|
binding.ivCover.load(item.coverImageUrl) {
|
||||||
crossfade(true)
|
crossfade(true)
|
||||||
@@ -29,7 +28,10 @@ class AudioContentPlaylistListAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.tvTitle.text = item.title
|
binding.tvTitle.text = item.title
|
||||||
binding.tvContentCount.text = "총 ${item.contentCount}개"
|
binding.tvContentCount.text = binding.root.context.getString(
|
||||||
|
R.string.audio_content_playlist_content_count,
|
||||||
|
item.contentCount
|
||||||
|
)
|
||||||
|
|
||||||
if (item.desc.isNotBlank()) {
|
if (item.desc.isNotBlank()) {
|
||||||
binding.tvDesc.text = item.desc
|
binding.tvDesc.text = item.desc
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content.playlist
|
package kr.co.vividnext.sodalive.audio_content.playlist
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.annotation.OptIn
|
||||||
import androidx.appcompat.app.AppCompatActivity.RESULT_OK
|
import androidx.appcompat.app.AppCompatActivity.RESULT_OK
|
||||||
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.create.AudioContentPlaylistCreateActivity
|
import kr.co.vividnext.sodalive.audio_content.playlist.create.AudioContentPlaylistCreateActivity
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistDetailActivity
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistDetailActivity
|
||||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||||
@@ -43,6 +45,7 @@ class AudioContentPlaylistListFragment : BaseFragment<FragmentAudioContentPlayli
|
|||||||
viewModel.getPlaylistList()
|
viewModel.getPlaylistList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class)
|
||||||
private fun setupView() {
|
private fun setupView() {
|
||||||
loadingDialog = LoadingDialog(requireActivity(), layoutInflater)
|
loadingDialog = LoadingDialog(requireActivity(), layoutInflater)
|
||||||
adapter = AudioContentPlaylistListAdapter { playlistId ->
|
adapter = AudioContentPlaylistListAdapter { playlistId ->
|
||||||
@@ -107,7 +110,6 @@ class AudioContentPlaylistListFragment : BaseFragment<FragmentAudioContentPlayli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.isLoading.observe(viewLifecycleOwner) {
|
viewModel.isLoading.observe(viewLifecycleOwner) {
|
||||||
if (it) {
|
if (it) {
|
||||||
@@ -122,7 +124,8 @@ class AudioContentPlaylistListFragment : BaseFragment<FragmentAudioContentPlayli
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.totalCountLiveData.observe(viewLifecycleOwner) {
|
viewModel.totalCountLiveData.observe(viewLifecycleOwner) {
|
||||||
binding.tvTotalCount.text = "${it}개"
|
binding.tvTotalCount.text =
|
||||||
|
getString(R.string.audio_content_playlist_total_count, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.playlistLiveData.observe(viewLifecycleOwner) {
|
viewModel.playlistLiveData.observe(viewLifecycleOwner) {
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
|
||||||
class AudioContentPlaylistListViewModel(
|
class AudioContentPlaylistListViewModel(
|
||||||
private val repository: AudioContentPlaylistRepository
|
private val repository: AudioContentPlaylistRepository
|
||||||
@@ -44,7 +46,8 @@ class AudioContentPlaylistListViewModel(
|
|||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +55,10 @@ class AudioContentPlaylistListViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content.playlist.create
|
package kr.co.vividnext.sodalive.audio_content.playlist.create
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -11,10 +10,12 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.jakewharton.rxbinding4.widget.textChanges
|
import com.jakewharton.rxbinding4.widget.textChanges
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.create.add_content.PlaylistAddContentDialogFragment
|
import kr.co.vividnext.sodalive.audio_content.playlist.create.add_content.PlaylistAddContentDialogFragment
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentPlaylistCreateBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentPlaylistCreateBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
@@ -39,7 +40,8 @@ class AudioContentPlaylistCreateActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
title = item.title,
|
title = item.title,
|
||||||
category = item.themeStr,
|
category = item.themeStr,
|
||||||
coverUrl = item.coverImageUrl,
|
coverUrl = item.coverImageUrl,
|
||||||
duration = item.duration ?: "00:00:00",
|
duration = item.duration ?: SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.screen_audio_content_upload_preview_start_time_default),
|
||||||
creatorNickname = item.creatorNickname,
|
creatorNickname = item.creatorNickname,
|
||||||
creatorProfileUrl = ""
|
creatorProfileUrl = ""
|
||||||
)
|
)
|
||||||
@@ -70,7 +72,8 @@ class AudioContentPlaylistCreateActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
binding.tvBack.text = "새 재생목록 만들기"
|
binding.tvBack.text = getString(R.string.audio_content_playlist_create_title)
|
||||||
|
binding.tvSave.text = getString(R.string.audio_content_playlist_create_save)
|
||||||
binding.tvBack.setOnClickListener { finish() }
|
binding.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
@@ -153,8 +156,8 @@ class AudioContentPlaylistCreateActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe {
|
.subscribe {
|
||||||
if (it.length > 30) {
|
if (it.length > PLAYLIST_TITLE_MAX_LENGTH) {
|
||||||
val truncated = it.take(30)
|
val truncated = it.take(PLAYLIST_TITLE_MAX_LENGTH)
|
||||||
binding.etTitle.setText(truncated)
|
binding.etTitle.setText(truncated)
|
||||||
binding.etTitle.setSelection(truncated.length)
|
binding.etTitle.setSelection(truncated.length)
|
||||||
setTitle(truncated)
|
setTitle(truncated)
|
||||||
@@ -171,8 +174,8 @@ class AudioContentPlaylistCreateActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe {
|
.subscribe {
|
||||||
if (it.length > 40) {
|
if (it.length > PLAYLIST_DESC_MAX_LENGTH) {
|
||||||
val truncated = it.take(40)
|
val truncated = it.take(PLAYLIST_DESC_MAX_LENGTH)
|
||||||
binding.etDesc.setText(truncated)
|
binding.etDesc.setText(truncated)
|
||||||
binding.etDesc.setSelection(truncated.length)
|
binding.etDesc.setSelection(truncated.length)
|
||||||
setDesc(truncated)
|
setDesc(truncated)
|
||||||
@@ -183,15 +186,26 @@ class AudioContentPlaylistCreateActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
private fun setTitle(title: String) {
|
private fun setTitle(title: String) {
|
||||||
binding.tvTitleLength.text = "${title.length}/30"
|
binding.tvTitleLength.text = getString(
|
||||||
|
R.string.audio_content_playlist_create_length_format,
|
||||||
|
title.length,
|
||||||
|
PLAYLIST_TITLE_MAX_LENGTH
|
||||||
|
)
|
||||||
viewModel.title = title
|
viewModel.title = title
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
private fun setDesc(desc: String) {
|
private fun setDesc(desc: String) {
|
||||||
binding.tvDescLength.text = "${desc.length}/40"
|
binding.tvDescLength.text = getString(
|
||||||
|
R.string.audio_content_playlist_create_length_format,
|
||||||
|
desc.length,
|
||||||
|
PLAYLIST_DESC_MAX_LENGTH
|
||||||
|
)
|
||||||
viewModel.desc = desc
|
viewModel.desc = desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private const val PLAYLIST_TITLE_MAX_LENGTH = 30
|
||||||
|
private const val PLAYLIST_DESC_MAX_LENGTH = 40
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.AudioContentPlaylistRepository
|
import kr.co.vividnext.sodalive.audio_content.playlist.AudioContentPlaylistRepository
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
|
||||||
class AudioContentPlaylistCreateViewModel(
|
class AudioContentPlaylistCreateViewModel(
|
||||||
private val repository: AudioContentPlaylistRepository
|
private val repository: AudioContentPlaylistRepository
|
||||||
@@ -41,6 +43,8 @@ class AudioContentPlaylistCreateViewModel(
|
|||||||
|
|
||||||
fun savePlaylist(onSuccess: () -> Unit) {
|
fun savePlaylist(onSuccess: () -> Unit) {
|
||||||
if (validate()) {
|
if (validate()) {
|
||||||
|
val unknownError =
|
||||||
|
SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
val contentIdAndOrderList = contentList.mapIndexed { index, item ->
|
val contentIdAndOrderList = contentList.mapIndexed { index, item ->
|
||||||
PlaylistContentIdAndOrder(item.id, index + 1)
|
PlaylistContentIdAndOrder(item.id, index + 1)
|
||||||
@@ -66,7 +70,7 @@ class AudioContentPlaylistCreateViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.value = it.message
|
_toastLiveData.value = it.message
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -75,7 +79,7 @@ class AudioContentPlaylistCreateViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.value = it.message
|
_toastLiveData.value = it.message
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -84,16 +88,27 @@ class AudioContentPlaylistCreateViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun validate(): Boolean {
|
private fun validate(): Boolean {
|
||||||
if (title.isBlank() || title.length < 3) {
|
if (title.isBlank() || title.length < MIN_TITLE_LENGTH) {
|
||||||
_toastLiveData.value = "제목을 3자 이상 입력하세요"
|
_toastLiveData.value = SodaLiveApplicationHolder.get().getString(
|
||||||
|
R.string.audio_content_playlist_create_title_min_length_error,
|
||||||
|
MIN_TITLE_LENGTH
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contentList.isEmpty()) {
|
if (contentList.isEmpty()) {
|
||||||
_toastLiveData.value = "콘텐츠를 1개 이상 추가하세요"
|
_toastLiveData.value = SodaLiveApplicationHolder.get().getString(
|
||||||
|
R.string.audio_content_playlist_create_content_min_count_error,
|
||||||
|
MIN_CONTENT_COUNT
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private const val MIN_TITLE_LENGTH = 3
|
||||||
|
private const val MIN_CONTENT_COUNT = 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderListViewModel
|
import kr.co.vividnext.sodalive.audio_content.order.AudioContentOrderListViewModel
|
||||||
import kr.co.vividnext.sodalive.audio_content.order.GetAudioContentOrderListItem
|
import kr.co.vividnext.sodalive.audio_content.order.GetAudioContentOrderListItem
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
||||||
@@ -148,7 +149,7 @@ class PlaylistAddContentDialogFragment(
|
|||||||
recyclerView.adapter = adapter
|
recyclerView.adapter = adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n", "NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
||||||
Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show()
|
Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show()
|
||||||
@@ -175,7 +176,10 @@ class PlaylistAddContentDialogFragment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.totalCount.observe(viewLifecycleOwner) {
|
viewModel.totalCount.observe(viewLifecycleOwner) {
|
||||||
binding.tvContentCount.text = "${it}개"
|
binding.tvContentCount.text = getString(
|
||||||
|
R.string.audio_content_playlist_total_count,
|
||||||
|
it
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,8 +173,9 @@ class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
if (playlistId <= 0) {
|
if (playlistId <= 0) {
|
||||||
showToast("잘못된 요청입니다.")
|
showToast(getString(R.string.screen_audio_content_error_invalid_request))
|
||||||
finish()
|
finish()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bindData()
|
bindData()
|
||||||
@@ -283,16 +284,19 @@ class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = this@AudioContentPlaylistDetailActivity,
|
activity = this@AudioContentPlaylistDetailActivity,
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "재생 목록 삭제",
|
title = getString(R.string.audio_content_playlist_detail_delete_title),
|
||||||
desc = "'${binding.tvTitle.text}'을 삭제하시겠습니까?",
|
desc = getString(
|
||||||
confirmButtonTitle = "삭제",
|
R.string.audio_content_playlist_detail_delete_message,
|
||||||
|
binding.tvTitle.text
|
||||||
|
),
|
||||||
|
confirmButtonTitle = getString(R.string.screen_audio_content_detail_delete),
|
||||||
confirmButtonClick = {
|
confirmButtonClick = {
|
||||||
viewModel.deletePlaylist(playlistId = playlistId) {
|
viewModel.deletePlaylist(playlistId = playlistId) {
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cancelButtonTitle = "취소",
|
cancelButtonTitle = getString(R.string.cancel),
|
||||||
cancelButtonClick = {}
|
cancelButtonClick = {}
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
}
|
}
|
||||||
@@ -319,8 +323,14 @@ class AudioContentPlaylistDetailActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
viewModel.detailResponseLiveData.observe(this) {
|
viewModel.detailResponseLiveData.observe(this) {
|
||||||
binding.tvDesc.text = it.desc
|
binding.tvDesc.text = it.desc
|
||||||
binding.tvTitle.text = it.title
|
binding.tvTitle.text = it.title
|
||||||
binding.tvContentCount.text = " ${it.contentCount}개"
|
binding.tvContentCount.text = getString(
|
||||||
binding.tvCreateDate.text = "만든 날짜 ${it.createdDate} "
|
R.string.audio_content_playlist_total_count,
|
||||||
|
it.contentCount
|
||||||
|
)
|
||||||
|
binding.tvCreateDate.text = getString(
|
||||||
|
R.string.audio_content_playlist_detail_created_date,
|
||||||
|
it.createdDate
|
||||||
|
)
|
||||||
adapter.updateItems(it.contentList)
|
adapter.updateItems(it.contentList)
|
||||||
this.contentList.clear()
|
this.contentList.clear()
|
||||||
this.contentList.addAll(it.contentList)
|
this.contentList.addAll(it.contentList)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.AudioContentPlaylistRepository
|
import kr.co.vividnext.sodalive.audio_content.playlist.AudioContentPlaylistRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
|
||||||
class AudioContentPlaylistDetailViewModel(
|
class AudioContentPlaylistDetailViewModel(
|
||||||
@@ -24,6 +26,14 @@ class AudioContentPlaylistDetailViewModel(
|
|||||||
val detailResponseLiveData: LiveData<GetPlaylistDetailResponse>
|
val detailResponseLiveData: LiveData<GetPlaylistDetailResponse>
|
||||||
get() = _detailResponseLiveData
|
get() = _detailResponseLiveData
|
||||||
|
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
|
private val deleteSuccessMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(
|
||||||
|
R.string.audio_content_playlist_detail_delete_success
|
||||||
|
)
|
||||||
|
|
||||||
fun getPlaylistDetail(playlistId: Long) {
|
fun getPlaylistDetail(playlistId: Long) {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
@@ -41,9 +51,7 @@ class AudioContentPlaylistDetailViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
@@ -51,7 +59,7 @@ class AudioContentPlaylistDetailViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -69,15 +77,13 @@ class AudioContentPlaylistDetailViewModel(
|
|||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
if (it.success) {
|
if (it.success) {
|
||||||
_toastLiveData.value = "삭제되었습니다."
|
_toastLiveData.value = deleteSuccessMessage
|
||||||
onSuccess()
|
onSuccess()
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
@@ -85,7 +91,7 @@ class AudioContentPlaylistDetailViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.jakewharton.rxbinding4.widget.textChanges
|
import com.jakewharton.rxbinding4.widget.textChanges
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.create.add_content.PlaylistAddContentDialogFragment
|
import kr.co.vividnext.sodalive.audio_content.playlist.create.add_content.PlaylistAddContentDialogFragment
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentPlaylistModifyBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentPlaylistModifyBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
@@ -45,7 +47,8 @@ class AudioContentPlaylistModifyActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
title = item.title,
|
title = item.title,
|
||||||
category = item.themeStr,
|
category = item.themeStr,
|
||||||
coverUrl = item.coverImageUrl,
|
coverUrl = item.coverImageUrl,
|
||||||
duration = item.duration ?: "00:00:00",
|
duration = item.duration ?: SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.screen_audio_content_upload_preview_start_time_default),
|
||||||
creatorNickname = item.creatorNickname,
|
creatorNickname = item.creatorNickname,
|
||||||
creatorProfileUrl = ""
|
creatorProfileUrl = ""
|
||||||
)
|
)
|
||||||
@@ -70,8 +73,9 @@ class AudioContentPlaylistModifyActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
if (playlistId <= 0) {
|
if (playlistId <= 0) {
|
||||||
showToast("잘못된 요청입니다.")
|
showToast(getString(R.string.screen_audio_content_error_invalid_request))
|
||||||
finish()
|
finish()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
imm = getSystemService(
|
imm = getSystemService(
|
||||||
@@ -83,7 +87,6 @@ class AudioContentPlaylistModifyActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
binding.tvBack.text = "재생목록 수정"
|
|
||||||
binding.tvBack.setOnClickListener { finish() }
|
binding.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
@@ -207,13 +210,21 @@ class AudioContentPlaylistModifyActivity : BaseActivity<ActivityAudioContentPlay
|
|||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun setTitle(title: String) {
|
private fun setTitle(title: String) {
|
||||||
binding.tvTitleLength.text = "${title.length}/30"
|
binding.tvTitleLength.text = getString(
|
||||||
|
R.string.audio_content_playlist_create_length_format,
|
||||||
|
title.length,
|
||||||
|
30
|
||||||
|
)
|
||||||
viewModel.title = title
|
viewModel.title = title
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun setDesc(desc: String) {
|
private fun setDesc(desc: String) {
|
||||||
binding.tvDescLength.text = "${desc.length}/40"
|
binding.tvDescLength.text = getString(
|
||||||
|
R.string.audio_content_playlist_create_length_format,
|
||||||
|
desc.length,
|
||||||
|
40
|
||||||
|
)
|
||||||
viewModel.desc = desc
|
viewModel.desc = desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import kr.co.vividnext.sodalive.audio_content.playlist.create.PlaylistContentIdA
|
|||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.AudioContentPlaylistContent
|
||||||
import kr.co.vividnext.sodalive.audio_content.playlist.detail.GetPlaylistDetailResponse
|
import kr.co.vividnext.sodalive.audio_content.playlist.detail.GetPlaylistDetailResponse
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AudioContentPlaylistModifyViewModel(
|
class AudioContentPlaylistModifyViewModel(
|
||||||
private val repository: AudioContentPlaylistRepository
|
private val repository: AudioContentPlaylistRepository
|
||||||
@@ -37,6 +39,9 @@ class AudioContentPlaylistModifyViewModel(
|
|||||||
var desc: String = ""
|
var desc: String = ""
|
||||||
private var playlistId: Long = 0
|
private var playlistId: Long = 0
|
||||||
|
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
fun addContent(item: AudioContentPlaylistContent) {
|
fun addContent(item: AudioContentPlaylistContent) {
|
||||||
contentList.add(item)
|
contentList.add(item)
|
||||||
_contentListLiveData.value = contentList
|
_contentListLiveData.value = contentList
|
||||||
@@ -85,7 +90,7 @@ class AudioContentPlaylistModifyViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.value = it.message
|
_toastLiveData.value = it.message
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownErrorMessage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -94,7 +99,7 @@ class AudioContentPlaylistModifyViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.value = it.message
|
_toastLiveData.value = it.message
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownErrorMessage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -104,12 +109,18 @@ class AudioContentPlaylistModifyViewModel(
|
|||||||
|
|
||||||
private fun validate(): Boolean {
|
private fun validate(): Boolean {
|
||||||
if (title.isBlank() || title.length < 3) {
|
if (title.isBlank() || title.length < 3) {
|
||||||
_toastLiveData.value = "제목을 3자 이상 입력하세요"
|
_toastLiveData.value = SodaLiveApplicationHolder.get().getString(
|
||||||
|
R.string.audio_content_playlist_create_title_min_length_error,
|
||||||
|
3
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contentList.isEmpty()) {
|
if (contentList.isEmpty()) {
|
||||||
_toastLiveData.value = "콘텐츠를 1개 이상 추가하세요"
|
_toastLiveData.value = SodaLiveApplicationHolder.get().getString(
|
||||||
|
R.string.audio_content_playlist_create_content_min_count_error,
|
||||||
|
1
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,9 +147,7 @@ class AudioContentPlaylistModifyViewModel(
|
|||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
@@ -146,7 +155,7 @@ class AudioContentPlaylistModifyViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,7 +38,10 @@ class SeriesListAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.tvTitle.text = item.title
|
binding.tvTitle.text = item.title
|
||||||
binding.tvSeriesContentCount.text = "총 ${item.numberOfContent}화"
|
binding.tvSeriesContentCount.text = binding.root.context.getString(
|
||||||
|
R.string.screen_home_series_episode_count,
|
||||||
|
item.numberOfContent
|
||||||
|
)
|
||||||
binding.tvPublishedDaysOfWeek.text = item.publishedDaysOfWeek
|
binding.tvPublishedDaysOfWeek.text = item.publishedDaysOfWeek
|
||||||
|
|
||||||
binding.tvNew.visibility = if (item.isNew) {
|
binding.tvNew.visibility = if (item.isNew) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.widget.Toast
|
|||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
|
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
|
||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
@@ -57,11 +58,11 @@ class SeriesListAllActivity : BaseActivity<ActivitySeriesListAllBinding>(
|
|||||||
loadingDialog = LoadingDialog(this, layoutInflater)
|
loadingDialog = LoadingDialog(this, layoutInflater)
|
||||||
binding.toolbar.tvBack.text =
|
binding.toolbar.tvBack.text =
|
||||||
if (intent.getBooleanExtra(Constants.EXTRA_IS_COMPLETED, false)) {
|
if (intent.getBooleanExtra(Constants.EXTRA_IS_COMPLETED, false)) {
|
||||||
"완결 시리즈"
|
getString(R.string.screen_series_main_completed_title)
|
||||||
} else if (intent.getBooleanExtra(Constants.EXTRA_IS_ORIGINAL, false)) {
|
} else if (intent.getBooleanExtra(Constants.EXTRA_IS_ORIGINAL, false)) {
|
||||||
"오직 보이스온에서만"
|
getString(R.string.voiceon_original_only)
|
||||||
} else {
|
} else {
|
||||||
"시리즈 전체보기"
|
getString(R.string.screen_series_main_title)
|
||||||
}
|
}
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import com.google.gson.annotations.SerializedName
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
|
||||||
class SeriesListAllViewModel(private val repository: SeriesRepository) : BaseViewModel() {
|
class SeriesListAllViewModel(private val repository: SeriesRepository) : BaseViewModel() {
|
||||||
|
|
||||||
@@ -34,6 +36,8 @@ class SeriesListAllViewModel(private val repository: SeriesRepository) : BaseVie
|
|||||||
var isLast = false
|
var isLast = false
|
||||||
var page = 1
|
var page = 1
|
||||||
private val size = 20
|
private val size = 20
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
fun getSeriesList() {
|
fun getSeriesList() {
|
||||||
if (!_isLoading.value!! && !isLast) {
|
if (!_isLoading.value!! && !isLast) {
|
||||||
@@ -62,12 +66,7 @@ class SeriesListAllViewModel(private val repository: SeriesRepository) : BaseVie
|
|||||||
isLast = true
|
isLast = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
_toastLiveData.value = it.message ?: unknownErrorMessage
|
||||||
_toastLiveData.value = it.message
|
|
||||||
} else {
|
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
@@ -75,7 +74,7 @@ class SeriesListAllViewModel(private val repository: SeriesRepository) : BaseVie
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class SeriesContentAdapter(
|
|||||||
} else if (item.isRented) {
|
} else if (item.isRented) {
|
||||||
binding.tvRented.visibility = View.VISIBLE
|
binding.tvRented.visibility = View.VISIBLE
|
||||||
} else if (item.price > 0) {
|
} else if (item.price > 0) {
|
||||||
binding.tvPrice.text = "${item.price}"
|
binding.tvPrice.text = item.price.toString()
|
||||||
binding.tvPrice.visibility = View.VISIBLE
|
binding.tvPrice.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
binding.tvPriceFree.visibility = View.VISIBLE
|
binding.tvPriceFree.visibility = View.VISIBLE
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ class SeriesContentAllActivity : BaseActivity<ActivitySeriesContentAllBinding>(
|
|||||||
|
|
||||||
val seriesId = intent.getLongExtra(Constants.EXTRA_SERIES_ID, 0)
|
val seriesId = intent.getLongExtra(Constants.EXTRA_SERIES_ID, 0)
|
||||||
if (seriesId <= 0) {
|
if (seriesId <= 0) {
|
||||||
Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
getString(R.string.screen_audio_content_error_invalid_request),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,9 +49,12 @@ class SeriesContentAllActivity : BaseActivity<ActivitySeriesContentAllBinding>(
|
|||||||
|
|
||||||
val seriesTitle = intent.getStringExtra(Constants.EXTRA_SERIES_TITLE) ?: ""
|
val seriesTitle = intent.getStringExtra(Constants.EXTRA_SERIES_TITLE) ?: ""
|
||||||
binding.toolbar.tvBack.text = if (seriesTitle.isNotBlank()) {
|
binding.toolbar.tvBack.text = if (seriesTitle.isNotBlank()) {
|
||||||
"$seriesTitle - 전체회차 듣기"
|
getString(
|
||||||
|
R.string.screen_series_content_all_title_format,
|
||||||
|
seriesTitle
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
" 전체회차 듣기"
|
getString(R.string.screen_series_content_all_title_default)
|
||||||
}
|
}
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import kr.co.vividnext.sodalive.audio_content.series.SeriesRepository
|
|||||||
import kr.co.vividnext.sodalive.audio_content.series.detail.GetSeriesContentListItem
|
import kr.co.vividnext.sodalive.audio_content.series.detail.GetSeriesContentListItem
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class SeriesContentAllViewModel(private val repository: SeriesRepository) : BaseViewModel() {
|
class SeriesContentAllViewModel(private val repository: SeriesRepository) : BaseViewModel() {
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<String?>()
|
||||||
@@ -33,6 +35,8 @@ class SeriesContentAllViewModel(private val repository: SeriesRepository) : Base
|
|||||||
var page = 1
|
var page = 1
|
||||||
private var pageSize = 10
|
private var pageSize = 10
|
||||||
private var isLast = false
|
private var isLast = false
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
fun getSeriesContentList() {
|
fun getSeriesContentList() {
|
||||||
if (!_isLoading.value!! && !isLast) {
|
if (!_isLoading.value!! && !isLast) {
|
||||||
@@ -59,18 +63,14 @@ class SeriesContentAllViewModel(private val repository: SeriesRepository) : Base
|
|||||||
isLast = true
|
isLast = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
_toastLiveData.value = it.message ?: unknownErrorMessage
|
||||||
_toastLiveData.value = it.message
|
|
||||||
} else {
|
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ data class GetSeriesDetailResponse(
|
|||||||
@SerializedName("writer") val writer: String?,
|
@SerializedName("writer") val writer: String?,
|
||||||
@SerializedName("studio") val studio: String?,
|
@SerializedName("studio") val studio: String?,
|
||||||
@SerializedName("publishedDate") val publishedDate: String,
|
@SerializedName("publishedDate") val publishedDate: String,
|
||||||
|
@SerializedName("publishedDateUtc") val publishedDateUtc: String,
|
||||||
@SerializedName("creator") val creator: GetSeriesDetailCreator,
|
@SerializedName("creator") val creator: GetSeriesDetailCreator,
|
||||||
@SerializedName("rentalMinPrice") var rentalMinPrice: Int,
|
@SerializedName("rentalMinPrice") var rentalMinPrice: Int,
|
||||||
@SerializedName("rentalMaxPrice") var rentalMaxPrice: Int,
|
@SerializedName("rentalMaxPrice") var rentalMaxPrice: Int,
|
||||||
@@ -26,7 +27,9 @@ data class GetSeriesDetailResponse(
|
|||||||
@SerializedName("keywordList") var keywordList: List<String>,
|
@SerializedName("keywordList") var keywordList: List<String>,
|
||||||
@SerializedName("publishedDaysOfWeek") var publishedDaysOfWeek: String,
|
@SerializedName("publishedDaysOfWeek") var publishedDaysOfWeek: String,
|
||||||
@SerializedName("contentList") val contentList: List<GetSeriesContentListItem>,
|
@SerializedName("contentList") val contentList: List<GetSeriesContentListItem>,
|
||||||
@SerializedName("contentCount") val contentCount: Int
|
@SerializedName("contentCount") val contentCount: Int,
|
||||||
|
@SerializedName("translated") val translated: TranslatedSeries?,
|
||||||
|
@SerializedName("translatedGenre") val translatedGenre: String?
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@Keep
|
@Keep
|
||||||
@@ -38,3 +41,11 @@ data class GetSeriesDetailResponse(
|
|||||||
@SerializedName("isNotify") var isNotify: Boolean
|
@SerializedName("isNotify") var isNotify: Boolean
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
@Keep
|
||||||
|
data class TranslatedSeries(
|
||||||
|
@SerializedName("title") val title: String,
|
||||||
|
@SerializedName("introduction") val introduction: String,
|
||||||
|
@SerializedName("keywords") val keywords: List<String>
|
||||||
|
) : Parcelable
|
||||||
|
|||||||
@@ -38,7 +38,11 @@ class SeriesDetailActivity : BaseActivity<ActivitySeriesDetailBinding>(
|
|||||||
|
|
||||||
val seriesId = intent.getLongExtra(Constants.EXTRA_SERIES_ID, 0)
|
val seriesId = intent.getLongExtra(Constants.EXTRA_SERIES_ID, 0)
|
||||||
if (seriesId <= 0) {
|
if (seriesId <= 0) {
|
||||||
Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show()
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
getString(R.string.screen_audio_content_error_invalid_request),
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,8 +61,14 @@ class SeriesDetailActivity : BaseActivity<ActivitySeriesDetailBinding>(
|
|||||||
|
|
||||||
private fun setupTab() {
|
private fun setupTab() {
|
||||||
val tabs = binding.tabs
|
val tabs = binding.tabs
|
||||||
tabs.addTab(tabs.newTab().setText("홈").setTag("home"))
|
tabs.addTab(
|
||||||
tabs.addTab(tabs.newTab().setText("작품소개").setTag("introduction"))
|
tabs.newTab().setText(R.string.screen_series_detail_tab_home).setTag("home")
|
||||||
|
)
|
||||||
|
tabs.addTab(
|
||||||
|
tabs.newTab()
|
||||||
|
.setText(R.string.screen_series_detail_tab_introduction)
|
||||||
|
.setTag("introduction")
|
||||||
|
)
|
||||||
|
|
||||||
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||||
@@ -108,10 +118,13 @@ class SeriesDetailActivity : BaseActivity<ActivitySeriesDetailBinding>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.seriesDetailLiveData.observe(this) {
|
viewModel.seriesDetailLiveData.observe(this) {
|
||||||
|
// GetSeriesDetailResponse에 추가한대로 번역 데이터가 있으면 번역데이터 표시
|
||||||
|
// 없으면 지금과 동일하게 원본 데이터 표시
|
||||||
setSeriesBg(it.coverImage)
|
setSeriesBg(it.coverImage)
|
||||||
setSeriesInfo(it)
|
setSeriesInfo(it)
|
||||||
setSeriesCreator(it.creator)
|
setSeriesCreator(it.creator)
|
||||||
setSeriesKeywordChipList(it.keywordList)
|
// 번역 키워드가 있으면 번역 키워드 표시, 없으면 기존 키워드 표시
|
||||||
|
setSeriesKeywordChipList(it.translated?.keywords ?: it.keywordList)
|
||||||
|
|
||||||
changeFragment("home")
|
changeFragment("home")
|
||||||
}
|
}
|
||||||
@@ -137,7 +150,7 @@ class SeriesDetailActivity : BaseActivity<ActivitySeriesDetailBinding>(
|
|||||||
|
|
||||||
chip.setPadding(0, 0, 0, 0)
|
chip.setPadding(0, 0, 0, 0)
|
||||||
chip.setTextColor(ContextCompat.getColor(applicationContext, R.color.color_d2d2d2))
|
chip.setTextColor(ContextCompat.getColor(applicationContext, R.color.color_d2d2d2))
|
||||||
chip.typeface = ResourcesCompat.getFont(applicationContext, R.font.gmarket_sans_medium)
|
chip.typeface = ResourcesCompat.getFont(applicationContext, R.font.medium)
|
||||||
binding.chipGroup.addView(chip)
|
binding.chipGroup.addView(chip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,9 +163,23 @@ class SeriesDetailActivity : BaseActivity<ActivitySeriesDetailBinding>(
|
|||||||
transformations(RoundedCornersTransformation(5f.dpToPx()))
|
transformations(RoundedCornersTransformation(5f.dpToPx()))
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.tvTitle.text = seriesDetail.title
|
// 번역 데이터 사용 우선, 없으면 원본 사용
|
||||||
binding.tvGenre.text = seriesDetail.genre
|
val displayTitle = seriesDetail.translated?.title?.takeIf { it.isNotBlank() }
|
||||||
binding.tvPublishedDaysOfWeek.text = "${seriesDetail.publishedDaysOfWeek} 연재"
|
?: seriesDetail.title
|
||||||
|
val displayGenre = seriesDetail.translatedGenre?.takeIf { it.isNotBlank() }
|
||||||
|
?: seriesDetail.genre
|
||||||
|
|
||||||
|
binding.tvTitle.text = displayTitle
|
||||||
|
binding.tvGenre.text = displayGenre
|
||||||
|
val publishedDays = if (seriesDetail.publishedDaysOfWeek == getString(R.string.day_random)) {
|
||||||
|
getString(R.string.day_random)
|
||||||
|
} else {
|
||||||
|
seriesDetail.publishedDaysOfWeek
|
||||||
|
}
|
||||||
|
binding.tvPublishedDaysOfWeek.text = getString(
|
||||||
|
R.string.screen_series_detail_published_days_format,
|
||||||
|
publishedDays
|
||||||
|
)
|
||||||
|
|
||||||
if (seriesDetail.isAdult) {
|
if (seriesDetail.isAdult) {
|
||||||
binding.tvAge19.visibility = View.VISIBLE
|
binding.tvAge19.visibility = View.VISIBLE
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ import android.content.Intent
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.content.SeriesContentAdapter
|
import kr.co.vividnext.sodalive.audio_content.series.content.SeriesContentAdapter
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.content.SeriesContentAllActivity
|
import kr.co.vividnext.sodalive.audio_content.series.content.SeriesContentAllActivity
|
||||||
@@ -44,9 +47,12 @@ class SeriesDetailHomeFragment : BaseFragment<FragmentSeriesDetailHomeBinding>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@OptIn(UnstableApi::class)
|
||||||
private fun setContent() {
|
private fun setContent() {
|
||||||
binding.tvTotalCount.text = "(${seriesDetailResponse!!.contentCount})"
|
binding.tvTotalCount.text = getString(
|
||||||
|
R.string.screen_series_detail_content_count_format,
|
||||||
|
seriesDetailResponse!!.contentCount
|
||||||
|
)
|
||||||
binding.llContentAll.setOnClickListener {
|
binding.llContentAll.setOnClickListener {
|
||||||
startActivity(
|
startActivity(
|
||||||
Intent(requireActivity(), SeriesContentAllActivity::class.java).apply {
|
Intent(requireActivity(), SeriesContentAllActivity::class.java).apply {
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import kr.co.vividnext.sodalive.base.BaseFragment
|
|||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
import kr.co.vividnext.sodalive.databinding.FragmentSeriesDetailIntroductionBinding
|
import kr.co.vividnext.sodalive.databinding.FragmentSeriesDetailIntroductionBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
class SeriesDetailIntroductionFragment : BaseFragment<FragmentSeriesDetailIntroductionBinding>(
|
class SeriesDetailIntroductionFragment : BaseFragment<FragmentSeriesDetailIntroductionBinding>(
|
||||||
FragmentSeriesDetailIntroductionBinding::inflate
|
FragmentSeriesDetailIntroductionBinding::inflate
|
||||||
@@ -38,8 +41,15 @@ class SeriesDetailIntroductionFragment : BaseFragment<FragmentSeriesDetailIntrod
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
if (seriesDetailResponse != null) {
|
if (seriesDetailResponse != null) {
|
||||||
setSeriesKeywordChipList(seriesDetailResponse!!.keywordList)
|
// 번역 데이터가 있으면 번역 데이터 우선 적용
|
||||||
setSeriesIntroduction(seriesDetailResponse!!.introduction)
|
setSeriesKeywordChipList(
|
||||||
|
seriesDetailResponse!!.translated?.keywords
|
||||||
|
?: seriesDetailResponse!!.keywordList
|
||||||
|
)
|
||||||
|
setSeriesIntroduction(
|
||||||
|
seriesDetailResponse!!.translated?.introduction
|
||||||
|
?: seriesDetailResponse!!.introduction
|
||||||
|
)
|
||||||
setSeriesPrice()
|
setSeriesPrice()
|
||||||
setSeriesInfo()
|
setSeriesInfo()
|
||||||
}
|
}
|
||||||
@@ -53,41 +63,63 @@ class SeriesDetailIntroductionFragment : BaseFragment<FragmentSeriesDetailIntrod
|
|||||||
|
|
||||||
binding.tvRentalPrice.text = if (rentalMinPrice == rentalMaxPrice) {
|
binding.tvRentalPrice.text = if (rentalMinPrice == rentalMaxPrice) {
|
||||||
if (rentalMaxPrice == 0) {
|
if (rentalMaxPrice == 0) {
|
||||||
"무료(5일)"
|
getString(R.string.screen_series_detail_price_rental_free)
|
||||||
} else {
|
} else {
|
||||||
"$rentalMaxPrice(5일)"
|
getString(R.string.screen_series_detail_price_rental_single, rentalMaxPrice)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"${if (rentalMinPrice == 0) "무료" else rentalMinPrice} ~ ${rentalMaxPrice}캔 (5일)"
|
val minText = if (rentalMinPrice == 0) {
|
||||||
|
getString(R.string.audio_content_price_free)
|
||||||
|
} else {
|
||||||
|
rentalMinPrice.toString()
|
||||||
|
}
|
||||||
|
getString(
|
||||||
|
R.string.screen_series_detail_price_rental_range,
|
||||||
|
minText,
|
||||||
|
rentalMaxPrice
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.tvPrice.text = if (minPrice == maxPrice) {
|
binding.tvPrice.text = if (minPrice == maxPrice) {
|
||||||
if (maxPrice == 0) {
|
if (maxPrice == 0) {
|
||||||
"무료"
|
getString(R.string.audio_content_price_free)
|
||||||
} else {
|
} else {
|
||||||
"$maxPrice"
|
getString(R.string.screen_series_detail_price_keep_single, maxPrice)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"${if (minPrice == 0) "무료" else minPrice} ~ ${maxPrice}캔"
|
val minText = if (minPrice == 0) {
|
||||||
|
getString(R.string.audio_content_price_free)
|
||||||
|
} else {
|
||||||
|
minPrice.toString()
|
||||||
|
}
|
||||||
|
getString(R.string.screen_series_detail_price_keep_range, minText, maxPrice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun setSeriesInfo() {
|
private fun setSeriesInfo() {
|
||||||
binding.tvGenre.text = seriesDetailResponse!!.genre
|
// 장르는 번역 데이터가 있으면 번역 장르 사용
|
||||||
|
binding.tvGenre.text =
|
||||||
|
seriesDetailResponse!!.translatedGenre ?: seriesDetailResponse!!.genre
|
||||||
binding.tvIsAdult.text = if (seriesDetailResponse!!.isAdult) {
|
binding.tvIsAdult.text = if (seriesDetailResponse!!.isAdult) {
|
||||||
"19세 이상"
|
getString(R.string.screen_series_detail_age_19)
|
||||||
} else {
|
} else {
|
||||||
"전체연령가"
|
getString(R.string.screen_series_detail_age_all)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.tvPublishedDate.text = seriesDetailResponse!!.publishedDate
|
// 공개일은 publishedDateUtc(UTC)를 단말 타임존으로 변환하여 표시
|
||||||
binding.tvPublishedDaysOfWeek.text =
|
binding.tvPublishedDate.text =
|
||||||
if (seriesDetailResponse!!.publishedDaysOfWeek == "랜덤") {
|
formatPublishedDateUtc(seriesDetailResponse!!.publishedDateUtc)
|
||||||
seriesDetailResponse!!.publishedDaysOfWeek
|
val publishedDays =
|
||||||
|
if (seriesDetailResponse!!.publishedDaysOfWeek == getString(R.string.day_random)) {
|
||||||
|
getString(R.string.day_random)
|
||||||
} else {
|
} else {
|
||||||
seriesDetailResponse!!.publishedDaysOfWeek
|
seriesDetailResponse!!.publishedDaysOfWeek
|
||||||
}
|
}
|
||||||
|
binding.tvPublishedDaysOfWeek.text = getString(
|
||||||
|
R.string.screen_series_detail_published_days_format,
|
||||||
|
publishedDays
|
||||||
|
)
|
||||||
|
|
||||||
if (seriesDetailResponse!!.writer != null) {
|
if (seriesDetailResponse!!.writer != null) {
|
||||||
binding.tvWriter.visibility = View.VISIBLE
|
binding.tvWriter.visibility = View.VISIBLE
|
||||||
@@ -110,6 +142,26 @@ class SeriesDetailIntroductionFragment : BaseFragment<FragmentSeriesDetailIntrod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun formatPublishedDateUtc(utcString: String): String {
|
||||||
|
return try {
|
||||||
|
val utcFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault()).apply {
|
||||||
|
timeZone = TimeZone.getTimeZone("UTC")
|
||||||
|
}
|
||||||
|
val date = utcFormat.parse(utcString)
|
||||||
|
if (date != null) {
|
||||||
|
val localFormat = SimpleDateFormat("yyyy.MM.dd", Locale.getDefault()).apply {
|
||||||
|
timeZone = TimeZone.getDefault()
|
||||||
|
}
|
||||||
|
localFormat.format(date)
|
||||||
|
} else {
|
||||||
|
// 파싱 실패 시 서버에서 제공한 기존 publishedDate로 폴백
|
||||||
|
seriesDetailResponse?.publishedDate ?: utcString
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
seriesDetailResponse?.publishedDate ?: utcString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setSeriesIntroduction(introduction: String) {
|
private fun setSeriesIntroduction(introduction: String) {
|
||||||
binding.tvIntroduce.text = introduction
|
binding.tvIntroduce.text = introduction
|
||||||
}
|
}
|
||||||
@@ -134,7 +186,7 @@ class SeriesDetailIntroductionFragment : BaseFragment<FragmentSeriesDetailIntrod
|
|||||||
chip.setEnsureMinTouchTargetSize(false)
|
chip.setEnsureMinTouchTargetSize(false)
|
||||||
chip.setPadding(0, 0, 0, 0)
|
chip.setPadding(0, 0, 0, 0)
|
||||||
chip.setTextColor(ContextCompat.getColor(requireContext(), R.color.color_d2d2d2))
|
chip.setTextColor(ContextCompat.getColor(requireContext(), R.color.color_d2d2d2))
|
||||||
chip.typeface = ResourcesCompat.getFont(requireContext(), R.font.gmarket_sans_medium)
|
chip.typeface = ResourcesCompat.getFont(requireContext(), R.font.medium)
|
||||||
binding.chipGroup.addView(chip)
|
binding.chipGroup.addView(chip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.SeriesRepository
|
import kr.co.vividnext.sodalive.audio_content.series.SeriesRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.user.UserRepository
|
import kr.co.vividnext.sodalive.user.UserRepository
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
|
||||||
class SeriesDetailViewModel(
|
class SeriesDetailViewModel(
|
||||||
private val repository: SeriesRepository,
|
private val repository: SeriesRepository,
|
||||||
@@ -29,6 +31,8 @@ class SeriesDetailViewModel(
|
|||||||
var seriesId = 0L
|
var seriesId = 0L
|
||||||
|
|
||||||
lateinit var seriesDetailResponse: GetSeriesDetailResponse
|
lateinit var seriesDetailResponse: GetSeriesDetailResponse
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
fun getSeriesDetail() {
|
fun getSeriesDetail() {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
@@ -46,18 +50,14 @@ class SeriesDetailViewModel(
|
|||||||
seriesDetailResponse = it.data
|
seriesDetailResponse = it.data
|
||||||
_seriesDetailLiveData.value = seriesDetailResponse
|
_seriesDetailLiveData.value = seriesDetailResponse
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
_toastLiveData.value = it.message ?: unknownErrorMessage
|
||||||
_toastLiveData.value = it.message
|
|
||||||
} else {
|
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -84,20 +84,14 @@ class SeriesDetailViewModel(
|
|||||||
if (it.success && it.data != null) {
|
if (it.success && it.data != null) {
|
||||||
onSuccess()
|
onSuccess()
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
_toastLiveData.postValue(it.message ?: unknownErrorMessage)
|
||||||
_toastLiveData.postValue(it.message)
|
|
||||||
} else {
|
|
||||||
_toastLiveData.postValue(
|
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,16 +14,22 @@ class SeriesMainActivity : BaseActivity<ActivitySeriesMainBinding>(
|
|||||||
private var currentTab = 0
|
private var currentTab = 0
|
||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
binding.toolbar.tvBack.text = "시리즈 전체보기"
|
binding.toolbar.tvBack.text = getString(R.string.screen_series_main_title)
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
|
|
||||||
setupTabs()
|
setupTabs()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTabs() {
|
private fun setupTabs() {
|
||||||
binding.tabLayout.addTab(binding.tabLayout.newTab().setText("홈"))
|
binding.tabLayout.addTab(
|
||||||
binding.tabLayout.addTab(binding.tabLayout.newTab().setText("요일별"))
|
binding.tabLayout.newTab().setText(R.string.screen_series_main_tab_home)
|
||||||
binding.tabLayout.addTab(binding.tabLayout.newTab().setText("장르별"))
|
)
|
||||||
|
binding.tabLayout.addTab(
|
||||||
|
binding.tabLayout.newTab().setText(R.string.screen_series_main_tab_day_of_week)
|
||||||
|
)
|
||||||
|
binding.tabLayout.addTab(
|
||||||
|
binding.tabLayout.newTab().setText(R.string.screen_series_main_tab_genre)
|
||||||
|
)
|
||||||
|
|
||||||
// 탭 선택 리스너 설정
|
// 탭 선택 리스너 설정
|
||||||
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.main.SeriesMainRepository
|
import kr.co.vividnext.sodalive.audio_content.series.main.SeriesMainRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
|
||||||
class SeriesMainByGenreViewModel(
|
class SeriesMainByGenreViewModel(
|
||||||
private val repository: SeriesMainRepository
|
private val repository: SeriesMainRepository
|
||||||
@@ -36,6 +38,9 @@ class SeriesMainByGenreViewModel(
|
|||||||
val selectedGenreId: Long?
|
val selectedGenreId: Long?
|
||||||
get() = _selectedGenreId
|
get() = _selectedGenreId
|
||||||
|
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
fun loadGenres() {
|
fun loadGenres() {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
@@ -59,12 +64,12 @@ class SeriesMainByGenreViewModel(
|
|||||||
_genreListLiveData.value = emptyList()
|
_genreListLiveData.value = emptyList()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = it.message ?: unknownErrorMessage
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownErrorMessage
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -108,12 +113,12 @@ class SeriesMainByGenreViewModel(
|
|||||||
isLast = true
|
isLast = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = it.message ?: unknownErrorMessage
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownErrorMessage
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import android.widget.Toast
|
|||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.SeriesListAdapter
|
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
|
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
|
||||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
@@ -61,7 +60,7 @@ class SeriesMainDayOfWeekFragment : BaseFragment<FragmentSeriesMainDayOfWeekBind
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupDayOfWeekDay() {
|
private fun setupDayOfWeekDay() {
|
||||||
val dayOfWeekAdapter = DayOfWeekAdapter(screenWidth = screenWidth) {
|
val dayOfWeekAdapter = DayOfWeekAdapter(requireContext()) {
|
||||||
adapter.clear()
|
adapter.clear()
|
||||||
viewModel.dayOfWeek = it
|
viewModel.dayOfWeek = it
|
||||||
}
|
}
|
||||||
@@ -73,7 +72,7 @@ class SeriesMainDayOfWeekFragment : BaseFragment<FragmentSeriesMainDayOfWeekBind
|
|||||||
false
|
false
|
||||||
) {
|
) {
|
||||||
override fun canScrollVertically() = false
|
override fun canScrollVertically() = false
|
||||||
override fun canScrollHorizontally() = false
|
override fun canScrollHorizontally() = true
|
||||||
}
|
}
|
||||||
rvDayOfWeek.layoutManager = layoutManager
|
rvDayOfWeek.layoutManager = layoutManager
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.main.SeriesMainRepository
|
import kr.co.vividnext.sodalive.audio_content.series.main.SeriesMainRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.home.SeriesPublishedDaysOfWeek
|
import kr.co.vividnext.sodalive.home.SeriesPublishedDaysOfWeek
|
||||||
|
|
||||||
class SeriesMainDayOfWeekViewModel(
|
class SeriesMainDayOfWeekViewModel(
|
||||||
@@ -30,6 +32,9 @@ class SeriesMainDayOfWeekViewModel(
|
|||||||
private var isLast = false
|
private var isLast = false
|
||||||
private val pageSize = 20
|
private val pageSize = 20
|
||||||
|
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
var dayOfWeek = SeriesPublishedDaysOfWeek.RANDOM
|
var dayOfWeek = SeriesPublishedDaysOfWeek.RANDOM
|
||||||
set(newValue) {
|
set(newValue) {
|
||||||
if (field != newValue) {
|
if (field != newValue) {
|
||||||
@@ -67,17 +72,13 @@ class SeriesMainDayOfWeekViewModel(
|
|||||||
isLast = true
|
isLast = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
_toastLiveData.value = it.message ?: unknownErrorMessage
|
||||||
_toastLiveData.value = it.message
|
|
||||||
} else {
|
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownErrorMessage
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.main.SeriesMainRepository
|
import kr.co.vividnext.sodalive.audio_content.series.main.SeriesMainRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
|
||||||
class SeriesMainHomeViewModel(
|
class SeriesMainHomeViewModel(
|
||||||
private val repository: SeriesMainRepository
|
private val repository: SeriesMainRepository
|
||||||
@@ -35,6 +37,9 @@ class SeriesMainHomeViewModel(
|
|||||||
val recommendSeriesLiveData: LiveData<List<GetSeriesListResponse.SeriesListItem>>
|
val recommendSeriesLiveData: LiveData<List<GetSeriesListResponse.SeriesListItem>>
|
||||||
get() = _recommendSeriesLiveData
|
get() = _recommendSeriesLiveData
|
||||||
|
|
||||||
|
private val unknownErrorMessage: String
|
||||||
|
get() = SodaLiveApplicationHolder.get().getString(R.string.common_error_unknown)
|
||||||
|
|
||||||
fun fetchData() {
|
fun fetchData() {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
|
|
||||||
@@ -52,19 +57,13 @@ class SeriesMainHomeViewModel(
|
|||||||
_completedSeriesLiveData.value = data.completedSeriesList
|
_completedSeriesLiveData.value = data.completedSeriesList
|
||||||
_recommendSeriesLiveData.value = data.recommendSeriesList
|
_recommendSeriesLiveData.value = data.recommendSeriesList
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
_toastLiveData.postValue(it.message ?: unknownErrorMessage)
|
||||||
_toastLiveData.postValue(it.message)
|
|
||||||
} else {
|
|
||||||
_toastLiveData.postValue(
|
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(unknownErrorMessage)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -83,17 +82,13 @@ class SeriesMainHomeViewModel(
|
|||||||
if (it.success && it.data != null) {
|
if (it.success && it.data != null) {
|
||||||
_recommendSeriesLiveData.value = it.data
|
_recommendSeriesLiveData.value = it.data
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
_toastLiveData.value = it.message ?: unknownErrorMessage
|
||||||
_toastLiveData.value = it.message
|
|
||||||
} else {
|
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value = unknownErrorMessage
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content.upload
|
package kr.co.vividnext.sodalive.audio_content.upload
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.DatePickerDialog
|
import android.app.DatePickerDialog
|
||||||
import android.app.TimePickerDialog
|
import android.app.TimePickerDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -32,6 +31,7 @@ import kr.co.vividnext.sodalive.common.ImagePickerCropper
|
|||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
import kr.co.vividnext.sodalive.common.RealPathUtil
|
import kr.co.vividnext.sodalive.common.RealPathUtil
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentUploadBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAudioContentUploadBinding
|
||||||
import kr.co.vividnext.sodalive.dialog.LiveDialog
|
import kr.co.vividnext.sodalive.dialog.LiveDialog
|
||||||
import kr.co.vividnext.sodalive.dialog.SodaLiveTimePickerDialog
|
import kr.co.vividnext.sodalive.dialog.SodaLiveTimePickerDialog
|
||||||
@@ -84,16 +84,17 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
"잘못된 파일입니다.\n다시 선택해 주세요.",
|
getString(R.string.audio_content_upload_error_invalid_file),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.tvSelectContent.text = "파일 선택"
|
binding.tvSelectContent.text =
|
||||||
|
getString(R.string.screen_audio_content_upload_select_file)
|
||||||
viewModel.contentUri = null
|
viewModel.contentUri = null
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
"파일 선택을 실패했습니다.\n다시 시도해 주세요.",
|
getString(R.string.audio_content_upload_error_select_file),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
@@ -177,11 +178,11 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
)
|
)
|
||||||
|
|
||||||
binding.tvServiceDate.text = if (SharedPreferenceManager.userId == 17958L) {
|
binding.tvServiceDate.text = if (SharedPreferenceManager.userId == 17958L) {
|
||||||
"※ 이용기간 : 대여(5일) | 소장(이용 기간 1년)"
|
getString(R.string.screen_audio_content_upload_service_period_one_year)
|
||||||
} else {
|
} else {
|
||||||
"※ 이용기간 : 대여(5일) | 소장(서비스 종료시까지)"
|
getString(R.string.screen_audio_content_upload_service_period_until_end)
|
||||||
}
|
}
|
||||||
binding.toolbar.tvBack.text = "콘텐츠 등록"
|
binding.toolbar.tvBack.text = getString(R.string.screen_audio_content_upload_title)
|
||||||
binding.toolbar.tvBack.setOnClickListener { finish() }
|
binding.toolbar.tvBack.setOnClickListener { finish() }
|
||||||
binding.llTheme.setOnClickListener {
|
binding.llTheme.setOnClickListener {
|
||||||
if (themeFragment.isAdded) return@setOnClickListener
|
if (themeFragment.isAdded) return@setOnClickListener
|
||||||
@@ -200,7 +201,7 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
selectAudioActivityResultLauncher.launch(
|
selectAudioActivityResultLauncher.launch(
|
||||||
Intent.createChooser(
|
Intent.createChooser(
|
||||||
intent,
|
intent,
|
||||||
"Select Audio"
|
getString(R.string.audio_content_upload_select_audio_title)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -235,11 +236,9 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
LiveDialog(
|
LiveDialog(
|
||||||
activity = this,
|
activity = this,
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "콘텐츠 업로드",
|
title = getString(R.string.audio_content_upload_dialog_title),
|
||||||
desc = "등록한 콘텐츠가 업로드 중입니다.\n" +
|
desc = getString(R.string.audio_content_upload_dialog_desc),
|
||||||
"콘텐츠 등록이 완료되면 알림을 보내드립니다.\n" +
|
confirmButtonTitle = getString(R.string.confirm),
|
||||||
"이 페이지를 나가도 콘텐츠는 자동으로 등록됩니다.",
|
|
||||||
confirmButtonTitle = "확인",
|
|
||||||
confirmButtonClick = { finish() },
|
confirmButtonClick = { finish() },
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
}
|
}
|
||||||
@@ -309,6 +308,13 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
|
|
||||||
timePicker.show()
|
timePicker.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.setReservationDate(
|
||||||
|
getString(R.string.screen_audio_content_upload_reservation_date_placeholder)
|
||||||
|
)
|
||||||
|
viewModel.setReservationTime(
|
||||||
|
getString(R.string.screen_audio_content_upload_reservation_time_placeholder)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPermissions() {
|
private fun checkPermissions() {
|
||||||
@@ -332,8 +338,12 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
.check()
|
.check()
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
|
binding.tvNumberOfCharacters.text = getString(
|
||||||
|
R.string.screen_audio_content_upload_char_count_format,
|
||||||
|
binding.etDetail.text?.length ?: 0
|
||||||
|
)
|
||||||
|
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
binding.etTitle.textChanges().skip(1)
|
binding.etTitle.textChanges().skip(1)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
@@ -348,7 +358,10 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe {
|
.subscribe {
|
||||||
binding.tvNumberOfCharacters.text = "${it.length}자"
|
binding.tvNumberOfCharacters.text = getString(
|
||||||
|
R.string.screen_audio_content_upload_char_count_format,
|
||||||
|
it.length
|
||||||
|
)
|
||||||
viewModel.detail = it.toString()
|
viewModel.detail = it.toString()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -424,13 +437,21 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
viewModel.toastLiveData.observe(this) {
|
viewModel.toastLiveData.observe(this) { toastMessage ->
|
||||||
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
|
toastMessage?.let {
|
||||||
|
val message = it.message ?: it.resId?.let(::getString)
|
||||||
|
message?.let { text ->
|
||||||
|
Toast.makeText(applicationContext, text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.isLoading.observe(this) {
|
viewModel.isLoading.observe(this) {
|
||||||
if (it) {
|
if (it) {
|
||||||
loadingDialog.show(screenWidth, "콘텐츠를 업로드 하는 중입니다.")
|
loadingDialog.show(
|
||||||
|
screenWidth,
|
||||||
|
getString(R.string.screen_audio_content_upload_loading_message)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
loadingDialog.dismiss()
|
loadingDialog.dismiss()
|
||||||
}
|
}
|
||||||
@@ -647,7 +668,7 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
|
|
||||||
private fun checkPriceFree() {
|
private fun checkPriceFree() {
|
||||||
viewModel.price = 0
|
viewModel.price = 0
|
||||||
binding.etSetPrice.setText("0")
|
binding.etSetPrice.setText(SodaLiveApplicationHolder.get().getString(R.string.common_zero))
|
||||||
binding.llSetPrice.visibility = View.GONE
|
binding.llSetPrice.visibility = View.GONE
|
||||||
binding.llConfigPurchase.visibility = View.GONE
|
binding.llConfigPurchase.visibility = View.GONE
|
||||||
binding.tvTitleConfigKeep.visibility = View.GONE
|
binding.tvTitleConfigKeep.visibility = View.GONE
|
||||||
@@ -876,7 +897,8 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
|
|
||||||
private fun checkBoth() {
|
private fun checkBoth() {
|
||||||
uncheckPurchaseOption()
|
uncheckPurchaseOption()
|
||||||
binding.tvPriceTitle.text = "소장 가격"
|
binding.tvPriceTitle.text =
|
||||||
|
getString(R.string.screen_audio_content_upload_price_title_keep)
|
||||||
binding.ivBoth.visibility = View.VISIBLE
|
binding.ivBoth.visibility = View.VISIBLE
|
||||||
binding.tvBoth.setTextColor(
|
binding.tvBoth.setTextColor(
|
||||||
ContextCompat.getColor(
|
ContextCompat.getColor(
|
||||||
@@ -889,7 +911,8 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
|
|
||||||
private fun checkBuyOnly() {
|
private fun checkBuyOnly() {
|
||||||
uncheckPurchaseOption()
|
uncheckPurchaseOption()
|
||||||
binding.tvPriceTitle.text = "소장 가격"
|
binding.tvPriceTitle.text =
|
||||||
|
getString(R.string.screen_audio_content_upload_price_title_keep)
|
||||||
binding.ivBuyOnly.visibility = View.VISIBLE
|
binding.ivBuyOnly.visibility = View.VISIBLE
|
||||||
binding.tvBuyOnly.setTextColor(
|
binding.tvBuyOnly.setTextColor(
|
||||||
ContextCompat.getColor(
|
ContextCompat.getColor(
|
||||||
@@ -902,7 +925,8 @@ class AudioContentUploadActivity : BaseActivity<ActivityAudioContentUploadBindin
|
|||||||
|
|
||||||
private fun checkRentOnly() {
|
private fun checkRentOnly() {
|
||||||
uncheckPurchaseOption()
|
uncheckPurchaseOption()
|
||||||
binding.tvPriceTitle.text = "대여 가격"
|
binding.tvPriceTitle.text =
|
||||||
|
getString(R.string.screen_audio_content_upload_price_title_rent)
|
||||||
binding.ivRentOnly.visibility = View.VISIBLE
|
binding.ivRentOnly.visibility = View.VISIBLE
|
||||||
binding.tvRentOnly.setTextColor(
|
binding.tvRentOnly.setTextColor(
|
||||||
ContextCompat.getColor(
|
ContextCompat.getColor(
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
|||||||
import kr.co.vividnext.sodalive.audio_content.PurchaseOption
|
import kr.co.vividnext.sodalive.audio_content.PurchaseOption
|
||||||
import kr.co.vividnext.sodalive.audio_content.upload.theme.GetAudioContentThemeResponse
|
import kr.co.vividnext.sodalive.audio_content.upload.theme.GetAudioContentThemeResponse
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
@@ -27,8 +29,8 @@ class AudioContentUploadViewModel(
|
|||||||
private val repository: AudioContentRepository
|
private val repository: AudioContentRepository
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<ToastMessage?>()
|
||||||
val toastLiveData: LiveData<String?>
|
val toastLiveData: LiveData<ToastMessage?>
|
||||||
get() = _toastLiveData
|
get() = _toastLiveData
|
||||||
|
|
||||||
private var _isLoading = MutableLiveData(false)
|
private var _isLoading = MutableLiveData(false)
|
||||||
@@ -71,11 +73,11 @@ class AudioContentUploadViewModel(
|
|||||||
val isActiveReservationLiveData: LiveData<Boolean>
|
val isActiveReservationLiveData: LiveData<Boolean>
|
||||||
get() = _isActiveReservationLiveData
|
get() = _isActiveReservationLiveData
|
||||||
|
|
||||||
private val _reservationDateLiveData = MutableLiveData("날짜를 선택해주세요")
|
private val _reservationDateLiveData = MutableLiveData("")
|
||||||
val reservationDateLiveData: LiveData<String>
|
val reservationDateLiveData: LiveData<String>
|
||||||
get() = _reservationDateLiveData
|
get() = _reservationDateLiveData
|
||||||
|
|
||||||
private val _reservationTimeLiveData = MutableLiveData("시간을 설정해주세요")
|
private val _reservationTimeLiveData = MutableLiveData("")
|
||||||
val reservationTimeLiveData: LiveData<String>
|
val reservationTimeLiveData: LiveData<String>
|
||||||
get() = _reservationTimeLiveData
|
get() = _reservationTimeLiveData
|
||||||
|
|
||||||
@@ -262,12 +264,16 @@ class AudioContentUploadViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (coverImage == null) {
|
if (coverImage == null) {
|
||||||
_toastLiveData.postValue("커버이미지를 선택해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_cover_required)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contentFile == null) {
|
if (contentFile == null) {
|
||||||
_toastLiveData.postValue("오디오 콘텐츠를 선택해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_content_required)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,10 +292,12 @@ class AudioContentUploadViewModel(
|
|||||||
onSuccess()
|
onSuccess()
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(message = it.message)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,7 +307,7 @@ class AudioContentUploadViewModel(
|
|||||||
_isLoading.postValue(false)
|
_isLoading.postValue(false)
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -309,48 +317,64 @@ class AudioContentUploadViewModel(
|
|||||||
|
|
||||||
private fun validateData(): Boolean {
|
private fun validateData(): Boolean {
|
||||||
if (title.isBlank()) {
|
if (title.isBlank()) {
|
||||||
_toastLiveData.postValue("제목을 입력해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_title_required)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detail.isBlank() || detail.length < 5) {
|
if (detail.isBlank() || detail.length < 5) {
|
||||||
_toastLiveData.postValue("내용을 5자 이상 입력해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_detail_min_length)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theme == null) {
|
if (theme == null) {
|
||||||
_toastLiveData.postValue("테마를 선택해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_theme_required)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coverImageFile == null) {
|
if (coverImageFile == null) {
|
||||||
_toastLiveData.postValue("커버이미지를 선택해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_cover_required)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (previewStartTime != null && previewEndTime != null) {
|
if (previewStartTime != null && previewEndTime != null) {
|
||||||
val startTimeArray = previewStartTime!!.split(":")
|
val startTimeArray = previewStartTime!!.split(":")
|
||||||
if (startTimeArray.size != 3) {
|
if (startTimeArray.size != 3) {
|
||||||
_toastLiveData.postValue("미리 듣기 시간 형식은 00:30:00 과 같아야 합니다")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_preview_format)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for (time in startTimeArray) {
|
for (time in startTimeArray) {
|
||||||
if (time.length != 2) {
|
if (time.length != 2) {
|
||||||
_toastLiveData.postValue("미리 듣기 시간 형식은 00:30:00 과 같아야 합니다")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_preview_format)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val endTimeArray = previewEndTime!!.split(":")
|
val endTimeArray = previewEndTime!!.split(":")
|
||||||
if (endTimeArray.size != 3) {
|
if (endTimeArray.size != 3) {
|
||||||
_toastLiveData.postValue("미리 듣기 시간 형식은 00:30:00 과 같아야 합니다")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_preview_format)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for (time in endTimeArray) {
|
for (time in endTimeArray) {
|
||||||
if (time.length != 2) {
|
if (time.length != 2) {
|
||||||
_toastLiveData.postValue("미리 듣기 시간 형식은 00:30:00 과 같아야 합니다")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_preview_format)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,7 +383,7 @@ class AudioContentUploadViewModel(
|
|||||||
|
|
||||||
if (timeDifference < 15000) {
|
if (timeDifference < 15000) {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"미리 듣기의 최소 시간은 15초 입니다."
|
ToastMessage(resId = R.string.audio_content_upload_error_preview_minimum)
|
||||||
)
|
)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@@ -367,7 +391,9 @@ class AudioContentUploadViewModel(
|
|||||||
} else {
|
} else {
|
||||||
if (previewStartTime != null || previewEndTime != null) {
|
if (previewStartTime != null || previewEndTime != null) {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"미리 듣기 시작 시간과 종료 시간 둘 다 입력을 하거나 둘 다 입력 하지 않아야 합니다."
|
ToastMessage(
|
||||||
|
resId = R.string.audio_content_upload_error_preview_both_required
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@@ -375,12 +401,16 @@ class AudioContentUploadViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (contentUri == null) {
|
if (contentUri == null) {
|
||||||
_toastLiveData.postValue("오디오 콘텐츠를 선택해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_content_required)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isPriceFreeLiveData.value!! && price < 5) {
|
if (!isPriceFreeLiveData.value!! && price < 5) {
|
||||||
_toastLiveData.postValue("콘텐츠의 최소금액은 5캔 입니다.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_minimum_price)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +418,9 @@ class AudioContentUploadViewModel(
|
|||||||
_isActiveReservationLiveData.value!! &&
|
_isActiveReservationLiveData.value!! &&
|
||||||
(releaseDate.isBlank() || releaseTime.isBlank())
|
(releaseDate.isBlank() || releaseTime.isBlank())
|
||||||
) {
|
) {
|
||||||
_toastLiveData.postValue("예약날짜와 시간을 선택해주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.audio_content_upload_error_reservation_required)
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,13 @@ class AudioContentThemeFragment(
|
|||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
||||||
it?.let { Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show() }
|
it?.let { toastMessage ->
|
||||||
|
val message = toastMessage.message
|
||||||
|
?: toastMessage.resId?.let(::getString)
|
||||||
|
message?.let { text ->
|
||||||
|
Toast.makeText(requireActivity(), text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.themeLiveData.observe(viewLifecycleOwner) {
|
viewModel.themeLiveData.observe(viewLifecycleOwner) {
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
|
|
||||||
class AudioContentThemeViewModel(private val repository: AudioContentRepository) : BaseViewModel() {
|
class AudioContentThemeViewModel(private val repository: AudioContentRepository) : BaseViewModel() {
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<ToastMessage?>()
|
||||||
val toastLiveData: LiveData<String?>
|
val toastLiveData: LiveData<ToastMessage?>
|
||||||
get() = _toastLiveData
|
get() = _toastLiveData
|
||||||
|
|
||||||
private val _themeLiveData = MutableLiveData<List<GetAudioContentThemeResponse>>()
|
private val _themeLiveData = MutableLiveData<List<GetAudioContentThemeResponse>>()
|
||||||
@@ -29,17 +31,19 @@ class AudioContentThemeViewModel(private val repository: AudioContentRepository)
|
|||||||
_themeLiveData.postValue(it.data!!)
|
_themeLiveData.postValue(it.data!!)
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(ToastMessage(message = it.message))
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -124,8 +124,13 @@ class AuditionFragment : BaseFragment<FragmentAuditionBinding>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
viewModel.toastLiveData.observe(viewLifecycleOwner) { toastMessage ->
|
||||||
it?.let { Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show() }
|
toastMessage?.let {
|
||||||
|
val message = it.message ?: it.resId?.let(::getString)
|
||||||
|
message?.let { text ->
|
||||||
|
Toast.makeText(requireActivity(), text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.isLoading.observe(viewLifecycleOwner) {
|
viewModel.isLoading.observe(viewLifecycleOwner) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package kr.co.vividnext.sodalive.audition
|
package kr.co.vividnext.sodalive.audition
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -47,18 +46,18 @@ class AuditionListAdapter(
|
|||||||
inner class InProgressHeaderViewHolder(
|
inner class InProgressHeaderViewHolder(
|
||||||
private val binding: ItemAuditionListInProgressHeaderBinding
|
private val binding: ItemAuditionListInProgressHeaderBinding
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
fun bind(totalCount: Int) {
|
fun bind(totalCount: Int) {
|
||||||
binding.tvTotalCount.text = "총 ${totalCount}개"
|
binding.tvTotalCount.text =
|
||||||
|
binding.root.context.getString(R.string.screen_audition_total_count, totalCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class CompletedHeaderViewHolder(
|
inner class CompletedHeaderViewHolder(
|
||||||
private val binding: ItemAuditionListCompletedHeaderBinding
|
private val binding: ItemAuditionListCompletedHeaderBinding
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
fun bind(totalCount: Int) {
|
fun bind(totalCount: Int) {
|
||||||
binding.tvTotalCount.text = "총 ${totalCount}개"
|
binding.tvTotalCount.text =
|
||||||
|
binding.root.context.getString(R.string.screen_audition_total_count, totalCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import com.orhanobut.logger.Logger
|
|||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
|
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
|
||||||
import kr.co.vividnext.sodalive.user.UserRepository
|
import kr.co.vividnext.sodalive.user.UserRepository
|
||||||
|
|
||||||
@@ -14,8 +16,8 @@ class AuditionViewModel(
|
|||||||
private val repository: AuditionRepository,
|
private val repository: AuditionRepository,
|
||||||
private val userRepository: UserRepository
|
private val userRepository: UserRepository
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<ToastMessage?>()
|
||||||
val toastLiveData: LiveData<String?>
|
val toastLiveData: LiveData<ToastMessage?>
|
||||||
get() = _toastLiveData
|
get() = _toastLiveData
|
||||||
|
|
||||||
private var _isLoading = MutableLiveData(false)
|
private var _isLoading = MutableLiveData(false)
|
||||||
@@ -53,10 +55,10 @@ class AuditionViewModel(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(ToastMessage(message = it.message))
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +66,9 @@ class AuditionViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.postValue(false)
|
_isLoading.postValue(false)
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import androidx.media3.common.util.UnstableApi
|
|||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
||||||
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
class AuditionApplicantMediaPlayerManager(
|
class AuditionApplicantMediaPlayerManager(
|
||||||
@@ -101,7 +102,11 @@ class AuditionApplicantMediaPlayerManager(
|
|||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Toast.makeText(context, "콘텐츠를 재생하지 못했습니다.\n다시 시도해 주세요", Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.getString(R.string.screen_audition_play_error),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
showLoadingDialog(false)
|
showLoadingDialog(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import kr.co.vividnext.sodalive.databinding.FragmentAuditionApplyDialogBinding
|
import kr.co.vividnext.sodalive.databinding.FragmentAuditionApplyDialogBinding
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AuditionApplyDialogFragment(
|
class AuditionApplyDialogFragment(
|
||||||
private val fileName: String,
|
private val fileName: String,
|
||||||
@@ -59,13 +60,13 @@ class AuditionApplyDialogFragment(
|
|||||||
if (phoneNumber.isBlank() || phoneNumber.length != 11) {
|
if (phoneNumber.isBlank() || phoneNumber.length != 11) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
"잘못된 연락처 입니다.\n다시 입력해 주세요.",
|
getString(R.string.dialog_audition_apply_error_invalid_phone),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
} else if (!binding.tvAgree.isSelected) {
|
} else if (!binding.tvAgree.isSelected) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
activity,
|
activity,
|
||||||
"연락처 수집 및 활용에 동의하셔야 오디션 지원이 가능합니다.",
|
getString(R.string.dialog_audition_apply_error_need_agreement),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import android.view.View
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
|
||||||
import coil.transform.RoundedCornersTransformation
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.MultiTransformation
|
import com.bumptech.glide.load.MultiTransformation
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||||
@@ -19,6 +17,7 @@ import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailActivity
|
|||||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAuditionDetailBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAuditionDetailBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
@@ -40,7 +39,7 @@ class AuditionDetailActivity : BaseActivity<ActivityAuditionDetailBinding>(
|
|||||||
if (auditionId <= 0) {
|
if (auditionId <= 0) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
"잘못된 요청입니다.\n다시 시도해 주세요.",
|
getString(R.string.screen_audition_error_invalid_request),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
|
|
||||||
@@ -60,7 +59,7 @@ class AuditionDetailActivity : BaseActivity<ActivityAuditionDetailBinding>(
|
|||||||
isOpenInformation = !isOpenInformation
|
isOpenInformation = !isOpenInformation
|
||||||
if (isOpenInformation) {
|
if (isOpenInformation) {
|
||||||
binding.tvInformation.maxLines = Int.MAX_VALUE
|
binding.tvInformation.maxLines = Int.MAX_VALUE
|
||||||
binding.tvOpen.text = "접기"
|
binding.tvOpen.text = getString(R.string.screen_audition_detail_collapse)
|
||||||
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
R.drawable.ic_live_detail_top,
|
R.drawable.ic_live_detail_top,
|
||||||
0,
|
0,
|
||||||
@@ -69,7 +68,7 @@ class AuditionDetailActivity : BaseActivity<ActivityAuditionDetailBinding>(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
binding.tvInformation.maxLines = 3
|
binding.tvInformation.maxLines = 3
|
||||||
binding.tvOpen.text = "펼치기"
|
binding.tvOpen.text = getString(R.string.screen_audition_detail_expand)
|
||||||
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
R.drawable.ic_live_detail_bottom,
|
R.drawable.ic_live_detail_bottom,
|
||||||
0,
|
0,
|
||||||
@@ -125,8 +124,13 @@ class AuditionDetailActivity : BaseActivity<ActivityAuditionDetailBinding>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.toastLiveData.observe(this) {
|
viewModel.toastLiveData.observe(this) { toastMessage ->
|
||||||
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
|
toastMessage?.let {
|
||||||
|
val message = it.message ?: it.resId?.let(::getString)
|
||||||
|
message?.let { text ->
|
||||||
|
Toast.makeText(applicationContext, text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.isLoading.observe(this) {
|
viewModel.isLoading.observe(this) {
|
||||||
|
|||||||
@@ -60,11 +60,11 @@ class AuditionDetailRoleAdapter(
|
|||||||
|
|
||||||
if (item.isComplete) {
|
if (item.isComplete) {
|
||||||
binding.blackCover.visibility = View.VISIBLE
|
binding.blackCover.visibility = View.VISIBLE
|
||||||
binding.tvStatus.text = "모집완료"
|
binding.tvStatus.text = context.getString(R.string.screen_audition_status_closed)
|
||||||
binding.tvStatus.setBackgroundResource(R.drawable.bg_round_corner_13_3_909090)
|
binding.tvStatus.setBackgroundResource(R.drawable.bg_round_corner_13_3_909090)
|
||||||
} else {
|
} else {
|
||||||
binding.blackCover.visibility = View.GONE
|
binding.blackCover.visibility = View.GONE
|
||||||
binding.tvStatus.text = "모집중"
|
binding.tvStatus.text = context.getString(R.string.screen_audition_status_open)
|
||||||
binding.tvStatus.setBackgroundResource(R.drawable.bg_round_corner_13_3_3bb9f1)
|
binding.tvStatus.setBackgroundResource(R.drawable.bg_round_corner_13_3_3bb9f1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,15 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.audition.AuditionRepository
|
import kr.co.vividnext.sodalive.audition.AuditionRepository
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
class AuditionDetailViewModel(
|
class AuditionDetailViewModel(
|
||||||
private val repository: AuditionRepository
|
private val repository: AuditionRepository
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<ToastMessage?>()
|
||||||
val toastLiveData: LiveData<String?>
|
val toastLiveData: LiveData<ToastMessage?>
|
||||||
get() = _toastLiveData
|
get() = _toastLiveData
|
||||||
|
|
||||||
private var _isLoading = MutableLiveData(false)
|
private var _isLoading = MutableLiveData(false)
|
||||||
@@ -39,10 +41,10 @@ class AuditionDetailViewModel(
|
|||||||
_auditionDetailLiveData.value = it.data
|
_auditionDetailLiveData.value = it.data
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(ToastMessage(message = it.message))
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +58,9 @@ class AuditionDetailViewModel(
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
|
)
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.audition.role
|
package kr.co.vividnext.sodalive.audition.role
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@@ -28,6 +29,7 @@ import kr.co.vividnext.sodalive.common.Constants
|
|||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
import kr.co.vividnext.sodalive.common.RealPathUtil
|
import kr.co.vividnext.sodalive.common.RealPathUtil
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
import kr.co.vividnext.sodalive.databinding.ActivityAuditionRoleDetailBinding
|
import kr.co.vividnext.sodalive.databinding.ActivityAuditionRoleDetailBinding
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
|
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.write.RecordingVoiceFragment
|
import kr.co.vividnext.sodalive.explorer.profile.creator_community.write.RecordingVoiceFragment
|
||||||
@@ -66,14 +68,14 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
"잘못된 녹음 파일 입니다.\n다시 선택해 주세요.",
|
getString(R.string.screen_audition_invalid_audio_file),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
"잘못된 녹음 파일 입니다.\n다시 선택해 주세요.",
|
getString(R.string.screen_audition_invalid_audio_file),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
@@ -87,7 +89,7 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
if (auditionRoleId <= 0) {
|
if (auditionRoleId <= 0) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
"잘못된 요청입니다.\n다시 시도해 주세요.",
|
getString(R.string.screen_audition_error_invalid_request),
|
||||||
Toast.LENGTH_LONG
|
Toast.LENGTH_LONG
|
||||||
).show()
|
).show()
|
||||||
|
|
||||||
@@ -137,7 +139,7 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
isOpenInformation = !isOpenInformation
|
isOpenInformation = !isOpenInformation
|
||||||
if (isOpenInformation) {
|
if (isOpenInformation) {
|
||||||
binding.tvInformation.maxLines = Int.MAX_VALUE
|
binding.tvInformation.maxLines = Int.MAX_VALUE
|
||||||
binding.tvOpen.text = "접기"
|
binding.tvOpen.text = getString(R.string.screen_audition_detail_collapse)
|
||||||
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
R.drawable.ic_live_detail_top,
|
R.drawable.ic_live_detail_top,
|
||||||
0,
|
0,
|
||||||
@@ -146,7 +148,7 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
binding.tvInformation.maxLines = 3
|
binding.tvInformation.maxLines = 3
|
||||||
binding.tvOpen.text = "펼치기"
|
binding.tvOpen.text = getString(R.string.screen_audition_detail_expand)
|
||||||
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
binding.tvOpen.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
R.drawable.ic_live_detail_bottom,
|
R.drawable.ic_live_detail_bottom,
|
||||||
0,
|
0,
|
||||||
@@ -162,9 +164,9 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = this@AuditionRoleDetailActivity,
|
activity = this@AuditionRoleDetailActivity,
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "재지원 안내",
|
title = getString(R.string.dialog_audition_reapply_title),
|
||||||
desc = "재지원 시 이전 지원 내역은 삭제되며 받은 투표수는 무효 처리됩니다.",
|
desc = getString(R.string.dialog_audition_reapply_desc),
|
||||||
confirmButtonTitle = "확인",
|
confirmButtonTitle = getString(R.string.confirm),
|
||||||
confirmButtonClick = { showApplicationMethodDialog() }
|
confirmButtonClick = { showApplicationMethodDialog() }
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
} else {
|
} else {
|
||||||
@@ -174,9 +176,9 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = this@AuditionRoleDetailActivity,
|
activity = this@AuditionRoleDetailActivity,
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "- 본인인증 -",
|
title = getString(R.string.dialog_audition_auth_title),
|
||||||
desc = "마이페이지에서 '본인인증'을 하고 다시 오디션에 지원해 주세요.",
|
desc = getString(R.string.dialog_audition_auth_desc),
|
||||||
confirmButtonTitle = "확인",
|
confirmButtonTitle = getString(R.string.confirm),
|
||||||
confirmButtonClick = {}
|
confirmButtonClick = {}
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
}
|
}
|
||||||
@@ -211,23 +213,23 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = this@AuditionRoleDetailActivity,
|
activity = this@AuditionRoleDetailActivity,
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
"[오디션 응원]",
|
getString(R.string.dialog_audition_vote_title),
|
||||||
"오디션을 응원하셨습니다\n(무료응원 : 1계정당 1일 1회)\n1캔으로 추가 응원을 해보세요.",
|
getString(R.string.dialog_audition_vote_desc),
|
||||||
confirmButtonTitle = "확인",
|
confirmButtonTitle = getString(R.string.confirm),
|
||||||
confirmButtonClick = {
|
confirmButtonClick = {
|
||||||
isShowNotifyVote = false
|
isShowNotifyVote = false
|
||||||
},
|
},
|
||||||
descGravity = Gravity.CENTER
|
descGravity = Gravity.CENTER
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFailure = {
|
onFailure = {
|
||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = this@AuditionRoleDetailActivity,
|
activity = this@AuditionRoleDetailActivity,
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
"[오늘 응원 제한]",
|
getString(R.string.dialog_audition_vote_limit_title),
|
||||||
"오늘 응원은 여기까지!\n하루 최대 10회까지 이용이 가능합니다.\n내일 다시 이용해주세요.",
|
getString(R.string.dialog_audition_vote_limit_desc),
|
||||||
confirmButtonTitle = "확인",
|
confirmButtonTitle = getString(R.string.confirm),
|
||||||
confirmButtonClick = {},
|
confirmButtonClick = {},
|
||||||
descGravity = Gravity.CENTER
|
descGravity = Gravity.CENTER
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
@@ -307,7 +309,7 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
selectAudioActivityResultLauncher.launch(
|
selectAudioActivityResultLauncher.launch(
|
||||||
Intent.createChooser(
|
Intent.createChooser(
|
||||||
intent,
|
intent,
|
||||||
"Select Audio"
|
getString(R.string.screen_audition_select_audio)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -339,9 +341,15 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
auditionApplyDialogFragment.show(supportFragmentManager, auditionApplyDialogFragment.tag)
|
auditionApplyDialogFragment.show(supportFragmentManager, auditionApplyDialogFragment.tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.toastLiveData.observe(this) {
|
viewModel.toastLiveData.observe(this) {
|
||||||
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
|
it?.let { toastMessage ->
|
||||||
|
val message = toastMessage.message ?: toastMessage.resId?.let(::getString)
|
||||||
|
message?.let { text ->
|
||||||
|
Toast.makeText(applicationContext, text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.isLoading.observe(this) {
|
viewModel.isLoading.observe(this) {
|
||||||
@@ -381,10 +389,10 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
|
|
||||||
if (roleDetail.isAlreadyApplicant) {
|
if (roleDetail.isAlreadyApplicant) {
|
||||||
reApplication = true
|
reApplication = true
|
||||||
binding.tvApplicant.text = "오디션 재지원"
|
binding.tvApplicant.text = getString(R.string.screen_audition_apply_again)
|
||||||
} else {
|
} else {
|
||||||
reApplication = false
|
reApplication = false
|
||||||
binding.tvApplicant.text = "오디션 지원"
|
binding.tvApplicant.text = getString(R.string.screen_audition_apply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +402,7 @@ class AuditionRoleDetailActivity : BaseActivity<ActivityAuditionRoleDetailBindin
|
|||||||
|
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
binding.groupApplicant.visibility = View.VISIBLE
|
binding.groupApplicant.visibility = View.VISIBLE
|
||||||
binding.tvApplicantCount.text = "$it"
|
binding.tvApplicantCount.text = " $it"
|
||||||
} else {
|
} else {
|
||||||
binding.groupNoApplicant.visibility = View.VISIBLE
|
binding.groupNoApplicant.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import kr.co.vividnext.sodalive.audition.applicant.ApplyAuditionRoleRequest
|
|||||||
import kr.co.vividnext.sodalive.audition.applicant.GetAuditionRoleApplicantItem
|
import kr.co.vividnext.sodalive.audition.applicant.GetAuditionRoleApplicantItem
|
||||||
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
import kr.co.vividnext.sodalive.audition.vote.VoteAuditionApplicantRequest
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
@@ -24,8 +26,8 @@ import java.io.File
|
|||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
|
|
||||||
class AuditionRoleDetailViewModel(private val repository: AuditionRepository) : BaseViewModel() {
|
class AuditionRoleDetailViewModel(private val repository: AuditionRepository) : BaseViewModel() {
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<ToastMessage?>()
|
||||||
val toastLiveData: LiveData<String?>
|
val toastLiveData: LiveData<ToastMessage?>
|
||||||
get() = _toastLiveData
|
get() = _toastLiveData
|
||||||
|
|
||||||
private val _isLoading = MutableLiveData(false)
|
private val _isLoading = MutableLiveData(false)
|
||||||
@@ -90,9 +92,10 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
_auditionRoleDetailLiveData.value = roleDetailResponse.data!!
|
_auditionRoleDetailLiveData.value = roleDetailResponse.data!!
|
||||||
} else {
|
} else {
|
||||||
if (roleDetailResponse.message != null) {
|
if (roleDetailResponse.message != null) {
|
||||||
_toastLiveData.value = roleDetailResponse.message
|
_toastLiveData.value = ToastMessage(message = roleDetailResponse.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value =
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
@@ -113,9 +116,10 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (applicantListResponse.message != null) {
|
if (applicantListResponse.message != null) {
|
||||||
_toastLiveData.value = applicantListResponse.message
|
_toastLiveData.value = ToastMessage(message = applicantListResponse.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value =
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
@@ -128,7 +132,9 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
|
)
|
||||||
if (onFailure != null) {
|
if (onFailure != null) {
|
||||||
onFailure()
|
onFailure()
|
||||||
}
|
}
|
||||||
@@ -166,9 +172,10 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.value = it.message
|
_toastLiveData.value = ToastMessage(message = it.message)
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value =
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +184,9 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -186,7 +195,8 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
|
|
||||||
fun applyAudition(auditionRoleId: Long, phoneNumber: String, onSuccess: () -> Unit) {
|
fun applyAudition(auditionRoleId: Long, phoneNumber: String, onSuccess: () -> Unit) {
|
||||||
if (audioFile == null) {
|
if (audioFile == null) {
|
||||||
_toastLiveData.value = "잘못된 녹음 파일 입니다.\n다시 선택해 주세요."
|
_toastLiveData.value =
|
||||||
|
ToastMessage(resId = R.string.screen_audition_invalid_audio_file)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,10 +246,10 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
onSuccess()
|
onSuccess()
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(ToastMessage(message = it.message))
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,7 +258,7 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue(
|
_toastLiveData.postValue(
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -304,11 +314,11 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
) {
|
) {
|
||||||
onFailure()
|
onFailure()
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = it.message
|
_toastLiveData.value = ToastMessage(message = it.message)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value =
|
_toastLiveData.value =
|
||||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +327,8 @@ class AuditionRoleDetailViewModel(private val repository: AuditionRepository) :
|
|||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
_toastLiveData.value =
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import androidx.core.view.WindowInsetsControllerCompat
|
|||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaLiveApplicationHolder
|
||||||
|
import kr.co.vividnext.sodalive.settings.language.LocaleHelper
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
abstract class BaseActivity<T : ViewBinding>(
|
abstract class BaseActivity<T : ViewBinding>(
|
||||||
@@ -43,6 +46,12 @@ abstract class BaseActivity<T : ViewBinding>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun attachBaseContext(newBase: Context) {
|
||||||
|
// 앱 설정 언어가 있으면 해당 Locale을 적용한 Context로 래핑한다.
|
||||||
|
val wrapped = LocaleHelper.wrap(newBase)
|
||||||
|
super.attachBaseContext(wrapped)
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("SourceLockedOrientationActivity")
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -103,7 +112,8 @@ abstract class BaseActivity<T : ViewBinding>(
|
|||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "포인트 지급",
|
title = "포인트 지급",
|
||||||
desc = message,
|
desc = message,
|
||||||
confirmButtonTitle = "확인",
|
confirmButtonTitle = SodaLiveApplicationHolder.get()
|
||||||
|
.getString(R.string.screen_live_tag_confirm),
|
||||||
confirmButtonClick = {}
|
confirmButtonClick = {}
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,15 @@ class ChatFragment : BaseFragment<FragmentChatBinding>(FragmentChatBinding::infl
|
|||||||
|
|
||||||
private fun setupTabs() {
|
private fun setupTabs() {
|
||||||
// 탭 추가
|
// 탭 추가
|
||||||
binding.tabLayout.addTab(binding.tabLayout.newTab().setText("캐릭터"))
|
binding.tabLayout.addTab(
|
||||||
binding.tabLayout.addTab(binding.tabLayout.newTab().setText("작품별"))
|
binding.tabLayout.newTab().setText(R.string.screen_chat_tab_character)
|
||||||
binding.tabLayout.addTab(binding.tabLayout.newTab().setText("톡"))
|
)
|
||||||
|
binding.tabLayout.addTab(
|
||||||
|
binding.tabLayout.newTab().setText(R.string.screen_chat_tab_original)
|
||||||
|
)
|
||||||
|
binding.tabLayout.addTab(
|
||||||
|
binding.tabLayout.newTab().setText(R.string.screen_chat_tab_talk)
|
||||||
|
)
|
||||||
|
|
||||||
// 탭 선택 리스너 설정
|
// 탭 선택 리스너 설정
|
||||||
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import kr.co.vividnext.sodalive.chat.character.detail.gallery.CharacterImageList
|
|||||||
import kr.co.vividnext.sodalive.chat.character.detail.gallery.CharacterImagePurchaseRequest
|
import kr.co.vividnext.sodalive.chat.character.detail.gallery.CharacterImagePurchaseRequest
|
||||||
import kr.co.vividnext.sodalive.chat.character.detail.gallery.CharacterImagePurchaseResponse
|
import kr.co.vividnext.sodalive.chat.character.detail.gallery.CharacterImagePurchaseResponse
|
||||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
import retrofit2.http.Body
|
|
||||||
import retrofit2.http.POST
|
|
||||||
|
|
||||||
interface CharacterApi {
|
interface CharacterApi {
|
||||||
@GET("/api/chat/character/main")
|
@GET("/api/chat/character/main")
|
||||||
|
|||||||
@@ -379,12 +379,11 @@ class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
|
|||||||
SodaDialog(
|
SodaDialog(
|
||||||
activity = requireActivity(),
|
activity = requireActivity(),
|
||||||
layoutInflater = layoutInflater,
|
layoutInflater = layoutInflater,
|
||||||
title = "본인인증",
|
title = getString(R.string.auth_title),
|
||||||
desc = "보이스온의 오픈월드 캐릭터톡은\n청소년 보호를 위해 본인인증한\n성인만 이용이 가능합니다.\n" +
|
desc = getString(R.string.auth_desc),
|
||||||
"캐릭터톡 서비스를 이용하시려면\n본인인증을 하고 이용해주세요.",
|
confirmButtonTitle = getString(R.string.auth_go),
|
||||||
confirmButtonTitle = "본인인증 하러가기",
|
|
||||||
confirmButtonClick = { startAuthFlow() },
|
confirmButtonClick = { startAuthFlow() },
|
||||||
cancelButtonTitle = "취소",
|
cancelButtonTitle = getString(R.string.cancel),
|
||||||
cancelButtonClick = {},
|
cancelButtonClick = {},
|
||||||
descGravity = Gravity.CENTER
|
descGravity = Gravity.CENTER
|
||||||
).show(screenWidth)
|
).show(screenWidth)
|
||||||
@@ -430,7 +429,10 @@ class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
||||||
it?.let { Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show() }
|
val text = it?.message ?: it?.resId?.let { resId -> getString(resId) }
|
||||||
|
if (!text.isNullOrBlank()) {
|
||||||
|
Toast.makeText(requireActivity(), text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package kr.co.vividnext.sodalive.chat.character
|
package kr.co.vividnext.sodalive.chat.character
|
||||||
|
|
||||||
class CharacterTabRepository(private val api: CharacterApi) {
|
class CharacterTabRepository(private val api: CharacterApi) {
|
||||||
fun getCharacterMain(
|
fun getCharacterMain(token: String) = api.getCharacterMain(authHeader = token)
|
||||||
token: String
|
|
||||||
) = api.getCharacterMain(authHeader = token)
|
|
||||||
|
|
||||||
fun refreshRecommendCharacters(
|
fun refreshRecommendCharacters(
|
||||||
token: String
|
token: String
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.chat.character.recent.RecentCharacter
|
import kr.co.vividnext.sodalive.chat.character.recent.RecentCharacter
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.ToastMessage
|
||||||
|
|
||||||
class CharacterTabViewModel(
|
class CharacterTabViewModel(
|
||||||
private val repository: CharacterTabRepository
|
private val repository: CharacterTabRepository
|
||||||
@@ -16,8 +18,8 @@ class CharacterTabViewModel(
|
|||||||
val isLoading: LiveData<Boolean>
|
val isLoading: LiveData<Boolean>
|
||||||
get() = _isLoading
|
get() = _isLoading
|
||||||
|
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<ToastMessage?>()
|
||||||
val toastLiveData: LiveData<String?>
|
val toastLiveData: LiveData<ToastMessage?>
|
||||||
get() = _toastLiveData
|
get() = _toastLiveData
|
||||||
|
|
||||||
private var _bannerListLiveData = MutableLiveData<List<CharacterBannerResponse>>()
|
private var _bannerListLiveData = MutableLiveData<List<CharacterBannerResponse>>()
|
||||||
@@ -48,7 +50,9 @@ class CharacterTabViewModel(
|
|||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
|
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.getCharacterMain(token = "Bearer ${SharedPreferenceManager.token}")
|
repository.getCharacterMain(
|
||||||
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
@@ -61,15 +65,18 @@ class CharacterTabViewModel(
|
|||||||
_newCharacters.value = data.newCharacters
|
_newCharacters.value = data.newCharacters
|
||||||
_recommendCharacters.value = data.recommendCharacters
|
_recommendCharacters.value = data.recommendCharacters
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value =
|
_toastLiveData.value = it.message?.let { message ->
|
||||||
it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(message = message)
|
||||||
|
} ?: ToastMessage(resId = R.string.common_error_unknown)
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
it.message?.let { message -> Logger.e(message) }
|
it.message?.let { message -> Logger.e(message) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -78,7 +85,9 @@ class CharacterTabViewModel(
|
|||||||
fun refreshRecommendCharacters() {
|
fun refreshRecommendCharacters() {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
repository.refreshRecommendCharacters(token = "Bearer ${SharedPreferenceManager.token}")
|
repository.refreshRecommendCharacters(
|
||||||
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
@@ -86,15 +95,18 @@ class CharacterTabViewModel(
|
|||||||
if (response.success && response.data != null) {
|
if (response.success && response.data != null) {
|
||||||
_recommendCharacters.value = response.data
|
_recommendCharacters.value = response.data
|
||||||
} else {
|
} else {
|
||||||
_toastLiveData.value = response.message
|
_toastLiveData.value = response.message?.let { message ->
|
||||||
?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
ToastMessage(message = message)
|
||||||
|
} ?: ToastMessage(resId = R.string.common_error_unknown)
|
||||||
}
|
}
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
},
|
},
|
||||||
{ throwable ->
|
{ throwable ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
throwable.message?.let { msg -> Logger.e(msg) }
|
throwable.message?.let { msg -> Logger.e(msg) }
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(
|
||||||
|
ToastMessage(resId = R.string.common_error_unknown)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|||||||
import kr.co.vividnext.sodalive.R
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
|
import kr.co.vividnext.sodalive.common.UiText
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.databinding.FragmentCharacterCommentListBinding
|
import kr.co.vividnext.sodalive.databinding.FragmentCharacterCommentListBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
@@ -173,8 +174,7 @@ class CharacterCommentListFragment : BaseFragment<FragmentCharacterCommentListBi
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.toastLiveData.observe(viewLifecycleOwner) { msg ->
|
viewModel.toastLiveData.observe(viewLifecycleOwner) { msg ->
|
||||||
|
msg?.let { showToast(it.asString(requireContext())) }
|
||||||
msg?.let { showToast(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.totalCommentCount.observe(viewLifecycleOwner) { count ->
|
viewModel.totalCommentCount.observe(viewLifecycleOwner) { count ->
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ import com.orhanobut.logger.Logger
|
|||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.common.UiText
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
|
||||||
class CharacterCommentListViewModel(
|
class CharacterCommentListViewModel(
|
||||||
private val repository: CharacterCommentRepository
|
private val repository: CharacterCommentRepository
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<UiText?>()
|
||||||
val toastLiveData: LiveData<String?>
|
val toastLiveData: LiveData<UiText?>
|
||||||
get() = _toastLiveData
|
get() = _toastLiveData
|
||||||
|
|
||||||
private val _isLoading = MutableLiveData(false)
|
private val _isLoading = MutableLiveData(false)
|
||||||
@@ -80,14 +82,16 @@ class CharacterCommentListViewModel(
|
|||||||
// 응답 아이템 전달 (비어있어도 전달) — UI는 addAll 처리
|
// 응답 아이템 전달 (비어있어도 전달) — UI는 addAll 처리
|
||||||
_commentList.postValue(items)
|
_commentList.postValue(items)
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
onFailure?.invoke()
|
onFailure?.invoke()
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character comments load failed")
|
Logger.e(e, "Character comments load failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
onFailure?.invoke()
|
onFailure?.invoke()
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -95,7 +99,7 @@ class CharacterCommentListViewModel(
|
|||||||
|
|
||||||
fun createComment(characterId: Long, comment: String) {
|
fun createComment(characterId: Long, comment: String) {
|
||||||
if (comment.isBlank()) {
|
if (comment.isBlank()) {
|
||||||
_toastLiveData.postValue("내용을 입력하세요")
|
_toastLiveData.postValue(UiText.StringResource(R.string.character_comment_error_empty))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (_isLoading.value == true) return
|
if (_isLoading.value == true) return
|
||||||
@@ -119,13 +123,15 @@ class CharacterCommentListViewModel(
|
|||||||
cursor = null
|
cursor = null
|
||||||
getCommentList(characterId)
|
getCommentList(characterId)
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character comment create failed")
|
Logger.e(e, "Character comment create failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -151,20 +157,24 @@ class CharacterCommentListViewModel(
|
|||||||
cursor = null
|
cursor = null
|
||||||
getCommentList(characterId)
|
getCommentList(characterId)
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character comment delete failed")
|
Logger.e(e, "Character comment delete failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reportComment(characterId: Long, commentId: Long, reason: String) {
|
fun reportComment(characterId: Long, commentId: Long, reason: String) {
|
||||||
if (reason.isBlank()) {
|
if (reason.isBlank()) {
|
||||||
_toastLiveData.postValue("신고 사유를 입력하세요")
|
_toastLiveData.postValue(
|
||||||
|
UiText.StringResource(R.string.character_comment_error_report_reason)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (_isLoading.value == true) return
|
if (_isLoading.value == true) return
|
||||||
@@ -182,15 +192,19 @@ class CharacterCommentListViewModel(
|
|||||||
.subscribe({ resp ->
|
.subscribe({ resp ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
_toastLiveData.postValue("신고가 접수되었습니다.")
|
_toastLiveData.postValue(
|
||||||
|
UiText.StringResource(R.string.character_comment_report_submitted)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character comment report failed")
|
Logger.e(e, "Character comment report failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class CharacterReplyHeaderVH(
|
|||||||
) : CharacterReplyVH(binding) {
|
) : CharacterReplyVH(binding) {
|
||||||
override fun bind(item: Any) {
|
override fun bind(item: Any) {
|
||||||
val data = item as CharacterCommentResponse
|
val data = item as CharacterCommentResponse
|
||||||
|
val context = binding.root.context
|
||||||
if (data.memberProfileImage.isNotBlank()) {
|
if (data.memberProfileImage.isNotBlank()) {
|
||||||
binding.ivCommentProfile.load(data.memberProfileImage) {
|
binding.ivCommentProfile.load(data.memberProfileImage) {
|
||||||
crossfade(true)
|
crossfade(true)
|
||||||
@@ -71,7 +72,7 @@ class CharacterReplyHeaderVH(
|
|||||||
binding.ivCommentProfile.setImageResource(R.drawable.ic_placeholder_profile)
|
binding.ivCommentProfile.setImageResource(R.drawable.ic_placeholder_profile)
|
||||||
}
|
}
|
||||||
binding.tvCommentNickname.text = data.memberNickname
|
binding.tvCommentNickname.text = data.memberNickname
|
||||||
binding.tvCommentDate.text = timeAgo(data.createdAt)
|
binding.tvCommentDate.text = formatCommentTime(context, data.createdAt)
|
||||||
binding.tvComment.text = data.comment
|
binding.tvComment.text = data.comment
|
||||||
binding.tvWriteReply.visibility = View.GONE
|
binding.tvWriteReply.visibility = View.GONE
|
||||||
binding.ivMenu.visibility = View.GONE
|
binding.ivMenu.visibility = View.GONE
|
||||||
@@ -86,6 +87,7 @@ class CharacterReplyItemVH(
|
|||||||
|
|
||||||
override fun bind(item: Any) {
|
override fun bind(item: Any) {
|
||||||
val data = item as CharacterReplyResponse
|
val data = item as CharacterReplyResponse
|
||||||
|
val context = binding.root.context
|
||||||
if (data.memberProfileImage.isNotBlank()) {
|
if (data.memberProfileImage.isNotBlank()) {
|
||||||
binding.ivCommentProfile.load(data.memberProfileImage) {
|
binding.ivCommentProfile.load(data.memberProfileImage) {
|
||||||
crossfade(true)
|
crossfade(true)
|
||||||
@@ -98,7 +100,7 @@ class CharacterReplyItemVH(
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.tvCommentNickname.text = data.memberNickname
|
binding.tvCommentNickname.text = data.memberNickname
|
||||||
binding.tvCommentDate.text = timeAgo(data.createdAt)
|
binding.tvCommentDate.text = formatCommentTime(context, data.createdAt)
|
||||||
binding.tvComment.text = data.comment
|
binding.tvComment.text = data.comment
|
||||||
|
|
||||||
val isOwner = data.memberId == currentUserId
|
val isOwner = data.memberId == currentUserId
|
||||||
@@ -109,17 +111,3 @@ class CharacterReplyItemVH(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun timeAgo(createdAtMillis: Long): String {
|
|
||||||
val now = System.currentTimeMillis()
|
|
||||||
val diff = (now - createdAtMillis).coerceAtLeast(0)
|
|
||||||
val minutes = diff / 60_000
|
|
||||||
if (minutes < 1) return "방금전"
|
|
||||||
if (minutes < 60) return "${minutes}분전"
|
|
||||||
val hours = minutes / 60
|
|
||||||
if (hours < 24) return "${hours}시간전"
|
|
||||||
val days = hours / 24
|
|
||||||
if (days < 365) return "${days}일전"
|
|
||||||
val years = days / 365
|
|
||||||
return "${years}년전"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import coil.transform.CircleCropTransformation
|
|||||||
import kr.co.vividnext.sodalive.R
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
|
import kr.co.vividnext.sodalive.common.UiText
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.databinding.FragmentCharacterCommentReplyBinding
|
import kr.co.vividnext.sodalive.databinding.FragmentCharacterCommentReplyBinding
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
@@ -179,7 +180,7 @@ class CharacterCommentReplyFragment : BaseFragment<FragmentCharacterCommentReply
|
|||||||
if (loading) loadingDialog.show(screenWidth) else loadingDialog.dismiss()
|
if (loading) loadingDialog.show(screenWidth) else loadingDialog.dismiss()
|
||||||
}
|
}
|
||||||
viewModel.toastLiveData.observe(viewLifecycleOwner) { msg ->
|
viewModel.toastLiveData.observe(viewLifecycleOwner) { msg ->
|
||||||
msg?.let { showToast(it) }
|
msg?.let { showToast(it.asString(requireContext())) }
|
||||||
}
|
}
|
||||||
viewModel.replies.observe(viewLifecycleOwner) { list ->
|
viewModel.replies.observe(viewLifecycleOwner) { list ->
|
||||||
// 헤더(원본 댓글)는 index 0에 유지, 나머지를 교체
|
// 헤더(원본 댓글)는 index 0에 유지, 나머지를 교체
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ import com.orhanobut.logger.Logger
|
|||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
|
import kr.co.vividnext.sodalive.common.UiText
|
||||||
|
|
||||||
class CharacterCommentReplyViewModel(
|
class CharacterCommentReplyViewModel(
|
||||||
private val repository: CharacterCommentRepository
|
private val repository: CharacterCommentRepository
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private val _toastLiveData = MutableLiveData<String?>()
|
private val _toastLiveData = MutableLiveData<UiText?>()
|
||||||
val toastLiveData: LiveData<String?> get() = _toastLiveData
|
val toastLiveData: LiveData<UiText?> get() = _toastLiveData
|
||||||
|
|
||||||
private val _isLoading = MutableLiveData(false)
|
private val _isLoading = MutableLiveData(false)
|
||||||
val isLoading: LiveData<Boolean> get() = _isLoading
|
val isLoading: LiveData<Boolean> get() = _isLoading
|
||||||
@@ -65,20 +67,22 @@ class CharacterCommentReplyViewModel(
|
|||||||
cursor = resp.data.cursor
|
cursor = resp.data.cursor
|
||||||
page += 1
|
page += 1
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character replies load failed")
|
Logger.e(e, "Character replies load failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createReply(characterId: Long, comment: String) {
|
fun createReply(characterId: Long, comment: String) {
|
||||||
if (comment.isBlank()) {
|
if (comment.isBlank()) {
|
||||||
_toastLiveData.postValue("내용을 입력하세요")
|
_toastLiveData.postValue(UiText.StringResource(R.string.character_comment_error_empty))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val originalId = _original.value?.commentId ?: return
|
val originalId = _original.value?.commentId ?: return
|
||||||
@@ -110,13 +114,15 @@ class CharacterCommentReplyViewModel(
|
|||||||
val current = _replies.value ?: emptyList()
|
val current = _replies.value ?: emptyList()
|
||||||
_replies.postValue(current + listOf(me))
|
_replies.postValue(current + listOf(me))
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character reply create failed")
|
Logger.e(e, "Character reply create failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -139,20 +145,24 @@ class CharacterCommentReplyViewModel(
|
|||||||
val current = _replies.value ?: emptyList()
|
val current = _replies.value ?: emptyList()
|
||||||
_replies.postValue(current.filterNot { it.replyId == replyId })
|
_replies.postValue(current.filterNot { it.replyId == replyId })
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character reply delete failed")
|
Logger.e(e, "Character reply delete failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reportReply(characterId: Long, replyId: Long, reason: String) {
|
fun reportReply(characterId: Long, replyId: Long, reason: String) {
|
||||||
if (reason.isBlank()) {
|
if (reason.isBlank()) {
|
||||||
_toastLiveData.postValue("신고 사유를 입력하세요")
|
_toastLiveData.postValue(
|
||||||
|
UiText.StringResource(R.string.character_comment_error_report_reason)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (_isLoading.value == true) return
|
if (_isLoading.value == true) return
|
||||||
@@ -170,15 +180,19 @@ class CharacterCommentReplyViewModel(
|
|||||||
.subscribe({ resp ->
|
.subscribe({ resp ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
_toastLiveData.postValue("신고가 접수되었습니다.")
|
_toastLiveData.postValue(
|
||||||
|
UiText.StringResource(R.string.character_comment_report_submitted)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val message = resp.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
val message = resp.message?.takeIf { it.isNotBlank() }
|
||||||
|
?.let { UiText.DynamicString(it) }
|
||||||
|
?: UiText.StringResource(R.string.common_error_unknown)
|
||||||
_toastLiveData.postValue(message)
|
_toastLiveData.postValue(message)
|
||||||
}
|
}
|
||||||
}, { e ->
|
}, { e ->
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
Logger.e(e, "Character reply report failed")
|
Logger.e(e, "Character reply report failed")
|
||||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
_toastLiveData.postValue(UiText.StringResource(R.string.common_error_unknown))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ class CharacterCommentReportBottomSheet : BottomSheetDialogFragment() {
|
|||||||
|
|
||||||
var onSubmit: ((String) -> Unit)? = null
|
var onSubmit: ((String) -> Unit)? = null
|
||||||
|
|
||||||
private var reasons: ArrayList<String>? = null
|
private var reasons: ArrayList<String> = ArrayList()
|
||||||
private var selectedIndex: Int = -1
|
private var selectedIndex: Int = -1
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
reasons = arguments?.getStringArrayList(ARG_REASONS) ?: DEFAULT_REASONS
|
val defaultReasons = resources.getStringArray(R.array.character_comment_report_reasons)
|
||||||
|
.toCollection(ArrayList())
|
||||||
|
reasons = arguments?.getStringArrayList(ARG_REASONS) ?: defaultReasons
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@@ -49,7 +51,7 @@ class CharacterCommentReportBottomSheet : BottomSheetDialogFragment() {
|
|||||||
tvTitle.text = getString(R.string.report_title)
|
tvTitle.text = getString(R.string.report_title)
|
||||||
setReportEnabled(btnReport, false)
|
setReportEnabled(btnReport, false)
|
||||||
|
|
||||||
val items = reasons ?: DEFAULT_REASONS
|
val items = reasons
|
||||||
val textColor = ContextCompat.getColor(requireContext(), R.color.white)
|
val textColor = ContextCompat.getColor(requireContext(), R.color.white)
|
||||||
|
|
||||||
// RadioButton 동적 생성 및 단일 선택 처리
|
// RadioButton 동적 생성 및 단일 선택 처리
|
||||||
@@ -64,8 +66,9 @@ class CharacterCommentReportBottomSheet : BottomSheetDialogFragment() {
|
|||||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
||||||
// 폰트: pretendard_regular
|
// 폰트: pretendard_regular
|
||||||
try {
|
try {
|
||||||
typeface = ResourcesCompat.getFont(context, R.font.pretendard_regular)
|
typeface = ResourcesCompat.getFont(context, R.font.regular)
|
||||||
} catch (_: Exception) { /* 폰트 미존재 대비 안전 처리 */ }
|
} catch (_: Exception) { /* 폰트 미존재 대비 안전 처리 */
|
||||||
|
}
|
||||||
// 항목 간 간격: 기존 paddingVertical 12dp의 1.3배 -> 15.6dp
|
// 항목 간 간격: 기존 paddingVertical 12dp의 1.3배 -> 15.6dp
|
||||||
val vPadPx = (14f * resources.displayMetrics.density).toInt()
|
val vPadPx = (14f * resources.displayMetrics.density).toInt()
|
||||||
setPadding(paddingLeft, vPadPx, paddingRight, vPadPx)
|
setPadding(paddingLeft, vPadPx, paddingRight, vPadPx)
|
||||||
@@ -106,16 +109,6 @@ class CharacterCommentReportBottomSheet : BottomSheetDialogFragment() {
|
|||||||
companion object {
|
companion object {
|
||||||
private const val ARG_REASONS = "arg_reasons"
|
private const val ARG_REASONS = "arg_reasons"
|
||||||
|
|
||||||
private val DEFAULT_REASONS = arrayListOf(
|
|
||||||
"원치 않는 상업성 콘텐츠 또는 스팸",
|
|
||||||
"아동 학대",
|
|
||||||
"증오시 표현 또는 노골적인 폭력",
|
|
||||||
"테러 조장",
|
|
||||||
"희롱 또는 괴롭힘",
|
|
||||||
"자살 또는 자해",
|
|
||||||
"잘못된 정보"
|
|
||||||
)
|
|
||||||
|
|
||||||
fun newInstance(reasons: ArrayList<String>? = null): CharacterCommentReportBottomSheet {
|
fun newInstance(reasons: ArrayList<String>? = null): CharacterCommentReportBottomSheet {
|
||||||
return CharacterCommentReportBottomSheet().apply {
|
return CharacterCommentReportBottomSheet().apply {
|
||||||
arguments = bundleOf(ARG_REASONS to reasons)
|
arguments = bundleOf(ARG_REASONS to reasons)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package kr.co.vividnext.sodalive.chat.character.comment
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
|
||||||
|
fun formatCommentTime(context: Context, createdAtMillis: Long): String {
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
val diff = (now - createdAtMillis).coerceAtLeast(0)
|
||||||
|
val minutes = diff / 60_000
|
||||||
|
return when {
|
||||||
|
minutes < 1 -> context.getString(R.string.character_comment_time_just_now)
|
||||||
|
minutes < 60 -> context.getString(R.string.character_comment_time_minutes, minutes)
|
||||||
|
minutes < 1_440 -> {
|
||||||
|
val hours = minutes / 60
|
||||||
|
context.getString(R.string.character_comment_time_hours, hours)
|
||||||
|
}
|
||||||
|
minutes < 525_600 -> {
|
||||||
|
val days = minutes / 1_440
|
||||||
|
context.getString(R.string.character_comment_time_days, days)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val years = minutes / 525_600
|
||||||
|
context.getString(R.string.character_comment_time_years, years)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user