初次代码上传
This commit is contained in:
commit
058e46bae8
109
app/build.gradle.kts
Normal file
109
app/build.gradle.kts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.android.application)
|
||||||
|
alias(libs.plugins.kotlin.android)
|
||||||
|
// id("com.google.gms.google-services")
|
||||||
|
// id("com.google.firebase.firebase-perf")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.jia.er.nebuluxe.app"
|
||||||
|
compileSdk = 35
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "com.jia.er.nebuluxe.app"
|
||||||
|
minSdk = 24
|
||||||
|
targetSdk = 35
|
||||||
|
versionCode = 1
|
||||||
|
versionName = "1.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
// signingConfig = signingConfigs.getByName("debug")
|
||||||
|
}
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = true
|
||||||
|
isShrinkResources = true
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
}
|
||||||
|
buildFeatures {
|
||||||
|
buildConfig = true
|
||||||
|
viewBinding = true
|
||||||
|
}
|
||||||
|
android.applicationVariants.all {
|
||||||
|
val buildType = this.buildType.name
|
||||||
|
val date = SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(Date())
|
||||||
|
outputs.all {
|
||||||
|
if (this is com.android.build.gradle
|
||||||
|
.internal.api.ApkVariantOutputImpl
|
||||||
|
) {
|
||||||
|
this.outputFileName = "Nebuluxe" +
|
||||||
|
"_${android.defaultConfig.versionName}_${android.defaultConfig.versionCode}_${date}_${buildType}.apk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
|
||||||
|
implementation(libs.androidx.core.ktx)
|
||||||
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
|
implementation(libs.androidx.appcompat)
|
||||||
|
implementation(libs.androidx.lifecycle.viewmodel.ktx)
|
||||||
|
implementation(libs.material)
|
||||||
|
implementation(libs.com.github.wuao.flycotablayout2)
|
||||||
|
implementation(libs.io.github.youth5201314.banner)
|
||||||
|
implementation(libs.io.github.cymchad.baserecyclerviewadapterhelper4)
|
||||||
|
implementation(libs.com.github.bumptech.glide.glide2)
|
||||||
|
implementation(libs.org.greenrobot.eventbus3)
|
||||||
|
implementation(libs.androidx.media3.media3.exoplayer2)
|
||||||
|
implementation(libs.androidx.media3.media3.exoplayer.dash2)
|
||||||
|
implementation(libs.androidx.media3.media3.ui2)
|
||||||
|
implementation(libs.androidx.media3.media3.exoplayer.hls2)
|
||||||
|
implementation(libs.androidx.media3.media3.exoplayer.rtsp2)
|
||||||
|
implementation(libs.squareup.okhttp)
|
||||||
|
implementation(libs.squareup.logging.interceptor)
|
||||||
|
implementation(libs.squareup.retrofit)
|
||||||
|
implementation(libs.squareup.converter.gson)
|
||||||
|
implementation(libs.com.tencent.mmkv)
|
||||||
|
implementation(libs.androidx.lifecycle.lifecycle.livedata.ktx3)
|
||||||
|
implementation(libs.androidx.lifecycle.lifecycle.extensions4)
|
||||||
|
implementation(libs.scwang90.refresh.layout.kernel)
|
||||||
|
implementation(libs.scwang90.refresh.header.material)
|
||||||
|
implementation(libs.scwang90.refresh.footer.classics)
|
||||||
|
implementation(libs.com.getkeepsafe.relinker.relinker)
|
||||||
|
implementation(libs.utilcodex)
|
||||||
|
implementation(libs.shapeblurview)
|
||||||
|
implementation(libs.com.google.android.flexbox.flexbox)
|
||||||
|
implementation(libs.play.services.ads.identifier)
|
||||||
|
implementation("com.github.getActivity:ShapeView:9.8")
|
||||||
|
// implementation(libs.android.billing)
|
||||||
|
// implementation(platform(libs.google.firebase.bom))
|
||||||
|
// implementation(libs.google.firebase.messaging.ktx)
|
||||||
|
// implementation(libs.google.firebase.analytics.ktx)
|
||||||
|
// implementation(libs.firebase.perf)
|
||||||
|
// implementation(libs.adjust.android)
|
||||||
|
// implementation(libs.adjust.android.webbridge)
|
||||||
|
// implementation(libs.com.android.installreferrer.installreferrer)
|
||||||
|
// implementation("com.facebook.android:facebook-android-sdk:17.0.2")
|
||||||
|
}
|
21
app/proguard-rules.pro
vendored
Normal file
21
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
61
app/src/main/AndroidManifest.xml
Normal file
61
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||||
|
<application
|
||||||
|
android:name=".basics.MyApplication"
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:networkSecurityConfig="@xml/net"
|
||||||
|
android:theme="@style/Theme.Nebuluxe"
|
||||||
|
tools:targetApi="31">
|
||||||
|
<provider
|
||||||
|
android:name=".basics.MyContentProvider"
|
||||||
|
android:authorities="${applicationId}.mycontentprovider"
|
||||||
|
android:exported="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".main.SplashActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/Theme.Splash">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".main.MainActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:launchMode="singleTask">
|
||||||
|
<intent-filter
|
||||||
|
android:autoVerify="true"
|
||||||
|
tools:ignore="AppLinkUrlError">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="nebuluxe" />
|
||||||
|
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name="com.jia.er.nebuluxe.app.video.PlayerDetailActivity" />
|
||||||
|
<activity android:name="com.jia.er.nebuluxe.app.me.AboutActivity" />
|
||||||
|
<activity android:name="com.jia.er.nebuluxe.app.me.SettingActivity" />
|
||||||
|
<activity android:name="com.jia.er.nebuluxe.app.home.HotActivity" />
|
||||||
|
<activity android:name="com.jia.er.nebuluxe.app.home.RankActivity" />
|
||||||
|
<activity android:name="com.jia.er.nebuluxe.app.home.FreshActivity" />
|
||||||
|
<activity android:name="com.jia.er.nebuluxe.app.home.GenresActivity" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
141
app/src/main/java/com/jia/er/nebuluxe/app/basics/BaseActivity.kt
Normal file
141
app/src/main/java/com/jia/er/nebuluxe/app/basics/BaseActivity.kt
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.basics
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.viewbinding.ViewBinding
|
||||||
|
import com.blankj.utilcode.util.BarUtils
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
|
||||||
|
abstract class BaseActivity<BV : ViewBinding> : AppCompatActivity() {
|
||||||
|
lateinit var binding: BV
|
||||||
|
private var networkErrorView: View? = null
|
||||||
|
private var noDramaView: View? = null
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = getViewBinding()
|
||||||
|
val container = FrameLayout(this).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
addView(
|
||||||
|
binding.root,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
setContentView(container)
|
||||||
|
networkErrorView =
|
||||||
|
layoutInflater.inflate(R.layout.layout_network_error, container, false).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
visibility = View.INVISIBLE
|
||||||
|
findViewById<AppCompatTextView>(R.id.tv_example_retry)?.setOnClickListener {
|
||||||
|
onRetry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container.addView(networkErrorView)
|
||||||
|
noDramaView =
|
||||||
|
layoutInflater.inflate(R.layout.layout_no_drama, container, false).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
visibility = View.INVISIBLE
|
||||||
|
findViewById<AppCompatTextView>(R.id.tv_example_retry)?.setOnClickListener {
|
||||||
|
onReturn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container.addView(noDramaView)
|
||||||
|
BarUtils.transparentStatusBar(this)
|
||||||
|
BarUtils.setStatusBarLightMode(this, false)
|
||||||
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
top()
|
||||||
|
center()
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(container) { v, insets ->
|
||||||
|
val systemInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
|
||||||
|
v.setPadding(0, 0, 0, systemInsets.bottom)
|
||||||
|
window.navigationBarColor = ContextCompat.getColor(this, R.color.black)
|
||||||
|
insets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun top()
|
||||||
|
protected abstract fun center()
|
||||||
|
protected abstract fun getViewBinding(): BV
|
||||||
|
|
||||||
|
protected open fun onRetry() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun onReturn() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showNetError() {
|
||||||
|
networkErrorView?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideNetError() {
|
||||||
|
networkErrorView?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showNoDrama(){
|
||||||
|
noDramaView?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
private var loadingDialog: Dialog? = null
|
||||||
|
|
||||||
|
protected open fun showLoading(
|
||||||
|
message: String = "Loading..."
|
||||||
|
) {
|
||||||
|
if (loadingDialog?.isShowing == true) return
|
||||||
|
|
||||||
|
loadingDialog = Dialog(this, R.style.FullScreenLoadingDialog).apply {
|
||||||
|
setContentView(R.layout.dialog_loading)
|
||||||
|
window?.apply {
|
||||||
|
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
|
decorView.setBackgroundColor(Color.argb(150, 0, 0, 0))
|
||||||
|
}
|
||||||
|
setCancelable(true)
|
||||||
|
findViewById<TextView>(R.id.tv_loading_text)?.text = message
|
||||||
|
}
|
||||||
|
loadingDialog?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun hideLoading() {
|
||||||
|
loadingDialog?.takeIf { it.isShowing }?.dismiss()
|
||||||
|
loadingDialog = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showKeyBord(mEditText: EditText, mContext: Context) {
|
||||||
|
val imm = mContext.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
imm.showSoftInput(mEditText, InputMethodManager.RESULT_SHOWN)
|
||||||
|
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideKeyBord(mEditText: EditText, mContext: Context) {
|
||||||
|
val imm = mContext.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
imm.hideSoftInputFromWindow(mEditText.windowToken, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.basics
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.viewbinding.ViewBinding
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
|
||||||
|
abstract class BaseFragment<VB : ViewBinding> : Fragment() {
|
||||||
|
lateinit var binding: VB
|
||||||
|
var networkErrorView: View? = null
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
binding = getViewBinding()
|
||||||
|
val layout = FrameLayout(requireContext()).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
addView(
|
||||||
|
binding.root,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
networkErrorView =
|
||||||
|
layoutInflater.inflate(R.layout.layout_network_error, layout, false).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
visibility = View.INVISIBLE
|
||||||
|
findViewById<AppCompatTextView>(R.id.tv_example_retry)?.setOnClickListener {
|
||||||
|
onRetry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layout.addView(networkErrorView)
|
||||||
|
return layout
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun onRetry() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showNetError() {
|
||||||
|
networkErrorView?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideNetError() {
|
||||||
|
networkErrorView?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
top()
|
||||||
|
center()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun top()
|
||||||
|
protected abstract fun center()
|
||||||
|
protected abstract fun getViewBinding(): VB
|
||||||
|
|
||||||
|
private var loadingDialog: Dialog? = null
|
||||||
|
|
||||||
|
protected open fun showLoading(
|
||||||
|
message: String = "Loading..."
|
||||||
|
) {
|
||||||
|
if (loadingDialog?.isShowing == true) return
|
||||||
|
|
||||||
|
loadingDialog = Dialog(requireContext(), R.style.FullScreenLoadingDialog).apply {
|
||||||
|
setContentView(R.layout.dialog_loading)
|
||||||
|
window?.apply {
|
||||||
|
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
|
decorView.setBackgroundColor(Color.argb(150, 0, 0, 0))
|
||||||
|
}
|
||||||
|
setCancelable(true)
|
||||||
|
|
||||||
|
findViewById<TextView>(R.id.tv_loading_text)?.text = message
|
||||||
|
}
|
||||||
|
loadingDialog?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun hideLoading() {
|
||||||
|
loadingDialog?.takeIf { it.isShowing }?.dismiss()
|
||||||
|
loadingDialog = null
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.basics
|
||||||
|
|
||||||
|
|
||||||
|
object Constants {
|
||||||
|
var isUat = false
|
||||||
|
const val Constants_BASE_URL_RES = "https://api-nebuluxetv.nebuluxetv.com/xe/"
|
||||||
|
const val CONSTANTS_AuthorizationExample = "Authorization"
|
||||||
|
const val CONSTANTS_device_id = "device-id"
|
||||||
|
const val CONSTANTS_device_gaid = "device-gaid"
|
||||||
|
const val CONSTANTS_app_name = "app-name"
|
||||||
|
const val CONSTANTS_app_version = "app-version"
|
||||||
|
const val CONSTANTS_system_type = "system-type"
|
||||||
|
const val CONSTANTS_lang_key = "lang-key"
|
||||||
|
const val CONSTANTS_time_zone = "time-zone"
|
||||||
|
const val CONSTANTS_model = "model"
|
||||||
|
const val CONSTANTS_brand = "brand"
|
||||||
|
const val CONSTANTS_edit = "CONSTANTS_edit"
|
||||||
|
const val CONSTANTS_system_version = "system-version"
|
||||||
|
const val CONSTANTS_auth_refresh = "CONSTANTS_auth_refresh"
|
||||||
|
const val CONSTANTS_User_STRING = "CONSTANTS_User_STRING"
|
||||||
|
const val CONSTANTS_SEARCH_STRINGExample = "searchString"
|
||||||
|
const val CONSTANTS_main_stop = "CONSTANTS_main_stop"
|
||||||
|
const val CONSTANTS_short_play_id = "CONSTANTS_short_play_id"
|
||||||
|
const val Constants_Episodes_Series_Data_currentPositionExample =
|
||||||
|
"Constants_Episodes_Series_Data_currentPositionExample"
|
||||||
|
const val Constants_Episodes_Series_Data_ListExample =
|
||||||
|
"Constants_Episodes_Series_Data_ListExample"
|
||||||
|
const val Constants_Episodes_Series_DataExample = "Constants_Episodes_Series_DataExample"
|
||||||
|
const val CONSTANTS_activity_id = "activity_id"
|
||||||
|
const val CONSTANTS_refresh_me = "CONSTANTS_refresh_me"
|
||||||
|
const val Constants_DDL_Url = "Constants_DDL_Url"
|
||||||
|
const val CONSTANTS_leaveApp = "CONSTANTS_leaveApp"
|
||||||
|
const val CONSTANTS_enterTheApp = "CONSTANTS_enterTheApp"
|
||||||
|
const val CONSTANTS_onLine = "CONSTANTS_onLine"
|
||||||
|
const val CONSTANTS_examplePayReq = "CONSTANTS_examplePayReq"
|
||||||
|
const val CONSTANTS_Episode = "CONSTANTS_Episode"
|
||||||
|
const val CONSTANTS_pay_refresh = "CONSTANTS_pay_refresh"
|
||||||
|
const val CONSTANTS_collect_refresh = "CONSTANTS_collect_refresh"
|
||||||
|
const val Constants_onTokenRefresh = "onTokenRefresh"
|
||||||
|
const val Constants_getClip = "Constants_getClip"
|
||||||
|
const val CONSTANTS_web_Login = "CONSTANTS_web_Login"
|
||||||
|
const val CONSTANTS_PREF_LAST_POPUP_TIME_Notification =
|
||||||
|
"CONSTANTS_PREF_LAST_POPUP_TIME_Notification"
|
||||||
|
const val ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000L
|
||||||
|
var CanNotification: Boolean = false
|
||||||
|
const val CONSTANTS_Detail_id = "CONSTANTS_Detail_id"
|
||||||
|
const val Constants_requestPermissions_photo = "Constants_requestPermissions_photo"
|
||||||
|
const val Constants_requestPermissions_photo_detail =
|
||||||
|
"Constants_requestPermissions_photo_detail"
|
||||||
|
const val Constants_openFeedbackDetail = "Constants_openFeedbackDetail"
|
||||||
|
const val Constants_openFeedback = "Constants_openFeedback"
|
||||||
|
const val CONSTANTS_web_notification = "CONSTANTS_web_notification"
|
||||||
|
const val feedback_URL_res: String = "https://campaign.nebuluxetv.com/pages/leave/index"
|
||||||
|
const val feedback_list_URL_res: String = "https://campaign.nebuluxetv.com/pages/leave/list"
|
||||||
|
const val feedback_detail_URL_res: String = "https://campaign.nebuluxetv.com/pages/leave/detail"
|
||||||
|
const val Constants_Main_Video_status = "Constants_Main_Video_status"
|
||||||
|
const val Constants_Main_Video_info = "Constants_Main_Video_info"
|
||||||
|
var WebRefresh: Boolean = false
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.basics
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import com.jia.er.nebuluxe.app.BuildConfig.DEBUG
|
||||||
|
//import com.adjust.sdk.Adjust
|
||||||
|
//import com.adjust.sdk.AdjustConfig
|
||||||
|
//import com.adjust.sdk.LogLevel
|
||||||
|
//import com.adjust.sdk.OnEventTrackingFailedListener
|
||||||
|
//import com.adjust.sdk.OnEventTrackingSucceededListener
|
||||||
|
//import com.facebook.FacebookSdk
|
||||||
|
//import com.facebook.LoggingBehavior
|
||||||
|
//import com.facebook.appevents.AppEventsLogger
|
||||||
|
//import com.facebook.applinks.AppLinkData
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
|
||||||
|
class MyApplication : Application() {
|
||||||
|
private val LOG_TAG: String = "MyApplication"
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
lateinit var context: Context
|
||||||
|
var isAppInBackground = true
|
||||||
|
var countActivity = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
context = this
|
||||||
|
// initAdjust()
|
||||||
|
if (DEBUG) {
|
||||||
|
registerActivityLifecycleCallbacks(AdjustLifecycleCallbacks())
|
||||||
|
}
|
||||||
|
// registerActivityLifecycleCallbacks({
|
||||||
|
// fun onActivityResumed(activity: Activity) {
|
||||||
|
// Log.d("onResume", activity.javaClass.simpleName)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } as ActivityLifecycleCallbacks?)
|
||||||
|
// GlobalScope.launch(Dispatchers.Main) {
|
||||||
|
// initFacebookSdk()
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// private fun initAdjust() {
|
||||||
|
// val appToken = "dmq04yk7ftvk"
|
||||||
|
// val environment = AdjustConfig.ENVIRONMENT_PRODUCTION
|
||||||
|
// val config = AdjustConfig(context, appToken, environment)
|
||||||
|
// config.setLogLevel(LogLevel.VERBOSE)
|
||||||
|
// config.onEventTrackingSucceededListener =
|
||||||
|
// OnEventTrackingSucceededListener { adjustEventSuccess ->
|
||||||
|
// Log.d(LOG_TAG, "Event recorded at " + adjustEventSuccess.timestamp)
|
||||||
|
// }
|
||||||
|
// config.onEventTrackingFailedListener =
|
||||||
|
// OnEventTrackingFailedListener { adjustEventFailure ->
|
||||||
|
// Log.v(
|
||||||
|
// LOG_TAG,
|
||||||
|
// "Event recording failed. Response: " + adjustEventFailure.message
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// config.setOnDeferredDeeplinkResponseListener { deeplink ->
|
||||||
|
// Log.d(LOG_TAG, "Deferred deep link callback called!")
|
||||||
|
// Log.d(LOG_TAG, "Deep link URL: $deeplink")
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putString(Constants.Constants_DDL_Url, deeplink.toString())
|
||||||
|
// EventBus.getDefault().post(Constants.Constants_DDL_Url)
|
||||||
|
// true
|
||||||
|
// }
|
||||||
|
// Adjust.initSdk(config)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
inner class AdjustLifecycleCallbacks : ActivityLifecycleCallbacks {
|
||||||
|
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
|
||||||
|
override fun onActivityStarted(activity: Activity) {
|
||||||
|
// countActivity++
|
||||||
|
// if (countActivity == 1 && isAppInBackground) {
|
||||||
|
// isAppInBackground = false
|
||||||
|
// Log.d("Lifecycle", "onActivityStarted")
|
||||||
|
// EventBus.getDefault().post(Constants.CONSTANTS_enterTheApp)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResumed(activity: Activity) {
|
||||||
|
// Adjust.onResume()
|
||||||
|
Log.d("onResume", "=========" + activity.javaClass.simpleName + "=========")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityPaused(activity: Activity) {
|
||||||
|
// Adjust.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStopped(activity: Activity) {
|
||||||
|
// countActivity--
|
||||||
|
// if (countActivity <= 0 && !isAppInBackground) {
|
||||||
|
// isAppInBackground = true
|
||||||
|
// Log.d("Lifecycle", "onActivityStopped")
|
||||||
|
// EventBus.getDefault().post(Constants.CONSTANTS_leaveApp)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||||
|
override fun onActivityDestroyed(activity: Activity) {}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// private fun initFacebookSdk() {
|
||||||
|
// FacebookSdk.setAutoInitEnabled(true)
|
||||||
|
// FacebookSdk.fullyInitialize()
|
||||||
|
// if (Constants.isUat) {
|
||||||
|
// FacebookSdk.setIsDebugEnabled(true)
|
||||||
|
// FacebookSdk.addLoggingBehavior(LoggingBehavior.APP_EVENTS)
|
||||||
|
// }
|
||||||
|
// AppEventsLogger.activateApp(this)
|
||||||
|
// AppLinkData.fetchDeferredAppLinkData(
|
||||||
|
// this
|
||||||
|
// ) {
|
||||||
|
// // Process app link data
|
||||||
|
// if (null != it) {
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putString(Constants.Constants_DDL_Url, it.targetUri.toString())
|
||||||
|
// Log.d(
|
||||||
|
// "initFacebookSdk",
|
||||||
|
// "fetchDeferredAppLinkData callback called!====${it.targetUri}"
|
||||||
|
// )
|
||||||
|
// EventBus.getDefault().post(Constants.Constants_DDL_Url)
|
||||||
|
// }
|
||||||
|
// Log.d("initFacebookSdk", "fetchDeferredAppLinkData callback called!")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.basics
|
||||||
|
|
||||||
|
import android.content.ContentProvider
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.net.Uri
|
||||||
|
import com.getkeepsafe.relinker.ReLinker
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
|
||||||
|
class MyContentProvider : ContentProvider() {
|
||||||
|
override fun onCreate(): Boolean {
|
||||||
|
initMMKV()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initMMKV() {
|
||||||
|
try {
|
||||||
|
context?.let { MMKV.initialize(it) }
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
try {
|
||||||
|
val dir: String = context?.filesDir?.absolutePath + "/mmkv"
|
||||||
|
MMKV.initialize(context, dir) { libName -> ReLinker.loadLibrary(
|
||||||
|
context, libName) }
|
||||||
|
} catch (e2: Exception) {
|
||||||
|
e2.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
override fun query(
|
||||||
|
uri: Uri,
|
||||||
|
projection: Array<out String>?,
|
||||||
|
selection: String?,
|
||||||
|
selectionArgs: Array<out String>?,
|
||||||
|
sortOrder: String?
|
||||||
|
): Cursor? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(uri: Uri): String? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun insert(uri: Uri, values: ContentValues?): Uri? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(
|
||||||
|
uri: Uri,
|
||||||
|
values: ContentValues?,
|
||||||
|
selection: String?,
|
||||||
|
selectionArgs: Array<out String>?
|
||||||
|
): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
130
app/src/main/java/com/jia/er/nebuluxe/app/data/AndroidBridge.kt
Normal file
130
app/src/main/java/com/jia/er/nebuluxe/app/data/AndroidBridge.kt
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.webkit.JavascriptInterface
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.jia.er.nebuluxe.app.net.Retrofit.getCurrentTimeZone
|
||||||
|
import com.jia.er.nebuluxe.app.utils.Memory
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.JsonParser
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.video.PlayerDetailActivity
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
class AndroidBridge(private val context: Context) {
|
||||||
|
@JavascriptInterface
|
||||||
|
fun getUserInfo(): String {
|
||||||
|
val jsInfo = ReelCrushJsInfo(
|
||||||
|
Memory.getMMKV()
|
||||||
|
.getString(Constants.CONSTANTS_AuthorizationExample, "")
|
||||||
|
.toString(),
|
||||||
|
getCurrentTimeZone(),
|
||||||
|
Memory.getMMKV().getString(Constants.CONSTANTS_lang_key, "en")
|
||||||
|
.toString(),
|
||||||
|
"android",
|
||||||
|
Memory.getMMKV().getString(Constants.CONSTANTS_Detail_id, "")
|
||||||
|
.toString(),"theme_1"
|
||||||
|
)
|
||||||
|
return Gson().toJson(jsInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun js2app(string: String) {
|
||||||
|
val parser = JsonParser()
|
||||||
|
val rootJson = parser.parse(string) as JsonObject
|
||||||
|
when (rootJson.get("type").asString) {
|
||||||
|
|
||||||
|
"open_notify" -> {
|
||||||
|
singleClick {
|
||||||
|
EventBus.getDefault().post(Constants.CONSTANTS_web_notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"watch_video" -> {
|
||||||
|
singleClick {
|
||||||
|
val fromJson = Gson().fromJson(string, JsonInfo::class.java)
|
||||||
|
context.startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id,
|
||||||
|
fromJson.data?.short_play_id
|
||||||
|
)
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_activity_id,
|
||||||
|
fromJson.data?.activity_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun openFeedbackDetail(id: String) {
|
||||||
|
EventBus.getDefault()
|
||||||
|
.post(BaseEventBus(Constants.Constants_openFeedbackDetail, id))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun openFeedbackList() {
|
||||||
|
EventBus.getDefault()
|
||||||
|
.post(Constants.Constants_openFeedback)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun openPhotoPicker() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
if (ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.READ_MEDIA_IMAGES
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
openFilePicker()
|
||||||
|
} else {
|
||||||
|
EventBus.getDefault().post(Constants.Constants_requestPermissions_photo)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
) == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
) == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.CAMERA
|
||||||
|
) == PackageManager.PERMISSION_GRANTED)
|
||||||
|
) {
|
||||||
|
openFilePicker()
|
||||||
|
} else {
|
||||||
|
EventBus.getDefault().post(Constants.Constants_requestPermissions_photo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val REQUEST_PICK_FILE: Int = 1002
|
||||||
|
|
||||||
|
private fun openFilePicker() {
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "image/*"
|
||||||
|
}
|
||||||
|
(context as? Activity)?.startActivityForResult(intent, REQUEST_PICK_FILE)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.webkit.JavascriptInterface
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.jia.er.nebuluxe.app.utils.Memory
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.net.Retrofit.getCurrentTimeZone
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
class AndroidBridgeDetail(private val context: Context) {
|
||||||
|
@JavascriptInterface
|
||||||
|
fun getUserInfo(): String {
|
||||||
|
val moviaJsInfo = ReelCrushJsInfo(
|
||||||
|
Memory.getMMKV()
|
||||||
|
.getString(Constants.CONSTANTS_AuthorizationExample, "")
|
||||||
|
.toString(),
|
||||||
|
getCurrentTimeZone(),
|
||||||
|
Memory.getMMKV().getString(Constants.CONSTANTS_lang_key, "en")
|
||||||
|
.toString(),
|
||||||
|
"android",
|
||||||
|
Memory.getMMKV().getString(Constants.CONSTANTS_Detail_id, "")
|
||||||
|
.toString(),"theme_1"
|
||||||
|
)
|
||||||
|
return Gson().toJson(moviaJsInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun openPhotoPicker() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
if (ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.READ_MEDIA_IMAGES
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
openFilePicker()
|
||||||
|
} else {
|
||||||
|
EventBus.getDefault().post(Constants.Constants_requestPermissions_photo_detail)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
) == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
) == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.CAMERA
|
||||||
|
) == PackageManager.PERMISSION_GRANTED)
|
||||||
|
) {
|
||||||
|
openFilePicker()
|
||||||
|
} else {
|
||||||
|
EventBus.getDefault().post(Constants.Constants_requestPermissions_photo_detail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val REQUEST_PICK_FILE: Int = 1003
|
||||||
|
|
||||||
|
private fun openFilePicker() {
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "image/*"
|
||||||
|
}
|
||||||
|
(context as? Activity)?.startActivityForResult(intent, REQUEST_PICK_FILE)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class BaseEventBus<T>(val code: String, val data: T)
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class BaseRes<T>(
|
||||||
|
val code: Int,
|
||||||
|
val msg: String,
|
||||||
|
val data: T?)
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class BuyVideoRes(
|
||||||
|
val status: String,
|
||||||
|
val coin_left_total: Int,
|
||||||
|
val send_coin_left_total: Int
|
||||||
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class CategoriesDataRes(
|
||||||
|
val list: ArrayList<Item8>
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Item8(
|
||||||
|
val id: Int,
|
||||||
|
val name: String
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class CollectionRes(
|
||||||
|
val list: List<CollectionData>,
|
||||||
|
val pagination: Pagination
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class CollectionData(
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val current_episode: Int,
|
||||||
|
val short_play_video_id: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Pagination(
|
||||||
|
val current_page: Int,
|
||||||
|
val page_size: Int,
|
||||||
|
val page_total: Int,
|
||||||
|
val total_size: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class CreateOrderReq(
|
||||||
|
val pay_setting_id: String,
|
||||||
|
val payment_channel: String,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val video_id: Int
|
||||||
|
)
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class CreateOrderRes(
|
||||||
|
val order_code: String
|
||||||
|
)
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class CustomerBuyRecordsRes(
|
||||||
|
val list: List<Data>
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Data(
|
||||||
|
val coin_type: Int,
|
||||||
|
val coins: Int,
|
||||||
|
val created_at: String,
|
||||||
|
val episode: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val is_grounding: Int,
|
||||||
|
val name: String,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val short_play_video_id: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class CustomerOrderRes(
|
||||||
|
val list: List<Item0>,
|
||||||
|
val pagination: Pagination
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Item0(
|
||||||
|
val created_at: String,
|
||||||
|
val type: String,
|
||||||
|
val value: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Pagination(
|
||||||
|
val current_page: Int,
|
||||||
|
val page_size: Int,
|
||||||
|
val page_total: Int,
|
||||||
|
val total_size: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class DetailsRecommendRes(
|
||||||
|
val brief: String,
|
||||||
|
val description: String,
|
||||||
|
val list: List<Item>,
|
||||||
|
val tag: String,
|
||||||
|
val title: String
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Item(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val video_url: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int?,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class ExampleKeywordDataRes(
|
||||||
|
val list: List<KeywordData>,
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class KeywordData(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val categoryList: List<Category>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Long,
|
||||||
|
val search_click_total: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Category(
|
||||||
|
val id: Int,
|
||||||
|
val name: String
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class FbNotificationReq(val is_open_notice: String)
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class FreeSeriesMoreRes(
|
||||||
|
val list: List<Item9>
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Item9(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class HistoryDataRes(
|
||||||
|
val list: List<Data>,
|
||||||
|
val pagination: Pagination
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Data(
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val category: List<String>,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val short_play_id: Int,
|
||||||
|
var is_collect: Int,
|
||||||
|
val current_episode: Int,
|
||||||
|
val short_play_video_id: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Pagination(
|
||||||
|
val current_page: Int,
|
||||||
|
val page_size: Int,
|
||||||
|
val page_total: Int,
|
||||||
|
val total_size: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class HomeBannerAndNineSquarepRes(
|
||||||
|
val arrangement: String,
|
||||||
|
val list: List<Item0>,
|
||||||
|
val title: String
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Item0(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val category: List<String>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val ffmpeg_id: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val jump_ffmpeg_id: Int,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val video_url: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class HomeBannerBean(
|
||||||
|
val all_coins: Any,
|
||||||
|
val buy_type: Int,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val video_url: String,
|
||||||
|
val watch_total: Int,
|
||||||
|
val category: List<String>
|
||||||
|
)
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
|
||||||
|
class HomeBestSellersData : ArrayList<HomeBestSellersData.HomeBestSellersDataItem>() {
|
||||||
|
data class HomeBestSellersDataItem(
|
||||||
|
val all_coins: String,
|
||||||
|
val buy_type: Int,
|
||||||
|
val categoryList: List<Category>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Category(
|
||||||
|
val id: Int,
|
||||||
|
val name: String
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement
|
||||||
|
|
||||||
|
|
||||||
|
class HomeModuleBean(
|
||||||
|
val list: List<RecommandDataBean>,
|
||||||
|
) {
|
||||||
|
data class RecommandDataBean(
|
||||||
|
val module_key :String,
|
||||||
|
val data: JsonElement
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class HomeNewShortPlayNoPaginateRes(
|
||||||
|
val list: List<Item8>
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Item8(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val category: List<String>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class HomeNewShortPlayRes(
|
||||||
|
val category_list: List<Category>,
|
||||||
|
val pagination: Pagination,
|
||||||
|
val ranking_list: List<Ranking>,
|
||||||
|
val short_play_list: MutableList<ShortPlay>
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Category(
|
||||||
|
val category_id: Int,
|
||||||
|
val category_name: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Pagination(
|
||||||
|
val current_page: Int,
|
||||||
|
val page_size: Int,
|
||||||
|
val page_total: Int,
|
||||||
|
val total_size: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Ranking(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ShortPlay(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val category: List<String>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
var view_type: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Int,
|
||||||
|
var ranking_list: List<Ranking>,
|
||||||
|
var category_list: List<Category>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class HomeRankingRes(
|
||||||
|
val list: List<Item7>
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Item7(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val category: List<String>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Long
|
||||||
|
)
|
||||||
|
}
|
30
app/src/main/java/com/jia/er/nebuluxe/app/data/HomeTopRes.kt
Normal file
30
app/src/main/java/com/jia/er/nebuluxe/app/data/HomeTopRes.kt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class HomeTopRes(
|
||||||
|
val category: List<Category>,
|
||||||
|
val hotData: List<HotData>
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Category(
|
||||||
|
val category_id: Int,
|
||||||
|
val category_name: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class HotData(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class HomeTopWeekRes(
|
||||||
|
val list: List<Item8>
|
||||||
|
){
|
||||||
|
|
||||||
|
data class Item8(
|
||||||
|
val all_coins: String,
|
||||||
|
val buy_type: Int,
|
||||||
|
val category: List<String>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val search_click_total: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val video_url: String,
|
||||||
|
val watch_total: Int
|
||||||
|
)}
|
14
app/src/main/java/com/jia/er/nebuluxe/app/data/JsonInfo.kt
Normal file
14
app/src/main/java/com/jia/er/nebuluxe/app/data/JsonInfo.kt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class JsonInfo(
|
||||||
|
val `data`: Data?,
|
||||||
|
val is_complete: Boolean,
|
||||||
|
val is_show: Int,
|
||||||
|
val type: String
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Data(
|
||||||
|
val activity_id: Int,
|
||||||
|
val short_play_id: Int?
|
||||||
|
)
|
||||||
|
}
|
10
app/src/main/java/com/jia/er/nebuluxe/app/data/LoginReq.kt
Normal file
10
app/src/main/java/com/jia/er/nebuluxe/app/data/LoginReq.kt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class LoginReq(
|
||||||
|
val avator: String,
|
||||||
|
val email: String,
|
||||||
|
val family_name: String,
|
||||||
|
val giving_name: String,
|
||||||
|
val platform: String,
|
||||||
|
val third_id: String
|
||||||
|
)
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class LoginRes(
|
||||||
|
val customer_id: String,
|
||||||
|
val token: String
|
||||||
|
)
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class MainDataHis(
|
||||||
|
val episode_total: String,
|
||||||
|
val video_id: Int,
|
||||||
|
val video_last: String,
|
||||||
|
val video_img: String
|
||||||
|
)
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class NoticeNumRes(
|
||||||
|
val feedback_notice_num: Int
|
||||||
|
)
|
11
app/src/main/java/com/jia/er/nebuluxe/app/data/PayReq.kt
Normal file
11
app/src/main/java/com/jia/er/nebuluxe/app/data/PayReq.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class PayReq(
|
||||||
|
val order_code: String,
|
||||||
|
val pay_setting_id: String,//id
|
||||||
|
val pkg_name: String,
|
||||||
|
val product_id: String,//template id
|
||||||
|
val purchases_token: String,
|
||||||
|
val transaction_id: String,
|
||||||
|
val show_money: String,
|
||||||
|
)
|
8
app/src/main/java/com/jia/er/nebuluxe/app/data/PayRes.kt
Normal file
8
app/src/main/java/com/jia/er/nebuluxe/app/data/PayRes.kt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class PayRes(
|
||||||
|
val is_backhaul: Int,
|
||||||
|
val money: String,
|
||||||
|
val order_code: String,
|
||||||
|
val status: String
|
||||||
|
)
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class PaySettingRes(
|
||||||
|
val list_coins: List<Coins>,
|
||||||
|
val sort: List<String>,
|
||||||
|
val list_sub_vip: List<Vip>,
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Coins(
|
||||||
|
val android_template_id: String,
|
||||||
|
val backhaul_price: String,
|
||||||
|
val brief: String,
|
||||||
|
val buy_type: String,
|
||||||
|
val coins: Int,
|
||||||
|
val created_at: String,
|
||||||
|
val currency: String,
|
||||||
|
var currency_goolge: String?,
|
||||||
|
val description: String,
|
||||||
|
val id: Int,
|
||||||
|
val ios_template_id: String,
|
||||||
|
val corner_marker: String,
|
||||||
|
val lang_id: Int,
|
||||||
|
val origin_price: String,
|
||||||
|
val platform: String,
|
||||||
|
val price: String,
|
||||||
|
var price_google: String?,
|
||||||
|
val send_coins: Int,
|
||||||
|
val sort: Int,
|
||||||
|
val status: String,
|
||||||
|
val title: String,
|
||||||
|
val size: String,
|
||||||
|
val translate_key: String,
|
||||||
|
val updated_at: String,
|
||||||
|
val vip_type: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Vip(
|
||||||
|
val android_template_id: String,
|
||||||
|
val backhaul_price: String,
|
||||||
|
val brief: String,
|
||||||
|
val short_type: String,
|
||||||
|
val buy_type: String,
|
||||||
|
val coins: Int,
|
||||||
|
val corner_marker: String,
|
||||||
|
val created_at: String,
|
||||||
|
val currency: String,
|
||||||
|
var currency_goolge: String?,
|
||||||
|
val description: String,
|
||||||
|
val id: Int,
|
||||||
|
val ios_template_id: String,
|
||||||
|
val lang_id: Int,
|
||||||
|
val origin_price: String,
|
||||||
|
val platform: String,
|
||||||
|
val price: String,
|
||||||
|
var price_google: String?,
|
||||||
|
val send_coins: Int,
|
||||||
|
val send_coin_ttl: Int,
|
||||||
|
val sort: Int,
|
||||||
|
var show: Int,
|
||||||
|
val status: String,
|
||||||
|
val title: String,
|
||||||
|
val translate_key: String,
|
||||||
|
val updated_at: String,
|
||||||
|
val auto_sub: String,
|
||||||
|
var vip_type: String,
|
||||||
|
var vip_type_key: String,
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
import android.os.Parcel
|
||||||
|
import android.os.Parcelable
|
||||||
|
|
||||||
|
data class PlayerDetailDataRes(
|
||||||
|
val episodeList: List<Episode>,
|
||||||
|
val is_collect: Boolean,
|
||||||
|
val show_share_coin: Boolean,
|
||||||
|
val share_coin: Int,
|
||||||
|
val install_coins: Int,
|
||||||
|
val unlock_video_ad_count: Int,
|
||||||
|
val revolution: Int,
|
||||||
|
val discount: Int,
|
||||||
|
var jump_type: Int,
|
||||||
|
var jump_short_play_id: Int,
|
||||||
|
var business_model: String,
|
||||||
|
val shortPlayInfo: ShortPlayInfo,
|
||||||
|
val video_info: VideoInfo
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Episode(
|
||||||
|
val coins: Int,
|
||||||
|
val episode: Int,
|
||||||
|
val id: Int,
|
||||||
|
var is_lock: Boolean,
|
||||||
|
val is_vip: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val short_play_video_id: Int,
|
||||||
|
val video_url: String,
|
||||||
|
val vip_coins: Int,
|
||||||
|
var play_seconds: String?,
|
||||||
|
var shortPlayInfo: ShortPlayInfo?,
|
||||||
|
var promise_view_ad: Int,
|
||||||
|
): Parcelable {
|
||||||
|
constructor(parcel: Parcel) : this(
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readByte() != 0.toByte(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readString().toString(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readString(),
|
||||||
|
parcel.readParcelable(ShortPlayInfo::class.java.classLoader),
|
||||||
|
parcel.readInt()
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeInt(coins)
|
||||||
|
parcel.writeInt(episode)
|
||||||
|
parcel.writeInt(id)
|
||||||
|
parcel.writeByte(if (is_lock) 1 else 0)
|
||||||
|
parcel.writeInt(is_vip)
|
||||||
|
parcel.writeInt(short_play_id)
|
||||||
|
parcel.writeInt(short_play_video_id)
|
||||||
|
parcel.writeString(video_url)
|
||||||
|
parcel.writeInt(vip_coins)
|
||||||
|
parcel.writeString(play_seconds)
|
||||||
|
parcel.writeParcelable(shortPlayInfo, flags)
|
||||||
|
parcel.writeInt(promise_view_ad)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<Episode> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): Episode {
|
||||||
|
return Episode(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<Episode?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ShortPlayInfo(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
var collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val category: ArrayList<String>?,
|
||||||
|
val episode_total: Int,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
var is_collect: Boolean,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val watch_total: Int
|
||||||
|
): Parcelable {
|
||||||
|
constructor(parcel: Parcel) : this(
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readString().toString(),
|
||||||
|
parcel.createStringArrayList(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readString().toString(),
|
||||||
|
parcel.readByte() != 0.toByte(),
|
||||||
|
parcel.readString().toString(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt(),
|
||||||
|
parcel.readInt()
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||||
|
parcel.writeInt(all_coins)
|
||||||
|
parcel.writeInt(buy_type)
|
||||||
|
parcel.writeInt(collect_total)
|
||||||
|
parcel.writeString(description)
|
||||||
|
parcel.writeStringList(category)
|
||||||
|
parcel.writeInt(episode_total)
|
||||||
|
parcel.writeInt(id)
|
||||||
|
parcel.writeString(image_url)
|
||||||
|
parcel.writeByte(if (is_collect) 1 else 0)
|
||||||
|
parcel.writeString(name)
|
||||||
|
parcel.writeInt(process)
|
||||||
|
parcel.writeInt(short_id)
|
||||||
|
parcel.writeInt(watch_total)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun describeContents(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object CREATOR : Parcelable.Creator<ShortPlayInfo> {
|
||||||
|
override fun createFromParcel(parcel: Parcel): ShortPlayInfo {
|
||||||
|
return ShortPlayInfo(parcel)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newArray(size: Int): Array<ShortPlayInfo?> {
|
||||||
|
return arrayOfNulls(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data class VideoInfo(
|
||||||
|
val coins: Int,
|
||||||
|
val episode: Int,
|
||||||
|
val id: Int,
|
||||||
|
val is_vip: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val short_play_video_id: Int,
|
||||||
|
val promise_view_ad: Int,
|
||||||
|
val video_url: String,
|
||||||
|
val vip_coins: Int
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class RecommendDataRes(
|
||||||
|
val list: List<Data>,
|
||||||
|
val pagination: Pagination
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class Data(
|
||||||
|
val all_price_total: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
var collect_total: Int?,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
var is_collect: Boolean,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val video_info: VideoInfo?,
|
||||||
|
val watch_total: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Pagination(
|
||||||
|
val current_page: Int,
|
||||||
|
val page_size: Int,
|
||||||
|
val page_total: Int,
|
||||||
|
val total_size: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
data class VideoInfo(
|
||||||
|
val episode: Int,
|
||||||
|
val id: Int,
|
||||||
|
val is_vip: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val short_play_video_id: Int,
|
||||||
|
val video_url: String,
|
||||||
|
val image_url: String
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class ReelCrushJsInfo(
|
||||||
|
val token: String,
|
||||||
|
val time_zone: String,
|
||||||
|
val lang: String,
|
||||||
|
val type: String,
|
||||||
|
val id: String,
|
||||||
|
val theme: String
|
||||||
|
)
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class RewardCoinsRes(val list: List<ExampleRewardCoinsResItem>) {
|
||||||
|
data class ExampleRewardCoinsResItem(
|
||||||
|
val coins: Int,
|
||||||
|
val created_at: String,
|
||||||
|
val diff_datetime: String,
|
||||||
|
val expired_time: Int,
|
||||||
|
val id: Int,
|
||||||
|
val is_effective: Int,
|
||||||
|
val left_coins: String,
|
||||||
|
val type: String
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
|
||||||
|
class ShortListCategoryDataInfo(
|
||||||
|
val list: List<CategoryListData>,
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class CategoryListData(
|
||||||
|
|
||||||
|
val id: Int,
|
||||||
|
val category_name: String,
|
||||||
|
val short_play_list: List<ShortPlayListData>
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ShortPlayListData(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Long
|
||||||
|
)
|
||||||
|
}
|
20
app/src/main/java/com/jia/er/nebuluxe/app/data/TabEntity.kt
Normal file
20
app/src/main/java/com/jia/er/nebuluxe/app/data/TabEntity.kt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
import com.flyco.tablayout.listener.CustomTabEntity
|
||||||
|
|
||||||
|
class TabEntity(var s1: String, var i1: Int, var i2: Int) :
|
||||||
|
CustomTabEntity {
|
||||||
|
|
||||||
|
override fun getTabTitle(): String {
|
||||||
|
return s1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTabSelectedIcon(): Int {
|
||||||
|
return i1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTabUnselectedIcon(): Int {
|
||||||
|
return i2
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class UploadHistoryReq(
|
||||||
|
val play_seconds: Long?,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val video_id: Int?
|
||||||
|
)
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class UserInfoRes(
|
||||||
|
val avator: String = "",
|
||||||
|
val coin_left_total: Int = 0,
|
||||||
|
val country: String = "",
|
||||||
|
val country_code: String = "",
|
||||||
|
val customer_id: String = "",
|
||||||
|
val email: String = "",
|
||||||
|
val family_name: String = "",
|
||||||
|
val fn: String = "",
|
||||||
|
val giving_name: String = "",
|
||||||
|
val id: String = "",
|
||||||
|
val ip_address: String = "0.0.0.0",
|
||||||
|
val is_guide_vip: Boolean = false,
|
||||||
|
val is_tourist: Boolean = true,
|
||||||
|
val is_vip: Boolean = false,
|
||||||
|
val ln: String = "",
|
||||||
|
val registered_days: Int = 0,
|
||||||
|
val send_coin_left_total: Int = 0,
|
||||||
|
val third_access_platform: String = "",
|
||||||
|
val vip_end_time: Int = 0,
|
||||||
|
val vip_type: String = ""
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun createWithDefaults(): UserInfoRes {
|
||||||
|
return UserInfoRes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
data class UserRegisterRes(val customer_id: String,
|
||||||
|
val token: String)
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.data
|
||||||
|
|
||||||
|
class VideoListDataRes(
|
||||||
|
val list: List<VideoListData>,
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class VideoListData(
|
||||||
|
val all_coins: Int,
|
||||||
|
val buy_type: Int,
|
||||||
|
val categoryList: List<Category>,
|
||||||
|
val collect_total: Int,
|
||||||
|
val description: String,
|
||||||
|
val episode_total: Int,
|
||||||
|
val horizontally_img: String,
|
||||||
|
val id: Int,
|
||||||
|
val image_url: String,
|
||||||
|
val name: String,
|
||||||
|
val process: Int,
|
||||||
|
val short_id: Int,
|
||||||
|
val short_play_id: Int,
|
||||||
|
val tag_type: String,
|
||||||
|
val watch_total: Long
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Category(
|
||||||
|
val id: Int,
|
||||||
|
val name: String
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.blankj.utilcode.util.NetworkUtils
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityFreshBinding
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityRankingsBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import com.jia.er.nebuluxe.app.video.PlayerDetailActivity
|
||||||
|
|
||||||
|
|
||||||
|
class FreshActivity : BaseActivity<ActivityFreshBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
private var type = "new_releases"
|
||||||
|
|
||||||
|
override fun top() {
|
||||||
|
binding?.exampleIvBack?.setOnClickListener { finish() }
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.homeRanking(type)
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
}
|
||||||
|
binding.srRank.setOnRefreshListener {
|
||||||
|
mViewModel.homeRanking(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.homeRankingData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
if (it.data?.list?.isNotEmpty() == true) {
|
||||||
|
val homeRankTrendingAdapter = FreshAdapter()
|
||||||
|
val manager1 = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding?.rvRanks?.layoutManager = manager1
|
||||||
|
binding?.rvRanks?.adapter = homeRankTrendingAdapter
|
||||||
|
homeRankTrendingAdapter?.submitList(it.data.list)
|
||||||
|
homeRankTrendingAdapter?.isStateViewEnable = true
|
||||||
|
homeRankTrendingAdapter?.setStateViewLayout(this, R.layout.layout_emptyview)
|
||||||
|
homeRankTrendingAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||||
|
val data = adapter.getItem(position) as HomeRankingRes.Item7
|
||||||
|
startActivity(Intent(
|
||||||
|
this, PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id, data.short_play_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.srRank.finishRefresh()
|
||||||
|
hideNetError()
|
||||||
|
hideLoading()
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivityFreshBinding {
|
||||||
|
return ActivityFreshBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRetry() {
|
||||||
|
super.onRetry()
|
||||||
|
singleClick {
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.homeRanking(type)
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.example_no_network))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.fullspan.FullSpanAdapterType
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.ui.CustomRoundedCorners
|
||||||
|
import com.jia.er.nebuluxe.app.utils.dpToPxByFloat
|
||||||
|
|
||||||
|
|
||||||
|
class FreshAdapter :
|
||||||
|
BaseQuickAdapter<HomeRankingRes.Item7, QuickViewHolder>(),
|
||||||
|
FullSpanAdapterType {
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: HomeRankingRes.Item7?
|
||||||
|
) {
|
||||||
|
Glide.with(context).load(item?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(holder.getView(R.id.iv_cover))
|
||||||
|
holder.setText(R.id.tv_rank_name, item?.name)
|
||||||
|
if (item?.category?.isNotEmpty() == true) {
|
||||||
|
val string = item.category[0]
|
||||||
|
holder.setText(R.id.tv_rank_tag, string)
|
||||||
|
holder.setVisible(R.id.tv_rank_tag, true)
|
||||||
|
} else {
|
||||||
|
holder.setVisible(R.id.tv_rank_tag, false)
|
||||||
|
}
|
||||||
|
val view = holder.getView<AppCompatImageView>(R.id.example_iv_icon_ceo)
|
||||||
|
Glide.with(context)
|
||||||
|
.load(item?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.transform(
|
||||||
|
CenterCrop(),
|
||||||
|
CustomRoundedCorners(
|
||||||
|
dpToPxByFloat(20, context),
|
||||||
|
0f,
|
||||||
|
dpToPxByFloat(20, context),
|
||||||
|
dpToPxByFloat(20, context)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.into(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_fresh, parent)
|
||||||
|
}
|
||||||
|
}
|
101
app/src/main/java/com/jia/er/nebuluxe/app/home/GenresActivity.kt
Normal file
101
app/src/main/java/com/jia/er/nebuluxe/app/home/GenresActivity.kt
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.view.View
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.blankj.utilcode.util.NetworkUtils
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.ShortListCategoryDataInfo
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityFreshBinding
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityRankingsBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import com.jia.er.nebuluxe.app.video.PlayerDetailActivity
|
||||||
|
|
||||||
|
|
||||||
|
class GenresActivity : BaseActivity<ActivityFreshBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
|
||||||
|
override fun top() {
|
||||||
|
binding?.exampleIvBack?.setOnClickListener { finish() }
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.userCenterRecommend()
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
}
|
||||||
|
binding.srRank.setOnRefreshListener {
|
||||||
|
mViewModel.userCenterRecommend()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.userCenterRecommendData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
if (it.data?.list?.isNotEmpty() == true) {
|
||||||
|
val homeRankTrendingAdapter = GenresAdapter()
|
||||||
|
val manager1 = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding?.rvRanks?.layoutManager = manager1
|
||||||
|
binding?.rvRanks?.adapter = homeRankTrendingAdapter
|
||||||
|
homeRankTrendingAdapter?.submitList(it.data.list)
|
||||||
|
binding?.rvRanks?.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||||
|
override fun getItemOffsets(
|
||||||
|
outRect: Rect,
|
||||||
|
view: View,
|
||||||
|
parent: RecyclerView,
|
||||||
|
state: RecyclerView.State
|
||||||
|
) {
|
||||||
|
super.getItemOffsets(outRect, view, parent, state)
|
||||||
|
if (parent.getChildPosition(view) != (it.data.list.size - 1)) {
|
||||||
|
outRect.bottom = -100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
homeRankTrendingAdapter?.isStateViewEnable = true
|
||||||
|
homeRankTrendingAdapter?.setStateViewLayout(this, R.layout.layout_emptyview)
|
||||||
|
homeRankTrendingAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||||
|
val data =
|
||||||
|
adapter.getItem(position) as ShortListCategoryDataInfo.CategoryListData
|
||||||
|
// startActivity(Intent(
|
||||||
|
// this, PlayerDetailActivity::class.java
|
||||||
|
// ).apply {
|
||||||
|
// putExtra(
|
||||||
|
// Constants.CONSTANTS_short_play_id, data.short_play_id
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.srRank.finishRefresh()
|
||||||
|
hideNetError()
|
||||||
|
hideLoading()
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivityFreshBinding {
|
||||||
|
return ActivityFreshBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRetry() {
|
||||||
|
super.onRetry()
|
||||||
|
singleClick {
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.userCenterRecommend()
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.example_no_network))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.fullspan.FullSpanAdapterType
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.ShortListCategoryDataInfo
|
||||||
|
|
||||||
|
|
||||||
|
class GenresAdapter :
|
||||||
|
BaseQuickAdapter<ShortListCategoryDataInfo.CategoryListData, QuickViewHolder>(),
|
||||||
|
FullSpanAdapterType {
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: ShortListCategoryDataInfo.CategoryListData?
|
||||||
|
) {
|
||||||
|
when (position) {
|
||||||
|
0 -> {
|
||||||
|
holder.setBackgroundResource(R.id.rl, R.drawable.iv_genres_1)
|
||||||
|
holder.setBackgroundResource(R.id.line, R.color.E3D4FF)
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
holder.setBackgroundResource(R.id.rl, R.drawable.iv_genres_2)
|
||||||
|
holder.setBackgroundResource(R.id.line, R.color.BDF5E2)
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
holder.setBackgroundResource(R.id.rl, R.drawable.iv_genres_3)
|
||||||
|
holder.setBackgroundResource(R.id.line, R.color.FFFA80)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
holder.setBackgroundResource(R.id.rl, R.drawable.iv_genres_4)
|
||||||
|
holder.setBackgroundResource(R.id.line, R.color.F0C2E1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val view = holder.getView<RecyclerView>(R.id.rv_genres_item)
|
||||||
|
holder.setText(R.id.tv_type, item?.category_name)
|
||||||
|
holder.setText(
|
||||||
|
R.id.tv_num,
|
||||||
|
item?.short_play_list?.size.toString().plus("\n").plus("Dramas")
|
||||||
|
)
|
||||||
|
val homeRankTrendingAdapter = GenresItemAdapter()
|
||||||
|
val manager1 = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
view?.layoutManager = manager1
|
||||||
|
view?.adapter = homeRankTrendingAdapter
|
||||||
|
homeRankTrendingAdapter?.submitList(item?.short_play_list)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_genres, parent)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.fullspan.FullSpanAdapterType
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.ShortListCategoryDataInfo
|
||||||
|
|
||||||
|
|
||||||
|
class GenresItemAdapter :
|
||||||
|
BaseQuickAdapter<ShortListCategoryDataInfo.ShortPlayListData, QuickViewHolder>(),
|
||||||
|
FullSpanAdapterType {
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: ShortListCategoryDataInfo.ShortPlayListData?
|
||||||
|
) {
|
||||||
|
Glide.with(context).load(item?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(holder.getView(R.id.iv_cover))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_genres_img, parent)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeBannerAndNineSquarepRes
|
||||||
|
import com.youth.banner.adapter.BannerAdapter
|
||||||
|
|
||||||
|
class HomeBannerAdapter(items: List<HomeBannerAndNineSquarepRes.Item0?>?) :
|
||||||
|
BannerAdapter<HomeBannerAndNineSquarepRes.Item0?, HomeBannerAdapter.BannerViewHolder?>(
|
||||||
|
items
|
||||||
|
) {
|
||||||
|
override fun onCreateHolder(parent: ViewGroup, viewType: Int): BannerViewHolder {
|
||||||
|
val view: View = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.custom_banner_view, parent, false)
|
||||||
|
view.layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
return BannerViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onBindView(
|
||||||
|
holder: BannerViewHolder?,
|
||||||
|
data: HomeBannerAndNineSquarepRes.Item0?,
|
||||||
|
position: Int,
|
||||||
|
size: Int
|
||||||
|
) {
|
||||||
|
val findViewById =
|
||||||
|
holder?.view?.findViewById<AppCompatImageView>(R.id.iv_icon_banner)
|
||||||
|
val tv_name = holder?.view?.findViewById<AppCompatTextView>(R.id.tv_name)
|
||||||
|
val tv_tag = holder?.view?.findViewById<AppCompatTextView>(R.id.tv_tag)
|
||||||
|
if (findViewById != null) {
|
||||||
|
Glide.with(holder.itemView.context)
|
||||||
|
.load(data?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(findViewById)
|
||||||
|
}
|
||||||
|
tv_name?.text = data?.name
|
||||||
|
if (data?.category?.isNotEmpty() == true) {
|
||||||
|
tv_tag?.visibility = View.VISIBLE
|
||||||
|
tv_tag?.text = data?.category[0]
|
||||||
|
} else {
|
||||||
|
tv_tag?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class BannerViewHolder(var view: View) : RecyclerView.ViewHolder(
|
||||||
|
view
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeBannerAndNineSquarepRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeTopWeekRes
|
||||||
|
import com.youth.banner.adapter.BannerAdapter
|
||||||
|
|
||||||
|
class HomeBannerBottomAdapter(items: List<HomeTopWeekRes.Item8?>?) :
|
||||||
|
BannerAdapter<HomeTopWeekRes.Item8?, HomeBannerBottomAdapter.BannerViewHolder?>(
|
||||||
|
items
|
||||||
|
) {
|
||||||
|
override fun onCreateHolder(parent: ViewGroup, viewType: Int): BannerViewHolder {
|
||||||
|
val view: View = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.custom_banner_view_bottom, parent, false)
|
||||||
|
view.layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
return BannerViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onBindView(
|
||||||
|
holder: BannerViewHolder?,
|
||||||
|
data: HomeTopWeekRes.Item8?,
|
||||||
|
position: Int,
|
||||||
|
size: Int
|
||||||
|
) {
|
||||||
|
val findViewById =
|
||||||
|
holder?.view?.findViewById<AppCompatImageView>(R.id.iv_icon_banner)
|
||||||
|
val tv_name = holder?.view?.findViewById<AppCompatTextView>(R.id.tv_name)
|
||||||
|
val tv_tag = holder?.view?.findViewById<AppCompatTextView>(R.id.tv_tag)
|
||||||
|
val tv_des = holder?.view?.findViewById<AppCompatTextView>(R.id.tv_des)
|
||||||
|
if (findViewById != null) {
|
||||||
|
Glide.with(holder.itemView.context)
|
||||||
|
.load(data?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(findViewById)
|
||||||
|
}
|
||||||
|
tv_name?.text = data?.name
|
||||||
|
tv_des?.text = data?.description
|
||||||
|
if (data?.category?.isNotEmpty() == true) {
|
||||||
|
tv_tag?.visibility = View.VISIBLE
|
||||||
|
tv_tag?.text = data?.category[0]
|
||||||
|
} else {
|
||||||
|
tv_tag?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class BannerViewHolder(var view: View) : RecyclerView.ViewHolder(
|
||||||
|
view
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.RecommendDataRes
|
||||||
|
|
||||||
|
class HomeForYouAdapter :
|
||||||
|
BaseQuickAdapter<RecommendDataRes.Data, QuickViewHolder>() {
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: RecommendDataRes.Data?
|
||||||
|
) {
|
||||||
|
Glide.with(context).load(item?.image_url)
|
||||||
|
.into(holder.getView(R.id.iv_icon))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_home_for_you, parent)
|
||||||
|
}
|
||||||
|
}
|
265
app/src/main/java/com/jia/er/nebuluxe/app/home/HomeFragment.kt
Normal file
265
app/src/main/java/com/jia/er/nebuluxe/app/home/HomeFragment.kt
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.view.View
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.blankj.utilcode.util.NetworkUtils
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseFragment
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeBannerAndNineSquarepRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeBannerBean
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeTopWeekRes
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.FragmentHomeBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.ui.RotateDownPageTransformer
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import com.jia.er.nebuluxe.app.video.PlayerDetailActivity
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
|
||||||
|
class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
private var page: Int = 1
|
||||||
|
private val gson = Gson()
|
||||||
|
override fun top() {
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
mViewModel.allModules()
|
||||||
|
} else {
|
||||||
|
EventBus.getDefault().post(Constants.CONSTANTS_main_stop)
|
||||||
|
showNetError()
|
||||||
|
}
|
||||||
|
binding?.srHome?.setOnRefreshListener {
|
||||||
|
page = 1
|
||||||
|
mViewModel.allModules()
|
||||||
|
}
|
||||||
|
binding.tvHot.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
HotActivity::class.java
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.tvTop.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
RankActivity::class.java
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.tvFresh.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
FreshActivity::class.java
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.tvFresh.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
GenresActivity::class.java
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var dataList: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.allModulesData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
if (it?.data?.list?.isNotEmpty() == true) {
|
||||||
|
for (item in it.data.list) {
|
||||||
|
when (item.module_key) {
|
||||||
|
"marquee" -> {
|
||||||
|
binding.root.postDelayed({
|
||||||
|
dataList.clear()
|
||||||
|
val marqueeList =
|
||||||
|
gson.fromJson(item.data, Array<HomeBannerBean>::class.java)
|
||||||
|
.toList()
|
||||||
|
marqueeList?.forEach { it1 ->
|
||||||
|
dataList.add(it1.name)
|
||||||
|
}
|
||||||
|
if (dataList.isNotEmpty()) {
|
||||||
|
binding?.tvText?.setData(dataList)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
"home_banner" -> {
|
||||||
|
val bannerList =
|
||||||
|
gson.fromJson(item.data, Array<HomeBannerBean>::class.java)
|
||||||
|
.toList()
|
||||||
|
if (bannerList?.isNotEmpty() == true) {
|
||||||
|
binding?.clFs?.visibility = View.VISIBLE
|
||||||
|
val exampleDominantCeoAdapter = HomeMostAdapter()
|
||||||
|
val layoutManager =
|
||||||
|
LinearLayoutManager(
|
||||||
|
context,
|
||||||
|
LinearLayoutManager.HORIZONTAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding?.rvFs?.layoutManager = layoutManager
|
||||||
|
binding?.rvFs?.adapter = exampleDominantCeoAdapter
|
||||||
|
binding?.rvFs?.isNestedScrollingEnabled = false
|
||||||
|
exampleDominantCeoAdapter.submitList(bannerList)
|
||||||
|
val video = bannerList[0]
|
||||||
|
Glide.with(requireContext()).load(video?.horizontally_img)
|
||||||
|
.placeholder(R.drawable.iv_placeholder_h)
|
||||||
|
.into(binding.ivFs)
|
||||||
|
binding.tvName.text = video.name
|
||||||
|
if (video.category.isNotEmpty()) {
|
||||||
|
binding.tvTag.visibility = View.VISIBLE
|
||||||
|
binding.tvTag.text = video.category[0]
|
||||||
|
} else {
|
||||||
|
binding.tvTag.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
binding.ivFs.setOnClickListener {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id,
|
||||||
|
video.short_play_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
exampleDominantCeoAdapter.setOnItemClickListener { adapter, view, position ->
|
||||||
|
exampleDominantCeoAdapter.currentPosition = position
|
||||||
|
val video =
|
||||||
|
adapter.getItem(position) as HomeBannerBean
|
||||||
|
Glide.with(requireContext()).load(video?.horizontally_img)
|
||||||
|
.placeholder(R.drawable.iv_placeholder_h)
|
||||||
|
.into(binding.ivFs)
|
||||||
|
binding.tvName.text = video.name
|
||||||
|
if (video.category.isNotEmpty()) {
|
||||||
|
binding.tvTag.visibility = View.VISIBLE
|
||||||
|
binding.tvTag.text = video.category[0]
|
||||||
|
} else {
|
||||||
|
binding.tvTag.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
binding.ivFs.setOnClickListener {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id,
|
||||||
|
video.short_play_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
exampleDominantCeoAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
binding?.clFs?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"home_v3_recommand" -> {
|
||||||
|
val homeBannerAndNineSquarepRes =
|
||||||
|
gson.fromJson(
|
||||||
|
item.data,
|
||||||
|
HomeBannerAndNineSquarepRes::class.java
|
||||||
|
)
|
||||||
|
if (homeBannerAndNineSquarepRes?.list?.isNotEmpty() == true) {
|
||||||
|
binding?.clBanner?.visibility = View.VISIBLE
|
||||||
|
val exampleHomeBannerAdapter =
|
||||||
|
HomeBannerAdapter(homeBannerAndNineSquarepRes?.list)
|
||||||
|
binding?.bannerHome?.apply {
|
||||||
|
setAdapter(exampleHomeBannerAdapter)
|
||||||
|
setBannerGalleryEffect(65, 10, 1f)
|
||||||
|
setPageTransformer(RotateDownPageTransformer(10.5f))
|
||||||
|
}
|
||||||
|
exampleHomeBannerAdapter.setOnBannerListener { data, position ->
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id,
|
||||||
|
data?.short_play_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding?.clBanner?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"new_recommand" -> {
|
||||||
|
val cagetoryBean =
|
||||||
|
gson.fromJson(item.data, HomeTopWeekRes::class.java)
|
||||||
|
if (cagetoryBean.list.isNotEmpty()) {
|
||||||
|
binding?.clBannerB?.visibility = View.VISIBLE
|
||||||
|
val exampleHomeBannerAdapter =
|
||||||
|
HomeBannerBottomAdapter(cagetoryBean.list)
|
||||||
|
binding?.bannerHomeB?.setBannerGalleryEffect(24, 10, 1f)
|
||||||
|
binding?.bannerHomeB?.setAdapter(
|
||||||
|
exampleHomeBannerAdapter
|
||||||
|
)?.addBannerLifecycleObserver(this)
|
||||||
|
?.setIndicator(binding.indicatorHome, false)
|
||||||
|
exampleHomeBannerAdapter.setOnBannerListener { data, position ->
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id,
|
||||||
|
data?.short_play_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding?.clBannerB?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideLoading()
|
||||||
|
hideNetError()
|
||||||
|
binding?.srHome?.finishRefresh()
|
||||||
|
EventBus.getDefault().post(Constants.CONSTANTS_main_stop)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
hideLoading()
|
||||||
|
binding?.srHome?.finishRefresh()
|
||||||
|
EventBus.getDefault().post(Constants.CONSTANTS_main_stop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): FragmentHomeBinding {
|
||||||
|
return FragmentHomeBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRetry() {
|
||||||
|
super.onRetry()
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.allModules()
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.example_no_network))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Outline
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.ViewOutlineProvider
|
||||||
|
import android.widget.ImageView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
|
import com.google.android.material.shape.RelativeCornerSize
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeBannerBean
|
||||||
|
|
||||||
|
class HomeMostAdapter :
|
||||||
|
BaseQuickAdapter<HomeBannerBean, QuickViewHolder>() {
|
||||||
|
var currentPosition = 0
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: HomeBannerBean?
|
||||||
|
) {
|
||||||
|
val view = holder.getView<ShapeableImageView>(R.id.example_iv_icon_ceo)
|
||||||
|
Glide.with(context).load(item?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(view)
|
||||||
|
view.scaleType = ImageView.ScaleType.CENTER_CROP
|
||||||
|
view.shapeAppearanceModel = view.shapeAppearanceModel
|
||||||
|
.toBuilder()
|
||||||
|
.setAllCornerSizes(RelativeCornerSize(0.5f))
|
||||||
|
.build()
|
||||||
|
view.elevation = 0f
|
||||||
|
view.clipToOutline = true
|
||||||
|
view.outlineProvider = object : ViewOutlineProvider() {
|
||||||
|
override fun getOutline(view: View, outline: Outline) {
|
||||||
|
val size = minOf(view.width, view.height)
|
||||||
|
outline.setOval(0, 0, size, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPosition == position) {
|
||||||
|
holder.setVisible(R.id.view, false)
|
||||||
|
} else {
|
||||||
|
holder.setVisible(R.id.view, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_dominant_ceo, parent)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||||
|
import com.blankj.utilcode.util.NetworkUtils
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.data.VideoListDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.FragmentHotBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import com.jia.er.nebuluxe.app.video.PlayerDetailActivity
|
||||||
|
|
||||||
|
class HotActivity : BaseActivity<FragmentHotBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
|
||||||
|
private var hotAdapter: HotAdapter? = null
|
||||||
|
private var isLoad = false
|
||||||
|
override fun top() {
|
||||||
|
binding?.exampleIvBack?.setOnClickListener { finish() }
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.homeHot(1, 10)
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
}
|
||||||
|
binding?.srFree?.setOnRefreshListener {
|
||||||
|
mViewModel.homeHot(1, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.homeHotData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
hotAdapter = HotAdapter()
|
||||||
|
val layoutManager =
|
||||||
|
StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
|
||||||
|
binding?.rvDataFree?.layoutManager = layoutManager
|
||||||
|
binding?.rvDataFree?.adapter = hotAdapter
|
||||||
|
binding?.rvDataFree?.isNestedScrollingEnabled = false
|
||||||
|
hotAdapter?.submitList(it.data?.list)
|
||||||
|
hotAdapter?.isStateViewEnable = true
|
||||||
|
hotAdapter?.setStateViewLayout(
|
||||||
|
this,
|
||||||
|
R.layout.layout_emptyview
|
||||||
|
)
|
||||||
|
hotAdapter?.setOnItemClickListener { adapter, _, position ->
|
||||||
|
val videoListData =
|
||||||
|
adapter.getItem(position) as VideoListDataRes.VideoListData
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
this,
|
||||||
|
PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id,
|
||||||
|
videoListData.id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
}
|
||||||
|
binding?.srFree?.finishRefresh()
|
||||||
|
hideLoading()
|
||||||
|
hideNetError()
|
||||||
|
isLoad = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): FragmentHotBinding {
|
||||||
|
return FragmentHotBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRetry() {
|
||||||
|
super.onRetry()
|
||||||
|
singleClick {
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.freeMoreVideo()
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.example_no_network))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
62
app/src/main/java/com/jia/er/nebuluxe/app/home/HotAdapter.kt
Normal file
62
app/src/main/java/com/jia/er/nebuluxe/app/home/HotAdapter.kt
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.VideoListDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.ui.PosterStyleImageView
|
||||||
|
|
||||||
|
class HotAdapter :
|
||||||
|
BaseQuickAdapter<VideoListDataRes.VideoListData, QuickViewHolder>() {
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: VideoListDataRes.VideoListData?
|
||||||
|
) {
|
||||||
|
val posterView = holder.getView<PosterStyleImageView>(R.id.iv_hot)
|
||||||
|
posterView.loadImage(
|
||||||
|
url = item?.image_url.toString(),
|
||||||
|
placeholderRes = R.drawable.iv_placeholder_v,
|
||||||
|
errorRes = R.drawable.iv_placeholder_v
|
||||||
|
)
|
||||||
|
if (0 == position) {
|
||||||
|
holder.setGone(R.id.iv_top, false)
|
||||||
|
posterView.apply {
|
||||||
|
// 顶部倾斜程度(左侧更低)
|
||||||
|
setTopSlantOffsetDp(25f)
|
||||||
|
|
||||||
|
// 左上小圆角,其他正常
|
||||||
|
setTopLeftShortStyle(topLeftDp = 12f, otherDp = 18f)
|
||||||
|
|
||||||
|
// 如果还需更贴合
|
||||||
|
setCornerRadiiDp(12f, 18f, 18f, 18f)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
holder.setGone(R.id.iv_top, true)
|
||||||
|
posterView.apply {
|
||||||
|
// 顶部倾斜程度(左侧更低)
|
||||||
|
setTopSlantOffsetDp(0f)
|
||||||
|
|
||||||
|
// 左上小圆角,其他正常
|
||||||
|
setTopLeftShortStyle(topLeftDp = 18f, otherDp = 18f)
|
||||||
|
// 如果还需更贴合
|
||||||
|
setCornerRadiiDp(18f, 18f, 18f, 18f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_hot, parent)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.blankj.utilcode.util.NetworkUtils
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityRankingsBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import com.jia.er.nebuluxe.app.video.PlayerDetailActivity
|
||||||
|
|
||||||
|
|
||||||
|
class RankActivity : BaseActivity<ActivityRankingsBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
private var type = "most_trending"
|
||||||
|
|
||||||
|
override fun top() {
|
||||||
|
binding?.exampleIvBack?.setOnClickListener { finish() }
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.homeRanking(type)
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
}
|
||||||
|
binding.srRank.setOnRefreshListener {
|
||||||
|
mViewModel.homeRanking(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.homeRankingData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
if (it.data?.list?.isNotEmpty() == true) {
|
||||||
|
val homeRankTrendingAdapter = RankAdapter()
|
||||||
|
val manager1 = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding?.rvRanks?.layoutManager = manager1
|
||||||
|
binding?.rvRanks?.adapter = homeRankTrendingAdapter
|
||||||
|
homeRankTrendingAdapter?.submitList(it.data.list)
|
||||||
|
homeRankTrendingAdapter?.isStateViewEnable = true
|
||||||
|
homeRankTrendingAdapter?.setStateViewLayout(this, R.layout.layout_emptyview)
|
||||||
|
homeRankTrendingAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||||
|
val data = adapter.getItem(position) as HomeRankingRes.Item7
|
||||||
|
startActivity(Intent(
|
||||||
|
this, PlayerDetailActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(
|
||||||
|
Constants.CONSTANTS_short_play_id, data.short_play_id
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.srRank.finishRefresh()
|
||||||
|
hideNetError()
|
||||||
|
hideLoading()
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivityRankingsBinding {
|
||||||
|
return ActivityRankingsBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRetry() {
|
||||||
|
super.onRetry()
|
||||||
|
singleClick {
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.homeRanking(type)
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.example_no_network))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.fullspan.FullSpanAdapterType
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.utils.formatNumberByLong
|
||||||
|
|
||||||
|
class RankAdapter :
|
||||||
|
BaseQuickAdapter<HomeRankingRes.Item7, QuickViewHolder>(),
|
||||||
|
FullSpanAdapterType {
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: HomeRankingRes.Item7?
|
||||||
|
) {
|
||||||
|
Glide.with(context).load(item?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(holder.getView(R.id.iv_cover))
|
||||||
|
holder.setText(R.id.tv_rank_name, item?.name)
|
||||||
|
holder.setText(R.id.tv_des, item?.description)
|
||||||
|
if (item?.category?.isNotEmpty() == true) {
|
||||||
|
val string = item.category[0]
|
||||||
|
holder.setText(R.id.tv_rank_tag, string)
|
||||||
|
holder.setVisible(R.id.tv_rank_tag, true)
|
||||||
|
} else {
|
||||||
|
holder.setVisible(R.id.tv_rank_tag, false)
|
||||||
|
}
|
||||||
|
val view = holder.getView<AppCompatTextView>(R.id.tv_rank_watch)
|
||||||
|
holder.setText(R.id.tv_num, (position + 1).toString())
|
||||||
|
when (position) {
|
||||||
|
0 -> {
|
||||||
|
holder.setBackgroundResource(R.id.tv_num, R.drawable.bg_rank_1)
|
||||||
|
holder.setTextColor(R.id.tv_num,Color.parseColor("#4F2500"))
|
||||||
|
holder.setTextColor(R.id.tv_rank_tag,Color.parseColor("#FFE8C4"))
|
||||||
|
view?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
context?.getDrawable(R.drawable.iv_item_rank_heat),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
holder.setBackgroundResource(R.id.tv_num, R.drawable.bg_rank_2)
|
||||||
|
holder.setTextColor(R.id.tv_num,Color.parseColor("#424242"))
|
||||||
|
holder.setTextColor(R.id.tv_rank_tag,Color.parseColor("#FFE8C4"))
|
||||||
|
view?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
context?.getDrawable(R.drawable.iv_item_rank_heat),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
holder.setBackgroundResource(R.id.tv_num, R.drawable.bg_rank_3)
|
||||||
|
holder.setTextColor(R.id.tv_num,Color.parseColor("#79471B"))
|
||||||
|
holder.setTextColor(R.id.tv_rank_tag,Color.parseColor("#FFE8C4"))
|
||||||
|
view?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
context?.getDrawable(R.drawable.iv_item_rank_heat),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
holder.setBackgroundResource(R.id.tv_num, R.drawable.bg_rank_other)
|
||||||
|
holder.setTextColor(R.id.tv_num,Color.parseColor("#0F0F0F"))
|
||||||
|
holder.setTextColor(R.id.tv_rank_tag,Color.parseColor("#F0C2E1"))
|
||||||
|
view?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
context?.getDrawable(R.drawable.iv_item_rank_heat_1),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
holder.setText(R.id.tv_rank_watch, item?.watch_total?.let { formatNumberByLong(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_ranks, parent)
|
||||||
|
}
|
||||||
|
}
|
464
app/src/main/java/com/jia/er/nebuluxe/app/home/ReelsFragment.kt
Normal file
464
app/src/main/java/com/jia/er/nebuluxe/app/home/ReelsFragment.kt
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.net.Uri
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.SeekBar
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.appcompat.widget.AppCompatSeekBar
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.PlaybackException
|
||||||
|
import androidx.media3.common.Player
|
||||||
|
import androidx.media3.datasource.DataSource
|
||||||
|
import androidx.media3.datasource.DefaultDataSourceFactory
|
||||||
|
import androidx.media3.exoplayer.DefaultRenderersFactory
|
||||||
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
|
import androidx.media3.exoplayer.hls.HlsMediaSource
|
||||||
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
|
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||||
|
import androidx.media3.ui.PlayerView
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.PagerSnapHelper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.jia.er.nebuluxe.app.data.RecommendDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.ui.FfmpegRenderersFactory
|
||||||
|
import com.jia.er.nebuluxe.app.ui.LoadingLine
|
||||||
|
import com.jia.er.nebuluxe.app.ui.OnSnapHelperCurrentListener
|
||||||
|
import com.jia.er.nebuluxe.app.ui.RecyclerViewScrollerDetection
|
||||||
|
import com.blankj.utilcode.util.NetworkUtils
|
||||||
|
import com.blankj.utilcode.util.ViewUtils
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseFragment
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.FragmentReelsBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.appendWithStyle
|
||||||
|
import com.jia.er.nebuluxe.app.utils.formatTimestamp
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import com.jia.er.nebuluxe.app.utils.DialogUtils
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
class ReelsFragment : BaseFragment<FragmentReelsBinding>(),
|
||||||
|
OnSnapHelperCurrentListener {
|
||||||
|
private var builder: ExoPlayer.Builder? = null
|
||||||
|
private var player: ExoPlayer? = null
|
||||||
|
private val pagerSnapHelper = PagerSnapHelper()
|
||||||
|
private val recyclerViewScrollerDetection = RecyclerViewScrollerDetection()
|
||||||
|
private var homeForYouAdapter: HomeForYouAdapter? = null
|
||||||
|
private var playerView: PlayerView? = null
|
||||||
|
private var currentView: View? = null
|
||||||
|
private var loadingLine: LoadingLine? = null
|
||||||
|
private var tvName: AppCompatTextView? = null
|
||||||
|
private var tvTime: AppCompatTextView? = null
|
||||||
|
private var play: AppCompatImageView? = null
|
||||||
|
private var collection: AppCompatImageView? = null
|
||||||
|
private var ivIconPlayer: AppCompatImageView? = null
|
||||||
|
private var ivCover: AppCompatImageView? = null
|
||||||
|
private var exampleSeekbarPlayerController: AppCompatSeekBar? = null
|
||||||
|
private var exampleProgressJob: Job? = null
|
||||||
|
private var isDragging = false
|
||||||
|
private var isPlaying = false
|
||||||
|
private var currentPage = 1
|
||||||
|
private val currentSize = 10
|
||||||
|
private var dataRes: RecommendDataRes.Data? = null
|
||||||
|
private var currentPosition = 0
|
||||||
|
private var tvEpTotal: AppCompatTextView? = null
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
private var isCanPlay = false
|
||||||
|
|
||||||
|
override fun top() {
|
||||||
|
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
builder = ExoPlayer.Builder(requireContext(), FfmpegRenderersFactory(requireContext()))
|
||||||
|
.setRenderersFactory(
|
||||||
|
DefaultRenderersFactory(requireContext()).setEnableDecoderFallback(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
player = builder?.build()
|
||||||
|
playerView = ViewUtils.layoutId2View(R.layout.include_player_view) as PlayerView
|
||||||
|
playerView?.player = player
|
||||||
|
loadingLine = playerView?.findViewById(R.id.load_line)
|
||||||
|
tvName = playerView?.findViewById(R.id.example_tv_title_player_controller)
|
||||||
|
tvTime = playerView?.findViewById(R.id.tv_player_seek_time)
|
||||||
|
tvEpTotal = playerView?.findViewById(R.id.tv_ep_total)
|
||||||
|
play = playerView?.findViewById(R.id.example_iv_play_player_controller)
|
||||||
|
collection = playerView?.findViewById(R.id.example_iv_collection_controller)
|
||||||
|
ivIconPlayer = playerView?.findViewById(R.id.iv_icon_player)
|
||||||
|
exampleSeekbarPlayerController =
|
||||||
|
playerView?.findViewById(R.id.example_seekBar_player_controller)
|
||||||
|
play?.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
if (isPlaying) {
|
||||||
|
pause()
|
||||||
|
} else {
|
||||||
|
play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player?.addListener(object : Player.Listener {
|
||||||
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||||
|
super.onPlaybackStateChanged(playbackState)
|
||||||
|
when (playbackState) {
|
||||||
|
Player.STATE_BUFFERING -> {
|
||||||
|
if (!isHidden) {
|
||||||
|
ivIconPlayer?.visibility = View.VISIBLE
|
||||||
|
loadingLine?.visibility = View.VISIBLE
|
||||||
|
loadingLine?.postDelayed({ loadingLine?.startAnimation() }, 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.STATE_READY -> {
|
||||||
|
if (isCanPlay) {
|
||||||
|
canPlay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.STATE_ENDED -> {
|
||||||
|
val plus = currentPosition.plus(1)
|
||||||
|
binding.rvRecommend.smoothScrollToPosition(plus)
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.STATE_IDLE -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
|
super.onPlayerError(error)
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
collection?.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
if (dataRes?.is_collect == true) {
|
||||||
|
dataRes?.video_info?.short_play_id?.let { it1 ->
|
||||||
|
dataRes?.video_info?.short_play_video_id?.let { it2 ->
|
||||||
|
DialogUtils.unFavoriteDialog(
|
||||||
|
requireContext(),
|
||||||
|
it1, it2, mViewModel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataRes?.video_info?.short_play_id?.let {
|
||||||
|
dataRes?.video_info?.short_play_video_id.let { it1 ->
|
||||||
|
if (it1 != null) {
|
||||||
|
mViewModel.doCollect(
|
||||||
|
it, it1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.srFy.apply {
|
||||||
|
setOnRefreshListener {
|
||||||
|
recyclerViewScrollerDetection.isFirstAttached = false
|
||||||
|
player?.stop()
|
||||||
|
mViewModel.getRecommands(currentPage, currentSize, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.rvRecommend.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
|
|
||||||
|
var isSlidingUp = false
|
||||||
|
|
||||||
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
|
super.onScrolled(recyclerView, dx, dy)
|
||||||
|
|
||||||
|
isSlidingUp = dy > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||||
|
super.onScrollStateChanged(recyclerView, newState)
|
||||||
|
|
||||||
|
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||||
|
val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
|
||||||
|
val totalItemCount = layoutManager.itemCount
|
||||||
|
|
||||||
|
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||||
|
if (isSlidingUp &&
|
||||||
|
lastVisibleItemPosition == totalItemCount - 1
|
||||||
|
) {
|
||||||
|
currentPage++
|
||||||
|
mViewModel.getRecommands(currentPage, currentSize, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
exampleSeekbarPlayerController?.setOnSeekBarChangeListener(object :
|
||||||
|
SeekBar.OnSeekBarChangeListener {
|
||||||
|
override fun onProgressChanged(
|
||||||
|
seekBar: SeekBar?,
|
||||||
|
progress: Int,
|
||||||
|
fromUser: Boolean
|
||||||
|
) {
|
||||||
|
if (fromUser) {
|
||||||
|
seekTo(progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||||
|
tvTime?.visibility = FrameLayout.VISIBLE
|
||||||
|
isDragging = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||||
|
isDragging = false
|
||||||
|
tvTime?.visibility = FrameLayout.INVISIBLE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.getRecommands(currentPage, currentSize, "")
|
||||||
|
} else {
|
||||||
|
showNetError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setProgress() {
|
||||||
|
exampleProgressJob?.cancel()
|
||||||
|
val duration = player!!.duration
|
||||||
|
exampleSeekbarPlayerController?.max = duration.toInt()
|
||||||
|
exampleSeekbarPlayerController?.progress = player!!.currentPosition.toInt()
|
||||||
|
exampleProgressJob = lifecycleScope.launch {
|
||||||
|
while (isActive) {
|
||||||
|
if (!isDragging) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
exampleSeekbarPlayerController?.progress =
|
||||||
|
player!!.currentPosition.toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun play() {
|
||||||
|
player?.play()
|
||||||
|
play?.setImageResource(R.drawable.iv_example_stop)
|
||||||
|
isPlaying = true
|
||||||
|
isDragging = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pause() {
|
||||||
|
player?.pause()
|
||||||
|
play?.setImageResource(R.drawable.iv_example_play)
|
||||||
|
isPlaying = false
|
||||||
|
isDragging = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seekTo(progress: Int) {
|
||||||
|
player?.seekTo(progress.toLong())
|
||||||
|
seekTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seekTime() {
|
||||||
|
val currentPosition = player!!.currentPosition
|
||||||
|
val currentTime = formatTimestamp(currentPosition / 1000)
|
||||||
|
val totalDuration = player!!.duration
|
||||||
|
val totalTime = formatTimestamp(totalDuration / 1000)
|
||||||
|
tvTime?.text = "$currentTime/$totalTime"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.recommendData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
if (it.data?.list?.isNotEmpty() == true) {
|
||||||
|
if (currentPage == 1) {
|
||||||
|
homeForYouAdapter = HomeForYouAdapter()
|
||||||
|
val layoutManager =
|
||||||
|
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding?.rvRecommend?.layoutManager = layoutManager
|
||||||
|
binding?.rvRecommend?.adapter = homeForYouAdapter
|
||||||
|
binding?.rvRecommend?.isNestedScrollingEnabled = false
|
||||||
|
pagerSnapHelper.attachToRecyclerView(binding?.rvRecommend)
|
||||||
|
recyclerViewScrollerDetection.setCurrentListener(this)
|
||||||
|
recyclerViewScrollerDetection.attachToSnapHelper(pagerSnapHelper)
|
||||||
|
binding?.rvRecommend?.let { it1 ->
|
||||||
|
recyclerViewScrollerDetection.addOnScrollListener(
|
||||||
|
it1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
it.data?.list?.forEach { item ->
|
||||||
|
Glide.with(requireContext()).load(item.image_url).preload()
|
||||||
|
}
|
||||||
|
homeForYouAdapter?.submitList(it.data.list)
|
||||||
|
} else {
|
||||||
|
homeForYouAdapter?.addAll(it.data.list)
|
||||||
|
}
|
||||||
|
hideLoading()
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.no_more_data))
|
||||||
|
}
|
||||||
|
hideNetError()
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
binding.srFy.finishRefresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
mViewModel.collectData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
collection?.setImageResource(R.drawable.iv_example_collection_h)
|
||||||
|
dataRes?.collect_total = dataRes?.collect_total?.plus(1)
|
||||||
|
homeForYouAdapter?.getItem(currentPosition)?.is_collect = true
|
||||||
|
homeForYouAdapter?.getItem(currentPosition)?.collect_total =
|
||||||
|
dataRes?.collect_total
|
||||||
|
toast(getString(R.string.success))
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mViewModel.cancelCollectData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
collection?.setImageResource(R.drawable.iv_example_collection_n)
|
||||||
|
dataRes?.collect_total = dataRes?.collect_total?.minus(1)
|
||||||
|
homeForYouAdapter?.getItem(currentPosition)?.is_collect = false
|
||||||
|
homeForYouAdapter?.getItem(currentPosition)?.collect_total =
|
||||||
|
dataRes?.collect_total
|
||||||
|
toast(getString(R.string.success))
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildMediaSource(videoPath: String): MediaSource {
|
||||||
|
val dataSourceFactory: DataSource.Factory =
|
||||||
|
DefaultDataSourceFactory(requireContext(), "loopdrama")
|
||||||
|
|
||||||
|
return if (videoPath.endsWith(".m3u8")) {
|
||||||
|
HlsMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(MediaItem.fromUri(Uri.parse(videoPath)))
|
||||||
|
} else {
|
||||||
|
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(MediaItem.fromUri(Uri.parse(videoPath)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): FragmentReelsBinding {
|
||||||
|
return FragmentReelsBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
isCanPlay = false
|
||||||
|
binding.root.postDelayed({ pause() }, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (isVisible) {
|
||||||
|
isCanPlay = true
|
||||||
|
canPlay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
override fun setActive(
|
||||||
|
currentView: View?, position: Int, previousView: View?, previousPosition: Int
|
||||||
|
) {
|
||||||
|
isCanPlay = true
|
||||||
|
currentPosition = position
|
||||||
|
this.currentView = currentView
|
||||||
|
val frameLayout = currentView?.findViewById<FrameLayout>(R.id.video)
|
||||||
|
(playerView?.parent as FrameLayout?)?.removeView(playerView)
|
||||||
|
frameLayout?.removeAllViews()
|
||||||
|
frameLayout?.addView(playerView)
|
||||||
|
playerView?.showController()
|
||||||
|
dataRes = homeForYouAdapter?.getItem(position)
|
||||||
|
dataRes?.video_info?.video_url?.let { buildMediaSource(it) }
|
||||||
|
?.let { player?.setMediaSource(it) }
|
||||||
|
player?.prepare()
|
||||||
|
setUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUI() {
|
||||||
|
ivIconPlayer?.let { it1 ->
|
||||||
|
Glide.with(this).load(dataRes?.image_url).into(it1)
|
||||||
|
}
|
||||||
|
tvName?.text = dataRes?.name
|
||||||
|
val builder = SpannableStringBuilder()
|
||||||
|
builder.appendWithStyle(
|
||||||
|
"Ep.".plus(dataRes?.video_info?.episode),
|
||||||
|
Color.parseColor("#50FFFFFF"),
|
||||||
|
isBold = true
|
||||||
|
)
|
||||||
|
.appendWithStyle(
|
||||||
|
"/Ep.".plus(dataRes?.episode_total),
|
||||||
|
Color.parseColor("#50FFFFFF"),
|
||||||
|
isBold = false
|
||||||
|
)
|
||||||
|
tvEpTotal?.text = builder
|
||||||
|
collection?.setImageResource(if (dataRes?.is_collect == true) R.drawable.iv_example_collection_h else R.drawable.iv_example_collection_n)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun disActive(detachedView: View?, detachedPosition: Int) {
|
||||||
|
if (null == detachedView) return
|
||||||
|
ivCover = detachedView.findViewById(R.id.iv_icon)
|
||||||
|
ivCover?.visibility = View.VISIBLE
|
||||||
|
if (player?.isPlaying == true) {
|
||||||
|
pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onHiddenChanged(hidden: Boolean) {
|
||||||
|
super.onHiddenChanged(hidden)
|
||||||
|
if (hidden) {
|
||||||
|
isCanPlay = false
|
||||||
|
binding.root.postDelayed({ pause() }, 200)
|
||||||
|
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
} else {
|
||||||
|
isCanPlay = true
|
||||||
|
canPlay()
|
||||||
|
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canPlay() {
|
||||||
|
loadingLine?.endAnimation()
|
||||||
|
loadingLine?.visibility = View.INVISIBLE
|
||||||
|
ivCover = currentView?.findViewById(R.id.iv_icon)
|
||||||
|
ivCover?.visibility = View.INVISIBLE
|
||||||
|
ivIconPlayer?.visibility = View.INVISIBLE
|
||||||
|
play()
|
||||||
|
setProgress()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRetry() {
|
||||||
|
super.onRetry()
|
||||||
|
singleClick {
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
mViewModel.getRecommands(currentPage, currentSize, "")
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.example_no_network))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
player?.stop()
|
||||||
|
player?.release()
|
||||||
|
recyclerViewScrollerDetection.detachToSnapHelper()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
142
app/src/main/java/com/jia/er/nebuluxe/app/home/SavedFragment.kt
Normal file
142
app/src/main/java/com/jia/er/nebuluxe/app/home/SavedFragment.kt
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.home
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.jia.er.nebuluxe.app.data.CollectionRes
|
||||||
|
import com.blankj.utilcode.util.NetworkUtils
|
||||||
|
import com.chad.library.adapter4.layoutmanager.QuickGridLayoutManager
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseFragment
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.FragmentSavedBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
|
||||||
|
class SavedFragment : BaseFragment<FragmentSavedBinding>() {
|
||||||
|
private var page: Int = 1
|
||||||
|
// private var myListAdapter: MyListAdapter? = null
|
||||||
|
private var edit = false
|
||||||
|
private var current: Int = 0
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
override fun top() {
|
||||||
|
// if (NetworkUtils.isConnected()) {
|
||||||
|
// showLoading()
|
||||||
|
// mViewModel.getCollections(page)
|
||||||
|
// } else {
|
||||||
|
// showNetError()
|
||||||
|
// }
|
||||||
|
// binding?.srMyList?.setOnRefreshListener {
|
||||||
|
// page = 1
|
||||||
|
// mViewModel.getCollections(page)
|
||||||
|
// }
|
||||||
|
// binding?.srMyList?.setOnLoadMoreListener {
|
||||||
|
// page++
|
||||||
|
// mViewModel.getCollections(page)
|
||||||
|
// }
|
||||||
|
// binding?.exampleIvEditMyFavorites?.setOnClickListener {
|
||||||
|
// if (!edit) {
|
||||||
|
// edit = true
|
||||||
|
// binding?.exampleIvEditMyFavorites?.setImageResource(R.drawable.iv_edit_favorites_complete)
|
||||||
|
// myListAdapter?.eidt = true
|
||||||
|
// binding?.tvTitle?.text = "Delete"
|
||||||
|
// binding.tvTitle.background = context?.getDrawable(R.drawable.iv_list_title_bg_h)
|
||||||
|
// myListAdapter?.notifyDataSetChanged()
|
||||||
|
// } else {
|
||||||
|
// edit = false
|
||||||
|
// binding?.exampleIvEditMyFavorites?.setImageResource(R.drawable.iv_edit_favorites)
|
||||||
|
// binding.tvTitle.background = context?.getDrawable(R.drawable.iv_list_title_bg)
|
||||||
|
// myListAdapter?.eidt = false
|
||||||
|
// binding?.tvTitle?.text = "Favorites"
|
||||||
|
// myListAdapter?.notifyDataSetChanged()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding.ivHis.setOnClickListener {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireContext(),
|
||||||
|
// HistoryActivity::class.java
|
||||||
|
// ))
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
// mViewModel.collectionsData.observe(this) {
|
||||||
|
// if (it != null) {
|
||||||
|
// if (page == 1) {
|
||||||
|
// myListAdapter = MyListAdapter()
|
||||||
|
// val manager = QuickGridLayoutManager(requireContext(), 3)
|
||||||
|
// binding?.rvMyList?.layoutManager = manager
|
||||||
|
// binding?.rvMyList?.adapter = myListAdapter
|
||||||
|
// myListAdapter?.submitList(it.data?.list)
|
||||||
|
// myListAdapter?.isStateViewEnable = true
|
||||||
|
// myListAdapter?.setStateViewLayout(requireContext(), R.layout.layout_emptyview)
|
||||||
|
// myListAdapter?.addOnItemChildClickListener(R.id.iv_favorites_delete) { adapter, view, position ->
|
||||||
|
// current = position
|
||||||
|
// val collectionData =
|
||||||
|
// adapter.getItem(position) as CollectionRes.CollectionData
|
||||||
|
// DialogUtils.unFavoriteDialog(
|
||||||
|
// requireContext(),
|
||||||
|
// collectionData.short_play_id,
|
||||||
|
// collectionData.short_play_video_id,
|
||||||
|
// mViewModel
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// myListAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||||
|
// val data = adapter.getItem(position) as CollectionRes.CollectionData
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireContext(),
|
||||||
|
// PlayerDetailActivity::class.java
|
||||||
|
// ).apply {
|
||||||
|
// putExtra(
|
||||||
|
// Constants.CONSTANTS_short_play_id,
|
||||||
|
// data.short_play_id
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (it.data?.list?.isNotEmpty() == true) {
|
||||||
|
// myListAdapter?.addAll(it.data.list)
|
||||||
|
// } else {
|
||||||
|
// toast(getString(R.string.no_more_data))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// hideLoading()
|
||||||
|
// hideNetError()
|
||||||
|
// } else {
|
||||||
|
// hideLoading()
|
||||||
|
// toast(getString(R.string.network_error))
|
||||||
|
// }
|
||||||
|
// binding?.srMyList?.finishRefresh()
|
||||||
|
// binding?.srMyList?.finishLoadMore()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// mViewModel.cancelCollectData.observe(this) {
|
||||||
|
// if (it != null) {
|
||||||
|
// toast(getString(R.string.success))
|
||||||
|
// myListAdapter?.removeAt(current)
|
||||||
|
// myListAdapter?.notifyDataSetChanged()
|
||||||
|
// } else {
|
||||||
|
// toast(getString(R.string.network_error))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): FragmentSavedBinding {
|
||||||
|
return FragmentSavedBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRetry() {
|
||||||
|
super.onRetry()
|
||||||
|
singleClick {
|
||||||
|
if (NetworkUtils.isConnected()) {
|
||||||
|
showLoading()
|
||||||
|
page = 1
|
||||||
|
mViewModel.getCollections(page)
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.example_no_network))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
705
app/src/main/java/com/jia/er/nebuluxe/app/main/MainActivity.kt
Normal file
705
app/src/main/java/com/jia/er/nebuluxe/app/main/MainActivity.kt
Normal file
@ -0,0 +1,705 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.main
|
||||||
|
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import androidx.fragment.app.FragmentTransaction
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.jia.er.nebuluxe.app.home.HomeFragment
|
||||||
|
import com.jia.er.nebuluxe.app.home.ReelsFragment
|
||||||
|
import com.jia.er.nebuluxe.app.home.SavedFragment
|
||||||
|
import com.flyco.tablayout.listener.CustomTabEntity
|
||||||
|
import com.flyco.tablayout.listener.OnTabSelectListener
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.data.TabEntity
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityMainBinding
|
||||||
|
import com.jia.er.nebuluxe.app.me.MeFragment
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.Memory
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
|
||||||
|
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
|
||||||
|
private var titles = arrayOf(
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
)
|
||||||
|
private val iconUnSelectIds by lazy {
|
||||||
|
intArrayOf(
|
||||||
|
R.drawable.iv_home_n,
|
||||||
|
R.drawable.iv_reels_n,
|
||||||
|
R.drawable.iv_saved_n,
|
||||||
|
R.drawable.iv_me_n
|
||||||
|
)
|
||||||
|
}
|
||||||
|
private val iconSelectIds by lazy {
|
||||||
|
intArrayOf(
|
||||||
|
R.drawable.iv_home_h,
|
||||||
|
R.drawable.iv_reels_h,
|
||||||
|
R.drawable.iv_saved_h,
|
||||||
|
R.drawable.iv_me_h
|
||||||
|
)
|
||||||
|
}
|
||||||
|
private val tabEntities = ArrayList<CustomTabEntity>()
|
||||||
|
private var homeFragment: HomeFragment? = null
|
||||||
|
private var reelsFragment: ReelsFragment? = null
|
||||||
|
private var myListFragment: SavedFragment? = null
|
||||||
|
private var meFragment: MeFragment? = null
|
||||||
|
private var index = 0
|
||||||
|
private var shortVideoId: Int = 0
|
||||||
|
// private var notificationDialog: NotificationDialog? = null
|
||||||
|
// private var path = ""
|
||||||
|
// private var short_play_id = ""
|
||||||
|
// private var message_id = ""
|
||||||
|
// private var title = ""
|
||||||
|
// private var scheduler: ScheduledExecutorService? = Executors.newSingleThreadScheduledExecutor()
|
||||||
|
// private val scope = CoroutineScope(Dispatchers.Main)
|
||||||
|
|
||||||
|
// override fun onNewIntent(intent: Intent?) {
|
||||||
|
// super.onNewIntent(intent)
|
||||||
|
// val webpageURL = intent?.data
|
||||||
|
// uploadDDL(webpageURL)
|
||||||
|
// path = intent?.getStringExtra("path").toString()
|
||||||
|
// short_play_id = intent?.getStringExtra("short_play_id").toString()
|
||||||
|
// message_id = intent?.getStringExtra("message_id").toString()
|
||||||
|
// title = intent?.getStringExtra("title").toString()
|
||||||
|
// notificationGo()
|
||||||
|
// }
|
||||||
|
|
||||||
|
override fun top() {
|
||||||
|
// val webpageURL = intent.data
|
||||||
|
// uploadDDL(webpageURL)
|
||||||
|
// path = intent?.getStringExtra("path").toString()
|
||||||
|
// short_play_id = intent?.getStringExtra("short_play_id").toString()
|
||||||
|
// message_id = intent?.getStringExtra("message_id").toString()
|
||||||
|
// title = intent?.getStringExtra("title").toString()
|
||||||
|
showLoading()
|
||||||
|
EventBus.getDefault().register(this)
|
||||||
|
(titles.indices).mapTo(tabEntities) {
|
||||||
|
TabEntity(
|
||||||
|
titles[it], iconSelectIds[it], iconUnSelectIds[it]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
binding.tabLayout.setTabData(tabEntities)
|
||||||
|
binding?.tabLayout?.setOnTabSelectListener(object : OnTabSelectListener {
|
||||||
|
override fun onTabSelect(position: Int) {
|
||||||
|
switchFragment(position)
|
||||||
|
// when (position) {
|
||||||
|
// 0 -> {
|
||||||
|
// binding?.dialogHistory?.root?.postDelayed(
|
||||||
|
// {
|
||||||
|
// val string = Memory.getMMKV()
|
||||||
|
// .getString(Constants.Constants_Main_Video_info, "")
|
||||||
|
// if (string?.isNotEmpty() == true && NetworkUtils.isConnected()) {
|
||||||
|
// val fromJson = Gson().fromJson(string, MainDataHis::class.java)
|
||||||
|
// showHistoryDialog(fromJson)
|
||||||
|
// }
|
||||||
|
// }, 500
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// else -> {
|
||||||
|
// binding?.dialogHistory?.root?.visibility = View.INVISIBLE
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabReselect(position: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Constants.CanNotification = NotificationUtils.isNotificationEnabled(this)
|
||||||
|
// mViewModel.uploadNoticeStatus(
|
||||||
|
// FbNotificationReq(
|
||||||
|
// if (Constants.CanNotification) "1" else "0"
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
mViewModel.getInfo()
|
||||||
|
switchFragment(index)
|
||||||
|
// GoogleApiAvailability.getInstance().makeGooglePlayServicesAvailable(this)
|
||||||
|
// .addOnCompleteListener {
|
||||||
|
// if (it.isSuccessful) {
|
||||||
|
// askNotificationPermission()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding?.root?.postDelayed({ notificationGo() }, 700)
|
||||||
|
// mViewModel.enterTheApp()
|
||||||
|
// val intervalMillis = 10 * 60 * 1000
|
||||||
|
// scheduler?.scheduleWithFixedDelay({
|
||||||
|
// try {
|
||||||
|
// lifecycleScope.launch {
|
||||||
|
// mViewModel.onLine()
|
||||||
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// }
|
||||||
|
// }, 0, intervalMillis.toLong(), TimeUnit.MILLISECONDS)
|
||||||
|
// binding?.root?.postDelayed({
|
||||||
|
// if (Memory.getOrder().isNotEmpty()) {
|
||||||
|
// val string = Memory.getOrder()
|
||||||
|
// scope.launch {
|
||||||
|
// flow {
|
||||||
|
// for (item in string) {
|
||||||
|
// emit(item)
|
||||||
|
// }
|
||||||
|
// }.onEach { item ->
|
||||||
|
// upError(
|
||||||
|
// "pay restore",
|
||||||
|
// mViewModel,
|
||||||
|
// "restore",
|
||||||
|
// "pay_restore",
|
||||||
|
// "auto", GsonUtils.toJson(item), 0, 0
|
||||||
|
// )
|
||||||
|
// mViewModel.restorePaid(item)
|
||||||
|
// }.debounce(1000).collect {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }, 3000)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
// mViewModel.restorePaidData.observe(this) {
|
||||||
|
// if (it != null) {
|
||||||
|
// it.data?.order_code?.let { it1 -> Memory.removeOrderString(it1) }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
mViewModel.infoData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
it.data?.let { it1 ->
|
||||||
|
Memory.saveUserInfo(it1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mViewModel.userRegisterData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
Memory.getMMKV()
|
||||||
|
.putString(Constants.CONSTANTS_AuthorizationExample, it.data?.token)
|
||||||
|
EventBus.getDefault().post(Constants.CONSTANTS_refresh_me)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mViewModel.loginData.observe(this) {
|
||||||
|
// if (it != null) {
|
||||||
|
// toast(getString(R.string.success))
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putString(Constants.CONSTANTS_AuthorizationExample, it.data?.token)
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_enterTheApp)
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_onLine)
|
||||||
|
// mViewModel.getInfo()
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_refresh_me)
|
||||||
|
// hideLoading()
|
||||||
|
// loginDialog?.dismiss()
|
||||||
|
// } else {
|
||||||
|
// hideLoading()
|
||||||
|
// toast(getString(R.string.network_error))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// override fun onResume() {
|
||||||
|
// super.onResume()
|
||||||
|
// if (index == 0) {
|
||||||
|
// binding?.dialogHistory?.root?.postDelayed(
|
||||||
|
// {
|
||||||
|
// val string = Memory.getMMKV()
|
||||||
|
// .getString(Constants.Constants_Main_Video_info, "")
|
||||||
|
// if (string?.isNotEmpty() == true && NetworkUtils.isConnected()) {
|
||||||
|
// val fromJson = Gson().fromJson(string, MainDataHis::class.java)
|
||||||
|
// showHistoryDialog(fromJson)
|
||||||
|
// }
|
||||||
|
// }, 500
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private fun showHistoryDialog(data: MainDataHis) {
|
||||||
|
// binding?.dialogHistory?.ivCloseHistory?.setOnClickListener {
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putBoolean(Constants.Constants_Main_Video_status, false)
|
||||||
|
// binding?.dialogHistory?.root?.visibility = View.INVISIBLE
|
||||||
|
// }
|
||||||
|
// if (Memory.getMMKV()
|
||||||
|
// .getBoolean(Constants.Constants_Main_Video_status, false)
|
||||||
|
// ) {
|
||||||
|
// binding?.dialogHistory?.ivVideo?.let {
|
||||||
|
// if (!isFinishing && !isDestroyed) {
|
||||||
|
// Glide.with(this).load(
|
||||||
|
// data.video_img
|
||||||
|
// ).placeholder(R.drawable.iv_placeholder_v).into(it)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding?.dialogHistory?.cl?.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// this, PlayerDetailActivity::class.java
|
||||||
|
// ).apply {
|
||||||
|
// putExtra(
|
||||||
|
// Constants.CONSTANTS_short_play_id, data.video_id
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding?.dialogHistory?.root?.post {
|
||||||
|
// binding?.dialogHistory?.tvEp?.text =
|
||||||
|
// "Ep.".plus(data.video_last).plus("/").plus("Ep.").plus(data.episode_total)
|
||||||
|
// }
|
||||||
|
// binding?.dialogHistory?.root?.visibility = View.VISIBLE
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private fun askNotificationPermission() {
|
||||||
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
// if (ContextCompat.checkSelfPermission(
|
||||||
|
// this, Manifest.permission.POST_NOTIFICATIONS
|
||||||
|
// ) == PackageManager.PERMISSION_GRANTED
|
||||||
|
// ) {
|
||||||
|
// NotificationUtils.firebase(mViewModel)
|
||||||
|
// } else {
|
||||||
|
// if (Constants.isUat) {
|
||||||
|
// openNotification()
|
||||||
|
// } else {
|
||||||
|
// if (shouldShowNotification()) {
|
||||||
|
// openNotification()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (NotificationUtils.isNotificationEnabled(this)) {
|
||||||
|
// NotificationUtils.firebase(mViewModel)
|
||||||
|
// } else {
|
||||||
|
// if (Constants.isUat) {
|
||||||
|
// openNotification()
|
||||||
|
// } else {
|
||||||
|
// if (shouldShowNotification()) {
|
||||||
|
// openNotification()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private fun openNotification() {
|
||||||
|
// notificationDialog = NotificationDialog(this)
|
||||||
|
// val example_tv_later =
|
||||||
|
// notificationDialog?.findViewById<AppCompatTextView>(R.id.example_tv_unfavorite)
|
||||||
|
// val iv_close_notification =
|
||||||
|
// notificationDialog?.findViewById<AppCompatImageView>(R.id.iv_close_notification)
|
||||||
|
// val example_open =
|
||||||
|
// notificationDialog?.findViewById<AppCompatTextView>(R.id.example_tv_think_again)
|
||||||
|
// notificationDialog?.setOnDismissListener {
|
||||||
|
// Memory.getMMKV().putLong(
|
||||||
|
// Constants.CONSTANTS_PREF_LAST_POPUP_TIME_Notification,
|
||||||
|
// System.currentTimeMillis()
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// example_tv_later?.setOnClickListener { notificationDialog?.dismiss() }
|
||||||
|
// iv_close_notification?.setOnClickListener { notificationDialog?.dismiss() }
|
||||||
|
// example_open?.setOnClickListener {
|
||||||
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
// requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
// notificationDialog?.dismiss()
|
||||||
|
// } else {
|
||||||
|
// NotificationUtils.openNotificationSettings(this)
|
||||||
|
// notificationDialog?.dismiss()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// notificationDialog?.show()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private val requestPermissionLauncher = registerForActivityResult(
|
||||||
|
// ActivityResultContracts.RequestPermission(),
|
||||||
|
// ) { isGranted: Boolean ->
|
||||||
|
// Constants.CanNotification = isGranted
|
||||||
|
// if (isGranted) {
|
||||||
|
// NotificationUtils.firebase(mViewModel)
|
||||||
|
// mViewModel.uploadNoticeStatus(
|
||||||
|
// FbNotificationReq(
|
||||||
|
// if (Constants.CanNotification) "1" else "0"
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// notificationDialog?.dismiss()
|
||||||
|
// } else {
|
||||||
|
// NotificationUtils.openNotificationSettings(this)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
// super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
// if (index == 0) {
|
||||||
|
// if (requestCode == NotificationUtils.NOTIFICATION_SETTINGS_REQUEST_CODE) {
|
||||||
|
// Constants.CanNotification =
|
||||||
|
// NotificationUtils.isNotificationEnabled(this)
|
||||||
|
// if (Constants.CanNotification) {
|
||||||
|
// NotificationUtils.firebase(mViewModel)
|
||||||
|
// }
|
||||||
|
// mViewModel.uploadNoticeStatus(
|
||||||
|
// FbNotificationReq(
|
||||||
|
// if (Constants.CanNotification) "1" else "0"
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// val fragments: List<Fragment> = supportFragmentManager.fragments
|
||||||
|
// if (fragments.isNotEmpty()) {
|
||||||
|
// for (fragment in fragments) {
|
||||||
|
// if (fragment.isAdded && !fragment.isDetached) {
|
||||||
|
// fragment.onActivityResult(requestCode, resultCode, data)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private fun notificationGo() {
|
||||||
|
// if (message_id.isNotBlank() && !message_id.contentEquals("null")) {
|
||||||
|
// if ("0" != message_id) {
|
||||||
|
// mViewModel.sendReport(message_id, title)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// when (path) {
|
||||||
|
// "detail" -> {
|
||||||
|
// if (short_play_id.isNotEmpty() && "null" != short_play_id) {
|
||||||
|
// try {
|
||||||
|
// val toInt = short_play_id.toInt()
|
||||||
|
// binding?.root?.postDelayed({
|
||||||
|
// startActivity(Intent(
|
||||||
|
// this, PlayerDetailActivity::class.java
|
||||||
|
// ).apply {
|
||||||
|
// putExtra(
|
||||||
|
// Constants.CONSTANTS_short_play_id, toInt
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// }, 700)
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// "orderDetail" -> {
|
||||||
|
// binding?.root?.postDelayed({
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// this, StoreActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }, 500)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// "feedback" -> {
|
||||||
|
// binding?.root?.postDelayed({
|
||||||
|
// if (message_id.isNotBlank() && message_id != "null") {
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putString(Constants.CONSTANTS_Detail_id, message_id)
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// this, FeedBackDetailActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// } else {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// this, FeedBackListActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }, 500)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// private fun uploadDDL(webpageURL: Uri?) {
|
||||||
|
// val ddl = webpageURL.toString()
|
||||||
|
// if (ddl.isNotEmpty() && !ddl.contentEquals("null")) {
|
||||||
|
// w2aSelfAttribution(ddl)
|
||||||
|
// val regex = """short_play_id=(\d+).*""".toRegex()
|
||||||
|
// val matchResult = regex.find(ddl)
|
||||||
|
// if (matchResult != null) {
|
||||||
|
// val shortPlayId = matchResult.groupValues[1]
|
||||||
|
// shortVideoId = shortPlayId.toInt()
|
||||||
|
// if (shortVideoId != 0) {
|
||||||
|
// binding.root.postDelayed({
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// this, PlayerDetailActivity::class.java
|
||||||
|
// ).apply {
|
||||||
|
// putExtra(
|
||||||
|
// Constants.CONSTANTS_short_play_id, shortVideoId
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// }, 1000)
|
||||||
|
// }
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putString(Constants.Constants_DDL_Url, "")
|
||||||
|
// clearClipboardContent(this)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun getClip() {
|
||||||
|
// this.window.decorView.post {
|
||||||
|
// val clipContent = getClipContent()
|
||||||
|
// if (clipContent.isNotEmpty()) {
|
||||||
|
// if (clipContent.startsWith("[QJ]")) {
|
||||||
|
// val urlString = clipContent.removePrefix("[QJ]").trim()
|
||||||
|
// val extractVideoInfo = parseVideoAndShortPlayIds(urlString)
|
||||||
|
// if (urlString.contains("reelcrush")) {
|
||||||
|
// shortVideoId = extractVideoInfo.second?.toInt() ?: 0
|
||||||
|
// w2aSelfAttribution(clipContent)
|
||||||
|
// if (shortVideoId != 0) {
|
||||||
|
// binding.root.postDelayed({
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// this, PlayerDetailActivity::class.java
|
||||||
|
// ).apply {
|
||||||
|
// putExtra(
|
||||||
|
// Constants.CONSTANTS_short_play_id, shortVideoId
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// }, 3000)
|
||||||
|
// }
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putString(Constants.Constants_DDL_Url, "")
|
||||||
|
// clearClipboardContent(this)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private fun switchFragment(position: Int) {
|
||||||
|
val transaction = supportFragmentManager.beginTransaction()
|
||||||
|
hideFragments(transaction)
|
||||||
|
when (position) {
|
||||||
|
0 -> homeFragment?.let {
|
||||||
|
transaction.show(it)
|
||||||
|
} ?: HomeFragment().let {
|
||||||
|
homeFragment = it
|
||||||
|
transaction.add(R.id.container, it, "HomeFragment")
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> reelsFragment?.let {
|
||||||
|
transaction.show(it)
|
||||||
|
} ?: ReelsFragment().let {
|
||||||
|
reelsFragment = it
|
||||||
|
transaction.add(
|
||||||
|
R.id.container, it, "ReelsFragment"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> myListFragment?.let {
|
||||||
|
transaction.show(it)
|
||||||
|
} ?: SavedFragment().let {
|
||||||
|
myListFragment = it
|
||||||
|
transaction.add(R.id.container, it, "SavedFragment")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
3 -> meFragment?.let {
|
||||||
|
transaction.show(it)
|
||||||
|
} ?: MeFragment().let {
|
||||||
|
meFragment = it
|
||||||
|
transaction.add(R.id.container, it, "MeFragment")
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index = position
|
||||||
|
binding?.tabLayout?.currentTab = index
|
||||||
|
transaction.commitAllowingStateLoss()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun hideFragments(transaction: FragmentTransaction) {
|
||||||
|
homeFragment?.let { transaction.hide(it) }
|
||||||
|
reelsFragment?.let { transaction.hide(it) }
|
||||||
|
myListFragment?.let { transaction.hide(it) }
|
||||||
|
meFragment?.let { transaction.hide(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// private fun getClipContent(): String {
|
||||||
|
// val manager: ClipboardManager = getSystemService(
|
||||||
|
// CLIPBOARD_SERVICE
|
||||||
|
// ) as ClipboardManager
|
||||||
|
// val primaryClip = manager.primaryClip
|
||||||
|
// val itemCount = primaryClip?.itemCount
|
||||||
|
// if (itemCount != null) {
|
||||||
|
// if (manager.hasPrimaryClip() && itemCount > 0) {
|
||||||
|
// val itemAt = manager.primaryClip?.getItemAt(0)
|
||||||
|
// val addedText: CharSequence = itemAt?.text.toString()
|
||||||
|
// val addedTextString = addedText.toString()
|
||||||
|
// if (!TextUtils.isEmpty(addedTextString)) {
|
||||||
|
// return addedTextString
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return ""
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private fun w2aSelfAttribution(data: String?) {
|
||||||
|
// data?.let { mViewModel.w2aSelfAttribution(it) }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private fun clearClipboardContent(context: Context) {
|
||||||
|
// val clipboardManager =
|
||||||
|
// context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
//
|
||||||
|
// val emptyClip = ClipData.newPlainText("", "")
|
||||||
|
//
|
||||||
|
// clipboardManager.setPrimaryClip(emptyClip)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private fun parseVideoAndShortPlayIds(clipboardContent: String): Pair<String?, String?> {
|
||||||
|
//
|
||||||
|
// val queryStartIndex = clipboardContent.indexOf('?')
|
||||||
|
// val queryString =
|
||||||
|
// if (queryStartIndex != -1) clipboardContent.substring(queryStartIndex + 1) else ""
|
||||||
|
//
|
||||||
|
// val videoIdRegex = Regex("video_id=(\\d+)")
|
||||||
|
// val shortPlayIdRegex = Regex("short_play_id=(\\d+)")
|
||||||
|
//
|
||||||
|
// val videoIdMatch = videoIdRegex.find(queryString)?.groupValues?.get(1)
|
||||||
|
// val shortPlayIdMatch = shortPlayIdRegex.find(queryString)?.groupValues?.get(1)
|
||||||
|
//
|
||||||
|
// return Pair(videoIdMatch, shortPlayIdMatch)
|
||||||
|
// }
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivityMainBinding {
|
||||||
|
return ActivityMainBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onEvent(event: String) {
|
||||||
|
if (Constants.CONSTANTS_auth_refresh == event) {
|
||||||
|
mViewModel.createUserAccount()
|
||||||
|
}
|
||||||
|
if (Constants.CONSTANTS_main_stop == event) {
|
||||||
|
binding?.root?.postDelayed({ hideLoading() }, 300)
|
||||||
|
}
|
||||||
|
// if (Constants.CONSTANTS_enterTheApp == event) {
|
||||||
|
// mViewModel.enterTheApp()
|
||||||
|
// }
|
||||||
|
// if (Constants.CONSTANTS_leaveApp == event) {
|
||||||
|
// mViewModel.leaveApp()
|
||||||
|
// }
|
||||||
|
// if (Constants.CONSTANTS_onLine == event) {
|
||||||
|
// mViewModel.onLine()
|
||||||
|
// }
|
||||||
|
// if (Constants.Constants_onTokenRefresh == event) {
|
||||||
|
// NotificationUtils.firebase(mViewModel)
|
||||||
|
// }
|
||||||
|
// if (Constants.Constants_getClip == event) {
|
||||||
|
// getClip()
|
||||||
|
// }
|
||||||
|
// if (Constants.CONSTANTS_web_Login == event) {
|
||||||
|
// if (!NetworkUtils.isConnected()) {
|
||||||
|
// toast(getString(R.string.example_no_network))
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// showLogin()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// private var callbackManager: CallbackManager? = null
|
||||||
|
// private var loginDialog: LoginDialog? = null
|
||||||
|
//
|
||||||
|
// private fun showLogin() {
|
||||||
|
// callbackManager = CallbackManager.Factory.create()
|
||||||
|
// LoginManager.getInstance().registerCallback(callbackManager,
|
||||||
|
// object : FacebookCallback<LoginResult> {
|
||||||
|
// override fun onSuccess(loginResult: LoginResult) {
|
||||||
|
// val enableButtons = AccessToken.getCurrentAccessToken() != null
|
||||||
|
// if (enableButtons) {
|
||||||
|
// val mGraphRequest = GraphRequest.newMeRequest(
|
||||||
|
// loginResult.accessToken
|
||||||
|
// ) { jsonObject, response ->
|
||||||
|
// if (response!!.error != null) {
|
||||||
|
// toast("Facebook login exception.${response.error?.exception.toString()}")
|
||||||
|
// loginDialog?.dismiss()
|
||||||
|
// } else {
|
||||||
|
// val id = jsonObject?.optString("id")
|
||||||
|
// val name = jsonObject?.optString("name")
|
||||||
|
// val object_pic: JSONObject? =
|
||||||
|
// jsonObject!!.optJSONObject("picture")
|
||||||
|
// val object_data = object_pic?.optJSONObject("data")
|
||||||
|
// val photo = object_data?.optString("url")
|
||||||
|
// showLoading()
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_leaveApp)
|
||||||
|
// mViewModel.doLogin(
|
||||||
|
// LoginReq(
|
||||||
|
// photo.toString(),
|
||||||
|
// "",
|
||||||
|
// name.toString(),
|
||||||
|
// "",
|
||||||
|
// "facebook",
|
||||||
|
// id.toString()
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// val parameters = Bundle()
|
||||||
|
// parameters.putString("fields", "id,name,email,picture")
|
||||||
|
// mGraphRequest.parameters = parameters
|
||||||
|
// mGraphRequest.executeAsync()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onCancel() {
|
||||||
|
// toast("Facebook login Cancel")
|
||||||
|
// loginDialog?.dismiss()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onError(exception: FacebookException) {
|
||||||
|
// toast("Facebook login exception.$exception")
|
||||||
|
// loginDialog?.dismiss()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// loginDialog = LoginDialog(this)
|
||||||
|
// val tv_facebook_login =
|
||||||
|
// loginDialog?.findViewById<AppCompatTextView>(R.id.tv_facebook_login)
|
||||||
|
// tv_facebook_login?.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// callbackManager?.let { it1 ->
|
||||||
|
// LoginManager.getInstance()
|
||||||
|
// .logInWithReadPermissions(this, it1, arrayListOf("public_profile", "email"))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// loginDialog?.show()
|
||||||
|
// loginDialog?.setOnDismissListener {
|
||||||
|
// LoginManager.getInstance().unregisterCallback(callbackManager)
|
||||||
|
// callbackManager = null
|
||||||
|
// loginDialog = null
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||||
|
moveTaskToBack(true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onKeyDown(keyCode, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
// scheduler?.shutdown()
|
||||||
|
// scheduler = null
|
||||||
|
super.onDestroy()
|
||||||
|
EventBus.getDefault().unregister(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.main
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivitySplashBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.Memory
|
||||||
|
|
||||||
|
class SplashActivity : BaseActivity<ActivitySplashBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
override fun top() {
|
||||||
|
|
||||||
|
val toString = Memory.getMMKV()
|
||||||
|
.getString(Constants.CONSTANTS_AuthorizationExample, "")
|
||||||
|
.toString()
|
||||||
|
if (toString.isEmpty()) {
|
||||||
|
mViewModel.createUserAccount()
|
||||||
|
} else {
|
||||||
|
goMain()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.userRegisterData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
Memory.getMMKV()
|
||||||
|
.putString(Constants.CONSTANTS_AuthorizationExample, it.data?.token)
|
||||||
|
goMain()
|
||||||
|
} else {
|
||||||
|
goMain()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun goMain() {
|
||||||
|
binding?.root?.postDelayed({
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
this,
|
||||||
|
MainActivity::class.java
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivitySplashBinding {
|
||||||
|
return ActivitySplashBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.me
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityAboutBinding
|
||||||
|
import com.jia.er.nebuluxe.app.utils.PackageUtils
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
|
||||||
|
class AboutActivity : BaseActivity<ActivityAboutBinding>() {
|
||||||
|
override fun top() {
|
||||||
|
binding.exampleIvBack.setOnClickListener { finish() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
binding.tvVersion.text = "V".plus(PackageUtils.getPackageVersion(this))
|
||||||
|
binding.tvPrivacyPolicy.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
val webIntent =
|
||||||
|
Intent(Intent.ACTION_VIEW, Uri.parse("https://www.nebuluxetv.com/private"))
|
||||||
|
startActivity(webIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.tvUserAgreement.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
val webIntent =
|
||||||
|
Intent(Intent.ACTION_VIEW, Uri.parse("https://www.nebuluxetv.com/user_policy"))
|
||||||
|
startActivity(webIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.tvVisitWebsite.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
val webIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.nebuluxetv.com"))
|
||||||
|
startActivity(webIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivityAboutBinding {
|
||||||
|
return ActivityAboutBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
}
|
247
app/src/main/java/com/jia/er/nebuluxe/app/me/MeFragment.kt
Normal file
247
app/src/main/java/com/jia/er/nebuluxe/app/me/MeFragment.kt
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.me
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableString
|
||||||
|
import android.text.style.UnderlineSpan
|
||||||
|
import android.view.View
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CircleCrop
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseFragment
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.FragmentMeBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.Memory
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
class MeFragment : BaseFragment<FragmentMeBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
|
||||||
|
override fun top() {
|
||||||
|
EventBus.getDefault().register(this)
|
||||||
|
mViewModel.noticeNum()
|
||||||
|
binding.srMe.setOnRefreshListener {
|
||||||
|
mViewModel.getInfo()
|
||||||
|
mViewModel.noticeNum()
|
||||||
|
}
|
||||||
|
// binding.llFeedback.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireActivity(),
|
||||||
|
// FeedBackActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding.clTopUp.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireActivity(),
|
||||||
|
// StoreActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding.clVip.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireActivity(),
|
||||||
|
// StoreActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding.tvExampleAbout.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireActivity(),
|
||||||
|
// AboutActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding.tvExampleSettings.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireActivity(),
|
||||||
|
// SettingActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding.tvId.setOnClickListener {
|
||||||
|
// val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
// clipboard.setPrimaryClip(
|
||||||
|
// ClipData.newPlainText(
|
||||||
|
// "label",
|
||||||
|
// Memory.getCustomId()
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// toast("Copied")
|
||||||
|
// }
|
||||||
|
// binding.wallet.setOnClickListener {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// requireActivity(),
|
||||||
|
// MyWalletActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// setUserUI()
|
||||||
|
// binding.tvVipStatus.applyTextSkew(-10f)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
setUserUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.infoData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
it.data?.let { it1 ->
|
||||||
|
Memory.saveUserInfo(it1)
|
||||||
|
setUserUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.srMe.finishRefresh()
|
||||||
|
}
|
||||||
|
// mViewModel.noticeNumData.observe(this) {
|
||||||
|
// if (it != null) {
|
||||||
|
// if (it.data?.feedback_notice_num != 0) {
|
||||||
|
// binding?.tvBackNum?.visibility = View.VISIBLE
|
||||||
|
// binding?.tvBackNum?.text = it.data?.feedback_notice_num.toString()
|
||||||
|
// } else {
|
||||||
|
// binding?.tvBackNum?.visibility = View.INVISIBLE
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// binding?.tvBackNum?.visibility = View.INVISIBLE
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("UseCompatLoadingForDrawables")
|
||||||
|
private fun setUserUI() {
|
||||||
|
if (Memory.isTourist()) {
|
||||||
|
binding?.ivAvatar?.let {
|
||||||
|
Glide.with(this).load(Memory.getUserInfo()?.avator).skipMemoryCache(true)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.apply(RequestOptions.bitmapTransform(CircleCrop()))
|
||||||
|
.placeholder(R.drawable.iv_avatar)
|
||||||
|
.error(R.drawable.iv_avatar).into(it)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding?.tvUserName?.text =
|
||||||
|
Memory.getUserInfo()?.family_name.plus(Memory.getUserInfo()?.giving_name)
|
||||||
|
binding?.ivAvatar?.let {
|
||||||
|
Glide.with(this).load(Memory.getUserInfo()?.avator).skipMemoryCache(true)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.apply(RequestOptions.bitmapTransform(CircleCrop()))
|
||||||
|
.placeholder(R.drawable.iv_avatar)
|
||||||
|
.error(R.drawable.iv_avatar).into(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if (Memory.isVip()) {
|
||||||
|
// binding.clVip.background = context?.getDrawable(R.drawable.iv_me_vip_h)
|
||||||
|
// binding.tvVipStatus.text = Memory.getUserInfo()?.vip_type
|
||||||
|
// val content = binding.tvVipStatus.text
|
||||||
|
// val spannableString = SpannableString(content)
|
||||||
|
// spannableString.setSpan(
|
||||||
|
// UnderlineSpan(),
|
||||||
|
// 0,
|
||||||
|
// content.length,
|
||||||
|
// Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
// )
|
||||||
|
// binding.tvVipStatus.text = spannableString
|
||||||
|
// binding?.tvInfoVip?.text =
|
||||||
|
// "Expiration Time:".plus(Memory.getUserInfo()?.vip_end_time?.toLong()
|
||||||
|
// ?.let { transToString(it) })
|
||||||
|
// binding?.tvInfoVip?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
// context?.getDrawable(R.drawable.iv_time),
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// null
|
||||||
|
// )
|
||||||
|
// binding?.tvVipStatus?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
// context?.getDrawable(R.drawable.iv_vip_h),
|
||||||
|
// null,
|
||||||
|
// context?.getDrawable(R.drawable.iv_vip_right),
|
||||||
|
// null
|
||||||
|
// )
|
||||||
|
// binding.tvGo.text = "Renew"
|
||||||
|
// binding.tvGo.background = context?.getDrawable(R.drawable.bg_vip_go_h)
|
||||||
|
// } else {
|
||||||
|
// binding?.tvInfoVip?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// null,
|
||||||
|
// null
|
||||||
|
// )
|
||||||
|
// val spannableString = SpannableString("VIP Membership")
|
||||||
|
// spannableString.setSpan(
|
||||||
|
// UnderlineSpan(),
|
||||||
|
// 0,
|
||||||
|
// spannableString.length,
|
||||||
|
// Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
// )
|
||||||
|
// binding.tvVipStatus.text = spannableString
|
||||||
|
// binding?.tvVipStatus?.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
// context?.getDrawable(R.drawable.iv_vip),
|
||||||
|
// null,
|
||||||
|
// context?.getDrawable(R.drawable.iv_vip_right),
|
||||||
|
// null
|
||||||
|
// )
|
||||||
|
// binding.tvGo.text = "Go"
|
||||||
|
// binding.tvGo.background = context?.getDrawable(R.drawable.bg_vip_go)
|
||||||
|
// binding?.tvInfoVip?.text = "Unlock VIP Now"
|
||||||
|
// binding.clVip.background = context?.getDrawable(R.drawable.iv_me_vip_n)
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
binding?.tvId?.text = "ID:".plus(Memory.getUserInfo()?.customer_id)
|
||||||
|
// binding?.tvCoinNum?.text = Memory.getUserInfo()?.coin_left_total.toString()
|
||||||
|
// binding?.tvDonateNum?.text = Memory.getUserInfo()?.send_coin_left_total.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onHiddenChanged(hidden: Boolean) {
|
||||||
|
super.onHiddenChanged(hidden)
|
||||||
|
if (!hidden) {
|
||||||
|
mViewModel.getInfo()
|
||||||
|
mViewModel.noticeNum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onEvent(event: String) {
|
||||||
|
if (Constants.CONSTANTS_refresh_me == event) {
|
||||||
|
mViewModel.getInfo()
|
||||||
|
mViewModel.noticeNum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): FragmentMeBinding {
|
||||||
|
return FragmentMeBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
EventBus.getDefault().unregister(this)
|
||||||
|
}
|
||||||
|
}
|
131
app/src/main/java/com/jia/er/nebuluxe/app/me/SettingActivity.kt
Normal file
131
app/src/main/java/com/jia/er/nebuluxe/app/me/SettingActivity.kt
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.me
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivitySettingBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class SettingActivity : BaseActivity<ActivitySettingBinding>() {
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
|
||||||
|
override fun top() {
|
||||||
|
binding.exampleIvBack.setOnClickListener { finish() }
|
||||||
|
binding.tvClearCache.setOnClickListener {
|
||||||
|
clearCache(this)
|
||||||
|
toast(getString(R.string.success))
|
||||||
|
}
|
||||||
|
binding.exampleIvBack.setOnClickListener { finish() }
|
||||||
|
// binding.tvExampleLogOut.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// if (!Memory.isTourist()) {
|
||||||
|
// startActivity(
|
||||||
|
// Intent(
|
||||||
|
// this,
|
||||||
|
// AccountDeleteActivity::class.java
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
// } else {
|
||||||
|
// toast(getString(R.string.log_first))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding?.tvExampleQuit?.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// if (!Memory.isTourist()) {
|
||||||
|
// val exampleUnFavoriteDialog = NotificationDialog(this)
|
||||||
|
// val tvThinkAgain =
|
||||||
|
// exampleUnFavoriteDialog.findViewById<AppCompatTextView>(R.id.example_tv_think_again)
|
||||||
|
// val tvUnfavorite =
|
||||||
|
// exampleUnFavoriteDialog.findViewById<AppCompatTextView>(R.id.example_tv_unfavorite)
|
||||||
|
// val tvTitle =
|
||||||
|
// exampleUnFavoriteDialog.findViewById<AppCompatTextView>(R.id.example_tv_title)
|
||||||
|
// val tvContent =
|
||||||
|
// exampleUnFavoriteDialog.findViewById<AppCompatTextView>(R.id.example_tv_content)
|
||||||
|
// tvThinkAgain.text = "Cancel"
|
||||||
|
// tvUnfavorite.text = "Confirm"
|
||||||
|
// tvTitle.text = "Tips"
|
||||||
|
// tvContent.text = "Are you sure you want to log out?"
|
||||||
|
// tvThinkAgain.setOnClickListener { exampleUnFavoriteDialog.dismiss() }
|
||||||
|
// tvUnfavorite.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// showLoading()
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_leaveApp)
|
||||||
|
// mViewModel.doSignout()
|
||||||
|
// exampleUnFavoriteDialog.dismiss()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// exampleUnFavoriteDialog.show()
|
||||||
|
// } else {
|
||||||
|
// toast(getString(R.string.log_first))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// override fun onResume() {
|
||||||
|
// super.onResume()
|
||||||
|
// if (Constants.WebRefresh){
|
||||||
|
// finish()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
// mViewModel.signoutData.observe(this) {
|
||||||
|
// if (it != null) {
|
||||||
|
// toast(getString(R.string.success))
|
||||||
|
// LoginManager.getInstance().logOut()
|
||||||
|
// Memory.getMMKV()
|
||||||
|
// .putString(Constants.CONSTANTS_AuthorizationExample, it.data?.token)
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_enterTheApp)
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_onLine)
|
||||||
|
// EventBus.getDefault()
|
||||||
|
// .post(Constants.CONSTANTS_refresh_me)
|
||||||
|
// Constants.WebRefresh = true
|
||||||
|
// finish()
|
||||||
|
// } else {
|
||||||
|
// toast(getString(R.string.network_error))
|
||||||
|
// }
|
||||||
|
// hideLoading()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivitySettingBinding {
|
||||||
|
return ActivitySettingBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun clearCache(context: Context) {
|
||||||
|
deleteFilesInDirectory(context.cacheDir)
|
||||||
|
|
||||||
|
context.externalCacheDir?.let {
|
||||||
|
deleteFilesInDirectory(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteFilesInDirectory(directory: File) {
|
||||||
|
if (directory.isDirectory) {
|
||||||
|
val files = directory.listFiles()
|
||||||
|
if (files != null) {
|
||||||
|
for (file in files) {
|
||||||
|
if (file.isDirectory) {
|
||||||
|
deleteFilesInDirectory(file)
|
||||||
|
} else {
|
||||||
|
file.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
directory.delete()
|
||||||
|
}
|
||||||
|
}
|
258
app/src/main/java/com/jia/er/nebuluxe/app/net/AppService.kt
Normal file
258
app/src/main/java/com/jia/er/nebuluxe/app/net/AppService.kt
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.net
|
||||||
|
|
||||||
|
import com.jia.er.nebuluxe.app.data.BaseRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.BuyVideoRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CategoriesDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CollectionRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CreateOrderReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.CreateOrderRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CustomerBuyRecordsRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CustomerOrderRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.DetailsRecommendRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.ExampleKeywordDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.FbNotificationReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.FreeSeriesMoreRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HistoryDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeModuleBean
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeNewShortPlayNoPaginateRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeNewShortPlayRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeTopRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.LoginReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.LoginRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.NoticeNumRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PayReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.PayRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PaySettingRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PlayerDetailDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.RecommendDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.RewardCoinsRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.ShortListCategoryDataInfo
|
||||||
|
import com.jia.er.nebuluxe.app.data.UploadHistoryReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.VideoListDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.UserInfoRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.UserRegisterRes
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.Field
|
||||||
|
import retrofit2.http.FormUrlEncoded
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.POST
|
||||||
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
interface AppService {
|
||||||
|
|
||||||
|
@POST("customer/register")
|
||||||
|
fun register(): Call<BaseRes<UserRegisterRes>>
|
||||||
|
|
||||||
|
@GET("customer/info")
|
||||||
|
fun getInfo(): Call<BaseRes<UserInfoRes>>
|
||||||
|
|
||||||
|
|
||||||
|
@POST("homeTop")
|
||||||
|
fun homeTop(): Call<BaseRes<HomeTopRes>>
|
||||||
|
|
||||||
|
@POST("newShortPlay")
|
||||||
|
fun newShortPlay(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("page_size") page_size: Int = 10
|
||||||
|
): Call<BaseRes<HomeNewShortPlayRes>>
|
||||||
|
|
||||||
|
@GET("myCollections")
|
||||||
|
fun getCollections(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("page_size") page_size: Int = 10
|
||||||
|
): Call<BaseRes<CollectionRes>>
|
||||||
|
|
||||||
|
@GET("getVideoDetails")
|
||||||
|
fun getVideoDetails(
|
||||||
|
@Query("short_play_id") short_play_id: Int,
|
||||||
|
@Query("video_id") video_id: Int,
|
||||||
|
@Query("activity_id") activity_id: Int,
|
||||||
|
@Query("revolution") revolution: String,
|
||||||
|
@Query("no_ads") no_ads: Boolean?,
|
||||||
|
): Call<BaseRes<PlayerDetailDataRes>>
|
||||||
|
|
||||||
|
@POST("newShortPlayNoPaginate")
|
||||||
|
fun newShortPlayNoPaginate(): Call<BaseRes<HomeNewShortPlayNoPaginateRes>>
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("createHistory")
|
||||||
|
fun createHistory(
|
||||||
|
@Field("short_play_id") short_play_id: Int,
|
||||||
|
@Field("video_id") video_id: Int,
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@GET("getRecommands")
|
||||||
|
fun getRecommands(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("page_size") page_size: Int,
|
||||||
|
@Query("revolution") revolution: String,
|
||||||
|
): Call<BaseRes<RecommendDataRes>>
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("collect")
|
||||||
|
fun collect(
|
||||||
|
@Field("short_play_id") short_play_id: Int,
|
||||||
|
@Field("video_id") video_id: Int
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("cancelCollect")
|
||||||
|
fun cancelCollect(
|
||||||
|
@Field("short_play_id") short_play_id: Int,
|
||||||
|
@Field("video_id") video_id: Int
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
|
||||||
|
@GET("myHistorys")
|
||||||
|
fun myHistorys(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("page_size") page_size: Int = 10
|
||||||
|
): Call<BaseRes<HistoryDataRes>>
|
||||||
|
|
||||||
|
@GET("search")
|
||||||
|
fun getVideoList(@Query("search") search: String): Call<BaseRes<VideoListDataRes>>
|
||||||
|
|
||||||
|
@GET("videoList")
|
||||||
|
fun getVideoList(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("category_id") category_id: Int,
|
||||||
|
@Query("page_size") page_size: Int = 10
|
||||||
|
): Call<BaseRes<VideoListDataRes>>
|
||||||
|
|
||||||
|
@POST("homeRanking")
|
||||||
|
fun homeRanking(@Query("type") type: String): Call<BaseRes<HomeRankingRes>>
|
||||||
|
|
||||||
|
@POST("uploadHistorySeconds")
|
||||||
|
fun uploadHistorySeconds(
|
||||||
|
@Body uploadHistoryReq: UploadHistoryReq
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@GET("freeShorPlayListNoPaginate")
|
||||||
|
fun freeMoreVideo(): Call<BaseRes<FreeSeriesMoreRes>>
|
||||||
|
|
||||||
|
@GET("getDetailsRecommand")
|
||||||
|
fun getDetailsRecommand(
|
||||||
|
): Call<BaseRes<DetailsRecommendRes>>
|
||||||
|
|
||||||
|
@GET("search/hots")
|
||||||
|
fun hots(): Call<BaseRes<ExampleKeywordDataRes>>
|
||||||
|
|
||||||
|
@POST("search/click")
|
||||||
|
fun click(
|
||||||
|
@Query("short_play_id") short_play_id: Int,
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
|
||||||
|
@GET("search")
|
||||||
|
fun keyword(@Query("search") search: String): Call<BaseRes<ExampleKeywordDataRes>>
|
||||||
|
|
||||||
|
@GET("home/all-modules")
|
||||||
|
fun allModules(): Call<BaseRes<HomeModuleBean>>
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("buy_video")
|
||||||
|
fun buyVideo(
|
||||||
|
@Field("short_play_id") short_play_id: Int,
|
||||||
|
@Field("video_id") video_id: Int,
|
||||||
|
): Call<BaseRes<BuyVideoRes>>
|
||||||
|
|
||||||
|
@GET("getCategories")
|
||||||
|
fun getCategories(): Call<BaseRes<CategoriesDataRes>>
|
||||||
|
|
||||||
|
@POST("customer/onLine")
|
||||||
|
fun onLine(
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@POST("customer/enterTheApp")
|
||||||
|
fun enterTheApp(): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@POST("customer/leaveApp")
|
||||||
|
fun leaveApp(): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("customer/firebaseToken")
|
||||||
|
fun firebaseToken(@Field("fcm_token") fcm_token: String): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("w2aSelfAttribution")
|
||||||
|
fun w2aSelfAttribution(
|
||||||
|
@Field("data") data: String
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
|
||||||
|
@POST("openNotify")
|
||||||
|
fun openNotify(
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@POST("customer/uploadNoticeStatus")
|
||||||
|
fun uploadNoticeStatus(
|
||||||
|
@Body fbNotificationReq: FbNotificationReq
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("message/sendReport")
|
||||||
|
fun sendReport(
|
||||||
|
@Field("message_id") message_id: String, @Field("title") title: String
|
||||||
|
): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@POST("noticeNum")
|
||||||
|
fun noticeNum(): Call<BaseRes<NoticeNumRes>>
|
||||||
|
|
||||||
|
@GET("getCustomerOrder")
|
||||||
|
fun getCustomerOrder(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("buy_type") buy_type: String,
|
||||||
|
@Query("page_size") page_size: Int = 10
|
||||||
|
): Call<BaseRes<CustomerOrderRes>>
|
||||||
|
|
||||||
|
@GET("getCustomerBuyRecords")
|
||||||
|
fun getCustomerBuyRecords(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("page_size") page_size: Int = 10
|
||||||
|
): Call<BaseRes<CustomerBuyRecordsRes>>
|
||||||
|
|
||||||
|
@POST("sendCoinList")
|
||||||
|
fun sendCoinList(
|
||||||
|
@Query("current_page") current_page: Int,
|
||||||
|
@Query("page_size") page_size: Int = 10
|
||||||
|
): Call<BaseRes<RewardCoinsRes>>
|
||||||
|
|
||||||
|
@GET("paySettingsV3")
|
||||||
|
fun getPaySetting(
|
||||||
|
@Query("short_play_id") short_play_id: Int?,
|
||||||
|
@Query("short_play_video_id") short_play_video_id: Int?
|
||||||
|
): Call<BaseRes<PaySettingRes>>
|
||||||
|
|
||||||
|
|
||||||
|
@POST("createOrder")
|
||||||
|
fun createOrder(@Body createOrderReq: CreateOrderReq): Call<BaseRes<CreateOrderRes>>
|
||||||
|
|
||||||
|
@POST("googlePaid")
|
||||||
|
fun googlePaid(@Body examplePayReq: PayReq?): Call<BaseRes<PayRes>>
|
||||||
|
|
||||||
|
@POST("event/add")
|
||||||
|
suspend fun upError(@Body body: Map<String, @JvmSuppressWildcards Any>): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@POST("customer/login")
|
||||||
|
fun login(@Body exampleLoginReq: LoginReq): Call<BaseRes<LoginRes>>
|
||||||
|
|
||||||
|
@POST("customer/logoff")
|
||||||
|
fun logoff(): Call<BaseRes<Any>>
|
||||||
|
|
||||||
|
@POST("customer/signout")
|
||||||
|
fun signout(): Call<BaseRes<LoginRes>>
|
||||||
|
|
||||||
|
@GET("highestPaymentAndHottestVideo")
|
||||||
|
fun homeHot(
|
||||||
|
@Query("buy_count_num") buycount: Int,
|
||||||
|
@Query("hottest_num") hottestnum: Int,
|
||||||
|
): Call<BaseRes<VideoListDataRes>>
|
||||||
|
|
||||||
|
@GET("categoryListAppendShortPlay")
|
||||||
|
fun userCenterRecommend(
|
||||||
|
@Query("short_play_num") shortplaynum: Int,
|
||||||
|
): Call<BaseRes<ShortListCategoryDataInfo>>
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.net
|
||||||
|
|
||||||
|
import com.jia.er.nebuluxe.app.net.Decryption.EN_STR_TAG
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
import okhttp3.ResponseBody
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
|
||||||
|
class BodyInterceptor : Interceptor {
|
||||||
|
|
||||||
|
@kotlin.jvm.Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val k_center = chain.proceed(chain.request())
|
||||||
|
return if (k_center.body != null && k_center.body!!.contentType() != null) {
|
||||||
|
val actiity = k_center.body!!.contentType()
|
||||||
|
val circle = k_center.body!!.string()
|
||||||
|
val str: String = if (!circle.startsWith(EN_STR_TAG)) {
|
||||||
|
circle
|
||||||
|
} else {
|
||||||
|
Decryption.deStr(circle)
|
||||||
|
}
|
||||||
|
val current = ResponseBody.create(actiity, str)
|
||||||
|
k_center.newBuilder().body(current).build()
|
||||||
|
} else {
|
||||||
|
k_center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
app/src/main/java/com/jia/er/nebuluxe/app/net/Decryption.kt
Normal file
66
app/src/main/java/com/jia/er/nebuluxe/app/net/Decryption.kt
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.net
|
||||||
|
|
||||||
|
|
||||||
|
object Decryption {
|
||||||
|
const val BF_SIZE = 2048
|
||||||
|
const val EN_STR_TAG = '$'
|
||||||
|
|
||||||
|
fun deStr(data: String): String {
|
||||||
|
return String(deStrBytes(data), Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt bytes from hex string
|
||||||
|
fun deStrBytes(data: String): ByteArray {
|
||||||
|
if (!data.startsWith(EN_STR_TAG)) {
|
||||||
|
throw IllegalArgumentException("Invalid encoded string")
|
||||||
|
}
|
||||||
|
val hexData = data.substring(1)
|
||||||
|
val bytes = hexData.chunked(2).map { it.toInt(16).toByte() }.toByteArray()
|
||||||
|
return desadasd(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt data
|
||||||
|
fun desadasd(data: ByteArray): ByteArray {
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
val saltLen = data[0].toInt()
|
||||||
|
val salt = data.slice(1 until 1 + saltLen).toByteArray()
|
||||||
|
return deWithSalt(data.slice(1 + saltLen until data.size).toByteArray(), salt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt data with salt
|
||||||
|
fun deWithSalt(data: ByteArray, salt: ByteArray): ByteArray {
|
||||||
|
val decryptedData = cxEd(data)
|
||||||
|
return removeSalt(decryptedData, salt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt/Decrypt data by flipping bits
|
||||||
|
fun cxEd(data: ByteArray): ByteArray {
|
||||||
|
return data.map { (it.toInt() xor 0xFF).toByte() }.toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove salt from data
|
||||||
|
fun removeSalt(data: ByteArray, salt: ByteArray): ByteArray {
|
||||||
|
if (salt.isEmpty()) return data
|
||||||
|
val ret = mutableListOf<Byte>()
|
||||||
|
var idx = 0
|
||||||
|
val sl = salt.size
|
||||||
|
data.forEach {
|
||||||
|
val s = salt[idx % sl]
|
||||||
|
ret.add(ssadcalRemoveSalt(it, s))
|
||||||
|
idx++
|
||||||
|
}
|
||||||
|
return ret.toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ssadcalRemoveSalt(v: Byte, s: Byte): Byte {
|
||||||
|
return if (v >= s) {
|
||||||
|
(v - s).toByte()
|
||||||
|
} else {
|
||||||
|
(0xFF - (s - v) + 1).toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
316
app/src/main/java/com/jia/er/nebuluxe/app/net/MainRequest.kt
Normal file
316
app/src/main/java/com/jia/er/nebuluxe/app/net/MainRequest.kt
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.net
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import com.jia.er.nebuluxe.app.data.BaseRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.BuyVideoRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CollectionRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CreateOrderReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.CreateOrderRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CustomerBuyRecordsRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CustomerOrderRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.DetailsRecommendRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.ExampleKeywordDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.FbNotificationReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.FreeSeriesMoreRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HistoryDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeModuleBean
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeNewShortPlayNoPaginateRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeNewShortPlayRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeTopRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.NoticeNumRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PayReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.PayRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PaySettingRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PlayerDetailDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.RecommendDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.RewardCoinsRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.UploadHistoryReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.VideoListDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.UserInfoRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.UserRegisterRes
|
||||||
|
import com.jia.er.nebuluxe.app.net.Retrofit.handleData
|
||||||
|
import com.jia.er.nebuluxe.app.net.Retrofit.response
|
||||||
|
import com.jia.er.nebuluxe.app.data.CategoriesDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.LoginReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.LoginRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.ShortListCategoryDataInfo
|
||||||
|
|
||||||
|
object MainRequest {
|
||||||
|
private val appService = Retrofit.build(AppService::class.java)
|
||||||
|
|
||||||
|
|
||||||
|
fun userRegister(): LiveData<Result<BaseRes<UserRegisterRes>>> = handleData {
|
||||||
|
appService.register().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getInfo(): LiveData<Result<BaseRes<UserInfoRes>>> = handleData {
|
||||||
|
appService.getInfo().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun homeTop(): LiveData<Result<BaseRes<HomeTopRes>>> = handleData {
|
||||||
|
appService.homeTop()
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun newShortPlay(current_page: Int): LiveData<Result<BaseRes<HomeNewShortPlayRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.newShortPlay(current_page)
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getCollections(current_page: Int): LiveData<Result<BaseRes<CollectionRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.getCollections(current_page).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVideoDetails(
|
||||||
|
short_play_id: Int, video_id: Int, activity_id: Int, revolution: String, no_ads: Boolean?
|
||||||
|
): LiveData<Result<BaseRes<PlayerDetailDataRes>>> = handleData {
|
||||||
|
appService.getVideoDetails(
|
||||||
|
short_play_id,
|
||||||
|
video_id,
|
||||||
|
activity_id,
|
||||||
|
revolution,
|
||||||
|
no_ads
|
||||||
|
)
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun newShortPlayNoPaginate(): LiveData<Result<BaseRes<HomeNewShortPlayNoPaginateRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.newShortPlayNoPaginate()
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun doCreateHistory(
|
||||||
|
short_play_id: Int, video_id: Int
|
||||||
|
): LiveData<Result<BaseRes<Any>>> = handleData {
|
||||||
|
appService.createHistory(short_play_id, video_id).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getRecommands(
|
||||||
|
current_page: Int, page_size: Int, revolution: String
|
||||||
|
): LiveData<Result<BaseRes<RecommendDataRes>>> = handleData {
|
||||||
|
appService.getRecommands(current_page, page_size, revolution).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private suspend fun collect(short_play_id: Int, video_id: Int) =
|
||||||
|
appService.collect(short_play_id, video_id).response()
|
||||||
|
|
||||||
|
fun doCollect(
|
||||||
|
short_play_id: Int, video_id: Int
|
||||||
|
): LiveData<Result<BaseRes<Any>>> = handleData {
|
||||||
|
collect(short_play_id, video_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun cancelCollect(short_play_id: Int, video_id: Int) =
|
||||||
|
appService.cancelCollect(short_play_id, video_id).response()
|
||||||
|
|
||||||
|
fun doCancelCollect(
|
||||||
|
short_play_id: Int, video_id: Int
|
||||||
|
): LiveData<Result<BaseRes<Any>>> = handleData {
|
||||||
|
cancelCollect(short_play_id, video_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun myHistorys(
|
||||||
|
current_page: Int
|
||||||
|
): LiveData<Result<BaseRes<HistoryDataRes>>> = handleData {
|
||||||
|
appService.myHistorys(current_page).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getVideoList(search: String): LiveData<Result<BaseRes<VideoListDataRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.getVideoList(search).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVideoList(
|
||||||
|
current_page: Int,
|
||||||
|
category_id: Int
|
||||||
|
): LiveData<Result<BaseRes<VideoListDataRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.getVideoList(current_page, category_id).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun homeRanking(type: String): LiveData<Result<BaseRes<HomeRankingRes>>> = handleData {
|
||||||
|
appService.homeRanking(type)
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun freeMoreVideo(
|
||||||
|
): LiveData<Result<BaseRes<FreeSeriesMoreRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.freeMoreVideo().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getDetailsRecommand(
|
||||||
|
): LiveData<Result<BaseRes<DetailsRecommendRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.getDetailsRecommand().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uploadHistorySeconds(
|
||||||
|
uploadHistoryReq: UploadHistoryReq
|
||||||
|
): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.uploadHistorySeconds(uploadHistoryReq).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun hots(): LiveData<Result<BaseRes<ExampleKeywordDataRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.hots().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun click(short_play_id: Int): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.click(short_play_id).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun keyword(search: String): LiveData<Result<BaseRes<ExampleKeywordDataRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.keyword(search).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun allModules(): LiveData<Result<BaseRes<HomeModuleBean>>> = handleData {
|
||||||
|
appService.allModules().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doBuyVideo(
|
||||||
|
short_play_id: Int, video_id: Int
|
||||||
|
): LiveData<Result<BaseRes<BuyVideoRes>>> = handleData {
|
||||||
|
appService.buyVideo(short_play_id, video_id).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCategories(): LiveData<Result<BaseRes<CategoriesDataRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.getCategories().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enterTheApp(): LiveData<Result<BaseRes<Any>>> = handleData {
|
||||||
|
appService.enterTheApp().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun leaveApp(): LiveData<Result<BaseRes<Any>>> = handleData {
|
||||||
|
appService.leaveApp().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onLine(
|
||||||
|
): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.onLine().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun firebaseToken(fcm_token: String): LiveData<Result<BaseRes<Any>>> = handleData {
|
||||||
|
appService.firebaseToken(fcm_token).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun w2aSelfAttribution(
|
||||||
|
data: String
|
||||||
|
): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.w2aSelfAttribution(data).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openNotify(
|
||||||
|
): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.openNotify().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uploadNoticeStatus(fbNotificationReq: FbNotificationReq): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.uploadNoticeStatus(fbNotificationReq)
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendReport(
|
||||||
|
message_id: String, title: String
|
||||||
|
): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.sendReport(message_id, title).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun noticeNum(): LiveData<Result<BaseRes<NoticeNumRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.noticeNum().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCustomerOrder(
|
||||||
|
current_page: Int,
|
||||||
|
buy_type: String
|
||||||
|
): LiveData<Result<BaseRes<CustomerOrderRes>>> = handleData {
|
||||||
|
appService.getCustomerOrder(current_page, buy_type).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCustomerBuyRecords(current_page: Int): LiveData<Result<BaseRes<CustomerBuyRecordsRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.getCustomerBuyRecords(current_page).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun sendCoinList(current_page: Int): LiveData<Result<BaseRes<RewardCoinsRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.sendCoinList(current_page).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPaySetting(
|
||||||
|
short_play_id: Int?,
|
||||||
|
video_id: Int?
|
||||||
|
): LiveData<Result<BaseRes<PaySettingRes>>> = handleData {
|
||||||
|
appService.getPaySetting(short_play_id, video_id).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doGooglePaid(examplePayReq: PayReq?): LiveData<Result<BaseRes<PayRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.googlePaid(examplePayReq).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doCreateOrder(createOrderReq: CreateOrderReq): LiveData<Result<BaseRes<CreateOrderRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.createOrder(createOrderReq).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun upError(body: Map<String, @JvmSuppressWildcards Any>): LiveData<Result<BaseRes<Any>>> =
|
||||||
|
handleData {
|
||||||
|
appService.upError(body).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doLogin(exampleLoginReq: LoginReq): LiveData<Result<BaseRes<LoginRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.login(exampleLoginReq).response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doLogoff(): LiveData<Result<BaseRes<Any>>> = handleData {
|
||||||
|
appService.logoff().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun doSignout(): LiveData<Result<BaseRes<LoginRes>>> = handleData {
|
||||||
|
appService.signout().response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun homeHot(buycount: Int, hottestnum: Int): LiveData<Result<BaseRes<VideoListDataRes>>> =
|
||||||
|
handleData {
|
||||||
|
appService.homeHot(buycount, hottestnum)
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun userCenterRecommend(): LiveData<Result<BaseRes<ShortListCategoryDataInfo>>> =
|
||||||
|
handleData {
|
||||||
|
appService.userCenterRecommend(5)
|
||||||
|
.response()
|
||||||
|
}
|
||||||
|
}
|
403
app/src/main/java/com/jia/er/nebuluxe/app/net/MainViewModel.kt
Normal file
403
app/src/main/java/com/jia/er/nebuluxe/app/net/MainViewModel.kt
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.net
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.data.LoginRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.BaseRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.BuyVideoRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CategoriesDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CollectionRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CreateOrderReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.CreateOrderRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CustomerBuyRecordsRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.CustomerOrderRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.DetailsRecommendRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.ExampleKeywordDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.FbNotificationReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.FreeSeriesMoreRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HistoryDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeModuleBean
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeNewShortPlayNoPaginateRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeNewShortPlayRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.HomeRankingRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.LoginReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.NoticeNumRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PayReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.PayRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PaySettingRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.PlayerDetailDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.RecommendDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.RewardCoinsRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.ShortListCategoryDataInfo
|
||||||
|
import com.jia.er.nebuluxe.app.data.UploadHistoryReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.UserInfoRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.UserRegisterRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.VideoListDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainRequest
|
||||||
|
|
||||||
|
class MainViewModel : ViewModel() {
|
||||||
|
private val userRegisterLiveData = MutableLiveData<BaseRes<UserRegisterRes>>()
|
||||||
|
val userRegisterData: MutableLiveData<BaseRes<UserRegisterRes>> get() = userRegisterLiveData
|
||||||
|
fun createUserAccount(
|
||||||
|
) {
|
||||||
|
MainRequest.userRegister().observeForever { result ->
|
||||||
|
userRegisterLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val infoLiveData = MutableLiveData<BaseRes<UserInfoRes>>()
|
||||||
|
val infoData: MutableLiveData<BaseRes<UserInfoRes>> get() = infoLiveData
|
||||||
|
fun getInfo() {
|
||||||
|
MainRequest.getInfo().observeForever { result ->
|
||||||
|
infoLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val newShortPlayLiveData = MutableLiveData<BaseRes<HomeNewShortPlayRes>>()
|
||||||
|
val newShortPlayData: MutableLiveData<BaseRes<HomeNewShortPlayRes>> get() = newShortPlayLiveData
|
||||||
|
fun newShortPlay(current_page: Int) {
|
||||||
|
MainRequest.newShortPlay(current_page)
|
||||||
|
.observeForever {
|
||||||
|
newShortPlayLiveData.value = it.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val videoDetailsLiveData = MutableLiveData<BaseRes<PlayerDetailDataRes>>()
|
||||||
|
val videoDetailsData: MutableLiveData<BaseRes<PlayerDetailDataRes>> get() = videoDetailsLiveData
|
||||||
|
fun getVideoDetails(
|
||||||
|
short_play_id: Int,
|
||||||
|
video_id: Int,
|
||||||
|
activity_id: Int,
|
||||||
|
revolution: String,
|
||||||
|
no_ads: Boolean?
|
||||||
|
) {
|
||||||
|
MainRequest.getVideoDetails(
|
||||||
|
short_play_id,
|
||||||
|
video_id,
|
||||||
|
activity_id,
|
||||||
|
revolution,
|
||||||
|
no_ads
|
||||||
|
)
|
||||||
|
.observeForever { result ->
|
||||||
|
videoDetailsLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val homeNewLiveData = MutableLiveData<BaseRes<HomeNewShortPlayNoPaginateRes>>()
|
||||||
|
val homeNewData: MutableLiveData<BaseRes<HomeNewShortPlayNoPaginateRes>> get() = homeNewLiveData
|
||||||
|
fun newShortPlayNoPaginate() {
|
||||||
|
MainRequest.newShortPlayNoPaginate()
|
||||||
|
.observeForever {
|
||||||
|
homeNewLiveData.value = it.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun doCreateHistory(short_play_id: Int, video_id: Int) {
|
||||||
|
MainRequest.doCreateHistory(short_play_id, video_id).observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val searchLiveData = MutableLiveData<BaseRes<VideoListDataRes>>()
|
||||||
|
val searchData: MutableLiveData<BaseRes<VideoListDataRes>> get() = searchLiveData
|
||||||
|
fun getVideoList(search: String) {
|
||||||
|
MainRequest.getVideoList(search).observeForever { result ->
|
||||||
|
searchLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val videoListLiveData = MutableLiveData<BaseRes<VideoListDataRes>>()
|
||||||
|
val videoListData: MutableLiveData<BaseRes<VideoListDataRes>> get() = videoListLiveData
|
||||||
|
fun getVideoList(current_page: Int, category_id: Int) {
|
||||||
|
MainRequest.getVideoList(current_page, category_id).observeForever { result ->
|
||||||
|
videoListLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val homeRankingLiveData = MutableLiveData<BaseRes<HomeRankingRes>>()
|
||||||
|
val homeRankingData: MutableLiveData<BaseRes<HomeRankingRes>> get() = homeRankingLiveData
|
||||||
|
fun homeRanking(type: String) {
|
||||||
|
MainRequest.homeRanking(type)
|
||||||
|
.observeForever {
|
||||||
|
homeRankingLiveData.value = it.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val freeMoreLiveData = MutableLiveData<BaseRes<FreeSeriesMoreRes>>()
|
||||||
|
val freeMoreData: MutableLiveData<BaseRes<FreeSeriesMoreRes>> get() = freeMoreLiveData
|
||||||
|
|
||||||
|
fun freeMoreVideo() {
|
||||||
|
MainRequest.freeMoreVideo().observeForever { result ->
|
||||||
|
freeMoreLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val recommendLiveData = MutableLiveData<BaseRes<RecommendDataRes>>()
|
||||||
|
val recommendData: MutableLiveData<BaseRes<RecommendDataRes>> get() = recommendLiveData
|
||||||
|
fun getRecommands(current_page: Int, page_size: Int, revolution: String) {
|
||||||
|
MainRequest.getRecommands(current_page, page_size, revolution)
|
||||||
|
.observeForever { result ->
|
||||||
|
recommendLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val collectLiveData = MutableLiveData<BaseRes<Any>>()
|
||||||
|
val collectData: MutableLiveData<BaseRes<Any>> get() = collectLiveData
|
||||||
|
fun doCollect(short_play_id: Int, video_id: Int) {
|
||||||
|
MainRequest.doCollect(short_play_id, video_id).observeForever { result ->
|
||||||
|
collectLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val cancelCollectLiveData = MutableLiveData<BaseRes<Any>>()
|
||||||
|
val cancelCollectData: MutableLiveData<BaseRes<Any>> get() = cancelCollectLiveData
|
||||||
|
fun doCancelCollect(short_play_id: Int, video_id: Int) {
|
||||||
|
MainRequest.doCancelCollect(short_play_id, video_id).observeForever { result ->
|
||||||
|
cancelCollectLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val collectionsLiveData = MutableLiveData<BaseRes<CollectionRes>>()
|
||||||
|
val collectionsData: MutableLiveData<BaseRes<CollectionRes>> get() = collectionsLiveData
|
||||||
|
fun getCollections(current_page: Int) {
|
||||||
|
MainRequest.getCollections(current_page).observeForever { result ->
|
||||||
|
collectionsLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val historysLiveData = MutableLiveData<BaseRes<HistoryDataRes>>()
|
||||||
|
val historysData: MutableLiveData<BaseRes<HistoryDataRes>> get() = historysLiveData
|
||||||
|
fun myHistorys(
|
||||||
|
current_page: Int
|
||||||
|
) {
|
||||||
|
MainRequest.myHistorys(current_page).observeForever { result ->
|
||||||
|
historysLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val getDetailsRecommandLiveData = MutableLiveData<BaseRes<DetailsRecommendRes>>()
|
||||||
|
val getDetailsRecommandData: MutableLiveData<BaseRes<DetailsRecommendRes>> get() = getDetailsRecommandLiveData
|
||||||
|
|
||||||
|
fun getDetailsRecommand() {
|
||||||
|
MainRequest.getDetailsRecommand().observeForever { result ->
|
||||||
|
getDetailsRecommandLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uploadHistorySeconds(uploadHistoryReq: UploadHistoryReq) {
|
||||||
|
MainRequest.uploadHistorySeconds(uploadHistoryReq).observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val hotsLiveData = MutableLiveData<BaseRes<ExampleKeywordDataRes>>()
|
||||||
|
val hotsData: MutableLiveData<BaseRes<ExampleKeywordDataRes>> get() = hotsLiveData
|
||||||
|
fun hots() {
|
||||||
|
MainRequest.hots().observeForever { result ->
|
||||||
|
hotsLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun click(short_play_id: Int) {
|
||||||
|
MainRequest.click(short_play_id).observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val keywordLiveData = MutableLiveData<BaseRes<ExampleKeywordDataRes>>()
|
||||||
|
val keywordData: MutableLiveData<BaseRes<ExampleKeywordDataRes>> get() = keywordLiveData
|
||||||
|
fun keyword(search: String) {
|
||||||
|
MainRequest.keyword(search).observeForever { result ->
|
||||||
|
keywordLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val allModulesLiveData = MutableLiveData<BaseRes<HomeModuleBean>>()
|
||||||
|
val allModulesData: MutableLiveData<BaseRes<HomeModuleBean>> get() = allModulesLiveData
|
||||||
|
fun allModules() {
|
||||||
|
MainRequest.allModules().observeForever { result ->
|
||||||
|
allModulesLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val buy_videoLiveData = MutableLiveData<BaseRes<BuyVideoRes>>()
|
||||||
|
val buy_videoData: MutableLiveData<BaseRes<BuyVideoRes>> get() = buy_videoLiveData
|
||||||
|
fun doBuyVideo(short_play_id: Int, video_id: Int) {
|
||||||
|
MainRequest.doBuyVideo(short_play_id, video_id).observeForever { result ->
|
||||||
|
buy_videoLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val categoriesLiveData = MutableLiveData<BaseRes<CategoriesDataRes>>()
|
||||||
|
val categoriesData: MutableLiveData<BaseRes<CategoriesDataRes>> get() = categoriesLiveData
|
||||||
|
fun getCategories() {
|
||||||
|
MainRequest.getCategories().observeForever { result ->
|
||||||
|
categoriesLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enterTheApp() {
|
||||||
|
MainRequest.enterTheApp().observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun leaveApp() {
|
||||||
|
MainRequest.leaveApp().observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onLine() {
|
||||||
|
MainRequest.onLine().observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun firebaseToken(
|
||||||
|
fcm_token: String
|
||||||
|
) {
|
||||||
|
MainRequest.firebaseToken(fcm_token).observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val w2aSelfAttributionLiveData =
|
||||||
|
MutableLiveData<BaseRes<Any>>()
|
||||||
|
|
||||||
|
fun w2aSelfAttribution(data: String) {
|
||||||
|
MainRequest.w2aSelfAttribution(data).observeForever { result ->
|
||||||
|
w2aSelfAttributionLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val openNotifyLiveData = MutableLiveData<BaseRes<Any>>()
|
||||||
|
val openNotifyData: MutableLiveData<BaseRes<Any>> get() = openNotifyLiveData
|
||||||
|
|
||||||
|
fun openNotify() {
|
||||||
|
MainRequest.openNotify().observeForever { result ->
|
||||||
|
openNotifyLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val notificationLiveData = MutableLiveData<BaseRes<Any>>()
|
||||||
|
fun uploadNoticeStatus(fbNotificationReq: FbNotificationReq) {
|
||||||
|
MainRequest.uploadNoticeStatus(fbNotificationReq)
|
||||||
|
.observeForever {
|
||||||
|
notificationLiveData.value = it.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendReport(message_id: String, title: String) {
|
||||||
|
MainRequest.sendReport(message_id, title).observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val noticeNumLiveData =
|
||||||
|
MutableLiveData<BaseRes<NoticeNumRes>>()
|
||||||
|
val noticeNumData: MutableLiveData<BaseRes<NoticeNumRes>> get() = noticeNumLiveData
|
||||||
|
fun noticeNum() {
|
||||||
|
MainRequest.noticeNum().observeForever { result ->
|
||||||
|
noticeNumLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val getPaySettingLiveData = MutableLiveData<BaseRes<PaySettingRes>>()
|
||||||
|
val getPaySettingData: MutableLiveData<BaseRes<PaySettingRes>> get() = getPaySettingLiveData
|
||||||
|
fun getPaySetting(
|
||||||
|
short_play_id: Int?,
|
||||||
|
video_id: Int?
|
||||||
|
) {
|
||||||
|
MainRequest.getPaySetting(short_play_id, video_id).observeForever { result ->
|
||||||
|
getPaySettingLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val restorePaidLiveData = MutableLiveData<BaseRes<PayRes>>()
|
||||||
|
val restorePaidData: MutableLiveData<BaseRes<PayRes>> get() = restorePaidLiveData
|
||||||
|
fun restorePaid(examplePayReq: PayReq?) {
|
||||||
|
MainRequest.doGooglePaid(examplePayReq).observeForever { result ->
|
||||||
|
restorePaidLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val createOrderLiveData = MutableLiveData<BaseRes<CreateOrderRes>>()
|
||||||
|
val createOrderData: MutableLiveData<BaseRes<CreateOrderRes>> get() = createOrderLiveData
|
||||||
|
fun createOrder(createOrderReq: CreateOrderReq) {
|
||||||
|
MainRequest.doCreateOrder(createOrderReq).observeForever { result ->
|
||||||
|
createOrderLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val googlePaidLiveData = MutableLiveData<BaseRes<PayRes>>()
|
||||||
|
val googlePaidData: MutableLiveData<BaseRes<PayRes>> get() = googlePaidLiveData
|
||||||
|
fun googlePaid(examplePayReq: PayReq?) {
|
||||||
|
MainRequest.doGooglePaid(examplePayReq).observeForever { result ->
|
||||||
|
googlePaidLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val customerOrderLiveData = MutableLiveData<BaseRes<CustomerOrderRes>>()
|
||||||
|
val customerOrderData: MutableLiveData<BaseRes<CustomerOrderRes>> get() = customerOrderLiveData
|
||||||
|
fun getCustomerOrder(current_page: Int, buy_type: String) {
|
||||||
|
MainRequest.getCustomerOrder(current_page, buy_type).observeForever { result ->
|
||||||
|
customerOrderLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val customerBuyRecordsLiveData =
|
||||||
|
MutableLiveData<BaseRes<CustomerBuyRecordsRes>>()
|
||||||
|
val customerBuyRecordsData: MutableLiveData<BaseRes<CustomerBuyRecordsRes>> get() = customerBuyRecordsLiveData
|
||||||
|
fun getCustomerBuyRecords(current_page: Int) {
|
||||||
|
MainRequest.getCustomerBuyRecords(current_page).observeForever { result ->
|
||||||
|
customerBuyRecordsLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val sendCoinListLiveData =
|
||||||
|
MutableLiveData<BaseRes<RewardCoinsRes>>()
|
||||||
|
val sendCoinListData: MutableLiveData<BaseRes<RewardCoinsRes>> get() = sendCoinListLiveData
|
||||||
|
fun sendCoinList(current_page: Int) {
|
||||||
|
MainRequest.sendCoinList(current_page).observeForever { result ->
|
||||||
|
sendCoinListLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun upError(body: Map<String, @JvmSuppressWildcards Any>) {
|
||||||
|
MainRequest.upError(body).observeForever {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val loginLiveData = MutableLiveData<BaseRes<LoginRes>>()
|
||||||
|
val loginData: MutableLiveData<BaseRes<LoginRes>> get() = loginLiveData
|
||||||
|
fun doLogin(exampleLoginReq: LoginReq) {
|
||||||
|
MainRequest.doLogin(exampleLoginReq).observeForever { result ->
|
||||||
|
loginLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val logoffLiveData = MutableLiveData<BaseRes<Any>>()
|
||||||
|
val logoffData: MutableLiveData<BaseRes<Any>> get() = logoffLiveData
|
||||||
|
fun doLogoff() {
|
||||||
|
MainRequest.doLogoff().observeForever { result ->
|
||||||
|
logoffLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val signoutLiveData = MutableLiveData<BaseRes<LoginRes>>()
|
||||||
|
val signoutData: MutableLiveData<BaseRes<LoginRes>> get() = signoutLiveData
|
||||||
|
fun doSignout() {
|
||||||
|
MainRequest.doSignout().observeForever { result ->
|
||||||
|
signoutLiveData.value = result.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val homeHotLiveData = MutableLiveData<BaseRes<VideoListDataRes>?>()
|
||||||
|
val homeHotData: MutableLiveData<BaseRes<VideoListDataRes>?> get() = homeHotLiveData
|
||||||
|
fun homeHot(buycount: Int, hottestnum: Int) {
|
||||||
|
MainRequest.homeHot(buycount, hottestnum)
|
||||||
|
.observeForever {
|
||||||
|
homeHotLiveData.value = it.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val userCenterRecommendLiveData = MutableLiveData<BaseRes<ShortListCategoryDataInfo>?>()
|
||||||
|
val userCenterRecommendData: MutableLiveData<BaseRes<ShortListCategoryDataInfo>?> get() = userCenterRecommendLiveData
|
||||||
|
fun userCenterRecommend(){
|
||||||
|
MainRequest.userCenterRecommend()
|
||||||
|
.observeForever {
|
||||||
|
userCenterRecommendLiveData.value = it.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
221
app/src/main/java/com/jia/er/nebuluxe/app/net/Retrofit.kt
Normal file
221
app/src/main/java/com/jia/er/nebuluxe/app/net/Retrofit.kt
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.net
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.Settings
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.liveData
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.basics.MyApplication.Companion.context
|
||||||
|
import com.jia.er.nebuluxe.app.data.BaseRes
|
||||||
|
import com.jia.er.nebuluxe.app.utils.Memory
|
||||||
|
import com.jia.er.nebuluxe.app.utils.PackageUtils
|
||||||
|
import com.jia.er.nebuluxe.app.utils.getAdvertisingIdInfo
|
||||||
|
import com.jia.er.nebuluxe.app.utils.getUserAgent
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import java.util.TimeZone
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.coroutines.resumeWithException
|
||||||
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
|
|
||||||
|
object Retrofit {
|
||||||
|
private val retrofit: Retrofit
|
||||||
|
fun <P> build(serviceClass: Class<P>): P = retrofit.create(serviceClass)
|
||||||
|
private val httpLoggingInterceptor = HttpLoggingInterceptor()
|
||||||
|
private const val DELAY_TIME_MILLIS = 2000L
|
||||||
|
private var lastPostTime: Long = 0L
|
||||||
|
private val lock = Any()
|
||||||
|
private val lock1 = Any()
|
||||||
|
|
||||||
|
init {
|
||||||
|
httpLoggingInterceptor.level =
|
||||||
|
if (Constants.isUat) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
|
||||||
|
val okHttpClient = OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.addInterceptor(httpLoggingInterceptor)
|
||||||
|
.addInterceptor(BodyInterceptor())
|
||||||
|
.addInterceptor { chain ->
|
||||||
|
val request =
|
||||||
|
chain.request().newBuilder().header("Content-Type", "application/json")
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_AuthorizationExample,
|
||||||
|
Memory.getMMKV()
|
||||||
|
.getString(Constants.CONSTANTS_AuthorizationExample, "")
|
||||||
|
.toString()
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_device_id,
|
||||||
|
Settings.Secure.getString(
|
||||||
|
context.contentResolver,
|
||||||
|
Settings.Secure.ANDROID_ID
|
||||||
|
)
|
||||||
|
).addHeader("User-Agent", getUserAgent())
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_device_gaid,
|
||||||
|
getAdvertisingIdInfo(context)
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_app_name,
|
||||||
|
context.getString(R.string.app_name)
|
||||||
|
).addHeader(
|
||||||
|
Constants.CONSTANTS_app_version,
|
||||||
|
PackageUtils.getPackageVersion(context)
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_system_type,
|
||||||
|
"android"
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_lang_key,
|
||||||
|
Memory.getMMKV()
|
||||||
|
.getString(Constants.CONSTANTS_lang_key, "en").toString()
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_time_zone,
|
||||||
|
getCurrentTimeZone()
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_model,
|
||||||
|
Build.MODEL
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_brand,
|
||||||
|
Build.BRAND
|
||||||
|
)
|
||||||
|
.addHeader(
|
||||||
|
Constants.CONSTANTS_system_version,
|
||||||
|
Build.VERSION.RELEASE
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
if (Constants.isUat) {
|
||||||
|
for (headerName in request.headers.names()) {
|
||||||
|
println(headerName + ": " + request.header(headerName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chain.proceed(request)
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
retrofit =
|
||||||
|
Retrofit.Builder()
|
||||||
|
.baseUrl(Constants.Constants_BASE_URL_RES)
|
||||||
|
.addConverterFactory(
|
||||||
|
GsonConverterFactory.create()
|
||||||
|
)
|
||||||
|
.client(okHttpClient)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T> Call<T>.response(): T {
|
||||||
|
return suspendCoroutine { continuation ->
|
||||||
|
enqueue(object : Callback<T> {
|
||||||
|
override fun onFailure(call: Call<T>, t: Throwable) {
|
||||||
|
continuation.resumeWithException(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call<T>, response: Response<T>) {
|
||||||
|
val body = response.body()
|
||||||
|
if (response.raw().code == 401) {
|
||||||
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
|
handle401Response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (response.raw().code == 402) {
|
||||||
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
|
handle402Response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (body != null) continuation.resume(body)
|
||||||
|
else continuation.resumeWithException(RuntimeException("response body is null"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private suspend fun handle402Response() = withContext(Dispatchers.Main) {
|
||||||
|
synchronized(lock) {
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
if (currentTime - lastPostTime >= DELAY_TIME_MILLIS) {
|
||||||
|
EventBus.getDefault()
|
||||||
|
.post(Constants.CONSTANTS_auth_refresh)
|
||||||
|
lastPostTime = currentTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun handle401Response() = withContext(Dispatchers.Main) {
|
||||||
|
synchronized(lock1) {
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
if (currentTime - lastPostTime >= DELAY_TIME_MILLIS) {
|
||||||
|
EventBus.getDefault()
|
||||||
|
.post(Constants.CONSTANTS_auth_refresh)
|
||||||
|
lastPostTime = currentTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun <T> handleData(apiCall: suspend () -> BaseRes<T>): LiveData<Result<BaseRes<T>>> {
|
||||||
|
return liveData(Dispatchers.IO) {
|
||||||
|
val result = try {
|
||||||
|
val response = apiCall.invoke()
|
||||||
|
if (response.code == 200) {
|
||||||
|
Result.success(response)
|
||||||
|
} else {
|
||||||
|
Memory.getMMKV().putString("errorMsg", response.msg)
|
||||||
|
Result.failure(RuntimeException("Result failure"))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Result.failure(e)
|
||||||
|
}
|
||||||
|
emit(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCurrentTimeZone(): String {
|
||||||
|
return createGmtOffsetString(true, true, TimeZone.getDefault().rawOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createGmtOffsetString(
|
||||||
|
includeGmt: Boolean, includeMinuteSeparator: Boolean, offsetMillis: Int
|
||||||
|
): String {
|
||||||
|
var offsetMinutes = offsetMillis / 60000
|
||||||
|
var sign = '+'
|
||||||
|
if (offsetMinutes < 0) {
|
||||||
|
sign = '-'
|
||||||
|
offsetMinutes = -offsetMinutes
|
||||||
|
}
|
||||||
|
val builder: StringBuilder = StringBuilder(9)
|
||||||
|
if (includeGmt) {
|
||||||
|
builder.append("GMT")
|
||||||
|
}
|
||||||
|
builder.append(sign)
|
||||||
|
appendNumber(builder, 2, offsetMinutes / 60)
|
||||||
|
if (includeMinuteSeparator) {
|
||||||
|
builder.append(':')
|
||||||
|
}
|
||||||
|
appendNumber(builder, 2, offsetMinutes % 60)
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun appendNumber(builder: StringBuilder, count: Int, value: Int) {
|
||||||
|
val string = value.toString()
|
||||||
|
for (i in 0 until count - string.length) {
|
||||||
|
builder.append('0')
|
||||||
|
}
|
||||||
|
builder.append(string);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.graphics.*
|
||||||
|
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
class CustomRoundedCorners(
|
||||||
|
private val topLeft: Float = 0f,
|
||||||
|
private val topRight: Float = 0f,
|
||||||
|
private val bottomRight: Float = 0f,
|
||||||
|
private val bottomLeft: Float = 0f
|
||||||
|
) : BitmapTransformation() {
|
||||||
|
|
||||||
|
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
|
||||||
|
messageDigest.update("$topLeft-$topRight-$bottomRight-$bottomLeft".toByteArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transform(
|
||||||
|
pool: BitmapPool,
|
||||||
|
toTransform: Bitmap,
|
||||||
|
outWidth: Int,
|
||||||
|
outHeight: Int
|
||||||
|
): Bitmap {
|
||||||
|
return roundCrop(pool, toTransform)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun roundCrop(pool: BitmapPool, source: Bitmap?): Bitmap {
|
||||||
|
if (source == null) return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
|
||||||
|
|
||||||
|
val result = pool.get(source.width, source.height, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(result)
|
||||||
|
|
||||||
|
val paint = Paint().apply {
|
||||||
|
isAntiAlias = true
|
||||||
|
shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
|
||||||
|
}
|
||||||
|
|
||||||
|
val path = Path()
|
||||||
|
val radii = floatArrayOf(
|
||||||
|
topLeft, topLeft,
|
||||||
|
topRight, topRight,
|
||||||
|
bottomRight, bottomRight,
|
||||||
|
bottomLeft, bottomLeft
|
||||||
|
)
|
||||||
|
path.addRoundRect(
|
||||||
|
RectF(0f, 0f, source.width.toFloat(), source.height.toFloat()),
|
||||||
|
radii,
|
||||||
|
Path.Direction.CW
|
||||||
|
)
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import androidx.media3.decoder.ffmpeg.FfmpegAudioRenderer
|
||||||
|
import androidx.media3.exoplayer.DefaultRenderersFactory
|
||||||
|
import androidx.media3.exoplayer.Renderer
|
||||||
|
import androidx.media3.exoplayer.audio.AudioRendererEventListener
|
||||||
|
import androidx.media3.exoplayer.audio.AudioSink
|
||||||
|
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
internal class FfmpegRenderersFactory(context: Context?) : DefaultRenderersFactory(
|
||||||
|
context!!
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
setExtensionRendererMode(EXTENSION_RENDERER_MODE_ON)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildAudioRenderers(
|
||||||
|
context: Context,
|
||||||
|
extensionRendererMode: Int,
|
||||||
|
mediaCodecSelector: MediaCodecSelector,
|
||||||
|
enableDecoderFallback: Boolean,
|
||||||
|
audioSink: AudioSink,
|
||||||
|
eventHandler: Handler,
|
||||||
|
eventListener: AudioRendererEventListener,
|
||||||
|
out: ArrayList<Renderer>
|
||||||
|
) {
|
||||||
|
out.add(FfmpegAudioRenderer())
|
||||||
|
super.buildAudioRenderers(
|
||||||
|
context,
|
||||||
|
extensionRendererMode,
|
||||||
|
mediaCodecSelector,
|
||||||
|
enableDecoderFallback,
|
||||||
|
audioSink,
|
||||||
|
eventHandler,
|
||||||
|
eventListener,
|
||||||
|
out
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
||||||
|
interface ListItemsVisibilityCalculator {
|
||||||
|
fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int)
|
||||||
|
fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int)
|
||||||
|
fun detachToSnapHelper()
|
||||||
|
}
|
59
app/src/main/java/com/jia/er/nebuluxe/app/ui/LoadingLine.kt
Normal file
59
app/src/main/java/com/jia/er/nebuluxe/app/ui/LoadingLine.kt
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.animation.AlphaAnimation
|
||||||
|
import android.view.animation.Animation
|
||||||
|
import android.view.animation.AnimationSet
|
||||||
|
import android.view.animation.ScaleAnimation
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
|
||||||
|
|
||||||
|
class LoadingLine : FrameLayout {
|
||||||
|
private var loadView: View? = null
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context) {
|
||||||
|
initView(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
|
||||||
|
initView(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet?,
|
||||||
|
defStyleAttr: Int
|
||||||
|
) : super(context, attrs, defStyleAttr) {
|
||||||
|
initView(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView(mContext: Context) {
|
||||||
|
val view: View = LayoutInflater.from(mContext).inflate(R.layout.line_layout, null)
|
||||||
|
loadView = view.findViewById<View>(R.id.loadingView)
|
||||||
|
this.addView(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startAnimation() {
|
||||||
|
val scale = ScaleAnimation(
|
||||||
|
0.3f, 1f, 1f, 1f,
|
||||||
|
Animation.RELATIVE_TO_SELF, 0.5f,
|
||||||
|
Animation.RELATIVE_TO_SELF, 0.5f
|
||||||
|
)
|
||||||
|
val alpha = AlphaAnimation(1f, 0.2f)
|
||||||
|
scale.repeatCount = -1
|
||||||
|
alpha.repeatCount = -1
|
||||||
|
val set = AnimationSet(true)
|
||||||
|
set.addAnimation(scale)
|
||||||
|
set.addAnimation(alpha)
|
||||||
|
set.duration = 500
|
||||||
|
loadView!!.startAnimation(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endAnimation(){
|
||||||
|
loadView!!.clearAnimation()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
interface OnSnapHelperCurrentListener {
|
||||||
|
|
||||||
|
fun setActive(currentView: View?, position: Int, previousView: View?, previousPosition: Int)
|
||||||
|
|
||||||
|
fun disActive(detachedView: View?, detachedPosition: Int)
|
||||||
|
}
|
@ -0,0 +1,244 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.*
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import com.bumptech.glide.request.target.CustomTarget
|
||||||
|
import com.bumptech.glide.request.transition.Transition
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 海报风格图片视图 - 简化版
|
||||||
|
* 使用顶部略倾斜的大圆角路径,贴合上传海报的形状
|
||||||
|
*/
|
||||||
|
class PosterStyleImageView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : View(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
// 画笔
|
||||||
|
private val imagePaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
|
||||||
|
// 路径
|
||||||
|
private val imagePath = Path()
|
||||||
|
|
||||||
|
// 图片相关
|
||||||
|
private var imageBitmap: Bitmap? = null
|
||||||
|
private var imageMatrix = Matrix()
|
||||||
|
private var imageShader: BitmapShader? = null
|
||||||
|
|
||||||
|
// 尺寸和位置
|
||||||
|
private var imageRect = RectF()
|
||||||
|
|
||||||
|
// 圆角(像素)——默认左上更短,其余正常
|
||||||
|
private var cornerRadiusTopLeft = dpToPx(12f)
|
||||||
|
private var cornerRadiusTopRight = dpToPx(18f)
|
||||||
|
private var cornerRadiusBottomRight = dpToPx(18f)
|
||||||
|
private var cornerRadiusBottomLeft = dpToPx(18f)
|
||||||
|
|
||||||
|
// 顶边倾斜偏移(像素):左上相对右上向下偏移,正值代表左侧更低
|
||||||
|
private var topSlantOffset = dpToPx(10f)
|
||||||
|
|
||||||
|
init {
|
||||||
|
setupPaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupPaint() {
|
||||||
|
imagePaint.style = Paint.Style.FILL
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh)
|
||||||
|
|
||||||
|
imageRect.set(
|
||||||
|
paddingLeft.toFloat(),
|
||||||
|
paddingTop.toFloat(),
|
||||||
|
(w - paddingRight).toFloat(),
|
||||||
|
(h - paddingBottom).toFloat()
|
||||||
|
)
|
||||||
|
|
||||||
|
createImagePath()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createImagePath() {
|
||||||
|
imagePath.reset()
|
||||||
|
|
||||||
|
// 四个角的半径,限定不要超过边长的一半
|
||||||
|
val rTL = cornerRadiusTopLeft.coerceAtMost(minOf(imageRect.width(), imageRect.height()) / 2f)
|
||||||
|
val rTR = cornerRadiusTopRight.coerceAtMost(minOf(imageRect.width(), imageRect.height()) / 2f)
|
||||||
|
val rBR = cornerRadiusBottomRight.coerceAtMost(minOf(imageRect.width(), imageRect.height()) / 2f)
|
||||||
|
val rBL = cornerRadiusBottomLeft.coerceAtMost(minOf(imageRect.width(), imageRect.height()) / 2f)
|
||||||
|
|
||||||
|
// 顶部两点,形成倾斜
|
||||||
|
val left = imageRect.left
|
||||||
|
val right = imageRect.right
|
||||||
|
val topLeftY = imageRect.top + topSlantOffset
|
||||||
|
val topRightY = imageRect.top
|
||||||
|
val bottom = imageRect.bottom
|
||||||
|
|
||||||
|
// 起点:左上边内切圆起始点(顺时针)
|
||||||
|
imagePath.moveTo(left + rTL, topLeftY)
|
||||||
|
|
||||||
|
// 顶边(倾斜)到右上角前
|
||||||
|
imagePath.lineTo(right - rTR, topRightY)
|
||||||
|
// 右上角圆弧(用二阶贝塞尔逼近)
|
||||||
|
imagePath.quadTo(right, topRightY, right, topRightY + rTR)
|
||||||
|
|
||||||
|
// 右边到右下角前
|
||||||
|
imagePath.lineTo(right, bottom - rBR)
|
||||||
|
// 右下角
|
||||||
|
imagePath.quadTo(right, bottom, right - rBR, bottom)
|
||||||
|
|
||||||
|
// 底边到左下角前
|
||||||
|
imagePath.lineTo(left + rBL, bottom)
|
||||||
|
// 左下角
|
||||||
|
imagePath.quadTo(left, bottom, left, bottom - rBL)
|
||||||
|
|
||||||
|
// 左边到左上角前(注意顶边是倾斜的,终点是 topLeftY)
|
||||||
|
imagePath.lineTo(left, topLeftY + rTL)
|
||||||
|
// 左上角(小圆角)
|
||||||
|
imagePath.quadTo(left, topLeftY, left + rTL, topLeftY)
|
||||||
|
|
||||||
|
imagePath.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
super.onDraw(canvas)
|
||||||
|
drawImage(canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawImage(canvas: Canvas) {
|
||||||
|
imageBitmap?.let { bitmap ->
|
||||||
|
if (imageShader == null) {
|
||||||
|
imageShader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bitmapWidth = bitmap.width.toFloat()
|
||||||
|
val bitmapHeight = bitmap.height.toFloat()
|
||||||
|
val scaleX = imageRect.width() / bitmapWidth
|
||||||
|
val scaleY = imageRect.height() / bitmapHeight
|
||||||
|
val scale = maxOf(scaleX, scaleY)
|
||||||
|
|
||||||
|
imageMatrix.reset()
|
||||||
|
imageMatrix.setScale(scale, scale)
|
||||||
|
imageMatrix.postTranslate(
|
||||||
|
imageRect.left + (imageRect.width() - bitmapWidth * scale) / 2,
|
||||||
|
imageRect.top + (imageRect.height() - bitmapHeight * scale) / 2
|
||||||
|
)
|
||||||
|
|
||||||
|
imageShader?.setLocalMatrix(imageMatrix)
|
||||||
|
imagePaint.shader = imageShader
|
||||||
|
canvas.drawPath(imagePath, imagePaint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setImage(bitmap: Bitmap) {
|
||||||
|
imageBitmap = bitmap
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setImageResource(resId: Int) {
|
||||||
|
ContextCompat.getDrawable(context, resId)?.let { drawable ->
|
||||||
|
setImage(drawable.toBitmap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 Glide 从网络加载图片
|
||||||
|
*/
|
||||||
|
fun loadImage(url: String, placeholderRes: Int? = null, errorRes: Int? = null) {
|
||||||
|
val requestOptions = RequestOptions()
|
||||||
|
placeholderRes?.let { requestOptions.placeholder(it) }
|
||||||
|
errorRes?.let { requestOptions.error(it) }
|
||||||
|
|
||||||
|
Glide.with(this)
|
||||||
|
.asBitmap()
|
||||||
|
.load(url)
|
||||||
|
.apply(requestOptions)
|
||||||
|
.into(object : CustomTarget<Bitmap>() {
|
||||||
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||||
|
setImage(resource)
|
||||||
|
}
|
||||||
|
override fun onLoadCleared(placeholder: Drawable?) {
|
||||||
|
placeholder?.toBitmap()?.let { setImage(it) }
|
||||||
|
}
|
||||||
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
|
super.onLoadFailed(errorDrawable)
|
||||||
|
errorDrawable?.toBitmap()?.let { setImage(it) }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一设置四角圆角(像素)
|
||||||
|
fun setCornerRadius(radiusPx: Float) {
|
||||||
|
cornerRadiusTopLeft = radiusPx
|
||||||
|
cornerRadiusTopRight = radiusPx
|
||||||
|
cornerRadiusBottomRight = radiusPx
|
||||||
|
cornerRadiusBottomLeft = radiusPx
|
||||||
|
createImagePath()
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分别设置四角圆角(像素)
|
||||||
|
fun setCornerRadii(
|
||||||
|
topLeftPx: Float,
|
||||||
|
topRightPx: Float,
|
||||||
|
bottomRightPx: Float,
|
||||||
|
bottomLeftPx: Float
|
||||||
|
) {
|
||||||
|
cornerRadiusTopLeft = topLeftPx
|
||||||
|
cornerRadiusTopRight = topRightPx
|
||||||
|
cornerRadiusBottomRight = bottomRightPx
|
||||||
|
cornerRadiusBottomLeft = bottomLeftPx
|
||||||
|
createImagePath()
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一设置四角圆角(dp)
|
||||||
|
fun setCornerRadiusDp(radiusDp: Float) {
|
||||||
|
setCornerRadius(dpToPx(radiusDp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分别设置四角圆角(dp)
|
||||||
|
fun setCornerRadiiDp(
|
||||||
|
topLeftDp: Float,
|
||||||
|
topRightDp: Float,
|
||||||
|
bottomRightDp: Float,
|
||||||
|
bottomLeftDp: Float
|
||||||
|
) {
|
||||||
|
setCornerRadii(
|
||||||
|
dpToPx(topLeftDp),
|
||||||
|
dpToPx(topRightDp),
|
||||||
|
dpToPx(bottomRightDp),
|
||||||
|
dpToPx(bottomLeftDp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 便捷方法:左上短、其他正常(传入dp)
|
||||||
|
fun setTopLeftShortStyle(topLeftDp: Float = 12f, otherDp: Float = 18f) {
|
||||||
|
setCornerRadiiDp(topLeftDp, otherDp, otherDp, otherDp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置顶边倾斜偏移
|
||||||
|
fun setTopSlantOffsetPx(offsetPx: Float) {
|
||||||
|
topSlantOffset = offsetPx
|
||||||
|
createImagePath()
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
fun setTopSlantOffsetDp(offsetDp: Float) {
|
||||||
|
setTopSlantOffsetPx(dpToPx(offsetDp))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCornerRadius(): Float = cornerRadiusTopLeft
|
||||||
|
|
||||||
|
private fun dpToPx(dp: Float): Float {
|
||||||
|
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView.OnChildAttachStateChangeListener
|
||||||
|
import androidx.recyclerview.widget.SnapHelper
|
||||||
|
|
||||||
|
class RecyclerViewScrollerDetection : ListItemsVisibilityCalculator {
|
||||||
|
|
||||||
|
private var mSnapHelper: SnapHelper? = null
|
||||||
|
private var mCurrentListener: OnSnapHelperCurrentListener? = null
|
||||||
|
var position = RecyclerView.NO_POSITION
|
||||||
|
private var previousPosition = RecyclerView.NO_POSITION
|
||||||
|
var isFirstAttached = false
|
||||||
|
private var recyclerView: RecyclerView? = null
|
||||||
|
val mSnapScrollListener = SnapScrollListener()
|
||||||
|
var mSnapChildAttachStateListener: SnapChildAttachStateChangeListener? = null
|
||||||
|
|
||||||
|
var isFirstActive = true
|
||||||
|
private var currentItemView: View? = null
|
||||||
|
private var previousView: View? = null
|
||||||
|
|
||||||
|
|
||||||
|
fun attachToSnapHelper(snapHelper: SnapHelper) {
|
||||||
|
mSnapHelper = snapHelper
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addOnScrollListener(recyclerView: RecyclerView) {
|
||||||
|
this.recyclerView = recyclerView
|
||||||
|
recyclerView.addOnScrollListener(mSnapScrollListener)
|
||||||
|
mSnapChildAttachStateListener = SnapChildAttachStateChangeListener(recyclerView)
|
||||||
|
mSnapChildAttachStateListener?.run {
|
||||||
|
recyclerView.addOnChildAttachStateChangeListener(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class SnapScrollListener : RecyclerView.OnScrollListener() {
|
||||||
|
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||||
|
super.onScrollStateChanged(recyclerView, newState)
|
||||||
|
this@RecyclerViewScrollerDetection.onScrollStateChanged(recyclerView, newState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class SnapChildAttachStateChangeListener(var recyclerView: RecyclerView) :
|
||||||
|
OnChildAttachStateChangeListener {
|
||||||
|
override fun onChildViewAttachedToWindow(view: View) {
|
||||||
|
if (!isFirstActive || isFirstAttached) return
|
||||||
|
position = recyclerView.getChildAdapterPosition(view)
|
||||||
|
currentItemView = view
|
||||||
|
mCurrentListener?.setActive(view, position, null, previousPosition)
|
||||||
|
previousPosition = position
|
||||||
|
previousView = view
|
||||||
|
isFirstAttached = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChildViewDetachedFromWindow(view: View) {
|
||||||
|
val previousPosition = recyclerView.getChildAdapterPosition(view)
|
||||||
|
currentItemView?.run {
|
||||||
|
val position = recyclerView.getChildAdapterPosition(
|
||||||
|
this
|
||||||
|
)
|
||||||
|
mCurrentListener?.let {
|
||||||
|
if (position == previousPosition) {
|
||||||
|
it.disActive(view, previousPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCurrentListener(mCurrentListener: OnSnapHelperCurrentListener?) {
|
||||||
|
this.mCurrentListener = mCurrentListener
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||||
|
try {
|
||||||
|
when (newState) {
|
||||||
|
RecyclerView.SCROLL_STATE_IDLE -> {
|
||||||
|
val layoutManager = recyclerView.layoutManager
|
||||||
|
currentItemView = mSnapHelper?.findSnapView(layoutManager)
|
||||||
|
if (null == currentItemView) return
|
||||||
|
val currentPosition = recyclerView.getChildAdapterPosition(currentItemView!!)
|
||||||
|
if (previousPosition == currentPosition || null == mCurrentListener) return
|
||||||
|
position = recyclerView.getChildAdapterPosition(currentItemView!!)
|
||||||
|
val mPreviousView = previousView
|
||||||
|
val mPreviousPosition = previousPosition
|
||||||
|
mCurrentListener?.setActive(
|
||||||
|
currentItemView,
|
||||||
|
position,
|
||||||
|
mPreviousView,
|
||||||
|
mPreviousPosition
|
||||||
|
)
|
||||||
|
previousPosition = currentPosition
|
||||||
|
previousView = currentItemView
|
||||||
|
}
|
||||||
|
|
||||||
|
RecyclerView.SCROLL_STATE_DRAGGING -> {
|
||||||
|
}
|
||||||
|
|
||||||
|
RecyclerView.SCROLL_STATE_SETTLING -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun detachToSnapHelper() {
|
||||||
|
recyclerView?.removeOnScrollListener(mSnapScrollListener)
|
||||||
|
mSnapChildAttachStateListener?.run {
|
||||||
|
recyclerView?.removeOnChildAttachStateChangeListener(
|
||||||
|
this
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
|
||||||
|
|
||||||
|
class RotateDownPageTransformer(
|
||||||
|
private val maxRotate: Float = DEFAULT_MAX_ROTATE,
|
||||||
|
private val sideMargin: Float = 0f, // Positive value creates visible gap
|
||||||
|
private val scaleFactor: Float = 0.95f
|
||||||
|
) : ViewPager2.PageTransformer {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DEFAULT_MAX_ROTATE = 15.0f
|
||||||
|
private const val DEFAULT_CENTER = 0.5f
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformPage(view: View, position: Float) {
|
||||||
|
val scale = if (abs(position) <= 1) {
|
||||||
|
(1 - abs(position)) * (1 - scaleFactor) + scaleFactor
|
||||||
|
} else {
|
||||||
|
scaleFactor
|
||||||
|
}
|
||||||
|
|
||||||
|
when {
|
||||||
|
position < -1 -> {
|
||||||
|
// [-Infinity,-1)
|
||||||
|
view.rotation = maxRotate * -1
|
||||||
|
view.pivotX = view.width.toFloat()
|
||||||
|
view.pivotY = view.height.toFloat()
|
||||||
|
view.scaleX = scaleFactor
|
||||||
|
view.scaleY = scaleFactor
|
||||||
|
view.translationX = -sideMargin * 2
|
||||||
|
}
|
||||||
|
position <= 1 -> { // [-1,1]
|
||||||
|
// Calculate direction (left or right)
|
||||||
|
val direction = if (position < 0) -1f else 1f
|
||||||
|
|
||||||
|
view.pivotX = if (position < 0) {
|
||||||
|
view.width * (DEFAULT_CENTER + DEFAULT_CENTER * -position)
|
||||||
|
} else {
|
||||||
|
view.width * DEFAULT_CENTER * (1 - position)
|
||||||
|
}
|
||||||
|
|
||||||
|
view.pivotY = view.height.toFloat()
|
||||||
|
view.rotation = maxRotate * position
|
||||||
|
view.scaleX = scale
|
||||||
|
view.scaleY = scale
|
||||||
|
view.translationX = (sideMargin * position) + (sideMargin * direction)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// (1,+Infinity]
|
||||||
|
view.rotation = maxRotate
|
||||||
|
view.pivotX = 0f
|
||||||
|
view.pivotY = view.height.toFloat()
|
||||||
|
view.scaleX = scaleFactor
|
||||||
|
view.scaleY = scaleFactor
|
||||||
|
view.translationX = sideMargin * 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun abs(value: Float): Float {
|
||||||
|
return if (value < 0) -value else value
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.animation.Animator
|
||||||
|
import android.animation.AnimatorListenerAdapter
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
|
||||||
|
|
||||||
|
class ScrollTextView @JvmOverloads constructor(
|
||||||
|
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||||
|
) : AppCompatTextView(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private var animator: ObjectAnimator? = null
|
||||||
|
private var currentIndex = 0
|
||||||
|
private var dataList: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
|
fun setData(data: MutableList<String>) {
|
||||||
|
dataList.clear()
|
||||||
|
dataList = data
|
||||||
|
currentIndex = 0
|
||||||
|
animator?.cancel()
|
||||||
|
animator?.removeAllListeners()
|
||||||
|
if (dataList.isNotEmpty()) {
|
||||||
|
animateText(dataList[currentIndex])
|
||||||
|
startSwitchAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startSwitchAnimation() {
|
||||||
|
animator = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f)
|
||||||
|
animator?.duration = 500
|
||||||
|
animator?.addListener(object : AnimatorListenerAdapter() {
|
||||||
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
|
super.onAnimationEnd(animation)
|
||||||
|
if (dataList.size != 0) {
|
||||||
|
currentIndex = (currentIndex + 1) % dataList.size
|
||||||
|
text = dataList[currentIndex]
|
||||||
|
animateText(dataList[currentIndex])
|
||||||
|
animate().alpha(1f).start()
|
||||||
|
startSwitchAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
animator?.startDelay = 4500
|
||||||
|
animator?.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun animateText(text: String) {
|
||||||
|
animate().cancel()
|
||||||
|
alpha = 0f
|
||||||
|
this.text = text
|
||||||
|
animate().alpha(1f).setDuration(500).start()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
animator?.cancel()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.ui
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.Window
|
||||||
|
import android.view.WindowManager
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
|
||||||
|
class UnFavoriteDialog(context: Context) : Dialog(context) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun init() {
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
setContentView(R.layout.dialog_un_collection)
|
||||||
|
|
||||||
|
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||||
|
window?.setLayout(
|
||||||
|
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||||
|
WindowManager.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
window?.setGravity(Gravity.CENTER)
|
||||||
|
setCancelable(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.ui.UnFavoriteDialog
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
|
||||||
|
|
||||||
|
object DialogUtils {
|
||||||
|
|
||||||
|
|
||||||
|
fun unFavoriteDialog(
|
||||||
|
context: Context,
|
||||||
|
short_play_id: Int,
|
||||||
|
video_id: Int,
|
||||||
|
genresViewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
val exampleUnFavoriteDialog = UnFavoriteDialog(context)
|
||||||
|
val tvThinkAgain =
|
||||||
|
exampleUnFavoriteDialog.findViewById<AppCompatTextView>(R.id.example_tv_think_again)
|
||||||
|
val iv_close_notification =
|
||||||
|
exampleUnFavoriteDialog.findViewById<AppCompatImageView>(R.id.iv_close_notification)
|
||||||
|
iv_close_notification.setOnClickListener { exampleUnFavoriteDialog.dismiss() }
|
||||||
|
tvThinkAgain.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
genresViewModel.doCancelCollect(short_play_id, video_id)
|
||||||
|
}
|
||||||
|
exampleUnFavoriteDialog.dismiss()
|
||||||
|
}
|
||||||
|
exampleUnFavoriteDialog.show()
|
||||||
|
}
|
||||||
|
}
|
104
app/src/main/java/com/jia/er/nebuluxe/app/utils/Memory.kt
Normal file
104
app/src/main/java/com/jia/er/nebuluxe/app/utils/Memory.kt
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.utils
|
||||||
|
|
||||||
|
import com.jia.er.nebuluxe.app.data.PayReq
|
||||||
|
import com.jia.er.nebuluxe.app.data.UserInfoRes
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants.CONSTANTS_SEARCH_STRINGExample
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
|
||||||
|
|
||||||
|
object Memory {
|
||||||
|
|
||||||
|
private var mmkv: MMKV? = null
|
||||||
|
|
||||||
|
|
||||||
|
fun getMMKV(): MMKV {
|
||||||
|
if (mmkv == null) {
|
||||||
|
mmkv = MMKV.mmkvWithID("nebuluxe")
|
||||||
|
}
|
||||||
|
return mmkv!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveUserInfo(infoRes: UserInfoRes?) {
|
||||||
|
val toJson = Gson().toJson(infoRes)
|
||||||
|
getMMKV()
|
||||||
|
.putString(Constants.CONSTANTS_User_STRING, toJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserInfo(): UserInfoRes? {
|
||||||
|
val string = getMMKV().getString(Constants.CONSTANTS_User_STRING, "{}")
|
||||||
|
if ("{}" == string) {
|
||||||
|
return UserInfoRes.createWithDefaults()
|
||||||
|
}
|
||||||
|
return Gson().fromJson(string, UserInfoRes::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveSearchString(search: String) {
|
||||||
|
val strings = getSearch()
|
||||||
|
if (!strings.contains(search)) {
|
||||||
|
strings.add(0, search)
|
||||||
|
}
|
||||||
|
val toJson = Gson().toJson(strings)
|
||||||
|
getMMKV().putString(CONSTANTS_SEARCH_STRINGExample, toJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSearch(): MutableList<String> {
|
||||||
|
val string = getMMKV().getString(CONSTANTS_SEARCH_STRINGExample, "[]")
|
||||||
|
return Gson().fromJson(string, Array<String>::class.java).toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isTourist(): Boolean {
|
||||||
|
return getUserInfo()?.is_tourist == true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCustomId(): String {
|
||||||
|
return getUserInfo()?.customer_id.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllCoin(): Int {
|
||||||
|
if (getUserInfo() == null) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return getUserInfo()?.coin_left_total!! + getUserInfo()?.send_coin_left_total!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isVip(): Boolean {
|
||||||
|
return getUserInfo()?.is_vip == true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveOrder(payReq: PayReq) {
|
||||||
|
val list = getOrder()
|
||||||
|
if (!list.contains(payReq)) {
|
||||||
|
list.add(payReq)
|
||||||
|
}
|
||||||
|
val toJson = Gson().toJson(list)
|
||||||
|
getMMKV().putString(Constants.CONSTANTS_examplePayReq, toJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeOrderString(order: String) {
|
||||||
|
val updatedList = getOrder().filterNot { it.order_code == order }
|
||||||
|
getMMKV().putString(
|
||||||
|
Constants.CONSTANTS_examplePayReq,
|
||||||
|
Gson().toJson(updatedList)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrder(): MutableList<PayReq> {
|
||||||
|
try {
|
||||||
|
val string = getMMKV().getString(Constants.CONSTANTS_examplePayReq, "[]")
|
||||||
|
if (null != string && "[]" != string) {
|
||||||
|
return Gson().fromJson(string, Array<PayReq>::class.java).toMutableList()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
getMMKV().putString(
|
||||||
|
Constants.CONSTANTS_examplePayReq,
|
||||||
|
"[]"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return mutableListOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import com.jia.er.nebuluxe.app.basics.MyApplication
|
||||||
|
|
||||||
|
object PackageUtils {
|
||||||
|
|
||||||
|
fun getPackageName(): String {
|
||||||
|
var packageName = ""
|
||||||
|
try {
|
||||||
|
packageName = MyApplication.context.packageName
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return packageName
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPackageVersion(context: Context): String {
|
||||||
|
var packageVersion = ""
|
||||||
|
try {
|
||||||
|
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||||
|
packageVersion = packageInfo.versionName.toString()
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return packageVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPackageVersionCode(context: Context): Int {
|
||||||
|
var versionCode = 0
|
||||||
|
try {
|
||||||
|
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||||
|
versionCode = packageInfo.versionCode
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return versionCode
|
||||||
|
}
|
||||||
|
}
|
183
app/src/main/java/com/jia/er/nebuluxe/app/utils/Toast.kt
Normal file
183
app/src/main/java/com/jia/er/nebuluxe/app/utils/Toast.kt
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.utils
|
||||||
|
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.LinearGradient
|
||||||
|
import android.graphics.Shader
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
|
import android.text.style.StyleSpan
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import com.google.android.gms.ads.identifier.AdvertisingIdClient
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants.ONE_DAY_IN_MILLIS
|
||||||
|
import com.jia.er.nebuluxe.app.basics.MyApplication
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import kotlin.math.tan
|
||||||
|
|
||||||
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
fun toast(text: String) {
|
||||||
|
handler.post {
|
||||||
|
Toast.makeText(MyApplication.context, text, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun formatNumber(num: Int): String {
|
||||||
|
return when {
|
||||||
|
num >= 1000000 -> "${(num / 1000000.0).format(1)}M"
|
||||||
|
num >= 1000 -> "${(num / 1000.0).format(1)}K"
|
||||||
|
else -> num.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatNumberByLong(num: Long): String {
|
||||||
|
return when {
|
||||||
|
num >= 1000000 -> "${(num / 1000000.0).format(1)}M"
|
||||||
|
num >= 1000 -> "${(num / 1000.0).format(1)}K"
|
||||||
|
else -> num.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
|
||||||
|
|
||||||
|
|
||||||
|
var lastClickTime = 0L
|
||||||
|
fun singleClick(during: Long = 500L, callBack: () -> Unit) {
|
||||||
|
val now = Date().time
|
||||||
|
if (now - lastClickTime > during) {
|
||||||
|
callBack()
|
||||||
|
}
|
||||||
|
lastClickTime = now
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SimpleDateFormat")
|
||||||
|
fun transToString(time: Long): String {
|
||||||
|
val date = Date(time * 1000)
|
||||||
|
return SimpleDateFormat("yyyy-MM-dd").format(date)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserAgent(): String {
|
||||||
|
return System.getProperty("http.agent") ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatTimestamp(timestampInSeconds: Long): String {
|
||||||
|
val minutes = timestampInSeconds / 60
|
||||||
|
val seconds = timestampInSeconds % 60
|
||||||
|
return String.format("%02d:%02d", minutes, seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun SpannableStringBuilder.appendWithStyle(
|
||||||
|
text: String,
|
||||||
|
color: Int = Color.BLACK,
|
||||||
|
isBold: Boolean = false
|
||||||
|
): SpannableStringBuilder {
|
||||||
|
val start = this.length
|
||||||
|
append(text)
|
||||||
|
val end = this.length
|
||||||
|
setSpan(ForegroundColorSpan(color), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
setSpan(
|
||||||
|
StyleSpan(if (isBold) Typeface.BOLD else Typeface.NORMAL),
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shouldShowNotification(): Boolean {
|
||||||
|
val lastPopupTime =
|
||||||
|
Memory.getMMKV().getLong(Constants.CONSTANTS_PREF_LAST_POPUP_TIME_Notification, 0)
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
|
||||||
|
return currentTime - lastPopupTime > ONE_DAY_IN_MILLIS
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAdvertisingIdInfo(context: Context): String {
|
||||||
|
try {
|
||||||
|
return AdvertisingIdClient.getAdvertisingIdInfo(context).id.toString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AppCompatTextView.applyTextSkew(angle: Float) {
|
||||||
|
val skewX = tan(Math.toRadians(angle.toDouble())).toFloat()
|
||||||
|
paint.textSkewX = skewX
|
||||||
|
post {
|
||||||
|
val extraWidth = (height * skewX).toInt()
|
||||||
|
layoutParams.width = measuredWidth + extraWidth + paddingEnd
|
||||||
|
requestLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dpToPx(dp: Int, context: Context): Int {
|
||||||
|
return (dp * context.resources.displayMetrics.density).toInt()
|
||||||
|
}
|
||||||
|
fun dpToPxByFloat(dp: Int, context: Context): Float {
|
||||||
|
return (dp * context.resources.displayMetrics.density)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun upError(
|
||||||
|
event_name: String,
|
||||||
|
viewModel: MainViewModel,
|
||||||
|
error_msg: String,
|
||||||
|
event_key: String,
|
||||||
|
type: String? = "",
|
||||||
|
pay_data: String? = "",
|
||||||
|
short_play_id: Int,
|
||||||
|
short_play_video_id: Int
|
||||||
|
) {
|
||||||
|
val map = HashMap<String, Any>()
|
||||||
|
map.put("error_msg", error_msg)
|
||||||
|
map.put("userId", Memory.getCustomId())
|
||||||
|
map.put("event_name", event_name)
|
||||||
|
map.put("event_key", event_key)
|
||||||
|
if (pay_data?.isNotEmpty() == true) {
|
||||||
|
map.put("pay_data", pay_data)
|
||||||
|
}
|
||||||
|
if (type?.isNotEmpty() == true) {
|
||||||
|
map.put("type", type)
|
||||||
|
}
|
||||||
|
map.put("short_play_id", short_play_id)
|
||||||
|
map.put("short_play_video_id", short_play_video_id)
|
||||||
|
viewModel.upError(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setLeftRightGradient(textView: TextView, colors: IntArray) {
|
||||||
|
textView.paint.shader = LinearGradient(
|
||||||
|
0f, 0f,
|
||||||
|
textView.textSize * textView.text.length, 0f,
|
||||||
|
colors,
|
||||||
|
null,
|
||||||
|
Shader.TileMode.CLAMP
|
||||||
|
)
|
||||||
|
textView.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUpDownGradient(textView: TextView, colors: IntArray) {
|
||||||
|
textView.paint.shader = LinearGradient(
|
||||||
|
0f, 0f,
|
||||||
|
0f, textView.textSize,
|
||||||
|
colors,
|
||||||
|
null,
|
||||||
|
Shader.TileMode.CLAMP
|
||||||
|
)
|
||||||
|
textView.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.video
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.PlaybackException
|
||||||
|
import androidx.media3.common.Player
|
||||||
|
import androidx.media3.exoplayer.DefaultRenderersFactory
|
||||||
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
|
import androidx.media3.exoplayer.LoadControl
|
||||||
|
import androidx.media3.ui.PlayerView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.DetailsRecommendRes
|
||||||
|
import com.youth.banner.adapter.BannerAdapter
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
class NewRecommendBannerAdapter(items: List<DetailsRecommendRes.Item?>?, context: Context) :
|
||||||
|
BannerAdapter<DetailsRecommendRes.Item?, NewRecommendBannerAdapter.BannerViewHolder?>(items) {
|
||||||
|
var currentPlayingPosition = -1
|
||||||
|
private var context: Context? = null
|
||||||
|
val playerMap = mutableMapOf<Int, ExoPlayer>()
|
||||||
|
val imageMap = mutableMapOf<Int, AppCompatImageView>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.context = context
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateHolder(parent: ViewGroup, viewType: Int): BannerViewHolder {
|
||||||
|
val view: View = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.new_detail_player_banner_view, parent, false)
|
||||||
|
view.layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
return BannerViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onBindView(
|
||||||
|
holder: BannerViewHolder?,
|
||||||
|
data: DetailsRecommendRes.Item?,
|
||||||
|
position: Int,
|
||||||
|
size: Int
|
||||||
|
) {
|
||||||
|
val playerView = holder?.view?.findViewById<PlayerView>(R.id.player_view)
|
||||||
|
val imageView = holder?.view?.findViewById<AppCompatImageView>(R.id.iv_cover)
|
||||||
|
if (null != imageView) {
|
||||||
|
Glide.with(context!!)
|
||||||
|
.load(data?.image_url)
|
||||||
|
.placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(imageView)
|
||||||
|
}
|
||||||
|
imageView?.visibility = View.VISIBLE
|
||||||
|
imageView?.let { imageMap[position] = it }
|
||||||
|
var exoPlayer = playerMap[position]
|
||||||
|
if (exoPlayer == null) {
|
||||||
|
val mediaItem = MediaItem.fromUri(Uri.parse(data?.video_url))
|
||||||
|
exoPlayer = ExoPlayer.Builder(context!!)
|
||||||
|
.setRenderersFactory(
|
||||||
|
DefaultRenderersFactory(context!!).setEnableDecoderFallback(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.setLoadControl(getLoadControl())
|
||||||
|
.build().apply {
|
||||||
|
setMediaItem(mediaItem)
|
||||||
|
prepare()
|
||||||
|
}
|
||||||
|
playerMap[position] = exoPlayer
|
||||||
|
}
|
||||||
|
playerView?.player = exoPlayer
|
||||||
|
exoPlayer.let { player ->
|
||||||
|
|
||||||
|
player.addListener(object : Player.Listener {
|
||||||
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||||
|
super.onPlaybackStateChanged(playbackState)
|
||||||
|
when (playbackState) {
|
||||||
|
Player.STATE_READY -> {
|
||||||
|
if (position == currentPlayingPosition) {
|
||||||
|
player.play()
|
||||||
|
imageView?.visibility = View.INVISIBLE
|
||||||
|
} else {
|
||||||
|
player.playWhenReady = false
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.STATE_ENDED -> {
|
||||||
|
player.seekTo(0)
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
|
super.onPlayerError(error)
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
imageView?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLoadControl(): LoadControl {
|
||||||
|
return androidx.media3.exoplayer.DefaultLoadControl.Builder()
|
||||||
|
.setBufferDurationsMs(
|
||||||
|
2500, 15000, 1500, 2000
|
||||||
|
)
|
||||||
|
.setTargetBufferBytes(50 * 1024 * 1024)
|
||||||
|
.setPrioritizeTimeOverSizeThresholds(false)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inner class BannerViewHolder(var view: View) : RecyclerView.ViewHolder(
|
||||||
|
view
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun resumeCurrentPlayer() {
|
||||||
|
playerMap[currentPlayingPosition]?.let { player ->
|
||||||
|
if (player.playbackState != Player.STATE_ENDED) {
|
||||||
|
player.play()
|
||||||
|
imageMap[currentPlayingPosition]?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pauseAllPlayers() {
|
||||||
|
playerMap.values.forEach { player ->
|
||||||
|
if (player.isPlaying) {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageMap[currentPlayingPosition]?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
fun releaseAllPlayers() {
|
||||||
|
playerMap.values.forEach { player ->
|
||||||
|
player.stop()
|
||||||
|
player.release()
|
||||||
|
}
|
||||||
|
playerMap.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,820 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.video
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.SeekBar
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.appcompat.widget.AppCompatSeekBar
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.PlaybackException
|
||||||
|
import androidx.media3.common.Player
|
||||||
|
import androidx.media3.datasource.DataSource
|
||||||
|
import androidx.media3.datasource.DefaultDataSourceFactory
|
||||||
|
import androidx.media3.exoplayer.DefaultRenderersFactory
|
||||||
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
|
import androidx.media3.exoplayer.hls.HlsMediaSource
|
||||||
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
|
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||||
|
import androidx.media3.ui.PlayerView
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.PagerSnapHelper
|
||||||
|
import com.blankj.utilcode.util.ViewUtils
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.BaseActivity
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.data.DetailsRecommendRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.MainDataHis
|
||||||
|
import com.jia.er.nebuluxe.app.data.PlayerDetailDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.data.UploadHistoryReq
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.ActivityPlayDetailBinding
|
||||||
|
import com.jia.er.nebuluxe.app.net.MainViewModel
|
||||||
|
import com.jia.er.nebuluxe.app.ui.FfmpegRenderersFactory
|
||||||
|
import com.jia.er.nebuluxe.app.ui.LoadingLine
|
||||||
|
import com.jia.er.nebuluxe.app.ui.OnSnapHelperCurrentListener
|
||||||
|
import com.jia.er.nebuluxe.app.ui.RecyclerViewScrollerDetection
|
||||||
|
import com.jia.er.nebuluxe.app.utils.DialogUtils
|
||||||
|
import com.jia.er.nebuluxe.app.utils.Memory
|
||||||
|
import com.jia.er.nebuluxe.app.utils.appendWithStyle
|
||||||
|
import com.jia.er.nebuluxe.app.utils.formatTimestamp
|
||||||
|
import com.jia.er.nebuluxe.app.utils.singleClick
|
||||||
|
import com.jia.er.nebuluxe.app.utils.toast
|
||||||
|
import com.youth.banner.listener.OnPageChangeListener
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
class PlayerDetailActivity : BaseActivity<ActivityPlayDetailBinding>(),
|
||||||
|
OnSnapHelperCurrentListener, SeriesDialogFragment.SeriesCallBack {
|
||||||
|
private var builder: ExoPlayer.Builder? = null
|
||||||
|
private var player: ExoPlayer? = null
|
||||||
|
private val pagerSnapHelper = PagerSnapHelper()
|
||||||
|
private val recyclerViewScrollerDetection = RecyclerViewScrollerDetection()
|
||||||
|
private var playerDetailAdapter: PlayerDetailAdapter? = null
|
||||||
|
private var playerView: PlayerView? = null
|
||||||
|
private var currentView: View? = null
|
||||||
|
private var loadingLine: LoadingLine? = null
|
||||||
|
private var tvName: AppCompatTextView? = null
|
||||||
|
private var tvTime: AppCompatTextView? = null
|
||||||
|
private var tvEpTotal: AppCompatTextView? = null
|
||||||
|
private var tvCollectionNum: AppCompatTextView? = null
|
||||||
|
private var play: AppCompatImageView? = null
|
||||||
|
private var collection: AppCompatImageView? = null
|
||||||
|
private var ivIconPlayer: AppCompatImageView? = null
|
||||||
|
private var ivCover: AppCompatImageView? = null
|
||||||
|
private var ivBackController: AppCompatImageView? = null
|
||||||
|
private var exampleSeekbarPlayerController: AppCompatSeekBar? = null
|
||||||
|
private var exampleProgressJob: Job? = null
|
||||||
|
private var isDragging = false
|
||||||
|
private var isPlaying = false
|
||||||
|
private var shortVideoId: Int = 0
|
||||||
|
private var dataRes: PlayerDetailDataRes.Episode? = null
|
||||||
|
private var currentPosition = 0
|
||||||
|
private val mViewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
|
||||||
|
private var activityId: Int = 0
|
||||||
|
private var progress: Long = 0L
|
||||||
|
private var seek = true
|
||||||
|
private var needRestart: Boolean = false
|
||||||
|
private var startTime: Long = 0
|
||||||
|
private var recommendBannerAdapter: NewRecommendBannerAdapter? = null
|
||||||
|
private var revolution = ""
|
||||||
|
private var needRefresh: Boolean = false
|
||||||
|
private var payPosition = 0
|
||||||
|
private var isCanPlay = false
|
||||||
|
// private var isLock = false
|
||||||
|
private var exampleSeriesDialogFragment: SeriesDialogFragment? = null
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
override fun top() {
|
||||||
|
EventBus.getDefault().register(this)
|
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
showLoading()
|
||||||
|
startTime = System.currentTimeMillis()
|
||||||
|
shortVideoId = intent.getIntExtra(Constants.CONSTANTS_short_play_id, 0)
|
||||||
|
activityId = intent.getIntExtra(Constants.CONSTANTS_activity_id, 0)
|
||||||
|
builder = ExoPlayer.Builder(this, FfmpegRenderersFactory(this))
|
||||||
|
.setRenderersFactory(
|
||||||
|
DefaultRenderersFactory(this).setEnableDecoderFallback(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
player = builder?.build()
|
||||||
|
playerView = ViewUtils.layoutId2View(R.layout.include_detail_player_view) as PlayerView
|
||||||
|
playerView?.player = player
|
||||||
|
loadingLine = playerView?.findViewById(R.id.load_line)
|
||||||
|
tvName = playerView?.findViewById(R.id.example_tv_title_player_controller)
|
||||||
|
tvTime = playerView?.findViewById(R.id.tv_player_seek_time)
|
||||||
|
tvEpTotal = playerView?.findViewById(R.id.tv_ep_total)
|
||||||
|
tvCollectionNum = playerView?.findViewById(R.id.example_tv_collection_num_controller)
|
||||||
|
collection = playerView?.findViewById(R.id.example_iv_collection_controller)
|
||||||
|
play = playerView?.findViewById(R.id.example_iv_play_player_controller)
|
||||||
|
ivIconPlayer = playerView?.findViewById(R.id.iv_icon_player)
|
||||||
|
ivBackController = playerView?.findViewById(R.id.iv_back_controller)
|
||||||
|
exampleSeekbarPlayerController =
|
||||||
|
playerView?.findViewById(R.id.example_seekBar_player_controller)
|
||||||
|
play?.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
if (isPlaying) {
|
||||||
|
pause()
|
||||||
|
} else {
|
||||||
|
play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ivBackController?.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
handleCustomLogic()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player?.addListener(object : Player.Listener {
|
||||||
|
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||||
|
super.onPlaybackStateChanged(playbackState)
|
||||||
|
when (playbackState) {
|
||||||
|
Player.STATE_BUFFERING -> {
|
||||||
|
loadingLine?.visibility = View.VISIBLE
|
||||||
|
loadingLine?.startAnimation()
|
||||||
|
ivIconPlayer?.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.STATE_READY -> {
|
||||||
|
// if (!isLock) {
|
||||||
|
if (isCanPlay) {
|
||||||
|
if (seek && progress > 0) {
|
||||||
|
player?.seekTo(progress)
|
||||||
|
seek = false
|
||||||
|
}
|
||||||
|
canPlay()
|
||||||
|
}
|
||||||
|
// } else {
|
||||||
|
// loadingLine?.endAnimation()
|
||||||
|
// loadingLine?.visibility = View.INVISIBLE
|
||||||
|
// ivCover = currentView?.findViewById(R.id.iv_icon)
|
||||||
|
// ivCover?.visibility = View.INVISIBLE
|
||||||
|
// ivIconPlayer?.visibility = View.INVISIBLE
|
||||||
|
// pause()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.STATE_ENDED -> {
|
||||||
|
needRestart = true
|
||||||
|
uploadSeconds()
|
||||||
|
val plus = currentPosition.plus(1)
|
||||||
|
recyclerViewScrollerDetection.isFirstAttached = false
|
||||||
|
binding.rvDetail.scrollToPosition(plus)
|
||||||
|
}
|
||||||
|
|
||||||
|
Player.STATE_IDLE -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
|
super.onPlayerError(error)
|
||||||
|
ivIconPlayer?.visibility = View.VISIBLE
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
collection?.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
doCollect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tvEpTotal?.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
exampleSeriesDialogFragment = SeriesDialogFragment()
|
||||||
|
val bundle = Bundle()
|
||||||
|
dataRes?.episode?.let { it1 ->
|
||||||
|
bundle.putInt(
|
||||||
|
Constants.Constants_Episodes_Series_Data_currentPositionExample,
|
||||||
|
it1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
bundle.putParcelable(
|
||||||
|
Constants.Constants_Episodes_Series_DataExample,
|
||||||
|
dataRes?.shortPlayInfo
|
||||||
|
)
|
||||||
|
bundle.putParcelableArrayList(
|
||||||
|
Constants.Constants_Episodes_Series_Data_ListExample,
|
||||||
|
playerDetailAdapter?.items?.let { it1 -> ArrayList(it1) }
|
||||||
|
)
|
||||||
|
exampleSeriesDialogFragment?.seriesCallBack = this
|
||||||
|
exampleSeriesDialogFragment?.arguments = bundle
|
||||||
|
exampleSeriesDialogFragment?.show(
|
||||||
|
supportFragmentManager,
|
||||||
|
"SeriesDialogFragment"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mViewModel.getVideoDetails(
|
||||||
|
shortVideoId,
|
||||||
|
0,
|
||||||
|
activityId,
|
||||||
|
revolution,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
if (handleCustomLogic()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// binding.tvLockEpisode.setOnClickListener {
|
||||||
|
// singleClick {
|
||||||
|
// if (currentPosition > 0) {
|
||||||
|
// val beforeItem =
|
||||||
|
// playerDetailAdapter?.getItem(currentPosition - 1) as PlayerDetailDataRes.Episode
|
||||||
|
// if (beforeItem.is_lock && !Memory.isVip()) {
|
||||||
|
// toast(getString(R.string.prequel_before))
|
||||||
|
// return@singleClick
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// val allCoin = Memory.getAllCoin()
|
||||||
|
// val coins = dataRes?.coins!!
|
||||||
|
// if (allCoin >= coins) {
|
||||||
|
// showLoading()
|
||||||
|
// dataRes?.short_play_id?.let { it1 ->
|
||||||
|
// dataRes?.short_play_video_id?.let { it2 ->
|
||||||
|
// mViewModel.doBuyVideo(
|
||||||
|
// it1,
|
||||||
|
// it2
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// rechargeDialog(dataRes)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
binding?.viewVideoRecommend?.ivCloseRecommend?.setOnClickListener { finish() }
|
||||||
|
binding?.viewVideoRecommend?.tvWatchNowRecommend?.setOnClickListener {
|
||||||
|
singleClick {
|
||||||
|
val data = recommendBannerAdapter?.getData(recommendBannerPosition)
|
||||||
|
watchNow(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doCollect() {
|
||||||
|
if (dataRes?.shortPlayInfo?.is_collect == true) {
|
||||||
|
dataRes?.short_play_id?.let { it1 ->
|
||||||
|
dataRes?.short_play_video_id?.let { it2 ->
|
||||||
|
DialogUtils.unFavoriteDialog(
|
||||||
|
this,
|
||||||
|
it1,
|
||||||
|
it2,
|
||||||
|
mViewModel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataRes?.short_play_id?.let {
|
||||||
|
dataRes?.short_play_video_id.let { it1 ->
|
||||||
|
if (it1 != null) {
|
||||||
|
mViewModel.doCollect(
|
||||||
|
it, it1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canPlay() {
|
||||||
|
loadingLine?.endAnimation()
|
||||||
|
loadingLine?.visibility = View.INVISIBLE
|
||||||
|
ivCover = currentView?.findViewById(R.id.iv_icon)
|
||||||
|
play()
|
||||||
|
setProgress()
|
||||||
|
ivCover?.visibility = View.INVISIBLE
|
||||||
|
ivIconPlayer?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
// private var storeDialogFragment: StoreDialogFragment? = null
|
||||||
|
// private fun rechargeDialog(dataRes: PlayerDetailDataRes.Episode?) {
|
||||||
|
// try {
|
||||||
|
// storeDialogFragment =
|
||||||
|
// StoreDialogFragment()
|
||||||
|
// val bundle = Bundle()
|
||||||
|
// bundle.putParcelable(Constants.CONSTANTS_Episode, dataRes)
|
||||||
|
// storeDialogFragment?.setStyle(DialogFragment.STYLE_NO_FRAME, 0)
|
||||||
|
// storeDialogFragment?.arguments = bundle
|
||||||
|
// storeDialogFragment?.show(
|
||||||
|
// supportFragmentManager,
|
||||||
|
// "StoreDialogFragment"
|
||||||
|
// )
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private fun watchNow(
|
||||||
|
data: DetailsRecommendRes.Item?
|
||||||
|
) {
|
||||||
|
binding?.viewVideoRecommend?.exampleBannerRecommend?.postDelayed({
|
||||||
|
if (data?.short_play_id != null) {
|
||||||
|
shortVideoId = data.short_play_id
|
||||||
|
recommendBannerAdapter?.releaseAllPlayers()
|
||||||
|
detailRefresh()
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
binding?.viewVideoRecommend?.root?.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleCustomLogic(): Boolean {
|
||||||
|
if (binding?.viewVideoRecommend?.root?.visibility == View.INVISIBLE) {
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
val duration = currentTime - startTime
|
||||||
|
if (duration > 3000) {
|
||||||
|
mViewModel.getDetailsRecommand()
|
||||||
|
binding.root.postDelayed({
|
||||||
|
pause()
|
||||||
|
player?.stop()
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private var recommendBannerPosition = 0
|
||||||
|
|
||||||
|
override fun center() {
|
||||||
|
mViewModel.getDetailsRecommandData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
if (it.data?.list?.isNotEmpty() == true) {
|
||||||
|
binding.viewVideoRecommend.root.visibility = View.VISIBLE
|
||||||
|
binding.viewVideoRecommend.bottom.setOnClickListener { }
|
||||||
|
recommendBannerAdapter =
|
||||||
|
NewRecommendBannerAdapter(it.data.list, this)
|
||||||
|
binding?.viewVideoRecommend?.exampleBannerRecommend?.setBannerGalleryEffect(
|
||||||
|
52,
|
||||||
|
12
|
||||||
|
)
|
||||||
|
binding?.viewVideoRecommend?.exampleBannerRecommend?.setAdapter(
|
||||||
|
recommendBannerAdapter
|
||||||
|
)
|
||||||
|
val i = it.data.list.size / 2
|
||||||
|
binding?.viewVideoRecommend?.exampleBannerRecommend?.setCurrentItem(
|
||||||
|
i,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
recommendBannerAdapter?.currentPlayingPosition = i
|
||||||
|
recommendBannerPosition = i
|
||||||
|
recommendBannerAdapter?.resumeCurrentPlayer()
|
||||||
|
binding?.viewVideoRecommend?.exampleBannerRecommend?.addOnPageChangeListener(
|
||||||
|
object :
|
||||||
|
OnPageChangeListener {
|
||||||
|
override fun onPageScrolled(
|
||||||
|
position: Int,
|
||||||
|
positionOffset: Float,
|
||||||
|
positionOffsetPixels: Int
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
override fun onPageSelected(position: Int) {
|
||||||
|
recommendBannerPosition = position
|
||||||
|
recommendBannerAdapter?.pauseAllPlayers()
|
||||||
|
recommendBannerAdapter?.currentPlayingPosition = position
|
||||||
|
recommendBannerAdapter?.playerMap?.get(position)?.let { newPlayer ->
|
||||||
|
recommendBannerAdapter?.resumeCurrentPlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mViewModel.infoData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
it.data?.let { it1 ->
|
||||||
|
Memory.saveUserInfo(it1)
|
||||||
|
if (needRefresh) {
|
||||||
|
detailRefresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mViewModel.buy_videoData.observe(this) {
|
||||||
|
// if (it != null) {
|
||||||
|
// when (it.data?.status) {
|
||||||
|
// "not_enough" -> {
|
||||||
|
// rechargeDialog(dataRes)
|
||||||
|
// hideLoading()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// "success" -> {
|
||||||
|
// needRefresh = false
|
||||||
|
// mViewModel.getInfo()
|
||||||
|
// toast(getString(R.string.success))
|
||||||
|
// val get = playerDetailAdapter?.items?.get(currentPosition)
|
||||||
|
// get?.is_lock = false
|
||||||
|
// collection?.isEnabled = true
|
||||||
|
// tvEpTotal?.isEnabled = true
|
||||||
|
// play?.isEnabled = true
|
||||||
|
// binding.tvLockEpisode.postDelayed({
|
||||||
|
// binding.tvLockEpisode.visibility = View.INVISIBLE
|
||||||
|
// binding.clLock.visibility = View.INVISIBLE
|
||||||
|
// canPlay()
|
||||||
|
// hideLoading()
|
||||||
|
// }, 1000)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// else -> {
|
||||||
|
// hideLoading()
|
||||||
|
// toast(it.data?.status.toString())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// hideLoading()
|
||||||
|
// toast(getString(R.string.network_error))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
mViewModel.videoDetailsData.observe(this) { it ->
|
||||||
|
if (it != null) {
|
||||||
|
playerDetailAdapter = PlayerDetailAdapter()
|
||||||
|
val layoutManager =
|
||||||
|
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding?.rvDetail?.layoutManager = layoutManager
|
||||||
|
binding?.rvDetail?.adapter = playerDetailAdapter
|
||||||
|
binding?.rvDetail?.isNestedScrollingEnabled = false
|
||||||
|
pagerSnapHelper.attachToRecyclerView(binding?.rvDetail)
|
||||||
|
recyclerViewScrollerDetection.setCurrentListener(this)
|
||||||
|
recyclerViewScrollerDetection.attachToSnapHelper(pagerSnapHelper)
|
||||||
|
binding?.rvDetail?.let { it1 ->
|
||||||
|
recyclerViewScrollerDetection.addOnScrollListener(
|
||||||
|
it1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
it.data?.episodeList?.forEach { it1 ->
|
||||||
|
it1.shortPlayInfo = it.data.shortPlayInfo
|
||||||
|
}
|
||||||
|
ivIconPlayer?.let { it1 ->
|
||||||
|
Glide.with(this).load(it.data?.shortPlayInfo?.image_url)
|
||||||
|
.into(it1)
|
||||||
|
}
|
||||||
|
playerDetailAdapter?.submitList(it.data?.episodeList)
|
||||||
|
if (needRefresh) {
|
||||||
|
recyclerViewScrollerDetection.isFirstAttached = false
|
||||||
|
binding.rvDetail.scrollToPosition(payPosition)
|
||||||
|
needRefresh = false
|
||||||
|
} else {
|
||||||
|
if (it.data?.video_info != null) {
|
||||||
|
if (it.data.video_info.episode > 1) {
|
||||||
|
it.data.video_info.episode.minus(1)
|
||||||
|
.let { it1 ->
|
||||||
|
recyclerViewScrollerDetection.isFirstAttached = false
|
||||||
|
binding.rvDetail.scrollToPosition(it1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideLoading()
|
||||||
|
} else {
|
||||||
|
showNoDrama()
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mViewModel.collectData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
collection?.setImageResource(R.drawable.iv_example_collection_h)
|
||||||
|
dataRes?.shortPlayInfo?.collect_total =
|
||||||
|
dataRes?.shortPlayInfo?.collect_total?.plus(1)!!
|
||||||
|
tvCollectionNum?.text = dataRes?.shortPlayInfo?.collect_total.toString()
|
||||||
|
dataRes?.shortPlayInfo?.is_collect = true
|
||||||
|
EventBus.getDefault().post(Constants.CONSTANTS_collect_refresh)
|
||||||
|
toast(getString(R.string.success))
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mViewModel.cancelCollectData.observe(this) {
|
||||||
|
if (it != null) {
|
||||||
|
collection?.setImageResource(R.drawable.iv_example_collection_n)
|
||||||
|
dataRes?.shortPlayInfo?.collect_total =
|
||||||
|
dataRes?.shortPlayInfo?.collect_total?.minus(1)!!
|
||||||
|
tvCollectionNum?.text = dataRes?.shortPlayInfo?.collect_total.toString()
|
||||||
|
dataRes?.shortPlayInfo?.is_collect = false
|
||||||
|
toast(getString(R.string.success))
|
||||||
|
EventBus.getDefault().post(Constants.CONSTANTS_collect_refresh)
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.network_error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
private fun buildMediaSource(videoPath: String): MediaSource {
|
||||||
|
val dataSourceFactory: DataSource.Factory =
|
||||||
|
DefaultDataSourceFactory(this, "reelcrush")
|
||||||
|
|
||||||
|
return if (videoPath.endsWith(".m3u8")) {
|
||||||
|
HlsMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(MediaItem.fromUri(Uri.parse(videoPath)))
|
||||||
|
} else {
|
||||||
|
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
|
.createMediaSource(MediaItem.fromUri(Uri.parse(videoPath)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
isCanPlay = false
|
||||||
|
binding.root.postDelayed({ player?.pause() }, 300)
|
||||||
|
recommendBannerAdapter?.pauseAllPlayers()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
// if (!isLock && player?.isPlaying == false) {
|
||||||
|
isCanPlay = true
|
||||||
|
binding.root.postDelayed({ canPlay() }, 300)
|
||||||
|
// }
|
||||||
|
recommendBannerAdapter?.resumeCurrentPlayer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setProgress() {
|
||||||
|
exampleProgressJob?.cancel()
|
||||||
|
val duration = player!!.duration
|
||||||
|
exampleSeekbarPlayerController?.max = duration.toInt()
|
||||||
|
exampleSeekbarPlayerController?.progress = player!!.currentPosition.toInt()
|
||||||
|
exampleSeekbarPlayerController?.setOnSeekBarChangeListener(null)
|
||||||
|
exampleProgressJob = lifecycleScope.launch {
|
||||||
|
while (isActive) {
|
||||||
|
if (!isDragging) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
exampleSeekbarPlayerController?.progress = player!!.currentPosition.toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exampleSeekbarPlayerController?.setOnSeekBarChangeListener(object :
|
||||||
|
SeekBar.OnSeekBarChangeListener {
|
||||||
|
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||||
|
if (fromUser) {
|
||||||
|
seekTo(progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||||
|
tvTime?.visibility = FrameLayout.VISIBLE
|
||||||
|
isDragging = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||||
|
isDragging = false
|
||||||
|
tvTime?.visibility = FrameLayout.INVISIBLE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun play() {
|
||||||
|
player?.play()
|
||||||
|
play?.setImageResource(R.drawable.iv_example_stop)
|
||||||
|
isPlaying = true
|
||||||
|
isDragging = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pause() {
|
||||||
|
player?.pause()
|
||||||
|
play?.setImageResource(R.drawable.iv_example_play)
|
||||||
|
isPlaying = false
|
||||||
|
isDragging = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seekTo(progress: Int) {
|
||||||
|
player?.seekTo(progress.toLong())
|
||||||
|
seekTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun seekTime() {
|
||||||
|
val currentPosition = player!!.currentPosition
|
||||||
|
val currentTime = formatTimestamp(currentPosition / 1000)
|
||||||
|
val totalDuration = player!!.duration
|
||||||
|
val totalTime = formatTimestamp(totalDuration / 1000)
|
||||||
|
tvTime?.text = "$currentTime/$totalTime"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getViewBinding(): ActivityPlayDetailBinding {
|
||||||
|
return ActivityPlayDetailBinding.inflate(layoutInflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
isCanPlay = false
|
||||||
|
player?.stop()
|
||||||
|
player?.release()
|
||||||
|
// storeDialogFragment?.storeCallBack = null
|
||||||
|
exampleSeriesDialogFragment?.seriesCallBack = null
|
||||||
|
recommendBannerAdapter?.releaseAllPlayers()
|
||||||
|
super.onDestroy()
|
||||||
|
recyclerViewScrollerDetection.detachToSnapHelper()
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
EventBus.getDefault().unregister(this)
|
||||||
|
System.gc()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
|
override fun setActive(
|
||||||
|
currentView: View?,
|
||||||
|
position: Int,
|
||||||
|
previousView: View?,
|
||||||
|
previousPosition: Int
|
||||||
|
) {
|
||||||
|
seek = true
|
||||||
|
isCanPlay = true
|
||||||
|
this.currentView = currentView
|
||||||
|
currentPosition = position
|
||||||
|
val frameLayout = currentView?.findViewById<FrameLayout>(R.id.video)
|
||||||
|
(playerView?.parent as FrameLayout?)?.removeView(playerView)
|
||||||
|
frameLayout?.removeAllViews()
|
||||||
|
frameLayout?.addView(playerView)
|
||||||
|
playerView?.showController()
|
||||||
|
dataRes = playerDetailAdapter?.getItem(position)
|
||||||
|
progress = if (dataRes?.play_seconds?.isNotEmpty() == true) {
|
||||||
|
dataRes?.play_seconds!!.toLong()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
// isLock = (dataRes?.is_lock == true && !Memory.isVip())
|
||||||
|
// collection?.isEnabled = !isLock
|
||||||
|
// tvEpTotal?.isEnabled = !isLock
|
||||||
|
// play?.isEnabled = !isLock
|
||||||
|
// binding.tvLockEpisode.visibility = if (isLock) View.VISIBLE else View.INVISIBLE
|
||||||
|
// binding.clLock.visibility = if (isLock) View.VISIBLE else View.INVISIBLE
|
||||||
|
// if (currentPosition > 0) {
|
||||||
|
// playerDetailAdapter?.items?.get(currentPosition - 1)
|
||||||
|
// ?.let { it2 ->
|
||||||
|
// if (!it2.is_lock) {
|
||||||
|
// binding.tvLockEpisode.text =
|
||||||
|
// "Unlocking costs ".plus(dataRes?.coins).plus(" coins")
|
||||||
|
// } else {
|
||||||
|
// binding.tvLockEpisode.text = "Prev. locked"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// binding.tvLockEpisode.text = "Unlocking costs ".plus(dataRes?.coins).plus(" coins")
|
||||||
|
// }
|
||||||
|
dataRes?.video_url?.let { buildMediaSource(it) }?.let { player?.setMediaSource(it) }
|
||||||
|
player?.prepare()
|
||||||
|
tvName?.text = dataRes?.shortPlayInfo?.name
|
||||||
|
tvCollectionNum?.text = dataRes?.shortPlayInfo?.collect_total.toString()
|
||||||
|
val builder = SpannableStringBuilder()
|
||||||
|
builder.appendWithStyle(
|
||||||
|
"Ep.".plus(dataRes?.episode),
|
||||||
|
Color.parseColor("#FFDAA4"),
|
||||||
|
isBold = true
|
||||||
|
)
|
||||||
|
.appendWithStyle(
|
||||||
|
"/Ep.".plus(dataRes?.shortPlayInfo?.episode_total),
|
||||||
|
Color.parseColor("#FFFFFF"),
|
||||||
|
isBold = false
|
||||||
|
)
|
||||||
|
tvEpTotal?.text = builder
|
||||||
|
if (dataRes?.is_lock == false || Memory.isVip()) {
|
||||||
|
dataRes?.short_play_video_id?.let {
|
||||||
|
mViewModel.doCreateHistory(
|
||||||
|
shortVideoId,
|
||||||
|
it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collection?.setImageResource(if (dataRes?.shortPlayInfo?.is_collect == true) R.drawable.iv_example_collection_h else R.drawable.iv_example_collection_n)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun disActive(detachedView: View?, detachedPosition: Int) {
|
||||||
|
if (null == detachedView) return
|
||||||
|
ivCover = detachedView.findViewById(R.id.iv_icon)
|
||||||
|
ivCover?.visibility = View.VISIBLE
|
||||||
|
if (player?.isPlaying == true) {
|
||||||
|
pause()
|
||||||
|
}
|
||||||
|
exampleSeekbarPlayerController?.progress = 0
|
||||||
|
uploadSeconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun uploadSeconds() {
|
||||||
|
if (dataRes?.is_lock == false) {
|
||||||
|
playerDetailAdapter?.getItem(currentPosition)?.play_seconds =
|
||||||
|
if (needRestart) "0" else lastProgress()
|
||||||
|
.toString()
|
||||||
|
mViewModel.uploadHistorySeconds(
|
||||||
|
UploadHistoryReq(
|
||||||
|
if (needRestart) 0 else lastProgress(),
|
||||||
|
shortVideoId,
|
||||||
|
dataRes?.short_play_video_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
needRestart = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chooseSeries(episode: PlayerDetailDataRes.Episode) {
|
||||||
|
// isLock = episode.is_lock
|
||||||
|
uploadSeconds()
|
||||||
|
val index = playerDetailAdapter?.items?.withIndex()?.firstOrNull {
|
||||||
|
(episode.episode == it.value.episode) && (episode.shortPlayInfo?.name == it.value.shortPlayInfo?.name
|
||||||
|
)
|
||||||
|
}?.index
|
||||||
|
recyclerViewScrollerDetection.isFirstAttached = false
|
||||||
|
index?.let { binding.rvDetail.scrollToPosition(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun collection() {
|
||||||
|
doCollect()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
if (dataRes?.is_lock == false || Memory.isVip()) {
|
||||||
|
dataRes?.short_play_id?.let {
|
||||||
|
UploadHistoryReq(
|
||||||
|
lastProgress(),
|
||||||
|
it,
|
||||||
|
dataRes?.short_play_video_id
|
||||||
|
)
|
||||||
|
}?.let {
|
||||||
|
mViewModel.uploadHistorySeconds(
|
||||||
|
it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dataRes?.shortPlayInfo?.image_url?.isNotEmpty() == true) {
|
||||||
|
val toJson = Gson().toJson(
|
||||||
|
dataRes?.short_play_id?.let {
|
||||||
|
MainDataHis(
|
||||||
|
dataRes?.shortPlayInfo?.episode_total.toString(),
|
||||||
|
it,
|
||||||
|
dataRes?.episode.toString(),
|
||||||
|
dataRes?.shortPlayInfo?.image_url.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Memory.getMMKV()
|
||||||
|
.putString(Constants.Constants_Main_Video_info, toJson)
|
||||||
|
Memory.getMMKV()
|
||||||
|
.putBoolean(Constants.Constants_Main_Video_status, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lastProgress(): Long {
|
||||||
|
return player?.currentPosition ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun detailRefresh() {
|
||||||
|
recyclerViewScrollerDetection.isFirstAttached = false
|
||||||
|
player?.pause()
|
||||||
|
player?.stop()
|
||||||
|
mViewModel.getVideoDetails(
|
||||||
|
shortVideoId,
|
||||||
|
0,
|
||||||
|
activityId,
|
||||||
|
revolution,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onEvent(event: String) {
|
||||||
|
if (Constants.CONSTANTS_pay_refresh == event) {
|
||||||
|
payPosition = dataRes?.episode?.minus(1)!!
|
||||||
|
needRefresh = true
|
||||||
|
mViewModel.getInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onReturn() {
|
||||||
|
super.onReturn()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.video
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.PlayerDetailDataRes
|
||||||
|
|
||||||
|
class PlayerDetailAdapter :
|
||||||
|
BaseQuickAdapter<PlayerDetailDataRes.Episode, QuickViewHolder>() {
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: PlayerDetailDataRes.Episode?
|
||||||
|
) {
|
||||||
|
Glide.with(context).load(item?.shortPlayInfo?.image_url).placeholder(R.drawable.iv_placeholder_v)
|
||||||
|
.into(holder.getView(R.id.iv_icon))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_home_for_you, parent)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.video
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.data.PlayerDetailDataRes
|
||||||
|
|
||||||
|
class SeriesDataAdapter :
|
||||||
|
BaseQuickAdapter<PlayerDetailDataRes.Episode, QuickViewHolder>() {
|
||||||
|
var currentPosition = -1
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: QuickViewHolder,
|
||||||
|
position: Int,
|
||||||
|
item: PlayerDetailDataRes.Episode?
|
||||||
|
) {
|
||||||
|
val view = holder.getView<AppCompatTextView>(R.id.example_tv_num_data)
|
||||||
|
view.text = item?.episode.toString()
|
||||||
|
if (currentPosition == view.text.toString().toInt()) {
|
||||||
|
holder.setBackgroundResource(R.id.example_tv_num_data, R.drawable.bg_example_num_h)
|
||||||
|
holder.setTextColor(
|
||||||
|
R.id.example_tv_num_data,
|
||||||
|
context.getColor(R.color.black)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
holder.setBackgroundResource(R.id.example_tv_num_data, R.drawable.bg_example_num_n)
|
||||||
|
holder.setTextColor(
|
||||||
|
R.id.example_tv_num_data,
|
||||||
|
context.getColor(R.color.white)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// if (item?.is_lock == true && !Memory.isVip()) {
|
||||||
|
// holder.setVisible(R.id.iv_example_lock, true)
|
||||||
|
// } else {
|
||||||
|
// holder.setVisible(R.id.iv_example_lock, false)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): QuickViewHolder {
|
||||||
|
return QuickViewHolder(R.layout.item_num_data, parent)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.jia.er.nebuluxe.app.video
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import com.jia.er.nebuluxe.app.R
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants.Constants_Episodes_Series_DataExample
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants.Constants_Episodes_Series_Data_ListExample
|
||||||
|
import com.jia.er.nebuluxe.app.basics.Constants.Constants_Episodes_Series_Data_currentPositionExample
|
||||||
|
import com.jia.er.nebuluxe.app.data.PlayerDetailDataRes
|
||||||
|
import com.jia.er.nebuluxe.app.databinding.DialogSeriesBinding
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
class SeriesDialogFragment : DialogFragment() {
|
||||||
|
var seriesCallBack: SeriesCallBack? = null
|
||||||
|
var is_collect = false
|
||||||
|
var exampleDialogSeriesBinding: DialogSeriesBinding? = null
|
||||||
|
|
||||||
|
interface SeriesCallBack {
|
||||||
|
fun chooseSeries(episode: PlayerDetailDataRes.Episode)
|
||||||
|
fun collection()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
EventBus.getDefault().register(this)
|
||||||
|
val builder = AlertDialog.Builder(requireActivity())
|
||||||
|
val inflater = requireActivity().layoutInflater
|
||||||
|
val view = inflater.inflate(R.layout.dialog_series, null)
|
||||||
|
exampleDialogSeriesBinding = DialogSeriesBinding.bind(view)
|
||||||
|
val episodeList: List<PlayerDetailDataRes.Episode>? =
|
||||||
|
arguments?.getParcelableArrayList(Constants_Episodes_Series_Data_ListExample)
|
||||||
|
val data: PlayerDetailDataRes.ShortPlayInfo? =
|
||||||
|
arguments?.getParcelable(Constants_Episodes_Series_DataExample)
|
||||||
|
val currentPosition =
|
||||||
|
arguments?.getInt(Constants_Episodes_Series_Data_currentPositionExample, 0)
|
||||||
|
val exampleSeriesDataAdapter = SeriesDataAdapter()
|
||||||
|
val spanCount = 6
|
||||||
|
val layoutManager = GridLayoutManager(context, spanCount)
|
||||||
|
exampleDialogSeriesBinding?.rvDataDialogSeries?.layoutManager = layoutManager
|
||||||
|
exampleDialogSeriesBinding?.rvDataDialogSeries?.adapter = exampleSeriesDataAdapter
|
||||||
|
exampleSeriesDataAdapter.submitList(episodeList)
|
||||||
|
if (currentPosition != null) {
|
||||||
|
exampleSeriesDataAdapter.currentPosition = currentPosition
|
||||||
|
}
|
||||||
|
exampleDialogSeriesBinding?.tvDesDialogSeries?.text = data?.description
|
||||||
|
if (data?.category?.isNotEmpty() == true) {
|
||||||
|
exampleDialogSeriesBinding?.tvTag?.visibility = View.VISIBLE
|
||||||
|
exampleDialogSeriesBinding?.tvTag?.text = data?.category?.get(0)
|
||||||
|
} else {
|
||||||
|
exampleDialogSeriesBinding?.tvTag?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
is_collect = data?.is_collect == true
|
||||||
|
exampleDialogSeriesBinding?.ivCollect?.setImageResource(if (data?.is_collect == true) R.drawable.iv_example_collection_h else R.drawable.iv_example_collection_n)
|
||||||
|
exampleDialogSeriesBinding?.ivCollect?.setOnClickListener {
|
||||||
|
seriesCallBack?.collection()
|
||||||
|
}
|
||||||
|
exampleSeriesDataAdapter.setOnItemClickListener { adapter, view, position ->
|
||||||
|
val item = adapter.getItem(position) as PlayerDetailDataRes.Episode
|
||||||
|
// if (position > 0) {
|
||||||
|
// val beforeItem = adapter.getItem(position - 1) as PlayerDetailDataRes.Episode
|
||||||
|
// if (beforeItem.is_lock && !Memory.isVip()) {
|
||||||
|
// toast(getString(R.string.prequel_before))
|
||||||
|
// dismiss()
|
||||||
|
// return@setOnItemClickListener
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
seriesCallBack?.chooseSeries(item)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
isCancelable = true
|
||||||
|
exampleDialogSeriesBinding?.tvContentDialogSeries?.text = data?.name
|
||||||
|
builder.setView(exampleDialogSeriesBinding?.root)
|
||||||
|
val dialog = builder.create()
|
||||||
|
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
|
||||||
|
val window = dialog.window
|
||||||
|
window?.decorView?.setPadding(0, 0, 0, 0)
|
||||||
|
window?.setGravity(Gravity.BOTTOM)
|
||||||
|
val layoutParams = window?.attributes
|
||||||
|
layoutParams?.width = WindowManager.LayoutParams.MATCH_PARENT
|
||||||
|
layoutParams?.height = WindowManager.LayoutParams.WRAP_CONTENT
|
||||||
|
window?.attributes = layoutParams
|
||||||
|
return dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
EventBus.getDefault().unregister(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onEvent(event: String) {
|
||||||
|
if (Constants.CONSTANTS_collect_refresh == event) {
|
||||||
|
is_collect = !is_collect
|
||||||
|
exampleDialogSeriesBinding?.ivCollect?.setImageResource(if (is_collect == true) R.drawable.iv_example_collection_h else R.drawable.iv_example_collection_n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
app/src/main/res/drawable-xxhdpi/bg_rank_1.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/bg_rank_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
app/src/main/res/drawable-xxhdpi/bg_rank_2.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/bg_rank_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
BIN
app/src/main/res/drawable-xxhdpi/bg_rank_3.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/bg_rank_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user