first commit
This commit is contained in:
commit
fc428a8e09
16
Android_Mireo/.gitignore
vendored
Normal file
16
Android_Mireo/.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
/app/release
|
BIN
Android_Mireo/app/AppMireo.jks
Normal file
BIN
Android_Mireo/app/AppMireo.jks
Normal file
Binary file not shown.
155
Android_Mireo/app/build.gradle
Normal file
155
Android_Mireo/app/build.gradle
Normal file
@ -0,0 +1,155 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'android-aspectjx'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply from: '../common.gradle'
|
||||
|
||||
|
||||
android {
|
||||
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'com.localee.mireo.app'
|
||||
resConfigs 'zh'
|
||||
resConfigs 'xxhdpi'
|
||||
proguardFiles 'proguard-sdk.pro', 'proguard-app.pro'
|
||||
buildConfigField('boolean', 'LOG_ENABLE', '' + LOG_ENABLE + '')
|
||||
buildConfigField('String', 'HOST_URL', '"' + HOST_URL + '"')
|
||||
}
|
||||
|
||||
|
||||
signingConfigs {
|
||||
config {
|
||||
storeFile file(StoreFile)
|
||||
storePassword StorePassword
|
||||
keyAlias KeyAlias
|
||||
keyPassword KeyPassword
|
||||
}
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
dataBinding = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
||||
debug {
|
||||
|
||||
applicationIdSuffix '.debug'
|
||||
debuggable true
|
||||
jniDebuggable true
|
||||
zipAlignEnabled false
|
||||
shrinkResources false
|
||||
minifyEnabled false
|
||||
signingConfig signingConfigs.config
|
||||
addManifestPlaceholders([
|
||||
'app_name': 'Mireo Debug'
|
||||
])
|
||||
}
|
||||
|
||||
preview.initWith(debug)
|
||||
preview {
|
||||
debuggable false
|
||||
jniDebuggable false
|
||||
zipAlignEnabled true
|
||||
shrinkResources false
|
||||
minifyEnabled false
|
||||
signingConfig signingConfigs.config
|
||||
addManifestPlaceholders([
|
||||
'app_name': '@string/app_name'
|
||||
])
|
||||
}
|
||||
|
||||
release {
|
||||
debuggable false
|
||||
jniDebuggable false
|
||||
zipAlignEnabled false
|
||||
shrinkResources true
|
||||
minifyEnabled true
|
||||
signingConfig signingConfigs.config
|
||||
addManifestPlaceholders([
|
||||
'app_name': '@string/app_name'
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/*******'
|
||||
}
|
||||
|
||||
aspectjx {
|
||||
include android.defaultConfig.applicationId
|
||||
}
|
||||
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.all { output ->
|
||||
outputFileName = rootProject.getName() + '_v' + variant.versionName + '_' + variant.buildType.name
|
||||
if (variant.buildType.name == buildTypes.release.getName()) {
|
||||
outputFileName += '_' + new Date().format('MMdd')
|
||||
}
|
||||
outputFileName += '.apk'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':library:base')
|
||||
implementation project(':library:widget')
|
||||
|
||||
implementation 'com.github.getActivity:XXPermissions:12.3'
|
||||
|
||||
implementation 'com.github.getActivity:TitleBar:9.2'
|
||||
|
||||
implementation 'com.github.getActivity:ToastUtils:9.5'
|
||||
|
||||
implementation 'com.github.getActivity:EasyHttp:13.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.14.9'
|
||||
|
||||
implementation 'com.google.code.gson:gson:2.8.8'
|
||||
implementation 'com.github.getActivity:GsonFactory:5.2'
|
||||
|
||||
implementation 'com.github.getActivity:ShapeView:9.0'
|
||||
|
||||
implementation 'org.aspectj:aspectjrt:1.9.6'
|
||||
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.12.0'
|
||||
|
||||
implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
|
||||
|
||||
implementation 'com.github.Baseflow:PhotoView:2.3.0'
|
||||
|
||||
implementation 'com.tencent.bugly:crashreport:3.4.4'
|
||||
implementation 'com.tencent.bugly:nativecrashreport:3.9.2'
|
||||
|
||||
implementation 'com.airbnb.android:lottie:4.1.0'
|
||||
|
||||
implementation 'com.scwang.smart:refresh-layout-kernel:2.0.3'
|
||||
implementation 'com.scwang.smart:refresh-header-material:2.0.3'
|
||||
|
||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||
|
||||
implementation 'me.relex:circleindicator:2.1.6'
|
||||
|
||||
implementation 'com.tencent:mmkv-static:1.2.10'
|
||||
|
||||
// banner
|
||||
implementation 'io.github.youth5201314:banner:2.2.3'
|
||||
|
||||
implementation "io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.4"
|
||||
|
||||
implementation "com.afollestad.material-dialogs:core:3.1.1"
|
||||
implementation "com.afollestad.material-dialogs:lifecycle:3.1.1"
|
||||
|
||||
implementation "androidx.media3:media3-ui:1.4.0"
|
||||
implementation "androidx.media3:media3-exoplayer:1.4.0"
|
||||
implementation "androidx.media3:media3-exoplayer-dash:1.4.0"
|
||||
implementation "androidx.media3:media3-exoplayer-hls:1.4.0"
|
||||
implementation(files("libs/lib-decoder-ffmpeg-release.aar"))
|
||||
|
||||
implementation "org.greenrobot:eventbus:3.3.1"
|
||||
implementation("com.blankj:utilcodex:1.31.1")
|
||||
implementation("com.github.li-xiaojun:XPopup:2.10.0")
|
||||
|
||||
|
||||
}
|
4
Android_Mireo/app/gradle.properties
Normal file
4
Android_Mireo/app/gradle.properties
Normal file
@ -0,0 +1,4 @@
|
||||
StoreFile = AppMireo.jks
|
||||
StorePassword = appmireo
|
||||
KeyAlias = appmireo
|
||||
KeyPassword = appmireo
|
36
Android_Mireo/app/proguard-app.pro
Normal file
36
Android_Mireo/app/proguard-app.pro
Normal file
@ -0,0 +1,36 @@
|
||||
#-ignorewarning
|
||||
|
||||
-libraryjars libs/lib-decoder-ffmpeg-release.aar
|
||||
|
||||
-keep class com.localee.mireo.app.http.api.** {
|
||||
<fields>;
|
||||
}
|
||||
-keep class com.localee.mireo.app.http.response.** {
|
||||
<fields>;
|
||||
}
|
||||
-keep class com.localee.mireo.app.http.model.** {
|
||||
<fields>;
|
||||
}
|
||||
-keep class com.localee.mireo.app.http.exception.** {
|
||||
<fields>;
|
||||
}
|
||||
|
||||
-keepclassmembernames class ** {
|
||||
@com.localee.mireo.app.aop.Log <methods>;
|
||||
}
|
||||
|
||||
|
||||
-keep public class * extends android.view.View{
|
||||
*** get*();
|
||||
void set*(***);
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
-keepclassmembers class * {
|
||||
public void *(android.view.View);
|
||||
}
|
45
Android_Mireo/app/proguard-sdk.pro
Normal file
45
Android_Mireo/app/proguard-sdk.pro
Normal file
@ -0,0 +1,45 @@
|
||||
# Glide
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep class * extends com.bumptech.glide.module.AppGlideModule {
|
||||
<init>(...);
|
||||
}
|
||||
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
||||
-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
|
||||
*** rewind();
|
||||
}
|
||||
|
||||
# for DexGuard only
|
||||
#-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
|
||||
|
||||
# Bugly
|
||||
-dontwarn com.tencent.bugly.**
|
||||
-keep public class com.tencent.bugly.**{*;}
|
||||
|
||||
# AOP
|
||||
-adaptclassstrings
|
||||
-keepattributes InnerClasses, EnclosingMethod, Signature, *Annotation*
|
||||
|
||||
-keepnames @org.aspectj.lang.annotation.Aspect class * {
|
||||
public <methods>;
|
||||
}
|
||||
|
||||
# OkHttp3
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
-keep class okhttp3.** { *; }
|
||||
-keep interface okhttp3.** { *; }
|
||||
-dontwarn okhttp3.**
|
||||
-dontwarn okio.**
|
||||
-dontwarn org.conscrypt.**
|
||||
|
||||
-keep class com.gyf.immersionbar.* {*;}
|
||||
-dontwarn com.gyf.immersionbar.**
|
||||
|
||||
# com.hjq
|
||||
-keep class com.hjq.permissions.** {*;}
|
||||
-keep class com.hjq.bar.** {*;}
|
||||
-keep class com.hjq.toast.** {*;}
|
||||
-keep class com.hjq.shape.** {*;}
|
125
Android_Mireo/app/src/main/AndroidManifest.xml
Normal file
125
Android_Mireo/app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.localee.mireo.app">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
|
||||
<application
|
||||
android:name=".app.AppApplication"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_app_logo"
|
||||
android:label="${app_name}"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:resizeableActivity="true"
|
||||
android:roundIcon="@mipmap/ic_app_logo"
|
||||
android:supportsRtl="false"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="AllowBackup,LockedOrientationActivity"
|
||||
tools:replace="android:allowBackup,android:supportsRtl"
|
||||
tools:targetApi="31">
|
||||
|
||||
<meta-data
|
||||
android:name="ScopedStorage"
|
||||
android:value="true" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.SplashActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.Splash"
|
||||
>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.HomeActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustPan" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.SettingActivity"
|
||||
android:label="@string/setting_title"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.AboutActivity"
|
||||
android:label="@string/about_title"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.BrowserActivity"
|
||||
android:label="@string/web_title"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.VideoPlayActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/FullScreenTheme" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.SearchActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
</intent>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.GET_CONTENT" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,74 @@
|
||||
package com.localee.mireo.app.action
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkInfo
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.RawRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.widget.StatusLayout
|
||||
import com.localee.mireo.app.widget.StatusLayout.OnRetryListener
|
||||
|
||||
|
||||
interface StatusAction {
|
||||
|
||||
|
||||
fun getStatusLayout(): StatusLayout?
|
||||
|
||||
|
||||
fun showLoading(@RawRes id: Int = R.raw.loading) {
|
||||
getStatusLayout()?.let {
|
||||
it.show()
|
||||
it.setAnimResource(id)
|
||||
it.setHint("")
|
||||
it.setOnRetryListener(null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun showComplete() {
|
||||
getStatusLayout()?.let {
|
||||
if (!it.isShow()) {
|
||||
return
|
||||
}
|
||||
it.hide()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun showEmpty() {
|
||||
showLayout(R.drawable.status_empty_ic, R.string.status_layout_no_data, null)
|
||||
}
|
||||
|
||||
|
||||
fun showError(listener: OnRetryListener?) {
|
||||
getStatusLayout()?.let {
|
||||
val manager: ConnectivityManager? = ContextCompat.getSystemService(it.context, ConnectivityManager::class.java)
|
||||
if (manager != null) {
|
||||
val info: NetworkInfo? = manager.activeNetworkInfo
|
||||
if (info == null || !info.isConnected) {
|
||||
showLayout(R.drawable.status_network_ic, R.string.status_layout_error_network, listener)
|
||||
return
|
||||
}
|
||||
}
|
||||
showLayout(R.drawable.status_error_ic, R.string.status_layout_error_request, listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun showLayout(@DrawableRes drawableId: Int, @StringRes stringId: Int, listener: OnRetryListener?) {
|
||||
getStatusLayout()?.let {
|
||||
showLayout(ContextCompat.getDrawable(it.context, drawableId), it.context.getString(stringId), listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun showLayout(drawable: Drawable?, hint: CharSequence?, listener: OnRetryListener?) {
|
||||
getStatusLayout()?.let {
|
||||
it.show()
|
||||
it.setIcon(drawable)
|
||||
it.setHint(hint)
|
||||
it.setOnRetryListener(listener)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package com.localee.mireo.app.action
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.StringRes
|
||||
import com.hjq.bar.OnTitleBarListener
|
||||
import com.hjq.bar.TitleBar
|
||||
|
||||
interface TitleBarAction : OnTitleBarListener {
|
||||
|
||||
fun getTitleBar(): TitleBar?
|
||||
|
||||
override fun onLeftClick(view: View) {}
|
||||
|
||||
override fun onTitleClick(view: View) {}
|
||||
|
||||
override fun onRightClick(view: View) {}
|
||||
|
||||
fun setTitle(@StringRes id: Int) {
|
||||
getTitleBar()?.setTitle(id)
|
||||
}
|
||||
|
||||
fun setTitle(title: CharSequence?) {
|
||||
getTitleBar()?.title = title
|
||||
}
|
||||
|
||||
fun setLeftTitle(id: Int) {
|
||||
getTitleBar()?.setLeftTitle(id)
|
||||
}
|
||||
|
||||
fun setLeftTitle(text: CharSequence?) {
|
||||
getTitleBar()?.leftTitle = text
|
||||
}
|
||||
|
||||
fun getLeftTitle(): CharSequence? {
|
||||
return getTitleBar()?.leftTitle
|
||||
}
|
||||
|
||||
fun setRightTitle(id: Int) {
|
||||
getTitleBar()?.setRightTitle(id)
|
||||
}
|
||||
|
||||
fun setRightTitle(text: CharSequence?) {
|
||||
getTitleBar()?.rightTitle = text
|
||||
}
|
||||
|
||||
fun getRightTitle(): CharSequence? {
|
||||
return getTitleBar()?.rightTitle
|
||||
}
|
||||
|
||||
fun setLeftIcon(id: Int) {
|
||||
getTitleBar()?.setLeftIcon(id)
|
||||
}
|
||||
|
||||
fun setLeftIcon(drawable: Drawable?) {
|
||||
getTitleBar()?.leftIcon = drawable
|
||||
}
|
||||
|
||||
fun getLeftIcon(): Drawable? {
|
||||
return getTitleBar()?.leftIcon
|
||||
}
|
||||
|
||||
fun setRightIcon(id: Int) {
|
||||
getTitleBar()?.setRightIcon(id)
|
||||
}
|
||||
|
||||
fun setRightIcon(drawable: Drawable?) {
|
||||
getTitleBar()?.rightIcon = drawable
|
||||
}
|
||||
|
||||
fun getRightIcon(): Drawable? {
|
||||
return getTitleBar()?.rightIcon
|
||||
}
|
||||
|
||||
fun obtainTitleBar(group: ViewGroup?): TitleBar? {
|
||||
if (group == null) {
|
||||
return null
|
||||
}
|
||||
for (i in 0 until group.childCount) {
|
||||
val view = group.getChildAt(i)
|
||||
if (view is TitleBar) {
|
||||
return view
|
||||
}
|
||||
if (view is ViewGroup) {
|
||||
val titleBar = obtainTitleBar(view)
|
||||
if (titleBar != null) {
|
||||
return titleBar
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.localee.mireo.app.action
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import com.hjq.toast.ToastUtils
|
||||
|
||||
interface ToastAction {
|
||||
|
||||
fun toast(text: CharSequence?) {
|
||||
ToastUtils.show(text)
|
||||
}
|
||||
|
||||
fun toast(@StringRes id: Int) {
|
||||
ToastUtils.show(id)
|
||||
}
|
||||
|
||||
fun toast(`object`: Any?) {
|
||||
ToastUtils.show(`object`)
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER)
|
||||
annotation class CheckNet
|
@ -0,0 +1,36 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
import android.app.*
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkInfo
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.manager.ActivityManager
|
||||
import com.hjq.toast.ToastUtils
|
||||
import org.aspectj.lang.ProceedingJoinPoint
|
||||
import org.aspectj.lang.annotation.Around
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.annotation.Pointcut
|
||||
|
||||
@Suppress("unused")
|
||||
@Aspect
|
||||
class CheckNetAspect {
|
||||
|
||||
@Pointcut("execution(@com.localee.mireo.app.aop.CheckNet * *(..))")
|
||||
fun method() {}
|
||||
|
||||
@Around("method() && @annotation(checkNet)")
|
||||
@Throws(Throwable::class)
|
||||
fun aroundJoinPoint(joinPoint: ProceedingJoinPoint, checkNet: CheckNet) {
|
||||
val application: Application = ActivityManager.getInstance().getApplication()
|
||||
val manager: ConnectivityManager? = ContextCompat.getSystemService(application, ConnectivityManager::class.java)
|
||||
if (manager != null) {
|
||||
val info: NetworkInfo? = manager.activeNetworkInfo
|
||||
if (info == null || !info.isConnected) {
|
||||
ToastUtils.show(R.string.common_network_hint)
|
||||
return
|
||||
}
|
||||
}
|
||||
joinPoint.proceed()
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER,
|
||||
AnnotationTarget.CONSTRUCTOR)
|
||||
annotation class Log constructor(val value: String = "AppLog")
|
@ -0,0 +1,96 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
import android.os.Looper
|
||||
import android.os.Trace
|
||||
import org.aspectj.lang.ProceedingJoinPoint
|
||||
import org.aspectj.lang.Signature
|
||||
import org.aspectj.lang.annotation.Around
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.annotation.Pointcut
|
||||
import org.aspectj.lang.reflect.CodeSignature
|
||||
import org.aspectj.lang.reflect.MethodSignature
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@Suppress("unused")
|
||||
@Aspect
|
||||
class LogAspect {
|
||||
|
||||
@Pointcut("execution(@com.localee.mireo.app.aop.Log *.new(..))")
|
||||
fun constructor() {}
|
||||
|
||||
@Pointcut("execution(@com.localee.mireo.app.aop.Log * *(..))")
|
||||
fun method() {}
|
||||
|
||||
@Around("(method() || constructor()) && @annotation(log)")
|
||||
@Throws(Throwable::class)
|
||||
fun aroundJoinPoint(joinPoint: ProceedingJoinPoint, log: Log): Any? {
|
||||
enterMethod(joinPoint, log)
|
||||
val startNanos: Long = System.nanoTime()
|
||||
val result: Any? = joinPoint.proceed()
|
||||
val stopNanos: Long = System.nanoTime()
|
||||
exitMethod(joinPoint, log, result, TimeUnit.NANOSECONDS.toMillis(stopNanos - startNanos))
|
||||
return result
|
||||
}
|
||||
|
||||
private fun enterMethod(joinPoint: ProceedingJoinPoint, log: Log) {
|
||||
val codeSignature: CodeSignature = joinPoint.signature as CodeSignature
|
||||
|
||||
val className: String = codeSignature.declaringType.name
|
||||
val methodName: String = codeSignature.name
|
||||
val parameterNames: Array<String?> = codeSignature.parameterNames
|
||||
val parameterValues: Array<Any?> = joinPoint.args
|
||||
|
||||
val builder: StringBuilder =
|
||||
getMethodLogInfo(className, methodName, parameterNames, parameterValues)
|
||||
log(log.value, builder.toString())
|
||||
val section: String = builder.substring(2)
|
||||
Trace.beginSection(section)
|
||||
}
|
||||
|
||||
private fun getMethodLogInfo(className: String, methodName: String, parameterNames: Array<String?>, parameterValues: Array<Any?>): StringBuilder {
|
||||
val builder: StringBuilder = StringBuilder("\u21E2 ")
|
||||
builder.append(className)
|
||||
.append(".")
|
||||
.append(methodName)
|
||||
.append('(')
|
||||
for (i in parameterValues.indices) {
|
||||
if (i > 0) {
|
||||
builder.append(", ")
|
||||
}
|
||||
builder.append(parameterNames[i]).append('=')
|
||||
builder.append(parameterValues[i].toString())
|
||||
}
|
||||
builder.append(')')
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
builder.append(" [Thread:\"").append(Thread.currentThread().name).append("\"]")
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
private fun exitMethod(joinPoint: ProceedingJoinPoint, log: Log, result: Any?, lengthMillis: Long) {
|
||||
Trace.endSection()
|
||||
val signature: Signature = joinPoint.signature
|
||||
val className: String? = signature.declaringType.name
|
||||
val methodName: String? = signature.name
|
||||
val builder: StringBuilder = StringBuilder("\u21E0 ")
|
||||
.append(className)
|
||||
.append(".")
|
||||
.append(methodName)
|
||||
.append(" [")
|
||||
.append(lengthMillis)
|
||||
.append("ms]")
|
||||
|
||||
// 判断方法是否有返回值
|
||||
if (signature is MethodSignature && signature.returnType != Void.TYPE) {
|
||||
builder.append(" = ")
|
||||
builder.append(result.toString())
|
||||
}
|
||||
log(log.value, builder.toString())
|
||||
}
|
||||
|
||||
private fun log(tag: String?, msg: String?) {
|
||||
Timber.tag(tag)
|
||||
Timber.d(msg)
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER)
|
||||
annotation class Permissions constructor(
|
||||
vararg val value: String
|
||||
)
|
@ -0,0 +1,58 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
import android.app.Activity
|
||||
import com.localee.mireo.app.other.PermissionCallback
|
||||
import com.hjq.permissions.XXPermissions
|
||||
import com.localee.mireo.app.manager.ActivityManager
|
||||
import com.tencent.bugly.crashreport.CrashReport
|
||||
import org.aspectj.lang.ProceedingJoinPoint
|
||||
import org.aspectj.lang.annotation.Around
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.annotation.Pointcut
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("unused")
|
||||
@Aspect
|
||||
class PermissionsAspect {
|
||||
@Pointcut("execution(@com.localee.mireo.app.aop.Permissions * *(..))")
|
||||
fun method() {}
|
||||
|
||||
@Around("method() && @annotation(permissions)")
|
||||
fun aroundJoinPoint(joinPoint: ProceedingJoinPoint, permissions: Permissions) {
|
||||
var activity: Activity? = null
|
||||
|
||||
val parameterValues: Array<Any?> = joinPoint.args
|
||||
for (arg: Any? in parameterValues) {
|
||||
if (arg !is Activity) {
|
||||
continue
|
||||
}
|
||||
activity = arg
|
||||
break
|
||||
}
|
||||
if ((activity == null) || activity.isFinishing || activity.isDestroyed) {
|
||||
activity = ActivityManager.getInstance().getTopActivity()
|
||||
}
|
||||
if ((activity == null) || activity.isFinishing || activity.isDestroyed) {
|
||||
Timber.e("The activity has been destroyed and permission requests cannot be made")
|
||||
return
|
||||
}
|
||||
requestPermissions(joinPoint, activity, permissions.value)
|
||||
}
|
||||
|
||||
private fun requestPermissions(joinPoint: ProceedingJoinPoint, activity: Activity, permissions: Array<out String>) {
|
||||
XXPermissions.with(activity)
|
||||
.permission(*permissions)
|
||||
.request(object : PermissionCallback() {
|
||||
override fun onGranted(permissions: MutableList<String?>?, all: Boolean) {
|
||||
if (all) {
|
||||
try {
|
||||
// 获得权限,执行原方法
|
||||
joinPoint.proceed()
|
||||
} catch (e: Throwable) {
|
||||
CrashReport.postCatchedException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER)
|
||||
annotation class SingleClick constructor(
|
||||
val value: Long = 1000
|
||||
)
|
@ -0,0 +1,51 @@
|
||||
package com.localee.mireo.app.aop
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint
|
||||
import org.aspectj.lang.annotation.Around
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.annotation.Pointcut
|
||||
import org.aspectj.lang.reflect.CodeSignature
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("unused")
|
||||
@Aspect
|
||||
class SingleClickAspect {
|
||||
|
||||
private var lastTime: Long = 0
|
||||
|
||||
private var lastTag: String? = null
|
||||
|
||||
@Pointcut("execution(@com.localee.mireo.app.aop.SingleClick * *(..))")
|
||||
fun method() {}
|
||||
|
||||
@Around("method() && @annotation(singleClick)")
|
||||
@Throws(Throwable::class)
|
||||
fun aroundJoinPoint(joinPoint: ProceedingJoinPoint, singleClick: SingleClick) {
|
||||
val codeSignature: CodeSignature = joinPoint.signature as CodeSignature
|
||||
val className: String = codeSignature.declaringType.name
|
||||
val methodName: String = codeSignature.name
|
||||
val builder: StringBuilder = StringBuilder("$className.$methodName")
|
||||
builder.append("(")
|
||||
val parameterValues: Array<Any?> = joinPoint.args
|
||||
for (i in parameterValues.indices) {
|
||||
val arg: Any? = parameterValues[i]
|
||||
if (i == 0) {
|
||||
builder.append(arg)
|
||||
} else {
|
||||
builder.append(", ")
|
||||
.append(arg)
|
||||
}
|
||||
}
|
||||
builder.append(")")
|
||||
val tag: String = builder.toString()
|
||||
val currentTimeMillis: Long = System.currentTimeMillis()
|
||||
if (currentTimeMillis - lastTime < singleClick.value && (tag == lastTag)) {
|
||||
Timber.tag("SingleClick")
|
||||
Timber.i("Within %s milliseconds, there was a rapid click:%s", singleClick.value, tag)
|
||||
return
|
||||
}
|
||||
lastTime = currentTimeMillis
|
||||
lastTag = tag
|
||||
joinPoint.proceed()
|
||||
}
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
package com.localee.mireo.app.app
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.hjq.bar.TitleBar
|
||||
import com.hjq.base.BaseActivity
|
||||
import com.hjq.base.BaseDialog
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.action.TitleBarAction
|
||||
import com.localee.mireo.app.action.ToastAction
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.ui.dialog.WaitDialog
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import com.hjq.http.listener.OnHttpListener
|
||||
import com.hjq.toast.ToastUtils
|
||||
|
||||
abstract class AppActivity : BaseActivity(),
|
||||
ToastAction, TitleBarAction, OnHttpListener<Any> {
|
||||
|
||||
private var titleBar: TitleBar? = null
|
||||
|
||||
private var immersionBar: ImmersionBar? = null
|
||||
|
||||
private var dialog: BaseDialog? = null
|
||||
|
||||
private var dialogCount: Int = 0
|
||||
|
||||
open fun isShowDialog(): Boolean {
|
||||
return dialog != null && dialog!!.isShowing
|
||||
}
|
||||
|
||||
open fun showDialog() {
|
||||
if (isFinishing || isDestroyed) {
|
||||
return
|
||||
}
|
||||
dialogCount++
|
||||
postDelayed(Runnable {
|
||||
if ((dialogCount <= 0) || isFinishing || isDestroyed) {
|
||||
return@Runnable
|
||||
}
|
||||
if (dialog == null) {
|
||||
dialog = WaitDialog.Builder(this)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
}
|
||||
if (!dialog!!.isShowing) {
|
||||
dialog!!.show()
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
|
||||
open fun hideDialog() {
|
||||
if (isFinishing || isDestroyed) {
|
||||
return
|
||||
}
|
||||
if (dialogCount > 0) {
|
||||
dialogCount--
|
||||
}
|
||||
if ((dialogCount != 0) || (dialog == null) || !dialog!!.isShowing) {
|
||||
return
|
||||
}
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
||||
override fun initLayout() {
|
||||
super.initLayout()
|
||||
|
||||
val titleBar = getTitleBar()
|
||||
titleBar?.setOnTitleBarListener(this)
|
||||
|
||||
if (isStatusBarEnabled()) {
|
||||
getStatusBarConfig().init()
|
||||
|
||||
if (titleBar != null) {
|
||||
ImmersionBar.setTitleBar(this, titleBar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun isStatusBarEnabled(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
open fun isStatusBarDarkFont(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
open fun getStatusBarConfig(): ImmersionBar {
|
||||
if (immersionBar == null) {
|
||||
immersionBar = createStatusBarConfig()
|
||||
}
|
||||
return immersionBar!!
|
||||
}
|
||||
|
||||
protected open fun createStatusBarConfig(): ImmersionBar {
|
||||
return ImmersionBar.with(this) // 默认状态栏字体颜色为黑色
|
||||
.statusBarDarkFont(false) // 指定导航栏背景颜色
|
||||
.navigationBarColor(R.color.black) // 状态栏字体和导航栏内容自动变色,必须指定状态栏颜色和导航栏颜色才可以自动变色
|
||||
.autoDarkModeEnable(true, 0.2f)
|
||||
}
|
||||
|
||||
override fun setTitle(@StringRes id: Int) {
|
||||
title = getString(id)
|
||||
}
|
||||
|
||||
override fun setTitle(title: CharSequence?) {
|
||||
super<BaseActivity>.setTitle(title)
|
||||
getTitleBar()?.title = title
|
||||
}
|
||||
|
||||
override fun getTitleBar(): TitleBar? {
|
||||
if (titleBar == null) {
|
||||
titleBar = obtainTitleBar(getContentView())
|
||||
}
|
||||
return titleBar
|
||||
}
|
||||
|
||||
override fun onLeftClick(view: View) {
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
override fun startActivityForResult(intent: Intent, requestCode: Int, options: Bundle?) {
|
||||
super.startActivityForResult(intent, requestCode, options)
|
||||
overridePendingTransition(R.anim.right_in_activity, R.anim.right_out_activity)
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
super.finish()
|
||||
overridePendingTransition(R.anim.left_in_activity, R.anim.left_out_activity)
|
||||
}
|
||||
|
||||
override fun onHttpStart(api: IRequestApi) {
|
||||
showDialog()
|
||||
}
|
||||
|
||||
override fun onHttpSuccess(result: Any) {
|
||||
if (result is HttpData<*>) {
|
||||
toast(result.getMessage())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onHttpFail(throwable: Throwable) {
|
||||
ToastUtils.show(throwable.message)
|
||||
}
|
||||
|
||||
override fun onHttpEnd(api: IRequestApi) {
|
||||
hideDialog()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (isShowDialog()) {
|
||||
hideDialog()
|
||||
}
|
||||
dialog = null
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package com.localee.mireo.app.app
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.annotation.IntRange
|
||||
import androidx.annotation.LayoutRes
|
||||
import com.hjq.base.BaseAdapter
|
||||
import java.util.*
|
||||
|
||||
abstract class AppAdapter<T> constructor(context: Context) :
|
||||
BaseAdapter<AppAdapter<T>.AppViewHolder>(context) {
|
||||
|
||||
private var dataSet: MutableList<T> = ArrayList()
|
||||
|
||||
private var pageNumber = 1
|
||||
|
||||
private var lastPage = false
|
||||
|
||||
private var tag: Any? = null
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return getCount()
|
||||
}
|
||||
|
||||
open fun getCount(): Int {
|
||||
return dataSet.size
|
||||
}
|
||||
|
||||
open fun setData(data: MutableList<T>?) {
|
||||
if (data == null) {
|
||||
dataSet.clear()
|
||||
} else {
|
||||
dataSet = data
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
open fun getData(): MutableList<T> {
|
||||
return dataSet
|
||||
}
|
||||
|
||||
open fun addData(data: MutableList<T>?) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
return
|
||||
}
|
||||
dataSet.addAll(data)
|
||||
notifyItemRangeInserted(dataSet.size - data.size, data.size)
|
||||
}
|
||||
|
||||
open fun clearData() {
|
||||
dataSet.clear()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
open fun containsItem(@IntRange(from = 0) position: Int): Boolean {
|
||||
return containsItem(getItem(position))
|
||||
}
|
||||
|
||||
open fun containsItem(item: T?): Boolean {
|
||||
return if (item == null) {
|
||||
false
|
||||
} else dataSet.contains(item)
|
||||
}
|
||||
|
||||
open fun getItem(@IntRange(from = 0) position: Int): T {
|
||||
return dataSet[position]
|
||||
}
|
||||
|
||||
open fun setItem(@IntRange(from = 0) position: Int, item: T) {
|
||||
dataSet[position] = item
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
||||
open fun addItem(item: T) {
|
||||
addItem(dataSet.size, item)
|
||||
}
|
||||
|
||||
open fun addItem(@IntRange(from = 0) position: Int, item: T) {
|
||||
var finalPosition = position
|
||||
if (finalPosition < dataSet.size) {
|
||||
dataSet.add(finalPosition, item)
|
||||
} else {
|
||||
dataSet.add(item)
|
||||
finalPosition = dataSet.size - 1
|
||||
}
|
||||
notifyItemInserted(finalPosition)
|
||||
}
|
||||
|
||||
open fun removeItem(item: T) {
|
||||
val index = dataSet.indexOf(item)
|
||||
if (index != -1) {
|
||||
removeItem(index)
|
||||
}
|
||||
}
|
||||
|
||||
open fun removeItem(@IntRange(from = 0) position: Int) {
|
||||
dataSet.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
}
|
||||
|
||||
open fun getPageNumber(): Int {
|
||||
return pageNumber
|
||||
}
|
||||
|
||||
open fun setPageNumber(@IntRange(from = 0) number: Int) {
|
||||
pageNumber = number
|
||||
}
|
||||
|
||||
open fun isLastPage(): Boolean {
|
||||
return lastPage
|
||||
}
|
||||
|
||||
open fun setLastPage(last: Boolean) {
|
||||
lastPage = last
|
||||
}
|
||||
|
||||
open fun getTag(): Any? {
|
||||
return tag
|
||||
}
|
||||
|
||||
open fun setTag(tag: Any) {
|
||||
this.tag = tag
|
||||
}
|
||||
|
||||
abstract inner class AppViewHolder : BaseViewHolder {
|
||||
|
||||
constructor(@LayoutRes id: Int) : super(id)
|
||||
|
||||
constructor(itemView: View) : super(itemView)
|
||||
}
|
||||
|
||||
inner class SimpleViewHolder : AppViewHolder {
|
||||
|
||||
constructor(@LayoutRes id: Int) : super(id)
|
||||
|
||||
constructor(itemView: View) : super(itemView)
|
||||
|
||||
override fun onBindView(position: Int) {}
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
package com.localee.mireo.app.app
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.google.gson.stream.JsonToken
|
||||
import com.hjq.bar.TitleBar
|
||||
import com.hjq.gson.factory.GsonFactory
|
||||
import com.hjq.http.EasyConfig
|
||||
import com.hjq.http.config.IRequestInterceptor
|
||||
import com.hjq.http.model.HttpHeaders
|
||||
import com.hjq.http.model.HttpParams
|
||||
import com.hjq.http.request.HttpRequest
|
||||
import com.hjq.toast.ToastUtils
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.aop.Log
|
||||
import com.localee.mireo.app.http.exception.HttpBodyInterceptor
|
||||
import com.localee.mireo.app.http.model.RequestHandler
|
||||
import com.localee.mireo.app.http.model.RequestServer
|
||||
import com.localee.mireo.app.manager.ActivityManager
|
||||
import com.localee.mireo.app.other.AppConfig
|
||||
import com.localee.mireo.app.other.CrashHandler
|
||||
import com.localee.mireo.app.other.DebugLoggerTree
|
||||
import com.localee.mireo.app.other.MaterialHeader
|
||||
import com.localee.mireo.app.other.SmartBallPulseFooter
|
||||
import com.localee.mireo.app.other.TitleBarStyle
|
||||
import com.localee.mireo.app.other.ToastStyle
|
||||
import com.localee.mireo.app.utils.MsMMKVUtils
|
||||
import com.localee.mireo.app.utils.MsSystemUtlis
|
||||
import com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import com.tencent.bugly.crashreport.CrashReport
|
||||
import com.tencent.mmkv.MMKV
|
||||
import okhttp3.OkHttpClient
|
||||
import timber.log.Timber
|
||||
|
||||
class AppApplication : Application() {
|
||||
|
||||
@Log("启动耗时")
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
instance = this;
|
||||
initSdk(this)
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
super.onTrimMemory(level)
|
||||
}
|
||||
|
||||
companion object {
|
||||
lateinit var instance: Application;
|
||||
var isCurrentPage: Boolean = true
|
||||
|
||||
fun initSdk(application: Application) {
|
||||
TitleBar.setDefaultStyle(TitleBarStyle())
|
||||
|
||||
SmartRefreshLayout.setDefaultRefreshHeaderCreator { context: Context, layout: RefreshLayout ->
|
||||
MaterialHeader(context).setColorSchemeColors(
|
||||
ContextCompat.getColor(
|
||||
context,
|
||||
R.color.common_accent_color
|
||||
)
|
||||
)
|
||||
}
|
||||
SmartRefreshLayout.setDefaultRefreshFooterCreator { context: Context, layout: RefreshLayout ->
|
||||
SmartBallPulseFooter(context)
|
||||
}
|
||||
SmartRefreshLayout.setDefaultRefreshInitializer { context: Context, layout: RefreshLayout ->
|
||||
layout.setEnableHeaderTranslationContent(true)
|
||||
.setEnableFooterTranslationContent(true)
|
||||
.setEnableFooterFollowWhenNoMoreData(true)
|
||||
.setEnableLoadMoreWhenContentNotFull(false)
|
||||
.setEnableOverScrollDrag(false)
|
||||
}
|
||||
|
||||
ToastUtils.init(application, ToastStyle())
|
||||
ToastUtils.setDebugMode(AppConfig.isDebug())
|
||||
|
||||
CrashHandler.register(application)
|
||||
|
||||
ActivityManager.getInstance().init(application)
|
||||
|
||||
MMKV.initialize(application)
|
||||
|
||||
val okHttpClient: OkHttpClient = OkHttpClient.Builder()
|
||||
.addInterceptor(HttpBodyInterceptor())
|
||||
.build()
|
||||
|
||||
|
||||
EasyConfig.with(okHttpClient)
|
||||
.setLogEnabled(AppConfig.isLogEnable())
|
||||
.setServer(RequestServer())
|
||||
.setHandler(RequestHandler(application))
|
||||
.setRetryCount(1)
|
||||
.setInterceptor(object : IRequestInterceptor {
|
||||
override fun interceptArguments(
|
||||
httpRequest: HttpRequest<*>,
|
||||
params: HttpParams,
|
||||
headers: HttpHeaders
|
||||
) {
|
||||
headers.put("Content-Type", "application/json; charset=utf-8")
|
||||
headers.put("Content-Type", "text/plain; charset=utf-8")
|
||||
|
||||
headers.put("Authorization", MsMMKVUtils.getToken())
|
||||
headers.put(
|
||||
"device-id",
|
||||
MsSystemUtlis.getDeviceId(instance).toString()
|
||||
)
|
||||
headers.put(
|
||||
"lang-key",
|
||||
"en"
|
||||
)
|
||||
headers.put("system-type", "android")
|
||||
headers.put("app_id", "nice_short")
|
||||
headers.put("system_version", "12")
|
||||
headers.put("model", Build.MODEL)
|
||||
headers.put("brand", Build.MANUFACTURER + "-" + Build.PRODUCT)
|
||||
headers.put(
|
||||
"app_version",
|
||||
MsSystemUtlis.getVerNameInfo(instance)
|
||||
)
|
||||
// headers.put("security","true")
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
.into()
|
||||
|
||||
GsonFactory.setJsonCallback { typeToken: TypeToken<*>, fieldName: String?, jsonToken: JsonToken ->
|
||||
CrashReport.postCatchedException(IllegalArgumentException("Type parsing exception:$typeToken#$fieldName,the type returned by the background is:$jsonToken"))
|
||||
}
|
||||
|
||||
if (AppConfig.isLogEnable()) {
|
||||
Timber.plant(DebugLoggerTree())
|
||||
}
|
||||
|
||||
val connectivityManager: ConnectivityManager? =
|
||||
ContextCompat.getSystemService(application, ConnectivityManager::class.java)
|
||||
if (connectivityManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
connectivityManager.registerDefaultNetworkCallback(object :
|
||||
ConnectivityManager.NetworkCallback() {
|
||||
override fun onLost(network: Network) {
|
||||
val topActivity: Activity? = ActivityManager.getInstance().getTopActivity()
|
||||
if (topActivity !is LifecycleOwner) {
|
||||
return
|
||||
}
|
||||
val lifecycleOwner: LifecycleOwner = topActivity
|
||||
if (lifecycleOwner.lifecycle.currentState != Lifecycle.State.RESUMED) {
|
||||
return
|
||||
}
|
||||
ToastUtils.show(R.string.common_network_error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.localee.mireo.app.app
|
||||
|
||||
import com.hjq.base.BaseFragment
|
||||
import com.localee.mireo.app.action.ToastAction
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import com.hjq.http.listener.OnHttpListener
|
||||
import com.hjq.toast.ToastUtils
|
||||
|
||||
abstract class AppFragment<A : AppActivity> : BaseFragment<A>(),
|
||||
ToastAction, OnHttpListener<Any> {
|
||||
|
||||
open fun isShowDialog(): Boolean {
|
||||
val activity: A = getAttachActivity() ?: return false
|
||||
return activity.isShowDialog()
|
||||
}
|
||||
|
||||
open fun showDialog() {
|
||||
getAttachActivity()?.showDialog()
|
||||
}
|
||||
|
||||
open fun hideDialog() {
|
||||
getAttachActivity()?.hideDialog()
|
||||
}
|
||||
|
||||
|
||||
override fun onHttpStart(api: IRequestApi) {
|
||||
showDialog()
|
||||
}
|
||||
|
||||
override fun onHttpSuccess(result: Any) {
|
||||
if (result !is HttpData<*>) {
|
||||
return
|
||||
}
|
||||
toast(result.getMessage())
|
||||
|
||||
}
|
||||
|
||||
override fun onHttpFail(throwable: Throwable) {
|
||||
ToastUtils.show(throwable.message)
|
||||
}
|
||||
|
||||
override fun onHttpEnd(api: IRequestApi) {
|
||||
hideDialog()
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package com.localee.mireo.app.app
|
||||
|
||||
|
||||
data class BaseEventBus<T>(val code: String, val data: T)
|
@ -0,0 +1,69 @@
|
||||
package com.localee.mireo.app.app
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.hjq.bar.TitleBar
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.action.TitleBarAction
|
||||
|
||||
|
||||
abstract class TitleBarFragment<A : AppActivity> : AppFragment<A>(), TitleBarAction {
|
||||
|
||||
private var titleBar: TitleBar? = null
|
||||
|
||||
private var immersionBar: ImmersionBar? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val titleBar = getTitleBar()
|
||||
titleBar?.setOnTitleBarListener(this)
|
||||
|
||||
if (isStatusBarEnabled()) {
|
||||
getStatusBarConfig().init()
|
||||
if (titleBar != null) {
|
||||
ImmersionBar.setTitleBar(this, titleBar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isStatusBarEnabled()) {
|
||||
getStatusBarConfig().init()
|
||||
}
|
||||
}
|
||||
|
||||
open fun isStatusBarEnabled(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
protected fun getStatusBarConfig(): ImmersionBar {
|
||||
if (immersionBar == null) {
|
||||
immersionBar = createStatusBarConfig()
|
||||
}
|
||||
return immersionBar!!
|
||||
}
|
||||
|
||||
protected fun createStatusBarConfig(): ImmersionBar {
|
||||
return ImmersionBar.with(this)
|
||||
.statusBarDarkFont(false)
|
||||
.navigationBarColor(R.color.black)
|
||||
.autoDarkModeEnable(true, 0.2f)
|
||||
}
|
||||
|
||||
protected open fun isStatusBarDarkFont(): Boolean {
|
||||
return getAttachActivity()!!.isStatusBarDarkFont()
|
||||
}
|
||||
|
||||
override fun getTitleBar(): TitleBar? {
|
||||
if (titleBar == null || !isLoading()) {
|
||||
titleBar = obtainTitleBar(view as ViewGroup)
|
||||
}
|
||||
return titleBar
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
|
||||
class CancelCollectApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "cancelCollect"
|
||||
}
|
||||
|
||||
var short_play_id: Int? = null
|
||||
|
||||
var video_id: Int? = null
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
|
||||
class CreateHistoryApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "createHistory"
|
||||
}
|
||||
|
||||
var short_play_id: Int? = null
|
||||
|
||||
var video_id: Int? = null
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class CustomerRegisterApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "customer/register"
|
||||
}
|
||||
|
||||
class Bean : Serializable{
|
||||
var token: String? = null
|
||||
var customer_id: Int? = null
|
||||
var auto_login: Boolean = false
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
|
||||
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,25 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
|
||||
class DoCollectApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "collect"
|
||||
}
|
||||
|
||||
private var short_play_id: String? = null
|
||||
|
||||
private var video_id: String? = null
|
||||
|
||||
fun setShortPlayId(short_play_id: String?): com.localee.mireo.app.http.api.DoCollectApi = apply {
|
||||
this.short_play_id = short_play_id
|
||||
}
|
||||
|
||||
fun setVideoId(video_id: String?): com.localee.mireo.app.http.api.DoCollectApi = apply {
|
||||
this.video_id = video_id
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
data class ExampleRecommendDataRes(
|
||||
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,33 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
class HistoryBean (
|
||||
val list: List<Data>,
|
||||
val pagination: Pagination
|
||||
) {
|
||||
|
||||
data class Data(
|
||||
val name: String,
|
||||
val short_play_video_id: Int,
|
||||
var description: String,
|
||||
val short_play_id: Int,
|
||||
val image_url: String,
|
||||
val episode_total: Int,
|
||||
val current_episode: String,
|
||||
var is_collect: Boolean,
|
||||
var is_check: Boolean,
|
||||
val categoryList: List<categoryBean>
|
||||
)
|
||||
|
||||
data class Pagination(
|
||||
val current_page: Int,
|
||||
val page_size: Int,
|
||||
val page_total: Int,
|
||||
val total_size: Int
|
||||
)
|
||||
|
||||
data class categoryBean(
|
||||
val id: String,
|
||||
val name: String
|
||||
)
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class HomeBannerApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "getBanners"
|
||||
}
|
||||
|
||||
class Bean : Serializable{
|
||||
var id: Int? = null
|
||||
var short_id: Int? = null
|
||||
var short_play_id: Int? = null
|
||||
var name: String? = null
|
||||
var description: String? = null
|
||||
var process: Int? = null
|
||||
var image_url: String? = null
|
||||
var horizontally_img: String? = null
|
||||
var buy_type: Int? = null
|
||||
var tag_type: String? = null
|
||||
var all_coins: Int? = null
|
||||
var collect_total: Int? = null
|
||||
var watch_total: Int? = null
|
||||
var episode_total: Int? = null
|
||||
var search_click_total: Int? = null
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
|
||||
class HomeCategoriesApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "getCategories"
|
||||
}
|
||||
|
||||
class Bean(
|
||||
val list: List<Data>,
|
||||
) {
|
||||
|
||||
data class Data(
|
||||
val id: Int,
|
||||
val name: String
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class HomeDayMaxRechargeShortPlayRankApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "homeRanking"
|
||||
}
|
||||
|
||||
class Bean {
|
||||
var list: List<RecommendBean>? = null
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class HomeModuleApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "homeModuleData"
|
||||
}
|
||||
|
||||
class Bean : Serializable {
|
||||
var bannerData: List<RecommendBean>? = null
|
||||
var recommandData: RecommandDataBean? = null
|
||||
var manualNewestRecommand: RecommandDataBean? = null
|
||||
var hotData: List<RecommendBean>? = null
|
||||
var newTopThree: List<RecommendBean>? = null
|
||||
var highestPayment: List<RecommendBean>? = null
|
||||
var hottestPist: List<RecommendBean>? = null
|
||||
|
||||
}
|
||||
|
||||
class RecommandDataBean {
|
||||
var title: String? = null
|
||||
var list: List<RecommendBean>? = null
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class HomeRecommendApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "getRecommands"
|
||||
}
|
||||
|
||||
var current_page: Int? = null
|
||||
var page_size: Int? = null
|
||||
var revolution: String? = null
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class HomeVideoListApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "videoList"
|
||||
}
|
||||
|
||||
var category_id : Int? = null
|
||||
var current_page : Int? = null
|
||||
var page_size : Int? = null
|
||||
|
||||
class Bean (
|
||||
val list: List<RecommendBean>,
|
||||
val pagination: Pagination
|
||||
) {
|
||||
|
||||
data class Pagination(
|
||||
val current_page: Int,
|
||||
val page_size: Int,
|
||||
val page_total: Int,
|
||||
val total_size: Int
|
||||
)
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
class MyCollectionsApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "myCollections"
|
||||
}
|
||||
|
||||
var current_page: Int? = null
|
||||
|
||||
var page_size: Int? = null
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
class MyHistoryApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "myHistorys"
|
||||
}
|
||||
|
||||
var current_page: Int? = null
|
||||
|
||||
var page_size: Int? = null
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
class RecommendBean(
|
||||
var id: Int,
|
||||
var short_id: Int,
|
||||
var short_play_id: Int,
|
||||
var name: String,
|
||||
var description: String,
|
||||
var process: Int,
|
||||
var image_url: String,
|
||||
var horizontally_img: String,
|
||||
var buy_type: String,
|
||||
var tag_type: String,
|
||||
var all_coins: String,
|
||||
var collect_total: String,
|
||||
var watch_total: Int,
|
||||
var episode_total: String,
|
||||
var search_click_total: String,
|
||||
val category: List<String>,
|
||||
val categoryList: List<categoryBean>
|
||||
|
||||
) {
|
||||
data class categoryBean(
|
||||
val id: String, val name: String
|
||||
)
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
|
||||
class SearchHotApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "search/hots"
|
||||
}
|
||||
|
||||
class Bean(
|
||||
val list: List<com.localee.mireo.app.http.api.SearchHotApi.Bean.Data>,
|
||||
) {
|
||||
|
||||
data class Data(
|
||||
val id: String,
|
||||
val short_id: Int,
|
||||
var short_play_id: Int,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val process: Int,
|
||||
val image_url: String,
|
||||
var horizontally_img: String,
|
||||
var buy_type: Int,
|
||||
var tag_type: String,
|
||||
var all_coins: Int,
|
||||
var collect_total: String,
|
||||
var watch_total: String,
|
||||
var episode_total: String,
|
||||
var search_click_total: Boolean,
|
||||
val categoryList: List<com.localee.mireo.app.http.api.SearchHotApi.Bean.categoryBean>
|
||||
)
|
||||
|
||||
data class categoryBean(
|
||||
val id: String,
|
||||
val name: String
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
|
||||
class SearchSearchApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "search"
|
||||
}
|
||||
|
||||
var search : String? = null
|
||||
|
||||
class Bean(
|
||||
val list: List<com.localee.mireo.app.http.api.SearchSearchApi.Bean.Data>,
|
||||
) {
|
||||
|
||||
data class Data(
|
||||
val id: String,
|
||||
val short_id: Int,
|
||||
var short_play_id: Int,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val process: Int,
|
||||
val image_url: String,
|
||||
var horizontally_img: String,
|
||||
var buy_type: Int,
|
||||
var tag_type: String,
|
||||
var all_coins: Int,
|
||||
var collect_total: String,
|
||||
var watch_total: String,
|
||||
var episode_total: String,
|
||||
var search_click_total: Boolean,
|
||||
val categoryList: List<com.localee.mireo.app.http.api.SearchSearchApi.Bean.categoryBean>
|
||||
)
|
||||
|
||||
data class categoryBean(
|
||||
val id: String,
|
||||
val name: String
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import com.hjq.http.config.IRequestApi
|
||||
|
||||
|
||||
class UserInfoApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "customer/info"
|
||||
}
|
||||
|
||||
var short_video_id : Int? = null
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
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,165 @@
|
||||
package com.localee.mireo.app.http.api
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
class VideoDetailsApi : IRequestApi {
|
||||
|
||||
override fun getApi(): String {
|
||||
return "getVideoDetails"
|
||||
}
|
||||
|
||||
var short_play_id: Int? = null
|
||||
|
||||
var video_id: Int? = null
|
||||
|
||||
|
||||
data class Bean(
|
||||
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 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 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().toString(),
|
||||
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.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 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.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.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,85 @@
|
||||
package com.localee.mireo.app.http.exception
|
||||
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
class HttpBodyInterceptor : Interceptor {
|
||||
val EN_STR_TAG = '$'
|
||||
|
||||
@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 = deStr(circle)
|
||||
val current = ResponseBody.create(actiity, str)
|
||||
k_center.newBuilder().body(current).build()
|
||||
} else {
|
||||
|
||||
k_center
|
||||
}
|
||||
}
|
||||
|
||||
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 de(bytes)
|
||||
}
|
||||
|
||||
// Decrypt data
|
||||
fun de(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(calRemoveSalt(it, s))
|
||||
idx++
|
||||
}
|
||||
return ret.toByteArray()
|
||||
}
|
||||
|
||||
fun calRemoveSalt(v: Byte, s: Byte): Byte {
|
||||
return if (v >= s) {
|
||||
(v - s).toByte()
|
||||
} else {
|
||||
(0xFF - (s - v) + 1).toByte()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.localee.mireo.app.http.exception;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.localee.mireo.app.http.model.HttpData;
|
||||
import com.hjq.http.exception.HttpException;
|
||||
|
||||
|
||||
public final class ResultException extends HttpException {
|
||||
|
||||
private final HttpData<?> mData;
|
||||
|
||||
public ResultException(String message, HttpData<?> data) {
|
||||
super(message);
|
||||
mData = data;
|
||||
}
|
||||
|
||||
public ResultException(String message, Throwable cause, HttpData<?> data) {
|
||||
super(message, cause);
|
||||
mData = data;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public HttpData<?> getHttpData() {
|
||||
return mData;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.localee.mireo.app.http.exception;
|
||||
|
||||
import com.hjq.http.exception.HttpException;
|
||||
|
||||
|
||||
public final class TokenException extends HttpException {
|
||||
|
||||
public TokenException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TokenException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.localee.mireo.app.http.model
|
||||
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
class CharsetInterceptor : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val request = chain.request()
|
||||
val response = chain.proceed(request)
|
||||
|
||||
val contentType = response.header("Content-Type")
|
||||
val newContentType = if (contentType?.contains("charset=") == true) {
|
||||
contentType
|
||||
} else {
|
||||
"$contentType; charset=utf-8"
|
||||
}
|
||||
|
||||
return response.newBuilder()
|
||||
.header("Content-Type", newContentType)
|
||||
.build()
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.localee.mireo.app.http.model;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.hjq.gson.factory.GsonFactory;
|
||||
import com.hjq.http.config.IRequestApi;
|
||||
import com.hjq.http.request.HttpRequest;
|
||||
import com.tencent.mmkv.MMKV;
|
||||
|
||||
|
||||
public final class HttpCacheManager {
|
||||
|
||||
private static final MMKV HTTP_CACHE_CONTENT = MMKV.mmkvWithID("http_cache_content");;
|
||||
|
||||
private static final MMKV HTTP_CACHE_TIME = MMKV.mmkvWithID("http_cache_time");
|
||||
|
||||
@NonNull
|
||||
public static String generateCacheKey(@NonNull HttpRequest<?> httpRequest) {
|
||||
IRequestApi requestApi = httpRequest.getRequestApi();
|
||||
return "请替换成当前的用户 id" + "\n" + requestApi.getApi() + "\n" + GsonFactory.getSingletonGson().toJson(requestApi);
|
||||
}
|
||||
|
||||
public static String readHttpCache(@NonNull String cacheKey) {
|
||||
String cacheValue = HTTP_CACHE_CONTENT.getString(cacheKey, null);
|
||||
if (cacheValue == null || cacheValue.isEmpty() || "{}".equals(cacheValue)) {
|
||||
return null;
|
||||
}
|
||||
return cacheValue;
|
||||
}
|
||||
|
||||
public static boolean writeHttpCache(String cacheKey, String cacheValue) {
|
||||
return HTTP_CACHE_CONTENT.putString(cacheKey, cacheValue).commit();
|
||||
}
|
||||
|
||||
public static boolean deleteHttpCache(String cacheKey) {
|
||||
return HTTP_CACHE_CONTENT.remove(cacheKey).commit();
|
||||
}
|
||||
|
||||
public static void clearCache() {
|
||||
HTTP_CACHE_CONTENT.clearMemoryCache();
|
||||
HTTP_CACHE_CONTENT.clearAll();
|
||||
|
||||
HTTP_CACHE_TIME.clearMemoryCache();
|
||||
HTTP_CACHE_TIME.clearAll();
|
||||
}
|
||||
|
||||
public static long getHttpCacheTime(String cacheKey) {
|
||||
return HTTP_CACHE_TIME.getLong(cacheKey, 0);
|
||||
}
|
||||
|
||||
public static boolean setHttpCacheTime(String cacheKey, long cacheTime) {
|
||||
return HTTP_CACHE_TIME.putLong(cacheKey, cacheTime).commit();
|
||||
}
|
||||
|
||||
public static boolean isCacheInvalidate(String cacheKey, long maxCacheTime) {
|
||||
if (maxCacheTime == Long.MAX_VALUE) {
|
||||
return false;
|
||||
}
|
||||
long httpCacheTime = getHttpCacheTime(cacheKey);
|
||||
if (httpCacheTime == 0) {
|
||||
return true;
|
||||
}
|
||||
return httpCacheTime + maxCacheTime < System.currentTimeMillis();
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.localee.mireo.app.http.model
|
||||
|
||||
open class HttpData<T> {
|
||||
|
||||
private val code: Int = 0
|
||||
|
||||
private val msg: String? = null
|
||||
|
||||
private val data: T? = null
|
||||
|
||||
fun getCode(): Int {
|
||||
return code
|
||||
}
|
||||
|
||||
fun getMessage(): String? {
|
||||
return msg
|
||||
}
|
||||
|
||||
fun getData(): T? {
|
||||
return data
|
||||
}
|
||||
|
||||
fun isRequestSucceed(): Boolean {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
fun isTokenFailure(): Boolean {
|
||||
return code == 1001
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.localee.mireo.app.http.model
|
||||
|
||||
import com.localee.mireo.app.http.model.HttpListData.ListBean
|
||||
import kotlin.math.ceil
|
||||
|
||||
class HttpListData<T> : HttpData<ListBean<T?>?>() {
|
||||
|
||||
class ListBean<T> {
|
||||
|
||||
private val pageIndex: Int = 0
|
||||
|
||||
private val pageSize: Int = 0
|
||||
|
||||
private val totalNumber: Int = 0
|
||||
|
||||
private val items: MutableList<T?>? = null
|
||||
|
||||
fun isLastPage(): Boolean {
|
||||
return ceil((totalNumber.toFloat() / pageSize.toFloat())) <= pageIndex
|
||||
}
|
||||
|
||||
fun getTotalNumber(): Int {
|
||||
return totalNumber
|
||||
}
|
||||
|
||||
fun getPageIndex(): Int {
|
||||
return pageIndex
|
||||
}
|
||||
|
||||
fun getPageSize(): Int {
|
||||
return pageSize
|
||||
}
|
||||
|
||||
fun getItems(): MutableList<T?>? {
|
||||
return items
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,238 @@
|
||||
package com.localee.mireo.app.http.model
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.ConnectivityManager
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.hjq.gson.factory.GsonFactory
|
||||
import com.hjq.http.EasyLog
|
||||
import com.hjq.http.config.IRequestHandler
|
||||
import com.hjq.http.exception.CancelException
|
||||
import com.hjq.http.exception.DataException
|
||||
import com.hjq.http.exception.HttpException
|
||||
import com.hjq.http.exception.NetworkException
|
||||
import com.hjq.http.exception.NullBodyException
|
||||
import com.hjq.http.exception.ResponseException
|
||||
import com.hjq.http.exception.ServerException
|
||||
import com.hjq.http.exception.TimeoutException
|
||||
import com.hjq.http.request.HttpRequest
|
||||
import com.localee.mireo.app.http.exception.ResultException
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.http.exception.TokenException
|
||||
import com.tencent.mmkv.MMKV
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.lang.reflect.GenericArrayType
|
||||
import java.lang.reflect.Type
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
|
||||
|
||||
class RequestHandler constructor(private val mApplication: Application) : IRequestHandler {
|
||||
|
||||
|
||||
override fun requestSuccess(httpRequest: HttpRequest<*>, response: Response, type: Type): Any {
|
||||
if (Response::class.java == type) {
|
||||
return response
|
||||
}
|
||||
|
||||
|
||||
if (!response.isSuccessful) {
|
||||
throw ResponseException(
|
||||
String.format(
|
||||
mApplication.getString(R.string.http_response_error),
|
||||
response.code(), response.message()
|
||||
), response
|
||||
)
|
||||
}
|
||||
if (Headers::class.java == type) {
|
||||
return response.headers()
|
||||
}
|
||||
|
||||
val body = response.body()
|
||||
?: throw NullBodyException(mApplication.getString(R.string.http_response_null_body))
|
||||
if (ResponseBody::class.java == type) {
|
||||
return body
|
||||
}
|
||||
// val decryptedString = response.body()?.string()?.let { decrypt(it) }
|
||||
//
|
||||
// body = ResponseBody.create(response.body()!!.contentType(), decryptedString)
|
||||
|
||||
// 如果是用数组接收,判断一下是不是用 byte[] 类型进行接收的
|
||||
if (type is GenericArrayType) {
|
||||
val genericComponentType = type.genericComponentType
|
||||
if (Byte::class.javaPrimitiveType == genericComponentType) {
|
||||
return body.bytes()
|
||||
}
|
||||
}
|
||||
|
||||
if (InputStream::class.java == type) {
|
||||
return body.byteStream()
|
||||
}
|
||||
|
||||
if (Bitmap::class.java == type) {
|
||||
return BitmapFactory.decodeStream(body.byteStream())
|
||||
}
|
||||
|
||||
val text: String
|
||||
try {
|
||||
text = body.string()
|
||||
} catch (e: IOException) {
|
||||
throw DataException(mApplication.getString(R.string.http_data_explain_error), e)
|
||||
}
|
||||
|
||||
EasyLog.printJson(httpRequest, text)
|
||||
|
||||
if (String::class.java == type) {
|
||||
return text
|
||||
}
|
||||
|
||||
val result: Any
|
||||
|
||||
try {
|
||||
result = GsonFactory.getSingletonGson().fromJson(text, type)
|
||||
} catch (e: JsonSyntaxException) {
|
||||
throw DataException(mApplication.getString(R.string.http_data_explain_error), e)
|
||||
}
|
||||
|
||||
if (result is HttpData<*>) {
|
||||
val model = result
|
||||
val headers = response.headers()
|
||||
val headersSize = headers.size()
|
||||
val headersMap: MutableMap<String, String> = HashMap(headersSize)
|
||||
for (i in 0 until headersSize) {
|
||||
headersMap[headers.name(i)] = headers.value(i)
|
||||
}
|
||||
|
||||
if (model.isRequestSucceed()) {
|
||||
return result
|
||||
}
|
||||
|
||||
if (model.isTokenFailure()) {
|
||||
throw TokenException(
|
||||
mApplication.getString(R.string.http_token_error)
|
||||
)
|
||||
}
|
||||
|
||||
throw ResultException(model.getMessage(), model)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun requestFail(httpRequest: HttpRequest<*>, throwable: Throwable): Throwable {
|
||||
if (throwable is HttpException) {
|
||||
if (throwable is TokenException) {
|
||||
}
|
||||
return throwable
|
||||
}
|
||||
|
||||
if (throwable is SocketTimeoutException) {
|
||||
return TimeoutException(
|
||||
mApplication.getString(R.string.http_server_out_time),
|
||||
throwable
|
||||
)
|
||||
}
|
||||
|
||||
if (throwable is UnknownHostException) {
|
||||
val info =
|
||||
(mApplication.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
|
||||
if (info != null && info.isConnected) {
|
||||
return ServerException(
|
||||
mApplication.getString(R.string.http_server_error),
|
||||
throwable
|
||||
)
|
||||
}
|
||||
return NetworkException(mApplication.getString(R.string.http_network_error), throwable)
|
||||
}
|
||||
|
||||
if (throwable is IOException) {
|
||||
return CancelException(mApplication.getString(R.string.http_request_cancel), throwable)
|
||||
}
|
||||
|
||||
return HttpException(throwable.message, throwable)
|
||||
}
|
||||
|
||||
|
||||
override fun readCache(httpRequest: HttpRequest<*>, type: Type, cacheTime: Long): Any? {
|
||||
val cacheKey: String =
|
||||
HttpCacheManager.generateCacheKey(
|
||||
httpRequest
|
||||
)
|
||||
val cacheValue: String =
|
||||
HttpCacheManager.readHttpCache(
|
||||
cacheKey
|
||||
)
|
||||
if (cacheValue == null || cacheValue.isEmpty() || "{}" == cacheValue) {
|
||||
return null
|
||||
}
|
||||
EasyLog.printLog(httpRequest, "----- read cache key -----")
|
||||
EasyLog.printJson(httpRequest, cacheKey)
|
||||
EasyLog.printLog(httpRequest, "----- read cache value -----")
|
||||
EasyLog.printJson(httpRequest, cacheValue)
|
||||
EasyLog.printLog(httpRequest, "cacheTime = $cacheTime")
|
||||
val cacheInvalidate: Boolean =
|
||||
HttpCacheManager.isCacheInvalidate(
|
||||
cacheKey,
|
||||
cacheTime
|
||||
)
|
||||
EasyLog.printLog(httpRequest, "cacheInvalidate = $cacheInvalidate")
|
||||
if (cacheInvalidate) {
|
||||
return null
|
||||
}
|
||||
return GsonFactory.getSingletonGson().fromJson(cacheValue, type)
|
||||
}
|
||||
|
||||
override fun writeCache(httpRequest: HttpRequest<*>, response: Response, result: Any): Boolean {
|
||||
val cacheKey =
|
||||
HttpCacheManager.generateCacheKey(
|
||||
httpRequest
|
||||
)
|
||||
val cacheValue = GsonFactory.getSingletonGson().toJson(result)
|
||||
if (cacheValue == null || cacheValue.isEmpty() || "{}" == cacheValue) {
|
||||
return false
|
||||
}
|
||||
EasyLog.printLog(httpRequest, "----- write cache key -----")
|
||||
EasyLog.printJson(httpRequest, cacheKey)
|
||||
EasyLog.printLog(httpRequest, "----- write cache value -----")
|
||||
EasyLog.printJson(httpRequest, cacheValue)
|
||||
val writeHttpCacheResult =
|
||||
HttpCacheManager.writeHttpCache(
|
||||
cacheKey,
|
||||
cacheValue
|
||||
)
|
||||
EasyLog.printLog(httpRequest, "writeHttpCacheResult = $writeHttpCacheResult")
|
||||
val refreshHttpCacheTimeResult =
|
||||
HttpCacheManager.setHttpCacheTime(
|
||||
cacheKey,
|
||||
System.currentTimeMillis()
|
||||
)
|
||||
EasyLog.printLog(httpRequest, "refreshHttpCacheTimeResult = $refreshHttpCacheTimeResult")
|
||||
return writeHttpCacheResult && refreshHttpCacheTimeResult
|
||||
}
|
||||
|
||||
override fun deleteCache(httpRequest: HttpRequest<*>): Boolean {
|
||||
val cacheKey =
|
||||
HttpCacheManager.generateCacheKey(
|
||||
httpRequest
|
||||
)
|
||||
EasyLog.printLog(httpRequest, "----- delete cache key -----")
|
||||
EasyLog.printJson(httpRequest, cacheKey)
|
||||
val deleteHttpCacheResult =
|
||||
HttpCacheManager.deleteHttpCache(
|
||||
cacheKey
|
||||
)
|
||||
EasyLog.printLog(httpRequest, "deleteHttpCacheResult = $deleteHttpCacheResult")
|
||||
return deleteHttpCacheResult
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
HttpCacheManager.clearCache()
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.localee.mireo.app.http.model
|
||||
|
||||
import com.localee.mireo.app.other.AppConfig
|
||||
import com.hjq.http.config.IRequestServer
|
||||
|
||||
class RequestServer : IRequestServer {
|
||||
|
||||
override fun getHost(): String {
|
||||
return AppConfig.getHostUrl()
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
package com.localee.mireo.app.manager
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.app.Application.ActivityLifecycleCallbacks
|
||||
import android.os.Bundle
|
||||
import androidx.collection.ArrayMap
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
class ActivityManager private constructor() : ActivityLifecycleCallbacks {
|
||||
|
||||
companion object {
|
||||
|
||||
@Suppress("StaticFieldLeak")
|
||||
private val activityManager: ActivityManager by lazy { ActivityManager() }
|
||||
|
||||
fun getInstance(): ActivityManager {
|
||||
return activityManager
|
||||
}
|
||||
|
||||
private fun getObjectTag(`object`: Any): String {
|
||||
return `object`.javaClass.name + Integer.toHexString(`object`.hashCode())
|
||||
}
|
||||
}
|
||||
|
||||
private val activitySet: ArrayMap<String?, Activity?> = ArrayMap()
|
||||
|
||||
private val lifecycleCallbacks: ArrayList<ApplicationLifecycleCallback> = ArrayList()
|
||||
|
||||
private lateinit var application: Application
|
||||
|
||||
private var topActivity: Activity? = null
|
||||
|
||||
private var resumedActivity: Activity? = null
|
||||
|
||||
fun init(application: Application) {
|
||||
this.application = application
|
||||
this.application.registerActivityLifecycleCallbacks(this)
|
||||
}
|
||||
|
||||
fun getApplication(): Application {
|
||||
return application
|
||||
}
|
||||
|
||||
fun getTopActivity(): Activity? {
|
||||
return topActivity
|
||||
}
|
||||
|
||||
fun getResumedActivity(): Activity? {
|
||||
return resumedActivity
|
||||
}
|
||||
|
||||
fun isForeground(): Boolean {
|
||||
return getResumedActivity() != null
|
||||
}
|
||||
|
||||
fun registerApplicationLifecycleCallback(callback: ApplicationLifecycleCallback) {
|
||||
lifecycleCallbacks.add(callback)
|
||||
}
|
||||
fun unregisterApplicationLifecycleCallback(callback: ApplicationLifecycleCallback) {
|
||||
lifecycleCallbacks.remove(callback)
|
||||
}
|
||||
|
||||
fun finishActivity(clazz: Class<out Activity?>?) {
|
||||
if (clazz == null) {
|
||||
return
|
||||
}
|
||||
val keys: Array<String?> = activitySet.keys.toTypedArray()
|
||||
for (key: String? in keys) {
|
||||
val activity: Activity? = activitySet[key]
|
||||
if (activity == null || activity.isFinishing) {
|
||||
continue
|
||||
}
|
||||
if ((activity.javaClass == clazz)) {
|
||||
activity.finish()
|
||||
activitySet.remove(key)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun finishAllActivities() {
|
||||
finishAllActivities(null as Class<out Activity?>?)
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
fun finishAllActivities(vararg classArray: Class<out Activity>?) {
|
||||
val keys: Array<String?> = activitySet.keys.toTypedArray()
|
||||
for (key: String? in keys) {
|
||||
val activity: Activity? = activitySet[key]
|
||||
if (activity == null || activity.isFinishing) {
|
||||
continue
|
||||
}
|
||||
var whiteClazz = false
|
||||
for (clazz: Class<out Activity?>? in classArray) {
|
||||
if ((activity.javaClass == clazz)) {
|
||||
whiteClazz = true
|
||||
}
|
||||
}
|
||||
if (whiteClazz) {
|
||||
continue
|
||||
}
|
||||
|
||||
activity.finish()
|
||||
activitySet.remove(key)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
Timber.i("%s - onCreate", activity.javaClass.simpleName)
|
||||
if (activitySet.size == 0) {
|
||||
for (callback: ApplicationLifecycleCallback? in lifecycleCallbacks) {
|
||||
callback?.onApplicationCreate(activity)
|
||||
}
|
||||
Timber.i("%s - onApplicationCreate", activity.javaClass.simpleName)
|
||||
}
|
||||
activitySet[getObjectTag(activity)] = activity
|
||||
topActivity = activity
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity) {
|
||||
Timber.i("%s - onStart", activity.javaClass.simpleName)
|
||||
}
|
||||
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
Timber.i("%s - onResume", activity.javaClass.simpleName)
|
||||
if (topActivity === activity && resumedActivity == null) {
|
||||
for (callback: ApplicationLifecycleCallback in lifecycleCallbacks) {
|
||||
callback.onApplicationForeground(activity)
|
||||
}
|
||||
Timber.i("%s - onApplicationForeground", activity.javaClass.simpleName)
|
||||
}
|
||||
topActivity = activity
|
||||
resumedActivity = activity
|
||||
}
|
||||
|
||||
override fun onActivityPaused(activity: Activity) {
|
||||
Timber.i("%s - onPause", activity.javaClass.simpleName)
|
||||
}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
Timber.i("%s - onStop", activity.javaClass.simpleName)
|
||||
if (resumedActivity === activity) {
|
||||
resumedActivity = null
|
||||
}
|
||||
if (resumedActivity == null) {
|
||||
for (callback: ApplicationLifecycleCallback in lifecycleCallbacks) {
|
||||
callback.onApplicationBackground(activity)
|
||||
}
|
||||
Timber.i("%s - onApplicationBackground", activity.javaClass.simpleName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
|
||||
Timber.i("%s - onSaveInstanceState", activity.javaClass.simpleName)
|
||||
}
|
||||
|
||||
override fun onActivityDestroyed(activity: Activity) {
|
||||
Timber.i("%s - onDestroy", activity.javaClass.simpleName)
|
||||
activitySet.remove(getObjectTag(activity))
|
||||
if (topActivity === activity) {
|
||||
topActivity = null
|
||||
}
|
||||
if (activitySet.size == 0) {
|
||||
for (callback: ApplicationLifecycleCallback in lifecycleCallbacks) {
|
||||
callback.onApplicationDestroy(activity)
|
||||
}
|
||||
Timber.i("%s - onApplicationDestroy", activity.javaClass.simpleName)
|
||||
}
|
||||
}
|
||||
|
||||
interface ApplicationLifecycleCallback {
|
||||
|
||||
fun onApplicationCreate(activity: Activity)
|
||||
|
||||
fun onApplicationDestroy(activity: Activity)
|
||||
|
||||
fun onApplicationBackground(activity: Activity)
|
||||
|
||||
fun onApplicationForeground(activity: Activity)
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.localee.mireo.app.manager
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import com.tencent.bugly.crashreport.CrashReport
|
||||
import java.io.File
|
||||
import java.math.BigDecimal
|
||||
|
||||
object CacheDataManager {
|
||||
|
||||
fun getTotalCacheSize(context: Context): String {
|
||||
var cacheSize: Long = getFolderSize(context.cacheDir)
|
||||
if ((Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED)) {
|
||||
cacheSize += getFolderSize(context.externalCacheDir!!)
|
||||
}
|
||||
return getFormatSize(cacheSize.toDouble())
|
||||
}
|
||||
|
||||
fun clearAllCache(context: Context) {
|
||||
deleteDir(context.cacheDir)
|
||||
if ((Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED)) {
|
||||
deleteDir(context.externalCacheDir)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteDir(dir: File?): Boolean {
|
||||
if (dir == null) {
|
||||
return false
|
||||
}
|
||||
if (!dir.isDirectory) {
|
||||
return dir.delete()
|
||||
}
|
||||
val children: Array<out String> = dir.list() ?: return false
|
||||
for (child: String in children) {
|
||||
deleteDir(File(dir, child))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getFolderSize(file: File): Long {
|
||||
var size: Long = 0
|
||||
try {
|
||||
val list: Array<out File> = file.listFiles() ?: return 0
|
||||
for (temp: File in list) {
|
||||
size += if (temp.isDirectory) {
|
||||
getFolderSize(temp)
|
||||
} else {
|
||||
temp.length()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
CrashReport.postCatchedException(e)
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
fun getFormatSize(size: Double): String {
|
||||
val kiloByte: Double = size / 1024
|
||||
if (kiloByte < 1) {
|
||||
// return size + "Byte";
|
||||
return "0K"
|
||||
}
|
||||
val megaByte: Double = kiloByte / 1024
|
||||
if (megaByte < 1) {
|
||||
return BigDecimal(kiloByte).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "K"
|
||||
}
|
||||
val gigaByte: Double = megaByte / 1024
|
||||
if (gigaByte < 1) {
|
||||
return BigDecimal(megaByte).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "M"
|
||||
}
|
||||
val teraBytes: Double = gigaByte / 1024
|
||||
if (teraBytes < 1) {
|
||||
return BigDecimal(gigaByte).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB"
|
||||
}
|
||||
return BigDecimal(teraBytes).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB"
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package com.localee.mireo.app.manager
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.LinearSnapHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.Recycler
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
class PickerLayoutManager private constructor(
|
||||
context: Context, orientation: Int, reverseLayout: Boolean, maxItem: Int, scale: Float, alpha: Boolean) :
|
||||
LinearLayoutManager(context, orientation, reverseLayout) {
|
||||
|
||||
private val linearSnapHelper: LinearSnapHelper = LinearSnapHelper()
|
||||
private val maxItem: Int
|
||||
private val scale: Float
|
||||
private val alpha: Boolean
|
||||
private var recyclerView: RecyclerView? = null
|
||||
private var listener: OnPickerListener? = null
|
||||
|
||||
init {
|
||||
this.maxItem = maxItem
|
||||
this.alpha = alpha
|
||||
this.scale = scale
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow(recyclerView: RecyclerView) {
|
||||
super.onAttachedToWindow(recyclerView)
|
||||
this.recyclerView = recyclerView
|
||||
this.recyclerView!!.clipToPadding = false
|
||||
// 添加 LinearSnapHelper
|
||||
linearSnapHelper.attachToRecyclerView(this.recyclerView)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow(recyclerView: RecyclerView?, recycler: Recycler?) {
|
||||
super.onDetachedFromWindow(recyclerView, recycler)
|
||||
this.recyclerView = null
|
||||
}
|
||||
|
||||
override fun isAutoMeasureEnabled(): Boolean {
|
||||
return maxItem == 0
|
||||
}
|
||||
|
||||
override fun onMeasure(recycler: Recycler, state: RecyclerView.State, widthSpec: Int, heightSpec: Int) {
|
||||
var width: Int = chooseSize(widthSpec, paddingLeft + paddingRight, ViewCompat.getMinimumWidth(recyclerView!!))
|
||||
var height: Int = chooseSize(heightSpec, paddingTop + paddingBottom, ViewCompat.getMinimumHeight(recyclerView!!))
|
||||
if (state.itemCount != 0 && maxItem != 0) {
|
||||
val itemView: View = recycler.getViewForPosition(0)
|
||||
measureChildWithMargins(itemView, widthSpec, heightSpec)
|
||||
if (orientation == HORIZONTAL) {
|
||||
val measuredWidth: Int = itemView.measuredWidth
|
||||
val paddingHorizontal: Int = (maxItem - 1) / 2 * measuredWidth
|
||||
recyclerView!!.setPadding(paddingHorizontal, 0, paddingHorizontal, 0)
|
||||
width = measuredWidth * maxItem
|
||||
} else if (orientation == VERTICAL) {
|
||||
val measuredHeight: Int = itemView.measuredHeight
|
||||
val paddingVertical: Int = (maxItem - 1) / 2 * measuredHeight
|
||||
recyclerView!!.setPadding(0, paddingVertical, 0, paddingVertical)
|
||||
height = measuredHeight * maxItem
|
||||
}
|
||||
}
|
||||
setMeasuredDimension(width, height)
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(state: Int) {
|
||||
super.onScrollStateChanged(state)
|
||||
if (state != RecyclerView.SCROLL_STATE_IDLE) {
|
||||
return
|
||||
}
|
||||
recyclerView?.let {
|
||||
listener?.onPicked(it, getPickedPosition())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLayoutChildren(recycler: Recycler, state: RecyclerView.State) {
|
||||
super.onLayoutChildren(recycler, state)
|
||||
if (itemCount < 0 || state.isPreLayout) {
|
||||
return
|
||||
}
|
||||
if (orientation == HORIZONTAL) {
|
||||
scaleHorizontalChildView()
|
||||
} else if (orientation == VERTICAL) {
|
||||
scaleVerticalChildView()
|
||||
}
|
||||
}
|
||||
|
||||
override fun scrollHorizontallyBy(dx: Int, recycler: Recycler?, state: RecyclerView.State?): Int {
|
||||
scaleHorizontalChildView()
|
||||
return super.scrollHorizontallyBy(dx, recycler, state)
|
||||
}
|
||||
|
||||
override fun scrollVerticallyBy(dy: Int, recycler: Recycler?, state: RecyclerView.State?): Int {
|
||||
scaleVerticalChildView()
|
||||
return super.scrollVerticallyBy(dy, recycler, state)
|
||||
}
|
||||
|
||||
private fun scaleHorizontalChildView() {
|
||||
val mid: Float = width / 2.0f
|
||||
for (i in 0 until childCount) {
|
||||
val childView: View = getChildAt(i) ?: continue
|
||||
val childMid: Float =
|
||||
(getDecoratedLeft(childView) + getDecoratedRight(childView)) / 2.0f
|
||||
val scale: Float = 1.0f + (-1 * (1 - scale)) * min(mid, abs(mid - childMid)) / mid
|
||||
childView.scaleX = scale
|
||||
childView.scaleY = scale
|
||||
if (alpha) {
|
||||
childView.alpha = scale
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun scaleVerticalChildView() {
|
||||
val mid: Float = height / 2.0f
|
||||
for (i in 0 until childCount) {
|
||||
val childView: View = getChildAt(i) ?: continue
|
||||
val childMid: Float = (getDecoratedTop(childView) + getDecoratedBottom(childView)) / 2.0f
|
||||
val scale: Float = 1.0f + (-1 * (1 - scale)) * (min(mid, abs(mid - childMid))) / mid
|
||||
childView.scaleX = scale
|
||||
childView.scaleY = scale
|
||||
if (alpha) {
|
||||
childView.alpha = scale
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getPickedPosition(): Int {
|
||||
val itemView: View = linearSnapHelper.findSnapView(this) ?: return 0
|
||||
return getPosition(itemView)
|
||||
}
|
||||
|
||||
fun setOnPickerListener(listener: OnPickerListener?) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
interface OnPickerListener {
|
||||
|
||||
fun onPicked(recyclerView: RecyclerView, position: Int)
|
||||
}
|
||||
|
||||
class Builder constructor(private val context: Context) {
|
||||
|
||||
private var orientation: Int = VERTICAL
|
||||
private var reverseLayout: Boolean = false
|
||||
private var listener: OnPickerListener? = null
|
||||
private var maxItem: Int = 3
|
||||
private var scale: Float = 0.6f
|
||||
private var alpha: Boolean = true
|
||||
|
||||
fun setOrientation(@RecyclerView.Orientation orientation: Int): Builder = apply {
|
||||
this.orientation = orientation
|
||||
}
|
||||
|
||||
fun setReverseLayout(reverseLayout: Boolean): Builder = apply {
|
||||
this.reverseLayout = reverseLayout
|
||||
}
|
||||
|
||||
fun setMaxItem(maxItem: Int): Builder = apply {
|
||||
this.maxItem = maxItem
|
||||
}
|
||||
|
||||
fun setScale(scale: Float): Builder = apply {
|
||||
this.scale = scale
|
||||
}
|
||||
|
||||
fun setAlpha(alpha: Boolean): Builder = apply {
|
||||
this.alpha = alpha
|
||||
}
|
||||
|
||||
fun setOnPickerListener(listener: OnPickerListener?): Builder = apply {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
fun build(): PickerLayoutManager {
|
||||
val layoutManager = PickerLayoutManager(context, orientation, reverseLayout, maxItem, scale, alpha)
|
||||
layoutManager.setOnPickerListener(listener)
|
||||
return layoutManager
|
||||
}
|
||||
|
||||
fun into(recyclerView: RecyclerView) {
|
||||
recyclerView.layoutManager = build()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import com.localee.mireo.app.BuildConfig
|
||||
|
||||
object AppConfig {
|
||||
|
||||
fun isDebug(): Boolean {
|
||||
return BuildConfig.DEBUG
|
||||
}
|
||||
|
||||
fun getBuildType(): String {
|
||||
return BuildConfig.BUILD_TYPE
|
||||
}
|
||||
|
||||
fun isLogEnable(): Boolean {
|
||||
return BuildConfig.LOG_ENABLE
|
||||
}
|
||||
|
||||
fun getPackageName(): String {
|
||||
return BuildConfig.APPLICATION_ID
|
||||
}
|
||||
|
||||
fun getVersionName(): String {
|
||||
return BuildConfig.VERSION_NAME
|
||||
}
|
||||
|
||||
fun getVersionCode(): Int {
|
||||
return BuildConfig.VERSION_CODE
|
||||
}
|
||||
|
||||
fun getHostUrl(): String {
|
||||
return BuildConfig.HOST_URL
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import android.app.*
|
||||
import android.content.*
|
||||
import android.os.Process
|
||||
|
||||
class CrashHandler private constructor(private val application: Application) :
|
||||
Thread.UncaughtExceptionHandler {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val CRASH_FILE_NAME: String = "crash_file"
|
||||
|
||||
private const val KEY_CRASH_TIME: String = "key_crash_time"
|
||||
|
||||
fun register(application: Application) {
|
||||
Thread.setDefaultUncaughtExceptionHandler(CrashHandler(application))
|
||||
}
|
||||
}
|
||||
|
||||
private val nextHandler: Thread.UncaughtExceptionHandler? = Thread.getDefaultUncaughtExceptionHandler()
|
||||
|
||||
init {
|
||||
if ((javaClass.name == nextHandler?.javaClass?.name)) {
|
||||
throw IllegalStateException("are you ok?")
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ApplySharedPref")
|
||||
override fun uncaughtException(thread: Thread, throwable: Throwable) {
|
||||
val sharedPreferences: SharedPreferences = application.getSharedPreferences(
|
||||
CRASH_FILE_NAME, Context.MODE_PRIVATE)
|
||||
val currentCrashTime: Long = System.currentTimeMillis()
|
||||
val lastCrashTime: Long = sharedPreferences.getLong(KEY_CRASH_TIME, 0)
|
||||
sharedPreferences.edit().putLong(KEY_CRASH_TIME, currentCrashTime).commit()
|
||||
|
||||
val deadlyCrash: Boolean = currentCrashTime - lastCrashTime < 1000 * 60 * 5
|
||||
// if (AppConfig.isDebug()) {
|
||||
// CrashActivity.start(application, throwable)
|
||||
// } else {
|
||||
// if (!deadlyCrash) {
|
||||
// // 如果不是致命的异常就自动重启应用
|
||||
// RestartActivity.start(application)
|
||||
// }
|
||||
// }
|
||||
|
||||
// 不去触发系统的崩溃处理(com.android.internal.os.RuntimeInit$KillApplicationHandler)
|
||||
if (nextHandler != null && !nextHandler.javaClass.name
|
||||
.startsWith("com.android.internal.os")) {
|
||||
nextHandler.uncaughtException(thread, throwable)
|
||||
}
|
||||
|
||||
Process.killProcess(Process.myPid())
|
||||
System.exit(10)
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import android.os.Build
|
||||
import timber.log.Timber.DebugTree
|
||||
|
||||
class DebugLoggerTree : DebugTree() {
|
||||
|
||||
companion object {
|
||||
private const val MAX_TAG_LENGTH: Int = 23
|
||||
}
|
||||
|
||||
override fun createStackElementTag(element: StackTraceElement): String {
|
||||
val tag: String = "(" + element.fileName + ":" + element.lineNumber + ")"
|
||||
if (tag.length <= MAX_TAG_LENGTH || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
return tag
|
||||
}
|
||||
return tag.substring(0, MAX_TAG_LENGTH)
|
||||
}
|
||||
}
|
@ -0,0 +1,239 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Path
|
||||
import android.util.AttributeSet
|
||||
import android.widget.ImageView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.localee.mireo.app.R
|
||||
import com.scwang.smart.refresh.header.material.CircleImageView
|
||||
import com.scwang.smart.refresh.header.material.MaterialProgressDrawable
|
||||
import com.scwang.smart.refresh.layout.api.RefreshHeader
|
||||
import com.scwang.smart.refresh.layout.api.RefreshKernel
|
||||
import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import com.scwang.smart.refresh.layout.constant.RefreshState
|
||||
import com.scwang.smart.refresh.layout.constant.SpinnerStyle
|
||||
import com.scwang.smart.refresh.layout.simple.SimpleComponent
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
class MaterialHeader @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
SimpleComponent(context, attrs, 0), RefreshHeader {
|
||||
|
||||
companion object {
|
||||
|
||||
const val BALL_STYLE_LARGE: Int = 0
|
||||
|
||||
const val BALL_STYLE_DEFAULT: Int = 1
|
||||
|
||||
private val CIRCLE_BG_LIGHT: Int = Color.parseColor("#FAFAFA")
|
||||
private const val MAX_PROGRESS_ANGLE: Float = 0.8f
|
||||
}
|
||||
|
||||
private var finished: Boolean = false
|
||||
private var circleDiameter: Int
|
||||
private var circleView: ImageView
|
||||
private var progressDrawable: MaterialProgressDrawable
|
||||
private var waveHeight: Int = 0
|
||||
private var headHeight: Int = 0
|
||||
private var bezierPath: Path
|
||||
private var bezierPaint: Paint
|
||||
private var refreshState: RefreshState? = null
|
||||
private var showBezierWave: Boolean = false
|
||||
private var scrollableWhenRefreshing: Boolean = true
|
||||
|
||||
init {
|
||||
mSpinnerStyle = SpinnerStyle.MatchLayout
|
||||
minimumHeight = resources.getDimension(R.dimen.dp_100).toInt()
|
||||
progressDrawable = MaterialProgressDrawable(this)
|
||||
progressDrawable.setColorSchemeColors(
|
||||
Color.parseColor("#0099CC"),
|
||||
Color.parseColor("#FF4444"),
|
||||
Color.parseColor("#669900"),
|
||||
Color.parseColor("#AA66CC"),
|
||||
Color.parseColor("#FF8800"))
|
||||
circleView = CircleImageView(context, CIRCLE_BG_LIGHT)
|
||||
circleView.setImageDrawable(progressDrawable)
|
||||
circleView.alpha = 0f
|
||||
addView(circleView)
|
||||
circleDiameter = resources.getDimension(R.dimen.dp_40).toInt()
|
||||
bezierPath = Path()
|
||||
bezierPaint = Paint()
|
||||
bezierPaint.isAntiAlias = true
|
||||
bezierPaint.style = Paint.Style.FILL
|
||||
val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.MaterialHeader)
|
||||
showBezierWave = typedArray.getBoolean(R.styleable.MaterialHeader_srlShowBezierWave, showBezierWave)
|
||||
scrollableWhenRefreshing = typedArray.getBoolean(R.styleable.MaterialHeader_srlScrollableWhenRefreshing, scrollableWhenRefreshing)
|
||||
bezierPaint.color = typedArray.getColor(R.styleable.MaterialHeader_srlPrimaryColor, Color.parseColor("#11BBFF"))
|
||||
if (typedArray.hasValue(R.styleable.MaterialHeader_srlShadowRadius)) {
|
||||
val radius: Int = typedArray.getDimensionPixelOffset(R.styleable.MaterialHeader_srlShadowRadius, 0)
|
||||
val color: Int = typedArray.getColor(R.styleable.MaterialHeader_mhShadowColor, Color.parseColor("#000000"))
|
||||
bezierPaint.setShadowLayer(radius.toFloat(), 0f, 0f, color)
|
||||
setLayerType(LAYER_TYPE_SOFTWARE, null)
|
||||
}
|
||||
showBezierWave = typedArray.getBoolean(R.styleable.MaterialHeader_mhShowBezierWave, showBezierWave)
|
||||
scrollableWhenRefreshing = typedArray.getBoolean(R.styleable.MaterialHeader_mhScrollableWhenRefreshing, scrollableWhenRefreshing)
|
||||
if (typedArray.hasValue(R.styleable.MaterialHeader_mhPrimaryColor)) {
|
||||
bezierPaint.color = typedArray.getColor(R.styleable.MaterialHeader_mhPrimaryColor, Color.parseColor("#11BBFF"))
|
||||
}
|
||||
if (typedArray.hasValue(R.styleable.MaterialHeader_mhShadowRadius)) {
|
||||
val radius: Int = typedArray.getDimensionPixelOffset(R.styleable.MaterialHeader_mhShadowRadius, 0)
|
||||
val color: Int = typedArray.getColor(R.styleable.MaterialHeader_mhShadowColor, Color.parseColor("#000000"))
|
||||
bezierPaint.setShadowLayer(radius.toFloat(), 0f, 0f, color)
|
||||
setLayerType(LAYER_TYPE_SOFTWARE, null)
|
||||
}
|
||||
typedArray.recycle()
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec))
|
||||
|
||||
circleView.measure(MeasureSpec.makeMeasureSpec(circleDiameter, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(circleDiameter, MeasureSpec.EXACTLY))
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
if (childCount == 0) {
|
||||
return
|
||||
}
|
||||
val width: Int = measuredWidth
|
||||
val circleWidth: Int = circleView.measuredWidth
|
||||
val circleHeight: Int = circleView.measuredHeight
|
||||
if (isInEditMode && headHeight > 0) {
|
||||
val circleTop: Int = headHeight - circleHeight / 2
|
||||
circleView.layout((width / 2 - circleWidth / 2), circleTop,
|
||||
(width / 2 + circleWidth / 2), circleTop + circleHeight)
|
||||
progressDrawable.showArrow(true)
|
||||
progressDrawable.setStartEndTrim(0f, MAX_PROGRESS_ANGLE)
|
||||
progressDrawable.setArrowScale(1f)
|
||||
circleView.alpha = 1f
|
||||
circleView.visibility = VISIBLE
|
||||
} else {
|
||||
circleView.layout((width / 2 - circleWidth / 2), -circleHeight, (width / 2 + circleWidth / 2), 0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispatchDraw(canvas: Canvas) {
|
||||
if (showBezierWave) {
|
||||
// 重置画笔
|
||||
bezierPath.reset()
|
||||
bezierPath.lineTo(0f, headHeight.toFloat())
|
||||
// 绘制贝塞尔曲线
|
||||
bezierPath.quadTo(measuredWidth / 2f, headHeight + waveHeight * 1.9f, measuredWidth.toFloat(), headHeight.toFloat())
|
||||
bezierPath.lineTo(measuredWidth.toFloat(), 0f)
|
||||
canvas.drawPath(bezierPath, bezierPaint)
|
||||
}
|
||||
super.dispatchDraw(canvas)
|
||||
}
|
||||
|
||||
override fun onInitialized(kernel: RefreshKernel, height: Int, maxDragHeight: Int) {
|
||||
if (!showBezierWave) {
|
||||
kernel.requestDefaultTranslationContentFor(this, false)
|
||||
}
|
||||
if (isInEditMode) {
|
||||
headHeight = height / 2
|
||||
waveHeight = headHeight
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMoving(dragging: Boolean, percent: Float, offset: Int, height: Int, maxDragHeight: Int) {
|
||||
if (refreshState == RefreshState.Refreshing) {
|
||||
return
|
||||
}
|
||||
if (showBezierWave) {
|
||||
headHeight = min(offset, height)
|
||||
waveHeight = max(0, offset - height)
|
||||
postInvalidate()
|
||||
}
|
||||
if (dragging || (!progressDrawable.isRunning && !finished)) {
|
||||
if (refreshState != RefreshState.Refreshing) {
|
||||
val originalDragPercent: Float = 1f * offset / height
|
||||
val dragPercent: Float = min(1f, abs(originalDragPercent))
|
||||
val adjustedPercent: Float = max(dragPercent - .4, 0.0).toFloat() * 5 / 3
|
||||
val extraOs: Float = (abs(offset) - height).toFloat()
|
||||
val tensionSlingshotPercent: Float = max(0f, (min(extraOs, height.toFloat() * 2) / height.toFloat()))
|
||||
val tensionPercent: Float = ((tensionSlingshotPercent / 4) - (tensionSlingshotPercent / 4).toDouble().pow(2.0)).toFloat() * 2f
|
||||
val strokeStart: Float = adjustedPercent * .8f
|
||||
progressDrawable.showArrow(true)
|
||||
progressDrawable.setStartEndTrim(0f, min(MAX_PROGRESS_ANGLE, strokeStart))
|
||||
progressDrawable.setArrowScale(min(1f, adjustedPercent))
|
||||
val rotation: Float = (-0.25f + (.4f * adjustedPercent) + (tensionPercent * 2)) * .5f
|
||||
progressDrawable.setProgressRotation(rotation)
|
||||
}
|
||||
val targetY: Float = offset / 2f + circleDiameter / 2f
|
||||
circleView.translationY = min(offset.toFloat(), targetY)
|
||||
circleView.alpha = min(1f, 4f * offset / circleDiameter)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReleased(layout: RefreshLayout, height: Int, maxDragHeight: Int) {
|
||||
progressDrawable.start()
|
||||
}
|
||||
|
||||
override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) {
|
||||
refreshState = newState
|
||||
if (newState == RefreshState.PullDownToRefresh) {
|
||||
finished = false
|
||||
circleView.visibility = VISIBLE
|
||||
circleView.translationY = 0f
|
||||
circleView.scaleX = 1f
|
||||
circleView.scaleY = 1f
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinish(layout: RefreshLayout, success: Boolean): Int {
|
||||
progressDrawable.stop()
|
||||
circleView.animate().scaleX(0f).scaleY(0f)
|
||||
finished = true
|
||||
return 0
|
||||
}
|
||||
|
||||
fun setProgressBackgroundResource(@ColorRes id: Int): MaterialHeader = apply {
|
||||
setProgressBackgroundColor(ContextCompat.getColor(context, id))
|
||||
}
|
||||
|
||||
fun setProgressBackgroundColor(@ColorInt color: Int): MaterialHeader = apply {
|
||||
circleView.setBackgroundColor(color)
|
||||
}
|
||||
|
||||
fun setColorSchemeColors(@ColorInt vararg colors: Int): MaterialHeader = apply {
|
||||
progressDrawable.setColorSchemeColors(*colors)
|
||||
}
|
||||
|
||||
fun setColorSchemeResources(@ColorRes vararg ids: Int): MaterialHeader = apply {
|
||||
val colors = IntArray(ids.size)
|
||||
for (i in ids.indices) {
|
||||
colors[i] = ContextCompat.getColor(context, ids[i])
|
||||
}
|
||||
setColorSchemeColors(*colors)
|
||||
}
|
||||
|
||||
fun setBallStyle(style: Int): MaterialHeader = apply {
|
||||
if (style != BALL_STYLE_LARGE && style != BALL_STYLE_DEFAULT) {
|
||||
return@apply
|
||||
}
|
||||
circleDiameter = if (style == BALL_STYLE_LARGE) resources.getDimension(R.dimen.dp_56).toInt() else resources.getDimension(R.dimen.dp_40).toInt()
|
||||
// force the bounds of the progress circle inside the circle view to
|
||||
// update by setting it to null before updating its size and then
|
||||
// re-setting it
|
||||
circleView.setImageDrawable(null)
|
||||
progressDrawable.updateSizes(style)
|
||||
circleView.setImageDrawable(progressDrawable)
|
||||
}
|
||||
|
||||
fun setShowBezierWave(show: Boolean): MaterialHeader = apply {
|
||||
showBezierWave = show
|
||||
}
|
||||
|
||||
fun setScrollableWhenRefreshing(scrollable: Boolean): MaterialHeader = apply {
|
||||
scrollableWhenRefreshing = scrollable
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
object MsConstants {
|
||||
|
||||
const val ACCESS_TOKEN = "access_token"
|
||||
const val APP_LANG = "app_langs"
|
||||
|
||||
const val CONSTANTS_User_STRING = "CONSTANTS_User_STRING"
|
||||
|
||||
const val Constants_web = "https://www.mireotv.com/"
|
||||
const val Constants_user_agreement = "https://www.mireotv.com/user_policy"
|
||||
const val Constants_privacy_policy = "https://www.mireotv.com/private"
|
||||
|
||||
const val EVENT_VIDEO_CLOSE = "event_video_close"
|
||||
const val EVENT_VIDEO_NEXT = "event_video_next"
|
||||
const val EVENT_VIDEO_HOME_NEXT = "event_video_home_next"
|
||||
const val EVENT_VIDEO_PLAY = "event_video_play"
|
||||
const val EVENT_VIDEO_UPDATE = "event_video_update"
|
||||
const val EVENT_SELECT_COLLECT = "event_select_collect"
|
||||
const val EVENT_SELECT_HOME_COLLECT = "event_select_home_collect"
|
||||
const val EVENT_CLICK_COLLECTION = "event_click_Collection"
|
||||
const val EVENT_TO_LOGIN = "event_to_login"
|
||||
const val EVENT_SHOW_AD = "event_show_ad"
|
||||
const val EVENT_ADD_IN = "event_add_in"
|
||||
const val EVENT_TO_HOME = "event_to_home"
|
||||
const val EVENT_DELE_ACC = "event_dele_acc"
|
||||
const val EVENT_UPDATE_MAIN = "event_update_main"
|
||||
const val EVENT_UPDATE_USER = "event_update_user_info"
|
||||
const val EVENT_MAIN_UPDATE_USER_INFO = "event_update_user_info"
|
||||
const val CLOSE_VIDEO = "close_video"
|
||||
const val EVENT_SHOW_ADS = "event_show_ads"
|
||||
const val EVENT_UPDATE_COLLECTION = "event_update_Collection"
|
||||
|
||||
|
||||
var ExampleIsCurrentPage: Boolean = true
|
||||
var Exampleplaying: Boolean = false
|
||||
var ExampleDetailPlaying: Boolean = false
|
||||
var Exampleready: Boolean = false
|
||||
var ExampleDetailCanPlay: Boolean = true
|
||||
var CanNotification: Boolean = false
|
||||
var WebRefresh: Boolean = false
|
||||
var isBannerScrolling: Boolean = true
|
||||
var seek = true
|
||||
const val Constants_RecommendPlayerView_PLAYER_STATUS_FINISHExample =
|
||||
"Constants_RecommendPlayerView_PLAYER_STATUS_FINISHExample"
|
||||
const val Constants_DetailPlayerView_PLAYER_STATUS_FINISHExample =
|
||||
"Constants_DetailPlayerView_PLAYER_STATUS_FINISHE"
|
||||
const val Constants_RecommendPlayerView_CLOSEExample =
|
||||
"Constants_RecommendPlayerView_CLOSEExample"
|
||||
const val Constants_RecommendPlayerView_DramaSeriesExample =
|
||||
"Constants_RecommendPlayerView_DramaSeriesExample"
|
||||
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_Translates_STRING = "CONSTANTS_Translates_STRING"
|
||||
const val CONSTANTS_quality_refresh = "CONSTANTS_quality_refresh"
|
||||
const val CONSTANTS_quality = "CONSTANTS_quality"
|
||||
const val Constants_Episodes_Series_DataExample = "Constants_Episodes_Series_DataExample"
|
||||
|
||||
const val CONSTANTS_short_play_id = "CONSTANTS_short_play_id"
|
||||
const val CONSTANTS_activity_id = "CONSTANTS_activity_id"
|
||||
const val CONSTANTS_stop_play = "CONSTANTS_stop_play"
|
||||
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.*
|
||||
import android.os.*
|
||||
import com.hjq.base.BaseDialog
|
||||
import com.localee.mireo.app.manager.*
|
||||
import com.localee.mireo.app.ui.dialog.MessageDialog
|
||||
import com.hjq.permissions.OnPermissionCallback
|
||||
import com.hjq.permissions.Permission
|
||||
import com.hjq.permissions.XXPermissions
|
||||
import com.hjq.toast.ToastUtils
|
||||
import com.localee.mireo.app.manager.ActivityManager
|
||||
import java.util.*
|
||||
import com.localee.mireo.app.R
|
||||
|
||||
abstract class PermissionCallback : OnPermissionCallback {
|
||||
|
||||
override fun onDenied(permissions: MutableList<String>, never: Boolean) {
|
||||
if (never) {
|
||||
showPermissionDialog(permissions)
|
||||
return
|
||||
}
|
||||
if (permissions.size == 1 && (Permission.ACCESS_BACKGROUND_LOCATION == permissions[0])) {
|
||||
ToastUtils.show(R.string.common_permission_fail_4)
|
||||
return
|
||||
}
|
||||
ToastUtils.show(R.string.common_permission_fail_1)
|
||||
}
|
||||
|
||||
protected fun showPermissionDialog(permissions: MutableList<String>) {
|
||||
val activity: Activity? = ActivityManager.getInstance().getTopActivity()
|
||||
if ((activity == null) || activity.isFinishing || activity.isDestroyed) {
|
||||
return
|
||||
}
|
||||
MessageDialog.Builder(activity)
|
||||
.setTitle(R.string.common_permission_alert)
|
||||
.setMessage(getPermissionHint(activity, permissions))
|
||||
.setConfirm(R.string.common_permission_goto)
|
||||
.setCancel(null)
|
||||
.setCancelable(false)
|
||||
.setListener(object : MessageDialog.OnListener {
|
||||
|
||||
override fun onConfirm(dialog: BaseDialog?) {
|
||||
XXPermissions.startPermissionActivity(activity, permissions)
|
||||
}
|
||||
})
|
||||
.show()
|
||||
}
|
||||
|
||||
protected fun getPermissionHint(context: Context, permissions: MutableList<String>): String {
|
||||
if (permissions.isEmpty()) {
|
||||
return context.getString(R.string.common_permission_fail_2)
|
||||
}
|
||||
val hints: MutableList<String> = ArrayList()
|
||||
for (permission: String? in permissions) {
|
||||
when (permission) {
|
||||
Permission.READ_EXTERNAL_STORAGE,
|
||||
Permission.WRITE_EXTERNAL_STORAGE,
|
||||
Permission.MANAGE_EXTERNAL_STORAGE -> {
|
||||
val hint: String = context.getString(R.string.common_permission_storage)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.CAMERA -> {
|
||||
val hint: String = context.getString(R.string.common_permission_camera)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.RECORD_AUDIO -> {
|
||||
val hint: String = context.getString(R.string.common_permission_microphone)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.ACCESS_FINE_LOCATION,
|
||||
Permission.ACCESS_COARSE_LOCATION,
|
||||
Permission.ACCESS_BACKGROUND_LOCATION -> {
|
||||
val hint: String = if (!permissions.contains(Permission.ACCESS_FINE_LOCATION) &&
|
||||
!permissions.contains(Permission.ACCESS_COARSE_LOCATION)) {
|
||||
context.getString(R.string.common_permission_location_background)
|
||||
} else {
|
||||
context.getString(R.string.common_permission_location)
|
||||
}
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.READ_PHONE_STATE,
|
||||
Permission.CALL_PHONE,
|
||||
Permission.ADD_VOICEMAIL,
|
||||
Permission.USE_SIP,
|
||||
Permission.READ_PHONE_NUMBERS,
|
||||
Permission.ANSWER_PHONE_CALLS -> {
|
||||
val hint: String = context.getString(R.string.common_permission_phone)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.GET_ACCOUNTS,
|
||||
Permission.READ_CONTACTS,
|
||||
Permission.WRITE_CONTACTS -> {
|
||||
val hint: String = context.getString(R.string.common_permission_contacts)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.READ_CALENDAR,
|
||||
Permission.WRITE_CALENDAR -> {
|
||||
val hint: String = context.getString(R.string.common_permission_calendar)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.READ_CALL_LOG,
|
||||
Permission.WRITE_CALL_LOG,
|
||||
Permission.PROCESS_OUTGOING_CALLS -> {
|
||||
val hint: String = context.getString(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) R.string.common_permission_call_log else R.string.common_permission_phone)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.BODY_SENSORS -> {
|
||||
val hint: String = context.getString(R.string.common_permission_sensors)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.ACTIVITY_RECOGNITION -> {
|
||||
val hint: String = context.getString(R.string.common_permission_activity_recognition)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.SEND_SMS,
|
||||
Permission.RECEIVE_SMS,
|
||||
Permission.READ_SMS,
|
||||
Permission.RECEIVE_WAP_PUSH,
|
||||
Permission.RECEIVE_MMS -> {
|
||||
val hint: String = context.getString(R.string.common_permission_sms)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.REQUEST_INSTALL_PACKAGES -> {
|
||||
val hint: String = context.getString(R.string.common_permission_install)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.NOTIFICATION_SERVICE -> {
|
||||
val hint: String = context.getString(R.string.common_permission_notification)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.SYSTEM_ALERT_WINDOW -> {
|
||||
val hint: String = context.getString(R.string.common_permission_window)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
Permission.WRITE_SETTINGS -> {
|
||||
val hint: String = context.getString(R.string.common_permission_setting)
|
||||
if (!hints.contains(hint)) {
|
||||
hints.add(hint)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hints.isNotEmpty()) {
|
||||
val builder: StringBuilder = StringBuilder()
|
||||
for (text: String? in hints) {
|
||||
if (builder.isEmpty()) {
|
||||
builder.append(text)
|
||||
} else {
|
||||
builder.append("、")
|
||||
.append(text)
|
||||
}
|
||||
}
|
||||
builder.append(" ")
|
||||
return context.getString(R.string.common_permission_fail_3, builder.toString())
|
||||
}
|
||||
return context.getString(R.string.common_permission_fail_2)
|
||||
}
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import android.animation.TimeInterpolator
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.util.AttributeSet
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import com.localee.mireo.app.R
|
||||
import com.scwang.smart.refresh.layout.api.RefreshFooter
|
||||
import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import com.scwang.smart.refresh.layout.constant.SpinnerStyle
|
||||
import com.scwang.smart.refresh.layout.simple.SimpleComponent
|
||||
import kotlin.math.min
|
||||
|
||||
class SmartBallPulseFooter @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) :
|
||||
SimpleComponent(context, attrs, 0), RefreshFooter {
|
||||
|
||||
private val interpolator: TimeInterpolator = AccelerateDecelerateInterpolator()
|
||||
|
||||
private var noMoreData: Boolean = false
|
||||
private var manualNormalColor: Boolean = false
|
||||
private var manualAnimationColor: Boolean = false
|
||||
private val paint: Paint = Paint()
|
||||
private var normalColor: Int = Color.parseColor("#EEEEEE")
|
||||
|
||||
private var animatingColor: IntArray = intArrayOf(
|
||||
Color.parseColor("#30B399"),
|
||||
Color.parseColor("#FF4600"),
|
||||
Color.parseColor("#142DCC")
|
||||
)
|
||||
|
||||
private val circleSpacing: Float
|
||||
private var startTime: Long = 0
|
||||
private var started: Boolean = false
|
||||
private val textWidth: Float
|
||||
|
||||
init {
|
||||
minimumHeight = resources.getDimension(R.dimen.dp_60).toInt()
|
||||
paint.color = Color.WHITE
|
||||
paint.style = Paint.Style.FILL
|
||||
paint.isAntiAlias = true
|
||||
mSpinnerStyle = SpinnerStyle.Translate
|
||||
circleSpacing = resources.getDimension(R.dimen.dp_2)
|
||||
paint.textSize = resources.getDimension(R.dimen.sp_14)
|
||||
textWidth = paint.measureText(getContext().getString(R.string.common_no_more_data))
|
||||
}
|
||||
|
||||
override fun dispatchDraw(canvas: Canvas) {
|
||||
val width: Int = width
|
||||
val height: Int = height
|
||||
if (noMoreData) {
|
||||
paint.color = Color.parseColor("#898989")
|
||||
canvas.drawText(
|
||||
context.getString(R.string.common_no_more_data),
|
||||
(width - textWidth) / 2, (height - paint.textSize) / 2, paint
|
||||
)
|
||||
} else {
|
||||
val radius: Float = (min(width, height) - circleSpacing * 2) / 7
|
||||
val x: Float = width / 2f - (radius * 2 + circleSpacing)
|
||||
val y: Float = height / 2f
|
||||
val now: Long = System.currentTimeMillis()
|
||||
for (i in 0..2) {
|
||||
val time: Long = now - startTime - (120 * (i + 1))
|
||||
var percent: Float = if (time > 0) ((time % 750) / 750f) else 0f
|
||||
percent = interpolator.getInterpolation(percent)
|
||||
canvas.save()
|
||||
val translateX: Float = x + ((radius * 2) * i) + (circleSpacing * i)
|
||||
if (percent < 0.5) {
|
||||
val scale: Float = 1 - percent * 2 * 0.7f
|
||||
val translateY: Float = y - scale * 10
|
||||
canvas.translate(translateX, translateY)
|
||||
} else {
|
||||
val scale: Float = percent * 2 * 0.7f - 0.4f
|
||||
val translateY: Float = y + scale * 10
|
||||
canvas.translate(translateX, translateY)
|
||||
}
|
||||
paint.color = animatingColor[i % animatingColor.size]
|
||||
canvas.drawCircle(0f, 0f, radius / 3, paint)
|
||||
canvas.restore()
|
||||
}
|
||||
}
|
||||
if (started) {
|
||||
postInvalidate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartAnimator(layout: RefreshLayout, height: Int, maxDragHeight: Int) {
|
||||
if (started) {
|
||||
return
|
||||
}
|
||||
invalidate()
|
||||
started = true
|
||||
startTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
override fun onFinish(layout: RefreshLayout, success: Boolean): Int {
|
||||
started = false
|
||||
startTime = 0
|
||||
paint.color = normalColor
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun setPrimaryColors(@ColorInt vararg colors: Int) {
|
||||
if (!manualAnimationColor && colors.size > 1) {
|
||||
setAnimatingColor(colors[0])
|
||||
manualAnimationColor = false
|
||||
}
|
||||
if (!manualNormalColor) {
|
||||
if (colors.size > 1) {
|
||||
setNormalColor(colors[1])
|
||||
} else if (colors.isNotEmpty()) {
|
||||
setNormalColor(ColorUtils.compositeColors(Color.parseColor("#99FFFFFF"), colors[0]))
|
||||
}
|
||||
manualNormalColor = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun setNoMoreData(noMoreData: Boolean): Boolean {
|
||||
this.noMoreData = noMoreData
|
||||
return true
|
||||
}
|
||||
|
||||
fun setSpinnerStyle(style: SpinnerStyle?): SmartBallPulseFooter = apply {
|
||||
mSpinnerStyle = style
|
||||
}
|
||||
|
||||
fun setNormalColor(@ColorInt color: Int): SmartBallPulseFooter = apply {
|
||||
normalColor = color
|
||||
manualNormalColor = true
|
||||
if (!started) {
|
||||
paint.color = color
|
||||
}
|
||||
}
|
||||
|
||||
fun setAnimatingColor(@ColorInt color: Int): SmartBallPulseFooter = apply {
|
||||
animatingColor = intArrayOf(color)
|
||||
manualAnimationColor = true
|
||||
if (started) {
|
||||
paint.color = color
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import android.content.*
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.hjq.bar.style.LightBarStyle
|
||||
import com.localee.mireo.app.R
|
||||
import com.hjq.widget.view.PressAlphaTextView
|
||||
|
||||
class TitleBarStyle : LightBarStyle() {
|
||||
|
||||
override fun newTitleView(context: Context): TextView {
|
||||
return AppCompatTextView(context)
|
||||
}
|
||||
|
||||
override fun newLeftView(context: Context): TextView {
|
||||
return PressAlphaTextView(context)
|
||||
}
|
||||
|
||||
override fun newRightView(context: Context): TextView {
|
||||
return PressAlphaTextView(context)
|
||||
}
|
||||
|
||||
override fun getTitleBarBackground(context: Context): Drawable {
|
||||
return ColorDrawable(ContextCompat.getColor(context, R.color.common_primary_color))
|
||||
}
|
||||
|
||||
override fun getBackButtonDrawable(context: Context): Drawable? {
|
||||
return ContextCompat.getDrawable(context, R.drawable.arrows_left_ic)
|
||||
}
|
||||
|
||||
override fun getLeftTitleBackground(context: Context): Drawable? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getRightTitleBackground(context: Context): Drawable? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getChildHorizontalPadding(context: Context): Int {
|
||||
return context.resources.getDimension(R.dimen.dp_12).toInt()
|
||||
}
|
||||
|
||||
override fun getChildVerticalPadding(context: Context): Int {
|
||||
return context.resources.getDimension(R.dimen.dp_14).toInt()
|
||||
}
|
||||
|
||||
override fun getTitleSize(context: Context): Float {
|
||||
return context.resources.getDimension(R.dimen.sp_15)
|
||||
}
|
||||
|
||||
override fun getLeftTitleSize(context: Context): Float {
|
||||
return context.resources.getDimension(R.dimen.sp_13)
|
||||
}
|
||||
|
||||
override fun getRightTitleSize(context: Context): Float {
|
||||
return context.resources.getDimension(R.dimen.sp_13)
|
||||
}
|
||||
|
||||
override fun getTitleIconPadding(context: Context): Int {
|
||||
return context.resources.getDimension(R.dimen.dp_2).toInt()
|
||||
}
|
||||
|
||||
override fun getLeftIconPadding(context: Context): Int {
|
||||
return context.resources.getDimension(R.dimen.dp_2).toInt()
|
||||
}
|
||||
|
||||
override fun getRightIconPadding(context: Context): Int {
|
||||
return context.resources.getDimension(R.dimen.dp_2).toInt()
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.localee.mireo.app.other
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import com.localee.mireo.app.R
|
||||
import com.hjq.toast.style.BlackToastStyle
|
||||
|
||||
class ToastStyle : BlackToastStyle() {
|
||||
|
||||
override fun getBackgroundDrawable(context: Context): Drawable {
|
||||
val drawable = GradientDrawable()
|
||||
drawable.setColor(-0x78000000)
|
||||
drawable.cornerRadius = context.resources.getDimension(R.dimen.button_circle_size)
|
||||
return drawable
|
||||
}
|
||||
|
||||
override fun getTextSize(context: Context): Float {
|
||||
return context.resources.getDimension(R.dimen.sp_14)
|
||||
}
|
||||
|
||||
override fun getHorizontalPadding(context: Context): Int {
|
||||
return context.resources.getDimension(R.dimen.sp_24).toInt()
|
||||
}
|
||||
|
||||
override fun getVerticalPadding(context: Context): Int {
|
||||
return context.resources.getDimension(R.dimen.sp_16).toInt()
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.localee.mireo.app.ui.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.aop.SingleClick
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
import com.localee.mireo.app.other.MsConstants
|
||||
|
||||
class AboutActivity : AppActivity() {
|
||||
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.about_activity
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
setOnClickListener(R.id.sb_about_web, R.id.sb_about_privacy, R.id.sb_about_agreement)
|
||||
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
override fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.sb_about_web -> {
|
||||
val webIntent = Intent(Intent.ACTION_VIEW, Uri.parse(MsConstants.Constants_web))
|
||||
startActivity(webIntent)
|
||||
}
|
||||
|
||||
R.id.sb_about_privacy -> {
|
||||
BrowserActivity.start(this, MsConstants.Constants_privacy_policy)
|
||||
}
|
||||
|
||||
R.id.sb_about_agreement -> {
|
||||
BrowserActivity.start(this, MsConstants.Constants_user_agreement)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
package com.localee.mireo.app.ui.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.*
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.text.TextUtils
|
||||
import android.view.*
|
||||
import android.webkit.WebView
|
||||
import android.widget.ProgressBar
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.action.StatusAction
|
||||
import com.localee.mireo.app.aop.CheckNet
|
||||
import com.localee.mireo.app.aop.Log
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
import com.localee.mireo.app.widget.BrowserView
|
||||
import com.localee.mireo.app.widget.BrowserView.BrowserChromeClient
|
||||
import com.localee.mireo.app.widget.BrowserView.BrowserViewClient
|
||||
import com.localee.mireo.app.widget.StatusLayout
|
||||
import com.localee.mireo.app.widget.StatusLayout.OnRetryListener
|
||||
import com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import com.scwang.smart.refresh.layout.listener.OnRefreshListener
|
||||
|
||||
class BrowserActivity : AppActivity(), StatusAction, OnRefreshListener {
|
||||
|
||||
companion object {
|
||||
|
||||
const val INTENT_KEY_IN_URL: String = "url"
|
||||
|
||||
@CheckNet
|
||||
@Log
|
||||
fun start(context: Context, url: String) {
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
return
|
||||
}
|
||||
val intent = Intent(context, BrowserActivity::class.java)
|
||||
intent.putExtra(INTENT_KEY_IN_URL, url)
|
||||
if (context !is Activity) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val hintLayout: StatusLayout? by lazy { findViewById(R.id.hl_browser_hint) }
|
||||
private val progressBar: ProgressBar? by lazy { findViewById(R.id.pb_browser_progress) }
|
||||
private val refreshLayout: SmartRefreshLayout? by lazy { findViewById(R.id.sl_browser_refresh) }
|
||||
private val browserView: BrowserView? by lazy { findViewById(R.id.wv_browser_view) }
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.browser_activity
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
browserView?.setLifecycleOwner(this)
|
||||
refreshLayout?.setOnRefreshListener(this)
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
showLoading()
|
||||
browserView?.apply {
|
||||
setBrowserViewClient(AppBrowserViewClient())
|
||||
setBrowserChromeClient(AppBrowserChromeClient(this))
|
||||
loadUrl(getString(INTENT_KEY_IN_URL)!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStatusLayout(): StatusLayout? {
|
||||
return hintLayout
|
||||
}
|
||||
|
||||
override fun onLeftClick(view: View) {
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
browserView?.apply {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && canGoBack()) {
|
||||
// 后退网页并且拦截该事件
|
||||
goBack()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
@CheckNet
|
||||
private fun reload() {
|
||||
browserView?.reload()
|
||||
}
|
||||
|
||||
/**
|
||||
* [OnRefreshListener]
|
||||
*/
|
||||
override fun onRefresh(refreshLayout: RefreshLayout) {
|
||||
reload()
|
||||
}
|
||||
|
||||
private inner class AppBrowserViewClient : BrowserViewClient() {
|
||||
|
||||
override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) {
|
||||
post {
|
||||
showError(object : OnRetryListener {
|
||||
override fun onRetry(layout: StatusLayout) {
|
||||
reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
|
||||
progressBar?.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView, url: String) {
|
||||
progressBar?.visibility = View.GONE
|
||||
refreshLayout?.finishRefresh()
|
||||
showComplete()
|
||||
}
|
||||
}
|
||||
|
||||
private inner class AppBrowserChromeClient constructor(view: BrowserView) : BrowserChromeClient(view) {
|
||||
|
||||
override fun onReceivedTitle(view: WebView, title: String?) {
|
||||
if (title == null) {
|
||||
return
|
||||
}
|
||||
setTitle(title)
|
||||
}
|
||||
|
||||
override fun onReceivedIcon(view: WebView, icon: Bitmap?) {
|
||||
if (icon == null) {
|
||||
return
|
||||
}
|
||||
setRightIcon(BitmapDrawable(resources, icon))
|
||||
}
|
||||
|
||||
override fun onProgressChanged(view: WebView, newProgress: Int) {
|
||||
progressBar?.progress = newProgress
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
package com.localee.mireo.app.ui.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.localee.mireo.app.utils.MsMMKVUtils
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.hjq.base.FragmentPagerAdapter
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
import com.localee.mireo.app.app.AppFragment
|
||||
import com.localee.mireo.app.http.api.UserInfoApi
|
||||
import com.localee.mireo.app.http.api.UserInfoRes
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.ui.adapter.NavigationAdapter
|
||||
import com.localee.mireo.app.ui.fragment.ExploreFragment
|
||||
import com.localee.mireo.app.ui.fragment.HomeFragment
|
||||
import com.localee.mireo.app.ui.fragment.MessageFragment
|
||||
import com.localee.mireo.app.ui.fragment.MineFragment
|
||||
import com.localee.mireo.app.ui.fragment.SharedViewModel
|
||||
|
||||
class HomeActivity : AppActivity(), NavigationAdapter.OnNavigationListener {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val INTENT_KEY_IN_FRAGMENT_INDEX: String = "fragmentIndex"
|
||||
private const val INTENT_KEY_IN_FRAGMENT_CLASS: String = "fragmentClass"
|
||||
|
||||
@JvmOverloads
|
||||
fun start(
|
||||
context: Context,
|
||||
fragmentClass: Class<out AppFragment<*>?>? = HomeFragment::class.java
|
||||
) {
|
||||
val intent = Intent(context, HomeActivity::class.java)
|
||||
intent.putExtra(INTENT_KEY_IN_FRAGMENT_CLASS, fragmentClass)
|
||||
if (context !is Activity) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private val viewPager: ViewPager? by lazy { findViewById(R.id.vp_home_pager) }
|
||||
private val navigationView: RecyclerView? by lazy { findViewById(R.id.rv_home_navigation) }
|
||||
private var navigationAdapter: NavigationAdapter? = null
|
||||
private var pagerAdapter: FragmentPagerAdapter<AppFragment<*>>? = null
|
||||
|
||||
private val viewModel: SharedViewModel by viewModels()
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.home_activity
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
|
||||
navigationAdapter = NavigationAdapter(this).apply {
|
||||
addItem(
|
||||
NavigationAdapter.MenuItem(
|
||||
getString(R.string.home_nav_index),
|
||||
ContextCompat.getDrawable(this@HomeActivity, R.drawable.home_home_selector)
|
||||
)
|
||||
)
|
||||
addItem(
|
||||
NavigationAdapter.MenuItem(
|
||||
getString(R.string.home_nav_explore),
|
||||
ContextCompat.getDrawable(this@HomeActivity, R.drawable.home_explore_selector)
|
||||
)
|
||||
)
|
||||
addItem(
|
||||
NavigationAdapter.MenuItem(
|
||||
getString(R.string.home_nav_my_list),
|
||||
ContextCompat.getDrawable(this@HomeActivity, R.drawable.home_my_list_selector)
|
||||
)
|
||||
)
|
||||
addItem(
|
||||
NavigationAdapter.MenuItem(
|
||||
getString(R.string.home_nav_me),
|
||||
ContextCompat.getDrawable(this@HomeActivity, R.drawable.home_me_selector)
|
||||
)
|
||||
)
|
||||
setOnNavigationListener(this@HomeActivity)
|
||||
navigationView?.adapter = this
|
||||
}
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
// getCustomerUser()
|
||||
|
||||
pagerAdapter = FragmentPagerAdapter<AppFragment<*>>(this).apply {
|
||||
addFragment(HomeFragment.newInstance())
|
||||
addFragment(ExploreFragment.newInstance())
|
||||
addFragment(MessageFragment.newInstance())
|
||||
addFragment(MineFragment.newInstance())
|
||||
viewPager?.adapter = this
|
||||
}
|
||||
onNewIntent(intent)
|
||||
|
||||
viewModel.action.observe(this) { data ->
|
||||
switchFragment(data);
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
pagerAdapter?.let {
|
||||
switchFragment(it.getFragmentIndex(getSerializable(INTENT_KEY_IN_FRAGMENT_CLASS)))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
viewPager?.let {
|
||||
outState.putInt(INTENT_KEY_IN_FRAGMENT_INDEX, it.currentItem)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
switchFragment(savedInstanceState.getInt(INTENT_KEY_IN_FRAGMENT_INDEX))
|
||||
}
|
||||
|
||||
private fun switchFragment(fragmentIndex: Int) {
|
||||
if (fragmentIndex == -1) {
|
||||
return
|
||||
}
|
||||
when (fragmentIndex) {
|
||||
0, 1, 2, 3 -> {
|
||||
viewPager?.currentItem = fragmentIndex
|
||||
navigationAdapter?.setSelectedPosition(fragmentIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [NavigationAdapter.OnNavigationListener]
|
||||
*/
|
||||
override fun onNavigationItemSelected(position: Int): Boolean {
|
||||
return when (position) {
|
||||
0, 1, 2, 3 -> {
|
||||
viewPager?.currentItem = position
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun createStatusBarConfig(): ImmersionBar {
|
||||
return super.createStatusBarConfig()
|
||||
.navigationBarColor(R.color.white)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
moveTaskToBack(false)
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
viewPager?.adapter = null
|
||||
navigationView?.adapter = null
|
||||
navigationAdapter?.setOnNavigationListener(null)
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package com.localee.mireo.app.ui.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.text.Editable
|
||||
import android.text.TextUtils
|
||||
import android.text.TextWatcher
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.action.StatusAction
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
import com.localee.mireo.app.http.api.SearchHotApi
|
||||
import com.localee.mireo.app.http.api.SearchSearchApi
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_short_play_id
|
||||
import com.localee.mireo.app.ui.adapter.SearchHotAdapter
|
||||
import com.localee.mireo.app.ui.adapter.SearchSearchAdapter
|
||||
import com.localee.mireo.app.widget.StatusLayout
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
|
||||
|
||||
class SearchActivity : AppActivity(), StatusAction {
|
||||
|
||||
private val hintLayout: StatusLayout? by lazy { findViewById(R.id.hl_status_hint) }
|
||||
private val ivClose: ImageView? by lazy { findViewById(R.id.iv_close) }
|
||||
private val etSearch: EditText? by lazy { findViewById(R.id.et_search) }
|
||||
private val recycler: RecyclerView? by lazy { findViewById(R.id.recycler) }
|
||||
|
||||
private var mAdapter: SearchHotAdapter? = null
|
||||
private var mKeyAdapter: SearchSearchAdapter? = null
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.status_activity
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
|
||||
recycler?.layoutManager =
|
||||
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||
|
||||
|
||||
mAdapter = SearchHotAdapter()
|
||||
mKeyAdapter = SearchSearchAdapter()
|
||||
recycler?.adapter = mAdapter
|
||||
|
||||
getSearchHot()
|
||||
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
ivClose?.setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
etSearch?.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
|
||||
}
|
||||
|
||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
|
||||
if (!TextUtils.isEmpty(charSequence.toString())) {
|
||||
recycler?.adapter = mKeyAdapter
|
||||
getSearchSearch(charSequence.toString())
|
||||
} else {
|
||||
recycler?.adapter = mAdapter
|
||||
}
|
||||
}
|
||||
|
||||
override fun afterTextChanged(editable: Editable) {
|
||||
}
|
||||
})
|
||||
|
||||
mAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val searchHot: com.localee.mireo.app.http.api.SearchHotApi.Bean.Data = adapter.items.get(position)
|
||||
startActivity(
|
||||
Intent(
|
||||
this,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
searchHot.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
mKeyAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val search: com.localee.mireo.app.http.api.SearchSearchApi.Bean.Data = adapter.items.get(position)
|
||||
startActivity(
|
||||
Intent(
|
||||
this,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
search.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getSearchHot() {
|
||||
EasyHttp.get(this)
|
||||
.api(com.localee.mireo.app.http.api.SearchHotApi().apply {
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<SearchHotApi.Bean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<SearchHotApi.Bean>) {
|
||||
result.getData()?.let {
|
||||
if (it.list.isEmpty()) {
|
||||
hintLayout?.show()
|
||||
} else {
|
||||
hintLayout?.hide()
|
||||
}
|
||||
mAdapter?.submitList(it.list)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onHttpFail(throwable: Throwable) {
|
||||
super.onHttpFail(throwable)
|
||||
hintLayout?.show()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getSearchSearch(searchKey: String) {
|
||||
EasyHttp.get(this)
|
||||
.api(com.localee.mireo.app.http.api.SearchSearchApi().apply {
|
||||
search = searchKey
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<SearchSearchApi.Bean>>(this) {
|
||||
|
||||
override fun onHttpStart(api: IRequestApi) {
|
||||
|
||||
}
|
||||
|
||||
override fun onHttpSuccess(result: HttpData<SearchSearchApi.Bean>) {
|
||||
result.getData()?.let {
|
||||
if (it.list.isEmpty()) {
|
||||
hintLayout?.show()
|
||||
} else {
|
||||
hintLayout?.hide()
|
||||
}
|
||||
mKeyAdapter?.submitList(it.list)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHttpFail(throwable: Throwable) {
|
||||
super.onHttpFail(throwable)
|
||||
hintLayout?.show()
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
override fun getStatusLayout(): StatusLayout? {
|
||||
return hintLayout
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.localee.mireo.app.ui.activity
|
||||
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.bumptech.glide.Glide
|
||||
import com.hjq.widget.layout.SettingBar
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
import com.localee.mireo.app.manager.CacheDataManager
|
||||
import com.localee.mireo.app.utils.singleClick
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
class SettingActivity : AppActivity(){
|
||||
|
||||
private val cleanCacheView: SettingBar? by lazy { findViewById(R.id.sb_setting_cache) }
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.setting_activity
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
|
||||
cleanCacheView?.setOnClickListener {
|
||||
singleClick {
|
||||
// 清除内存缓存(必须在主线程)
|
||||
Glide.get(this@SettingActivity).clearMemory()
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
CacheDataManager.clearAllCache(this@SettingActivity)
|
||||
// 清除本地缓存(必须在子线程)
|
||||
Glide.get(this@SettingActivity).clearDiskCache()
|
||||
withContext(Dispatchers.Main) {
|
||||
// 重新获取应用缓存大小
|
||||
cleanCacheView?.setRightText(CacheDataManager.getTotalCacheSize(this@SettingActivity))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
// 获取应用缓存大小
|
||||
cleanCacheView?.setRightText(CacheDataManager.getTotalCacheSize(this))
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.localee.mireo.app.ui.activity
|
||||
|
||||
import com.gyf.immersionbar.BarHide
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
|
||||
|
||||
class SplashActivity : AppActivity() {
|
||||
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.splash_activity
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
postDelayed(Runnable {
|
||||
HomeActivity.start(this@SplashActivity)
|
||||
finish()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
}
|
||||
|
||||
override fun createStatusBarConfig(): ImmersionBar {
|
||||
return super.createStatusBarConfig()
|
||||
.hideBar(BarHide.FLAG_HIDE_BAR)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,635 @@
|
||||
package com.localee.mireo.app.ui.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.blankj.utilcode.util.NetworkUtils
|
||||
import com.localee.mireo.app.utils.MsMMKVUtils
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
import com.hjq.toast.ToastUtils
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
import com.localee.mireo.app.app.BaseEventBus
|
||||
import com.localee.mireo.app.http.api.CreateHistoryApi
|
||||
import com.localee.mireo.app.http.api.VideoDetailsApi
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.other.MsConstants
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_activity_id
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_quality
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_quality_refresh
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_short_play_id
|
||||
import com.localee.mireo.app.other.MsConstants.Constants_Episodes_Series_Data_currentPositionExample
|
||||
import com.localee.mireo.app.ui.videoPaly.ExamplePlayerDetailDataRes
|
||||
import com.localee.mireo.app.ui.videoPaly.ExampleSeriesDialogFragment
|
||||
import com.localee.mireo.app.ui.videoPaly.ExampleUnFavoriteDialog
|
||||
import com.localee.mireo.app.ui.videoPaly.VideoPlayAdapter
|
||||
import com.localee.mireo.app.ui.videoPaly.VideoPlayerView
|
||||
import com.localee.mireo.app.utils.DHStringUtils.getPublicRequest
|
||||
import com.localee.mireo.app.utils.TranslatesUtils
|
||||
import com.localee.mireo.app.utils.formatNumber
|
||||
import com.localee.mireo.app.utils.singleClick
|
||||
import com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
open class VideoPlayActivity : AppActivity(), VideoPlayAdapter.PlayerDetailCollection,
|
||||
ExampleSeriesDialogFragment.SeriesCallBack {
|
||||
|
||||
companion object {
|
||||
const val INTENT_KEY_PARAMETERS: String = "parameters"
|
||||
}
|
||||
|
||||
private var first: Boolean = true
|
||||
private var play: Boolean = true
|
||||
private var qualityRefresh: Boolean = false
|
||||
|
||||
// private val exampleRecommendViewModel by lazy { ViewModelProvider(this)[ExampleRecommendViewModel::class.java] }
|
||||
private var currentPage = 1
|
||||
private val currentSize = 10
|
||||
private var currentPosition = 0
|
||||
private var exampleRecommendAdapter: VideoPlayAdapter? = null
|
||||
private var data: com.localee.mireo.app.http.api.ExampleRecommendDataRes.Data? = null
|
||||
private var revolution =
|
||||
MsMMKVUtils.getMMKV().getInt(MsConstants.CONSTANTS_quality, 0).toString()
|
||||
|
||||
|
||||
private val srRecommend: SmartRefreshLayout? by lazy { findViewById(R.id.sr_recommend) }
|
||||
private val viewPagerExampleRecommend: ViewPager2? by lazy { findViewById(R.id.viewPager_example_recommend) }
|
||||
|
||||
private val exampleNetwork: ViewGroup? by lazy { findViewById(R.id.example_network) }
|
||||
private val exampleTvNoNetwork: TextView? by lazy { exampleNetwork?.findViewById(R.id.example_tv_no_network) }
|
||||
private val tvExampleRetry: TextView? by lazy { exampleNetwork?.findViewById(R.id.tv_example_retry) }
|
||||
|
||||
private val exampleEmpty: ViewGroup? by lazy { findViewById(R.id.example_empty) }
|
||||
private val exampleTvEmpty: TextView? by lazy { exampleEmpty?.findViewById(R.id.example_tv_empty) }
|
||||
|
||||
// private val avi: LoadingAnimationView? by lazy { findViewById(R.id.avi) }
|
||||
private var shortVideoId: Int? = null
|
||||
private var activityId: Int? = null
|
||||
private var shortVideo: VideoDetailsApi.Bean.ShortPlayInfo? = null
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.video_play_activity
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
shortVideoId = intent.getIntExtra(CONSTANTS_short_play_id, 0)
|
||||
activityId = intent.getIntExtra(CONSTANTS_activity_id, 0)
|
||||
EventBus.getDefault().register(this)
|
||||
this.window?.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE
|
||||
)
|
||||
this.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
||||
exampleTvNoNetwork?.text =
|
||||
TranslatesUtils.translates()?.no_network
|
||||
tvExampleRetry?.text = TranslatesUtils.translates()?.retry
|
||||
exampleTvEmpty?.text = TranslatesUtils.translates()?.s_no_content
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
initialization()
|
||||
MsConstants.ExampleIsCurrentPage = true
|
||||
if (!play) {
|
||||
qualityLogic()
|
||||
} else {
|
||||
play = false
|
||||
}
|
||||
}
|
||||
|
||||
fun initialization() {
|
||||
|
||||
if (NetworkUtils.isConnected()) {
|
||||
// avi?.start()
|
||||
getVideoDetails()
|
||||
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
exampleNetwork?.visibility = View.VISIBLE
|
||||
}
|
||||
srRecommend?.setOnRefreshListener {
|
||||
if (NetworkUtils.isConnected()) {
|
||||
// avi?.start()
|
||||
currentPage = 1
|
||||
viewPagerExampleRecommend?.post {
|
||||
detailPlayerView()?.stop()
|
||||
detailPlayerView()?.release()
|
||||
}
|
||||
getVideoDetails()
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
}
|
||||
}
|
||||
viewPagerExampleRecommend?.registerOnPageChangeCallback(object :
|
||||
ViewPager2.OnPageChangeCallback() {
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
currentPosition = position
|
||||
val previousPosition = exampleRecommendAdapter?.currentPlayingPosition
|
||||
if (previousPosition != position) {
|
||||
exampleRecommendAdapter?.recyclerView?.post { exampleRecommendAdapter?.notifyDataSetChanged() }
|
||||
}
|
||||
exampleRecommendAdapter?.currentPlayingPosition = position
|
||||
|
||||
previousPosition?.let {
|
||||
val recyclerView =
|
||||
viewPagerExampleRecommend?.getChildAt(0) as RecyclerView
|
||||
val exampleDetailPlayerView =
|
||||
recyclerView.layoutManager?.findViewByPosition(it) as VideoPlayerView?
|
||||
if (null != exampleDetailPlayerView) {
|
||||
val episode1 =
|
||||
exampleRecommendAdapter?.items?.get(it)
|
||||
episode1?.short_play_id?.let { it1 ->
|
||||
episode1?.short_play_video_id?.let { it2 ->
|
||||
createHistory(
|
||||
it1,
|
||||
it2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
super.onPageScrollStateChanged(state)
|
||||
when (state) {
|
||||
ViewPager2.SCROLL_STATE_IDLE -> {
|
||||
if (viewPagerExampleRecommend?.currentItem == viewPagerExampleRecommend?.adapter?.itemCount?.minus(
|
||||
1
|
||||
)
|
||||
) {
|
||||
if (!first) {
|
||||
getVideoDetails()
|
||||
} else {
|
||||
first = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ViewPager2.SCROLL_STATE_DRAGGING -> {
|
||||
|
||||
}
|
||||
|
||||
ViewPager2.SCROLL_STATE_SETTLING -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
exampleTvEmpty?.setOnClickListener {
|
||||
singleClick {
|
||||
if (!NetworkUtils.isConnected()) {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
return@singleClick
|
||||
}
|
||||
// avi?.start()
|
||||
currentPage = 1
|
||||
getVideoDetails()
|
||||
}
|
||||
}
|
||||
tvExampleRetry?.setOnClickListener {
|
||||
singleClick {
|
||||
if (!NetworkUtils.isConnected()) {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
return@singleClick
|
||||
}
|
||||
// avi?.start()
|
||||
currentPage = 1
|
||||
getVideoDetails()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// override fun onHiddenChanged(hidden: Boolean) {
|
||||
// super.onHiddenChanged(hidden)
|
||||
// if (!hidden) {
|
||||
// activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
// MsConstants.ExampleIsCurrentPage = true
|
||||
// qualityLogic()
|
||||
// } else {
|
||||
// activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
// MsConstants.ExampleIsCurrentPage = false
|
||||
// srRecommend?.postDelayed({ detailPlayerView()?.pause() }, 300)
|
||||
// }
|
||||
// }
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!play) {
|
||||
detailPlayerView()?.play()
|
||||
} else {
|
||||
play = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun qualityLogic() {
|
||||
if (qualityRefresh) {
|
||||
viewPagerExampleRecommend?.post {
|
||||
detailPlayerView()?.stop()
|
||||
detailPlayerView()?.release()
|
||||
}
|
||||
getVideoDetails()
|
||||
qualityRefresh = false
|
||||
} else {
|
||||
detailPlayerView()?.play()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
MsConstants.ExampleIsCurrentPage = false
|
||||
srRecommend?.postDelayed({ detailPlayerView()?.pause() }, 300)
|
||||
}
|
||||
|
||||
fun getVideoDetails() {
|
||||
EasyHttp.get(this)
|
||||
.api(VideoDetailsApi().apply {
|
||||
if (activityId!! != 0) {
|
||||
video_id = activityId;
|
||||
}
|
||||
short_play_id = shortVideoId;
|
||||
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<VideoDetailsApi.Bean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<VideoDetailsApi.Bean>) {
|
||||
result.getData()?.let {
|
||||
if (it.episodeList.isNotEmpty()) {
|
||||
shortVideo = it.shortPlayInfo
|
||||
exampleRecommendAdapter = VideoPlayAdapter()
|
||||
exampleRecommendAdapter?.shortVideo = it.shortPlayInfo
|
||||
viewPagerExampleRecommend?.adapter = exampleRecommendAdapter
|
||||
exampleRecommendAdapter?.submitList(it.episodeList)
|
||||
exampleRecommendAdapter?.playerDetailCollection =
|
||||
this@VideoPlayActivity
|
||||
createHistory(
|
||||
it.episodeList[0].short_play_id,
|
||||
it.episodeList[0].short_play_video_id
|
||||
);
|
||||
exampleNetwork?.visibility = View.INVISIBLE
|
||||
exampleEmpty?.visibility = View.INVISIBLE
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_more_data.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_there_s_no_more_data))
|
||||
}
|
||||
if (currentPage == 1) {
|
||||
exampleEmpty?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
// avi?.stop()
|
||||
srRecommend?.finishRefresh()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// ExampleRecommendRequest.getVideoDetails(current_page, page_size, revolution)
|
||||
// .observeForever { result ->
|
||||
// recommendLiveData.value = result.getOrNull()
|
||||
// }
|
||||
}
|
||||
|
||||
fun createHistory(videoId: Int, shortPlayId: Int) {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap.put("short_play_id", videoId.toString())
|
||||
sMap.put("video_id", shortPlayId.toString())
|
||||
EasyHttp.post(this)
|
||||
.api(CreateHistoryApi())
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object : HttpCallbackProxy<HttpData<Any>>(this) {
|
||||
|
||||
override fun onHttpStart(api: IRequestApi) {
|
||||
}
|
||||
|
||||
override fun onHttpSuccess(result: HttpData<Any>) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun doCollect(shortPlayId: Int, videoId: Int) {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap.put("short_play_id", shortPlayId.toString())
|
||||
sMap.put("video_id", videoId.toString())
|
||||
|
||||
EasyHttp.post(this)
|
||||
.api(com.localee.mireo.app.http.api.DoCollectApi())
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object : HttpCallbackProxy<HttpData<Any>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<Any>) {
|
||||
result.getData()?.let {
|
||||
if (it != null) {
|
||||
val imageView =
|
||||
detailPlayerView()?.findViewById<AppCompatImageView>(R.id.example_iv_collection_controller)
|
||||
val textview =
|
||||
detailPlayerView()?.findViewById<AppCompatTextView>(R.id.example_tv_collection_num_controller)
|
||||
imageView?.setImageResource(R.mipmap.iv_example_collection_h)
|
||||
shortVideo?.collect_total = shortVideo?.collect_total?.plus(1)!!
|
||||
shortVideo?.is_collect = true
|
||||
textview?.text = formatNumber(shortVideo?.collect_total!!)
|
||||
textview?.setTextColor(resources.getColor(R.color.example_color_F56490))
|
||||
exampleRecommendAdapter?.shortVideo = shortVideo
|
||||
EventBus.getDefault().post(
|
||||
BaseEventBus(
|
||||
MsConstants.Constants_Episodes_Series_DataExample,
|
||||
shortVideo
|
||||
)
|
||||
)
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
toast(TranslatesUtils.translates()?.success.toString())
|
||||
}
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
toast(TranslatesUtils.translates()?.network_error.toString())
|
||||
} else {
|
||||
toast(getString(R.string.example_service_exception_please_try_again))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun doCancelCollect(shortPlayId: Int, videoId: Int) {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap.put("short_play_id", shortPlayId.toString())
|
||||
sMap.put("video_id", videoId.toString())
|
||||
|
||||
EasyHttp.post(this)
|
||||
.api(com.localee.mireo.app.http.api.CancelCollectApi())
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object : HttpCallbackProxy<HttpData<Any>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<Any>) {
|
||||
result.getData()?.let {
|
||||
if (it != null) {
|
||||
val imageView =
|
||||
detailPlayerView()?.findViewById<AppCompatImageView>(R.id.example_iv_collection_controller)
|
||||
val textview =
|
||||
detailPlayerView()?.findViewById<AppCompatTextView>(R.id.example_tv_collection_num_controller)
|
||||
imageView?.setImageResource(R.mipmap.iv_example_collection_n)
|
||||
shortVideo?.collect_total = shortVideo?.collect_total?.minus(1)!!
|
||||
shortVideo?.is_collect = false
|
||||
textview?.text = formatNumber(shortVideo?.collect_total!!)
|
||||
textview?.setTextColor(resources.getColor(R.color.white))
|
||||
exampleRecommendAdapter?.shortVideo = shortVideo
|
||||
EventBus.getDefault().post(
|
||||
BaseEventBus(
|
||||
MsConstants.Constants_Episodes_Series_DataExample,
|
||||
shortVideo
|
||||
)
|
||||
)
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
toast(TranslatesUtils.translates()?.success.toString())
|
||||
}
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
toast(TranslatesUtils.translates()?.network_error.toString())
|
||||
} else {
|
||||
toast(getString(R.string.example_service_exception_please_try_again))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private fun detailPlayerView(): VideoPlayerView? {
|
||||
try {
|
||||
val recyclerView = viewPagerExampleRecommend?.getChildAt(0) as RecyclerView
|
||||
return recyclerView.layoutManager?.findViewByPosition(currentPosition) as VideoPlayerView?
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
viewPagerExampleRecommend?.post {
|
||||
detailPlayerView()?.stop()
|
||||
detailPlayerView()?.release()
|
||||
}
|
||||
super.onDestroy()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEvent(event: String) {
|
||||
if (MsConstants.Constants_RecommendPlayerView_DramaSeriesExample == event) {
|
||||
if (exampleRecommendAdapter?.items?.isNotEmpty() == true) {
|
||||
val exampleSeriesDialogFragment = ExampleSeriesDialogFragment()
|
||||
val bundle = Bundle()
|
||||
bundle.putInt(
|
||||
Constants_Episodes_Series_Data_currentPositionExample,
|
||||
currentPosition
|
||||
)
|
||||
bundle.putParcelable(
|
||||
MsConstants.Constants_Episodes_Series_DataExample,
|
||||
shortVideo
|
||||
)
|
||||
bundle.putParcelableArrayList(
|
||||
MsConstants.Constants_Episodes_Series_Data_ListExample,
|
||||
exampleRecommendAdapter?.items?.let { ArrayList(it) }
|
||||
)
|
||||
exampleSeriesDialogFragment.seriesCallBack = this
|
||||
exampleSeriesDialogFragment.arguments = bundle
|
||||
exampleSeriesDialogFragment.show(
|
||||
supportFragmentManager,
|
||||
"ExampleSeriesDialogFragment"
|
||||
)
|
||||
}
|
||||
}
|
||||
if (MsConstants.Constants_DetailPlayerView_PLAYER_STATUS_FINISHExample == event) {
|
||||
if (viewPagerExampleRecommend?.currentItem == exampleRecommendAdapter?.items?.size?.minus(
|
||||
1
|
||||
)
|
||||
) {
|
||||
// exampleHomeViewModel.getDetailsRecommand()
|
||||
viewPagerExampleRecommend?.post {
|
||||
detailPlayerView()?.pause()
|
||||
detailPlayerView()?.release()
|
||||
viewPagerExampleRecommend?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
currentPosition.plus(1)
|
||||
.let {
|
||||
exampleRecommendAdapter?.items?.get(it)?.let { it1 ->
|
||||
if (it1.coins > 0) {
|
||||
if (MsMMKVUtils.getMMKV().getString(
|
||||
CONSTANTS_short_play_id,
|
||||
""
|
||||
) == shortVideoId.toString()
|
||||
) {
|
||||
}
|
||||
}
|
||||
}
|
||||
detailPlayerView()?.stop()
|
||||
viewPagerExampleRecommend?.currentItem = it
|
||||
}
|
||||
}
|
||||
|
||||
if (CONSTANTS_quality_refresh == event) {
|
||||
revolution =
|
||||
MsMMKVUtils.getMMKV().getInt(MsConstants.CONSTANTS_quality, 0)
|
||||
.toString()
|
||||
qualityRefresh = true
|
||||
}
|
||||
|
||||
if (MsConstants.Constants_RecommendPlayerView_CLOSEExample == event) {
|
||||
finish()
|
||||
}
|
||||
if (CONSTANTS_quality == event) {
|
||||
startActivity(SearchActivity::class.java)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEvent(event: BaseEventBus<ExamplePlayerDetailDataRes.ShortPlayInfo>) {
|
||||
// if (MsConstants.Constants_Episodes_Series_DataExample == event.code) {
|
||||
// if (exampleRecommendAdapter?.items?.get(currentPosition)?.name == event.data.name) {
|
||||
// val imageView =
|
||||
// detailPlayerView()?.findViewById<AppCompatImageView>(R.id.example_iv_collection_controller)
|
||||
// val textview =
|
||||
// detailPlayerView()?.findViewById<AppCompatTextView>(R.id.example_tv_collection_num_controller)
|
||||
// imageView?.setImageResource(if (event.data.is_collect) R.mipmap.iv_example_collection_h else R.mipmap.iv_example_collection_n)
|
||||
// exampleRecommendAdapter?.items?.get(currentPosition)?.collect_total =
|
||||
// event.data.collect_total
|
||||
// exampleRecommendAdapter?.items?.get(currentPosition)?.is_collect =
|
||||
// event.data.is_collect
|
||||
// textview?.text = formatNumber(event.data.collect_total)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// override fun collection(dataRes: ExampleRecommendDataRes.Data) {
|
||||
// singleClick {
|
||||
// data = dataRes
|
||||
// if (dataRes.is_collect) {
|
||||
// val exampleUnFavoriteDialog = ExampleUnFavoriteDialog(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)
|
||||
// if (TranslatesUtils.translates() != null) {
|
||||
// tvThinkAgain.text = TranslatesUtils.translates()?.try_again
|
||||
// tvUnfavorite.text = TranslatesUtils.translates()?.collection
|
||||
// tvTitle.text = TranslatesUtils.translates()?.collection
|
||||
// tvContent.text = TranslatesUtils.translates()?.not_collect_warning
|
||||
// }
|
||||
// tvThinkAgain.setOnClickListener { exampleUnFavoriteDialog.dismiss() }
|
||||
// tvUnfavorite.setOnClickListener {
|
||||
// dataRes.video_info?.short_play_id?.let {
|
||||
// dataRes.video_info.short_play_video_id.let { it1 ->
|
||||
// doCancelCollect(
|
||||
// it, it1
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// exampleUnFavoriteDialog.dismiss()
|
||||
// }
|
||||
// exampleUnFavoriteDialog.show()
|
||||
// } else {
|
||||
// dataRes.video_info?.short_play_id?.let {
|
||||
// dataRes.video_info.short_play_video_id.let { it1 ->
|
||||
// doCollect(
|
||||
// it, it1
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
override fun collection(episode: VideoDetailsApi.Bean.Episode) {
|
||||
singleClick {
|
||||
if (!episode.is_lock) {
|
||||
if (shortVideo?.is_collect == true) {
|
||||
val exampleUnFavoriteDialog = ExampleUnFavoriteDialog(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)
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
tvThinkAgain.text = TranslatesUtils.translates()?.try_again
|
||||
tvUnfavorite.text = TranslatesUtils.translates()?.collection
|
||||
tvTitle.text = TranslatesUtils.translates()?.collection
|
||||
tvContent.text = TranslatesUtils.translates()?.not_collect_warning
|
||||
}
|
||||
tvThinkAgain.setOnClickListener { exampleUnFavoriteDialog.dismiss() }
|
||||
tvUnfavorite.setOnClickListener {
|
||||
episode.short_play_id.let {
|
||||
episode.short_play_video_id.let { it1 ->
|
||||
doCancelCollect(
|
||||
it, it1
|
||||
)
|
||||
}
|
||||
}
|
||||
exampleUnFavoriteDialog.dismiss()
|
||||
}
|
||||
exampleUnFavoriteDialog.show()
|
||||
} else {
|
||||
episode.short_play_id.let {
|
||||
episode.short_play_video_id.let { it1 ->
|
||||
doCollect(
|
||||
it, it1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun chooseSeries(episode: VideoDetailsApi.Bean.Episode) {
|
||||
postDelayed({ detailPlayerView()?.pause() }, 300)
|
||||
episode.episode.minus(1)
|
||||
.let {
|
||||
viewPagerExampleRecommend?.currentItem = it
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.http.api.RecommendBean
|
||||
import com.youth.banner.adapter.BannerAdapter
|
||||
|
||||
class HomeBannerAdapter(mDatas: List<RecommendBean>) :
|
||||
BannerAdapter<RecommendBean, HomeBannerAdapter.BannerViewHolder>(mDatas) {
|
||||
|
||||
override fun onCreateHolder(parent: ViewGroup, viewType: Int): BannerViewHolder {
|
||||
val view: View =
|
||||
LayoutInflater.from(parent.context).inflate(R.layout.home_banner_item, parent, false)
|
||||
|
||||
return BannerViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindView(
|
||||
holder: BannerViewHolder,
|
||||
data: RecommendBean,
|
||||
position: Int,
|
||||
size: Int
|
||||
) {
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(data.image_url)
|
||||
.into(holder.imageView)
|
||||
|
||||
holder.tvName.setText(data.name)
|
||||
holder.tvDescription.setText(data.description)
|
||||
|
||||
holder.tvAdd.setOnClickListener {
|
||||
data.let { it1 -> homeBannerOnClick?.bannerAdd(it1) }
|
||||
}
|
||||
holder.tvPlay.setOnClickListener {
|
||||
data.let { it1 -> homeBannerOnClick?.bannerPlay(it1) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class BannerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val imageView: ImageView = view.findViewById(R.id.iv_img)
|
||||
val tvName: TextView = view.findViewById(R.id.tv_name)
|
||||
val tvDescription: TextView = view.findViewById(R.id.tv_description)
|
||||
val tvAdd: TextView = view.findViewById(R.id.tv_add)
|
||||
val tvPlay: TextView = view.findViewById(R.id.tv_play)
|
||||
}
|
||||
|
||||
var homeBannerOnClick: HomeBannerOnClick? = null
|
||||
|
||||
interface HomeBannerOnClick {
|
||||
fun bannerAdd(dataRes: RecommendBean)
|
||||
fun bannerPlay(dataRes: RecommendBean)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.databinding.ItemListTabBinding
|
||||
import com.localee.mireo.app.http.api.RecommendBean
|
||||
|
||||
class HomeCategoriesTabAdapter : BaseQuickAdapter<RecommendBean, HomeCategoriesTabAdapter.VH>() {
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemListTabBinding = ItemListTabBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int, item: RecommendBean?) {
|
||||
if (null != item) {
|
||||
holder.binding.tvName.text = item.name
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item.image_url)
|
||||
.into(holder.binding.ivContent)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.databinding.ItemHomeCriticallyBinding
|
||||
import com.localee.mireo.app.http.api.RecommendBean
|
||||
import com.localee.mireo.app.utils.formatNumber
|
||||
|
||||
class HomeCriticallyAdapter :
|
||||
BaseQuickAdapter<RecommendBean, HomeCriticallyAdapter.VH>() {
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemHomeCriticallyBinding = ItemHomeCriticallyBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(
|
||||
holder: VH,
|
||||
position: Int,
|
||||
item: RecommendBean?
|
||||
) {
|
||||
if (null != item) {
|
||||
holder.binding.tvName.text = item.name
|
||||
holder.binding.tvDescription.text = item.description
|
||||
holder.binding.tvScore.text = item.all_coins
|
||||
holder.binding.tvGood.text = item.watch_total?.let { formatNumber(it) }
|
||||
if (item.category.isEmpty()) {
|
||||
holder.binding.tvFavor.visibility = View.GONE
|
||||
} else {
|
||||
holder.binding.tvFavor.visibility = View.VISIBLE
|
||||
holder.binding.tvFavor.text = item.category[0]
|
||||
}
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item.image_url)
|
||||
.into(holder.binding.ivContent)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.hjq.shape.view.ShapeTextView
|
||||
import com.localee.mireo.app.databinding.ItemHomeGenresBinding
|
||||
|
||||
class HomeGenresAdapter(var id: Int) : BaseQuickAdapter<String, HomeGenresAdapter.VH>() {
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemHomeGenresBinding = ItemHomeGenresBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int, item: String?) {
|
||||
if (null != item) {
|
||||
holder.binding.tvType.text = item
|
||||
val text: ShapeTextView = holder.binding.tvType
|
||||
|
||||
if (position == id) {
|
||||
text.getShapeDrawableBuilder().setSolidColor(0xFFF8726D.toInt())
|
||||
.setShadowColor(0xFFF8726D.toInt())
|
||||
.intoBackground();
|
||||
} else {
|
||||
text.getShapeDrawableBuilder().setSolidColor(0x00000000.toInt())
|
||||
.setShadowColor(0xFFF8726D.toInt())
|
||||
.intoBackground();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.databinding.ItemHomeShortBinding
|
||||
import com.localee.mireo.app.http.api.RecommendBean
|
||||
|
||||
class HomeShortAdapter : BaseQuickAdapter<RecommendBean, HomeShortAdapter.VH>() {
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemHomeShortBinding = ItemHomeShortBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int, item: RecommendBean?) {
|
||||
if (null != item) {
|
||||
holder.binding.tvName.text = item.name
|
||||
holder.binding.tvDescription.text = item.description
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item.image_url)
|
||||
.into(holder.binding.ivContent)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
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.hjq.shape.view.ShapeTextView
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.http.api.RecommendBean
|
||||
|
||||
class HomeTopAdapter(var type: Int) :
|
||||
BaseQuickAdapter<RecommendBean, QuickViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
context: Context,
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): QuickViewHolder {
|
||||
return QuickViewHolder(R.layout.item_home_top, parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(
|
||||
holder: QuickViewHolder,
|
||||
position: Int,
|
||||
item: RecommendBean?
|
||||
) {
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item?.image_url)
|
||||
.into(holder.getView(R.id.iv_content))
|
||||
|
||||
val text: ShapeTextView = holder.getView(R.id.tv_hot)
|
||||
|
||||
when (type) {
|
||||
1 -> {
|
||||
text.setText("HOT")
|
||||
text.getShapeDrawableBuilder().setSolidColor(0xFFFF1E63.toInt())
|
||||
.intoBackground();
|
||||
}
|
||||
|
||||
2 -> {
|
||||
text.setText("NEW")
|
||||
text.getShapeDrawableBuilder().setSolidColor(0xFF564FC0.toInt())
|
||||
.intoBackground();
|
||||
}
|
||||
|
||||
3 -> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.databinding.ItemListTabBinding
|
||||
import com.localee.mireo.app.http.api.HistoryBean
|
||||
|
||||
class LostTabAdapter(var tabPosition: Int) :
|
||||
BaseQuickAdapter<HistoryBean.Data, LostTabAdapter.VH>() {
|
||||
|
||||
var type = 0
|
||||
var selectEdit = false
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemListTabBinding = ItemListTabBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int, item: HistoryBean.Data?) {
|
||||
if (null != item) {
|
||||
holder.binding.tvName.text = item.name
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item.image_url)
|
||||
.into(holder.binding.ivContent)
|
||||
holder.binding.tvName2.text = item.name
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item.image_url)
|
||||
.into(holder.binding.ivContent2)
|
||||
|
||||
if (type == 0) {
|
||||
holder.binding.clOne.visibility = View.VISIBLE
|
||||
holder.binding.rlTwo.visibility = View.GONE
|
||||
} else {
|
||||
holder.binding.clOne.visibility = View.GONE
|
||||
holder.binding.rlTwo.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
if (selectEdit) {
|
||||
holder.binding.cbOne.visibility = View.VISIBLE
|
||||
holder.binding.cbTwo.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.binding.cbOne.visibility = View.GONE
|
||||
holder.binding.cbTwo.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (item.is_check) {
|
||||
holder.binding.cbOne.isChecked = true
|
||||
holder.binding.cbTwo.isChecked = true
|
||||
} else {
|
||||
holder.binding.cbOne.isChecked = false
|
||||
holder.binding.cbTwo.isChecked = false
|
||||
|
||||
}
|
||||
|
||||
when (tabPosition) {
|
||||
0 -> {
|
||||
if (item.categoryList?.isNotEmpty() == true) {
|
||||
holder.binding.tvFavor.text = item.categoryList.get(0).name
|
||||
holder.binding.tvFavor.visibility = View.VISIBLE
|
||||
if (item.categoryList.size > 1) {
|
||||
holder.binding.tvLove.text = item.categoryList.get(1).name
|
||||
holder.binding.tvLove.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.binding.tvLove.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
holder.binding.tvFavor.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
1 -> {
|
||||
holder.binding.tvFavor.text =
|
||||
"EP" + item.current_episode + " / EP" + item.episode_total
|
||||
holder.binding.tvFavor.visibility = View.VISIBLE
|
||||
holder.binding.tvLove.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.databinding.ItemMeHistoryBinding
|
||||
import com.localee.mireo.app.http.api.HistoryBean
|
||||
|
||||
class MeHistoryAdapter() :
|
||||
BaseQuickAdapter<HistoryBean.Data, MeHistoryAdapter.VH>() {
|
||||
|
||||
var type = 0
|
||||
var selectEdit = false
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemMeHistoryBinding = ItemMeHistoryBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int, item: HistoryBean.Data?) {
|
||||
if (null != item) {
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item.image_url)
|
||||
.into(holder.binding.ivContent)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.*
|
||||
import android.widget.*
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.hjq.base.BaseAdapter
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppAdapter
|
||||
|
||||
class NavigationAdapter constructor(context: Context) :
|
||||
AppAdapter<NavigationAdapter.MenuItem>(context), BaseAdapter.OnItemClickListener {
|
||||
|
||||
private var selectedPosition: Int = 0
|
||||
|
||||
private var listener: OnNavigationListener? = null
|
||||
|
||||
init {
|
||||
setOnItemClickListener(this)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder()
|
||||
}
|
||||
|
||||
override fun generateDefaultLayoutManager(context: Context): RecyclerView.LayoutManager {
|
||||
return GridLayoutManager(context, getCount(), RecyclerView.VERTICAL, false)
|
||||
}
|
||||
|
||||
fun getSelectedPosition(): Int {
|
||||
return selectedPosition
|
||||
}
|
||||
|
||||
fun setSelectedPosition(position: Int) {
|
||||
selectedPosition = position
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setOnNavigationListener(listener: OnNavigationListener?) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
override fun onItemClick(recyclerView: RecyclerView?, itemView: View?, position: Int) {
|
||||
if (selectedPosition == position) {
|
||||
return
|
||||
}
|
||||
if (listener == null) {
|
||||
selectedPosition = position
|
||||
notifyDataSetChanged()
|
||||
return
|
||||
}
|
||||
if (listener!!.onNavigationItemSelected(position)) {
|
||||
selectedPosition = position
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
inner class ViewHolder : AppViewHolder(R.layout.home_navigation_item) {
|
||||
|
||||
private val iconView: ImageView? by lazy { findViewById(R.id.iv_home_navigation_icon) }
|
||||
private val titleView: TextView? by lazy { findViewById(R.id.tv_home_navigation_title) }
|
||||
|
||||
override fun onBindView(position: Int) {
|
||||
getItem(position).apply {
|
||||
iconView?.setImageDrawable(getDrawable())
|
||||
titleView?.text = getText()
|
||||
iconView?.isSelected = (selectedPosition == position)
|
||||
titleView?.isSelected = (selectedPosition == position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MenuItem constructor(private val text: String?, private val drawable: Drawable?) {
|
||||
|
||||
fun getText(): String? {
|
||||
return text
|
||||
}
|
||||
|
||||
fun getDrawable(): Drawable? {
|
||||
return drawable
|
||||
}
|
||||
}
|
||||
|
||||
interface OnNavigationListener {
|
||||
fun onNavigationItemSelected(position: Int): Boolean
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.localee.mireo.app.app.AppApplication
|
||||
import com.localee.mireo.app.databinding.ItemSearchHotBinding
|
||||
import com.localee.mireo.app.http.api.SearchHotApi
|
||||
|
||||
class SearchHotAdapter : BaseQuickAdapter<SearchHotApi.Bean.Data, SearchHotAdapter.VH>() {
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemSearchHotBinding = ItemSearchHotBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int, item: SearchHotApi.Bean.Data?) {
|
||||
if (null != item) {
|
||||
holder.binding.tvName.text = item.name
|
||||
holder.binding.tvDescription.text = item.description
|
||||
// 设置item数据
|
||||
Glide.with(AppApplication.instance)
|
||||
.load(item.image_url)
|
||||
.into(holder.binding.ivContent)
|
||||
|
||||
if (item.categoryList?.isNotEmpty() == true) {
|
||||
holder.binding.tvFavor.text = item.categoryList.get(0).name
|
||||
holder.binding.tvFavor.visibility = View.VISIBLE
|
||||
if (item.categoryList.size > 1) {
|
||||
holder.binding.tvLove.text = item.categoryList.get(1).name
|
||||
holder.binding.tvLove.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.binding.tvLove.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
holder.binding.tvFavor.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chad.library.adapter4.BaseQuickAdapter
|
||||
import com.localee.mireo.app.databinding.ItemSearchSearchBinding
|
||||
import com.localee.mireo.app.http.api.SearchSearchApi
|
||||
|
||||
class SearchSearchAdapter : BaseQuickAdapter<SearchSearchApi.Bean.Data, SearchSearchAdapter.VH>() {
|
||||
|
||||
class VH(
|
||||
parent: ViewGroup,
|
||||
val binding: ItemSearchSearchBinding = ItemSearchSearchBinding.inflate(
|
||||
LayoutInflater.from(parent.context), parent, false
|
||||
),
|
||||
) : RecyclerView.ViewHolder(binding.root)
|
||||
|
||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||
return VH(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VH, position: Int, item: SearchSearchApi.Bean.Data?) {
|
||||
if (null != item) {
|
||||
holder.binding.tvKey.text = item.name
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
package com.localee.mireo.app.ui.adapter
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener
|
||||
import android.content.Context
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
|
||||
import com.hjq.base.BaseAdapter
|
||||
import com.hjq.shape.view.ShapeTextView
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppAdapter
|
||||
|
||||
class TabAdapter @JvmOverloads constructor(
|
||||
context: Context,
|
||||
private val tabMode: Int = TAB_MODE_DESIGN,
|
||||
private val fixed: Boolean = true
|
||||
) : AppAdapter<String?>(context), BaseAdapter.OnItemClickListener {
|
||||
|
||||
companion object {
|
||||
const val TAB_MODE_DESIGN: Int = 1
|
||||
const val TAB_MODE_SLIDING: Int = 2
|
||||
}
|
||||
|
||||
private var selectedPosition: Int = 0
|
||||
|
||||
private var listener: OnTabListener? = null
|
||||
|
||||
init {
|
||||
setOnItemClickListener(this)
|
||||
registerAdapterDataObserver(TabAdapterDataObserver())
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return tabMode
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder {
|
||||
return when (viewType) {
|
||||
TAB_MODE_DESIGN -> DesignViewHolder()
|
||||
TAB_MODE_SLIDING -> SlidingViewHolder()
|
||||
else -> throw IllegalArgumentException("are you ok?")
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateDefaultLayoutManager(context: Context): RecyclerView.LayoutManager {
|
||||
return if (fixed) {
|
||||
var count: Int = getCount()
|
||||
if (count < 1) {
|
||||
count = 1
|
||||
}
|
||||
GridLayoutManager(context, count, RecyclerView.VERTICAL, false)
|
||||
} else {
|
||||
LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
recyclerView.itemAnimator = null
|
||||
}
|
||||
|
||||
fun getSelectedPosition(): Int {
|
||||
return selectedPosition
|
||||
}
|
||||
|
||||
fun setSelectedPosition(position: Int) {
|
||||
if (selectedPosition == position) {
|
||||
return
|
||||
}
|
||||
notifyItemChanged(selectedPosition)
|
||||
selectedPosition = position
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
||||
fun setOnTabListener(listener: OnTabListener?) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
override fun onItemClick(recyclerView: RecyclerView?, itemView: View?, position: Int) {
|
||||
if (selectedPosition == position) {
|
||||
return
|
||||
}
|
||||
if (listener == null) {
|
||||
selectedPosition = position
|
||||
notifyDataSetChanged()
|
||||
return
|
||||
}
|
||||
if (listener!!.onTabSelected(recyclerView, position)) {
|
||||
selectedPosition = position
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
inner class DesignViewHolder : AppViewHolder(R.layout.tab_item_design) {
|
||||
|
||||
private val titleView: TextView? by lazy { findViewById(R.id.tv_tab_design_title) }
|
||||
private val lineView: View? by lazy { findViewById(R.id.v_tab_design_line) }
|
||||
|
||||
init {
|
||||
if (fixed) {
|
||||
val itemView: View = getItemView()
|
||||
val layoutParams: ViewGroup.LayoutParams = itemView.layoutParams
|
||||
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
itemView.layoutParams = layoutParams
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindView(position: Int) {
|
||||
titleView?.text = getItem(position)
|
||||
titleView?.isSelected = (selectedPosition == position)
|
||||
lineView?.visibility =
|
||||
if (selectedPosition == position) View.VISIBLE else View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
inner class SlidingViewHolder : AppViewHolder(R.layout.tab_item_sliding),
|
||||
AnimatorUpdateListener {
|
||||
|
||||
private val titleView: ShapeTextView? by lazy { findViewById(R.id.tv_tab_sliding_title) }
|
||||
|
||||
private val mDefaultTextSize: Int by lazy {
|
||||
getResources().getDimension(R.dimen.sp_12).toInt()
|
||||
}
|
||||
private val mSelectedTextSize: Int by lazy {
|
||||
getResources().getDimension(R.dimen.sp_12).toInt()
|
||||
}
|
||||
|
||||
init {
|
||||
titleView?.setTextSize(TypedValue.COMPLEX_UNIT_PX, mDefaultTextSize.toFloat())
|
||||
if (fixed) {
|
||||
val itemView: View = getItemView()
|
||||
val layoutParams: ViewGroup.LayoutParams = itemView.layoutParams
|
||||
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
itemView.layoutParams = layoutParams
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindView(position: Int) {
|
||||
titleView?.let {
|
||||
it.text = getItem(position)
|
||||
it.isSelected = (selectedPosition == position)
|
||||
val textSize: Int = it.textSize.toInt()
|
||||
if (selectedPosition == position) {
|
||||
it.shapeDrawableBuilder.setSolidGradientColors(
|
||||
0xFFF24C92.toInt(),
|
||||
0xFFF8726D.toInt()
|
||||
).setStrokeSize(0)
|
||||
.intoBackground();
|
||||
if (textSize != mSelectedTextSize) {
|
||||
startAnimator(mDefaultTextSize, mSelectedTextSize)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
it.shapeDrawableBuilder.setSolidGradientColors(
|
||||
0x00000000.toInt(),
|
||||
0x00000000.toInt()
|
||||
).setStrokeSize(getResources().getDimension(R.dimen.dp_1).toInt())
|
||||
.setStrokeColor(0xFFF56490.toInt())
|
||||
.intoBackground();
|
||||
}
|
||||
if (textSize != mDefaultTextSize) {
|
||||
startAnimator(mSelectedTextSize, mDefaultTextSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun startAnimator(start: Int, end: Int) {
|
||||
val valueAnimator: ValueAnimator = ValueAnimator.ofInt(start, end)
|
||||
valueAnimator.addUpdateListener(this)
|
||||
valueAnimator.duration = 100
|
||||
valueAnimator.start()
|
||||
}
|
||||
|
||||
override fun onAnimationUpdate(animation: ValueAnimator) {
|
||||
titleView?.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_PX,
|
||||
(animation.animatedValue as Int).toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class TabAdapterDataObserver : AdapterDataObserver() {
|
||||
|
||||
override fun onChanged() {
|
||||
refreshLayoutManager()
|
||||
}
|
||||
|
||||
override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {}
|
||||
|
||||
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {}
|
||||
|
||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||
refreshLayoutManager()
|
||||
}
|
||||
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
refreshLayoutManager()
|
||||
if (getSelectedPosition() > positionStart - itemCount) {
|
||||
setSelectedPosition(positionStart - itemCount)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {}
|
||||
|
||||
private fun refreshLayoutManager() {
|
||||
if (!fixed) {
|
||||
return
|
||||
}
|
||||
getRecyclerView()?.layoutManager = generateDefaultLayoutManager(getContext())
|
||||
}
|
||||
}
|
||||
|
||||
interface OnTabListener {
|
||||
|
||||
fun onTabSelected(recyclerView: RecyclerView?, position: Int): Boolean
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package com.localee.mireo.app.ui.dialog
|
||||
|
||||
import android.content.*
|
||||
import android.view.*
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.StringRes
|
||||
import com.hjq.base.BaseDialog
|
||||
import com.hjq.base.action.AnimAction
|
||||
import com.localee.mireo.app.R
|
||||
|
||||
class CommonDialog {
|
||||
|
||||
@Suppress("UNCHECKED_CAST", "LeakingThis")
|
||||
open class Builder<B : Builder<B>>(context: Context) : BaseDialog.Builder<B>(context) {
|
||||
|
||||
private var autoDismiss = true
|
||||
|
||||
private val containerLayout: ViewGroup? by lazy { findViewById(R.id.ll_ui_container) }
|
||||
private val titleView: TextView? by lazy { findViewById(R.id.tv_ui_title) }
|
||||
private val cancelView: TextView? by lazy { findViewById(R.id.tv_ui_cancel) }
|
||||
private val lineView: View? by lazy { findViewById(R.id.v_ui_line) }
|
||||
private val confirmView: TextView? by lazy { findViewById(R.id.tv_ui_confirm) }
|
||||
|
||||
init {
|
||||
setContentView(R.layout.ui_dialog)
|
||||
setAnimStyle(AnimAction.ANIM_IOS)
|
||||
setGravity(Gravity.CENTER)
|
||||
setOnClickListener(cancelView, confirmView)
|
||||
}
|
||||
|
||||
fun setCustomView(@LayoutRes id: Int): B {
|
||||
return setCustomView(LayoutInflater.from(getContext()).inflate(id, containerLayout, false))
|
||||
}
|
||||
|
||||
fun setCustomView(view: View?): B {
|
||||
containerLayout?.addView(view, 1)
|
||||
return this as B
|
||||
}
|
||||
|
||||
fun setTitle(@StringRes id: Int): B {
|
||||
return setTitle(getString(id))
|
||||
}
|
||||
|
||||
fun setTitle(text: CharSequence?): B {
|
||||
titleView?.text = text
|
||||
return this as B
|
||||
}
|
||||
|
||||
fun setCancel(@StringRes id: Int): B {
|
||||
return setCancel(getString(id))
|
||||
}
|
||||
|
||||
fun setCancel(text: CharSequence?): B {
|
||||
cancelView?.text = text
|
||||
lineView?.visibility = if (text == null || "" == text.toString()) View.GONE else View.VISIBLE
|
||||
return this as B
|
||||
}
|
||||
|
||||
fun setConfirm(@StringRes id: Int): B {
|
||||
return setConfirm(getString(id))
|
||||
}
|
||||
|
||||
fun setConfirm(text: CharSequence?): B {
|
||||
confirmView?.text = text
|
||||
return this as B
|
||||
}
|
||||
|
||||
fun setAutoDismiss(dismiss: Boolean): B {
|
||||
autoDismiss = dismiss
|
||||
return this as B
|
||||
}
|
||||
|
||||
fun autoDismiss() {
|
||||
if (autoDismiss) {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.localee.mireo.app.ui.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.TextView
|
||||
import android.widget.TextView.OnEditorActionListener
|
||||
import androidx.annotation.StringRes
|
||||
import com.hjq.base.BaseDialog
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.aop.SingleClick
|
||||
import com.hjq.widget.view.RegexEditText
|
||||
|
||||
class InputDialog {
|
||||
|
||||
class Builder(context: Context) : CommonDialog.Builder<Builder>(context),
|
||||
BaseDialog.OnShowListener, OnEditorActionListener {
|
||||
|
||||
private val inputView: RegexEditText? by lazy { findViewById(R.id.tv_input_message) }
|
||||
|
||||
private var listener: OnListener? = null
|
||||
|
||||
init {
|
||||
setCustomView(R.layout.input_dialog)
|
||||
inputView?.setOnEditorActionListener(this)
|
||||
addOnShowListener(this)
|
||||
}
|
||||
|
||||
fun setHint(@StringRes id: Int): Builder = apply {
|
||||
setHint(getString(id))
|
||||
}
|
||||
|
||||
fun setHint(text: CharSequence?): Builder = apply {
|
||||
inputView?.hint = text
|
||||
}
|
||||
|
||||
fun setContent(@StringRes id: Int): Builder = apply {
|
||||
setContent(getString(id))
|
||||
}
|
||||
|
||||
fun setContent(text: CharSequence?): Builder = apply {
|
||||
inputView?.setText(text)
|
||||
val editable = inputView?.text ?: return@apply
|
||||
val index = editable.length
|
||||
if (index <= 0) {
|
||||
return@apply
|
||||
}
|
||||
inputView?.requestFocus()
|
||||
inputView?.setSelection(index)
|
||||
}
|
||||
|
||||
fun setInputRegex(regex: String?): Builder = apply {
|
||||
inputView?.setInputRegex(regex)
|
||||
}
|
||||
|
||||
fun setListener(listener: OnListener?): Builder = apply {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* [BaseDialog.OnShowListener]
|
||||
*/
|
||||
override fun onShow(dialog: BaseDialog?) {
|
||||
postDelayed({ showKeyboard(inputView) }, 500)
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
override fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.tv_ui_confirm -> {
|
||||
autoDismiss()
|
||||
listener?.onConfirm(getDialog(), inputView?.text?.toString() ?: "")
|
||||
}
|
||||
R.id.tv_ui_cancel -> {
|
||||
autoDismiss()
|
||||
listener?.onCancel(getDialog())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [TextView.OnEditorActionListener]
|
||||
*/
|
||||
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
findViewById<View>(R.id.tv_ui_confirm)?.let {
|
||||
// 模拟点击确认按钮
|
||||
onClick(it)
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
interface OnListener {
|
||||
fun onConfirm(dialog: BaseDialog?, content: String)
|
||||
fun onCancel(dialog: BaseDialog?) {}
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.localee.mireo.app.ui.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import com.hjq.base.BaseDialog
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.aop.SingleClick
|
||||
|
||||
class MessageDialog {
|
||||
|
||||
class Builder constructor(context: Context) : CommonDialog.Builder<Builder>(context) {
|
||||
|
||||
private val messageView: TextView? by lazy { findViewById(R.id.tv_message_message) }
|
||||
|
||||
private var listener: OnListener? = null
|
||||
|
||||
init {
|
||||
setCustomView(R.layout.message_dialog)
|
||||
}
|
||||
|
||||
fun setMessage(@StringRes id: Int): Builder = apply {
|
||||
setMessage(getString(id))
|
||||
}
|
||||
|
||||
fun setMessage(text: CharSequence?): Builder = apply {
|
||||
messageView?.text = text
|
||||
}
|
||||
|
||||
fun setListener(listener: OnListener?): Builder = apply {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
override fun create(): BaseDialog {
|
||||
if (("" == messageView?.text.toString())) {
|
||||
throw IllegalArgumentException("Dialog message not null")
|
||||
}
|
||||
return super.create()
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
override fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.tv_ui_confirm -> {
|
||||
autoDismiss()
|
||||
listener?.onConfirm(getDialog())
|
||||
}
|
||||
R.id.tv_ui_cancel -> {
|
||||
autoDismiss()
|
||||
listener?.onCancel(getDialog())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OnListener {
|
||||
|
||||
fun onConfirm(dialog: BaseDialog?)
|
||||
|
||||
fun onCancel(dialog: BaseDialog?) {}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.localee.mireo.app.ui.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import com.hjq.base.BaseDialog
|
||||
import com.hjq.base.action.AnimAction
|
||||
import com.localee.mireo.app.R
|
||||
|
||||
class TipsDialog {
|
||||
|
||||
companion object {
|
||||
const val ICON_FINISH: Int = R.drawable.tips_finish_ic
|
||||
const val ICON_ERROR: Int = R.drawable.tips_error_ic
|
||||
const val ICON_WARNING: Int = R.drawable.tips_warning_ic
|
||||
}
|
||||
|
||||
class Builder(context: Context) : BaseDialog.Builder<Builder>(context),
|
||||
Runnable, BaseDialog.OnShowListener {
|
||||
|
||||
private val messageView: TextView? by lazy { findViewById(R.id.tv_tips_message) }
|
||||
private val iconView: ImageView? by lazy { findViewById(R.id.iv_tips_icon) }
|
||||
|
||||
private var duration = 2000
|
||||
|
||||
init {
|
||||
setContentView(R.layout.tips_dialog)
|
||||
setAnimStyle(AnimAction.ANIM_TOAST)
|
||||
setBackgroundDimEnabled(false)
|
||||
setCancelable(false)
|
||||
addOnShowListener(this)
|
||||
}
|
||||
|
||||
fun setIcon(@DrawableRes id: Int): Builder = apply {
|
||||
iconView?.setImageResource(id)
|
||||
}
|
||||
|
||||
fun setDuration(duration: Int): Builder = apply {
|
||||
this.duration = duration
|
||||
}
|
||||
|
||||
fun setMessage(@StringRes id: Int): Builder = apply {
|
||||
setMessage(getString(id))
|
||||
}
|
||||
|
||||
fun setMessage(text: CharSequence?): Builder = apply {
|
||||
messageView?.text = text
|
||||
}
|
||||
|
||||
override fun create(): BaseDialog {
|
||||
requireNotNull(iconView?.drawable) { "The display type must be specified" }
|
||||
require(!TextUtils.isEmpty(messageView?.text.toString())) { "Dialog message not null" }
|
||||
return super.create()
|
||||
}
|
||||
|
||||
override fun onShow(dialog: BaseDialog?) {
|
||||
postDelayed(this, duration.toLong())
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if (!isShowing()) {
|
||||
return
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.localee.mireo.app.ui.dialog
|
||||
|
||||
import android.content.*
|
||||
import android.view.*
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import com.hjq.base.BaseDialog
|
||||
import com.hjq.base.action.AnimAction
|
||||
import com.localee.mireo.app.R
|
||||
|
||||
class WaitDialog {
|
||||
|
||||
class Builder(context: Context) : BaseDialog.Builder<Builder>(context) {
|
||||
|
||||
private val messageView: TextView? by lazy { findViewById(R.id.tv_wait_message) }
|
||||
|
||||
init {
|
||||
setContentView(R.layout.wait_dialog)
|
||||
setAnimStyle(AnimAction.ANIM_TOAST)
|
||||
setBackgroundDimEnabled(false)
|
||||
setCancelable(false)
|
||||
}
|
||||
|
||||
fun setMessage(@StringRes id: Int): Builder = apply {
|
||||
setMessage(getString(id))
|
||||
}
|
||||
|
||||
fun setMessage(text: CharSequence?): Builder = apply {
|
||||
messageView?.text = text
|
||||
messageView?.visibility = if (text == null) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.webkit.WebView
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.action.StatusAction
|
||||
import com.localee.mireo.app.aop.CheckNet
|
||||
import com.localee.mireo.app.aop.Log
|
||||
import com.localee.mireo.app.app.AppActivity
|
||||
import com.localee.mireo.app.app.AppFragment
|
||||
import com.localee.mireo.app.ui.activity.BrowserActivity
|
||||
import com.localee.mireo.app.widget.BrowserView
|
||||
import com.localee.mireo.app.widget.BrowserView.BrowserChromeClient
|
||||
import com.localee.mireo.app.widget.BrowserView.BrowserViewClient
|
||||
import com.localee.mireo.app.widget.StatusLayout
|
||||
import com.localee.mireo.app.widget.StatusLayout.OnRetryListener
|
||||
import com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import com.scwang.smart.refresh.layout.listener.OnRefreshListener
|
||||
import java.util.*
|
||||
|
||||
class BrowserFragment : AppFragment<AppActivity>(), StatusAction, OnRefreshListener {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val INTENT_KEY_IN_URL: String = "url"
|
||||
|
||||
@Log
|
||||
fun newInstance(url: String): BrowserFragment {
|
||||
val fragment = BrowserFragment()
|
||||
val bundle = Bundle()
|
||||
bundle.putString(INTENT_KEY_IN_URL, url)
|
||||
fragment.arguments = bundle
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
||||
private val hintLayout: StatusLayout? by lazy { findViewById(R.id.hl_browser_hint) }
|
||||
private val refreshLayout: SmartRefreshLayout? by lazy { findViewById(R.id.sl_browser_refresh) }
|
||||
private val browserView: BrowserView? by lazy { findViewById(R.id.wv_browser_view) }
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.browser_fragment
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
browserView?.setLifecycleOwner(this)
|
||||
refreshLayout?.setOnRefreshListener(this)
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
browserView?.apply {
|
||||
setBrowserViewClient(AppBrowserViewClient())
|
||||
setBrowserChromeClient(BrowserChromeClient(this))
|
||||
loadUrl(getString(INTENT_KEY_IN_URL)!!)
|
||||
}
|
||||
showLoading()
|
||||
}
|
||||
|
||||
override fun getStatusLayout(): StatusLayout {
|
||||
return hintLayout!!
|
||||
}
|
||||
|
||||
@CheckNet
|
||||
private fun reload() {
|
||||
browserView?.reload()
|
||||
}
|
||||
|
||||
/**
|
||||
* [OnRefreshListener]
|
||||
*/
|
||||
override fun onRefresh(refreshLayout: RefreshLayout) {
|
||||
reload()
|
||||
}
|
||||
|
||||
private inner class AppBrowserViewClient : BrowserViewClient() {
|
||||
override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) {
|
||||
post {
|
||||
showError(object : OnRetryListener {
|
||||
override fun onRetry(layout: StatusLayout) {
|
||||
reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {}
|
||||
|
||||
override fun onPageFinished(view: WebView, url: String) {
|
||||
refreshLayout?.finishRefresh()
|
||||
showComplete()
|
||||
}
|
||||
|
||||
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
||||
val scheme: String = Uri.parse(url).scheme ?: return true
|
||||
when (scheme.lowercase(Locale.getDefault())) {
|
||||
"http", "https" -> BrowserActivity.start(getAttachActivity()!!, url)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,502 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.blankj.utilcode.util.NetworkUtils
|
||||
import com.localee.mireo.app.utils.MsMMKVUtils
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.BaseEventBus
|
||||
import com.localee.mireo.app.app.TitleBarFragment
|
||||
import com.localee.mireo.app.http.api.ExampleRecommendDataRes
|
||||
import com.localee.mireo.app.http.api.HomeRecommendApi
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.other.MsConstants
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_quality_refresh
|
||||
import com.localee.mireo.app.ui.activity.HomeActivity
|
||||
import com.localee.mireo.app.ui.videoPaly.ExamplePlayerDetailDataRes
|
||||
import com.localee.mireo.app.ui.videoPaly.ExampleRecommendAdapter
|
||||
import com.localee.mireo.app.ui.videoPaly.ExampleRecommendPlayerView
|
||||
import com.localee.mireo.app.ui.videoPaly.ExampleUnFavoriteDialog
|
||||
import com.localee.mireo.app.utils.DHStringUtils.getPublicRequest
|
||||
import com.localee.mireo.app.utils.TranslatesUtils
|
||||
import com.localee.mireo.app.utils.formatNumber
|
||||
import com.localee.mireo.app.utils.singleClick
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
import com.hjq.toast.ToastUtils
|
||||
import com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
|
||||
class ExploreFragment : TitleBarFragment<HomeActivity>(),
|
||||
ExampleRecommendAdapter.ExampleRecommendCollection {
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): ExploreFragment {
|
||||
return ExploreFragment()
|
||||
}
|
||||
}
|
||||
|
||||
private var first: Boolean = true
|
||||
private var play: Boolean = true
|
||||
private var qualityRefresh: Boolean = false
|
||||
|
||||
// private val exampleRecommendViewModel by lazy { ViewModelProvider(this)[ExampleRecommendViewModel::class.java] }
|
||||
private var currentPage = 1
|
||||
private val currentSize = 10
|
||||
private var currentPosition = 0
|
||||
private var exampleRecommendAdapter: ExampleRecommendAdapter? = null
|
||||
private var data: com.localee.mireo.app.http.api.ExampleRecommendDataRes.Data? = null
|
||||
private var revolution =
|
||||
MsMMKVUtils.getMMKV().getInt(MsConstants.CONSTANTS_quality, 0).toString()
|
||||
|
||||
|
||||
private val srRecommend: SmartRefreshLayout? by lazy { findViewById(R.id.sr_recommend) }
|
||||
private val viewPagerExampleRecommend: ViewPager2? by lazy { findViewById(R.id.viewPager_example_recommend) }
|
||||
|
||||
private val exampleNetwork: ViewGroup? by lazy { findViewById(R.id.example_network) }
|
||||
private val exampleTvNoNetwork: TextView? by lazy { exampleNetwork?.findViewById(R.id.example_tv_no_network) }
|
||||
private val tvExampleRetry: TextView? by lazy { exampleNetwork?.findViewById(R.id.tv_example_retry) }
|
||||
|
||||
private val exampleEmpty: ViewGroup? by lazy { findViewById(R.id.example_empty) }
|
||||
private val exampleTvEmpty: TextView? by lazy { exampleEmpty?.findViewById(R.id.example_tv_empty) }
|
||||
|
||||
// private val avi: LoadingAnimationView? by lazy { findViewById(R.id.avi) }
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.find_fragment
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
EventBus.getDefault().register(this)
|
||||
activity?.window?.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE
|
||||
)
|
||||
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
|
||||
exampleTvNoNetwork?.text =
|
||||
TranslatesUtils.translates()?.no_network
|
||||
tvExampleRetry?.text = TranslatesUtils.translates()?.retry
|
||||
exampleTvEmpty?.text = TranslatesUtils.translates()?.s_no_content
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
|
||||
}
|
||||
|
||||
fun initialization() {
|
||||
|
||||
if (NetworkUtils.isConnected()) {
|
||||
// avi?.start()
|
||||
getRecommands(currentPage, currentSize, revolution)
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
exampleNetwork?.visibility = View.VISIBLE
|
||||
}
|
||||
srRecommend?.setOnRefreshListener {
|
||||
if (NetworkUtils.isConnected()) {
|
||||
// avi?.start()
|
||||
currentPage = 1
|
||||
viewPagerExampleRecommend?.post {
|
||||
recommendPlayerView()?.stop()
|
||||
recommendPlayerView()?.release()
|
||||
}
|
||||
getRecommands(
|
||||
currentPage,
|
||||
currentSize, revolution
|
||||
)
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
}
|
||||
}
|
||||
viewPagerExampleRecommend?.registerOnPageChangeCallback(object :
|
||||
ViewPager2.OnPageChangeCallback() {
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
currentPosition = position
|
||||
val previousPosition = exampleRecommendAdapter?.currentPlayingPosition
|
||||
if (previousPosition != position) {
|
||||
exampleRecommendAdapter?.recyclerView?.post { exampleRecommendAdapter?.notifyDataSetChanged() }
|
||||
}
|
||||
exampleRecommendAdapter?.currentPlayingPosition = position
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
super.onPageScrollStateChanged(state)
|
||||
when (state) {
|
||||
ViewPager2.SCROLL_STATE_IDLE -> {
|
||||
if (viewPagerExampleRecommend?.currentItem == viewPagerExampleRecommend?.adapter?.itemCount?.minus(
|
||||
1
|
||||
)
|
||||
) {
|
||||
if (!first) {
|
||||
currentPage++
|
||||
getRecommands(
|
||||
currentPage,
|
||||
currentSize,
|
||||
revolution
|
||||
)
|
||||
} else {
|
||||
first = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ViewPager2.SCROLL_STATE_DRAGGING -> {
|
||||
|
||||
}
|
||||
|
||||
ViewPager2.SCROLL_STATE_SETTLING -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
exampleTvEmpty?.setOnClickListener {
|
||||
singleClick {
|
||||
if (!NetworkUtils.isConnected()) {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
return@singleClick
|
||||
}
|
||||
// avi?.start()
|
||||
currentPage = 1
|
||||
getRecommands(
|
||||
currentPage,
|
||||
currentSize, revolution
|
||||
)
|
||||
}
|
||||
}
|
||||
tvExampleRetry?.setOnClickListener {
|
||||
singleClick {
|
||||
if (!NetworkUtils.isConnected()) {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_network.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_no_network))
|
||||
}
|
||||
return@singleClick
|
||||
}
|
||||
// avi?.start()
|
||||
currentPage = 1
|
||||
getRecommands(
|
||||
currentPage,
|
||||
currentSize, revolution
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHiddenChanged(hidden: Boolean) {
|
||||
super.onHiddenChanged(hidden)
|
||||
if (!hidden) {
|
||||
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
MsConstants.ExampleIsCurrentPage = true
|
||||
qualityLogic()
|
||||
} else {
|
||||
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
MsConstants.ExampleIsCurrentPage = false
|
||||
srRecommend?.postDelayed({ recommendPlayerView()?.pause() }, 300)
|
||||
}
|
||||
}
|
||||
|
||||
private var isDataLoaded = false
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isVisible && !isDataLoaded) { // 检查是否对用户可见
|
||||
initialization()
|
||||
isDataLoaded = true
|
||||
}
|
||||
MsConstants.ExampleIsCurrentPage = true
|
||||
if (isVisible) {
|
||||
if (!play) {
|
||||
qualityLogic()
|
||||
} else {
|
||||
play = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun qualityLogic() {
|
||||
if (qualityRefresh) {
|
||||
viewPagerExampleRecommend?.post {
|
||||
recommendPlayerView()?.stop()
|
||||
recommendPlayerView()?.release()
|
||||
}
|
||||
getRecommands(
|
||||
currentPage,
|
||||
currentSize, revolution
|
||||
)
|
||||
qualityRefresh = false
|
||||
} else {
|
||||
recommendPlayerView()?.play()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
MsConstants.ExampleIsCurrentPage = false
|
||||
srRecommend?.postDelayed({ recommendPlayerView()?.pause() }, 300)
|
||||
}
|
||||
|
||||
fun getRecommands(currentPage: Int, pageSize: Int, revolutionS: String) {
|
||||
EasyHttp.get(this)
|
||||
.api(HomeRecommendApi().apply {
|
||||
current_page = currentPage;
|
||||
page_size = pageSize;
|
||||
revolution = revolutionS;
|
||||
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<ExampleRecommendDataRes>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<ExampleRecommendDataRes>) {
|
||||
result.getData()?.let {
|
||||
if (it != null) {
|
||||
if (it.list?.isNotEmpty() == true) {
|
||||
if (currentPage == 1) {
|
||||
exampleRecommendAdapter = ExampleRecommendAdapter()
|
||||
viewPagerExampleRecommend?.adapter = exampleRecommendAdapter
|
||||
exampleRecommendAdapter?.submitList(it.list)
|
||||
exampleRecommendAdapter?.recommendCollection =
|
||||
this@ExploreFragment
|
||||
} else {
|
||||
exampleRecommendAdapter?.addAll(it.list)
|
||||
}
|
||||
exampleNetwork?.visibility = View.INVISIBLE
|
||||
exampleEmpty?.visibility = View.INVISIBLE
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.no_more_data.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_there_s_no_more_data))
|
||||
}
|
||||
if (currentPage == 1) {
|
||||
exampleEmpty?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (currentPage == 1) {
|
||||
recommendPlayerView()?.release()
|
||||
exampleEmpty?.visibility = View.VISIBLE
|
||||
}
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.network_error.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_service_exception_please_try_again))
|
||||
}
|
||||
}
|
||||
// avi?.stop()
|
||||
srRecommend?.finishRefresh()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// ExampleRecommendRequest.getRecommands(current_page, page_size, revolution)
|
||||
// .observeForever { result ->
|
||||
// recommendLiveData.value = result.getOrNull()
|
||||
// }
|
||||
}
|
||||
|
||||
fun doCollect(videoId: Int, shortPlayId: Int) {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap.put("short_play_id", videoId.toString())
|
||||
sMap.put("video_id", shortPlayId.toString())
|
||||
|
||||
EasyHttp.post(this)
|
||||
.api(com.localee.mireo.app.http.api.DoCollectApi())
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object : HttpCallbackProxy<HttpData<Any>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<Any>) {
|
||||
result.getData()?.let {
|
||||
if (it != null) {
|
||||
val imageView =
|
||||
recommendPlayerView()?.findViewById<AppCompatImageView>(R.id.example_iv_collection_controller)
|
||||
val textview =
|
||||
recommendPlayerView()?.findViewById<AppCompatTextView>(R.id.example_tv_collection_num_controller)
|
||||
imageView?.setImageResource(R.mipmap.iv_example_collection_h)
|
||||
data?.collect_total = data?.collect_total?.plus(1)
|
||||
exampleRecommendAdapter?.items?.get(currentPosition)?.collect_total =
|
||||
data?.collect_total
|
||||
exampleRecommendAdapter?.items?.get(currentPosition)?.is_collect = true
|
||||
textview?.text = data?.collect_total?.let { it1 -> formatNumber(it1) }
|
||||
textview?.setTextColor(resources.getColor(R.color.example_color_F56490))
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.success.toString())
|
||||
}
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.network_error.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_service_exception_please_try_again))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun doCancelCollect(videoId: Int, shortPlayId: Int) {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap.put("short_play_id", videoId.toString())
|
||||
sMap.put("video_id", shortPlayId.toString())
|
||||
|
||||
EasyHttp.post(this)
|
||||
.api(com.localee.mireo.app.http.api.CancelCollectApi())
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object : HttpCallbackProxy<HttpData<Any>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<Any>) {
|
||||
result.getData()?.let {
|
||||
if (it != null) {
|
||||
val imageView =
|
||||
recommendPlayerView()?.findViewById<AppCompatImageView>(R.id.example_iv_collection_controller)
|
||||
val textview =
|
||||
recommendPlayerView()?.findViewById<AppCompatTextView>(R.id.example_tv_collection_num_controller)
|
||||
imageView?.setImageResource(R.mipmap.iv_example_collection_n)
|
||||
data?.collect_total = data?.collect_total?.minus(1)
|
||||
exampleRecommendAdapter?.items?.get(currentPosition)?.collect_total =
|
||||
data?.collect_total
|
||||
exampleRecommendAdapter?.items?.get(currentPosition)?.is_collect = false
|
||||
textview?.text = data?.collect_total?.let { it1 -> formatNumber(it1) }
|
||||
textview?.setTextColor(resources.getColor(R.color.white))
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.success.toString())
|
||||
}
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.network_error.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_service_exception_please_try_again))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun recommendPlayerView(): ExampleRecommendPlayerView? {
|
||||
val recyclerView = viewPagerExampleRecommend?.getChildAt(0) as RecyclerView
|
||||
return recyclerView.layoutManager?.findViewByPosition(currentPosition) as ExampleRecommendPlayerView?
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
viewPagerExampleRecommend?.post {
|
||||
recommendPlayerView()?.stop()
|
||||
recommendPlayerView()?.release()
|
||||
}
|
||||
super.onDestroy()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEvent(event: String) {
|
||||
if (MsConstants.Constants_RecommendPlayerView_PLAYER_STATUS_FINISHExample == event) {
|
||||
if (viewPagerExampleRecommend?.currentItem == viewPagerExampleRecommend?.adapter?.itemCount?.minus(
|
||||
1
|
||||
)
|
||||
) {
|
||||
viewPagerExampleRecommend?.currentItem = 0
|
||||
} else {
|
||||
currentPosition.plus(1)
|
||||
.let {
|
||||
viewPagerExampleRecommend?.currentItem = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CONSTANTS_quality_refresh == event) {
|
||||
revolution =
|
||||
MsMMKVUtils.getMMKV().getInt(MsConstants.CONSTANTS_quality, 0)
|
||||
.toString()
|
||||
qualityRefresh = true
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEvent(event: BaseEventBus<ExamplePlayerDetailDataRes.ShortPlayInfo>) {
|
||||
if (MsConstants.Constants_Episodes_Series_DataExample == event.code) {
|
||||
if (exampleRecommendAdapter?.items?.get(currentPosition)?.name == event.data.name) {
|
||||
val imageView =
|
||||
recommendPlayerView()?.findViewById<AppCompatImageView>(R.id.example_iv_collection_controller)
|
||||
val textview =
|
||||
recommendPlayerView()?.findViewById<AppCompatTextView>(R.id.example_tv_collection_num_controller)
|
||||
imageView?.setImageResource(if (event.data.is_collect) R.mipmap.iv_example_collection_h else R.mipmap.iv_example_collection_n)
|
||||
exampleRecommendAdapter?.items?.get(currentPosition)?.collect_total =
|
||||
event.data.collect_total
|
||||
exampleRecommendAdapter?.items?.get(currentPosition)?.is_collect =
|
||||
event.data.is_collect
|
||||
textview?.text = formatNumber(event.data.collect_total)
|
||||
textview?.setTextColor(if (event.data.is_collect) resources.getColor(R.color.example_color_F56490) else resources.getColor(R.color.white))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun collection(dataRes: com.localee.mireo.app.http.api.ExampleRecommendDataRes.Data) {
|
||||
singleClick {
|
||||
data = dataRes
|
||||
if (dataRes.is_collect) {
|
||||
val exampleUnFavoriteDialog = ExampleUnFavoriteDialog(requireContext())
|
||||
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)
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
tvThinkAgain.text = TranslatesUtils.translates()?.try_again
|
||||
tvUnfavorite.text = TranslatesUtils.translates()?.collection
|
||||
tvTitle.text = TranslatesUtils.translates()?.collection
|
||||
tvContent.text = TranslatesUtils.translates()?.not_collect_warning
|
||||
}
|
||||
tvThinkAgain.setOnClickListener { exampleUnFavoriteDialog.dismiss() }
|
||||
tvUnfavorite.setOnClickListener {
|
||||
dataRes.video_info?.short_play_id?.let {
|
||||
dataRes.video_info.short_play_video_id.let { it1 ->
|
||||
doCancelCollect(
|
||||
it, it1
|
||||
)
|
||||
}
|
||||
}
|
||||
exampleUnFavoriteDialog.dismiss()
|
||||
}
|
||||
exampleUnFavoriteDialog.show()
|
||||
} else {
|
||||
dataRes.video_info?.short_play_id?.let {
|
||||
dataRes.video_info.short_play_video_id.let { it1 ->
|
||||
doCollect(
|
||||
it, it1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.action.StatusAction
|
||||
import com.localee.mireo.app.app.TitleBarFragment
|
||||
import com.localee.mireo.app.http.api.HomeVideoListApi
|
||||
import com.localee.mireo.app.http.api.RecommendBean
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_short_play_id
|
||||
import com.localee.mireo.app.ui.activity.HomeActivity
|
||||
import com.localee.mireo.app.ui.activity.VideoPlayActivity
|
||||
import com.localee.mireo.app.ui.adapter.HomeCategoriesTabAdapter
|
||||
import com.localee.mireo.app.widget.StatusLayout
|
||||
import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
|
||||
|
||||
|
||||
class HomeCategoriesTabFragment : TitleBarFragment<HomeActivity>(), OnRefreshLoadMoreListener,
|
||||
StatusAction {
|
||||
|
||||
companion object {
|
||||
fun newInstance(tabName: String, tabId: Int): HomeCategoriesTabFragment {
|
||||
return HomeCategoriesTabFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString("TAB_NAME", tabName)
|
||||
putInt("TAB_ID", tabId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var tabName: String? = null
|
||||
private var tabId: Int? = null
|
||||
|
||||
private val hintLayout: StatusLayout? by lazy { findViewById(R.id.hl_status_hint) }
|
||||
private val recyclerView: RecyclerView? by lazy { findViewById(R.id.recyclerView) }
|
||||
|
||||
private var mAdapter: HomeCategoriesTabAdapter? = null
|
||||
private var pageIndex = 1
|
||||
private var pageTotal = 1
|
||||
val detailList: MutableList<RecommendBean> = java.util.ArrayList()
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.fragment_categories_tab
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun initView() {
|
||||
tabName = arguments?.getString("TAB_NAME")
|
||||
tabId = arguments?.getInt("TAB_ID")
|
||||
|
||||
mAdapter = HomeCategoriesTabAdapter()
|
||||
|
||||
val layoutManager = GridLayoutManager(context, 3)
|
||||
// 设置给 RecyclerView
|
||||
recyclerView?.layoutManager = layoutManager
|
||||
recyclerView?.isNestedScrollingEnabled = false // 关键代码
|
||||
recyclerView?.setHasFixedSize(true) // 优化性能
|
||||
recyclerView?.adapter = mAdapter
|
||||
recyclerView?.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
outRect.right = 10
|
||||
outRect.left = 10
|
||||
}
|
||||
})
|
||||
|
||||
mAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val historyBean: RecommendBean = adapter.items.get(position)
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
historyBean.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
recyclerView?.addOnLayoutChangeListener { _, _, _, _, bottom, _, _, _, oldBottom ->
|
||||
if (bottom != oldBottom) {
|
||||
recyclerView?.layoutParams?.height = bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
private var isDataLoaded = false
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isVisible && !isDataLoaded) { // 检查是否对用户可见
|
||||
loadData()
|
||||
isDataLoaded = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
getHomeVideoListApi(pageIndex, 10)
|
||||
}
|
||||
|
||||
private fun getHomeVideoListApi(currentPage: Int, pageSize: Int) {
|
||||
EasyHttp.get(this)
|
||||
.api(HomeVideoListApi().apply {
|
||||
category_id = tabId
|
||||
current_page = currentPage
|
||||
page_size = pageSize
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<HomeVideoListApi.Bean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<HomeVideoListApi.Bean>) {
|
||||
result.getData()?.let {
|
||||
if (pageIndex == 1) {
|
||||
if (it.list.isEmpty()) {
|
||||
hintLayout?.show()
|
||||
} else {
|
||||
hintLayout?.hide()
|
||||
}
|
||||
mAdapter?.submitList(it.list)
|
||||
pageTotal = it.pagination.page_total
|
||||
} else {
|
||||
mAdapter?.addAll(it.list)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onHttpFail(throwable: Throwable) {
|
||||
super.onHttpFail(throwable)
|
||||
if (pageIndex == 1) {
|
||||
hintLayout?.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHttpEnd(api: IRequestApi) {
|
||||
super.onHttpEnd(api)
|
||||
// if (pageIndex == 1) {
|
||||
// rlStatusRefresh?.finishRefresh(200)
|
||||
// } else {
|
||||
// rlStatusRefresh?.finishLoadMore(200)
|
||||
// }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun onRefresh(refreshLayout: RefreshLayout) {
|
||||
pageIndex = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
override fun onLoadMore(refreshLayout: RefreshLayout) {
|
||||
if (pageIndex == pageTotal) {
|
||||
// rlStatusRefresh?.finishLoadMore(1000)
|
||||
} else {
|
||||
pageIndex++
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStatusLayout(): StatusLayout? {
|
||||
return hintLayout
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,434 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.hjq.base.FragmentPagerAdapter
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
import com.hjq.toast.ToastUtils
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppFragment
|
||||
import com.localee.mireo.app.app.TitleBarFragment
|
||||
import com.localee.mireo.app.http.api.CustomerRegisterApi
|
||||
import com.localee.mireo.app.http.api.HomeCategoriesApi
|
||||
import com.localee.mireo.app.http.api.HomeDayMaxRechargeShortPlayRankApi
|
||||
import com.localee.mireo.app.http.api.HomeModuleApi
|
||||
import com.localee.mireo.app.http.api.RecommendBean
|
||||
import com.localee.mireo.app.http.api.UserInfoApi
|
||||
import com.localee.mireo.app.http.api.UserInfoRes
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_short_play_id
|
||||
import com.localee.mireo.app.ui.activity.HomeActivity
|
||||
import com.localee.mireo.app.ui.activity.SearchActivity
|
||||
import com.localee.mireo.app.ui.activity.VideoPlayActivity
|
||||
import com.localee.mireo.app.ui.adapter.HomeBannerAdapter
|
||||
import com.localee.mireo.app.ui.adapter.HomeCriticallyAdapter
|
||||
import com.localee.mireo.app.ui.adapter.HomeGenresAdapter
|
||||
import com.localee.mireo.app.ui.adapter.HomeShortAdapter
|
||||
import com.localee.mireo.app.ui.adapter.HomeTopAdapter
|
||||
import com.localee.mireo.app.ui.adapter.TabAdapter
|
||||
import com.localee.mireo.app.ui.adapter.TabAdapter.Companion.TAB_MODE_SLIDING
|
||||
import com.localee.mireo.app.utils.DHStringUtils.getPublicRequest
|
||||
import com.localee.mireo.app.utils.MsMMKVUtils
|
||||
import com.localee.mireo.app.utils.TranslatesUtils
|
||||
import com.youth.banner.Banner
|
||||
import com.youth.banner.listener.OnBannerListener
|
||||
|
||||
class HomeFragment : TitleBarFragment<HomeActivity>(), HomeBannerAdapter.HomeBannerOnClick,
|
||||
TabAdapter.OnTabListener,
|
||||
ViewPager.OnPageChangeListener {
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): HomeFragment {
|
||||
return HomeFragment()
|
||||
}
|
||||
}
|
||||
|
||||
private val searchView: AppCompatImageView? by lazy { findViewById(R.id.iv_home_search) }
|
||||
private val banner: Banner<RecommendBean, HomeBannerAdapter>? by lazy {
|
||||
findViewById(
|
||||
R.id.banner
|
||||
)
|
||||
}
|
||||
|
||||
private val layoutTop: ViewGroup? by lazy { findViewById(R.id.layout_top) }
|
||||
private val tvTopOne: TextView? by lazy { layoutTop?.findViewById(R.id.tv_name) }
|
||||
private val ivTop: ImageView? by lazy { layoutTop?.findViewById(R.id.iv_img) }
|
||||
private val recyclerOne: RecyclerView? by lazy { layoutTop?.findViewById(R.id.recyclerView) }
|
||||
|
||||
private val layoutNew: ViewGroup? by lazy { findViewById(R.id.layout_new) }
|
||||
private val tvTopNew: TextView? by lazy { layoutNew?.findViewById(R.id.tv_name) }
|
||||
private val recyclerNew: RecyclerView? by lazy { layoutNew?.findViewById(R.id.recyclerView) }
|
||||
|
||||
private val layoutShort: ViewGroup? by lazy { findViewById(R.id.layout_short) }
|
||||
private val tvTopShort: TextView? by lazy { layoutShort?.findViewById(R.id.tv_name) }
|
||||
private val recyclerShort: RecyclerView? by lazy { layoutShort?.findViewById(R.id.recyclerView) }
|
||||
|
||||
private val layoutCritically: ViewGroup? by lazy { findViewById(R.id.layout_critically) }
|
||||
private val tvTopCritically: TextView? by lazy { layoutCritically?.findViewById(R.id.tv_name) }
|
||||
private val recyclerCritically: RecyclerView? by lazy { layoutCritically?.findViewById(R.id.recyclerView) }
|
||||
|
||||
private val layoutGenres: ViewGroup? by lazy { findViewById(R.id.layout_genres) }
|
||||
private val tvTopGenres: TextView? by lazy { layoutGenres?.findViewById(R.id.tv_name) }
|
||||
private val recyclerGenres: RecyclerView? by lazy { layoutGenres?.findViewById(R.id.recyclerView) }
|
||||
|
||||
private var bannerAdapter: HomeBannerAdapter? = null
|
||||
|
||||
private var topAdapter: HomeTopAdapter? = null
|
||||
private var newAdapter: HomeTopAdapter? = null
|
||||
private var shortAdapter: HomeShortAdapter? = null
|
||||
private var criticallyAdapter: HomeCriticallyAdapter? = null
|
||||
|
||||
private val nestedScrollView: NestedScrollView? by lazy { findViewById(R.id.nestedScrollView) }
|
||||
private val viewPager: ViewPager? by lazy { findViewById(R.id.viewPager) }
|
||||
private var tabAdapter: TabAdapter? = null
|
||||
private var pagerAdapter: FragmentPagerAdapter<AppFragment<*>>? = null
|
||||
|
||||
private var genresAdapter: HomeGenresAdapter? = null
|
||||
|
||||
private var category: List<HomeCategoriesApi.Bean.Data>? = null
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.home_fragment
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
recyclerOne?.layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
recyclerNew?.layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
recyclerShort?.layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
|
||||
val layoutManager: GridLayoutManager = GridLayoutManager(
|
||||
context, 3, RecyclerView.HORIZONTAL, false
|
||||
)
|
||||
recyclerCritically?.layoutManager = layoutManager
|
||||
|
||||
recyclerGenres?.layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
|
||||
|
||||
topAdapter = HomeTopAdapter(1)
|
||||
recyclerOne?.adapter = topAdapter
|
||||
newAdapter = HomeTopAdapter(2)
|
||||
recyclerNew?.adapter = newAdapter
|
||||
shortAdapter = HomeShortAdapter()
|
||||
recyclerShort?.adapter = shortAdapter
|
||||
criticallyAdapter = HomeCriticallyAdapter()
|
||||
recyclerCritically?.adapter = criticallyAdapter
|
||||
genresAdapter = HomeGenresAdapter(0)
|
||||
recyclerGenres?.adapter = genresAdapter
|
||||
|
||||
|
||||
recyclerCritically?.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
outRect.right = 8
|
||||
outRect.bottom = 28
|
||||
}
|
||||
})
|
||||
|
||||
ivTop?.visibility = View.VISIBLE
|
||||
tvTopOne?.setText("Top 10 Skits This Week")
|
||||
tvTopNew?.setText("New Releases")
|
||||
tvTopShort?.setText("Shorts for You")
|
||||
tvTopCritically?.setText("Critically Acclaimed")
|
||||
tvTopGenres?.setText("Genres to Explore")
|
||||
|
||||
|
||||
// genresAdapter?.submitList(genersList)
|
||||
|
||||
searchView?.setOnClickListener {
|
||||
startActivity(SearchActivity::class.java)
|
||||
}
|
||||
|
||||
pagerAdapter = FragmentPagerAdapter(this)
|
||||
|
||||
tabAdapter = TabAdapter(getAttachActivity()!!, TAB_MODE_SLIDING, false)
|
||||
recyclerGenres?.adapter = tabAdapter
|
||||
|
||||
tabAdapter?.addItem("All")
|
||||
pagerAdapter?.addFragment(HomeCategoriesTabFragment.newInstance("All", 0), "")
|
||||
tabAdapter?.setOnTabListener(this)
|
||||
|
||||
viewPager?.adapter = pagerAdapter
|
||||
viewPager?.addOnPageChangeListener(this@HomeFragment)
|
||||
|
||||
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
getCustomerRegister()
|
||||
|
||||
topAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val data: RecommendBean = adapter.items.get(position)
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
data.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
newAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val data: RecommendBean = adapter.items.get(position)
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
data.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
shortAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val data: RecommendBean = adapter.items.get(position)
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
data.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
criticallyAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val data: RecommendBean = adapter.items.get(position)
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
data.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun isStatusBarEnabled(): Boolean {
|
||||
return !super.isStatusBarEnabled()
|
||||
}
|
||||
|
||||
fun getCustomerRegister() {
|
||||
EasyHttp.post(this)
|
||||
.api(CustomerRegisterApi().apply {
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<CustomerRegisterApi.Bean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<CustomerRegisterApi.Bean>) {
|
||||
result.getData()?.token?.let {
|
||||
MsMMKVUtils.saveToken(it)
|
||||
getCustomerUser()
|
||||
getHomeModuleData()
|
||||
// getCategories()
|
||||
getDayMaxRechargeShortPlayRank();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getHomeModuleData() {
|
||||
EasyHttp.get(this)
|
||||
.api(HomeModuleApi().apply {
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<HomeModuleApi.Bean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<HomeModuleApi.Bean>) {
|
||||
result.getData()?.let {
|
||||
bannerAdapter = it.bannerData?.let { it1 -> HomeBannerAdapter(it1) }
|
||||
bannerAdapter?.homeBannerOnClick =
|
||||
this@HomeFragment
|
||||
banner?.addBannerLifecycleObserver(getAttachActivity())
|
||||
?.setAdapter(bannerAdapter)
|
||||
?.setOnBannerListener(OnBannerListener<Any?> { data, position ->
|
||||
val recommendBean: RecommendBean = it.bannerData!![position]
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
putExtra(
|
||||
CONSTANTS_short_play_id,
|
||||
recommendBean.short_play_id
|
||||
)
|
||||
})
|
||||
})
|
||||
if (it.hotData == null) {
|
||||
layoutTop?.visibility = View.GONE
|
||||
} else {
|
||||
layoutTop?.visibility = View.VISIBLE
|
||||
topAdapter?.submitList(it.hotData)
|
||||
}
|
||||
if (it.manualNewestRecommand == null) {
|
||||
layoutNew?.visibility = View.GONE
|
||||
} else {
|
||||
layoutNew?.visibility = View.VISIBLE
|
||||
newAdapter?.submitList(it.manualNewestRecommand?.list)
|
||||
}
|
||||
if (it.recommandData == null || it.recommandData?.list == null) {
|
||||
layoutShort?.visibility = View.GONE
|
||||
} else {
|
||||
layoutShort?.visibility = View.VISIBLE
|
||||
shortAdapter?.submitList(it.recommandData?.list)
|
||||
}
|
||||
// criticallyAdapter?.submitList(it.newTopThree)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun getDayMaxRechargeShortPlayRank() {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap.put("type", "top_searched")
|
||||
EasyHttp.post(this)
|
||||
.api(HomeDayMaxRechargeShortPlayRankApi().apply {
|
||||
})
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object :
|
||||
HttpCallbackProxy<HttpData<HomeDayMaxRechargeShortPlayRankApi.Bean>>(this) {
|
||||
override fun onHttpStart(api: IRequestApi) {
|
||||
}
|
||||
|
||||
override fun onHttpSuccess(result: HttpData<HomeDayMaxRechargeShortPlayRankApi.Bean>) {
|
||||
if (result.getData() == null) {
|
||||
layoutShort?.visibility = View.GONE
|
||||
} else {
|
||||
result.getData()?.let {
|
||||
layoutShort?.visibility = View.VISIBLE
|
||||
criticallyAdapter?.submitList(it.list)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getCategories() {
|
||||
EasyHttp.get(this)
|
||||
.api(HomeCategoriesApi().apply {
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<HomeCategoriesApi.Bean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<HomeCategoriesApi.Bean>) {
|
||||
result.getData()?.let {
|
||||
category = it.list
|
||||
for (cate in it.list) {
|
||||
tabAdapter?.addItem(cate.name)
|
||||
pagerAdapter?.addFragment(
|
||||
HomeCategoriesTabFragment.newInstance(
|
||||
cate.name,
|
||||
cate.id
|
||||
), ""
|
||||
)
|
||||
}
|
||||
pagerAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fun getCustomerUser() {
|
||||
EasyHttp.get(this)
|
||||
.api(UserInfoApi().apply {
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<UserInfoRes>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<UserInfoRes>) {
|
||||
result.getData()?.let {
|
||||
|
||||
MsMMKVUtils.saveUserInfo(it)
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
}
|
||||
|
||||
override fun bannerAdd(dataRes: RecommendBean) {
|
||||
dataRes.short_play_id?.let { doCollect(it) };
|
||||
}
|
||||
|
||||
override fun bannerPlay(dataRes: RecommendBean) {
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
dataRes.short_play_id.let {
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun doCollect(shortPlayId: Int) {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap["short_play_id"] = shortPlayId.toString()
|
||||
|
||||
EasyHttp.post(this)
|
||||
.api(com.localee.mireo.app.http.api.DoCollectApi())
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object : HttpCallbackProxy<HttpData<Any>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<Any>) {
|
||||
result.getData()?.let {
|
||||
if (it != null) {
|
||||
viewModel.triggerAction(2)
|
||||
viewModel.meToHistoryAction(0)
|
||||
} else {
|
||||
if (TranslatesUtils.translates() != null) {
|
||||
ToastUtils.show(TranslatesUtils.translates()?.network_error.toString())
|
||||
} else {
|
||||
ToastUtils.show(getString(R.string.example_service_exception_please_try_again))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private val viewModel: SharedViewModel by activityViewModels()
|
||||
|
||||
override fun onTabSelected(recyclerView: RecyclerView?, position: Int): Boolean {
|
||||
viewPager?.currentItem = position
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
tabAdapter?.setSelectedPosition(position)
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,385 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.config.IRequestApi
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
import com.hjq.shape.layout.ShapeLinearLayout
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.action.StatusAction
|
||||
import com.localee.mireo.app.app.TitleBarFragment
|
||||
import com.localee.mireo.app.http.api.HistoryBean
|
||||
import com.localee.mireo.app.http.api.MyCollectionsApi
|
||||
import com.localee.mireo.app.http.api.MyHistoryApi
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_activity_id
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_short_play_id
|
||||
import com.localee.mireo.app.ui.activity.HomeActivity
|
||||
import com.localee.mireo.app.ui.activity.VideoPlayActivity
|
||||
import com.localee.mireo.app.ui.adapter.LostTabAdapter
|
||||
import com.localee.mireo.app.utils.DHStringUtils.getPublicRequest
|
||||
import com.localee.mireo.app.widget.StatusLayout
|
||||
import com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener
|
||||
|
||||
|
||||
class ListTabFragment : TitleBarFragment<HomeActivity>(), OnRefreshLoadMoreListener,
|
||||
StatusAction {
|
||||
|
||||
companion object {
|
||||
fun newInstance(tabName: Int): ListTabFragment {
|
||||
return ListTabFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putInt("TAB_NAME", tabName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var tabName: Int? = null
|
||||
|
||||
private val hintLayout: StatusLayout? by lazy { findViewById(R.id.hl_status_hint) }
|
||||
private val recyclerView: RecyclerView? by lazy { findViewById(R.id.recyclerView) }
|
||||
private val rlStatusRefresh: SmartRefreshLayout? by lazy { findViewById(R.id.rl_status_refresh) }
|
||||
private val llDelete: ShapeLinearLayout? by lazy { findViewById(R.id.ll_delete) }
|
||||
private val ivDelete: ImageView? by lazy { findViewById(R.id.iv_delete) }
|
||||
private val tvDelete: TextView? by lazy { findViewById(R.id.tv_delete) }
|
||||
|
||||
private var mAdapter: LostTabAdapter? = null
|
||||
private var pageIndex = 1
|
||||
private var pageTotal = 1
|
||||
private var type = 0
|
||||
private var detailPosition = 0
|
||||
val detailList: MutableList<HistoryBean.Data> = java.util.ArrayList()
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.fragment_list_tab
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun initView() {
|
||||
tabName = arguments?.getInt("TAB_NAME")
|
||||
|
||||
mAdapter = tabName?.let { LostTabAdapter(it) }
|
||||
|
||||
val layoutManager = GridLayoutManager(context, 3)
|
||||
// 设置给 RecyclerView
|
||||
recyclerView!!.layoutManager = layoutManager
|
||||
recyclerView?.adapter = mAdapter
|
||||
recyclerView?.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
outRect.right = 10
|
||||
outRect.left = 10
|
||||
}
|
||||
})
|
||||
|
||||
mAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val historyBean: HistoryBean.Data = adapter.items.get(position)
|
||||
if (!mAdapter?.selectEdit!!) {
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
historyBean.short_play_id.let {
|
||||
historyBean.short_play_video_id.let { it1 ->
|
||||
putExtra(CONSTANTS_activity_id, it1)
|
||||
putExtra(CONSTANTS_short_play_id, it)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (historyBean.is_check) {
|
||||
adapter.items.get(position).is_check = false
|
||||
for (i in detailList.indices) {
|
||||
if (detailList[i].short_play_id == historyBean.short_play_id) {
|
||||
detailList.removeAt(i)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
adapter.items.get(position).is_check = true
|
||||
detailList.add(historyBean)
|
||||
}
|
||||
|
||||
if (detailList.size == 0) {
|
||||
llDelete?.shapeDrawableBuilder?.setStrokeColor(0xFF9D9D9D.toInt())
|
||||
?.intoBackground();
|
||||
context?.resources?.getColor(R.color.example_color_d9d9d9)
|
||||
?.let { tvDelete?.setTextColor(it) }
|
||||
tvDelete?.text = "Delete (0)"
|
||||
ivDelete?.setImageResource(R.mipmap.ic_list_detele_n)
|
||||
} else {
|
||||
llDelete?.shapeDrawableBuilder?.setStrokeColor(0xFFF56490.toInt())
|
||||
?.intoBackground();
|
||||
context?.resources?.getColor(R.color.example_color_F56490)
|
||||
?.let { tvDelete?.setTextColor(it) }
|
||||
tvDelete?.text = "Delete (" + detailList.size + ")"
|
||||
ivDelete?.setImageResource(R.mipmap.ic_list_detele_y)
|
||||
}
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
rlStatusRefresh?.setOnRefreshLoadMoreListener(this)
|
||||
|
||||
llDelete?.setOnClickListener {
|
||||
if (detailList.size != 0) {
|
||||
for (i in detailList.indices) {
|
||||
doCancelCollect(detailList[i].short_play_id, detailList[i].short_play_video_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun setMode() {
|
||||
when (type) {
|
||||
0 -> {
|
||||
val layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
|
||||
// 设置给 RecyclerView
|
||||
recyclerView!!.layoutManager = layoutManager
|
||||
recyclerView?.adapter = mAdapter
|
||||
type = 1
|
||||
mAdapter?.type = type
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
1 -> {
|
||||
// 创建一个 GridLayoutManager,指定列数(例如 3 列)
|
||||
val layoutManager = GridLayoutManager(context, 3)
|
||||
// 设置给 RecyclerView
|
||||
recyclerView!!.layoutManager = layoutManager
|
||||
recyclerView?.adapter = mAdapter
|
||||
type = 0
|
||||
mAdapter?.type = type
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setEdit() {
|
||||
mAdapter?.selectEdit = !mAdapter?.selectEdit!!
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
if (llDelete?.visibility == View.VISIBLE)
|
||||
llDelete?.visibility = View.GONE
|
||||
else
|
||||
llDelete?.visibility = View.VISIBLE
|
||||
|
||||
}
|
||||
|
||||
fun setAllSelect(isSelect: Boolean) {
|
||||
val allData: List<HistoryBean.Data>? = mAdapter?.items
|
||||
if (isSelect) {
|
||||
for (i in allData?.indices!!) {
|
||||
allData[i].is_check = true
|
||||
}
|
||||
allData.let { detailList.addAll(it) }
|
||||
} else {
|
||||
for (i in allData?.indices!!) {
|
||||
allData[i].is_check = false
|
||||
}
|
||||
detailList.clear()
|
||||
}
|
||||
if (detailList.size == 0) {
|
||||
llDelete?.shapeDrawableBuilder?.setStrokeColor(0xFF9D9D9D.toInt())
|
||||
?.intoBackground();
|
||||
context?.resources?.getColor(R.color.example_color_d9d9d9)
|
||||
?.let { tvDelete?.setTextColor(it) }
|
||||
tvDelete?.text = "Delete (0)"
|
||||
ivDelete?.setImageResource(R.mipmap.ic_list_detele_n)
|
||||
} else {
|
||||
llDelete?.shapeDrawableBuilder?.setStrokeColor(0xFFF56490.toInt())
|
||||
?.intoBackground();
|
||||
context?.resources?.getColor(R.color.example_color_F56490)
|
||||
?.let { tvDelete?.setTextColor(it) }
|
||||
tvDelete?.text = "Delete (" + detailList.size + ")"
|
||||
ivDelete?.setImageResource(R.mipmap.ic_list_detele_y)
|
||||
}
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private var isDataLoaded = false
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isVisible && !isDataLoaded) { // 检查是否对用户可见
|
||||
loadData()
|
||||
isDataLoaded = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
when (tabName) {
|
||||
0 -> {
|
||||
myCollections(pageIndex, 15)
|
||||
}
|
||||
|
||||
1 -> {
|
||||
getMyHistory(pageIndex, 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMyHistory(currentPage: Int, pageSize: Int) {
|
||||
EasyHttp.get(this)
|
||||
.api(MyHistoryApi().apply {
|
||||
current_page = currentPage
|
||||
page_size = pageSize
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<HistoryBean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<HistoryBean>) {
|
||||
result.getData()?.let {
|
||||
if (pageIndex == 1) {
|
||||
if (it.list.isEmpty()) {
|
||||
hintLayout?.show()
|
||||
} else {
|
||||
hintLayout?.hide()
|
||||
}
|
||||
mAdapter?.submitList(it.list)
|
||||
pageTotal = it.pagination.page_total
|
||||
} else {
|
||||
mAdapter?.addAll(it.list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHttpFail(throwable: Throwable) {
|
||||
super.onHttpFail(throwable)
|
||||
if (pageIndex == 1) {
|
||||
hintLayout?.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHttpEnd(api: IRequestApi) {
|
||||
super.onHttpEnd(api)
|
||||
if (pageIndex == 1) {
|
||||
rlStatusRefresh?.finishRefresh(200)
|
||||
} else {
|
||||
rlStatusRefresh?.finishLoadMore(200)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun myCollections(currentPage: Int, pageSize: Int) {
|
||||
EasyHttp.get(this)
|
||||
.api(MyCollectionsApi().apply {
|
||||
current_page = currentPage
|
||||
page_size = pageSize
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<HistoryBean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<HistoryBean>) {
|
||||
result.getData()?.let {
|
||||
if (pageIndex == 1) {
|
||||
if (it.list.isEmpty()) {
|
||||
hintLayout?.show()
|
||||
} else {
|
||||
hintLayout?.hide()
|
||||
}
|
||||
mAdapter?.submitList(it.list)
|
||||
pageTotal = it.pagination.page_total
|
||||
} else {
|
||||
mAdapter?.addAll(it.list)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onHttpFail(throwable: Throwable) {
|
||||
super.onHttpFail(throwable)
|
||||
if (pageIndex == 1) {
|
||||
hintLayout?.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHttpEnd(api: IRequestApi) {
|
||||
super.onHttpEnd(api)
|
||||
if (pageIndex == 1) {
|
||||
rlStatusRefresh?.finishRefresh(200)
|
||||
} else {
|
||||
rlStatusRefresh?.finishLoadMore(200)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun doCancelCollect(shortPlayId: Int, videoId: Int) {
|
||||
val sMap: MutableMap<String, String?> = LinkedHashMap()
|
||||
// StringMap = getSortMap(StringMap);
|
||||
sMap.put("short_play_id", shortPlayId.toString())
|
||||
sMap.put("video_id", videoId.toString())
|
||||
|
||||
EasyHttp.post(this)
|
||||
.api(com.localee.mireo.app.http.api.CancelCollectApi())
|
||||
.body(getPublicRequest(sMap))
|
||||
.request(object : HttpCallbackProxy<HttpData<Any>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<Any>) {
|
||||
result.getData()?.let {
|
||||
viewModel.listTabAction(0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHttpEnd(api: IRequestApi) {
|
||||
super.onHttpEnd(api)
|
||||
detailPosition++
|
||||
if (detailPosition == detailList.size) {
|
||||
pageIndex = 1
|
||||
mAdapter?.selectEdit = false
|
||||
loadData()
|
||||
llDelete?.visibility = View.GONE
|
||||
detailList.clear()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private val viewModel: SharedViewModel by activityViewModels()
|
||||
|
||||
fun onRefreshData() {
|
||||
if (isDataLoaded) {
|
||||
pageIndex = 1
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefresh(refreshLayout: RefreshLayout) {
|
||||
pageIndex = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
override fun onLoadMore(refreshLayout: RefreshLayout) {
|
||||
if (pageIndex == pageTotal) {
|
||||
rlStatusRefresh?.finishLoadMore(1000)
|
||||
} else {
|
||||
pageIndex++
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStatusLayout(): StatusLayout? {
|
||||
return hintLayout
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatCheckBox
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.hjq.base.FragmentPagerAdapter
|
||||
import com.lxj.xpopup.XPopup
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.app.AppFragment
|
||||
import com.localee.mireo.app.app.TitleBarFragment
|
||||
import com.localee.mireo.app.ui.activity.HomeActivity
|
||||
import com.localee.mireo.app.ui.adapter.TabAdapter
|
||||
import com.localee.mireo.app.ui.popup.CustomBubbleAttachPopup
|
||||
import com.localee.mireo.app.ui.popup.CustomBubbleAttachPopup.CustomPopupOnclick
|
||||
|
||||
|
||||
class MessageFragment : TitleBarFragment<HomeActivity>(), TabAdapter.OnTabListener,
|
||||
ViewPager.OnPageChangeListener {
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): MessageFragment {
|
||||
return MessageFragment()
|
||||
}
|
||||
}
|
||||
|
||||
private val ivMore: ImageView? by lazy { findViewById(R.id.iv_more) }
|
||||
private val tabView: RecyclerView? by lazy { findViewById(R.id.rv_list_tab) }
|
||||
private val viewPager: ViewPager? by lazy { findViewById(R.id.viewPager) }
|
||||
private val tvCancel: TextView? by lazy { findViewById(R.id.tv_cancel) }
|
||||
private val cbSelectCheck: AppCompatCheckBox? by lazy { findViewById(R.id.cb_select_check) }
|
||||
|
||||
private var tabAdapter: TabAdapter? = null
|
||||
private var pagerAdapter: FragmentPagerAdapter<AppFragment<*>>? = null
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.message_fragment
|
||||
}
|
||||
|
||||
private val viewModel: SharedViewModel by activityViewModels()
|
||||
|
||||
var modeOne: Int = 0
|
||||
var modeTwo: Int = 0
|
||||
var mode: Int = 0
|
||||
|
||||
override fun initView() {
|
||||
|
||||
ivMore?.setOnClickListener {
|
||||
XPopup.Builder(context)
|
||||
.hasShadowBg(false)
|
||||
.isTouchThrough(true)
|
||||
.atView(ivMore)
|
||||
.hasShadowBg(false)
|
||||
.hasNavigationBar(false)
|
||||
.asCustom(context?.let { it1 ->
|
||||
CustomBubbleAttachPopup(
|
||||
it1,
|
||||
viewPager?.currentItem,
|
||||
mode,
|
||||
object : CustomPopupOnclick {
|
||||
override fun onMode() {
|
||||
|
||||
when (viewPager?.currentItem) {
|
||||
0 -> {
|
||||
if (modeOne == 0) {
|
||||
modeOne = 1
|
||||
} else {
|
||||
modeOne = 0
|
||||
}
|
||||
mode = modeOne
|
||||
listTabOneFragment.setMode()
|
||||
}
|
||||
|
||||
1 -> {
|
||||
if (modeTwo == 0) {
|
||||
modeTwo = 1
|
||||
} else {
|
||||
modeTwo = 0
|
||||
}
|
||||
mode = modeTwo
|
||||
listTabTwoFragment.setMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEdit() {
|
||||
if (viewPager?.currentItem == 0) {
|
||||
tvCancel?.visibility = View.VISIBLE
|
||||
ivMore?.visibility = View.GONE
|
||||
tabView?.visibility = View.INVISIBLE
|
||||
cbSelectCheck?.visibility = View.VISIBLE
|
||||
listTabOneFragment.setEdit()
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.show()
|
||||
}
|
||||
|
||||
tvCancel?.setOnClickListener {
|
||||
tvCancel?.visibility = View.GONE
|
||||
ivMore?.visibility = View.VISIBLE
|
||||
tabView?.visibility = View.VISIBLE
|
||||
cbSelectCheck?.visibility = View.GONE
|
||||
listTabOneFragment.setEdit()
|
||||
}
|
||||
|
||||
cbSelectCheck?.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
if (isChecked) {
|
||||
listTabOneFragment.setAllSelect(true)
|
||||
} else {
|
||||
listTabOneFragment.setAllSelect(false)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.listTabAction.observe(this) { data ->
|
||||
tvCancel?.visibility = View.GONE
|
||||
ivMore?.visibility = View.VISIBLE
|
||||
tabView?.visibility = View.VISIBLE
|
||||
cbSelectCheck?.isChecked = false
|
||||
cbSelectCheck?.visibility = View.GONE
|
||||
listTabOneFragment.setEdit()
|
||||
}
|
||||
|
||||
viewModel.meToHistoryAction.observe(this) { data ->
|
||||
viewPager?.currentItem = data
|
||||
when(data) {
|
||||
0 -> {
|
||||
listTabOneFragment.onRefreshData()
|
||||
}
|
||||
1 -> {
|
||||
listTabTwoFragment.onRefreshData()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
val listTabOneFragment: ListTabFragment = ListTabFragment.newInstance(0)
|
||||
val listTabTwoFragment: ListTabFragment = ListTabFragment.newInstance(1)
|
||||
|
||||
fun initViewA() {
|
||||
pagerAdapter = FragmentPagerAdapter(this)
|
||||
pagerAdapter!!.addFragment(listTabOneFragment, "")
|
||||
pagerAdapter!!.addFragment(listTabTwoFragment, "")
|
||||
// 设置 Adapter
|
||||
viewPager?.adapter = pagerAdapter
|
||||
viewPager?.addOnPageChangeListener(this)
|
||||
|
||||
tabAdapter = TabAdapter(getAttachActivity()!!)
|
||||
tabView?.adapter = tabAdapter
|
||||
|
||||
tabAdapter?.addItem("Follow List")
|
||||
tabAdapter?.addItem("Play List")
|
||||
tabAdapter?.setOnTabListener(this)
|
||||
|
||||
|
||||
}
|
||||
|
||||
private var isDataLoaded = false
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isVisible && !isDataLoaded) {
|
||||
initViewA()
|
||||
isDataLoaded = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun initData() {}
|
||||
|
||||
|
||||
override fun onTabSelected(recyclerView: RecyclerView?, position: Int): Boolean {
|
||||
viewPager?.currentItem = position
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
tabAdapter?.setSelectedPosition(position)
|
||||
when (position) {
|
||||
0 -> {
|
||||
mode = modeOne
|
||||
}
|
||||
|
||||
1 -> {
|
||||
mode = modeTwo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.hjq.http.EasyHttp
|
||||
import com.hjq.http.listener.HttpCallbackProxy
|
||||
import com.localee.mireo.app.R
|
||||
import com.localee.mireo.app.aop.SingleClick
|
||||
import com.localee.mireo.app.app.TitleBarFragment
|
||||
import com.localee.mireo.app.http.api.HistoryBean
|
||||
import com.localee.mireo.app.http.api.MyHistoryApi
|
||||
import com.localee.mireo.app.http.api.UserInfoApi
|
||||
import com.localee.mireo.app.http.api.UserInfoRes
|
||||
import com.localee.mireo.app.http.model.HttpData
|
||||
import com.localee.mireo.app.other.MsConstants
|
||||
import com.localee.mireo.app.other.MsConstants.CONSTANTS_short_play_id
|
||||
import com.localee.mireo.app.ui.activity.AboutActivity
|
||||
import com.localee.mireo.app.ui.activity.BrowserActivity
|
||||
import com.localee.mireo.app.ui.activity.HomeActivity
|
||||
import com.localee.mireo.app.ui.activity.SettingActivity
|
||||
import com.localee.mireo.app.ui.activity.VideoPlayActivity
|
||||
import com.localee.mireo.app.ui.adapter.MeHistoryAdapter
|
||||
import com.localee.mireo.app.utils.MsMMKVUtils
|
||||
|
||||
|
||||
class MineFragment : TitleBarFragment<HomeActivity>() {
|
||||
|
||||
private val tvId: TextView? by lazy { findViewById(R.id.tv_id) }
|
||||
private val recyclerView: RecyclerView? by lazy { findViewById(R.id.recyclerView) }
|
||||
|
||||
private var mAdapter: MeHistoryAdapter? = null
|
||||
|
||||
private val viewModel: SharedViewModel by activityViewModels()
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): MineFragment {
|
||||
return MineFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.mine_fragment
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
setOnClickListener(
|
||||
R.id.sb_play_list,
|
||||
R.id.sb_setting,
|
||||
R.id.sb_privacy,
|
||||
R.id.sb_agreement,
|
||||
R.id.sb_about
|
||||
)
|
||||
|
||||
recyclerView?.layoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
|
||||
mAdapter = MeHistoryAdapter()
|
||||
recyclerView?.adapter = mAdapter
|
||||
|
||||
mAdapter?.setOnItemClickListener { adapter, view, position ->
|
||||
val data: HistoryBean.Data = adapter.items[position]
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
VideoPlayActivity::class.java
|
||||
).apply {
|
||||
putExtra(CONSTANTS_short_play_id, data.short_play_id)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
tvId?.text = "ID:".plus(MsMMKVUtils.getUserInfo()?.customer_id)
|
||||
}
|
||||
|
||||
private var isDataLoaded = false
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (isVisible && !isDataLoaded) {
|
||||
getCustomerUser()
|
||||
isDataLoaded = true
|
||||
}
|
||||
getMyHistory(1, 20)
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
override fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.sb_play_list -> {
|
||||
viewModel.triggerAction(2)
|
||||
viewModel.meToHistoryAction(1)
|
||||
}
|
||||
|
||||
R.id.sb_setting -> {
|
||||
startActivity(SettingActivity::class.java)
|
||||
}
|
||||
|
||||
R.id.sb_privacy -> {
|
||||
BrowserActivity.start(getAttachActivity()!!, MsConstants.Constants_privacy_policy)
|
||||
}
|
||||
|
||||
R.id.sb_agreement -> {
|
||||
BrowserActivity.start(getAttachActivity()!!, MsConstants.Constants_user_agreement)
|
||||
}
|
||||
|
||||
R.id.sb_about -> {
|
||||
startActivity(AboutActivity::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCustomerUser() {
|
||||
EasyHttp.get(this)
|
||||
.api(UserInfoApi().apply {
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<UserInfoRes>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<UserInfoRes>) {
|
||||
result.getData()?.let {
|
||||
|
||||
MsMMKVUtils.saveUserInfo(it)
|
||||
tvId?.text = "ID:".plus(MsMMKVUtils.getUserInfo()?.customer_id)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private fun getMyHistory(currentPage: Int, pageSize: Int) {
|
||||
EasyHttp.get(this)
|
||||
.api(MyHistoryApi().apply {
|
||||
current_page = currentPage
|
||||
page_size = pageSize
|
||||
})
|
||||
.request(object : HttpCallbackProxy<HttpData<HistoryBean>>(this) {
|
||||
override fun onHttpSuccess(result: HttpData<HistoryBean>) {
|
||||
result.getData()?.let {
|
||||
mAdapter?.submitList(it.list)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun isStatusBarEnabled(): Boolean {
|
||||
return !super.isStatusBarEnabled()
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.localee.mireo.app.ui.fragment
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class SharedViewModel : ViewModel() {
|
||||
private val _action = MutableLiveData<Int>()
|
||||
val action: LiveData<Int> get() = _action
|
||||
|
||||
fun triggerAction(data: Int) {
|
||||
_action.value = data
|
||||
}
|
||||
|
||||
private val _listTabAction = MutableLiveData<Int>()
|
||||
val listTabAction: LiveData<Int> get() = _listTabAction
|
||||
|
||||
fun listTabAction(data: Int) {
|
||||
_listTabAction.value = data
|
||||
}
|
||||
|
||||
private val _meToHistoryAction = MutableLiveData<Int>()
|
||||
val meToHistoryAction: LiveData<Int> get() = _meToHistoryAction
|
||||
|
||||
fun meToHistoryAction(data: Int) {
|
||||
_meToHistoryAction.value = data
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.localee.mireo.app.ui.popup
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import com.lxj.xpopup.core.BubbleAttachPopupView
|
||||
import com.localee.mireo.app.R
|
||||
|
||||
class CustomBubbleAttachPopup(context: Context,var tabPosition: Int?,var mode: Int, val popupOnclick: CustomPopupOnclick?) :
|
||||
BubbleAttachPopupView(context) {
|
||||
interface CustomPopupOnclick {
|
||||
fun onMode()
|
||||
|
||||
fun onEdit()
|
||||
}
|
||||
|
||||
|
||||
override fun getImplLayoutId(): Int {
|
||||
return R.layout.custom_bubble_attach_popup
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
val tvMode = findViewById<TextView>(R.id.tv_mode)
|
||||
val tvEdit = findViewById<TextView>(R.id.tv_edit)
|
||||
if (tabPosition == 0) {
|
||||
tvEdit.visibility = View.VISIBLE
|
||||
} else {
|
||||
tvEdit.visibility = View.GONE
|
||||
}
|
||||
if (mode == 0) {
|
||||
tvMode.text = "List mode"
|
||||
} else {
|
||||
tvMode.text = "Grid mode"
|
||||
}
|
||||
tvMode.setOnClickListener {
|
||||
popupOnclick?.onMode()
|
||||
dismiss()
|
||||
}
|
||||
tvEdit.setOnClickListener {
|
||||
popupOnclick?.onEdit()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package com.localee.mireo.app.ui.videoPaly
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
data class ExamplePlayerDetailDataRes(
|
||||
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 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 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().toString(),
|
||||
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.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 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.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.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
|
||||
)
|
||||
}
|
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