Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 113ebb36e9 | |||
| d0c9bd8038 | |||
| 104586fb7f | |||
| 1bc5bb3ef6 | |||
| 2719bff65f | |||
| b87972143d | |||
| 0cdec2a226 | |||
| 545c235b24 | |||
| 53d3cb320b | |||
| 38682f01a8 | |||
| 13a76e8de7 | |||
| 1e98fa98c3 | |||
| 20bc38add4 | |||
| efabaafa38 | |||
| 26927661e7 | |||
| 15ba945751 | |||
| 8e0527b777 | |||
| b9dfa0a8a9 | |||
| c462973eb6 | |||
| b8cefd69c0 | |||
| 1c1537be8a | |||
| 1dad632c70 | |||
| 41600c7576 | |||
| 5f0074c88d | |||
| 907f2a2678 | |||
| 4a118bd51c | |||
| 4919b46e5d | |||
| 034a6662f9 | |||
| 3fb1c9f315 | |||
| aed4610afd | |||
| 345be8035a | |||
| 68c7b0ddaf | |||
| f39ce00152 | |||
| 0b6d1bd6df | |||
| dca7a44884 | |||
| d90cdf341e | |||
| 7828189ea0 | |||
| e4cd8da65c | |||
| 8cebbd3bbe | |||
| 63d9b354d4 | |||
| 254944fbfc | |||
| ec93080190 | |||
| ec638cb231 | |||
| 7c72623f90 | |||
| 2e58404e01 | |||
| 5eae896330 | |||
| 6c2dcc7d37 | |||
| d40e4e97c1 | |||
| 3164ed1b0e | |||
| b49fae0384 | |||
| 80544aff32 | |||
| 64235951c2 | |||
| f08fe7d855 | |||
| ff1a9e8694 | |||
| 2abf87628a | |||
| e835482abd | |||
| e78882e911 | |||
| b021d99f78 | |||
| 084781dc0a | |||
| ce83fed40d | |||
| 24d16a234f | |||
| 536af50a4f | |||
| 9eccc459d9 | |||
| 6e8310e4c9 | |||
| 35e79f938c | |||
| 10764ac3f4 | |||
| 2a6ecfa176 | |||
| 5b44c7f856 | |||
| 1e5e36a8c7 | |||
| 92dda8e64c | |||
| 27488e8084 | |||
| 72871e55c6 | |||
| 07c05b2191 | |||
| 89d2fb98fa | |||
| 6d1719b877 | |||
| 51599d5bb4 | |||
| aedaee8d3a | |||
| 82a859e820 | |||
| c1c655fcb0 | |||
| fabcce9a6c | |||
| 16feb963f6 | |||
| c7db58f6ea | |||
| 79ff887375 | |||
| e7ae608986 | |||
| 7ec4625d45 | |||
| 4f68f30576 | |||
| 135d717715 | |||
| 77c3131a69 | |||
| 7e74cbfbd1 | |||
| a2cd548d1e | |||
| 0a4d6122df | |||
| 23d1435ed2 | |||
| dd60900bcb | |||
| 0fbb0aa363 | |||
| 23539b9316 | |||
| a1460b07c6 | |||
| 02b6c2733b | |||
| 1d29d68aa2 | |||
| aa76a20065 | |||
| ec945919ba | |||
| e626e82945 | |||
| 6e238379f2 | |||
| 7a4ae83a2b | |||
| 46827b1489 | |||
| 762897521b | |||
| b8d74357b5 | |||
| 21c116ea5b | |||
| 2cf23b9a32 | |||
| 6b03098ac7 | |||
| bcd846024e | |||
| d98edc8f77 | |||
| faef2a5e4d | |||
| 3d88792d11 | |||
| f7fe7a5153 | |||
| 9aeb1624a6 | |||
| ec9c282618 | |||
| 7e1da213d5 | |||
| 8d9fd482b9 | |||
| c87bf1e613 | |||
| 81dc17530f | |||
| b53f769a0d | |||
| aadd2071b9 | |||
| fc7566d2c9 | |||
| 7f082b7a36 | |||
| bebda2de70 | |||
| 3e0887b5f9 | |||
| a8894cc464 |
@ -23,6 +23,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
// jumboMode = true
|
||||
javaMaxHeapSize "4g"
|
||||
@ -183,6 +187,7 @@ dependencies {
|
||||
debugImplementation "com.facebook.stetho:stetho:${stetho}"
|
||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:${stetho}"
|
||||
debugImplementation "com.squareup.okhttp3:logging-interceptor:${okHttp}"
|
||||
debugImplementation "com.gu.android:toolargetool:${toolargetool}"
|
||||
|
||||
implementation "androidx.core:core:${core}"
|
||||
implementation "androidx.fragment:fragment:${fragment}"
|
||||
@ -192,14 +197,18 @@ dependencies {
|
||||
implementation "androidx.annotation:annotation:${annotation}"
|
||||
implementation "androidx.constraintlayout:constraintlayout:${constraintLayout}"
|
||||
implementation "androidx.recyclerview:recyclerview:${recyclerView}"
|
||||
implementation "androidx.lifecycle:lifecycle-runtime:${lifeCycle}"
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:${lifeCycle}"
|
||||
kapt "androidx.lifecycle:lifecycle-compiler:${lifeCycle}"
|
||||
// implementation "androidx.lifecycle:lifecycle-runtime:${lifeCycle}"
|
||||
// implementation "androidx.lifecycle:lifecycle-extensions:${lifeCycle}"
|
||||
// kapt "androidx.lifecycle:lifecycle-compiler:${lifeCycle}"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifeCycle"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifeCycle"
|
||||
implementation "androidx.lifecycle:lifecycle-common-java8:$lifeCycle"
|
||||
implementation "androidx.room:room-runtime:${room}"
|
||||
implementation "androidx.room:room-rxjava2:${room}"
|
||||
implementation "androidx.core:core-ktx:${ktx}"
|
||||
implementation "androidx.viewpager2:viewpager2:${viewpager2}"
|
||||
kapt "androidx.room:room-compiler:${room}"
|
||||
kapt "androidx.databinding:databinding-compiler:${databinding}"
|
||||
// kapt "androidx.databinding:databinding-compiler:${databinding}"
|
||||
|
||||
implementation "com.google.android.material:material:${material}"
|
||||
|
||||
@ -241,13 +250,13 @@ dependencies {
|
||||
// bugly with tinker support
|
||||
implementation "com.tencent.bugly:crashreport_upgrade:${buglyTinkerSupport}"
|
||||
|
||||
implementation 'com.google.android:flexbox:1.1.0'
|
||||
implementation "com.google.android:flexbox:${flexbox}"
|
||||
|
||||
implementation "pub.devrel:easypermissions:${easypermissions}"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation 'com.contrarywind:Android-PickerView:4.1.8'
|
||||
implementation "com.contrarywind:Android-PickerView:${pickerView}"
|
||||
|
||||
implementation "com.scwang.smartrefresh:SmartRefreshLayout:${smartRefreshLayout}"
|
||||
implementation "net.cachapa.expandablelayout:expandablelayout:${expandableLayout}"
|
||||
@ -271,20 +280,20 @@ dependencies {
|
||||
|
||||
implementation "android.arch.work:work-runtime:${workManager}"
|
||||
|
||||
implementation "com.llew.huawei:verifier:1.0.6"
|
||||
implementation "com.llew.huawei:verifier:${verifier}"
|
||||
|
||||
implementation "com.github.tbruyelle:rxpermissions:${rxPermissions}"
|
||||
|
||||
implementation 'com.ethanhua:skeleton:1.1.1'
|
||||
implementation 'io.supercharge:shimmerlayout:2.1.0'
|
||||
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:5.3.1"
|
||||
implementation 'com.walkud.rom.checker:RomChecker:1.0.0'
|
||||
implementation "com.ethanhua:skeleton:${skeleton}"
|
||||
implementation "io.supercharge:shimmerlayout:${shimmerlayout}"
|
||||
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:${mta}"
|
||||
implementation "com.walkud.rom.checker:RomChecker:${romChecker}"
|
||||
|
||||
debugImplementation "com.github.nichbar.chucker:library:$chucker"
|
||||
releaseImplementation "com.github.nichbar.chucker:library-no-op:$chucker"
|
||||
implementation "com.bytedance.applog:RangersAppLog-Lite-cn:$bytedanceApplog"
|
||||
|
||||
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.2'
|
||||
implementation "com.aliyun.dpa:oss-android-sdk:${oss}"
|
||||
|
||||
implementation "com.airbnb.android:lottie:$lottie"
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import android.app.Application;
|
||||
|
||||
import com.facebook.stetho.Stetho;
|
||||
import com.facebook.stetho.okhttp3.StethoInterceptor;
|
||||
import com.gu.toolargetool.TooLargeTool;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
@ -29,7 +30,7 @@ public class Injection {
|
||||
|
||||
// init stetho
|
||||
Stetho.initializeWithDefaults(application);
|
||||
|
||||
TooLargeTool.startLogging(application);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -6,13 +6,16 @@
|
||||
<link rel="stylesheet" type="text/css" href="normalize.css">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="video-js.min.css">
|
||||
<!-- <link rel="stylesheet" href="https://static-web.ghzs.com/website-static/lib/video-js.min.css">--> <!--在web页面播放视频-->
|
||||
<!--<link rel="stylesheet" type="text/css" href="https://resource.ghzs.com/css/halo_app.css">-->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body style="overflow-x: hidden; word-break: break-all;">
|
||||
<div id="editor" contenteditable="false"></div>
|
||||
<script type="text/javascript" src="zepto.min.js"></script>
|
||||
<script type="text/javascript" src="rich_editor.js"></script>
|
||||
<script type="text/javascript" src="video.min.js"></script>
|
||||
<!--<script src="https://static-web.ghzs.com/website-static/lib/video.min.js"></script>--> <!--在web页面播放视频-->
|
||||
<!--<script type="text/javascript" src="content.js"></script>-->
|
||||
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
|
||||
</body>
|
||||
|
||||
1
app/src/main/assets/lottie/follow.json
Normal file
1
app/src/main/assets/lottie/follow.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -624,3 +624,18 @@ function customLinkgo(self) {
|
||||
// console.log(datas)
|
||||
window.OnLinkClickListener.onClick(datas)
|
||||
}
|
||||
|
||||
// 在web页面播放视频
|
||||
//RE.initArticleVideo = function(){
|
||||
// initArticleVideo()
|
||||
//}
|
||||
|
||||
function showNativeDialog(title, message, positive, negative, callback) {
|
||||
var jsCallbackCode = "(" + function (v) {
|
||||
window.onNativeDialogCallback(v);
|
||||
delete window.onNativeDialogCallback;
|
||||
}.toString() + ")";
|
||||
|
||||
window.onNativeDialogCallback = callback;
|
||||
window.NativeCallBack.showDialog(title, message, positive, negative, jsCallbackCode);
|
||||
}
|
||||
@ -65,7 +65,9 @@ public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallba
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
AppManager.getInstance().finishActivity(activity);
|
||||
if (activity.isFinishing()) {
|
||||
AppManager.getInstance().finishActivity(activity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,9 +9,20 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler;
|
||||
import com.gh.common.syncpage.SyncDataEntity;
|
||||
import com.gh.common.syncpage.SyncPageRepository;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.eventbus.EBMiPush;
|
||||
import com.lightgame.OnTitleClickListener;
|
||||
@ -23,18 +34,14 @@ import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import kotlin.Pair;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
@ -141,6 +148,49 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
ButterKnife.bind(this, mCachedView);
|
||||
|
||||
initView(mCachedView);
|
||||
|
||||
if (addSyncPageObserver()) {
|
||||
initSyncPageObserver();
|
||||
}
|
||||
}
|
||||
|
||||
private void initSyncPageObserver() {
|
||||
SyncPageRepository.INSTANCE.getSyncPageLiveData().observe(this, syncDataEntities -> {
|
||||
try {
|
||||
Utils.log("SyncPageRepository initSyncPageObserver->" + syncDataEntities);
|
||||
List<SyncDataEntity> readyRemoveList = new ArrayList<>();
|
||||
if (syncDataEntities == null || syncDataEntities.isEmpty()) return;
|
||||
RecyclerView.Adapter adapter = provideSyncAdapter();
|
||||
if (!(adapter instanceof ISyncAdapterHandler)) return;
|
||||
for (int i = 0; i < adapter.getItemCount(); i++) {
|
||||
Pair<String, Object> syncKey = ((ISyncAdapterHandler) adapter).getSyncData(i);
|
||||
if (syncKey == null) continue;
|
||||
for (SyncDataEntity syncDataEntity : syncDataEntities) {
|
||||
if (syncDataEntity.getSyncId().equals(syncKey.getFirst())) {
|
||||
boolean isSuccess = SyncPageRepository.INSTANCE.handleSyncData(syncKey.getSecond(), syncDataEntity);
|
||||
if (isSuccess) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("SyncPageRepository notify position->" + i);
|
||||
}
|
||||
adapter.notifyItemChanged(i);
|
||||
|
||||
if (syncDataEntity.getRemove()) {
|
||||
readyRemoveList.add(syncDataEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBaseHandler.postDelayed(() -> SyncPageRepository.removeSyncData(readyRemoveList), 2000);
|
||||
} catch (Exception e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw e;
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 必须的有subscribe才能register
|
||||
@ -183,11 +233,7 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
try {
|
||||
Utils.toast(getContext(), msg);
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
Utils.toast(getContext(), msg);
|
||||
}
|
||||
|
||||
public void toastLong(@StringRes int msg) {
|
||||
@ -255,4 +301,12 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected RecyclerView.Adapter provideSyncAdapter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean addSyncPageObserver() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,10 +12,10 @@ abstract class BaseLazyFragment : NormalFragment() {
|
||||
|
||||
private var isViewCreated = false
|
||||
|
||||
private var isSupportVisible = false
|
||||
protected var isSupportVisible = false
|
||||
|
||||
/**
|
||||
* 用于分发可见时间的时候父获取 fragment 是否隐藏
|
||||
* 用于分发可见时间的时候获取 父fragment 是否隐藏
|
||||
*
|
||||
* @return true fragment 不可见, false 父 fragment 可见
|
||||
*/
|
||||
|
||||
@ -6,9 +6,11 @@ import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.LoginActivity
|
||||
import com.gh.gamecenter.ViewImageActivity
|
||||
import com.gh.gamecenter.entity.Badge
|
||||
import com.gh.gamecenter.entity.MtaEvent
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -76,6 +78,11 @@ class DefaultJsApi(var context: Context) {
|
||||
return HaloApp.getInstance().channel
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun getAppVersion(msg: Any): String {
|
||||
return BuildConfig.VERSION_NAME
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun bindWechat(msg: Any, handler: CompletionHandler<Any>) {
|
||||
context.ifLogin("浏览器") {
|
||||
@ -144,9 +151,6 @@ class DefaultJsApi(var context: Context) {
|
||||
context?.startActivity(ViewImageActivity.getBase64ViewImageIntent(context, true))
|
||||
}
|
||||
|
||||
@Keep
|
||||
internal data class MtaEvent(var name: String = "", var key: String = "", var value: String = "")
|
||||
|
||||
@Keep
|
||||
internal data class ImageEvent(var imageList: ArrayList<String> = arrayListOf(), var position: Int = 0)
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.EntranceUtils.ENTRANCE_BROWSER
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.LibaoDetailActivity
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
@ -15,7 +16,9 @@ import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.lightgame.utils.Utils
|
||||
import com.moor.imkf.requesturl.RequestUrl.type
|
||||
|
||||
object DefaultWebViewUrlHandler {
|
||||
|
||||
@ -124,8 +127,17 @@ object DefaultWebViewUrlHandler {
|
||||
}
|
||||
EntranceUtils.HOST_USERHOME -> {
|
||||
val position = uri.getQueryParameter("position")
|
||||
DirectUtils.directToHomeActivity(context, id, if(position.isNullOrEmpty()) -1 else position.toInt(), entrance, "")
|
||||
DirectUtils.directToHomeActivity(context, id, if (position.isNullOrEmpty()) -1 else position.toInt(), entrance, "")
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_VIDEO_MORE -> {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
val type = uri.getQueryParameter("type") ?: ""
|
||||
val act = uri.getQueryParameter("act") ?: ""
|
||||
val loaction = if (TextUtils.isEmpty(act)) id else VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value
|
||||
DirectUtils.directToVideoDetail(context, id, loaction, false, "", entrance, "", referer, type, act)
|
||||
}
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
|
||||
16
app/src/main/java/com/gh/common/annotation/SyncIgnore.java
Normal file
16
app/src/main/java/com/gh/common/annotation/SyncIgnore.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.gh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 标记那些不需要检查的同步字段
|
||||
*
|
||||
* 同步字段冲突时使用
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncIgnore {
|
||||
}
|
||||
12
app/src/main/java/com/gh/common/annotation/SyncPage.java
Normal file
12
app/src/main/java/com/gh/common/annotation/SyncPage.java
Normal file
@ -0,0 +1,12 @@
|
||||
package com.gh.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncPage {
|
||||
String[] syncNames();
|
||||
}
|
||||
@ -5,8 +5,6 @@ import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
@ -25,6 +23,7 @@ import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
||||
@ -62,6 +62,8 @@ public class Constants {
|
||||
public static final String SP_ADDONS_FUNCS_HAVE_READ = "addons_funcs_have_read";
|
||||
//视频非wifi提醒只提醒一次,重启恢复
|
||||
public static final String SP_NON_WIFI_TIPS = "non_wifi_tips";
|
||||
//首页视频最新tab提示
|
||||
public static final String SP_HOME_NEW_VIDEO_TIPS = "home_new_video";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
|
||||
@ -37,7 +37,7 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
titleTv.text = mNotificationHint?.title
|
||||
|
||||
contentContainer.removeAllViews()
|
||||
for (item in mNotificationHint?.content!!) {
|
||||
for (item in mNotificationHint?.content ?: arrayListOf()) {
|
||||
val tv = TextView(context)
|
||||
|
||||
tv.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
interface ISyncAdapterHandler {
|
||||
|
||||
/**
|
||||
* @param position position to query
|
||||
* @return Pair first: item sync id
|
||||
* Pair second: item data entity
|
||||
*/
|
||||
fun getSyncData(position: Int): Pair<String, Any>?
|
||||
|
||||
}
|
||||
43
app/src/main/java/com/gh/common/syncpage/SyncDataEntity.kt
Normal file
43
app/src/main/java/com/gh/common/syncpage/SyncDataEntity.kt
Normal file
@ -0,0 +1,43 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
import androidx.annotation.Keep
|
||||
|
||||
@Keep
|
||||
data class SyncDataEntity(
|
||||
/**
|
||||
* 标识一条数据的唯一ID
|
||||
*
|
||||
* 与[ISyncAdapterHandler.getSyncData]返回的Pair first一致
|
||||
*/
|
||||
val syncId: String,
|
||||
|
||||
/**
|
||||
* 需要同步的字段名
|
||||
*
|
||||
* 与@SyncPage注解的值一致
|
||||
*/
|
||||
val syncFieldName: String?,
|
||||
|
||||
/**
|
||||
* 需要同步的具体内容
|
||||
*/
|
||||
val syncFieldValue: Any?,
|
||||
|
||||
/**
|
||||
* 同步完一次是否自动删除
|
||||
*/
|
||||
val remove: Boolean = true,
|
||||
|
||||
/**
|
||||
* 是否需要查询同步实体的父级字段
|
||||
*
|
||||
* 由于反射可能会导致较大的性能消耗,默认关闭,具体按实际情况开启
|
||||
*/
|
||||
val checkInherited: Boolean = false,
|
||||
|
||||
/**
|
||||
* 是否需要查询同步实体的嵌套实体内容
|
||||
*
|
||||
* 由于反射可能会导致较大的性能消耗,默认关闭,具体按实际情况开启
|
||||
*/
|
||||
val checkFieldEntity: Boolean = false)
|
||||
@ -0,0 +1,17 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
object SyncFieldConstants {
|
||||
|
||||
// 是否点赞
|
||||
const val ANSWER_VOTE = "ANSWER_VOTE"
|
||||
const val ARTICLE_VOTE = "ARTICLE_VOTE"
|
||||
|
||||
// 赞同数量
|
||||
const val ANSWER_VOTE_COUNT = "ANSWER_VOTE_COUNT"
|
||||
const val ARTICLE_VOTE_COUNT = "ARTICLE_VOTE_COUNT"
|
||||
|
||||
// 评论数量
|
||||
const val ANSWER_COMMENT_COUNT = "ANSWER_COMMENT_COUNT"
|
||||
const val ARTICLE_COMMENT_COUNT = "ARTICLE_COMMENT_COUNT"
|
||||
|
||||
}
|
||||
154
app/src/main/java/com/gh/common/syncpage/SyncPageRepository.kt
Normal file
154
app/src/main/java/com/gh/common/syncpage/SyncPageRepository.kt
Normal file
@ -0,0 +1,154 @@
|
||||
package com.gh.common.syncpage
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.annotation.SyncIgnore
|
||||
import com.gh.common.annotation.SyncPage
|
||||
import com.gh.common.util.debugOnly
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import java.lang.reflect.Field
|
||||
|
||||
/**
|
||||
* 页面之间实现数据同步(主要是单个字段的同步)
|
||||
*
|
||||
* 实现思路:
|
||||
* 1.把需要同步的数据以一个特殊ID作为唯一标识,并存于一个全局的仓库
|
||||
* 2.利用LiveData进行页面回调,再通过[ISyncAdapterHandler.getSyncData]找到需要被同步的数据
|
||||
* 3.最后利用反射进行数据替换,具体请见[SyncPageRepository.replaceSyncData]
|
||||
*
|
||||
* 具体的接入方式(以列表为例):
|
||||
* 1.通过[SyncPageRepository.postSyncData]提交同步数据
|
||||
* 2.在Fragment重写[BaseFragment.addSyncPageObserver]开启同步事件监听
|
||||
* 3.在Fragment重写[BaseFragment.provideSyncAdapter]提供获取数据的来源
|
||||
* - [BaseFragment.provideSyncAdapter]提供的Adapter必须实现[ISyncAdapterHandler]接口
|
||||
*
|
||||
*/
|
||||
object SyncPageRepository {
|
||||
|
||||
// 只有在新增操作时,才需要进行页面刷新
|
||||
val syncPageLiveData = MutableLiveData<List<SyncDataEntity>>()
|
||||
|
||||
val syncDataList = ArrayList<SyncDataEntity>()
|
||||
|
||||
// size: 防止删除刚刚添加的数据
|
||||
@JvmStatic
|
||||
fun clearSyncData() {
|
||||
tryCatchInRelease {
|
||||
synchronized(syncDataList) {
|
||||
if (syncDataList.size > 0) {
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository clearSyncData 存在" + syncDataList.size + "条数据尚未处理,即将删除")
|
||||
}
|
||||
syncDataList.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeSyncData(list: List<SyncDataEntity>) {
|
||||
tryCatchInRelease {
|
||||
synchronized(syncDataList) {
|
||||
for (syncDataEntity in list) {
|
||||
val remove = syncDataList.remove(syncDataEntity)
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository removeSyncData ->" + syncDataEntity.syncId +
|
||||
", fieldName->" + syncDataEntity.syncFieldName +
|
||||
", remove->" + remove)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository removeSyncData ->" + syncDataList.size)
|
||||
}
|
||||
}
|
||||
|
||||
// 提交同步数据
|
||||
fun postSyncData(entity: SyncDataEntity) {
|
||||
tryCatchInRelease {
|
||||
synchronized(syncDataList) {
|
||||
// 检查是否存在重复操作
|
||||
for (syncDataEntity in syncDataList) {
|
||||
if (syncDataEntity.syncId == entity.syncId && syncDataEntity.syncFieldName == entity.syncFieldName) {
|
||||
syncDataList.remove(syncDataEntity)
|
||||
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository postSyncData 存在重复操作->" + entity.toJson())
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
syncDataList.add(entity)
|
||||
syncPageLiveData.postValue(syncDataList)
|
||||
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository postSyncData->" + entity.toJson())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleSyncData(rawData: Any, syncData: SyncDataEntity): Boolean {
|
||||
val fields = if (syncData.checkInherited) {
|
||||
getAllFieldsList(rawData::class.java)
|
||||
} else rawData::class.java.declaredFields.toList()
|
||||
|
||||
var isNeedNotify = false
|
||||
for (field in fields) {
|
||||
isNeedNotify = replaceSyncData(field, rawData, syncData)
|
||||
if (isNeedNotify) break
|
||||
}
|
||||
|
||||
if (!isNeedNotify) {
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository sync failure-> " + syncData.syncFieldName)
|
||||
}
|
||||
}
|
||||
|
||||
return isNeedNotify
|
||||
}
|
||||
|
||||
private fun replaceSyncData(field: Field, extractObject: Any, syncData: SyncDataEntity): Boolean {
|
||||
field.getAnnotation(SyncPage::class.java)?.syncNames?.forEach { syncName ->
|
||||
if (syncName == syncData.syncFieldName && field.getAnnotation(SyncIgnore::class.java) == null) {
|
||||
field.isAccessible = true
|
||||
debugOnly {
|
||||
Utils.log("SyncPageRepository sync success-> " + syncData.syncFieldName + ", fieldName->" + field.name + ", fieldValue->" + field.get(extractObject))
|
||||
}
|
||||
field.set(extractObject, syncData.syncFieldValue)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if (syncData.checkFieldEntity) {
|
||||
// 递归查询
|
||||
val pkgName = field.type.getPackage()?.name ?: return false
|
||||
if (pkgName.contains(HaloApp.getInstance().application.packageName) && field.getAnnotation(SyncIgnore::class.java) == null) {
|
||||
field.isAccessible = true
|
||||
val extractEntityObject = field.get(extractObject) ?: return false
|
||||
field.type.declaredFields.forEach {
|
||||
if (replaceSyncData(it, extractEntityObject, syncData)) return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 包括父类 Field 对象
|
||||
private fun getAllFieldsList(cls: Class<*>?): List<Field> {
|
||||
if (cls == null) return arrayListOf()
|
||||
val allFields = arrayListOf<Field>()
|
||||
var currentClass = cls
|
||||
while (currentClass != null) {
|
||||
val declaredFields = currentClass.declaredFields
|
||||
allFields.addAll(declaredFields)
|
||||
currentClass = currentClass.superclass
|
||||
}
|
||||
return allFields
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
package com.gh.common.syncpage.example
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.baselist.ListAdapter
|
||||
import com.gh.gamecenter.databinding.CommunityAnswerItemBinding
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.answer.CommunityAnswerItemViewHolder
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.Questions
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
|
||||
class ExampleAdapter(context: Context) : ListAdapter<AnswerEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun areItemsTheSame(oldItem: AnswerEntity?, newItem: AnswerEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == itemCount - 1) return ItemViewType.ITEM_FOOTER
|
||||
return ItemViewType.ITEM_BODY
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val view: View
|
||||
return when (viewType) {
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
|
||||
FooterViewHolder(view)
|
||||
}
|
||||
else -> {
|
||||
view = mLayoutInflater.inflate(R.layout.community_answer_item, parent, false)
|
||||
CommunityAnswerItemViewHolder(CommunityAnswerItemBinding.bind(view))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList.isNotEmpty()) mEntityList.size + FOOTER_ITEM_COUNT else 0
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (getItemViewType(position)) {
|
||||
ItemViewType.ITEM_BODY -> {
|
||||
val answer = mEntityList[position]
|
||||
if ("community_article" == answer.type) {
|
||||
val questions = Questions()
|
||||
questions.title = answer.articleTitle
|
||||
answer.questions = questions
|
||||
}
|
||||
|
||||
val answerViewHolder = holder as CommunityAnswerItemViewHolder
|
||||
val binding = answerViewHolder.binding
|
||||
answerViewHolder.bindAnswerItem(answer, "", getPath())
|
||||
binding.title.setOnClickListener {
|
||||
if ("community_article" == answer.type) {
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, UserManager.getInstance().community, answer.id!!, "", getPath()))
|
||||
} else {
|
||||
val questions = answer.questions
|
||||
mContext.startActivity(QuestionsDetailActivity.getIntent(mContext, questions.id, "", getPath()))
|
||||
}
|
||||
}
|
||||
|
||||
answerViewHolder.itemView.setOnClickListener {
|
||||
if ("community_article" == answer.type) {
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, UserManager.getInstance().community, answer.id!!, "", getPath()))
|
||||
} else {
|
||||
mContext.startActivity(AnswerDetailActivity.getIntent(mContext, answer.id, "", getPath()))
|
||||
}
|
||||
}
|
||||
}
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
val footerViewHolder = holder as FooterViewHolder
|
||||
footerViewHolder.initItemPadding()
|
||||
footerViewHolder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver, R.string.ask_loadover_hint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, AnswerEntity>? {
|
||||
if (position >= mEntityList.size) return null
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
|
||||
fun getPath(): String {
|
||||
return "问答-推荐-按时间"
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.gh.common.syncpage.example
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.baselist.ListFragment
|
||||
import com.gh.gamecenter.baselist.NormalListViewModel
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.Observable
|
||||
|
||||
class ExampleFragment : ListFragment<AnswerEntity, NormalListViewModel<AnswerEntity>>() {
|
||||
|
||||
private var mAdapter: ExampleAdapter? = null
|
||||
|
||||
override fun provideListAdapter(): ExampleAdapter {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = ExampleAdapter(requireContext())
|
||||
}
|
||||
return mAdapter!!
|
||||
}
|
||||
|
||||
override fun getItemDecoration(): RecyclerView.ItemDecoration {
|
||||
return VerticalItemDecoration(context, 8F, false)
|
||||
}
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<AnswerEntity>> {
|
||||
return RetrofitManager.getInstance(context).api.getCommunitiesRecommendNewest(UserManager.getInstance().community.id, page)
|
||||
}
|
||||
|
||||
override fun provideListViewModel(): NormalListViewModel<AnswerEntity> {
|
||||
val factory = NormalListViewModel.Factory(HaloApp.getInstance().application, this)
|
||||
return ViewModelProviders.of(this, factory).get(NormalListViewModel::class.java) as NormalListViewModel<AnswerEntity>
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// SyncPageRepository.syncPageLiveData.observe(this, Observer {
|
||||
// it ?: return@Observer
|
||||
// val adapter = mListRv.adapter
|
||||
// if (adapter !is ISyncAdapterHandler) return@Observer
|
||||
// for(position in 0 until adapter.itemCount) {
|
||||
// val syncKey = adapter.getSyncData(position)
|
||||
// for (syncDataEntity in it) {
|
||||
// if (syncDataEntity.syncId == syncKey?.first) {
|
||||
// val isSuccess = SyncPageRepository.handleSyncData(syncKey.second, syncDataEntity)
|
||||
// if (isSuccess) adapter.notifyItemChanged(position)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mListRv.adapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -1237,6 +1237,7 @@ public class DialogUtils {
|
||||
return context;
|
||||
}
|
||||
|
||||
// currentActivity 是否存在 isDestroyed 的情况?
|
||||
return AppManager.getInstance().currentActivity();
|
||||
}
|
||||
|
||||
|
||||
@ -528,7 +528,7 @@ object DirectUtils {
|
||||
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "") {
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "", type: String = "", act: String = "") {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
@ -539,12 +539,19 @@ object DirectUtils {
|
||||
bundle.putString(KEY_LOCATION, fromLocation)
|
||||
bundle.putBoolean(KEY_SHOW_COMMENT, showComment)
|
||||
bundle.putString(KEY_REFERER, referer)
|
||||
bundle.putString(KEY_TYPE, type)
|
||||
bundle.putString(KEY_ACTIVITY_NAME, act)
|
||||
jumpActivity(context, bundle)
|
||||
} else {
|
||||
DialogUtils.showLowSystemVersionDialog(context)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "") {
|
||||
directToVideoDetail(context, videoId, fromLocation, showComment, gameId, entrance, path, referer, "", "")
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转至安利墙
|
||||
* @param fixedTopAmwayCommentId 需要置顶的安利Id
|
||||
|
||||
@ -32,7 +32,7 @@ import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONObject
|
||||
import java.util.HashMap
|
||||
import java.util.*
|
||||
|
||||
object DownloadObserver {
|
||||
|
||||
@ -85,7 +85,10 @@ object DownloadObserver {
|
||||
if (DownloadStatus.done == downloadEntity.status) {
|
||||
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
|
||||
MtaHelper.onEvent("软件更新", "下载完成")
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path, true))
|
||||
tryWithDefaultCatch {
|
||||
// 会有 ActivityNotFoundException 异常,catch 掉不管了
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path, true))
|
||||
}
|
||||
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
|
||||
} else {
|
||||
statDoneEvent(downloadEntity)
|
||||
@ -111,7 +114,9 @@ object DownloadObserver {
|
||||
} else {
|
||||
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)) {
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path))
|
||||
tryWithDefaultCatch {
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path))
|
||||
}
|
||||
} else {
|
||||
// 弹出卸载提示框
|
||||
EventBus.getDefault().post(EBShowDialog(BaseActivity.PLUGGABLE, downloadEntity.path))
|
||||
@ -174,7 +179,7 @@ object DownloadObserver {
|
||||
val kv2 = HashMap<String, Any>()
|
||||
kv2["版本"] = downloadEntity.platform
|
||||
kv2["状态"] = "下载完成"
|
||||
kv2["位置"] = downloadEntity.entrance
|
||||
kv2["位置"] = downloadEntity.entrance ?: "null"
|
||||
kv2["游戏分平台"] = downloadEntity.name + "-" + platform
|
||||
kv2["光环助手版本"] = BuildConfig.VERSION_NAME
|
||||
DataUtils.onEvent(mApplication, "游戏下载位置", downloadEntity.name, kv2)
|
||||
@ -183,7 +188,7 @@ object DownloadObserver {
|
||||
val kv3 = HashMap<String, Any>()
|
||||
kv3["下载"] = "下载完成"
|
||||
kv3["版本"] = downloadEntity.platform
|
||||
kv3["位置"] = downloadEntity.entrance
|
||||
kv3["位置"] = downloadEntity.entrance ?: "null"
|
||||
type = ExposureUtils.DownloadType.PLUGIN_DOWNLOAD
|
||||
DataUtils.onEvent(mApplication, "插件化", downloadEntity.name, kv3)
|
||||
|
||||
|
||||
@ -147,8 +147,11 @@ public class EntranceUtils {
|
||||
public static final String KEY_IS_HOME_VIDEO = "isHomeVideo";
|
||||
public static final String KEY_IS_HOME = "isHome";
|
||||
public static final String KEY_WEB_SHARE = "webShare";
|
||||
public static final String KEY_ACTIVITY_NAME = "activityName";//活动名称
|
||||
public static final String KEY_REQUIRE_REDIRECT = "require_redirect"; // 标记需要再跳转
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
//TODO 把其他类似的跳转启动逻辑也处理掉
|
||||
if (RunningUtils.isRunning(context)
|
||||
@ -173,6 +176,7 @@ public class EntranceUtils {
|
||||
|
||||
|
||||
public static void jumpActivity(Context context, Bundle nextToBundle, Bundle bundle, Callback callback) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
//TODO 把其他类似的跳转启动逻辑也处理掉
|
||||
if (RunningUtils.isRunning(context)
|
||||
|
||||
@ -8,6 +8,7 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.SigningInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@ -170,6 +171,9 @@ public class PackageUtils {
|
||||
public static boolean compareSignatureBetweenInstalledAppWithApk(Context context, String packageName, String apkFilePath) {
|
||||
try {
|
||||
Signature sig = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures[0];
|
||||
|
||||
// Fuck HUAWEI, 华为系统调用 getPackageArchiveInfo 获取魔羯 apk 的签名时会耗时超过5秒造成 ANR,没有找到解决方法
|
||||
// 如果可以的话尽量避免调用 getPackageArchiveInfo 方法
|
||||
Signature releaseSig = context.getPackageManager().getPackageArchiveInfo(apkFilePath, PackageManager.GET_SIGNATURES).signatures[0];
|
||||
return sig.hashCode() == releaseSig.hashCode();
|
||||
} catch (Exception e) {
|
||||
@ -217,8 +221,9 @@ public class PackageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据apk路径,获取apk包名、签名 根据包名 判断 是否已安装游戏 根据签名 判断 是否一致
|
||||
/**
|
||||
* 根据 path 获取 apk 信息确定处理方式
|
||||
* @return true 为直接唤起系统 PackageInstaller, false 为需要插件化
|
||||
*/
|
||||
public static boolean isCanLaunchSetup(Context context, String path) {
|
||||
String packageName = getPackageNameByPath(context, path);
|
||||
@ -236,13 +241,13 @@ public class PackageUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 由于新增了非插件的也能更新的功能,倘若两个签名一样的话就不走下面的光环签名判断了
|
||||
if (compareSignatureBetweenInstalledAppWithApk(context, packageName, path)) {
|
||||
// 判断当前已安装应用是否为光环签名
|
||||
if (publicKey.equals(getApkSignatureByPackageName(context, packageName))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String signature = getApkSignatureByPackageName(context, packageName);
|
||||
return publicKey.equals(signature);
|
||||
// 若已安装的应用的签名与即将要安装的签名一致也返回 true
|
||||
return compareSignatureBetweenInstalledAppWithApk(context, packageName, path);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -18,7 +18,6 @@ import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.PopupWindow;
|
||||
@ -32,6 +31,7 @@ import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WeiBoShareActivity;
|
||||
import com.gh.gamecenter.eventbus.EBShare;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.sina.weibo.sdk.WbSdk;
|
||||
import com.sina.weibo.sdk.auth.AuthInfo;
|
||||
@ -46,6 +46,8 @@ import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
@ -53,7 +55,6 @@ import java.util.List;
|
||||
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
|
||||
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
|
||||
|
||||
@ -99,6 +100,7 @@ public class ShareUtils {
|
||||
private PopupWindow popupWindow;
|
||||
|
||||
private ShareType mShareType;
|
||||
public static ShareType shareType;//全局保存shareType,分享成功后判断分享的类型
|
||||
|
||||
private WeakReference<Activity> mActivity;
|
||||
|
||||
@ -108,6 +110,7 @@ public class ShareUtils {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
Utils.toast(mContext, R.string.share_success_hint);
|
||||
EventBus.getDefault().post(new EBShare(ShareUtils.shareType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -150,7 +153,7 @@ public class ShareUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void showShareWindowsCancelCallback(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType, Function0 function) {
|
||||
public void showShareWindowsCallback(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType, ShareCallBack callBack) {
|
||||
if (activity.isFinishing()) return;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.shareIcon = icon;
|
||||
@ -158,6 +161,7 @@ public class ShareUtils {
|
||||
this.mSummary = shareSummary;
|
||||
this.mTitle = shareTitle;
|
||||
this.mShareType = shareType;
|
||||
ShareUtils.shareType = mShareType;
|
||||
|
||||
View contentView = View.inflate(activity, R.layout.share_popup_layout, null);
|
||||
contentView.setFocusable(true);
|
||||
@ -178,8 +182,12 @@ public class ShareUtils {
|
||||
ShareRecyclerViewAdapter shareRecyclerViewAdapter = new ShareRecyclerViewAdapter();
|
||||
shareRecyclerView.setAdapter(shareRecyclerViewAdapter);
|
||||
shareRecyclerViewAdapter.setOnItemClickListener(position -> {
|
||||
if ("取消".equals(arrLabel[position])) {
|
||||
function.invoke();
|
||||
if (callBack != null) {
|
||||
if (position == arrLabel.length - 1) {
|
||||
callBack.onCancel();
|
||||
} else {
|
||||
callBack.onSuccess(arrLabel[position]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -221,7 +229,9 @@ public class ShareUtils {
|
||||
&& event.getRepeatCount() == 0
|
||||
&& popupWindow != null
|
||||
&& popupWindow.isShowing()) {
|
||||
function.invoke();
|
||||
if (callBack != null) {
|
||||
callBack.onCancel();
|
||||
}
|
||||
popupWindow.dismiss();
|
||||
}
|
||||
return false;
|
||||
@ -230,74 +240,7 @@ public class ShareUtils {
|
||||
|
||||
|
||||
public void showShareWindows(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType) {
|
||||
if (activity.isFinishing()) return;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.shareIcon = icon;
|
||||
this.shareUrl = url;
|
||||
this.mSummary = shareSummary;
|
||||
this.mTitle = shareTitle;
|
||||
this.mShareType = shareType;
|
||||
|
||||
View contentView = View.inflate(activity, R.layout.share_popup_layout, null);
|
||||
contentView.setFocusable(true);
|
||||
contentView.setFocusableInTouchMode(true);
|
||||
RecyclerView shareRecyclerView = contentView.findViewById(R.id.share_rv);
|
||||
|
||||
shareRecyclerView.setPadding(DisplayUtils.dip2px(mContext, 20), DisplayUtils.dip2px(mContext, 10), DisplayUtils.dip2px(mContext, 20), 0);
|
||||
|
||||
//RecyclerView禁止滑动
|
||||
GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 4) {
|
||||
@Override
|
||||
public boolean canScrollVertically() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
shareRecyclerView.setLayoutManager(gridLayoutManager);
|
||||
shareRecyclerView.setAdapter(new ShareRecyclerViewAdapter());
|
||||
|
||||
if (mShareType == ShareType.shareGh) {
|
||||
RelativeLayout layout = (RelativeLayout) view;
|
||||
layout.addView(contentView);
|
||||
arrLabel[6] = "邮件";
|
||||
arrLogo[6] = R.drawable.share_email_logo;
|
||||
arrLabel[7] = "复制链接";
|
||||
arrLogo[7] = R.drawable.share_copyfont_logo;
|
||||
return;
|
||||
} else {
|
||||
arrLabel[6] = "复制链接";
|
||||
arrLogo[6] = R.drawable.share_copyfont_logo;
|
||||
arrLabel[7] = "取消";
|
||||
arrLogo[7] = R.drawable.share_cancel_logo;
|
||||
}
|
||||
|
||||
popupWindow = new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
, LinearLayout.LayoutParams.MATCH_PARENT, true);
|
||||
popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style);
|
||||
//解决PopupWindow无法覆盖状态栏
|
||||
popupWindow.setClippingEnabled(false);
|
||||
int bottomLocation = -DisplayUtils.retrieveNavigationHeight(activity);
|
||||
if (!DisplayUtils.isNavigationBarShow(activity)) {
|
||||
bottomLocation = 0;
|
||||
}
|
||||
try {
|
||||
// popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);
|
||||
popupWindow.showAtLocation(view, Gravity.NO_GRAVITY, 0, bottomLocation);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
contentView.setOnClickListener(v -> popupWindow.dismiss());
|
||||
|
||||
contentView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK
|
||||
&& event.getRepeatCount() == 0
|
||||
&& popupWindow != null
|
||||
&& popupWindow.isShowing()) {
|
||||
popupWindow.dismiss();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
showShareWindowsCallback(activity, view, url, icon, shareTitle, shareSummary, shareType, null);
|
||||
}
|
||||
|
||||
//QQ分享
|
||||
@ -707,4 +650,10 @@ public class ShareUtils {
|
||||
void onItemClick(int position);
|
||||
}
|
||||
|
||||
public interface ShareCallBack {
|
||||
void onSuccess(String label);
|
||||
|
||||
void onCancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
216
app/src/main/java/com/gh/common/view/AdBannerView.kt
Normal file
216
app/src/main/java/com/gh/common/view/AdBannerView.kt
Normal file
@ -0,0 +1,216 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.*
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.rxTimer
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.SettingsEntity
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
/**
|
||||
* 视频流广告轮播控件
|
||||
*/
|
||||
class AdBannerView : LinearLayout {
|
||||
|
||||
private lateinit var mViewPager2: ViewPager2
|
||||
private var mDatas = ArrayList<SettingsEntity.Advertisement>()
|
||||
var isAutoPlay = true
|
||||
private var currentPage = 0
|
||||
private var autoDurationTime = 6000L
|
||||
private var mRxTimer: Disposable? = null
|
||||
private var lastX: Float = 0F
|
||||
private var lastY: Float = 0F
|
||||
private var startX: Float = 0F
|
||||
private var startY: Float = 0F
|
||||
private val mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
|
||||
private val bannerWidth = DisplayUtils.dip2px(52f)
|
||||
var onItemClick: ((position: Int) -> Unit)? = null
|
||||
private lateinit var mIndicatorLayout: LinearLayout
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||
|
||||
init {
|
||||
initViews()
|
||||
}
|
||||
|
||||
private fun initViews() {
|
||||
orientation = VERTICAL
|
||||
mViewPager2 = ViewPager2(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(bannerWidth, bannerWidth)
|
||||
orientation = ViewPager2.ORIENTATION_HORIZONTAL
|
||||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
currentPage = position
|
||||
slideIndicator(currentPage % mDatas.size)
|
||||
}
|
||||
})
|
||||
}
|
||||
val recyclerView = mViewPager2.getChildAt(0) as RecyclerView
|
||||
recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
|
||||
addView(mViewPager2)
|
||||
mIndicatorLayout = LinearLayout(context).apply {
|
||||
orientation = HORIZONTAL
|
||||
gravity = Gravity.CENTER
|
||||
val params = LayoutParams(LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(5F))
|
||||
params.topMargin = DisplayUtils.dip2px(8f)
|
||||
layoutParams = params
|
||||
visibility = View.GONE
|
||||
}
|
||||
addView(mIndicatorLayout)
|
||||
}
|
||||
|
||||
|
||||
fun start(datas: ArrayList<SettingsEntity.Advertisement>) {
|
||||
if (datas.isNullOrEmpty()) throw IllegalArgumentException("广告列表不能为空")
|
||||
val adapter = mViewPager2.adapter
|
||||
mDatas = datas
|
||||
if (adapter == null) {
|
||||
val bannerAdapter = AdBannerAdapter()
|
||||
mViewPager2.adapter = bannerAdapter
|
||||
} else {
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
currentPage = (mViewPager2.adapter as AdBannerAdapter).getActualFirstPositionInCenter()
|
||||
mViewPager2.setCurrentItem(currentPage, false)
|
||||
if (mDatas.size > 1) {
|
||||
addIndicator()
|
||||
slideIndicator(currentPage % mDatas.size)
|
||||
autoPlay()
|
||||
}
|
||||
}
|
||||
|
||||
private fun autoPlay() {
|
||||
if (isAutoPlay && mDatas.size > 1) {
|
||||
if (mRxTimer != null && !mRxTimer!!.isDisposed) {
|
||||
mRxTimer?.dispose()
|
||||
mRxTimer = null
|
||||
}
|
||||
mRxTimer = rxTimer(autoDurationTime) {
|
||||
slidePage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun slidePage() {
|
||||
currentPage++
|
||||
mViewPager2.setCurrentItem(currentPage, true)
|
||||
}
|
||||
|
||||
fun resumePage() {
|
||||
autoPlay()
|
||||
}
|
||||
|
||||
fun pausePage() {
|
||||
if (mRxTimer != null && !mRxTimer!!.isDisposed) {
|
||||
mRxTimer?.dispose()
|
||||
mRxTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun addIndicator() {
|
||||
mIndicatorLayout.removeAllViews()
|
||||
mDatas.forEach { _ ->
|
||||
val view = View(context).apply {
|
||||
background = ContextCompat.getDrawable(context, R.drawable.selector_video_detail_ad_indicator)
|
||||
val params = LayoutParams(DisplayUtils.dip2px(4F), DisplayUtils.dip2px(4F))
|
||||
params.leftMargin = DisplayUtils.dip2px(2F)
|
||||
params.rightMargin = DisplayUtils.dip2px(2F)
|
||||
layoutParams = params
|
||||
}
|
||||
mIndicatorLayout.addView(view)
|
||||
}
|
||||
}
|
||||
|
||||
private fun slideIndicator(position: Int) {
|
||||
for (i in 0 until mIndicatorLayout.childCount) {
|
||||
val childAt = mIndicatorLayout.getChildAt(i)
|
||||
childAt.isSelected = i == position
|
||||
}
|
||||
}
|
||||
|
||||
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
||||
val action = ev.action
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
lastX = ev.rawX
|
||||
startX = lastX
|
||||
lastY = ev.rawY
|
||||
startY = lastY
|
||||
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||
lastX = ev.rawX
|
||||
lastY = ev.rawY
|
||||
val distanceX = abs(lastX - startX)
|
||||
val distanceY = abs(lastY - startY)
|
||||
val disallowIntercept: Boolean
|
||||
disallowIntercept = if (mViewPager2.orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
|
||||
distanceX > mTouchSlop && distanceX > distanceY
|
||||
} else {
|
||||
distanceY > mTouchSlop && distanceY > distanceX
|
||||
}
|
||||
parent.requestDisallowInterceptTouchEvent(disallowIntercept)
|
||||
} else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
|
||||
return abs(lastX - startX) > mTouchSlop || abs(lastY - startY) > mTouchSlop
|
||||
}
|
||||
return super.onInterceptTouchEvent(ev)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
if (mRxTimer != null && !mRxTimer!!.isDisposed) {
|
||||
mRxTimer?.dispose()
|
||||
mRxTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
fun getAdDatas(): ArrayList<SettingsEntity.Advertisement> {
|
||||
return mDatas
|
||||
}
|
||||
|
||||
|
||||
private inner class AdBannerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return object : RecyclerView.ViewHolder(LayoutInflater.from(context).inflate(R.layout.item_ad_banner, parent, false)) {}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = if (mDatas.size == 1) mDatas.size else Int.MAX_VALUE
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val ad = mDatas[position % mDatas.size]
|
||||
val view = holder.itemView as SimpleDraweeView
|
||||
ImageUtils.addLimitWidthAndLoad(view, ad.image, bannerWidth, object : ImageUtils.OnImageloadListener {
|
||||
override fun onLoadFinal(imageInfo: ImageInfo?) {
|
||||
if (mIndicatorLayout.visibility == View.GONE) {
|
||||
mIndicatorLayout.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
})
|
||||
holder.itemView.setOnClickListener {
|
||||
onItemClick?.invoke(position % mDatas.size)
|
||||
}
|
||||
}
|
||||
|
||||
fun getActualFirstPositionInCenter(): Int {
|
||||
if (mDatas.size == 1) return 0
|
||||
var index = itemCount / 2
|
||||
if (index % mDatas.size != 0) {
|
||||
index -= (index % mDatas.size)
|
||||
}
|
||||
return index - 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,17 +14,24 @@ import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import com.gh.common.DefaultJsApi;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.util.DeviceUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.HtmlUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.RichEditorUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.MtaEvent;
|
||||
import com.gh.gamecenter.entity.MyVideoEntity;
|
||||
import com.gh.gamecenter.qa.entity.EditorInsertEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -509,6 +516,10 @@ public class RichEditor extends WebView {
|
||||
return HtmlUtils.stripHtml(mContents);
|
||||
}
|
||||
|
||||
// 在web页面播放视频
|
||||
// public void initArticleVideo() {
|
||||
// exec("javascript:RE.initArticleVideo();");
|
||||
// }
|
||||
|
||||
private String convertHexColorString(int color) {
|
||||
return String.format("#%06X", (0xFFFFFF & color));
|
||||
@ -615,5 +626,98 @@ public class RichEditor extends WebView {
|
||||
public boolean isInputEnabled() {
|
||||
return mInputEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取网络状态
|
||||
*
|
||||
* @return "WIFI", "2G", "3G", "4G","无网络","未知"
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public String getNetworkStatus() {
|
||||
return DeviceUtils.getNetwork(HaloApp.getInstance().getApplication());
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示toast
|
||||
*
|
||||
* @param text toast 内容
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public void toast(String text) {
|
||||
Utils.toast(HaloApp.getInstance().getApplication(), text);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示Dialog弹窗
|
||||
*
|
||||
* @param title 标题
|
||||
* @param message 内容
|
||||
* @param positive 确认按钮文本
|
||||
* @param negative 取消按钮文本
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public void showDialog(String title, String message, String positive, String negative, String jsCallbackCode) {
|
||||
DialogUtils.showAlertDialog(getContext(), title, message, positive, negative,
|
||||
() -> post(() -> loadUrl("javascript:" + jsCallbackCode + "(" + true + ")")),
|
||||
() -> post(() -> loadUrl("javascript:" + jsCallbackCode + "(" + false + ")")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript向App存储数据
|
||||
*
|
||||
* @param isPermanent true:永久存储 false:临时存储于内存中(注意:数据是不互通的)
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public void setDataToNative(String key, String value, boolean isPermanent) {
|
||||
key += "-RichEditor";
|
||||
if (!TextUtils.isEmpty(key)) {
|
||||
if (isPermanent) {
|
||||
if (value == null) {
|
||||
SPUtils.remove(key);
|
||||
} else {
|
||||
SPUtils.setString(key, value);
|
||||
}
|
||||
} else {
|
||||
if (value == null) {
|
||||
HaloApp.remove(key);
|
||||
} else {
|
||||
HaloApp.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript向App获取数据
|
||||
*
|
||||
* @param isPermanent 获取永久数据还是临时数据(注意:数据是不互通的)
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public String getDataFromNative(String key, boolean isPermanent) {
|
||||
key += "-RichEditor";
|
||||
if (!TextUtils.isEmpty(key)) {
|
||||
if (isPermanent) {
|
||||
return SPUtils.getString(key);
|
||||
} else {
|
||||
Object object = HaloApp.get(key, false);
|
||||
if (object != null) return object.toString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void logMtaEvent(String event) {
|
||||
try {
|
||||
MtaEvent mtaEvent = GsonUtils.fromJson(event, MtaEvent.class);
|
||||
MtaHelper.onEvent(mtaEvent.getName(), mtaEvent.getKey(), mtaEvent.getValue());
|
||||
} catch (Exception e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw e;
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.gh.common.view.vertical_recycler
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
/**
|
||||
* 列表在滑动过程中拦截事件
|
||||
*/
|
||||
class CustomRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :RecyclerView(context, attrs) {
|
||||
|
||||
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
|
||||
if(isScrolling()){
|
||||
return true
|
||||
}
|
||||
return super.onInterceptTouchEvent(e)
|
||||
}
|
||||
|
||||
private fun isScrolling():Boolean{
|
||||
return scrollState != SCROLL_STATE_IDLE
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +179,10 @@ public class PagerLayoutManager extends LinearLayoutManager {
|
||||
return super.scrollHorizontallyBy(dx, recycler, state);
|
||||
}
|
||||
|
||||
public boolean isSlideDown() {
|
||||
return mDrift >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置监听
|
||||
*
|
||||
|
||||
@ -648,9 +648,10 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
private void startDownloadService() {
|
||||
Intent serviceIntent = new Intent(mContext, DownloadService.class);
|
||||
// 当满足系统版本大于 8.0 、应用在后台运行时以前台服务开启
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
&& !HaloApp.getInstance().isRunningForeground) {
|
||||
// 当满足系统版本大于 8.0 就以前台服务开启 DownloadService
|
||||
// (因为即便在 SplashActivity 里初始化,也有可能报 not allowed to start service, app is in background 的错误)
|
||||
// DownloadService 会调用 stopForeground 方法,理论上会去掉 `光环助手正在运行中` 的通知
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
|
||||
mContext.startForegroundService(serviceIntent);
|
||||
} else {
|
||||
|
||||
@ -8,8 +8,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@ -30,10 +28,8 @@ import com.gh.base.BaseActivity;
|
||||
import com.gh.base.fragment.BaseFragment_ViewPager;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.avoidcallback.AvoidOnResultManager;
|
||||
import com.gh.common.avoidcallback.Callback;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.common.im.ImManager;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
@ -41,14 +37,12 @@ import com.gh.common.util.ActivationHelper;
|
||||
import com.gh.common.util.ClassUtils;
|
||||
import com.gh.common.util.ConcernUtils;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.DataLogUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DeviceTokenUtils;
|
||||
import com.gh.common.util.DeviceUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.DownloadNotificationHelper;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.LunchType;
|
||||
@ -59,23 +53,17 @@ import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.PushHelper;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.common.util.ThirdPartyPackageHelper;
|
||||
import com.gh.common.util.UrlFilterUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.download.DownloadFragment;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.GameDigestEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.InnerMetaInfoEntity;
|
||||
import com.gh.gamecenter.entity.NotificationHint;
|
||||
import com.gh.gamecenter.entity.NotificationUgc;
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBNetworkState;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.gh.gamecenter.eventbus.EBSkip;
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
import com.gh.gamecenter.manager.DataCollectionManager;
|
||||
@ -85,33 +73,26 @@ import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository;
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel;
|
||||
import com.gh.gamecenter.qa.CommunityFragment;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.EmptyResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gamecenter.suggest.SuggestSelectFragment;
|
||||
import com.gh.gamecenter.suggest.SuggestType;
|
||||
import com.google.android.exoplayer2.upstream.cache.Cache;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.halo.assistant.fragment.SettingsFragment;
|
||||
import com.lightgame.config.CommonDebug;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
import com.lightgame.download.FileUtils;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.shuyu.gsyvideoplayer.utils.StorageUtils;
|
||||
import com.tencent.bugly.beta.tinker.TinkerManager;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -129,19 +110,16 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import tv.danmaku.ijk.media.exo2.ExoSourceManager;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.ENTRANCE_BROWSER;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ;
|
||||
@ -173,9 +151,7 @@ public class MainActivity extends BaseActivity {
|
||||
// 黄壮华 按连续按返回键两次才退出应用
|
||||
private long[] mHits = new long[2];
|
||||
|
||||
private boolean isSkipped = false;
|
||||
public static boolean isNewFirstLaunch;
|
||||
public String uuid = UUID.randomUUID().toString();
|
||||
|
||||
private Handler handler = new Handler();
|
||||
|
||||
@ -186,10 +162,6 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
mSp = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
isSkipped = savedInstanceState.getBoolean(IS_SKIPPED);
|
||||
}
|
||||
|
||||
mMainWrapperFragment = new MainWrapperFragment();
|
||||
if (savedInstanceState != null) {
|
||||
mMainWrapperFragment.setArguments(savedInstanceState);
|
||||
@ -229,7 +201,6 @@ public class MainActivity extends BaseActivity {
|
||||
DialogUtils.showWarningDialog(this, "发生闪退", "光环助手刚刚发生了闪退,马上反馈以帮助我们更好地修复问题?(只需简单描述你刚才的操作)"
|
||||
, "暂不", "马上反馈",
|
||||
() -> {
|
||||
// SuggestionActivity.startSuggestionActivity(MainActivity.this, SuggestType.crash, "APP闪退:");
|
||||
startActivityForResult(SuggestionActivity.getIntent(MainActivity.this, SuggestType.crash, "APP闪退:"), 100);
|
||||
MtaHelper.onEventWithBasicDeviceInfo(
|
||||
"闪退弹窗",
|
||||
@ -262,7 +233,9 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
// 跳转至其它页面
|
||||
if (getIntent() != null && getIntent().getExtras() != null && !isSkipped) {
|
||||
if (getIntent() != null
|
||||
&& getIntent().getExtras() != null
|
||||
&& getIntent().getBooleanExtra(EntranceUtils.KEY_REQUIRE_REDIRECT, false)) {
|
||||
doSkip();
|
||||
}
|
||||
|
||||
@ -366,8 +339,10 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
private void doSkip() {
|
||||
if (getIntent() != null && getIntent().getExtras() != null) {
|
||||
getIntent().getExtras().putBoolean(EntranceUtils.KEY_REQUIRE_REDIRECT, false);
|
||||
}
|
||||
handler.postDelayed(() -> {
|
||||
isSkipped = true;
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
if (bundle != null) {
|
||||
String to = bundle.getString(KEY_TO);
|
||||
@ -505,7 +480,6 @@ public class MainActivity extends BaseActivity {
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(IS_SKIPPED, isSkipped);
|
||||
outState.putInt(CURRENT_PAGE, mMainWrapperFragment.getCurrentItem());
|
||||
if (mMainWrapperFragment != null) {
|
||||
outState.putInt(BaseFragment_ViewPager.ARGS_INDEX, mMainWrapperFragment.getCurrentItem());
|
||||
@ -521,6 +495,13 @@ public class MainActivity extends BaseActivity {
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
|
||||
// 跳转至其它页面
|
||||
if (getIntent() != null
|
||||
&& getIntent().getExtras() != null
|
||||
&& getIntent().getBooleanExtra(EntranceUtils.KEY_REQUIRE_REDIRECT, false)) {
|
||||
doSkip();
|
||||
}
|
||||
|
||||
// 跳转到问答社区并刷新
|
||||
if (getIntent().getBooleanExtra(SWITCH_TO_COMMUNITY, false)) {
|
||||
switchToCommunityTabAndRefresh();
|
||||
|
||||
@ -181,8 +181,10 @@ public class SkipActivity extends BaseActivity {
|
||||
false, "", ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer);
|
||||
break;
|
||||
case HOST_VIDEO_MORE:
|
||||
DirectUtils.directToVideoDetail(this, path, path,
|
||||
false, "", ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer);
|
||||
String act = uri.getQueryParameter("act");
|
||||
String loaction = TextUtils.isEmpty(act) ? path : VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.getValue();
|
||||
DirectUtils.directToVideoDetail(this, path, loaction,
|
||||
false, "", ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer, type, act);
|
||||
break;
|
||||
case HOST_VIDEO_STREAMING_HOME:
|
||||
// 把切换放到 MainActivity 处理
|
||||
|
||||
@ -182,6 +182,8 @@ public class SuggestionActivity extends ToolBarActivity implements OnRequestCall
|
||||
|
||||
private int mFunctionType = -1;
|
||||
|
||||
private String mCollectCancelPkgName = "";
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, SuggestType suggestType) {
|
||||
Intent intent = new Intent(context, SuggestionActivity.class);
|
||||
@ -714,6 +716,10 @@ public class SuggestionActivity extends ToolBarActivity implements OnRequestCall
|
||||
back.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("意见反馈", "意见反馈-游戏收录弹窗", "点击返回");
|
||||
dialog.dismiss();
|
||||
|
||||
if (mSelectGameEntity != null) {
|
||||
mCollectCancelPkgName = mSelectGameEntity.getPackageName();
|
||||
}
|
||||
});
|
||||
forcePost.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("意见反馈", "意见反馈-游戏收录弹窗", "点击不是我要的游戏,继续提交");
|
||||
@ -1023,6 +1029,10 @@ public class SuggestionActivity extends ToolBarActivity implements OnRequestCall
|
||||
|
||||
@Override
|
||||
protected boolean handleBackPressed() {
|
||||
if (mSelectGameEntity != null && mCollectCancelPkgName.equals(mSelectGameEntity.getPackageName())) {
|
||||
return super.handleBackPressed();
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(mSuggestContentEt.getText().toString()) ||
|
||||
!TextUtils.isEmpty(mSuggestGameName.getText().toString()) ||
|
||||
!TextUtils.isEmpty(mLinkEt.getText().toString()) ||
|
||||
|
||||
@ -13,6 +13,7 @@ import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
||||
import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.gamecenter.eventbus.EBShare;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.sina.weibo.sdk.api.ImageObject;
|
||||
import com.sina.weibo.sdk.api.TextObject;
|
||||
@ -24,6 +25,8 @@ import com.sina.weibo.sdk.utils.Utility;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/11/23.
|
||||
* <p>
|
||||
@ -149,6 +152,7 @@ public class WeiBoShareActivity extends Activity implements WbShareCallback {
|
||||
@Override
|
||||
public void onWbShareSuccess() {
|
||||
Utils.toast(this, R.string.share_success_hint);
|
||||
EventBus.getDefault().post(new EBShare(ShareUtils.shareType));
|
||||
finish();
|
||||
}
|
||||
|
||||
|
||||
@ -209,6 +209,7 @@ class AmwayAdapter(context: Context, private var mViewModel: AmwayViewModel, pri
|
||||
|
||||
if (amway.comment.me.isVoted) {
|
||||
binding.likeIv.setImageResource(R.drawable.ic_amway_liked)
|
||||
binding.likeCountTv.setTextColor(R.color.theme_font.toColor())
|
||||
binding.likeCountTv.setOnClickListener { binding.likeIv.performClick() }
|
||||
binding.likeIv.setOnClickListener {
|
||||
debounceActionWithInterval(binding.likeIv.id, 1000L) {
|
||||
@ -220,6 +221,7 @@ class AmwayAdapter(context: Context, private var mViewModel: AmwayViewModel, pri
|
||||
}
|
||||
} else {
|
||||
binding.likeIv.setImageResource(R.drawable.ic_amway_like)
|
||||
binding.likeCountTv.setTextColor(R.color.text_B3B3B3.toColor())
|
||||
binding.likeCountTv.setOnClickListener { binding.likeIv.performClick() }
|
||||
binding.likeIv.setOnClickListener {
|
||||
debounceActionWithInterval(binding.likeIv.id, 1000L) {
|
||||
|
||||
@ -3,12 +3,14 @@ package com.gh.gamecenter.collection;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import kotlin.Pair;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.common.constant.ItemViewType;
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler;
|
||||
import com.gh.common.util.CollectionUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -24,11 +26,13 @@ import com.gh.gamecenter.baselist.ListAdapter;
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Created by khy on 22/12/17.
|
||||
*/
|
||||
|
||||
public class AnswerAdapter extends ListAdapter<AnswerEntity> {
|
||||
public class AnswerAdapter extends ListAdapter<AnswerEntity> implements ISyncAdapterHandler {
|
||||
|
||||
private OnListClickListener mListClickListener;
|
||||
|
||||
@ -138,4 +142,12 @@ public class AnswerAdapter extends ListAdapter<AnswerEntity> {
|
||||
public int getItemCount() {
|
||||
return mEntityList == null || mEntityList.isEmpty() ? 0 : mEntityList.size() + FOOTER_ITEM_COUNT;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Pair<String, Object> getSyncData(int position) {
|
||||
if (position >= mEntityList.size()) return null;
|
||||
AnswerEntity entity = mEntityList.get(position);
|
||||
return new Pair(entity.getId(), entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,24 +2,20 @@ package com.gh.gamecenter.collection;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.common.history.HistoryDatabase;
|
||||
import com.gh.common.util.CollectionUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.baselist.ListAdapter;
|
||||
import com.gh.gamecenter.baselist.ListFragment;
|
||||
import com.gh.gamecenter.baselist.LoadType;
|
||||
import com.gh.gamecenter.eventbus.EBCollectionChanged;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import io.reactivex.Single;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Created by khy on 22/12/17.
|
||||
@ -41,18 +37,22 @@ public class AnswerFragment extends ListFragment<AnswerEntity, AnswerViewModel>
|
||||
return mAdapter == null ? mAdapter = new AnswerAdapter(getContext(), mListViewModel, mType, this, mEntrance) : mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
/*@Override
|
||||
public Single<List<AnswerEntity>> provideDataSingle(int page) {
|
||||
if (mType == Type.COLLECTION) {
|
||||
return Single.fromObservable(RetrofitManager.getInstance(getContext()).getApi().getCollectionAnswer(UserManager.getInstance().getUserId(), page));
|
||||
} else {
|
||||
return HistoryDatabase.Companion.getInstance().answerDao().getAnswersWithOffset(20, (page - 1) * 20);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@Override
|
||||
protected AnswerViewModel provideListViewModel() {
|
||||
AnswerViewModel viewModel = ViewModelProviders.of(this).get(AnswerViewModel.class);
|
||||
// TODO 因为 mType 是从外面传进来的,所以在应用回收重构时会为空,这里设置为 Type.Collection 只是为了不闪退,会影响逻辑(譬如当前类型为历史的时候)
|
||||
if (mType == null) {
|
||||
mType = Type.COLLECTION;
|
||||
}
|
||||
viewModel.setType(mType);
|
||||
return viewModel;
|
||||
}
|
||||
@ -81,4 +81,15 @@ public class AnswerFragment extends ListFragment<AnswerEntity, AnswerViewModel>
|
||||
|
||||
HISTORY
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean addSyncPageObserver() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected RecyclerView.Adapter provideSyncAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,12 @@ class AnswerViewModel(application: Application) : ListViewModel<AnswerEntity, An
|
||||
return if (type == AnswerFragment.Type.COLLECTION) {
|
||||
Single.fromObservable(mApi.getCollectionAnswer(UserManager.getInstance().userId, page))
|
||||
} else {
|
||||
HistoryDatabase.instance.answerDao().getAnswersWithOffset(20, (page - 1) * 20)
|
||||
if (page > 5) {
|
||||
Single.create { it.onSuccess(arrayListOf()) }
|
||||
} else {
|
||||
HistoryDatabase.instance.answerDao().getAnswersWithOffset(20, (page - 1) * 20)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package com.gh.gamecenter.collection;
|
||||
|
||||
import android.app.Application;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.common.history.HistoryDatabase;
|
||||
import com.gh.gamecenter.baselist.ListViewModel;
|
||||
@ -12,8 +10,11 @@ import com.gh.gamecenter.info.NewsViewsRepository;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
@ -74,6 +75,9 @@ public class ArticleViewModel extends ListViewModel<NewsEntity, NewsEntity> {
|
||||
if (type == ArticleFragment.Type.COLLECTION) {
|
||||
return Single.fromObservable(RetrofitManager.getInstance(getApplication()).getApi().getCollectionArticle(UserManager.getInstance().getUserId(), page));
|
||||
} else {
|
||||
if (page > 5) {
|
||||
return Single.create(emitter -> emitter.onSuccess(new ArrayList<>()));
|
||||
}
|
||||
return HistoryDatabase.Companion.getInstance().newsDao().getNewsWithOffset(20, (page - 1) * 20);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
@ -12,12 +13,13 @@ import com.gh.gamecenter.baselist.ListAdapter
|
||||
import com.gh.gamecenter.databinding.CommunityAnswerItemBinding
|
||||
import com.gh.gamecenter.qa.answer.CommunityAnswerItemViewHolder
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
|
||||
class CommunityArticleAdapter(context: Context,
|
||||
val mType: CommunityArticleFragment.Type,
|
||||
private val mViewModel: CommunityArticleViewModel,
|
||||
private val mEntrance: String) : ListAdapter<ArticleEntity>(context) {
|
||||
private val mEntrance: String) : ListAdapter<ArticleEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun areItemsTheSame(oldItem: ArticleEntity?, newItem: ArticleEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
@ -71,4 +73,10 @@ class CommunityArticleAdapter(context: Context,
|
||||
holder.initFooterViewHolder(mViewModel, mIsLoading, isNetworkError, mIsOver)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, ArticleEntity>? {
|
||||
if (position >= mEntityList.size) return null
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id, entity)
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.gamecenter.collection
|
||||
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.CollectionUtils
|
||||
import com.gh.gamecenter.baselist.ListFragment
|
||||
import com.gh.gamecenter.baselist.LoadType
|
||||
@ -16,7 +17,7 @@ class CommunityArticleFragment : ListFragment<ArticleEntity, CommunityArticleVie
|
||||
|
||||
override fun provideListAdapter(): CommunityArticleAdapter {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = CommunityArticleAdapter(context!!,mType, mListViewModel, mEntrance)
|
||||
mAdapter = CommunityArticleAdapter(requireContext(), mType, mListViewModel, mEntrance)
|
||||
}
|
||||
return mAdapter!!
|
||||
}
|
||||
@ -34,6 +35,14 @@ class CommunityArticleFragment : ListFragment<ArticleEntity, CommunityArticleVie
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(type: Type): CommunityArticleFragment {
|
||||
|
||||
@ -31,7 +31,11 @@ class CommunityArticleViewModel(application: Application) : ListViewModel<Articl
|
||||
return if (type == CommunityArticleFragment.Type.COLLECTION) {
|
||||
Single.fromObservable(RetrofitManager.getInstance(getApplication()).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page))
|
||||
} else {
|
||||
HistoryDatabase.instance.articleDao().getArticleWithOffset(20, (page - 1) * 20)
|
||||
if (page > 5) {
|
||||
Single.create { it.onSuccess(arrayListOf()) }
|
||||
} else {
|
||||
HistoryDatabase.instance.articleDao().getArticleWithOffset(20, (page - 1) * 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +73,7 @@ class CommunityArticleViewModel(application: Application) : ListViewModel<Articl
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun postCollectionArticleRead(communityId: String, articleId: String){
|
||||
fun postCollectionArticleRead(communityId: String, articleId: String) {
|
||||
RetrofitManager.getInstance(getApplication()).api
|
||||
.postCollectionArticleRead(UserManager.getInstance().userId, communityId, articleId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.gh.common.annotation.SyncPage
|
||||
import com.gh.common.syncpage.SyncFieldConstants
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@ -14,6 +16,7 @@ class MeEntity(@SerializedName("is_community_voted")
|
||||
@SerializedName("is_user_invite")
|
||||
var isUserInvite: Boolean = false,
|
||||
|
||||
@SyncPage(syncNames = [SyncFieldConstants.ANSWER_VOTE])
|
||||
@SerializedName("is_answer_voted")
|
||||
var isAnswerVoted: Boolean = false,
|
||||
|
||||
@ -50,10 +53,10 @@ class MeEntity(@SerializedName("is_community_voted")
|
||||
@SerializedName("is_toolkit_favorite")
|
||||
var isToolkitFavorite: Boolean = false,
|
||||
|
||||
@SerializedName("is_comment_own", alternate = ["is_answer_commented", "is_community_article_commented", "is_video_commented"])
|
||||
@SerializedName("is_comment_own", alternate = ["is_answer_commented", "is_community_article_commented", "is_video_commented"])
|
||||
var isCommentOwner: Boolean = false, // 是否是当前评论的拥有者
|
||||
|
||||
@SerializedName("is_comment_voted", alternate = ["is_answer_comment_voted","is_video_comment_voted", "is_community_article_comment_voted"])
|
||||
@SerializedName("is_comment_voted", alternate = ["is_answer_comment_voted", "is_video_comment_voted", "is_community_article_comment_voted"])
|
||||
var isCommentVoted: Boolean = false, // 是否已经点赞过当前评论
|
||||
|
||||
@SerializedName("is_version_requested")
|
||||
@ -65,6 +68,7 @@ class MeEntity(@SerializedName("is_community_voted")
|
||||
@SerializedName("is_favorite")
|
||||
var isCommunityArticleFavorite: Boolean = false,
|
||||
|
||||
@SyncPage(syncNames = [SyncFieldConstants.ARTICLE_VOTE])
|
||||
@SerializedName("is_vote")
|
||||
var isCommunityArticleVote: Boolean = false,
|
||||
|
||||
|
||||
3
app/src/main/java/com/gh/gamecenter/entity/MtaEvent.kt
Normal file
3
app/src/main/java/com/gh/gamecenter/entity/MtaEvent.kt
Normal file
@ -0,0 +1,3 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
data class MtaEvent(var name: String = "", var key: String = "", var value: String = "")
|
||||
@ -27,7 +27,7 @@ data class SettingsEntity(
|
||||
@SerializedName("article_entrance")
|
||||
private var articleEntrance: String = "",
|
||||
@SerializedName("video_advertisement")
|
||||
var videoAdvertisement: Advertisement? = null //新增字段video_advertisement,可能为空,代表广告关闭
|
||||
var videoAdvertisement: VideoAds? = null //新增字段video_advertisement,可能为空,代表广告关闭
|
||||
) {
|
||||
|
||||
fun setCommunityEntrance(communityEntrance: String) {
|
||||
@ -165,6 +165,12 @@ data class SettingsEntity(
|
||||
}
|
||||
}
|
||||
|
||||
data class VideoAds(
|
||||
var center: ArrayList<Advertisement>? = null,
|
||||
var left: ArrayList<Advertisement>? = null,
|
||||
var right: ArrayList<Advertisement>? = null
|
||||
)
|
||||
|
||||
data class Advertisement(
|
||||
var duration: Int = -1, //广告总显示秒数
|
||||
var frequency: Int = -1,//广告出现频率
|
||||
|
||||
@ -36,6 +36,8 @@ open class VideoEntity(
|
||||
@SerializedName("game_active")
|
||||
val gameActive: Boolean = false,//游戏是否被隐藏 false隐藏
|
||||
var game: GameEntity? = null,
|
||||
@SerializedName("share")
|
||||
var shareCount: Int = 0,//分享数量 v3.7.5新增
|
||||
|
||||
var videoIsMuted: Boolean = false//是否静音标记
|
||||
) : Parcelable {
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
data class WebShareEntity(var title: String = "",
|
||||
val description: String = "",
|
||||
val icon: String = "")
|
||||
19
app/src/main/java/com/gh/gamecenter/eventbus/EBShare.java
Normal file
19
app/src/main/java/com/gh/gamecenter/eventbus/EBShare.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.gh.gamecenter.eventbus;
|
||||
|
||||
import com.gh.common.util.ShareUtils;
|
||||
|
||||
public class EBShare {
|
||||
public ShareUtils.ShareType shareType;
|
||||
|
||||
public EBShare(ShareUtils.ShareType shareType) {
|
||||
this.shareType = shareType;
|
||||
}
|
||||
|
||||
public ShareUtils.ShareType getShareType() {
|
||||
return shareType;
|
||||
}
|
||||
|
||||
public void setShareType(ShareUtils.ShareType shareType) {
|
||||
this.shareType = shareType;
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,12 @@ import android.widget.CheckedTextView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
@ -26,6 +32,7 @@ import com.facebook.imagepipeline.image.ImageInfo;
|
||||
import com.gh.base.OnDoubleTapListener;
|
||||
import com.gh.base.fragment.BaseFragment_ViewPager_Checkable;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.syncpage.SyncPageRepository;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
@ -35,12 +42,8 @@ import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.view.ReserveDialog;
|
||||
import com.gh.common.view.WelcomeDialog;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.MainActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.db.GameTrendsDao;
|
||||
import com.gh.gamecenter.db.info.GameTrendsInfo;
|
||||
import com.gh.gamecenter.discover.DiscoverFragment;
|
||||
import com.gh.gamecenter.entity.ConcernEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
import com.gh.gamecenter.eventbus.EBConcernChanged;
|
||||
@ -49,13 +52,11 @@ import com.gh.gamecenter.eventbus.EBSkip;
|
||||
import com.gh.gamecenter.eventbus.EBUISwitch;
|
||||
import com.gh.gamecenter.game.GameFragment;
|
||||
import com.gh.gamecenter.home.HomeFragment;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.message.MessageUnreadRepository;
|
||||
import com.gh.gamecenter.message.MessageUnreadViewModel;
|
||||
import com.gh.gamecenter.personal.PersonalFragment;
|
||||
import com.gh.gamecenter.qa.CommunityFragment;
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerFragment;
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
|
||||
import com.gh.gamecenter.video.detail.HomeVideoFragment;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.listeners.OnBackPressedListener;
|
||||
import com.lightgame.view.CheckableImageView;
|
||||
@ -69,12 +70,6 @@ import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
import static com.gh.gamecenter.MainActivity.EB_SKIP_MAIN;
|
||||
@ -110,9 +105,6 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
@BindView(R.id.main_tab_game_name)
|
||||
TextView mTabGameName;
|
||||
|
||||
// @BindView(R.id.iv_discovery_hint_dot)
|
||||
// protected View mDiscoveryHintIv;
|
||||
|
||||
public static final int INDEX_HOME = 0;
|
||||
public static final int INDEX_GAME = 1;
|
||||
public static final int INDEX_VIDEO = 2;
|
||||
@ -127,7 +119,7 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
private MainWrapperViewModel mViewModel;
|
||||
private MessageUnreadViewModel mMessageUnreadViewModel;
|
||||
private GameTrendsDao mGameTrendsDao;
|
||||
private VideoDetailContainerFragment videoDetailContainerFragment;
|
||||
private HomeVideoFragment homeVideoFragment;
|
||||
private String[] resAssets = {"lottie/tab_home.json", "lottie/tab_game.json", "lottie/tab_video.json", "tab_community.gif", "tab_mine.gif"};
|
||||
|
||||
@Override
|
||||
@ -161,17 +153,15 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
mGameWrapperFragment.setArguments(homeArgs);
|
||||
fragments.add(mGameWrapperFragment);
|
||||
|
||||
videoDetailContainerFragment = new VideoDetailContainerFragment();
|
||||
|
||||
homeVideoFragment = new HomeVideoFragment();
|
||||
Bundle videoArgs = new Bundle();
|
||||
videoArgs.putString(EntranceUtils.KEY_LOCATION, VideoDetailContainerViewModel.Location.VIDEO_CHOICENESS.getValue());
|
||||
videoArgs.putString(EntranceUtils.KEY_PATH, "视频总入口");
|
||||
videoArgs.putString(EntranceUtils.KEY_UUID, ((MainActivity) requireContext()).uuid);
|
||||
//videoArgs.putString(EntranceUtils.KEY_PATH, "视频总入口");
|
||||
videoArgs.putBoolean(EntranceUtils.KEY_IS_HOME_VIDEO, true);
|
||||
videoDetailContainerFragment.setArguments(videoArgs);
|
||||
fragments.add(videoDetailContainerFragment);
|
||||
homeVideoFragment.setArguments(videoArgs);
|
||||
fragments.add(homeVideoFragment);
|
||||
|
||||
fragments.add(new CommunityFragment());
|
||||
//fragments.add(new DiscoverFragment());
|
||||
fragments.add(new PersonalFragment());
|
||||
}
|
||||
|
||||
@ -272,10 +262,9 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
//mViewModel.getDiscoveryData(false);
|
||||
MessageUnreadRepository.INSTANCE.loadMessageUnreadTotal();
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
SyncPageRepository.clearSyncData();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -582,8 +571,8 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
|
||||
|
||||
@Override
|
||||
public boolean onHandleBackPressed() {
|
||||
if (videoDetailContainerFragment != null) {
|
||||
return videoDetailContainerFragment.onHandleBackPressed();
|
||||
if (homeVideoFragment.getCurrentFragment() != null) {
|
||||
return homeVideoFragment.getCurrentFragment().onHandleBackPressed();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -31,7 +31,6 @@ import com.gh.gamecenter.normal.NormalFragment
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.CheckableImageView
|
||||
import kotterknife.bindView
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@ -96,9 +95,9 @@ class GameFragment : NormalFragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mBinding = FragmentGameBinding.bind(view)
|
||||
mBinding.gameRefresh.setColorSchemeColors(ContextCompat.getColor(context!!, R.color.theme))
|
||||
mBinding.gameRefresh.setColorSchemeColors(ContextCompat.getColor(requireContext(), R.color.theme))
|
||||
mLayoutManager = FixLinearLayoutManager(context)
|
||||
mListAdapter = GameFragmentAdapter(context!!, mViewModel, mLayoutManager)
|
||||
mListAdapter = GameFragmentAdapter(requireContext(), mViewModel, mLayoutManager)
|
||||
|
||||
mBinding.gameList.run {
|
||||
(itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
@ -133,6 +132,9 @@ class GameFragment : NormalFragment() {
|
||||
mReplaceDataButton.setOnClickListener {
|
||||
val firstVisiblePosition = mLayoutManager.findFirstVisibleItemPosition()
|
||||
val lastVisiblePosition = mLayoutManager.findLastVisibleItemPosition()
|
||||
if (firstVisiblePosition == RecyclerView.NO_POSITION
|
||||
|| lastVisiblePosition == RecyclerView.NO_POSITION) return@setOnClickListener
|
||||
|
||||
for (position in firstVisiblePosition..lastVisiblePosition) {
|
||||
val itemData = mListAdapter.getItemDataByPosition(position)
|
||||
if (itemData != null && mViewModel.replaceRefreshData(itemData)) mListAdapter.notifyItemChanged(position)
|
||||
@ -167,7 +169,7 @@ class GameFragment : NormalFragment() {
|
||||
//下载被删除事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus) {
|
||||
if ("delete" == status.status) {
|
||||
if (::mListAdapter.isInitialized && "delete" == status.status) {
|
||||
mListAdapter.notifyItemAndRemoveDownload(status)
|
||||
}
|
||||
}
|
||||
@ -175,23 +177,26 @@ class GameFragment : NormalFragment() {
|
||||
//安装、卸载事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
val data = mListAdapter.getGameEntityByPackage(busFour.packageName)
|
||||
for (gameAndPosition in data) {
|
||||
mListAdapter.notifyChildItem(gameAndPosition.position)
|
||||
if (::mListAdapter.isInitialized) {
|
||||
val data = mListAdapter.getGameEntityByPackage(busFour.packageName)
|
||||
for (gameAndPosition in data) {
|
||||
mListAdapter.notifyChildItem(gameAndPosition.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(reuse: EBReuse) {
|
||||
if ("Refresh" == reuse.type) {
|
||||
if (::mListAdapter.isInitialized && "Refresh" == reuse.type) {
|
||||
mListAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busNine: EBUISwitch) {
|
||||
if (MainWrapperFragment.EB_MAIN_SCROLL_TOP == busNine.from
|
||||
&& MainWrapperFragment.INDEX_GAME == busNine.position) {
|
||||
if (::mLayoutManager.isInitialized &&
|
||||
MainWrapperFragment.EB_MAIN_SCROLL_TOP == busNine.from &&
|
||||
MainWrapperFragment.INDEX_GAME == busNine.position) {
|
||||
mBinding.gameList.stopScroll()
|
||||
mLayoutManager.scrollToPosition(0)
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import androidx.lifecycle.*
|
||||
import com.gh.common.TimeElapsedHelper
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.baselist.LoadStatus
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.game.data.GameItemData
|
||||
@ -20,7 +19,7 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import retrofit2.HttpException
|
||||
import java.util.HashMap
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.set
|
||||
|
||||
@ -88,7 +87,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<List<LinkEntity>>() {
|
||||
override fun onResponse(response: List<LinkEntity>?) {
|
||||
if (response != null) mSlideList.addAll(response)
|
||||
if (response != null) mSlideList = response as ArrayList<LinkEntity>
|
||||
if (initData) getSubjectDigest(initData)
|
||||
}
|
||||
|
||||
@ -110,7 +109,7 @@ class GameViewModel(application: Application, var blockData: SubjectRecommendEnt
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<List<SubjectRecommendEntity>>() {
|
||||
override fun onResponse(response: List<SubjectRecommendEntity>?) {
|
||||
if (response != null) mSubjectDigestList.addAll(response)
|
||||
if (response != null) mSubjectDigestList = response as ArrayList<SubjectRecommendEntity>
|
||||
transformationItemData()
|
||||
if (initData) {
|
||||
getSubjectList(initData)
|
||||
|
||||
@ -197,7 +197,7 @@ class GameDetailFragment : NormalFragment() {
|
||||
checkReadPhoneStatePermissionBeforeAction {
|
||||
ifLogin("游戏详情-[关注]") {
|
||||
if (mGameDetailEntity != null && mGameDetailEntity!!.me.isGameConcerned) {
|
||||
DialogUtils.showCancelDialog(context!!, { mViewModel.concernCommand(false) }, null)
|
||||
DialogUtils.showCancelDialog(requireContext(), { mViewModel.concernCommand(false) }, null)
|
||||
} else {
|
||||
mViewModel.concernCommand(true)
|
||||
}
|
||||
@ -271,6 +271,9 @@ class GameDetailFragment : NormalFragment() {
|
||||
}
|
||||
|
||||
mAppBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
|
||||
// requireContext():not attached to context
|
||||
if (!isAdded) return@OnOffsetChangedListener
|
||||
|
||||
val absVerticalOffset = abs(verticalOffset)
|
||||
val total = appBarLayout.totalScrollRange
|
||||
|
||||
@ -368,7 +371,6 @@ class GameDetailFragment : NormalFragment() {
|
||||
GdtHelper.CONTENT_TYPE, "GAME",
|
||||
GdtHelper.CONTENT_ID, mGameEntity!!.id)
|
||||
|
||||
data.game.id = mGameEntity!!.id
|
||||
mGameDetailEntity = data.game
|
||||
downloadAddWord = data.game.getDownloadAddWord()
|
||||
downloadOffText = data.game.downloadOffText
|
||||
@ -376,7 +378,6 @@ class GameDetailFragment : NormalFragment() {
|
||||
showAlertDialogIfNeeded(data.game)
|
||||
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(UnifiedGameDetailEntity.TAG, data)
|
||||
bundle.putParcelable(GameEntity.TAG, mGameEntity)
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, mEntrance)
|
||||
bundle.putBoolean(EntranceUtils.KEY_SCROLL_TO_LIBAO, arguments?.getBoolean(EntranceUtils.KEY_SCROLL_TO_LIBAO) ?: false)
|
||||
|
||||
@ -84,6 +84,8 @@ class GameDetailViewModel(application: Application,
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<UnifiedGameDetailEntity>() {
|
||||
override fun onSuccess(data: UnifiedGameDetailEntity) {
|
||||
data.game.id = game?.id
|
||||
|
||||
// 过滤过期公告
|
||||
if (!data.game.notice.isNullOrEmpty()) {
|
||||
val l = System.currentTimeMillis()
|
||||
@ -197,6 +199,7 @@ class GameDetailViewModel(application: Application,
|
||||
for (originalAnswer in unifiedGameDetailEntity.communityColumnContents!!) {
|
||||
if (originalAnswer.id == answer.id) {
|
||||
originalAnswer.me = answer.me
|
||||
originalAnswer.vote = answer.vote
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,11 +14,11 @@ import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameDetailEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.UnifiedGameDetailEntity
|
||||
import com.gh.gamecenter.entity.RatingComment
|
||||
import com.gh.gamecenter.eventbus.EBReuse
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment.Companion.OPEN_APPBAR
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment.Companion.SKIP_DESC
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
import com.gh.gamecenter.video.detail.VideoDetailActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -66,20 +66,25 @@ class DescFragment : BaseFragment<Any>() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mGameEntity = arguments?.getParcelable(GameEntity.TAG)
|
||||
mDetailEntity = (arguments?.getParcelable(UnifiedGameDetailEntity.TAG) as UnifiedGameDetailEntity).game
|
||||
openVideoStreaming = arguments?.getBoolean(EntranceUtils.KEY_OPEN_VIDEO_STREAMING, false)
|
||||
?: false
|
||||
|
||||
val factory = DescViewModel.Factory(HaloApp.getInstance().application,
|
||||
mGameEntity,
|
||||
mDetailEntity)
|
||||
val gameDetailFactory = GameDetailViewModel.Factory(HaloApp.getInstance().application, mGameEntity?.id, mGameEntity)
|
||||
val gameDetailViewModel: GameDetailViewModel = viewModelProviderFromParent(gameDetailFactory)
|
||||
mDetailEntity = gameDetailViewModel.unifiedGameDetailLiveData.value?.data?.game
|
||||
|
||||
val factory = DescViewModel.Factory(HaloApp.getInstance().application, mGameEntity)
|
||||
mViewModel = viewModelProvider(factory)
|
||||
|
||||
gameDetailViewModel.unifiedGameDetailLiveData.observeNonNull(this) {
|
||||
mViewModel.constructList(it.data!!.game)
|
||||
}
|
||||
mViewModel.list.observe(this, Observer { descItemDataList ->
|
||||
descItemDataList?.let {
|
||||
mAdapter.updateDescItemList(it)
|
||||
}
|
||||
descItemDataList.forEach {
|
||||
if (openVideoStreaming && it.intro?.video != null&& !RunningUtils.isEqualsTop(context, VideoDetailActivity::class.java.name)) {
|
||||
if (openVideoStreaming && it.intro?.video != null && !RunningUtils.isEqualsTop(context, VideoDetailActivity::class.java.name)) {
|
||||
DirectUtils.directToVideoDetail(requireContext(), it.intro?.video?.videoId
|
||||
?: "", it.intro?.video?.videoId ?: "", path = "游戏详情-介绍视频")
|
||||
return@forEach
|
||||
|
||||
@ -22,18 +22,20 @@ import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
|
||||
class DescViewModel(application: Application,
|
||||
var game: GameEntity?,
|
||||
var gameDetail: GameDetailEntity?) : AndroidViewModel(application) {
|
||||
var game: GameEntity?) : AndroidViewModel(application) {
|
||||
|
||||
private var mDataList = arrayListOf<DescItemData>()
|
||||
private var mRelatedGameList = arrayListOf<GameEntity>()
|
||||
private var mGameDetail: GameDetailEntity? = null
|
||||
|
||||
var list = MutableLiveData<ArrayList<DescItemData>>()
|
||||
var gameId = game?.id
|
||||
|
||||
init {
|
||||
fun constructList(gameDetailEntity: GameDetailEntity) {
|
||||
|
||||
mGameDetail = gameDetailEntity
|
||||
// 构建列表
|
||||
gameDetail?.let {
|
||||
mGameDetail?.let {
|
||||
|
||||
// 这里的高、低优先级是指相对于游戏介绍区域的位置,高在上面低在下面
|
||||
val highPriorityCustomColumnList = arrayListOf<GameDetailEntity.CustomColumn>()
|
||||
@ -98,7 +100,7 @@ class DescViewModel(application: Application,
|
||||
|
||||
list.postValue(mDataList)
|
||||
|
||||
if (gameDetail?.showComment == true) {
|
||||
if (mGameDetail?.showComment == true) {
|
||||
retrieveComment()
|
||||
}
|
||||
}
|
||||
@ -109,14 +111,14 @@ class DescViewModel(application: Application,
|
||||
*/
|
||||
fun generateRecommendedGamesItem() {
|
||||
// 看游戏详情有没有相关游戏,没有就拿 3个 热门卡牌
|
||||
if (gameDetail == null
|
||||
|| gameDetail!!.relatedGames == null
|
||||
|| gameDetail!!.relatedGames!!.isEmpty()) {
|
||||
if (mGameDetail == null
|
||||
|| mGameDetail!!.relatedGames == null
|
||||
|| mGameDetail!!.relatedGames!!.isEmpty()) {
|
||||
assembleListWithRecommendedGames()
|
||||
return
|
||||
}
|
||||
|
||||
val relatedGames = gameDetail!!.relatedGames
|
||||
val relatedGames = mGameDetail!!.relatedGames
|
||||
val idList = ArrayList<String>()
|
||||
for (relatedGame in relatedGames!!) {
|
||||
val size = relatedGame.game!!.size
|
||||
@ -267,10 +269,9 @@ class DescViewModel(application: Application,
|
||||
}
|
||||
|
||||
class Factory(private val mApplication: Application,
|
||||
private val game: GameEntity?,
|
||||
private val gameDetail: GameDetailEntity?) : ViewModelProvider.NewInstanceFactory() {
|
||||
private val game: GameEntity?) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return DescViewModel(mApplication, game, gameDetail) as T
|
||||
return DescViewModel(mApplication, game) as T
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -46,6 +46,8 @@ class FuLiAdapter(context: Context,
|
||||
|
||||
private var mIsUpdateInfoFirstTimeLayout = true
|
||||
|
||||
var answerAdapter: GameDetailAnswerAdapter? = null
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (itemList == null || itemList!!.isEmpty()) {
|
||||
return NO_DATA
|
||||
@ -160,7 +162,8 @@ class FuLiAdapter(context: Context,
|
||||
}
|
||||
|
||||
answerItemList.layoutManager = LinearLayoutManager(mContext)
|
||||
answerItemList.adapter = GameDetailAnswerAdapter(mContext, mFuLiViewModel!!, itemList?.get(position)?.answer!!, mEntrance)
|
||||
answerAdapter = GameDetailAnswerAdapter(mContext, mFuLiViewModel!!, itemList?.get(position)?.answer!!, mEntrance)
|
||||
answerItemList.adapter = answerAdapter
|
||||
answerItemMore.setOnClickListener {
|
||||
answerItemHint.visibility = View.GONE
|
||||
mSharedPreferences.edit().putBoolean(mAnswerHintKey, false).apply()
|
||||
|
||||
@ -18,7 +18,6 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.LibaoEntity
|
||||
import com.gh.gamecenter.entity.ServerCalendarEntity
|
||||
import com.gh.gamecenter.entity.UnifiedGameDetailEntity
|
||||
import com.gh.gamecenter.eventbus.EBReuse
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.gamedetail.GameDetailViewModel
|
||||
@ -102,7 +101,6 @@ class FuLiFragment : BaseFragment<Any>() {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val gameEntity = arguments?.getParcelable(GameEntity.TAG) as GameEntity
|
||||
val unifiedGameDetailEntity = arguments?.getParcelable(UnifiedGameDetailEntity.TAG) as UnifiedGameDetailEntity
|
||||
val gameDetailFactory = GameDetailViewModel.Factory(HaloApp.getInstance().application, gameEntity.id, gameEntity)
|
||||
shouldScroolToLibao = arguments?.getBoolean(EntranceUtils.KEY_SCROLL_TO_LIBAO) ?: false
|
||||
|
||||
@ -110,7 +108,9 @@ class FuLiFragment : BaseFragment<Any>() {
|
||||
mGameDetailViewModel = viewModelProviderFromParent(gameDetailFactory)
|
||||
|
||||
mFuLiViewModel?.updateGameEntity(gameEntity)
|
||||
mFuLiViewModel?.updateUnifiedGameDetailEntity(unifiedGameDetailEntity)
|
||||
mGameDetailViewModel?.unifiedGameDetailLiveData?.value?.data?.let {
|
||||
mFuLiViewModel?.updateUnifiedGameDetailEntity(it)
|
||||
}
|
||||
|
||||
mFuLiViewModel?.fuFiDataLD?.observe(this, Observer {
|
||||
reuse_ll_loading.visibility = View.GONE
|
||||
@ -133,7 +133,7 @@ class FuLiFragment : BaseFragment<Any>() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mViewSkeletonScreen = Skeleton.bind(game_detail_skeleton).shimmer(false).load(R.layout.fragment_gamedongtai_skeleton).show()
|
||||
mAdapter = FuLiAdapter(context!!, this, mFuLiViewModel, mEntrance)
|
||||
mAdapter = FuLiAdapter(requireContext(), this, mFuLiViewModel, mEntrance)
|
||||
mRecyclerView.adapter = mAdapter
|
||||
layoutManager = object : androidx.recyclerview.widget.LinearLayoutManager(context) {
|
||||
override fun canScrollVertically(): Boolean {
|
||||
@ -223,4 +223,12 @@ class FuLiFragment : BaseFragment<Any>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mAdapter?.answerAdapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.gh.gamecenter.gamedetail.fuli.answer
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.StringUtils
|
||||
import com.gh.common.util.visibleIf
|
||||
@ -23,7 +24,7 @@ class GameDetailAnswerAdapter(context: Context,
|
||||
var mViewModel: FuLiViewModel,
|
||||
private val mAnswerList: List<AnswerEntity>,
|
||||
private val mEntrance: String)
|
||||
: BaseRecyclerAdapter<CommunityAnswerItemViewHolder>(context) {
|
||||
: BaseRecyclerAdapter<CommunityAnswerItemViewHolder>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommunityAnswerItemViewHolder {
|
||||
val view = mLayoutInflater.inflate(R.layout.community_answer_item, parent, false)
|
||||
@ -47,7 +48,7 @@ class GameDetailAnswerAdapter(context: Context,
|
||||
MtaHelper.onEvent("进入问答", "游戏详情", mViewModel.gameCommunity?.name + "+" + mViewModel.game?.name)
|
||||
if ("community_article" == entity.type) {
|
||||
MtaHelper.onEvent("游戏详情_新", "点击社区文章", mViewModel.game?.name + "->" + entity.questions.title)
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, CommunityEntity(entity.communityId!!, ""), entity.id!!, mEntrance, path))
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, CommunityEntity(entity.articleCommunityId, ""), entity.id!!, mEntrance, path))
|
||||
} else {
|
||||
MtaHelper.onEvent("游戏详情_新", "点击问题", mViewModel.game?.name + "->" + entity.questions.title)
|
||||
mContext.startActivity(QuestionsDetailActivity.getIntent(mContext, entity.questions.id, mEntrance, path))
|
||||
@ -59,7 +60,7 @@ class GameDetailAnswerAdapter(context: Context,
|
||||
MtaHelper.onEvent("进入问答", "游戏详情", mViewModel.gameCommunity?.name + "+" + mViewModel.game?.name)
|
||||
if ("community_article" == entity.type) {
|
||||
MtaHelper.onEvent("游戏详情_新", "点击社区文章", mViewModel.game?.name + "->" + entity.questions.title)
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, CommunityEntity(entity.communityId!!, ""), entity.id!!, mEntrance, path))
|
||||
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, CommunityEntity(entity.articleCommunityId, ""), entity.id!!, mEntrance, path))
|
||||
} else {
|
||||
MtaHelper.onEvent("游戏详情_新", "点击答案", mViewModel.game?.name + "->" + StringUtils.shrinkStringWithDot(entity.brief, 10))
|
||||
mContext.startActivity(AnswerDetailActivity.getIntent(mContext, entity.id, mEntrance, path))
|
||||
@ -67,4 +68,9 @@ class GameDetailAnswerAdapter(context: Context,
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, AnswerEntity>? {
|
||||
if (position >= mAnswerList.size) return null
|
||||
val entity = mAnswerList[position]
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ class HelpContentAdapter(context: Context,
|
||||
if (entity.content.startsWith("http")) {
|
||||
mContext.startActivity(WebActivity.getIntent(mContext, entity.content, false))
|
||||
} else {
|
||||
val content = "<html><head><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /><meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\" /><meta name=\"renderer\" content=\"webkit\"></head><body><div style=\"color:#333;font-size:18px;font-weight:bold;\">${entity.title}</div>${entity.content}</body></html>"
|
||||
val content = "<html><head><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /><meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\" /><meta name=\"renderer\" content=\"webkit\"></head><body style=\"overflow-x: hidden; word-break: break-all;\"><div style=\"color:#333;font-size:18px;font-weight:bold;\">${entity.title}</div>${entity.content}</body></html>"
|
||||
mContext.startActivity(WebActivity.getIntent(mContext, content, false))
|
||||
}
|
||||
val category = mFragment.getHelpCategory()
|
||||
|
||||
@ -14,12 +14,16 @@ class HistoryGameListViewModel(application: Application) : ListViewModel<GameEnt
|
||||
}
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<List<GameEntity>> {
|
||||
return HistoryDatabase.instance.gameDao().getGamesWithOffset(20, (page - 1) * 20).map {
|
||||
val gameEntityList = arrayListOf<GameEntity>()
|
||||
for (history in it) {
|
||||
gameEntityList.add(history.convertHistoryGameEntityToGameEntity())
|
||||
return if (page > 5) {
|
||||
Single.create { it.onSuccess(arrayListOf()) }
|
||||
} else {
|
||||
HistoryDatabase.instance.gameDao().getGamesWithOffset(20, (page - 1) * 20).map {
|
||||
val gameEntityList = arrayListOf<GameEntity>()
|
||||
for (history in it) {
|
||||
gameEntityList.add(history.convertHistoryGameEntityToGameEntity())
|
||||
}
|
||||
gameEntityList
|
||||
}
|
||||
gameEntityList
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ class HomeFragment : BaseFragment<Any>() {
|
||||
mListAdapter.notifyItemByDownload(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.fragment_game
|
||||
}
|
||||
@ -145,7 +146,8 @@ class HomeFragment : BaseFragment<Any>() {
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busNine: EBUISwitch) {
|
||||
if (MainWrapperFragment.EB_MAIN_SCROLL_TOP == busNine.from
|
||||
if (::mLayoutManager.isInitialized
|
||||
&& MainWrapperFragment.EB_MAIN_SCROLL_TOP == busNine.from
|
||||
&& MainWrapperFragment.INDEX_HOME == busNine.position) {
|
||||
mBinding.gameList.stopScroll()
|
||||
mLayoutManager.scrollToPosition(0)
|
||||
|
||||
@ -92,7 +92,7 @@ class HomeSlideListViewHolder(val binding: HomeSlideListBinding) : BaseRecyclerV
|
||||
// 缩放控制
|
||||
fun updateZoomAnimation() {
|
||||
val childCount = binding.recyclerView.childCount
|
||||
val width = binding.recyclerView.getChildAt(0).width
|
||||
val width = binding.recyclerView.getChildAt(0)?.width ?: return
|
||||
val padding = (binding.recyclerView.width - width) / 2
|
||||
|
||||
for (j in 0 until childCount) {
|
||||
|
||||
@ -8,6 +8,7 @@ import android.widget.RelativeLayout;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.base.BaseRecyclerViewHolder;
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
@ -123,7 +124,7 @@ public class MessageItemViewHolder extends BaseRecyclerViewHolder<MessageEntity>
|
||||
mBinding.messageOriginalTitle.setText(messageEntity.getQuestion().getTitle());
|
||||
images = messageEntity.getAnswer().getImages();
|
||||
if (images.size() > 0) {
|
||||
targetUrl=images.get(0);
|
||||
targetUrl = images.get(0);
|
||||
mBinding.messageAskIcon.setVisibility(View.VISIBLE);
|
||||
mBinding.messageArticleIcon.setVisibility(View.GONE);
|
||||
}
|
||||
@ -373,7 +374,9 @@ public class MessageItemViewHolder extends BaseRecyclerViewHolder<MessageEntity>
|
||||
|
||||
mBinding.messageUserMore.setOnClickListener(v -> {
|
||||
MessageEntity.Fold fold = messageEntity.getFold();
|
||||
if (fold != null) getFoldList(context, messageEntity.getFold().getResourceId());
|
||||
if (fold != null && !ClickUtils.isFastDoubleClick(mBinding.messageUserMore.getId(), 1000)) {
|
||||
getFoldList(context, messageEntity.getFold().getResourceId());
|
||||
}
|
||||
});
|
||||
mBinding.messageUserIcon.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("消息中心", mOuterInfo, "点击头像");
|
||||
|
||||
@ -189,7 +189,10 @@ class MyPlayedGameAdapter(context: Context, private val mViewModel: PlayedGameVi
|
||||
|
||||
playedGameRemoveView.findViewById<View>(R.id.remove_container).setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
mViewModel.deletePlayedGame(mEntityList[holder.adapterPosition])
|
||||
val adapterPosition = holder.adapterPosition
|
||||
if (adapterPosition != RecyclerView.NO_POSITION) {
|
||||
mViewModel.deletePlayedGame(mEntityList[adapterPosition])
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
|
||||
@ -24,6 +24,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.DefaultJsApi;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
@ -62,8 +63,10 @@ import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.CommentnumEntity;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.MtaEvent;
|
||||
import com.gh.gamecenter.entity.NewsDetailEntity;
|
||||
import com.gh.gamecenter.entity.NewsEntity;
|
||||
import com.gh.gamecenter.qa.editor.OnLinkClickListener;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gamecenter.subject.SubjectActivity;
|
||||
@ -225,12 +228,15 @@ public class NewsDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
|
||||
mRichEditor = viewHolder.contentTv;
|
||||
if (viewHolder.contentTv.getTag() == null) {
|
||||
MtaEvent mtaEvent = new MtaEvent("阅读文章", "视频", mNewsDetailEntity.getTitle());
|
||||
viewHolder.contentTv.addJavascriptInterface(new OnLinkClickListener(mContext, mEntrance, "新闻详情", mtaEvent), "OnLinkClickListener");
|
||||
viewHolder.contentTv.addJavascriptInterface(new JsInterface(viewHolder.contentTv), "imagelistener");
|
||||
mWebSettings = viewHolder.contentTv.getSettings();
|
||||
mWebSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
mWebSettings.setTextZoom(defaultTextZoom + sp.getInt(SettingsFragment.FONT_SIZE_SP_KEY, 1) * 15);
|
||||
viewHolder.contentTv.setHtml(mNewsDetailEntity.getContent(), true);
|
||||
// viewHolder.contentTv.initArticleVideo();
|
||||
viewHolder.contentTv.setInputEnabled(false);
|
||||
viewHolder.contentTv.setChromeClientListener(new RichEditor.WebChromeClientListener() {
|
||||
@Override
|
||||
@ -788,7 +794,9 @@ public class NewsDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
}
|
||||
|
||||
public void setFontSize(int fontsize) {
|
||||
mWebSettings.setTextZoom(defaultTextZoom + 15 * fontsize);
|
||||
if (mWebSettings != null) {
|
||||
mWebSettings.setTextZoom(defaultTextZoom + 15 * fontsize);
|
||||
}
|
||||
}
|
||||
|
||||
public class JsInterface {
|
||||
|
||||
@ -13,6 +13,16 @@ import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.fragment.BaseFragment;
|
||||
import com.gh.common.databind.BindingAdapters;
|
||||
@ -48,7 +58,6 @@ import com.gh.gamecenter.eventbus.EBConcernChanged;
|
||||
import com.gh.gamecenter.eventbus.EBNetworkState;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.eventbus.EBSkip;
|
||||
import com.gh.gamecenter.eventbus.EBUISwitch;
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.message.MessageUnreadRepository;
|
||||
@ -77,16 +86,6 @@ import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
@ -449,13 +448,13 @@ public class PersonalFragment extends BaseFragment implements Observer<ApiRespon
|
||||
}
|
||||
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBUISwitch busNine) {
|
||||
if (MainWrapperFragment.EB_MAIN_SCROLL_TOP.equals(busNine.getFrom())
|
||||
&& INDEX_PERSONAL == busNine.getPosition()) {
|
||||
//mScrollView.fullScroll(ScrollView.FOCUS_UP);
|
||||
}
|
||||
}
|
||||
// @Subscribe(threadMode = ThreadMode.MAIN)
|
||||
// public void onEventMainThread(EBUISwitch busNine) {
|
||||
// if (MainWrapperFragment.EB_MAIN_SCROLL_TOP.equals(busNine.getFrom())
|
||||
// && INDEX_PERSONAL == busNine.getPosition()) {
|
||||
// //mScrollView.fullScroll(ScrollView.FOCUS_UP);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBReuse reuse) {
|
||||
|
||||
@ -100,7 +100,7 @@ class PersonalFunctionAdapter(val context: Context, val groupName: String, var m
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
MtaHelper.onEvent("我的光环_新", "功能入口", "$groupName+${linkEntity.type}")
|
||||
MtaHelper.onEvent("我的光环_新", "功能入口", "$groupName+${linkEntity.name}")
|
||||
when (linkEntity.type) {
|
||||
"我的游戏" -> {
|
||||
if (UserManager.getInstance().isLoggedIn) {
|
||||
|
||||
@ -41,11 +41,9 @@ class PersonalFunctionGroupAdapter(val context: Context) : BaseRecyclerAdapter<R
|
||||
val groupNameTv = holder.itemView.findViewById<TextView>(R.id.tv_group_name)
|
||||
val funcRv = holder.itemView.findViewById<RecyclerView>(R.id.funcRv)
|
||||
groupNameTv.text = groupEntity.name
|
||||
val mPersonalFunctionAdapter: PersonalFunctionAdapter
|
||||
funcRv.apply {
|
||||
if (adapter == null) {
|
||||
mPersonalFunctionAdapter = PersonalFunctionAdapter(context, groupEntity.name, groupEntity.addons)
|
||||
adapter = mPersonalFunctionAdapter
|
||||
adapter = PersonalFunctionAdapter(context, groupEntity.name, groupEntity.addons)
|
||||
} else {
|
||||
(adapter as PersonalFunctionAdapter).checkResetData(groupEntity)
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.FunctionalGroupEntity
|
||||
import com.gh.gamecenter.entity.FunctionalLinkEntity
|
||||
@ -51,9 +50,7 @@ class PersonalViewModel(application: Application) : AndroidViewModel(application
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ArrayList<FunctionalGroupEntity>>() {
|
||||
override fun onSuccess(data: ArrayList<FunctionalGroupEntity>) {
|
||||
if (!BuildConfig.DEBUG) {
|
||||
haloAddData.postValue(data)
|
||||
}
|
||||
haloAddData.postValue(data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -396,6 +396,7 @@ class CommunityFragment : BaseFragment_TabLayout() {
|
||||
false)
|
||||
val window = dialog.window
|
||||
window?.setGravity(Gravity.BOTTOM)
|
||||
window?.setWindowAnimations(R.style.community_publication_animation)
|
||||
dialog.setContentView(contentView, params)
|
||||
dialog.show()
|
||||
contentView.findViewById<View>(R.id.community_edit_article).setOnClickListener {
|
||||
|
||||
@ -46,7 +46,7 @@ class CommunityAnswerItemViewHolder(val binding: CommunityAnswerItemBinding) : B
|
||||
if (filterIllegalCommentStatus(entity.commentable, entity.active)) return@setOnClickListener
|
||||
|
||||
if (entity.type == "community_article") {
|
||||
val communityId = if (!entity.communityId.isNullOrEmpty()) entity.communityId!!
|
||||
val communityId = if (entity.articleCommunityId.isNotEmpty()) entity.articleCommunityId
|
||||
else UserManager.getInstance().community.id
|
||||
val intent = CommentActivity.getArticleCommentIntent(itemView.context,
|
||||
entity.id!!,
|
||||
@ -210,8 +210,8 @@ class CommunityAnswerItemViewHolder(val binding: CommunityAnswerItemBinding) : B
|
||||
playVoteAnimation()
|
||||
|
||||
val voteObservable = if (entity.type == "community_article") {
|
||||
val communityId = if (entity.communityId.isNullOrEmpty()) UserManager.getInstance().community.id
|
||||
else entity.communityId
|
||||
val communityId = if (entity.articleCommunityId.isNotEmpty()) entity.articleCommunityId
|
||||
else UserManager.getInstance().community.id
|
||||
RetrofitManager.getInstance(itemView.context).api
|
||||
.postCommunityArticleVote(communityId, entity.id)
|
||||
} else {
|
||||
@ -223,7 +223,11 @@ class CommunityAnswerItemViewHolder(val binding: CommunityAnswerItemBinding) : B
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<VoteEntity>() {
|
||||
override fun onResponse(response: VoteEntity?) {
|
||||
entity.me.isAnswerVoted = true
|
||||
if (entity.type == "community_article") {
|
||||
entity.me.isCommunityArticleVote = true
|
||||
} else {
|
||||
entity.me.isAnswerVoted = true
|
||||
}
|
||||
Utils.toast(itemView.context, "已赞同")
|
||||
}
|
||||
|
||||
@ -242,7 +246,11 @@ class CommunityAnswerItemViewHolder(val binding: CommunityAnswerItemBinding) : B
|
||||
true
|
||||
} else {
|
||||
entity.vote = entity.vote - 1
|
||||
entity.me.isAnswerVoted = false
|
||||
if (entity.type == "community_article") {
|
||||
entity.me.isCommunityArticleVote = true
|
||||
} else {
|
||||
entity.me.isAnswerVoted = true
|
||||
}
|
||||
binding.voteCount.text = if (entity.vote > 0) entity.vote.toString() else "赞同"
|
||||
setVoteAndCommentStyle(entity)
|
||||
false
|
||||
@ -254,17 +262,21 @@ class CommunityAnswerItemViewHolder(val binding: CommunityAnswerItemBinding) : B
|
||||
|
||||
private fun cancelAnswerVote(entity: AnswerEntity) {
|
||||
entity.vote = entity.vote - 1
|
||||
entity.me.isAnswerVoted = false
|
||||
|
||||
binding.voteIcon.isChecked = false
|
||||
binding.voteCount.setTextColor(R.color.text_999999.toColor())
|
||||
binding.voteCount.text = if (entity.vote > 0) entity.vote.toString() else "赞同"
|
||||
|
||||
val unVoteObservable = if (entity.type == "community_article") {
|
||||
val communityId = if (entity.communityId.isNullOrEmpty()) UserManager.getInstance().community.id
|
||||
else entity.communityId
|
||||
entity.me.isCommunityArticleVote = false
|
||||
|
||||
val communityId = if (entity.articleCommunityId.isNotEmpty()) entity.articleCommunityId
|
||||
else UserManager.getInstance().community.id
|
||||
RetrofitManager.getInstance(itemView.context).api
|
||||
.postCommunityArticleUnVote(communityId, entity.id)
|
||||
} else {
|
||||
entity.me.isAnswerVoted = false
|
||||
|
||||
RetrofitManager.getInstance(itemView.context).api
|
||||
.postAnswerUnvote(entity.id)
|
||||
}
|
||||
@ -291,7 +303,11 @@ class CommunityAnswerItemViewHolder(val binding: CommunityAnswerItemBinding) : B
|
||||
true
|
||||
} else {
|
||||
entity.vote = entity.vote + 1
|
||||
entity.me.isAnswerVoted = true
|
||||
if (entity.type == "community_article") {
|
||||
entity.me.isCommunityArticleVote = true
|
||||
} else {
|
||||
entity.me.isAnswerVoted = true
|
||||
}
|
||||
binding.voteCount.text = if (entity.vote > 0) entity.vote.toString() else "赞同"
|
||||
setVoteAndCommentStyle(entity)
|
||||
false
|
||||
|
||||
@ -6,6 +6,9 @@ import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.history.HistoryHelper
|
||||
import com.gh.common.syncpage.SyncDataEntity
|
||||
import com.gh.common.syncpage.SyncFieldConstants
|
||||
import com.gh.common.syncpage.SyncPageRepository
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.SpecialColumn
|
||||
@ -88,6 +91,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
|
||||
val apiResponse = ApiResponse<VoteEntity>()
|
||||
apiResponse.data = response
|
||||
mVoteLiveData.postValue(apiResponse)
|
||||
|
||||
syncVoteData(answerId)
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -111,6 +116,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
|
||||
val apiResponse = ApiResponse<VoteEntity>()
|
||||
apiResponse.data = response
|
||||
mVoteLiveData.postValue(apiResponse)
|
||||
|
||||
syncVoteData(answerId)
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -134,6 +141,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
|
||||
answerDetail?.me?.isAnswerVoted = false
|
||||
|
||||
dislike.postValue(true)
|
||||
|
||||
syncVoteData(answerId)
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -150,6 +159,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
answerDetail?.me?.isAnswerOpposed = false
|
||||
dislike.postValue(false)
|
||||
|
||||
syncVoteData(answerId)
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -158,6 +169,16 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
|
||||
})
|
||||
}
|
||||
|
||||
private fun syncVoteData(answerId: String) {
|
||||
SyncPageRepository.postSyncData(SyncDataEntity(answerId,
|
||||
SyncFieldConstants.ANSWER_VOTE_COUNT,
|
||||
answerDetail!!.vote))
|
||||
SyncPageRepository.postSyncData(SyncDataEntity(answerId,
|
||||
SyncFieldConstants.ANSWER_VOTE,
|
||||
answerDetail?.me?.isAnswerVoted,
|
||||
checkFieldEntity = true))
|
||||
}
|
||||
|
||||
fun collectAnswer(answerId: String) {
|
||||
CollectionUtils.postCollection(getApplication(), answerId, CollectionUtils.CollectionType.answer, object : CollectionUtils.OnCollectionListener {
|
||||
override fun onSuccess() {
|
||||
|
||||
@ -6,6 +6,7 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.common.constant.ItemViewType;
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder;
|
||||
import com.gh.gamecenter.baselist.ListAdapter;
|
||||
@ -14,13 +15,16 @@ import com.gh.gamecenter.qa.answer.CommunityAnswerItemViewHolder;
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity;
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import kotlin.Pair;
|
||||
|
||||
/**
|
||||
* Created by khy on 11/12/17.
|
||||
*/
|
||||
|
||||
public class AnswerFoldAdapter extends ListAdapter<AnswerEntity> {
|
||||
public class AnswerFoldAdapter extends ListAdapter<AnswerEntity> implements ISyncAdapterHandler {
|
||||
|
||||
private OnListClickListener mListClickListener;
|
||||
|
||||
@ -59,8 +63,8 @@ public class AnswerFoldAdapter extends ListAdapter<AnswerEntity> {
|
||||
switch (getItemViewType(position)) {
|
||||
case ItemViewType.ITEM_BODY:
|
||||
AnswerEntity answer = mEntityList.get(position);
|
||||
((CommunityAnswerItemViewHolder) holder).bindAnswerItem(answer,true, mEntrance, "折叠答案");
|
||||
((CommunityAnswerItemViewHolder) holder).getBinding().getRoot().setOnClickListener( view -> {
|
||||
((CommunityAnswerItemViewHolder) holder).bindAnswerItem(answer, true, mEntrance, "折叠答案");
|
||||
((CommunityAnswerItemViewHolder) holder).getBinding().getRoot().setOnClickListener(view -> {
|
||||
mContext.startActivity(AnswerDetailActivity.getIntent(mContext, answer.getId(), mEntrance, "折叠答案"));
|
||||
});
|
||||
|
||||
@ -77,4 +81,12 @@ public class AnswerFoldAdapter extends ListAdapter<AnswerEntity> {
|
||||
public int getItemCount() {
|
||||
return mEntityList == null || mEntityList.isEmpty() ? 0 : mEntityList.size() + FOOTER_ITEM_COUNT;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Pair<String, Object> getSyncData(int position) {
|
||||
if (position >= mEntityList.size()) return null;
|
||||
AnswerEntity entity = mEntityList.get(position);
|
||||
return new Pair(entity.getId(), entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
package com.gh.gamecenter.qa.answer.fold;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
@ -97,4 +99,15 @@ public class AnswerFoldFragment extends ListFragment<AnswerEntity, NormalListVie
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected RecyclerView.Adapter provideSyncAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean addSyncPageObserver() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ class MyArticleFragment : ListFragment<ArticleEntity, NormalListViewModel<Articl
|
||||
return mAdapter!!
|
||||
}
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<ArticleEntity>> {
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<ArticleEntity>>? {
|
||||
return RetrofitManager.getInstance(HaloApp.getInstance().application).api.getMyArticle(mTargetUserId, page)
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.baselist.ListAdapter
|
||||
@ -15,7 +16,7 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
import com.gh.gamecenter.qa.entity.Questions
|
||||
|
||||
class SimpleArticleListAdapter(context: Context) : ListAdapter<ArticleEntity>(context) {
|
||||
class SimpleArticleListAdapter(context: Context) : ListAdapter<ArticleEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun areItemsTheSame(oldItem: ArticleEntity?, newItem: ArticleEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
@ -72,4 +73,10 @@ class SimpleArticleListAdapter(context: Context) : ListAdapter<ArticleEntity>(co
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, Any>? {
|
||||
if (position >= mEntityList.size) return null
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id, entity)
|
||||
}
|
||||
|
||||
}
|
||||
@ -86,4 +86,12 @@ class SimpleArticleListFragment : ListFragment<ArticleEntity, SimpleArticleListV
|
||||
mBaseHandler.postDelayed({ mListViewModel.load(LoadType.REFRESH) }, 100)
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,9 @@ import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.syncpage.SyncDataEntity
|
||||
import com.gh.common.syncpage.SyncFieldConstants
|
||||
import com.gh.common.syncpage.SyncPageRepository
|
||||
import com.gh.common.util.CollectionUtils
|
||||
import com.gh.common.util.ErrorHelper
|
||||
import com.gh.gamecenter.R
|
||||
@ -79,6 +82,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
|
||||
detailEntity!!.count.vote--
|
||||
|
||||
like.postValue(response)
|
||||
|
||||
syncVoteData()
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -99,6 +104,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
|
||||
detailEntity!!.count.vote++
|
||||
|
||||
like.postValue(response)
|
||||
|
||||
syncVoteData()
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -119,6 +126,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
|
||||
detailEntity?.me?.isCommunityArticleVote = false
|
||||
|
||||
dislike.postValue(true)
|
||||
|
||||
syncVoteData()
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -135,6 +144,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
|
||||
detailEntity?.me?.isCommunityArticleOppose = false
|
||||
|
||||
dislike.postValue(false)
|
||||
|
||||
syncVoteData()
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
@ -143,6 +154,19 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
|
||||
})
|
||||
}
|
||||
|
||||
private fun syncVoteData() {
|
||||
articleId?.apply {
|
||||
SyncPageRepository.postSyncData(SyncDataEntity(this,
|
||||
SyncFieldConstants.ARTICLE_VOTE_COUNT,
|
||||
detailEntity?.count?.vote,
|
||||
checkFieldEntity = true))
|
||||
SyncPageRepository.postSyncData(SyncDataEntity(this,
|
||||
SyncFieldConstants.ARTICLE_VOTE,
|
||||
detailEntity?.me?.isCommunityArticleVote,
|
||||
checkFieldEntity = true))
|
||||
}
|
||||
}
|
||||
|
||||
fun collectionCommand(isCollection: Boolean, callback: (isFollow: Boolean) -> Unit) {
|
||||
val observable = if (isCollection) {
|
||||
mApi.postCommunityArticleFavorites(UserManager.getInstance().userId, community?.id, articleId)
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.ViewGroup
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
@ -21,7 +22,7 @@ import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
class HotAdapter(context: Context,
|
||||
private val mEntrance: String,
|
||||
private val mPath: String,
|
||||
private val mSpecialColumn: SpecialColumn) : ListAdapter<AnswerEntity>(context) {
|
||||
private val mSpecialColumn: SpecialColumn) : ListAdapter<AnswerEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == itemCount - 1) ItemViewType.ITEM_FOOTER else ItemViewType.ITEM_BODY
|
||||
@ -87,4 +88,10 @@ class HotAdapter(context: Context,
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, AnswerEntity>? {
|
||||
if (position >= mEntityList.size) return null
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.gh.gamecenter.qa.column.detail.hot
|
||||
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.baselist.ListFragment
|
||||
import com.gh.gamecenter.entity.SpecialColumn
|
||||
@ -25,16 +26,16 @@ class HotFragment : ListFragment<AnswerEntity, HotViewModel>() {
|
||||
mSpecialColumn.type = "社区专栏"
|
||||
"专栏-热门"
|
||||
}
|
||||
mAdapter = HotAdapter(context!!, mEntrance, path, mSpecialColumn)
|
||||
mAdapter = HotAdapter(requireContext(), mEntrance, path, mSpecialColumn)
|
||||
}
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun provideListViewModel(): HotViewModel {
|
||||
val tag = arguments!!.getString(EntranceUtils.KEY_ASK_TAG)
|
||||
val entity = arguments!!.getParcelable<AskTagGroupsEntity>(EntranceUtils.KEY_ASK_COLUMN_TAG)
|
||||
val tag = requireArguments().getString(EntranceUtils.KEY_ASK_TAG)
|
||||
val entity = requireArguments().getParcelable<AskTagGroupsEntity>(EntranceUtils.KEY_ASK_COLUMN_TAG)
|
||||
val factory = HotViewModel.Factory(HaloApp.getInstance().application
|
||||
, if (tag.isNullOrEmpty()) entity else tag, arguments!!.getParcelable(EntranceUtils.KEY_COMMUNITY_DATA))
|
||||
, if (tag.isNullOrEmpty()) entity else tag, requireArguments().getParcelable(EntranceUtils.KEY_COMMUNITY_DATA))
|
||||
return ViewModelProviders.of(this, factory).get(HotViewModel::class.java)
|
||||
}
|
||||
|
||||
@ -48,4 +49,12 @@ class HotFragment : ListFragment<AnswerEntity, HotViewModel>() {
|
||||
mListRv.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.ViewGroup
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
@ -21,7 +22,7 @@ import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
class RecommendsAdapter(context: Context,
|
||||
private val mEntrance: String,
|
||||
private val mPath: String,
|
||||
private val mSpecialColumn: SpecialColumn) : ListAdapter<AnswerEntity>(context) {
|
||||
private val mSpecialColumn: SpecialColumn) : ListAdapter<AnswerEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == itemCount - 1) ItemViewType.ITEM_FOOTER else ItemViewType.ITEM_BODY
|
||||
@ -85,4 +86,9 @@ class RecommendsAdapter(context: Context,
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, AnswerEntity>? {
|
||||
if (position >= mEntityList.size) return null
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.gh.gamecenter.qa.column.detail.recommends
|
||||
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.baselist.ListFragment
|
||||
import com.gh.gamecenter.entity.SpecialColumn
|
||||
@ -25,16 +26,16 @@ class RecommendsFragment : ListFragment<AnswerEntity, RecommendsViewModel>() {
|
||||
mSpecialColumn.type = "社区专栏"
|
||||
"专栏-精华"
|
||||
}
|
||||
mAdapter = RecommendsAdapter(context!!, mEntrance, path, mSpecialColumn)
|
||||
mAdapter = RecommendsAdapter(requireContext(), mEntrance, path, mSpecialColumn)
|
||||
}
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun provideListViewModel(): RecommendsViewModel {
|
||||
val tag = arguments!!.getString(EntranceUtils.KEY_ASK_TAG)
|
||||
val entity = arguments!!.getParcelable<AskTagGroupsEntity>(EntranceUtils.KEY_ASK_COLUMN_TAG)
|
||||
val tag = requireArguments().getString(EntranceUtils.KEY_ASK_TAG)
|
||||
val entity = requireArguments().getParcelable<AskTagGroupsEntity>(EntranceUtils.KEY_ASK_COLUMN_TAG)
|
||||
val factory = RecommendsViewModel.Factory(HaloApp.getInstance().application
|
||||
, if (tag.isNullOrEmpty()) entity else tag, arguments!!.getParcelable(EntranceUtils.KEY_COMMUNITY_DATA))
|
||||
, if (tag.isNullOrEmpty()) entity else tag, requireArguments().getParcelable(EntranceUtils.KEY_COMMUNITY_DATA))
|
||||
return ViewModelProviders.of(this, factory).get(RecommendsViewModel::class.java)
|
||||
}
|
||||
|
||||
@ -48,4 +49,11 @@ class RecommendsFragment : ListFragment<AnswerEntity, RecommendsViewModel>() {
|
||||
mListRv.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -42,7 +42,6 @@ class UnansweredAdapter(context: Context,
|
||||
if (holder is CommunityQuestionViewHolder) {
|
||||
val questions = mEntityList[position]
|
||||
holder.bindQuestionViewHolder(questions, mEntrance, mPath)
|
||||
holder.binding.endDesc.setOnClickListener { holder.itemView.performClick() }
|
||||
holder.itemView.setOnClickListener {
|
||||
mContext.startActivity(QuestionsDetailActivity.getIntent(mContext, questions.id, mEntrance, mPath, mSpecialColumn))
|
||||
}
|
||||
|
||||
@ -21,6 +21,9 @@ import butterknife.BindView
|
||||
import butterknife.OnClick
|
||||
import butterknife.Optional
|
||||
import com.gh.base.fragment.BaseDialogWrapperFragment
|
||||
import com.gh.common.syncpage.SyncDataEntity
|
||||
import com.gh.common.syncpage.SyncFieldConstants
|
||||
import com.gh.common.syncpage.SyncPageRepository
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.VerticalItemDecoration
|
||||
import com.gh.gamecenter.R
|
||||
@ -93,6 +96,17 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
|
||||
mCommentListener?.onCommentDraftChange("")
|
||||
}
|
||||
commentEt.postDelayed({ setSoftInput(false) }, 100)
|
||||
|
||||
if (mCommentType == CommentType.COMMUNITY_ARTICLE) {
|
||||
SyncPageRepository.postSyncData(SyncDataEntity(mArticleId,
|
||||
SyncFieldConstants.ARTICLE_COMMENT_COUNT,
|
||||
mCommentCount,
|
||||
checkFieldEntity = true))
|
||||
} else if (mCommentType == CommentType.ANSWER) {
|
||||
SyncPageRepository.postSyncData(SyncDataEntity(mAnswerId,
|
||||
SyncFieldConstants.ANSWER_COMMENT_COUNT,
|
||||
mCommentCount))
|
||||
}
|
||||
}
|
||||
apiResponse.httpException != null -> {
|
||||
mSendingDialog?.dismiss()
|
||||
|
||||
@ -4,11 +4,14 @@ import android.content.Context
|
||||
import android.webkit.JavascriptInterface
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.DefaultJsApi
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.MtaEvent
|
||||
import com.gh.gamecenter.entity.MyVideoEntity
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
@ -21,7 +24,8 @@ import com.lightgame.utils.Utils
|
||||
*/
|
||||
class OnLinkClickListener(val context: Context,
|
||||
val entrance: String,
|
||||
val path: String) {
|
||||
val path: String,
|
||||
val mtaEvent: MtaEvent? = null) {
|
||||
@JavascriptInterface
|
||||
fun onClick(content: String) {
|
||||
AppExecutor.uiExecutor.execute {
|
||||
@ -58,6 +62,7 @@ class OnLinkClickListener(val context: Context,
|
||||
fun onVideoClick(content: String) {
|
||||
AppExecutor.uiExecutor.execute {
|
||||
tryWithDefaultCatch {
|
||||
if (mtaEvent != null) MtaHelper.onEvent(mtaEvent.name, mtaEvent.key, mtaEvent.value)
|
||||
val videoEntity = GsonUtils.fromJson(content, MyVideoEntity::class.java)
|
||||
if (videoEntity.status == "pass") {
|
||||
DirectUtils.directToVideoDetail(context,
|
||||
|
||||
@ -7,6 +7,9 @@ import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.gh.common.annotation.SyncIgnore
|
||||
import com.gh.common.annotation.SyncPage
|
||||
import com.gh.common.syncpage.SyncFieldConstants
|
||||
import com.gh.gamecenter.entity.MeEntity
|
||||
import com.gh.gamecenter.entity.UserEntity
|
||||
import com.gh.gamecenter.room.converter.AnswerUserConverter
|
||||
@ -25,8 +28,11 @@ class AnswerEntity() : Parcelable {
|
||||
@PrimaryKey
|
||||
var primaryKey: String = "" // db key
|
||||
|
||||
var communityId: String? = null // communityId + userId 社区推荐数据库存储专用,社区推荐接口不能给该字段
|
||||
|
||||
@Ignore
|
||||
@SerializedName("community_id")
|
||||
var communityId: String? = null // 社区推荐接口不能给该字段,否则和数据库分类(根据社区分类)数据有冲突
|
||||
var articleCommunityId: String = "" // 一般情况,只有该数据是文章时接口才会给该字段
|
||||
|
||||
var orderTag: Long = 0
|
||||
|
||||
@ -47,11 +53,13 @@ class AnswerEntity() : Parcelable {
|
||||
@TypeConverters(CommunityVideoConverter::class)
|
||||
var videos: List<CommunityVideoEntity> = ArrayList()
|
||||
|
||||
@SyncPage(syncNames = [SyncFieldConstants.ANSWER_VOTE_COUNT, SyncFieldConstants.ARTICLE_VOTE_COUNT])
|
||||
var vote: Int = 0
|
||||
|
||||
@TypeConverters(AnswerUserConverter::class)
|
||||
var user: UserEntity = UserEntity()
|
||||
|
||||
@SyncIgnore // questions里的vote当前entity的vote冲突
|
||||
@TypeConverters(QuestionsConverter::class)
|
||||
@SerializedName("question")
|
||||
var questions: Questions = Questions()
|
||||
@ -59,6 +67,7 @@ class AnswerEntity() : Parcelable {
|
||||
@SerializedName("community_name")
|
||||
var communityName: String? = null
|
||||
|
||||
@SyncPage(syncNames = [SyncFieldConstants.ANSWER_COMMENT_COUNT, SyncFieldConstants.ARTICLE_COMMENT_COUNT])
|
||||
@SerializedName("comment_count")
|
||||
var commentCount: Int = 0
|
||||
|
||||
@ -87,7 +96,7 @@ class AnswerEntity() : Parcelable {
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
primaryKey = parcel.readString()
|
||||
communityId = parcel.readString()
|
||||
articleCommunityId = parcel.readString()
|
||||
orderTag = parcel.readLong()
|
||||
id = parcel.readString()
|
||||
brief = parcel.readString()
|
||||
@ -105,7 +114,7 @@ class AnswerEntity() : Parcelable {
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(primaryKey)
|
||||
parcel.writeString(communityId)
|
||||
parcel.writeString(articleCommunityId)
|
||||
parcel.writeLong(orderTag)
|
||||
parcel.writeString(id)
|
||||
parcel.writeString(brief)
|
||||
|
||||
@ -5,6 +5,8 @@ import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.gh.common.annotation.SyncPage
|
||||
import com.gh.common.syncpage.SyncFieldConstants
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.MeEntity
|
||||
import com.gh.gamecenter.entity.UserEntity
|
||||
@ -69,7 +71,9 @@ data class ArticleEntity(
|
||||
|
||||
@Parcelize
|
||||
data class Count(
|
||||
@SyncPage(syncNames = [SyncFieldConstants.ARTICLE_COMMENT_COUNT])
|
||||
var comment: Int = 0,
|
||||
@SyncPage(syncNames = [SyncFieldConstants.ARTICLE_VOTE_COUNT])
|
||||
var vote: Int = 0,
|
||||
var answer: Int = 0) : Parcelable
|
||||
|
||||
|
||||
@ -68,12 +68,14 @@ class AskFollowAdapter(val context: Context, val viewModel: AskFollowViewModel)
|
||||
userDesc.text = highlightedString
|
||||
userDesc.visibility = View.VISIBLE
|
||||
userDesc.setOnClickListener {
|
||||
val dialog = AskFollowMoreDialog().apply {
|
||||
userList = ArrayList(historyEntity.foldUsers)
|
||||
this.type = "赞同$type"
|
||||
this.path = "问答首页-关注折叠"
|
||||
debounceActionWithInterval(userDesc.id, 1000) {
|
||||
val dialog = AskFollowMoreDialog().apply {
|
||||
userList = ArrayList(historyEntity.foldUsers)
|
||||
this.type = "赞同$type"
|
||||
this.path = "问答首页-关注折叠"
|
||||
}
|
||||
dialog.show((context as AppCompatActivity).supportFragmentManager, "more")
|
||||
}
|
||||
dialog.show((context as AppCompatActivity).supportFragmentManager, "more")
|
||||
}
|
||||
userCommand.text = "赞同了$type"
|
||||
} else {
|
||||
|
||||
@ -65,7 +65,6 @@ public class AskQuestionsNewBodyAdapter extends ListAdapter<Questions> {
|
||||
case ItemViewType.ITEM_BODY:
|
||||
Questions questions = mEntityList.get(position);
|
||||
((CommunityQuestionViewHolder) holder).bindQuestionViewHolder(questions, mEntrance, "问答-问题");
|
||||
((CommunityQuestionViewHolder) holder).getBinding().endDesc.setOnClickListener(v -> holder.itemView.performClick());
|
||||
holder.itemView.setOnClickListener(v -> mContext.startActivity(QuestionsDetailActivity.getIntent(mContext, questions.getId(), mEntrance, "问答-问题")));
|
||||
break;
|
||||
case ItemViewType.ITEM_FOOTER:
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package com.gh.gamecenter.qa.questions
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.NewsUtils
|
||||
@ -11,6 +14,7 @@ import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
|
||||
import com.gh.gamecenter.qa.entity.Questions
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
class CommunityQuestionViewHolder(val binding: CommunityQuestionItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
@ -24,6 +28,7 @@ class CommunityQuestionViewHolder(val binding: CommunityQuestionItemBinding) : B
|
||||
binding.endDesc.text = questions.communityName
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun bindViewHolder(questions: Questions, entrance: String, path: String) {
|
||||
binding.title.text = questions.title
|
||||
if (questions.answerCount > 0) {
|
||||
@ -38,16 +43,28 @@ class CommunityQuestionViewHolder(val binding: CommunityQuestionItemBinding) : B
|
||||
"回答")
|
||||
}
|
||||
|
||||
binding.answerCountContainer.setOnClickListener {
|
||||
if (questions.answerCount > 0) {
|
||||
itemView.context.startActivity(QuestionsDetailActivity.getIntent(itemView.context, questions.id, entrance, path))
|
||||
} else {
|
||||
// 虽然很丑陋,但是没有想到其它好的办法实现:https://gitlab.ghzs.com/pm/halo-app-issues/issues/812 (7)
|
||||
if (questions.answerCount <= 0 && questions.me.myAnswerId.isNullOrEmpty()) {
|
||||
binding.answerCountContainer.setOnTouchListener { _, event ->
|
||||
if (event.action == MotionEvent.ACTION_DOWN || event.action == MotionEvent.ACTION_MOVE) {
|
||||
binding.answerCountContainer.setBackgroundResource(R.drawable.reuse_listview_item_style)
|
||||
} else {
|
||||
binding.answerCountContainer.background = null
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
binding.answerCountContainer.setOnClickListener {
|
||||
CheckLoginUtils.checkLogin(itemView.context, entrance) {
|
||||
val communityName = if (questions.communityName.isNullOrEmpty()) UserManager.getInstance().community.name
|
||||
else questions.communityName
|
||||
itemView.context.startActivity(AnswerEditActivity.getIntent(itemView.context, questions, communityName))
|
||||
}
|
||||
}
|
||||
binding.answerCountContainer.isClickable = true
|
||||
} else {
|
||||
binding.answerCountContainer.isClickable = false
|
||||
binding.answerCountContainer.setOnTouchListener(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,7 @@ import butterknife.BindView
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.base.OnListClickListener
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.DrawableView
|
||||
import com.gh.gamecenter.R
|
||||
@ -27,6 +28,7 @@ import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.qa.answer.CommunityAnswerItemViewHolder
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
|
||||
import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.InviteEntity
|
||||
import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
|
||||
import com.gh.gamecenter.qa.questions.invite.QuestionsInviteAdapter
|
||||
@ -38,7 +40,7 @@ class QuestionsDetailAdapter(
|
||||
private var mListClickListener: OnListClickListener,
|
||||
private var mQuestionEntity: QuestionsDetailEntity? = null,
|
||||
private val mViewModel: QuestionsDetailViewModel,
|
||||
private val mEntrance: String) : ListAdapter<QuestionDetailItemData>(context) {
|
||||
private val mEntrance: String) : ListAdapter<QuestionDetailItemData>(context), ISyncAdapterHandler {
|
||||
|
||||
private var mIsNoneData: Boolean = false
|
||||
|
||||
@ -415,6 +417,16 @@ class QuestionsDetailAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, AnswerEntity>? {
|
||||
val index = position - TOP_ITEM_COUNT
|
||||
if (index < 0 || index >= mEntityList.size) return null
|
||||
val itemData = mEntityList[index]
|
||||
var entity = itemData.answer
|
||||
if (entity == null) entity = itemData.similarAnswer
|
||||
if (entity == null) return null
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
|
||||
class SimpleInviteAdapter(context: Context, onListClickListener: OnListClickListener, entrance: String)
|
||||
: QuestionsInviteAdapter(context, onListClickListener, entrance, "问题详情-邀请列表") {
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
|
||||
@ -301,9 +301,9 @@ class QuestionsDetailFragment :
|
||||
}
|
||||
R.id.questionsdetail_concern, R.id.questionsdetail_concern_container -> CheckLoginUtils.checkLogin(context, "问题详情-[关注问题]") {
|
||||
if (mQuestionsDetailEntity!!.me.isContentOwner) {
|
||||
startActivityForResult(QuestionEditActivity.getIntent(context!!, mQuestionsDetailEntity!!), QUESTIONS_EDIT_REQUEST)
|
||||
startActivityForResult(QuestionEditActivity.getIntent(requireContext(), mQuestionsDetailEntity!!), QUESTIONS_EDIT_REQUEST)
|
||||
} else if (!mQuestionsDetailEntity!!.me.isQuestionFollowed) {
|
||||
ConcernUtils.postConcernQuestions(context!!, mQuestionsId!!, object : ConcernUtils.onConcernListener {
|
||||
ConcernUtils.postConcernQuestions(requireContext(), mQuestionsId!!, object : ConcernUtils.onConcernListener {
|
||||
override fun onSuccess() {
|
||||
mQuestionsDetailEntity!!.me.isQuestionFollowed = true
|
||||
mQuestionsDetailEntity!!.setFollowCount(mQuestionsDetailEntity!!.getFollowCount() + 1)
|
||||
@ -381,7 +381,7 @@ class QuestionsDetailFragment :
|
||||
R.id.menu_more -> showMoreItemDialog()
|
||||
R.id.menu_question_and_answer -> {
|
||||
HaloApp.remove(GAME_DETAIL_COME_IN)
|
||||
DirectUtils.directToCommunity(context!!, it.community)
|
||||
DirectUtils.directToCommunity(requireContext(), it.community)
|
||||
LogUtils.qaAccess("问题详情-进入问答", it.community)
|
||||
MtaHelper.onEvent("进入问答", "问题详情", it.community.name + "+" + StringUtils.combineTwoString(it.title, it.id))
|
||||
}
|
||||
@ -511,7 +511,7 @@ class QuestionsDetailFragment :
|
||||
itemTv.setBackgroundResource(R.drawable.textview_white_style)
|
||||
itemTv.layoutParams = LinearLayout.LayoutParams(widthPixels * 9 / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
itemTv.setPadding(DisplayUtils.dip2px(context!!, 20f), pad, 0, pad)
|
||||
itemTv.setPadding(DisplayUtils.dip2px(requireContext(), 20f), pad, 0, pad)
|
||||
container.addView(itemTv)
|
||||
|
||||
itemTv.setOnClickListener {
|
||||
@ -644,6 +644,14 @@ class QuestionsDetailFragment :
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val QUESTIONS_DETAIL_ANSWER_REQUEST = 110
|
||||
const val QUESTIONS_EDIT_REQUEST = 111
|
||||
|
||||
@ -5,12 +5,14 @@ import android.content.Context;
|
||||
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import kotlin.Pair;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.common.constant.ItemViewType;
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -27,6 +29,8 @@ import com.gh.gamecenter.qa.entity.AnswerEntity;
|
||||
import com.gh.gamecenter.qa.entity.Questions;
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -34,7 +38,7 @@ import java.util.List;
|
||||
* Created by khy on 2/12/17.
|
||||
*/
|
||||
|
||||
public class AskQuestionsRecommendsAdapter extends ListAdapter<RecommendItemData> {
|
||||
public class AskQuestionsRecommendsAdapter extends ListAdapter<RecommendItemData> implements ISyncAdapterHandler {
|
||||
|
||||
private OnListClickListener mListClickListener;
|
||||
private AskQuestionsRecommendsViewModel mListViewModel;
|
||||
@ -187,4 +191,13 @@ public class AskQuestionsRecommendsAdapter extends ListAdapter<RecommendItemData
|
||||
public boolean isOver() {
|
||||
return mIsOver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Pair<String, Object> getSyncData(int position) {
|
||||
if (position >= mEntityList.size()) return null;
|
||||
AnswerEntity entity = mEntityList.get(position).getAnswer();
|
||||
if (entity != null) return new Pair(entity.getId(), entity);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,13 +26,8 @@ import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange;
|
||||
import com.gh.gamecenter.eventbus.EBUserFollow;
|
||||
import com.gh.gamecenter.fragment.MainWrapperFragment;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.qa.CommunityFragment;
|
||||
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity;
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity;
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity;
|
||||
import com.gh.gamecenter.qa.entity.Questions;
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity;
|
||||
import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
@ -289,4 +284,15 @@ public class AskQuestionsRecommendsFragment extends ListFragment<RecommendItemDa
|
||||
}
|
||||
return parentFragment;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected RecyclerView.Adapter provideSyncAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean addSyncPageObserver() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.baselist.ListAdapter
|
||||
@ -16,8 +17,9 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.Questions
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
open class RecommendNewestAdapter(context: Context) : ListAdapter<AnswerEntity>(context) {
|
||||
open class RecommendNewestAdapter(context: Context) : ListAdapter<AnswerEntity>(context), ISyncAdapterHandler {
|
||||
|
||||
override fun areItemsTheSame(oldItem: AnswerEntity?, newItem: AnswerEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
@ -88,4 +90,9 @@ open class RecommendNewestAdapter(context: Context) : ListAdapter<AnswerEntity>(
|
||||
return "问答-推荐-按时间"
|
||||
}
|
||||
|
||||
override fun getSyncData(position: Int): Pair<String, Any>? {
|
||||
if (position >= mEntityList.size) return null
|
||||
val entity = mEntityList[position]
|
||||
return Pair(entity.id ?: "", entity)
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ class RecommendNewestFragment : ListFragment<AnswerEntity, NormalListViewModel<A
|
||||
|
||||
override fun provideListAdapter(): RecommendNewestAdapter {
|
||||
if (mAdapter == null) {
|
||||
mAdapter = RecommendNewestAdapter(context!!)
|
||||
mAdapter = RecommendNewestAdapter(requireContext())
|
||||
}
|
||||
return mAdapter!!
|
||||
}
|
||||
@ -130,4 +130,12 @@ class RecommendNewestFragment : ListFragment<AnswerEntity, NormalListViewModel<A
|
||||
return (parentFragment as? AskRecommendWrapperFragment)?.refreshLayout
|
||||
?: DumbRefreshLayout(context)
|
||||
}
|
||||
|
||||
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
|
||||
return mAdapter
|
||||
}
|
||||
|
||||
override fun addSyncPageObserver(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,12 @@
|
||||
package com.gh.gamecenter.qa.search;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
@ -88,7 +89,7 @@ public class AskSearchFragment extends BaseFragment_TabLayout {
|
||||
|
||||
void updateSearch(String key) {
|
||||
for (Fragment fragment : mFragmentsList) {
|
||||
if (fragment instanceof BaseAskSearchFragment) {
|
||||
if (fragment instanceof BaseAskSearchFragment && isAdded()) {
|
||||
((BaseAskSearchFragment) fragment).search(key);
|
||||
Bundle arguments = fragment.getArguments();
|
||||
// 处于 state saved 状态的 fragment 不可 setArguments
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user