diff --git a/app/build.gradle b/app/build.gradle index 55cfb3f2b3..ca1c44dcdd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -249,6 +249,7 @@ dependencies { implementation "android.arch.lifecycle:extensions:${archLifecycleVersion}" implementation "android.arch.persistence.room:runtime:${archRoomVersion}" kapt "android.arch.persistence.room:compiler:${archRoomVersion}" + implementation "android.arch.persistence.room:rxjava2:${archRoomVersion}" implementation 'com.google.android:flexbox:0.2.2' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ba970e9325..78c2162a9e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -385,6 +385,10 @@ android:name = "com.gh.gamecenter.gamedetail.rating.RatingReplyActivity" android:screenOrientation = "portrait" /> + + Unit) { + AppExecutor.ioExecutor.execute(f) +} + +fun runOnUiThread(f: () -> Unit) { + AppExecutor.uiExecutor.execute(f) } \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/history/HistoryDatabase.kt b/app/src/main/java/com/gh/common/history/HistoryDatabase.kt new file mode 100644 index 0000000000..cc478dfeea --- /dev/null +++ b/app/src/main/java/com/gh/common/history/HistoryDatabase.kt @@ -0,0 +1,23 @@ +package com.gh.common.history + +import android.arch.persistence.room.Database +import android.arch.persistence.room.Room +import android.arch.persistence.room.RoomDatabase +import com.gh.gamecenter.qa.entity.AnswerEntity +import com.gh.gamecenter.room.dao.HistoryAnswerDao +import com.halo.assistant.HaloApp + +@Database(entities = [AnswerEntity::class], version = 1, exportSchema = false) +abstract class HistoryDatabase : RoomDatabase() { + + abstract fun answerDao(): HistoryAnswerDao + + companion object { + val instance by lazy { + Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE") + .fallbackToDestructiveMigration() + .build() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/history/HistoryHelper.kt b/app/src/main/java/com/gh/common/history/HistoryHelper.kt new file mode 100644 index 0000000000..54f8e93cb2 --- /dev/null +++ b/app/src/main/java/com/gh/common/history/HistoryHelper.kt @@ -0,0 +1,30 @@ +package com.gh.common.history + +import android.text.Html +import com.gh.common.runOnIoThread +import com.gh.gamecenter.qa.entity.AnswerDetailEntity +import com.gh.gamecenter.qa.entity.AnswerEntity + +object HistoryHelper { + + fun insertAnswerEntity(answerDetailEntity: AnswerDetailEntity) { + val answerEntity = convertAnswerDetailEntityToAnswerEntity(answerDetailEntity) + runOnIoThread { HistoryDatabase.instance.answerDao().addAnswer(answerEntity) } + } + + private fun convertAnswerDetailEntityToAnswerEntity(answerDetailEntity: AnswerDetailEntity): AnswerEntity { + val answerEntity = AnswerEntity() + + answerEntity.id = answerDetailEntity.id + answerEntity.primaryKey = answerDetailEntity.id + answerEntity.commentCount = answerDetailEntity.commentCount + answerEntity.questions = answerDetailEntity.question + answerEntity.vote = answerDetailEntity.vote + answerEntity.user = answerDetailEntity.user + answerEntity.orderTag = System.currentTimeMillis() + answerEntity.brief = Html.fromHtml(answerDetailEntity.content).toString() + answerEntity.time = answerDetailEntity.time + return answerEntity + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/view/ExpendTextView.java b/app/src/main/java/com/gh/common/view/ExpendTextView.java index 29af50ad6d..f3ebf3703d 100644 --- a/app/src/main/java/com/gh/common/view/ExpendTextView.java +++ b/app/src/main/java/com/gh/common/view/ExpendTextView.java @@ -89,7 +89,8 @@ public class ExpendTextView extends android.support.v7.widget.AppCompatTextView } SpannableStringBuilder msp = new SpannableStringBuilder(content); int length = msp.length(); - msp.replace(length - mExpendText.length(), length, mExpendText); + int startPosition = length - mExpendText.length(); + msp.replace(startPosition < 0 ? 0 : startPosition, length, mExpendText); msp.setSpan(new ClickableSpan() { @Override public void updateDrawState(TextPaint ds) { diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListActivity.java b/app/src/main/java/com/gh/gamecenter/baselist/ListActivity.java index 9551cb95ed..badf8ca0b6 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListActivity.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListActivity.java @@ -23,6 +23,7 @@ import java.util.List; import butterknife.BindView; import io.reactivex.Observable; +import io.reactivex.Single; public abstract class ListActivity extends BaseActivity @@ -144,6 +145,11 @@ public abstract class ListActivity provideDataSingle(int page) { + return null; + } + public void onLoadRefresh() { mReuseNoConn.setVisibility(View.GONE); mReuseNoData.setVisibility(View.GONE); diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java b/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java index a0e1ebf394..c73ccc4b9d 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java @@ -24,6 +24,7 @@ import java.util.List; import butterknife.BindView; import io.reactivex.Observable; +import io.reactivex.Single; /** * Created by khy on 2/12/17. @@ -161,6 +162,11 @@ public abstract class ListFragment> provideDataSingle(int page) { + return null; + } + public void onLoadRefresh() { mReuseNoConn.setVisibility(View.GONE); mReuseNoData.setVisibility(View.GONE); diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java b/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java index ba5d3414a0..fbe8eca86d 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java @@ -1,5 +1,6 @@ package com.gh.gamecenter.baselist; +import android.annotation.SuppressLint; import android.app.Application; import android.arch.lifecycle.MutableLiveData; import android.support.annotation.NonNull; @@ -7,13 +8,17 @@ import android.support.annotation.NonNull; import com.gh.common.util.ApkActiveUtils; import com.gh.download.DownloadManager; import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.retrofit.BiResponse; import com.gh.gamecenter.retrofit.Response; import com.halo.assistant.HaloApp; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.List; import io.reactivex.Observable; +import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import retrofit2.HttpException; @@ -42,14 +47,16 @@ public abstract class ListViewModel extends Ba mOverLimitSize = mCurLoadParams.getLoadSize() / 2; } + @SuppressLint("CheckResult") protected void loadData() { if (mCurLoadParams == null) initLoadParams(); LoadParams loadParams = mRetryParams != null ? mRetryParams : mCurLoadParams; Observable> listObservable = provideDataObservable(loadParams.getLoadOffset()); + Single> listSingle = provideDataSingle(loadParams.getLoadOffset()); LoadStatus curStatus = mLoadStatusLiveData.getValue(); - if (listObservable == null || curStatus != null && + if ((listObservable == null && listSingle == null) || curStatus != null && curStatus != LoadStatus.INIT_LOADED && curStatus != LoadStatus.LIST_LOADED && curStatus != LoadStatus.INIT) return; @@ -60,43 +67,84 @@ public abstract class ListViewModel extends Ba mLoadStatusLiveData.setValue(LoadStatus.LIST_LOADING); } - listObservable - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Response>() { - @Override - public void onResponse(List response) { - List previousData = mListLiveData.getValue(); - if (previousData == null || mCurLoadParams.getLoadOffset() == LoadParams.DEFAULT_OFFSET || - curStatus == LoadStatus.INIT) { - previousData = new ArrayList<>(); + if (listObservable != null) { + listObservable + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Response>() { + @Override + public void onResponse(List response) { + List previousData = mListLiveData.getValue(); + if (previousData == null || mCurLoadParams.getLoadOffset() == LoadParams.DEFAULT_OFFSET || + curStatus == LoadStatus.INIT) { + previousData = new ArrayList<>(); + } + + // 针对游戏的一些操作(过滤隐藏APK,增加下载数据) + if (response.size() > 0 && response.get(0) instanceof GameEntity) { + for (LD entity : response) { + GameEntity game = (GameEntity) entity; + game.setEntryMap(DownloadManager.getInstance(HaloApp.getInstance() + .getApplication()).getEntryMap(game.getName())); + ApkActiveUtils.filterHideApk(game); + } + } + + previousData.addAll(response); + mListLiveData.postValue(previousData); + loadStatusControl(response.size()); } - // 针对游戏的一些操作(过滤隐藏APK,增加下载数据) - if (response.size() > 0 && response.get(0) instanceof GameEntity) { - for (LD entity : response) { - GameEntity game = (GameEntity) entity; - game.setEntryMap(DownloadManager.getInstance(HaloApp.getInstance() - .getApplication()).getEntryMap(game.getName())); - ApkActiveUtils.filterHideApk(game); + @Override + public void onFailure(HttpException e) { + if (e != null && e.code() == 404) { + loadStatusControl(0); + } else { + loadStatusControl(REQUEST_FAILURE_SIZE); + mLoadExceptionLiveData.postValue(e); + } + } + }); + } else if (listSingle != null) { + listSingle.subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new BiResponse>() { + @Override + public void onFailure(@NotNull Exception exception) { + if (exception instanceof HttpException && ((HttpException) exception).code() == 404) { + loadStatusControl(0); + } else { + loadStatusControl(REQUEST_FAILURE_SIZE); + if (exception instanceof HttpException) { + mLoadExceptionLiveData.postValue((HttpException) exception); + } } } - previousData.addAll(response); - mListLiveData.postValue(previousData); - loadStatusControl(response.size()); - } + @Override + public void onSuccess(List response) { + List previousData = mListLiveData.getValue(); + if (previousData == null || mCurLoadParams.getLoadOffset() == LoadParams.DEFAULT_OFFSET || + curStatus == LoadStatus.INIT) { + previousData = new ArrayList<>(); + } - @Override - public void onFailure(HttpException e) { - if (e != null && e.code() == 404) { - loadStatusControl(0); - } else { - loadStatusControl(REQUEST_FAILURE_SIZE); - mLoadExceptionLiveData.postValue(e); + // 针对游戏的一些操作(过滤隐藏APK,增加下载数据) + if (response.size() > 0 && response.get(0) instanceof GameEntity) { + for (LD entity : response) { + GameEntity game = (GameEntity) entity; + game.setEntryMap(DownloadManager.getInstance(HaloApp.getInstance() + .getApplication()).getEntryMap(game.getName())); + ApkActiveUtils.filterHideApk(game); + } + } + + previousData.addAll(response); + mListLiveData.postValue(previousData); + loadStatusControl(response.size()); } - } - }); + }); + } } protected void loadStatusControl(int size) { @@ -147,6 +195,11 @@ public abstract class ListViewModel extends Ba loadData(); } + @Override + public Single> provideDataSingle(int page) { + return null; + } + protected abstract void mergeResultLiveData(); public MutableLiveData getLoadExceptionLiveData() { diff --git a/app/src/main/java/com/gh/gamecenter/baselist/NormalListViewModel.java b/app/src/main/java/com/gh/gamecenter/baselist/NormalListViewModel.java index 3b5496f713..4b6aa75ef5 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/NormalListViewModel.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/NormalListViewModel.java @@ -8,6 +8,7 @@ import android.support.annotation.NonNull; import java.util.List; import io.reactivex.Observable; +import io.reactivex.Single; /** * Created by khy on 21/03/18. @@ -35,6 +36,11 @@ public class NormalListViewModel extends ListViewModel { return mDataObservable.provideDataObservable(offset); } + @Override + public Single> provideDataSingle(int page) { + return mDataObservable.provideDataSingle(page); + } + public static class Factory extends ViewModelProvider.NewInstanceFactory { @NonNull private final Application mApplication; diff --git a/app/src/main/java/com/gh/gamecenter/baselist/OnDataObservable.java b/app/src/main/java/com/gh/gamecenter/baselist/OnDataObservable.java index 93a847a888..52ce8a75a0 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/OnDataObservable.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/OnDataObservable.java @@ -3,6 +3,7 @@ package com.gh.gamecenter.baselist; import java.util.List; import io.reactivex.Observable; +import io.reactivex.Single; /** @@ -11,4 +12,8 @@ import io.reactivex.Observable; public interface OnDataObservable { Observable> provideDataObservable(int page); + + // 一般的网络请求只有成功或失败两种情况,并不会有 onNext 所以主流是使用 single , + // 譬如 room 的 rxjava 支持就只支持 single 不支持 observable 所以这里增加了个 single 来供那些既兼容网络数据又兼容 room 数据的页面 + Single> provideDataSingle(int page); } diff --git a/app/src/main/java/com/gh/gamecenter/collection/AnswerFragment.java b/app/src/main/java/com/gh/gamecenter/collection/AnswerFragment.java index ca1e243025..c51637c948 100644 --- a/app/src/main/java/com/gh/gamecenter/collection/AnswerFragment.java +++ b/app/src/main/java/com/gh/gamecenter/collection/AnswerFragment.java @@ -2,6 +2,7 @@ package com.gh.gamecenter.collection; import android.view.View; +import com.gh.common.history.HistoryDatabase; import com.gh.common.util.CollectionUtils; import com.gh.common.util.DialogUtils; import com.gh.gamecenter.R; @@ -22,7 +23,7 @@ import org.greenrobot.eventbus.ThreadMode; import java.util.List; -import io.reactivex.Observable; +import io.reactivex.Single; /** * Created by khy on 22/12/17. @@ -31,6 +32,13 @@ import io.reactivex.Observable; public class AnswerFragment extends ListFragment { private AnswerAdapter mAdapter; + private Type mType; + + public static AnswerFragment getInstance(Type type) { + AnswerFragment fragment = new AnswerFragment(); + fragment.mType = type; + return fragment; + } @Override protected ListAdapter provideListAdapter() { @@ -38,8 +46,12 @@ public class AnswerFragment extends ListFragment> provideDataObservable(int page) { - return RetrofitManager.getInstance(getContext()).getApi().getCollectionAnswer(UserManager.getInstance().getUserId(), page); + public Single> 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 @@ -95,4 +107,10 @@ public class AnswerFragment extends ListFragment fragments) { - fragments.add(new AnswerFragment()); + fragments.add(AnswerFragment.getInstance(AnswerFragment.Type.COLLECTION)); fragments.add(new CommunityArticleFragment()); fragments.add(new ToolsFragment()); fragments.add(new ArticleFragment()); diff --git a/app/src/main/java/com/gh/gamecenter/history/HistoryActivity.kt b/app/src/main/java/com/gh/gamecenter/history/HistoryActivity.kt new file mode 100644 index 0000000000..ba2b90d0b6 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/history/HistoryActivity.kt @@ -0,0 +1,20 @@ +package com.gh.gamecenter.history + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.gh.common.util.EntranceUtils +import com.gh.gamecenter.NormalActivity + +class HistoryActivity: NormalActivity() { + + companion object { + @JvmStatic + fun getHistoryIntent(context: Context, entrance: String): Intent { + val bundle = Bundle() + bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance) + return NormalActivity.getTargetIntent(context, HistoryActivity::class.java, HistoryWrapperFragment::class.java, bundle) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/history/HistoryWrapperFragment.kt b/app/src/main/java/com/gh/gamecenter/history/HistoryWrapperFragment.kt new file mode 100644 index 0000000000..05153a9382 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/history/HistoryWrapperFragment.kt @@ -0,0 +1,47 @@ +package com.gh.gamecenter.history + +import android.os.Bundle +import android.support.v4.app.Fragment +import com.gh.base.fragment.BaseFragment_TabLayout +import com.gh.gamecenter.R +import com.gh.gamecenter.collection.* + +class HistoryWrapperFragment: BaseFragment_TabLayout() { + + fun newInstance(checkedIndex: Int): CollectionWrapperFragment { + val fragment = CollectionWrapperFragment() + val args = Bundle(1) + args.putInt(BaseFragment_TabLayout.PAGE_INDEX, checkedIndex) + fragment.arguments = args + return fragment + } + + override fun initTabTitleList(tabTitleList: MutableList) { + tabTitleList.add(getString(R.string.answer)) + tabTitleList.add(getString(R.string.collection_article)) + tabTitleList.add(getString(R.string.collection_info)) + tabTitleList.add(getString(R.string.collection_toolkit)) + } + + override fun initFragmentList(fragments: MutableList) { + fragments.add(AnswerFragment.getInstance(AnswerFragment.Type.HISTORY)) + fragments.add(CommunityArticleFragment()) + fragments.add(ArticleFragment()) + fragments.add(ToolsFragment()) + for (fragment in mFragmentsList) { + fragment.arguments = arguments + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setNavigationTitle("浏览记录") + } + + companion object { + const val INDEX_ANSWER = 0 + const val INDEX_ARTICLE = 1 + const val INDEX_NEWS = 2 + const val INDEX_GAME = 3 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java index ae165f9c37..98f8e45619 100644 --- a/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java +++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java @@ -48,6 +48,7 @@ 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.history.HistoryActivity; import com.gh.gamecenter.manager.UserManager; import com.gh.gamecenter.message.MessageUnreadRepository; import com.gh.gamecenter.message.MessageUnreadViewModel; @@ -293,8 +294,8 @@ public class PersonalFragment extends BaseFragment implements Observer? = null private val mAnswersImgs: ArrayList? = arrayListOf() @@ -146,9 +148,10 @@ class AnswerDetailFragment : NormalFragment() { private var mElapsedHelper: TimeElapsedHelper? = null private var mDetailEntity: AnswerDetailEntity? = null private var mCollectMenuItem: MenuItem? = null - private lateinit var mViewModel: AnswerDetailViewModel private lateinit var mBinding: FragmentAnswerDetailBinding + private lateinit var mViewModel: AnswerDetailViewModel + private var mSpecialColumn: SpecialColumn? = null private var mRefreshHeader: AnswerDetailRefreshHeader? = null @@ -178,6 +181,8 @@ class AnswerDetailFragment : NormalFragment() { mRichEditor.setInputEnabled(false) mRichEditor.setPadding(20, 15, 20, 15) + + // TODO 应该只对显示在屏幕上的 fragment 计时 mElapsedHelper = TimeElapsedHelper(this) initDrag() @@ -195,8 +200,6 @@ class AnswerDetailFragment : NormalFragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) setNavigationTitle(getString(R.string.answer_detail_title)) - (requireActivity() as BaseToolBarActivity).clearMenu() - initMenu(R.menu.menu_answer) } override fun onStart() { @@ -215,6 +218,17 @@ class AnswerDetailFragment : NormalFragment() { } } + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + super.setUserVisibleHint(isVisibleToUser) + mIsVisibleToUser = isVisibleToUser + if (!isVisibleToUser && isResumed) { + mElapsedHelper?.pauseCounting() + updateMenu() + } else if (isVisibleToUser && isResumed) { + mElapsedHelper?.resumeCounting() + } + } + override fun onDestroyView() { super.onDestroyView() if (mDetailEntity != null) { @@ -269,13 +283,14 @@ class AnswerDetailFragment : NormalFragment() { mContainerViewModel.appendAnswer(nextAnswerId) } - updateDragAbility() + updateAnswerStatus() updateDragHintAndListener() - GdtHelper.logAction(ActionType.PAGE_VIEW, GdtHelper.CONTENT_TYPE, "ANSWER", GdtHelper.CONTENT_ID, mAnswerId) - mBinding.detail = mDetailEntity updateView() + updateMenu() + + GdtHelper.logAction(ActionType.PAGE_VIEW, GdtHelper.CONTENT_TYPE, "ANSWER", GdtHelper.CONTENT_ID, mAnswerId) // 没点赞过,作者不是自己,正文长度不少于20个字。 开启停留一定时长(字数/10 + 5)秒)后的动画 if (!mDetailEntity!!.me.isAnswerOwn && !mDetailEntity!!.me.isAnswerVoted) { @@ -318,7 +333,7 @@ class AnswerDetailFragment : NormalFragment() { mBottomContainer.visibility = View.GONE } - if (activity is NormalActivity) { + if (activity is NormalActivity && mIsVisibleToUser) { val menu = (activity as NormalActivity).menu if (menu != null) { for (i in 0 until menu.size()) { @@ -432,6 +447,19 @@ class AnswerDetailFragment : NormalFragment() { } } + // 更新回答状态 + private fun updateAnswerStatus() { + mAnswerStatus = if (!TextUtils.isEmpty(mDetailEntity!!.me.myAnswerId)) { + if (mDetailEntity!!.me.isAnswerOwn) { + ANSWERED_MY_ANSWER + } else { + ANSWERED_NOT_MY_ANSWER + } + } else { + NOT_ANSWERED_YET + } + } + private fun toggleComment(enable: Boolean) { if (enable) { mAnswerCommentCountTv.text = String.format("%d 评论", mDetailEntity!!.commentCount) @@ -453,11 +481,11 @@ class AnswerDetailFragment : NormalFragment() { mRefreshLayout.setEnableAutoLoadMore(false) updateDragHintAndListener() - - updateDragAbility() } private fun updateDragHintAndListener() { + showDragHintDialog() + if (mContainerViewModel.answerIdList.first() == mAnswerId) { mRefreshHeader?.REFRESH_HEADER_PULLING = "不能向上翻页了" mRefreshHeader?.REFRESH_HEADER_RELEASE = "不能向上翻页了" @@ -477,8 +505,9 @@ class AnswerDetailFragment : NormalFragment() { if (UserManager.getInstance().isLoggedIn && mDetailEntity != null && mAnswerStatus == NOT_ANSWERED_YET) { - mRefreshFooter?.REFRESH_FOOTER_PULLING = "我来回答" - mRefreshFooter?.REFRESH_FOOTER_RELEASE = "我来回答" + mRefreshFooter?.REFRESH_FOOTER_PULLING = "没有更多内容了,上拉我来回答" + mRefreshFooter?.REFRESH_FOOTER_RELEASE = "没有更多内容了,松开我来回答" + mRefreshFooter?.restoreArrow() mRefreshLayout.setOnLoadMoreListener { mRefreshLayout.finishLoadMore(0) val question = mDetailEntity!!.question @@ -512,10 +541,13 @@ class AnswerDetailFragment : NormalFragment() { mSpecialColumn) } + HistoryHelper.insertAnswerEntity(mDetailEntity!!) + mElapsedHelper?.resetCounting() } // 开启超时统计(显示点赞动画) + // TODO 避免内存泄漏 private fun startTimeElapsedCount(timeout: Int) { mElapsedHelper?.timeout = timeout mElapsedHelper?.timeoutCallback = object : TimeoutCallback { @@ -609,7 +641,7 @@ class AnswerDetailFragment : NormalFragment() { R.id.menu_collect -> { if (mDetailEntity == null) return - CheckLoginUtils.checkLogin(context, "回答详情-收藏") { + ifLogin("回答详情-收藏") { if (!mDetailEntity!!.me.isAnswerFavorite) { CollectionUtils.postCollection(context!!, mAnswerId!!, CollectionUtils.CollectionType.answer, object : CollectionUtils.OnCollectionListener { override fun onSuccess() { @@ -765,7 +797,7 @@ class AnswerDetailFragment : NormalFragment() { startActivity(QuestionsDetailActivity.getIntent(context, mDetailEntity!!.question.id, mEntrance, "回答详情")) } - R.id.answer_detail_like_container -> CheckLoginUtils.checkLogin(context, "回答详情-赞同") { + R.id.answer_detail_like_container -> ifLogin("回答详情-赞同") { if (mDetailEntity != null && !mDetailEntity!!.me.isAnswerVoted) { mViewModel.postVote(mAnswerId!!) @@ -805,7 +837,7 @@ class AnswerDetailFragment : NormalFragment() { ANSWERED_NOT_MY_ANSWER -> { startActivityForResult(AnswerDetailActivity.getIntent(context, mDetailEntity!!.me.myAnswerId, mEntrance, "答案详情"), ANSWER_PATCH_REQUEST) } - NOT_ANSWERED_YET -> CheckLoginUtils.checkLogin(context, "回答详情-[我来回答]") { + NOT_ANSWERED_YET -> ifLogin("回答详情-[我来回答]") { val question = mDetailEntity!!.question startActivity(AnswerEditActivity.getIntent(context!!, question.id, question.title, true, question.communityName)) } @@ -817,7 +849,7 @@ class AnswerDetailFragment : NormalFragment() { R.id.answer_detail_username -> PersonalHomeActivity.startTargetActivity(context!!, mDetailEntity!!.user.id, mEntrance, "回答详情") R.id.answer_detail_follow -> { - CheckLoginUtils.checkLogin(context, "回答详情-[关注]用户") { + ifLogin("回答详情-[关注]用户") { if (mBinding.answerDetailFollow.text == "关注") { mViewModel.follow(mDetailEntity!!.user.id!!) } @@ -861,14 +893,6 @@ class AnswerDetailFragment : NormalFragment() { @SuppressLint("DefaultLocale") private fun updateView() { - mCollectMenuItem = getItemMenu(R.id.menu_collect) - - if (mDetailEntity!!.me.isAnswerFavorite) { - mCollectMenuItem!!.setIcon(R.drawable.menu_ic_collect_select) - } else { - mCollectMenuItem!!.setIcon(R.drawable.menu_ic_collect_unselect) - } - val user = mDetailEntity?.user if (user != null) { ImageUtils.displayIcon(mUsericon, user.icon) @@ -909,23 +933,22 @@ class AnswerDetailFragment : NormalFragment() { } // 是否已回答 - if (!TextUtils.isEmpty(mDetailEntity!!.me.myAnswerId)) { - if (mDetailEntity!!.me.isAnswerOwn) { - mAnswerStatus = ANSWERED_MY_ANSWER + when (mAnswerStatus) { + ANSWERED_MY_ANSWER -> { mAnswerStatusTv.text = "编辑回答" mAnswerStatusTv.setTextColor(resources.getColor(R.color.title)) mAnswerStatusIv.setImageResource(R.drawable.questionsdetail_myanswer_icon) - } else { - mAnswerStatus = ANSWERED_NOT_MY_ANSWER + } + ANSWERED_NOT_MY_ANSWER -> { mAnswerStatusTv.text = "我的回答" mAnswerStatusTv.setTextColor(resources.getColor(R.color.theme)) mAnswerStatusIv.setImageResource(R.drawable.ic_answer_detail_edit_full) } - } else { - mAnswerStatus = NOT_ANSWERED_YET - mAnswerStatusTv.text = "我来回答" - mAnswerStatusTv.setTextColor(resources.getColor(R.color.theme)) - mAnswerStatusIv.setImageResource(R.drawable.ic_answer_detail_edit_empty) + NOT_ANSWERED_YET -> { + mAnswerStatusTv.text = "我来回答" + mAnswerStatusTv.setTextColor(resources.getColor(R.color.theme)) + mAnswerStatusIv.setImageResource(R.drawable.ic_answer_detail_edit_empty) + } } if (mDetailEntity!!.publishTime == mDetailEntity!!.updateTime) { @@ -983,6 +1006,28 @@ class AnswerDetailFragment : NormalFragment() { updateVote() } + private fun updateMenu() { + if (isFragmentVisible()) { +// (requireActivity() as BaseToolBarActivity).clearMenu() + + initMenu(R.menu.menu_answer) + + mCollectMenuItem = getItemMenu(R.id.menu_collect) + + mDetailEntity?.let { + if (it.me.isAnswerFavorite) { + mCollectMenuItem?.setIcon(R.drawable.menu_ic_collect_select) + } else { + mCollectMenuItem?.setIcon(R.drawable.menu_ic_collect_unselect) + } + } + } + } + + private fun isFragmentVisible(): Boolean { + return isResumed && mIsVisibleToUser + } + private fun updateFollowBtn(isFollowed: Boolean) { if (isFollowed) { if (mBinding.answerDetailFollow.visibility == View.GONE) return @@ -1022,14 +1067,7 @@ class AnswerDetailFragment : NormalFragment() { } } - /** - * 更新上下可拖动切换答案的能力 - */ - private fun updateDragAbility() { - showHintDialog() - } - - private fun showHintDialog() { + private fun showDragHintDialog() { val hasShownDragHint = SPUtils.getBoolean(SHOWN_DRAG_HINT, false) if (hasShownDragHint) { return @@ -1110,11 +1148,6 @@ class AnswerDetailFragment : NormalFragment() { } } - interface CommentListener { - fun onCountChange(count: Int) - fun onCommentDraftChange(draft: String) - } - // 登录事件 @Subscribe(threadMode = ThreadMode.MAIN) fun onEventMainThread(reuse: EBReuse) { @@ -1123,6 +1156,11 @@ class AnswerDetailFragment : NormalFragment() { } } + interface CommentListener { + fun onCountChange(count: Int) + fun onCommentDraftChange(draft: String) + } + companion object { private const val ANSWER_STATUS_UNKNOWN = 0 private const val ANSWERED_MY_ANSWER = 1 diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailRefreshFooter.java b/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailRefreshFooter.java index fbff3efc47..0e7175bbe2 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailRefreshFooter.java +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailRefreshFooter.java @@ -145,6 +145,12 @@ public class AnswerDetailRefreshFooter extends InternalClassics> + +} diff --git a/app/src/main/res/layout/fragment_personal.xml b/app/src/main/res/layout/fragment_personal.xml index 3e9e7d520e..8e5e2c396c 100644 --- a/app/src/main/res/layout/fragment_personal.xml +++ b/app/src/main/res/layout/fragment_personal.xml @@ -334,9 +334,8 @@ - @@ -394,7 +393,7 @@ + + + + + + + + + 这里还没有东西哦 推荐关注 关注 + 浏览记录 分享 礼包中心 反馈