diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a93d3af35e..47b6c37bc0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -615,6 +615,10 @@ android:name=".personal.NewPersonalActivity" android:screenOrientation="portrait" /> + + diff --git a/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt b/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt index 5daca02c94..fc42fb695c 100644 --- a/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt +++ b/app/src/main/java/com/gh/common/simulator/SimulatorDownloadManager.kt @@ -118,7 +118,7 @@ class SimulatorDownloadManager private constructor() { key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗", logShowEvent = true ) - DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, Gravity.LEFT, { + DialogUtils.showNewAlertDialog(context, title, message, negativeText, positiveText, trackableEntity, Gravity.LEFT, false, { if (shouldShowUpdate && isInstalled) { cancelCallback?.invoke() MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说") diff --git a/app/src/main/java/com/gh/common/util/CommentUtils.java b/app/src/main/java/com/gh/common/util/CommentUtils.java index 7e17331a91..5471cfe04b 100644 --- a/app/src/main/java/com/gh/common/util/CommentUtils.java +++ b/app/src/main/java/com/gh/common/util/CommentUtils.java @@ -334,15 +334,16 @@ public class CommentUtils { }); }); } + public static void voteVideoComment(final Context context, - String answerId, - String articleId, - String articleCommunityId, - String videoId, - final CommentEntity commentEntity, - final TextView commentLikeCountTv, - final ImageView commentLikeIv, - final OnVoteListener listener) { + String answerId, + String articleId, + String articleCommunityId, + String videoId, + final CommentEntity commentEntity, + final TextView commentLikeCountTv, + final ImageView commentLikeIv, + final OnVoteListener listener) { String entrance = "视频流-评论-点赞"; CheckLoginUtils.checkLogin(context, entrance, () -> { @@ -389,10 +390,10 @@ public class CommentUtils { } public static void unVoteVideoComment(final Context context, - String videoId, - final CommentEntity commentEntity, - final TextView commentLikeCountTv, - final ImageView commentLikeIv) { + String videoId, + final CommentEntity commentEntity, + final TextView commentLikeCountTv, + final ImageView commentLikeIv) { String entrance = "视频流-评论-取消点赞"; CheckLoginUtils.checkLogin(context, entrance, () -> { RetrofitManager.getInstance(context).getApi() @@ -434,10 +435,10 @@ public class CommentUtils { holder.commentLikeIv.setImageResource(R.drawable.comment_vote_unselect); if (userDataEntity == null || !userDataEntity.isCommentOwner()) { - holder.replyLine.setVisibility(View.VISIBLE); + if (holder.replyLine != null) holder.replyLine.setVisibility(View.VISIBLE); holder.commentReply.setVisibility(View.VISIBLE); } else { - holder.replyLine.setVisibility(View.GONE); + if (holder.replyLine != null) holder.replyLine.setVisibility(View.GONE); holder.commentReply.setVisibility(View.GONE); } diff --git a/app/src/main/java/com/gh/common/util/DialogUtils.java b/app/src/main/java/com/gh/common/util/DialogUtils.java index 43fcfcb809..dc0d50621a 100644 --- a/app/src/main/java/com/gh/common/util/DialogUtils.java +++ b/app/src/main/java/com/gh/common/util/DialogUtils.java @@ -350,7 +350,7 @@ public class DialogUtils { * @param cmListener 确认按钮监听 */ public static Dialog showNewAlertDialog(Context context, String title, CharSequence message - , String negative, String positive, TrackableEntity trackableEntity, int gravity, final CancelListener clListener, final ConfirmListener cmListener) { + , String negative, String positive, TrackableEntity trackableEntity, int gravity, boolean shouldShowCloseBtn, final CancelListener clListener, final ConfirmListener cmListener) { context = checkDialogContext(context); final Dialog dialog; if (trackableEntity != null) { @@ -373,6 +373,7 @@ public class DialogUtils { TextView cancelBtn = contentView.findViewById(R.id.cancel); TextView confirmBtn = contentView.findViewById(R.id.confirm); View middleLine = contentView.findViewById(R.id.middle_line); + View closeIv = contentView.findViewById(R.id.closeIv); titleTv.setGravity(gravity); contentTv.setGravity(gravity); @@ -389,6 +390,8 @@ public class DialogUtils { confirmBtn.setVisibility(View.GONE); middleLine.setVisibility(View.GONE); } + closeIv.setVisibility(shouldShowCloseBtn ? View.VISIBLE : View.GONE); + closeIv.setOnClickListener(v -> dialog.dismiss()); cancelBtn.setOnClickListener(v -> { if (clListener != null) clListener.onCancel(); @@ -413,7 +416,12 @@ public class DialogUtils { public static Dialog showNewAlertDialog(Context context, String title, CharSequence message , String negative, String positive, final CancelListener clListener, final ConfirmListener cmListener) { - return showNewAlertDialog(context, title, message, negative, positive, null, Gravity.LEFT, clListener, cmListener); + return showNewAlertDialog(context, title, message, negative, positive, null, Gravity.LEFT, false, clListener, cmListener); + } + + public static Dialog showNewAlertDialog(Context context, String title, CharSequence message + , String negative, String positive, int gravity, boolean shouldShowCloseBtn, final CancelListener clListener, final ConfirmListener cmListener) { + return showNewAlertDialog(context, title, message, negative, positive, null, gravity, shouldShowCloseBtn, clListener, cmListener); } /** @@ -1951,8 +1959,8 @@ public class DialogUtils { final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent); View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_energy, null); - ((TextView)contentView.findViewById(R.id.userName)).setText("\"" + userName + "\""); - ((TextView)contentView.findViewById(R.id.energy)).setText(energy + ""); + ((TextView) contentView.findViewById(R.id.userName)).setText("\"" + userName + "\""); + ((TextView) contentView.findViewById(R.id.energy)).setText(energy + ""); contentView.findViewById(R.id.dialog_positive).setOnClickListener(v -> { dialog.dismiss(); diff --git a/app/src/main/java/com/gh/common/util/ShareUtils.java b/app/src/main/java/com/gh/common/util/ShareUtils.java index 98de9e0aad..6d32b49d53 100644 --- a/app/src/main/java/com/gh/common/util/ShareUtils.java +++ b/app/src/main/java/com/gh/common/util/ShareUtils.java @@ -319,7 +319,7 @@ public class ShareUtils { }); } - public void shareGameDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) { + public void shareParamsDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) { if (activity.isFinishing()) return; this.mActivity = new WeakReference<>(activity); this.shareIcon = icon; @@ -654,6 +654,10 @@ public class ShareUtils { } } + public String getTitle() { + return mTitle; + } + private class ShareRecyclerViewAdapter extends RecyclerView.Adapter { private OnItemClickListener listener; diff --git a/app/src/main/java/com/gh/common/util/UploadImageUtils.kt b/app/src/main/java/com/gh/common/util/UploadImageUtils.kt index 6672758ea4..aeb0934522 100644 --- a/app/src/main/java/com/gh/common/util/UploadImageUtils.kt +++ b/app/src/main/java/com/gh/common/util/UploadImageUtils.kt @@ -116,6 +116,7 @@ object UploadImageUtils { Observable.create(ObservableOnSubscribe> { val compressList = compressImageList(imgs, compressGif) + listener.onCompressSuccess(compressList.map { file -> file.absolutePath }.toList()) var listTotal = 0L // 总大小 var listProgress = 0L // 已上传的大小 for (img in compressList) { @@ -274,7 +275,7 @@ object UploadImageUtils { } // 防止GIF图片文件后缀不是GIF,这个FileName只是告诉服务端后缀格式,没有其他用处 - fun getFileName(file: File): String { + fun getFileName(file: File): String { val options = BitmapFactory.Options() options.inJustDecodeBounds = true BitmapFactory.decodeFile(file.absolutePath, options) @@ -292,6 +293,7 @@ object UploadImageUtils { interface OnUploadImageListListener { fun onSuccess(imageUrl: LinkedHashMap, errorMap: Map) // key:sourceImage value:compressImage + fun onCompressSuccess(imageUrls: List) {} fun onError(errorMap: Map) // 全部上传失败时回调 fun onProgress(total: Long, progress: Long) } diff --git a/app/src/main/java/com/gh/common/view/RichEditor.java b/app/src/main/java/com/gh/common/view/RichEditor.java index b9236033f6..c48ec0265d 100644 --- a/app/src/main/java/com/gh/common/view/RichEditor.java +++ b/app/src/main/java/com/gh/common/view/RichEditor.java @@ -24,6 +24,7 @@ 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.PackageUtils; import com.gh.common.util.RichEditorUtils; import com.gh.common.util.SPUtils; import com.gh.gamecenter.BuildConfig; @@ -321,6 +322,10 @@ public class RichEditor extends WebView { exec("javascript:RE.setBaseFontSize('" + px + "px');"); } + public boolean hasPlaceholderImage() { + return getHtml().contains("placeholder-image-container"); + } + @Override public void setPadding(int left, int top, int right, int bottom) { super.setPadding(left, top, right, bottom); @@ -444,6 +449,15 @@ public class RichEditor extends WebView { exec("javascript:RE.setTextColor('" + hex + "');"); } + public void insertPlaceholderImage(String id) { + exec("javascript:RE.prepareInsert();"); + exec("javascript:RE.insertPlaceholderImage('" + id + "');"); + } + + public void replacePlaceholderImage(String list) { + exec("javascript:RE.replacePlaceholderImage('" + list + "');"); + } + public void removeFormat() { exec("javascript:RE.removeFormat();"); } @@ -649,6 +663,16 @@ public class RichEditor extends WebView { return DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()); } + @JavascriptInterface + public String getAppVersion() { + return BuildConfig.VERSION_NAME; + } + + @JavascriptInterface + public int getAppVersionCode() { + return PackageUtils.getVersionCode(); + } + /** * 显示toast * @@ -737,7 +761,7 @@ public class RichEditor extends WebView { public void invalidate() { super.invalidate(); - if (mInitialLayoutCallback != null &&getHeight() > 0) { + if (mInitialLayoutCallback != null && getHeight() > 0) { // 仅初次 layout 完成会有回调 mInitialLayoutCallback.onCallback(); mInitialLayoutCallback = null; diff --git a/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java b/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java index 2ba84ab6cb..276dba7368 100644 --- a/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java +++ b/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java @@ -967,6 +967,11 @@ public class SuggestionActivity extends ToolBarActivity implements OnRequestCall private void postPic(final String email) { UploadImageUtils.INSTANCE.compressAndUploadImageList(UploadImageUtils.UploadType.suggestion , mAdapter.getFileList(), false, new UploadImageUtils.OnUploadImageListListener() { + @Override + public void onCompressSuccess(@NotNull List imageUrls) { + + } + @Override public void onProgress(long total, long progress) { int percent = (int) (100 * (progress / (float) total)); diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java index 68cae4c6e0..6cc6cf9faa 100644 --- a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/CommentViewHolder.java @@ -9,6 +9,7 @@ import com.facebook.drawee.view.SimpleDraweeView; import com.gh.base.BaseRecyclerViewHolder; import com.gh.gamecenter.R; +import androidx.annotation.Nullable; import butterknife.BindView; /** @@ -33,7 +34,7 @@ public class CommentViewHolder extends BaseRecyclerViewHolder { @BindView(R.id.comment_user_name) public TextView commentUserNameTv; @BindView(R.id.comment_author) - public TextView commentAuthorTv; + public View commentAuthorTv; @BindView(R.id.comment_badge) public View commentBadge; @@ -54,6 +55,7 @@ public class CommentViewHolder extends BaseRecyclerViewHolder { public View commentMore; @BindView(R.id.comment_reply) public View commentReply; + @Nullable @BindView(R.id.reply_dividing_line) public View replyLine; diff --git a/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt index d741082ecd..0afe7ab9fa 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/MenuItemEntity.kt @@ -3,5 +3,6 @@ package com.gh.gamecenter.entity data class MenuItemEntity( val text: String = "", val normalIcon: Int = 0, - val disableIcon: Int = 0 + val disableIcon: Int = 0, + val isEnable:Boolean = true ) \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt b/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt index f413a275ab..8ce88b45c4 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/detail/ForumArticleAskListFragment.kt @@ -31,6 +31,7 @@ class ForumArticleAskListFragment : ListFragment(R.id.reuse_ll_loading) - private val mReuseNoConnection by bindView(R.id.reuse_no_connection) - private val mReuseNoData by bindView(R.id.reuse_none_data) - private val mReuseNoDataTv by bindView(R.id.reuse_tv_none_data) - private var mAllForumArticleAskListFragment: ForumArticleAskListFragment? = null private var mEssenceForumArticleAskListFragment: ForumArticleAskListFragment? = null private var mAskForumArticleAskListFragment: ForumArticleAskListFragment? = null @@ -96,11 +90,11 @@ class ForumDetailFragment : BaseLazyTabFragment() { val factory = ForumDetailViewModel.Factory(bbsId) mViewModel = viewModelProvider(factory) mViewModel?.forumDetail?.observe(this, Observer { - mReuseLoading.visibility = View.GONE + mBinding.reuseLoading.reuseLlLoading.visibility = View.GONE if (it.status == Status.SUCCESS) { mBinding.communityEdit.visibility = View.VISIBLE mBinding.forumContainer.visibility = View.VISIBLE - mReuseNoConnection.visibility = View.GONE + mBinding.reuseNoConnection.reuseNoConnection.visibility = View.GONE if (it.data != null) { mForumDetail = it.data initUI() @@ -109,16 +103,20 @@ class ForumDetailFragment : BaseLazyTabFragment() { mBinding.communityEdit.visibility = View.GONE mBinding.forumContainer.visibility = View.GONE if (it.exception != null && it.exception.code() == 404) { - mReuseNoDataTv.text = "页面为空" - mReuseNoData.visibility = View.VISIBLE - mReuseNoConnection.visibility = View.GONE + mBinding.reuseNoneData.reuseTvNoneData.text = "页面为空" + mBinding.reuseNoneData.reuseNoneData.visibility = View.VISIBLE + mBinding.reuseNoConnection.reuseNoConnection.visibility = View.GONE ToastUtils.showToast("内容可能已被删除") } else { - mReuseNoData.visibility = View.GONE - mReuseNoConnection.visibility = View.VISIBLE + mBinding.reuseNoneData.reuseNoneData.visibility = View.GONE + mBinding.reuseNoConnection.reuseNoConnection.visibility = View.VISIBLE } } }) + mBinding.refreshLayout.setProgressViewOffset(false, 0, DisplayUtils.dip2px(40f) + DisplayUtils.getStatusBarHeight(requireContext().getResources())); + mBinding.appbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset -> + mBinding.refreshLayout.isEnabled = abs(verticalOffset) <= 2 + }) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -163,9 +161,24 @@ class ForumDetailFragment : BaseLazyTabFragment() { MtaHelper.onEvent("论坛详情", getKeyValue(mLastPosition), getKeyValue(it)) mLastPosition = it } + mBinding.refreshLayout.setOnRefreshListener { + if (mAllForumArticleAskListFragment != null && mViewPager.currentItem == 0) { + mAllForumArticleAskListFragment?.refresh() + } + if (mEssenceForumArticleAskListFragment != null && mViewPager.currentItem == 1) { + mEssenceForumArticleAskListFragment?.refresh() + } + if (mAskForumArticleAskListFragment != null && mViewPager.currentItem == 2) { + mAskForumArticleAskListFragment?.refresh() + } + } LogUtils.uploadAccessToBbs(bbsId, "论坛详情") } + fun hideRefreshingLayout() { + mBinding.refreshLayout.isRefreshing = false + } + private fun getKeyValue(position: Int): String { return when (position) { 0 -> "全部Tab" @@ -242,7 +255,7 @@ class ForumDetailFragment : BaseLazyTabFragment() { ?: "", mEntrance, "论坛详情")) } R.id.reuse_no_connection -> { - mReuseLoading.visibility = View.VISIBLE + mBinding.reuseLoading.reuseLlLoading.visibility = View.VISIBLE mViewModel?.getForumDetail() } R.id.gameZoneTv -> { diff --git a/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt b/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt index f5f9a4ea8b..6949f5edc5 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/follow/ForumMyFollowAdapter.kt @@ -69,7 +69,7 @@ class ForumMyFollowAdapter(context: Context, val mViewModel: ForumMyFollowViewMo popupWindow.dismiss() when (text) { "取消关注" -> { - DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, false, {}, { MtaHelper.onEvent("论坛首页", "我关注的论坛", "取消关注") mViewModel.unFollowForum(entity.id) { EventBus.getDefault().post(EBForumFollowChange(entity, false)) diff --git a/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt b/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt index cb175c8904..84e44ab883 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/select/ForumAdapter.kt @@ -4,20 +4,21 @@ import android.content.Context import android.view.Gravity import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.fragment.app.DialogFragment import androidx.recyclerview.widget.RecyclerView import com.gh.base.BaseRecyclerViewHolder import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.databinding.ForumItemBinding +import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.ForumEntity import com.gh.gamecenter.eventbus.EBForumFollowChange import com.gh.gamecenter.forum.detail.ForumDetailActivity -import com.gh.gamecenter.forum.home.ForumVisitDao import com.gh.gamecenter.qa.entity.CommunitySelectEntity import com.lightgame.adapter.BaseRecyclerAdapter import org.greenrobot.eventbus.EventBus -class ForumAdapter(context: Context, val mViewModel: ForumSelectViewModel?) : BaseRecyclerAdapter(context) { +class ForumAdapter(val context: Context, val mViewModel: ForumSelectViewModel?, val isSelectForum: Boolean = false, val onSelectCallback: ((entity: CommunityEntity) -> Unit)? = null) : BaseRecyclerAdapter(context) { val datas: ArrayList = arrayListOf() @@ -40,15 +41,20 @@ class ForumAdapter(context: Context, val mViewModel: ForumSelectViewModel?) : Ba val forumEntity = datas[position] holder.binding.entity = forumEntity holder.binding.forumIcon.displayGameIcon(forumEntity.game.getIcon(), forumEntity.game.iconSubscript) + holder.binding.followTv.goneIf(isSelectForum) holder.itemView.setOnClickListener { - MtaHelper.onEvent("论坛首页", "选择论坛", forumEntity.name) - mContext.startActivity(ForumDetailActivity.getIntent(mContext, forumEntity.id, "论坛-选择论坛")) + if (isSelectForum) { + onSelectCallback?.invoke(CommunityEntity(forumEntity.id, forumEntity.name, icon = forumEntity.game.getIcon(), iconSubscript = forumEntity.game.iconSubscript)) + } else { + MtaHelper.onEvent("论坛首页", "选择论坛", forumEntity.name) + mContext.startActivity(ForumDetailActivity.getIntent(mContext, forumEntity.id, "论坛-选择论坛")) + } } holder.binding.followTv.setOnClickListener { mContext.ifLogin("论坛-选择论坛") { debounceActionWithInterval(it.id) { if (forumEntity.isFollow) { - DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(mContext, "提示", "确定取消关注", "暂不", "确定", null, Gravity.CENTER, false, {}, { mViewModel?.unFollowForum(forumEntity.id) { MtaHelper.onEvent("论坛首页", "选择论坛", "关注") forumEntity.isFollow = false diff --git a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt index d3180a877d..920fbdad81 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectFragment.kt @@ -8,6 +8,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.gh.common.util.viewModelProvider import com.gh.gamecenter.R +import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.ForumCategoryEntity import com.gh.gamecenter.eventbus.EBForumFollowChange import com.gh.gamecenter.mvvm.Status @@ -28,6 +29,7 @@ class ForumSelectFragment : NormalFragment() { private var mViewModel: ForumSelectViewModel? = null private var selectCategory: ForumCategoryEntity? = null + var onSelectCallback: ((entity: CommunityEntity) -> Unit)? = null override fun getLayoutId(): Int = R.layout.fragment_forum_select @@ -38,10 +40,12 @@ class ForumSelectFragment : NormalFragment() { mLoadingView.visibility = View.GONE if (it.status == Status.SUCCESS) { if (it.data != null) { - mForumCategoryAdapter?.setListData(it.data) + val data = it.data as ArrayList + if (onSelectCallback != null) data.add(0, ForumCategoryEntity("", "我的关注")) + mForumCategoryAdapter?.setListData(data) if (it.data.isNotEmpty()) { selectCategory = it.data[0] - mViewModel?.getForumByCategoryId(it.data[0].id) + mViewModel?.getForumList(selectCategory) } } mForumCategoryRv.visibility = View.VISIBLE @@ -81,13 +85,13 @@ class ForumSelectFragment : NormalFragment() { mForumCategoryAdapter = ForumCategoryAdapter(requireContext()) { selectCategory = it mLoadingView.visibility = View.VISIBLE - mViewModel?.getForumByCategoryId(it.id) + mViewModel?.getForumList(it) } adapter = mForumCategoryAdapter } mForumRv.apply { layoutManager = LinearLayoutManager(requireContext()) - mForumAdapter = ForumAdapter(requireContext(), mViewModel) + mForumAdapter = ForumAdapter(requireContext(), mViewModel, onSelectCallback != null, onSelectCallback) adapter = mForumAdapter } @@ -97,7 +101,7 @@ class ForumSelectFragment : NormalFragment() { mViewModel?.getForumCategories() } else { mLoadingView.visibility = View.VISIBLE - mViewModel?.getForumByCategoryId(selectCategory?.id ?: "") + mViewModel?.getForumList(selectCategory) } } } diff --git a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt index 6f96f1ade5..3f0fa9650e 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/select/ForumSelectViewModel.kt @@ -8,6 +8,7 @@ import com.gh.common.util.UrlFilterUtils import com.gh.gamecenter.entity.ForumCategoryEntity import com.gh.gamecenter.entity.ForumEntity import com.gh.gamecenter.entity.LinkEntity +import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.mvvm.Resource import com.gh.gamecenter.qa.entity.CommunitySelectOpenEntity import com.gh.gamecenter.retrofit.BiResponse @@ -44,10 +45,15 @@ class ForumSelectViewModel(application: Application) : AndroidViewModel(applicat }) } - fun getForumByCategoryId(categoryId: String) { - RetrofitManager.getInstance(getApplication()).api - .getForumByCategories(categoryId) - .subscribeOn(Schedulers.io()) + fun getForumList(category: ForumCategoryEntity?) { + val observable = if (category?.name != "我的关注") { + RetrofitManager.getInstance(getApplication()).api + .getForumByCategories(category?.id ?: "") + } else { + RetrofitManager.getInstance(getApplication()).api + .getFollowsForum(UserManager.getInstance().userId) + } + observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Response>() { override fun onResponse(response: List?) { @@ -76,6 +82,7 @@ class ForumSelectViewModel(application: Application) : AndroidViewModel(applicat } }) } + @SuppressLint("CheckResult") fun unFollowForum(bbsId: String, onSuccess: () -> Unit) { RetrofitManager.getInstance(getApplication()).api diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt index 1b268f6cd4..9aea2ccb09 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/dialog/GameDetailMoreDialog.kt @@ -102,7 +102,7 @@ class GameDetailMoreDialog : BaseDialogFragment(), View.OnTouchListener { shareEntrance = ShareUtils.ShareEntrance.plugin } } - shareUtils.shareGameDetail(requireActivity(), url, gameEntity?.icon, gameEntity?.name, + shareUtils.shareParamsDetail(requireActivity(), url, gameEntity?.icon, gameEntity?.name, gameEntity?.brief, shareEntrance, gameEntity?.id ?: "", null) return shareUtils } diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt index bcd276cf8b..5018ba0bac 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/BaseAnswerOrArticleItemViewHolder.kt @@ -53,7 +53,7 @@ open class BaseAnswerOrArticleItemViewHolder(itemView: View) : BaseRecyclerViewH val intent = CommentActivity.getAnswerCommentIntent(itemView.context, entity.id!!, entity.commentCount, - entity.commentCount == 0) + false) itemView.context.startActivity(intent) } diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt index 09a5d388e1..35eb1292c4 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt @@ -4,19 +4,17 @@ import android.annotation.SuppressLint import android.app.Activity import android.app.Dialog import android.content.Intent -import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.text.TextUtils import android.view.Gravity import android.view.LayoutInflater import android.view.MenuItem import android.view.View -import android.view.animation.LinearInterpolator import android.webkit.JavascriptInterface import android.widget.ImageView import android.widget.LinearLayout -import android.widget.PopupWindow import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.databinding.BindingAdapter import androidx.databinding.DataBindingUtil @@ -48,6 +46,7 @@ import com.gh.gamecenter.normal.NormalFragment import com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.comment.CommentActivity +import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog import com.gh.gamecenter.qa.editor.OnLinkClickListener import com.gh.gamecenter.qa.entity.AnswerDetailEntity import com.gh.gamecenter.qa.entity.Questions @@ -151,6 +150,8 @@ class AnswerDetailFragment : NormalFragment() { mBinding.richEditor.setInputEnabled(false) mBinding.richEditor.setPadding(20, 15, 20, 15) + mBinding.bottomController.replyTv.text = "说点什么吧" + mBinding.bottomController.replyTv.setRoundedColorBackground(R.color.text_F5F5F5, 19F) mElapsedHelper = TimeElapsedHelper(this) // 只对显示在屏幕上的 fragment 计时 @@ -231,8 +232,8 @@ class AnswerDetailFragment : NormalFragment() { val count = data.getIntExtra(CommentActivity.COMMENT_COUNT, 0) if (count != 0) { mViewModel.answerDetail?.commentCount = count - mBinding.bottomController.tvCommentCount.text = String.format("评论 %s", NumberUtils.transSimpleCount(mViewModel.answerDetail?.commentCount - ?: 0)) + mBinding.bottomController.bottomCommentTv.text = NumberUtils.transSimpleCount(mViewModel.answerDetail?.commentCount + ?: 0) if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { LogUtils.uploadCommentFromWelcomeDialog() @@ -281,7 +282,7 @@ class AnswerDetailFragment : NormalFragment() { if (e != null && e.code() == 404 && e.response().errorBody()!!.string().isNotEmpty()) { HistoryHelper.deleteAnswerEntity(mAnswerId) - mBinding.bottomController.containerControl.visibility = View.GONE + mBinding.bottomController.root.visibility = View.GONE mNoDataTv.setText(R.string.content_delete_hint) mNoData.visibility = View.VISIBLE mNoConn.visibility = View.GONE @@ -308,7 +309,7 @@ class AnswerDetailFragment : NormalFragment() { } else { mNoConn.visibility = View.VISIBLE mBinding.scrollView.visibility = View.GONE - mBinding.bottomController.containerControl.visibility = View.GONE + mBinding.bottomController.root.visibility = View.GONE mBinding.bottomDividerView.visibility = View.GONE mBinding.bottomShadowView.visibility = View.GONE } @@ -486,25 +487,19 @@ class AnswerDetailFragment : NormalFragment() { mBinding.followTv.visibility = View.GONE } else { mBinding.followTv.isEnabled = true - if (!me.isFollower) { - mBinding.followTv.alpha = 1f - mBinding.followTv.visibility = View.VISIBLE - updateFollowBtn(false) - } else { - mBinding.followTv.visibility = View.GONE - } + updateFollowBtn(me.isFollower) } } private fun toggleComment(enable: Boolean, commentCount: Int) { if (enable) { - mBinding.bottomController.ivComment.setImageResource(R.drawable.community_content_detail_comment_open) - mBinding.bottomController.tvCommentCount.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) - mBinding.bottomController.tvCommentCount.text = String.format("评论 %d", commentCount) + mBinding.bottomController.bottomCommentIv.setImageResource(R.drawable.community_content_detail_comment_open) + mBinding.bottomController.bottomCommentTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) + mBinding.bottomController.bottomCommentTv.text = if (commentCount > 0) commentCount.toString() else "评论" } else { - mBinding.bottomController.ivComment.setImageResource(R.drawable.community_content_detail_comment_close) - mBinding.bottomController.tvCommentCount.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_b3b3b3)) - mBinding.bottomController.tvCommentCount.text = "评论已关闭" + mBinding.bottomController.bottomCommentIv.setImageResource(R.drawable.community_content_detail_comment_close) + mBinding.bottomController.bottomCommentTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_b3b3b3)) + mBinding.bottomController.bottomCommentTv.text = "评论已关闭" } } @@ -609,78 +604,76 @@ class AnswerDetailFragment : NormalFragment() { private fun showMoreItemDialog(answer: AnswerDetailEntity) { if (fragmentIsVisible()) { - val view = LayoutInflater.from(context).inflate(R.layout.menu_answer_detail_more_new, null) - val popupWindow = PopupWindow( - view, - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - popupWindow.apply { - setBackgroundDrawable(ColorDrawable(0)) - isTouchable = true - isFocusable = true - isOutsideTouchable = true - } - view.measure(0, 0) - val viewWidth = view.measuredWidth - popupWindow.showAsDropDown((activity as ToolBarActivity).menu.getItem(2).actionView, -viewWidth - 10, 10) - - val container = view.findViewById(R.id.container) val entities = ArrayList() - entities.add(MenuItemEntity("首页", R.drawable.menu_more_home)) if (answer.user.id != UserManager.getInstance().userId) { - entities.add(MenuItemEntity("投诉", R.drawable.ic_menu_gamedetail_feedback)) + entities.add(MenuItemEntity("投诉", R.drawable.icon_gamedetail_copyright)) } if (answer.me.isModerator) { - entities.add(MenuItemEntity("加精", R.drawable.menu_more_essence_enable, - if (answer.isHighlighted || answer.user.id == UserManager.getInstance().userId) - R.drawable.menu_more_essence_unenable else 0)) - entities.add(MenuItemEntity("折叠", R.drawable.menu_more_fold)) + val isEnable = answer.isHighlighted || answer.user.id == UserManager.getInstance().userId + entities.add(MenuItemEntity("加精", if (isEnable) + R.drawable.icon_more_panel_essence_unenable else R.drawable.icon_more_panel_essence, + isEnable = !isEnable)) + + entities.add(MenuItemEntity("折叠", R.drawable.icon_more_panel_fold)) } if (answer.user.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity(if (answer.commentable) "关闭评论" else "恢复评论", if (answer.commentable) R.drawable.ic_close_comment else R.drawable.ic_open_comment)) + entities.add(MenuItemEntity(if (answer.commentable) "关闭评论" else "恢复评论", if (answer.commentable) R.drawable.icon_more_panel_close_comment_enable + else R.drawable.icon_more_panel_close_comment_unenable)) } if (answer.me.isModerator || answer.user.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("删除", R.drawable.menu_more_delete)) + entities.add(MenuItemEntity("删除", R.drawable.icon_more_panel_delete)) } - entities.forEachIndexed { index, item -> - val menuItem = createMenuItem(index, item) - container.addView(menuItem) - menuItem.setOnClickListener { - popupWindow.dismiss() - when (item.text) { - "首页" -> { - val community = mViewModel.answerDetail?.community - MtaHelper.onEvent("回到首页", "回答详情", community?.name + "+" + StringUtils.combineTwoString(mViewModel.answerDetail?.content, mViewModel.answerDetail?.id)) - DirectUtils.directToCommunity(requireContext(), community) - } - "投诉" -> { - SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", "回答投诉($mAnswerId):") - } - "加精" -> { - addEssenceForum(answer) - } - "折叠" -> { - foldForum(answer) - } - "关闭评论", "恢复评论" -> { - if (mViewModel.answerDetail?.commentable!!) { - DialogUtils.showAlertDialog(requireContext(), "提示", "关闭评论之后,该回答将无法查看和发表评论,确定关闭吗?", - "确定", "取消", { mViewModel.toggleComment(mAnswerId, false) }, null) - } else { - DialogUtils.showAlertDialog(requireContext(), "提示", "确定恢复评论吗?", - "确定", "取消", { mViewModel.toggleComment(mAnswerId, true) }, null) - } - } - "删除" -> { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除回答后,其中的所有回复都将被删除", "取消", "删除", {}, { - mViewModel.doHideThisAnswer(mAnswerId) - }) + val shareIcon: String = if (mAnswersImages!!.size > 0) { + mAnswersImages[0] + } else { + getString(R.string.share_ghzs_logo) + } + var shareSummary = mBinding.richEditor.text + if (TextUtils.isEmpty(shareSummary)) { + shareSummary = getString(R.string.ask_share_default_summary) + } + val shareUrl = if (isPublishEnv()) { + getString(R.string.share_answers_url, mAnswerId) + } else { + getString(R.string.share_answers_url_dev, answer.question.id, mAnswerId) + } + val shareUtils = ShareUtils.getInstance(context) + shareUtils.shareParamsDetail(activity, + shareUrl, + shareIcon, + getString(R.string.ask_share_answers_title, answer.user.name, answer.question.title, answer.vote), + shareSummary, + ShareUtils.ShareEntrance.answerNormal, mAnswerId, null) + MoreFunctionPanelDialog.showMoreDialog(requireActivity() as AppCompatActivity, entities, answer.question.title + ?: "", shareUtils) { + when (it.text) { + "投诉" -> { + SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", "回答投诉($mAnswerId):") + } + "加精" -> { + addEssenceForum(answer) + } + "折叠" -> { + foldForum(answer) + } + "关闭评论", "恢复评论" -> { + if (mViewModel.answerDetail?.commentable!!) { + DialogUtils.showAlertDialog(requireContext(), "提示", "关闭评论之后,该回答将无法查看和发表评论,确定关闭吗?", + "确定", "取消", { mViewModel.toggleComment(mAnswerId, false) }, null) + } else { + DialogUtils.showAlertDialog(requireContext(), "提示", "确定恢复评论吗?", + "确定", "取消", { mViewModel.toggleComment(mAnswerId, true) }, null) } } + "删除" -> { + DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除回答后,其中的所有回复都将被删除", "取消", "删除", {}, { + mViewModel.doHideThisAnswer(mAnswerId) + }) + } } } + } } @@ -731,17 +724,12 @@ class AnswerDetailFragment : NormalFragment() { } @OnClick( - R.id.iv_comment, - R.id.tv_comment_count, - R.id.iv_collect, - R.id.tv_collect, - R.id.iv_share, - R.id.tv_share, - R.id.container_dislike, + R.id.replyTv, + R.id.bottomStarContainer, R.id.reuse_no_connection, R.id.status_tv, + R.id.bottomLikeContainer, R.id.answer_count_container, - R.id.container_like, R.id.follow_tv, R.id.user_icon_iv, R.id.questionsdetail_item_pic1, @@ -758,11 +746,11 @@ class AnswerDetailFragment : NormalFragment() { mViewModel.getAnswerDetail(mAnswerId, mEntrance) } - R.id.iv_share, R.id.tv_share -> { - shareAnswer() - } +// R.id.iv_share, R.id.tv_share -> { +// shareAnswer() +// } - R.id.iv_collect, R.id.tv_collect -> { + R.id.bottomStarContainer -> { ifLogin("回答详情-收藏") { mViewModel.answerDetail?.let { if (!it.me.isAnswerFavorite) { @@ -777,42 +765,32 @@ class AnswerDetailFragment : NormalFragment() { startActivity(QuestionsDetailActivity.getIntent(context, mViewModel.answerDetail!!.question.id, mEntrance, "回答详情")) } - R.id.container_like -> debounceActionWithInterval(R.id.container_like, 1000) { - ifLogin("回答详情-赞同") { - if (mViewModel.answerDetail != null && !mViewModel.answerDetail!!.me.isAnswerVoted) { - mViewModel.like(mAnswerId) + R.id.bottomLikeContainer -> { + debounceActionWithInterval(R.id.container_like, 1000) { + ifLogin("回答详情-赞同") { + if (mViewModel.answerDetail != null && !mViewModel.answerDetail!!.me.isAnswerVoted) { + mViewModel.like(mAnswerId) - if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { - LogUtils.uploadLikeFromWelcomeDialog() - } + if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { + LogUtils.uploadLikeFromWelcomeDialog() + } - DataUtils.onMtaEvent(context, - "答案点赞量_社区加位置", - mViewModel.answerDetail?.community?.name, - mPath) - } else { - mViewModel.cancelLike(mAnswerId) - } - } - } - - R.id.container_dislike -> debounceActionWithInterval(R.id.container_like, 1000) { - ifLogin("回答详情-反对") { - mViewModel.answerDetail?.let { - if (it.me.isAnswerOpposed) { - mViewModel.cancelDislike(mAnswerId) + DataUtils.onMtaEvent(context, + "答案点赞量_社区加位置", + mViewModel.answerDetail?.community?.name, + mPath) } else { - mViewModel.dislike(mAnswerId) + mViewModel.cancelLike(mAnswerId) } } } } - R.id.iv_comment, R.id.tv_comment_count -> { + R.id.replyTv -> { mViewModel.answerDetail?.run { if (commentable) { DataUtils.onMtaEvent(context, "详情页面", "答案评论详情", content.subStringIfPossible(30)) - showCommentDialog(commentCount == 0) + showCommentDialog(false) } else { toast("作者已关闭评论") } @@ -853,6 +831,8 @@ class AnswerDetailFragment : NormalFragment() { ifLogin("回答详情-[关注]用户") { if (mBinding.followTv.text == "关注") { mViewModel.follow(mViewModel.answerDetail!!.user.id!!) + } else { + mViewModel.unfollow(mViewModel.answerDetail!!.user.id!!) } } } @@ -883,10 +863,6 @@ class AnswerDetailFragment : NormalFragment() { R.id.questionsdetail_item_pic3 -> showQuestionImageDetail(view, 2 - videoSize) R.id.title_tv -> { -// startActivity(QuestionsDetailActivity.getIntent( -// context, -// mViewModel.answerDetail?.question?.id, mEntrance, -// "回答详情")) val intent = QuestionsDetailActivity.getIntent( context, mViewModel.answerDetail?.question?.id, mEntrance, @@ -931,13 +907,13 @@ class AnswerDetailFragment : NormalFragment() { private fun updateCollectView(isCollected: Boolean) { if (isCollected) { - mBinding.bottomController.tvCollect.text = "已收藏" - mBinding.bottomController.ivCollect.setImageResource(R.drawable.community_content_detail_collect_select) - mBinding.bottomController.tvCollect.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) + mBinding.bottomController.bottomStarIv.setImageResource(R.drawable.community_content_detail_collect_select) + mBinding.bottomController.bottomStarTv.text = "已收藏" + mBinding.bottomController.bottomStarTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) } else { - mBinding.bottomController.tvCollect.text = "收藏" - mBinding.bottomController.ivCollect.setImageResource(R.drawable.community_content_detail_collect_unselect) - mBinding.bottomController.tvCollect.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) + mBinding.bottomController.bottomStarIv.setImageResource(R.drawable.community_content_detail_collect_unselect) + mBinding.bottomController.bottomStarTv.text = "收藏" + mBinding.bottomController.bottomStarTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) } } @@ -989,7 +965,7 @@ class AnswerDetailFragment : NormalFragment() { if (mIsShowCommentManager) { mIsShowCommentManager = false - mBinding.bottomController.ivComment.performClick() + mBinding.bottomController.bottomCommentContainer.performClick() } mBinding.richEditor.clearFocus() @@ -1013,7 +989,7 @@ class AnswerDetailFragment : NormalFragment() { private fun hideLoadingViewAndShowContent() { mNoConn.visibility = View.GONE - mBinding.bottomController.containerControl.visibility = View.VISIBLE + mBinding.bottomController.root.visibility = View.VISIBLE mBinding.scrollView.visibility = View.VISIBLE } @@ -1126,21 +1102,11 @@ class AnswerDetailFragment : NormalFragment() { } private fun updateFollowBtn(isFollowed: Boolean) { + mBinding.followTv.visibility = View.VISIBLE if (isFollowed) { - if (mBinding.followTv.visibility == View.GONE) return DrawableView.setTextDrawable(mBinding.followTv, null, "已关注") mBinding.followTv.setTextColor(R.color.text_999999.toColor()) - mBinding.followTv.postDelayed({ - if (context == null) return@postDelayed - mBinding.followTv.animate() - .alpha(0f) - .setInterpolator(LinearInterpolator()) - .doOnEnd { context?.let { mBinding.followTv.visibility = View.GONE } } - .setDuration(500L) - .start() - }, 2000L) } else { - mBinding.followTv.visibility = View.VISIBLE mBinding.followTv.background = DrawableView.getOvalDrawable(R.color.background, 2F) mBinding.followTv.setTextColor(R.color.theme_font.toColor()) DrawableView.setTextDrawable( @@ -1152,22 +1118,24 @@ class AnswerDetailFragment : NormalFragment() { @SuppressLint("SetTextI18n") private fun updateLikeView(alreadyVoted: Boolean, voteCount: Int) { - mBinding.bottomController.tvLike.text = "赞同 ${NumberUtils.transSimpleCount(voteCount)}" +// mBinding.bottomController.bottomLikeTv.text = "赞同 ${NumberUtils.transSimpleCount(voteCount)}" if (alreadyVoted) { - mBinding.bottomController.ivLike.setImageResource(R.drawable.community_content_detail_vote_select) - mBinding.bottomController.tvLike.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) + mBinding.bottomController.bottomLikeIv.setImageResource(R.drawable.community_content_detail_vote_select) + mBinding.bottomController.bottomLikeTv.text = NumberUtils.transSimpleCount(voteCount) + mBinding.bottomController.bottomLikeTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.theme_font)) } else { - mBinding.bottomController.ivLike.setImageResource(R.drawable.community_content_detail_vote_unselect) - mBinding.bottomController.tvLike.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) + mBinding.bottomController.bottomLikeIv.setImageResource(R.drawable.community_content_detail_vote_unselect) + mBinding.bottomController.bottomLikeTv.text = "赞同" + mBinding.bottomController.bottomLikeTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_242529)) } } private fun updateDislikeView(disliked: Boolean) { - if (disliked) { - mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_select) - } else { - mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_unselect) - } +// if (disliked) { +// mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_select) +// } else { +// mBinding.bottomController.ivDislike.setImageResource(R.drawable.community_content_detail_oppose_unselect) +// } } private fun showDragHintDialog() { diff --git a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt index 26b3bea91b..0bd6ab2efa 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/answer/edit/AnswerEditActivity.kt @@ -33,6 +33,7 @@ import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel import com.halo.assistant.HaloApp import com.zhihu.matisse.Matisse import com.zhihu.matisse.MimeType +import org.json.JSONArray import org.json.JSONObject /** @@ -41,6 +42,7 @@ import org.json.JSONObject class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { private lateinit var mMenuDraft: MenuItem + private lateinit var mMenuPost: MenuItem private lateinit var mBinding: FragmentAnswerEditBinding private lateinit var mViewModel: AnswerEditViewModel @@ -81,6 +83,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { super.onCreate(savedInstanceState) setToolbarMenu(R.menu.menu_answer_post) mMenuDraft = mToolbar.menu.findItem(R.id.menu_draft) + mMenuPost = mToolbar.menu.findItem(R.id.menu_answer_post) mCommunityName = intent?.getStringExtra(EntranceUtils.KEY_COMMUNITY_NAME) mOpenAnswerInNewPage = intent?.getBooleanExtra(EntranceUtils.KEY_ANSWER_OPEN_IN_NEW_PAGE, false)!! mBinding = FragmentAnswerEditBinding.bind(mContentView) @@ -105,6 +108,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mBinding.answerPlaceholder.visibility = if (t.contains(" @@ -131,6 +135,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mKeyboardHeightProvider = KeyboardHeightProvider(this) mBinding.root.post { mKeyboardHeightProvider?.start() } + checkPostButtonEnable() } override fun getLayoutId(): Int { @@ -245,15 +250,24 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { } } - mViewModel.postImageLiveData.observeNonNull(this) { - if (it.status == Status.SUCCESS) { - val imageUrl = it.data!! - for (sourceImage in imageUrl.keys) { - mViewModel.mapImages.set(TextUtils.htmlEncode(sourceImage).decodeURI(), imageUrl[sourceImage]!!) - mRichEditor.insertImage(FILE_HOST + sourceImage.decodeURI()) - } + mViewModel.chooseImagesUpload.observe(this, Observer { + for (key in it.keys) { + mRichEditor.focusEditor() + mRichEditor.insertPlaceholderImage(key) } - } + }) + + mViewModel.chooseImagesUploadSuccess.observe(this, Observer { + val jsonArray = JSONArray() + mRichEditor.focusEditor() + for (key in it.keys) { + val jsonObject = JSONObject() + jsonObject.put("id", key) + jsonObject.put("url", it[key]) + jsonArray.put(jsonObject) + } + mRichEditor.replacePlaceholderImage(jsonArray.toString()) + }) mViewModel.deleteDraftLiveDate.observe(this, Observer { if (it == true) { @@ -265,6 +279,7 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.draftsLiveData.observe(this, Observer { mRichEditor.setHtml(it, false) requestFocusAndMoveCursorToEnd() + checkPostButtonEnable() }) mViewModel.saveDraftsLiveData.observeNonNull(this) { @@ -362,29 +377,33 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mRichEditor.postDelayed({ val answerContent = getReplaceRealContent() mRichEditor.showLinkStyle() - // filter rule - val answerLength = HtmlUtils.stripHtml(answerContent).length - if (answerLength < MIN_ANSWER_TEXT_LENGTH) { -// toast(R.string.answer_beneath_length_limit) - ToastUtils.showToast(getString(R.string.answer_beneath_length_limit), if (mIsKeyBoardShow) Gravity.CENTER else -1) - return@postDelayed - } else if (answerLength > MAX_ANSWER_TEXT_LENGTH) { - /* DialogUtils.showAlertDialog(this, - getString(R.string.answer_post_failed), - getString(R.string.answer_exceed_length_limit, - MAX_ANSWER_TEXT_LENGTH, - answerLength - MAX_ANSWER_TEXT_LENGTH), - getString(R.string.answer_resume_edit), "", { - // do nothing - }, null)*/ - ToastUtils.showToast("回答最多输入10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1) + if (mRichEditor.hasPlaceholderImage()) { + ToastUtils.showToast("图片上传ing") return@postDelayed } - mViewModel.postAnswer(answerContent) + if (checkData(answerContent)) { + mViewModel.postAnswer(answerContent) + } }, 100) } } + private fun checkData(answerContent: String, isShowToast: Boolean = true): Boolean { + val answerLength = HtmlUtils.stripHtml(answerContent).length + if (answerLength < MIN_ANSWER_TEXT_LENGTH) { + if (isShowToast) ToastUtils.showToast(getString(R.string.answer_beneath_length_limit), if (mIsKeyBoardShow) Gravity.CENTER else -1) + return false + } else if (answerLength > MAX_ANSWER_TEXT_LENGTH) { + if (isShowToast) ToastUtils.showToast("回答最多输入10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1) + return false + } + val draftValue = mViewModel.draftsLiveData.value + if (!draftValue.isNullOrEmpty()) { + return draftValue != answerContent + } + return true + } + private fun getReplaceRealContent(): String { var answerContent = mRichEditor.html for (s in mViewModel.mapImages.keys) { @@ -396,6 +415,12 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { return answerContent } + private fun checkPostButtonEnable() { + val answerContent = getReplaceRealContent() + val isEnabled = checkData(answerContent, false) + mMenuPost.actionView.alpha = if (isEnabled) 1f else 0.6f + } + override fun handleBackPressed(): Boolean { return if (TextUtils.isEmpty(UserManager.getInstance().token)) { false @@ -410,14 +435,9 @@ class AnswerEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { && !mRichEditor.html.contains("() val saveDraftsLiveData = MediatorLiveData() // 自动保存不会回调 + val uploadingImage = ArrayList>() + val chooseImagesUpload = MutableLiveData>() + val chooseImagesUploadSuccess = MutableLiveData>() + var uploadImageSubscription: Disposable? = null val mapImages = HashMap() @@ -156,19 +157,30 @@ class AnswerEditViewModel(application: Application, } if (pictureList.size == 0) return - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", true)) - uploadImageSubscription = UploadImageUtils.compressAndUploadImageList(UploadImageUtils.UploadType.answer, pictureList , false, object : UploadImageUtils.OnUploadImageListListener { override fun onProgress(total: Long, progress: Long) { - var percent = (100 * (progress / total.toFloat())).toInt() - if (percent >= 100) percent = 99 - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("图片上传中 $percent%", true)) } + override fun onCompressSuccess(imageUrls: List) { + val chooseImageMd5Map = HashMap() + imageUrls.forEach { + chooseImageMd5Map[MD5Utils.getUrlMD5(it)] = "" + } + uploadingImage.add(chooseImageMd5Map) + chooseImagesUpload.postValue(chooseImageMd5Map) + + } override fun onSuccess(imageUrl: LinkedHashMap, errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) - postImageLiveData.postValue(Resource.success(imageUrl)) + val uploadMap = uploadingImage.find { it.containsKey(MD5Utils.getUrlMD5(imageUrl.entries.iterator().next().key)) } + uploadMap?.let { + for (key in imageUrl.keys) { + uploadMap[MD5Utils.getUrlMD5(key)] = AnswerEditActivity.FILE_HOST + key.decodeURI() + mapImages[TextUtils.htmlEncode(key).decodeURI()] = imageUrl[key] ?: "" + } + chooseImagesUploadSuccess.postValue(uploadMap) + uploadingImage.remove(uploadMap) + } val errorSize = pictureList.size - imageUrl.size if (errorSize > 0) { for (error in errorMap.values) { @@ -182,8 +194,6 @@ class AnswerEditViewModel(application: Application, } override fun onError(errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) - postImageLiveData.postValue(Resource.error(null)) val errorSize = pictureList.size for (error in errorMap.values) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt index f50911a941..e6601214d3 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailContentViewHolder.kt @@ -44,77 +44,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } }) - likeContainer.setDebouncedClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "点赞") - root.context.ifLogin("帖子详情-赞同") { - if (!article.me.isCommunityArticleVote) { - viewModel.likeArticle() - if (EntranceUtils.ENTRANCE_WELCOME == mEntrance) { - LogUtils.uploadLikeFromWelcomeDialog() - } - } else { - viewModel.cancelLikeArticle() - } - } - } - - shareContainer.setOnClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "分享") -// GdtHelper.logAction(ActionType.SHARE, -// GdtHelper.CONTENT_TYPE, "QA_ARTICLE", -// GdtHelper.CONTENT_ID, viewModel.articleId) - - var shareSummary = richEditor.text - val shareIcon: String = if (articleImgUrlList.size > 0) { - articleImgUrlList[0] - } else { - root.context.getString(R.string.share_ghzs_logo) - } - if (TextUtils.isEmpty(shareSummary)) { - shareSummary = root.context.getString(R.string.ask_share_default_summary) - } - val shareUrl = if (isPublishEnv()) { - root.context.getString(R.string.share_community_article_url, article.community.id, article.id) - } else { - root.context.getString(R.string.share_community_article_url_dev, article.community.id, article.id) - } - ShareUtils.getInstance(root.context).showShareWindows( - root.context as Activity?, - root, - shareUrl, - shareIcon, - root.context.getString(R.string.share_community_article_title, article.user.name, article.title, article.count.vote), - shareSummary, - ShareUtils.ShareEntrance.communityArticle, - article.id) - } - - starContainer.setDebouncedClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "收藏") - root.context.ifLogin(entrance = "帖子详情-收藏") { - viewModel.collectionCommand(!article.me.isCommunityArticleFavorite, callback = { - viewModel.detailEntity?.me?.isCommunityArticleFavorite = it - if (it) { -// GdtHelper.logAction(ActionType.ADD_TO_WISHLIST, -// GdtHelper.CONTENT_TYPE, "QA_ARTICLE", -// GdtHelper.CONTENT_ID, viewModel.articleId) - } - updateCollectView(it) - }) - } - } - - dislikeContainer.setDebouncedClickListener { - MtaHelper.onEvent("帖子详情", "内容区域", "反对") - root.context.ifLogin("帖子详情-反对") { - if (!article.me.isCommunityArticleOppose) { - viewModel.dislikeArticle() - } else { - viewModel.cancelDislikeArticle() - } - } - } - followBtn.setOnClickListener { MtaHelper.onEvent("帖子详情", "内容区域", "关注") root.context.ifLogin("帖子详情-[关注]用户") { @@ -143,14 +72,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } binding.run { - if (article.me.isCommunityArticleFavorite) { - starIv.setImageResource(R.drawable.ic_article_detail_stared) - starTv.text = "已收藏" - } else { - starIv.setImageResource(R.drawable.ic_article_detail_star) - starTv.text = "收藏" - } - detail = article userIconIv.display(article.user.border, article.user.icon, article.user.auth?.icon) richEditor.setContentOwner(article.me.isContentOwner) @@ -160,9 +81,9 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } if (article.time.create == article.time.edit) { - releaseTimeTv.text = String.format("发布于 %s", NewsUtils.getFormattedTime(article.time.create)) + releaseTimeTv.text = String.format("发布于%s", NewsUtils.getFormattedTime(article.time.create)) } else { - releaseTimeTv.text = String.format("修改于 %s", NewsUtils.getFormattedTime(article.time.edit)) + releaseTimeTv.text = String.format("发布于%s 最后编辑于%s", NewsUtils.getFormattedTime(article.time.create), NewsUtils.getFormattedTime(article.time.edit)) } richEditor.visibility = View.VISIBLE @@ -199,9 +120,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } } badgeTv.setOnClickListener { badgeIv.performClick() } - - updateLikeView(article.me.isCommunityArticleVote, article.count.vote) - updateDislikeView(article.me.isCommunityArticleOppose) } } } @@ -213,16 +131,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin followBtn.text = "已关注" followBtn.background = null followBtn.setTextColor(ContextCompat.getColor(root.context, R.color.text_999999)) - followBtn.postDelayed({ - followBtn.animate() - .alpha(0f) - .setInterpolator(LinearInterpolator()) - .doOnEnd { - tryWithDefaultCatch { followBtn.visibility = View.GONE } - } - .setDuration(500L) - .start() - }, 2000L) } else { followBtn.setRoundedColorBackground(R.color.text_EEF5FB, 14F) followBtn.setTextColor(ContextCompat.getColor(root.context, R.color.theme_font)) @@ -231,40 +139,6 @@ class ArticleDetailContentViewHolder(var binding: ItemArticleDetailContentBindin } } - @SuppressLint("SetTextI18n") - fun updateLikeView(alreadyLiked: Boolean, likeCount: Int) { - binding.run { - likeTv.text = if (likeCount == 0) "赞同" else likeCount.toString() - if (alreadyLiked) { - likeIv.setImageResource(R.drawable.ic_article_detail_liked) - } else { - likeIv.setImageResource(R.drawable.ic_article_detail_like) - } - } - } - - fun updateDislikeView(disliked: Boolean) { - binding.run { - if (disliked) { - dislikeIv.setImageResource(R.drawable.ic_article_detail_disliked) - } else { - dislikeIv.setImageResource(R.drawable.ic_article_detail_dislike) - } - } - } - - fun updateCollectView(isCollected: Boolean) { - binding.run { - if (isCollected) { - starTv.text = "已收藏" - starIv.setImageResource(R.drawable.ic_article_detail_stared) - } else { - starTv.text = "收藏" - starIv.setImageResource(R.drawable.ic_article_detail_star) - } - } - } - private fun addTag(tag: String, isCommunityName: Boolean = false) { binding.run { if (isCommunityName) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt index ccc2e6adf0..8b96a1e1b7 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/ArticleDetailFragment.kt @@ -3,15 +3,14 @@ package com.gh.gamecenter.qa.article.detail import android.annotation.SuppressLint import android.app.Activity import android.content.Intent -import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout -import android.widget.PopupWindow import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.lifecycle.Lifecycle @@ -37,6 +36,7 @@ import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.personal.PersonalFragment import com.gh.gamecenter.qa.article.edit.ArticleEditActivity import com.gh.gamecenter.qa.comment.CommentActivity +import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog import com.gh.gamecenter.qa.entity.ArticleDetailEntity import com.gh.gamecenter.suggest.SuggestType import com.halo.assistant.HaloApp @@ -183,11 +183,29 @@ class ArticleDetailFragment : BaseArticleDetailCommentFragment(R.id.container) val entities = ArrayList() if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("修改", R.drawable.menu_more_edit)) + entities.add(MenuItemEntity("修改", R.drawable.icon_more_panel_edit)) } if (mViewModel.detailEntity?.user?.id != UserManager.getInstance().userId) { - entities.add(MenuItemEntity("投诉", R.drawable.ic_menu_gamedetail_feedback)) + entities.add(MenuItemEntity("投诉", R.drawable.icon_gamedetail_copyright)) } if (mViewModel.detailEntity?.me!!.isModerator) { - entities.add(MenuItemEntity("加精", R.drawable.menu_more_essence_enable, - if (mViewModel.detailEntity?.isHighlighted == true || mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) - R.drawable.menu_more_essence_unenable else 0)) + val isEnable = mViewModel.detailEntity?.isHighlighted == true || mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId + entities.add(MenuItemEntity("加精", if (isEnable) + R.drawable.icon_more_panel_essence_unenable else R.drawable.icon_more_panel_essence, isEnable = !isEnable)) } if (mViewModel.detailEntity?.me!!.isModerator || mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("删除", R.drawable.menu_more_delete)) + entities.add(MenuItemEntity("删除", R.drawable.icon_more_panel_delete)) } - entities.forEachIndexed { index, item -> - val menuItem = createMenuItem(index, item) - container.addView(menuItem) - menuItem.setOnClickListener { - popupWindow.dismiss() - when (item.text) { - "修改" -> { - startActivityForResult(ArticleEditActivity.getPatchIntent(requireContext(), mViewModel.detailEntity!!), ArticleDetailActivity.ARTICLE_PATCH_REQUEST) - } - "投诉" -> { - SuggestionActivity.startSuggestionActivity(requireContext(), SuggestType.normal, "report", - "帖子投诉(" + mViewModel.articleId + "):") - } - "加精" -> addEssenceForum(mViewModel.detailEntity!!) - "删除" -> { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除帖子后,其中的所有评论及回复都将被删除", "取消", "删除", {}, { - mViewModel.doHideThisArticle(mViewModel.detailEntity!!.community.id, mViewModel.articleId) - }) - } + val shareUrl = if (isPublishEnv()) { + requireContext().getString(R.string.share_community_article_url, mViewModel.communityId, mViewModel.detailEntity?.id) + } else { + requireContext().getString(R.string.share_community_article_url_dev, mViewModel.communityId, mViewModel.detailEntity?.id) + } + + val shareIcon: String = if (mViewModel.detailEntity?.images?.isNotEmpty() == true) { + mViewModel.detailEntity?.images!![0] + } else { + requireContext().getString(R.string.share_ghzs_logo) + } + val title = requireContext().getString(R.string.share_community_article_title, mViewModel.detailEntity?.user?.name, + mViewModel.detailEntity?.title, mViewModel.detailEntity?.count?.vote ?: 0) + val shareUtils = ShareUtils.getInstance(requireContext()) + shareUtils.shareParamsDetail(requireActivity(), + shareUrl, + shareIcon, + title, + HtmlUtils.stripHtml(mViewModel.detailEntity?.content), + ShareUtils.ShareEntrance.communityArticle, + mViewModel.detailEntity?.id, null) + MoreFunctionPanelDialog.showMoreDialog(requireActivity() as AppCompatActivity, entities, mViewModel.detailEntity?.title + ?: "", shareUtils) { + when (it.text) { + "修改" -> { + startActivityForResult(ArticleEditActivity.getPatchIntent(requireContext(), mViewModel.detailEntity!!), ArticleDetailActivity.ARTICLE_PATCH_REQUEST) + } + "投诉" -> { + SuggestionActivity.startSuggestionActivity(requireContext(), SuggestType.normal, "report", + "帖子投诉(" + mViewModel.articleId + "):") + } + "加精" -> addEssenceForum(mViewModel.detailEntity!!) + "删除" -> { + DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除帖子后,其中的所有评论及回复都将被删除", "取消", "删除", {}, { + mViewModel.doHideThisArticle(mViewModel.detailEntity!!.community.id, mViewModel.articleId) + }) } } } @@ -465,17 +483,31 @@ class ArticleDetailFragment : BaseArticleDetailCommentFragment { - DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论置顶?", "取消", "确认", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论置顶?", "取消", "确认", null, Gravity.CENTER, false, {}, { commentTop(binding.root.context, viewModel, comment, false) }) } "取消置顶" -> { - DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论取消置顶?", "取消", "确认", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(binding.root.context, "提示", "是否将此条评论取消置顶?", "取消", "确认", null, Gravity.CENTER, false, {}, { viewModel.updateCommentTop(comment.id ?: "", top = false, isAgain = false) { isSuccess, errorCode -> if (isSuccess) { @@ -432,7 +433,7 @@ abstract class BaseArticleDetailCommentAdapter(context: Context, viewModel.load(LoadType.REFRESH) } else { if (errorCode == 403095) { - DialogUtils.showNewAlertDialog(context, "提示", "当前已有置顶评论,\n是否将此条评论覆盖展示?", "取消", "确认", null, Gravity.CENTER, {}, { + DialogUtils.showNewAlertDialog(context, "提示", "当前已有置顶评论,\n是否将此条评论覆盖展示?", "取消", "确认", null, Gravity.CENTER, false, {}, { commentTop(context, viewModel, comment, true) }) } diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/BaseArticleDetailCommentFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/BaseArticleDetailCommentFragment.kt index ef8b128188..e651cba3bd 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/BaseArticleDetailCommentFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/BaseArticleDetailCommentFragment.kt @@ -4,6 +4,7 @@ import android.graphics.drawable.InsetDrawable import android.os.Bundle import android.view.View import android.widget.TextView +import androidx.annotation.Nullable import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import butterknife.BindView @@ -12,6 +13,9 @@ import com.gh.common.view.CustomDividerItemDecoration import com.gh.common.view.vertical_recycler.SnappingLinearLayoutManager import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment +import com.gh.gamecenter.qa.article.detail.comment.ArticleDetailCommentFragment +import com.gh.gamecenter.qa.comment.CommentActivity +import kotterknife.bindView abstract class BaseArticleDetailCommentFragment : ListFragment() { @@ -39,6 +43,7 @@ abstract class BaseArticleDetailCommentFragment?, displayFloor: Boolean = false) { + fun mergeListData(commentList: List?, displayFloor: Boolean = false, hasFilter: Boolean = true) { topItemData?.let { val mergedList = arrayListOf().apply { - if (mResultLiveData.value?.firstOrNull() != null) { - // 保持头两个 item 的内存地址不变 - add(mResultLiveData.value!![0]) - add(mResultLiveData.value!![1]) + if (hasFilter) { + if (mResultLiveData.value?.firstOrNull() != null) { + // 保持头两个 item 的内存地址不变 + add(mResultLiveData.value!![0]) + add(mResultLiveData.value!![1]) + } else { + add(topItemData!!) + add(CommentItemData(filter = true)) + } } else { add(topItemData!!) - add(CommentItemData(filter = true)) } if (commentList.isNullOrEmpty() && mLoadStatusLiveData.value == LoadStatus.INIT_EMPTY) { add(CommentItemData(errorEmpty = true)) diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt index a75598c149..e59907f961 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentAdapter.kt @@ -65,9 +65,9 @@ class ArticleDetailCommentAdapter(context: Context, binding.comment = comment binding.moreIv.visibility = View.GONE + binding.divider.visibility = View.VISIBLE + binding.commentCountTv.visibility = View.GONE binding.floorHintTv.text = if (comment.floor != 0) "${comment.floor}楼" else "" - binding.commentCountTv.text = mViewModel.getCommentText(comment.reply, "回复") - binding.commentCountTv.setOnClickListener { commentClosure?.invoke(comment) } binding.contentTv.text = comment.content binding.contentTv.maxLines = Int.MAX_VALUE diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt index d64e4456c8..fa1a72d4b0 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentFragment.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.ViewCompat import com.ethanhua.skeleton.Skeleton +import com.gh.common.AppExecutor import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListAdapter @@ -45,7 +46,6 @@ class ArticleDetailCommentFragment : BaseArticleDetailCommentFragment - (toolbarContainer.layoutParams as ViewGroup.MarginLayoutParams).topMargin = insets.systemWindowInsetTop - insets.consumeSystemWindowInsets() - } - mSkeletonScreen = Skeleton.bind(skeletonView).shimmer(false).load(R.layout.fragment_article_detail_comment_skeleton).show() bottomLikeContainer.visibility = View.GONE + bottomStarContainer.visibility = View.GONE bottomCommentContainer.visibility = View.GONE val lp = replyTv.layoutParams as ConstraintLayout.LayoutParams @@ -99,46 +95,7 @@ class ArticleDetailCommentFragment : BaseArticleDetailCommentFragment { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除评论后,评论下所有的回复都将被删除", "取消", "删除", null, { - mViewModel.hideCommunityArticleComment(entity.id ?: "") { - EventBus.getDefault().post(EBDeleteCommentDetail(entity.id)) - requireActivity().finish() - } - }) - } - else -> { - //do nothing - } - } - } - - }) - } + closeIv.setOnClickListener { requireActivity().finish() } } override fun onBackPressed(): Boolean { @@ -170,18 +127,18 @@ class ArticleDetailCommentFragment : BaseArticleDetailCommentFragment 2) { + mListRv.smoothScrollToPosition(1) + } + }, 100) } else -> { if (it == BaseArticleDetailCommentViewModel.LoadResult.DELETED) { mReuseNoConn?.visibility = View.GONE mReuseNoData?.visibility = View.VISIBLE toast(R.string.content_delete_toast) - - toolbar.menu?.run { - for (i in 0 until size()) { - getItem(i).isVisible = false - } - } } else { mReuseNoConn?.visibility = View.VISIBLE mReuseNoData?.visibility = View.GONE diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt index 901c2b185a..8a4e29d54e 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/detail/comment/ArticleDetailCommentViewModel.kt @@ -26,7 +26,7 @@ class ArticleDetailCommentViewModel(application: Application, override fun provideDataObservable(page: Int): Observable>? = null override fun mergeResultLiveData() { - mResultLiveData.addSource(mListLiveData) { mergeListData(it) } + mResultLiveData.addSource(mListLiveData) { mergeListData(it, hasFilter = false) } } override fun provideDataSingle(page: Int): Single> { @@ -46,7 +46,7 @@ class ArticleDetailCommentViewModel(application: Application, commentCount = data.reply topItemData = CommentItemData(commentTop = data) loadResultLiveData.postValue(LoadResult.SUCCESS) - mergeListData(mListLiveData.value) + mergeListData(mListLiveData.value, hasFilter = false) } override fun onFailure(exception: Exception) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt index 6245086e2e..fd2187c7f2 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/draft/ArticleDraftFragment.kt @@ -3,10 +3,13 @@ package com.gh.gamecenter.qa.article.draft import android.app.Activity import android.content.Intent import android.os.Bundle +import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.RecyclerView import com.gh.common.util.EntranceUtils import com.gh.common.util.UrlFilterUtils import com.gh.common.util.checkStoragePermissionBeforeAction +import com.gh.common.view.CustomDividerItemDecoration import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment import com.gh.gamecenter.baselist.LoadType @@ -89,6 +92,12 @@ class ArticleDraftFragment : ListFragment() { override fun onResponse(response: ResponseBody?) { - mListViewModel.load(LoadType.REFRESH) + val index = mAdapter?.entityList?.indexOf(entity) ?: -1 + if (index >= 0) { + mAdapter?.entityList?.remove(entity) + if (mAdapter?.entityList.isNullOrEmpty()) { + mListViewModel.load(LoadType.REFRESH) + } else { + mAdapter?.notifyItemRemoved(index) + } + } } override fun onFailure(e: HttpException?) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt index 4f0bd794c3..0369558ed5 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditActivity.kt @@ -12,16 +12,11 @@ import android.text.TextUtils import android.view.Gravity import android.view.MenuItem import android.view.View -import android.view.Window -import android.view.inputmethod.InputMethodManager import android.widget.* import androidx.core.content.ContextCompat -import androidx.core.widget.NestedScrollView import androidx.core.widget.doOnTextChanged import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders -import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView import butterknife.OnClick import com.gh.base.BaseRichEditorActivity import com.gh.base.fragment.WaitingDialogFragment @@ -32,9 +27,9 @@ import com.gh.gamecenter.R import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.manager.UserManager -import com.gh.gamecenter.mvvm.Status import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.article.draft.ArticleDraftActivity +import com.gh.gamecenter.qa.dialog.ChooseForumDialogFragment import com.gh.gamecenter.qa.entity.ArticleDetailEntity import com.gh.gamecenter.qa.entity.ArticleDraftEntity import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment @@ -44,6 +39,8 @@ import com.zhihu.matisse.Matisse import com.zhihu.matisse.MimeType import kotterknife.bindView import org.greenrobot.eventbus.EventBus +import org.json.JSONArray +import org.json.JSONObject class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { @@ -81,7 +78,8 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { if (mViewModel.mSelectCommunityData != null && !TextUtils.isEmpty(mEditTitle.text.trim()) && (!TextUtils.isEmpty(mRichEditor.text) - || mRichEditor.html.contains(" if (text?.contains("\n") == true) { mEditTitle.setText(text.toString().replace("\n", "")) @@ -160,25 +156,31 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { } private fun observeData() { - // 上传图片完成后的回调(本地图片) - mViewModel.postImageLiveData.observe(this, Observer { - if (it?.status == Status.SUCCESS) { - val imageUrl = it.data!! - for (sourceImage in imageUrl.keys) { - mViewModel.mapImg[TextUtils.htmlEncode(sourceImage).decodeURI()] = imageUrl[sourceImage]!! - mRichEditor.focusEditor() - mRichEditor.insertImage(AnswerEditActivity.FILE_HOST + sourceImage.decodeURI()) - closeExtendedKeyboard() - AppExecutor.uiExecutor.executeWithDelay(Runnable { - Util_System_Keyboard.showSoftKeyboard(this) - },100) - AppExecutor.uiExecutor.executeWithDelay(Runnable { - mRichEditor.scrollTo(0,1000000) - },500) - } - checkPostButtonEnable() + mViewModel.chooseImagesUpload.observe(this, Observer { + for (key in it.keys) { + mRichEditor.focusEditor() + mRichEditor.insertPlaceholderImage(key) } }) + mViewModel.chooseImagesUploadSuccess.observe(this, Observer { + val jsonArray = JSONArray() + mRichEditor.focusEditor() + for (key in it.keys) { + val jsonObject = JSONObject() + jsonObject.put("id", key) + jsonObject.put("url", it[key]) + jsonArray.put(jsonObject) + } + mRichEditor.replacePlaceholderImage(jsonArray.toString()) + closeExtendedKeyboard() + AppExecutor.uiExecutor.executeWithDelay(Runnable { + Util_System_Keyboard.showSoftKeyboard(this) + }, 100) + AppExecutor.uiExecutor.executeWithDelay(Runnable { + mRichEditor.scrollTo(0, 1000000) + }, 500) + checkPostButtonEnable() + }) // 保存草稿 mViewModel.postArticleDrafts.observe(this, Observer { pair -> @@ -190,7 +192,7 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { EventBus.getDefault().post(EBReuse(ARTICLE_DRAFT_CHANGE_TAG)) finish() } else { - showDraftFailureDialog() + //showDraftFailureDialog() } } SaveDraftType.AUTO -> { @@ -279,14 +281,16 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { setNavigationTitle("发布帖子") mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) mViewModel.mSelectCommunityData = intent.getParcelableExtra(CommunityEntity::class.java.simpleName) - if (mViewModel.mSelectCommunityData == null) { - showSelectGameDialog() - } else { + if (mViewModel.mSelectCommunityData != null) { setGameName() mGameName.isEnabled = false mGameName.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) } + mEditTitle.requestFocus() } + mViewModel.notSelectForum.observe(this, Observer { + if (it) showSelectGameDialog() + }) } override fun getSelectedLabel(): Int = mViewModel.selectedTags.size @@ -356,7 +360,6 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.mSelectCommunityData?.icon = mViewModel.draftEntity?.community?.game?.getIcon() mViewModel.mSelectCommunityData?.iconSubscript = mViewModel.draftEntity?.community?.game?.iconSubscript mEditTitle.setText(mViewModel.draftEntity?.title) - mMenuDraft.isVisible = false mGameName.isEnabled = true setGameName() mViewModel.getArticleDraftsContent(mViewModel.draftEntity?.id!!) @@ -368,7 +371,8 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.mSelectCommunityData?.iconSubscript = mViewModel.detailEntity?.community?.game?.iconSubscript setGameName() - mMenuDraft.isVisible = true + //编辑帖子草稿箱入口不存在 + mMenuDraft.isVisible = false mGameName.isEnabled = false mGameName.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) @@ -386,9 +390,6 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mRichEditor.setHtml(html, false) try { mRichEditor.scrollTo(0, 10000000) - val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.showSoftInput(mRichEditor, InputMethodManager.SHOW_IMPLICIT) - mRichEditor.postDelayed({ mRichEditor.focusEditor() }, 800) } catch (e: Exception) { e.printStackTrace() } @@ -413,69 +414,57 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { return false } - if (mViewModel.detailEntity != null) { - return if (!TextUtils.isEmpty(mEditTitle.text) - || mRichEditor.html.contains("(R.id.dialog_game_list) - val back = view.findViewById(R.id.dialog_back) - val loading = view.findViewById(R.id.dialog_loading) - - back.setOnClickListener { - selectGameDialog.cancel() - if (mViewModel.mSelectCommunityData == null) finish() - } - recyclerView.layoutManager = GridLayoutManager(this, 4) - recyclerView.adapter = ArticleSelectGameAdapter(this, loading) { - mViewModel.mSelectCommunityData = CommunityEntity(it.id, it.name, icon = it.game.icon, iconSubscript = it.game.iconSubscript) + ChooseForumDialogFragment.show(this) { + mViewModel.mSelectCommunityData = it setGameName() - selectGameDialog.cancel() } - - selectGameDialog.requestWindowFeature(Window.FEATURE_NO_TITLE) - selectGameDialog.setCanceledOnTouchOutside(false) - selectGameDialog.setContentView(view) - selectGameDialog.show() } private fun setGameName() { @@ -552,6 +522,10 @@ class ArticleEditActivity : BaseRichEditorActivity(), KeyboardHeightObserver { mViewModel.title = mEditTitle.text.toString() mViewModel.content = getReplaceRealContent() mRichEditor.showLinkStyle() + if (mRichEditor.hasPlaceholderImage()) { + ToastUtils.showToast("图片上传ing") + return@postDelayed + } if (mViewModel.checkDataAndLoadTitleTag(mIsKeyBoardShow)) { mArticleTagsSelectFragment?.publishArticle() } diff --git a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt index 1ec0aa922d..875def39dc 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/article/edit/ArticleEditViewModel.kt @@ -14,6 +14,7 @@ import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.mvvm.Resource +import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.entity.ArticleDetailEntity import com.gh.gamecenter.qa.entity.ArticleDraftEntity import com.gh.gamecenter.qa.questions.edit.QuestionEditViewModel @@ -34,6 +35,8 @@ import org.json.JSONObject import retrofit2.HttpException import java.io.File import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashMap class ArticleEditViewModel(application: Application) : AndroidViewModel(application) { @@ -43,11 +46,15 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat val MAX_ARTICLE_TEXT_LENGTH = 10000 val processDialog = MediatorLiveData() - val postImageLiveData = MediatorLiveData>>() val postArticle = MediatorLiveData() val postArticleDrafts = MediatorLiveData>() val articleDraftsContent = MediatorLiveData() val error = MutableLiveData() + val notSelectForum = MutableLiveData() + + val uploadingImage = ArrayList>() + val chooseImagesUpload = MutableLiveData>() + val chooseImagesUploadSuccess = MutableLiveData>() var uploadImageSubscription: Disposable? = null @@ -88,25 +95,17 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat * 根据问题标题获取相应标签(问题编辑无需获取) */ fun checkDataAndLoadTitleTag(isKeyBoardShow: Boolean = false): Boolean { - if (mSelectCommunityData == null) { - ToastUtils.showToast("请选择论坛", if (isKeyBoardShow) Gravity.CENTER else -1) - return false - } - if (TextUtils.isEmpty(title)) { ToastUtils.showToast("标题不能为空", if (isKeyBoardShow) Gravity.CENTER else -1) return false } - // 检查标题长度限制 title?.trim() -// title = title?.replace(" ", "")?.replace("\n", "") title = title?.replace("\n", "") if (title!!.length < QuestionEditViewModel.QUESTION_TITLE_MIN_LENGTH) { ToastUtils.showToast("标题至少${QuestionEditViewModel.QUESTION_TITLE_MIN_LENGTH}个字", if (isKeyBoardShow) Gravity.CENTER else -1) return false } - val articleContent = HtmlUtils.stripHtml(content).length if (articleContent < MIN_ARTICLE_TEXT_LENGTH) { ToastUtils.showToast("正文至少${QuestionEditViewModel.QUESTION_TITLE_MIN_LENGTH}个字", if (isKeyBoardShow) Gravity.CENTER else -1) @@ -116,6 +115,12 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat ToastUtils.showToast("帖子最多输入${MAX_ARTICLE_TEXT_LENGTH}个字", if (isKeyBoardShow) Gravity.CENTER else -1) return false } + if (detailEntity != null && detailEntity?.title == title && HtmlUtils.stripHtml(detailEntity?.content) == HtmlUtils.stripHtml(content)) return false + if (mSelectCommunityData == null) { + ToastUtils.showToast("请选择论坛", if (isKeyBoardShow) Gravity.CENTER else -1) + notSelectForum.postValue(true) + return false + } return true } @@ -127,32 +132,10 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat val articleContent = HtmlUtils.stripHtml(content).length if (articleContent < MIN_ARTICLE_TEXT_LENGTH) return false if (articleContent > MAX_ARTICLE_TEXT_LENGTH) return false + if (detailEntity != null && detailEntity?.title == title && HtmlUtils.stripHtml(detailEntity?.content) == HtmlUtils.stripHtml(content)) return false return true } - /** - * 根据问题标题获取相应标签(标签默认选中) - */ - fun loadTitleTags() { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true)) - mApi - .getQuestionTagsByTitle(mSelectCommunityData?.id, UrlFilterUtils.getFilterQuery("title", title)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Response>() { - override fun onResponse(response: List?) { - titleTags.postValue(response) - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - } - - override fun onFailure(e: HttpException?) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - Utils.toast(getApplication(), R.string.request_failure_normal_hint) - } - }) - } - - /** * 检查图片是否符合规则并上传图片 * @param picPath 图片本地路径 @@ -177,19 +160,32 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat } if (pictureList.size == 0) return - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", true)) uploadImageSubscription = UploadImageUtils.compressAndUploadImageList(UploadImageUtils.UploadType.answer, pictureList , false, object : UploadImageUtils.OnUploadImageListListener { override fun onProgress(total: Long, progress: Long) { - var percent = (100 * (progress / total.toFloat())).toInt() - if (percent >= 100) percent = 99 - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("图片上传中 $percent%", true)) + } + + override fun onCompressSuccess(imageUrls: List) { + val chooseImageMd5Map = HashMap() + imageUrls.forEach { + chooseImageMd5Map[MD5Utils.getUrlMD5(it)] = "" + } + uploadingImage.add(chooseImageMd5Map) + chooseImagesUpload.postValue(chooseImageMd5Map) + } override fun onSuccess(imageUrl: LinkedHashMap, errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) - postImageLiveData.postValue(Resource.success(imageUrl)) + val uploadMap = uploadingImage.find { it.containsKey(MD5Utils.getUrlMD5(imageUrl.entries.iterator().next().key)) } + uploadMap?.let { + for (key in imageUrl.keys) { + uploadMap[MD5Utils.getUrlMD5(key)] = AnswerEditActivity.FILE_HOST + key.decodeURI() + mapImg[TextUtils.htmlEncode(key).decodeURI()] = imageUrl[key] ?: "" + } + chooseImagesUploadSuccess.postValue(uploadMap) + uploadingImage.remove(uploadMap) + } val errorSize = pictureList.size - imageUrl.size if (errorSize > 0) { for (error in errorMap.values) { @@ -203,7 +199,6 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat } override fun onError(errorMap: Map) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("上传中...", false)) val errorSize = pictureList.size for (error in errorMap.values) { @@ -217,7 +212,6 @@ class ArticleEditViewModel(application: Application) : AndroidViewModel(applicat } else { Utils.toast(getApplication(), errorSize.toString() + "张图片上传失败") } - postImageLiveData.postValue(Resource.error(null)) } }) } diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt index 0a3ce8b66e..0cb44fec34 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/CommentActivity.kt @@ -8,10 +8,14 @@ import android.view.View import butterknife.OnClick import com.gh.base.BaseActivity import com.gh.common.util.DisplayUtils +import com.gh.common.util.EntranceUtils import com.gh.common.util.doOnEnd +import com.gh.gamecenter.NormalActivity import com.gh.gamecenter.R import com.gh.gamecenter.entity.CommentEntity import com.gh.gamecenter.qa.answer.detail.AnswerDetailFragment +import com.gh.gamecenter.qa.article.detail.comment.ArticleDetailCommentActivity +import com.gh.gamecenter.qa.article.detail.comment.ArticleDetailCommentFragment import com.lightgame.utils.Util_System_Keyboard import kotlinx.android.synthetic.main.activity_comment.* @@ -39,6 +43,7 @@ class CommentActivity : BaseActivity() { val commentEntity: CommentEntity? = intent.getParcelableExtra(COMMENT_ENTITY) ?: null val useReplyApi: Boolean = intent.getBooleanExtra(USE_REPLY_API, false) + val articleCommentId = intent.getStringExtra(EntranceUtils.KEY_ARTICLE_COMMENT_ID) mShowInputOnly = intent.getBooleanExtra(SHOW_INPUT_ONLY, false) @@ -68,16 +73,18 @@ class CommentActivity : BaseActivity() { } else if (!articleId.isNullOrEmpty()) { NewCommentFragment.getCommunityArticleCommentInstance( articleId, - communityId?:"", + communityId, showKeyboard, commentCount, mShowInputOnly, useReplyApi, commentEntity, commentCallback) + } else if (!articleCommentId.isNullOrEmpty()) { + ArticleDetailCommentFragment().with(intent.extras) } else { NewCommentFragment.getVideoCommentInstance( - videoId?:"", + videoId, showKeyboard, commentCount, isVideoAuthor, @@ -86,7 +93,7 @@ class CommentActivity : BaseActivity() { } } - supportFragmentManager.beginTransaction().replace(R.id.answerCommentPlaceholderView, commentFragment, NewCommentFragment::class.java.simpleName).commitNowAllowingStateLoss() + supportFragmentManager.beginTransaction().replace(R.id.answerCommentPlaceholderView, commentFragment!!, NewCommentFragment::class.java.simpleName).commitNowAllowingStateLoss() maskView.alpha = 0f if (videoId.isNullOrEmpty()) { @@ -158,6 +165,26 @@ class CommentActivity : BaseActivity() { return intent } + @JvmStatic + fun getArticleDetailCommentIntent(context: Context, + commentId: String, + communityId: String, + articleId: String, + showKeyboard: Boolean = false, + position: Int = -1, + entrance: String, + path: String): Intent { + val intent = Intent(context, CommentActivity::class.java) + intent.putExtra(EntranceUtils.KEY_ENTRANCE, NormalActivity.mergeEntranceAndPath(entrance, path)) + intent.putExtra(EntranceUtils.KEY_COMMUNITY_ARTICLE_ID, articleId) + intent.putExtra(EntranceUtils.KEY_COMMUNITY_ID, communityId) + intent.putExtra(EntranceUtils.KEY_POSITION, position) + intent.putExtra(EntranceUtils.KEY_ARTICLE_COMMENT_ID, commentId) + intent.putExtra(EntranceUtils.KEY_SHOW_KEYBOARD_IF_NEEDED, showKeyboard) + intent.putExtra(EntranceUtils.KEY_PATH, path) + return intent + } + @JvmStatic fun getArticleCommentIntent(context: Context, articleId: String, diff --git a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt index 5a3cf695ed..f9bdc55180 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/comment/NewCommentAdapter.kt @@ -1,6 +1,7 @@ package com.gh.gamecenter.qa.comment import android.content.Context +import android.text.SpannableStringBuilder import android.text.TextUtils import android.view.View import android.view.ViewGroup @@ -14,6 +15,7 @@ import com.gh.gamecenter.adapter.viewholder.FooterViewHolder import com.gh.gamecenter.baselist.ListAdapter import com.gh.gamecenter.entity.CommentEntity import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity +import com.gh.gamecenter.qa.article.detail.BaseArticleDetailCommentAdapter class NewCommentAdapter(context: Context, var mViewModel: NewCommentViewModel, @@ -27,7 +29,7 @@ class NewCommentAdapter(context: Context, val view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false) FooterViewHolder(view) } else { - val view = mLayoutInflater.inflate(R.layout.comment_item, parent, false) + val view = mLayoutInflater.inflate(R.layout.new_comment_item, parent, false) AnswerCommentViewHolder(view) } } @@ -55,11 +57,29 @@ class NewCommentAdapter(context: Context, val commentEntity = mEntityList[position] CommentUtils.setCommentUserView(mContext, holder, commentEntity) CommentUtils.setCommentTime(holder.commentTimeTv, commentEntity.time) + if (commentEntity.parentUser != null) { + val prefix = "回复" + val colon = " :" + val parentUserName = " ${commentEntity.parentUser?.name} " - if (!TextUtils.isEmpty(mViewModel.videoId)) { - holder.commentContentTv.setTextWithHighlightedTextWrappedInsideWrapper( - text = commentEntity.content ?: "", - copyClickedText = true) + val prefixSpan = SpanBuilder(prefix).color(holder.itemView.context, 0, prefix.length, R.color.text_999999).build() + val parentUserNameSpan = SpanBuilder(parentUserName) + .click(0, parentUserName.length, R.color.text_666666) { + DirectUtils.directToHomeActivity(holder.itemView.context, commentEntity.user.id, 1, mEntrance, "") + }.build() + val colonSpan = SpanBuilder(colon).color(holder.itemView.context, 0, colon.length, R.color.text_999999).build() + val authorSpan = if (commentEntity.parentUser?.me?.isCommentOwner == true) { + SpanBuilder("作者").image(0, "作者".length, R.drawable.ic_hint_author).build() + } else { + "" + } + + holder.commentContentTv.text = SpannableStringBuilder() + .append(prefixSpan) + .append(parentUserNameSpan) + .append(authorSpan) + .append(colonSpan) + .append(commentEntity.content) } else { holder.commentContentTv.text = commentEntity.content } @@ -69,43 +89,6 @@ class NewCommentAdapter(context: Context, return@OnLongClickListener true }) - val parentUser = commentEntity.parentUser - if (parentUser != null && !TextUtils.isEmpty(parentUser.name)) { - holder.quoteContainer.visibility = View.VISIBLE - holder.quoteAuthorTv.text = String.format("@%s", parentUser.name) - - val comment: String? - if (parentUser.active) { - comment = parentUser.comment - holder.quoteContentTv.setTextColor(mContext.resources.getColor(R.color.text_5d5d5d)) - } else { - comment = mContext.getString(R.string.comment_hide_hint) - holder.quoteContentTv.setTextColor(mContext.resources.getColor(R.color.text_d5d5d5)) - } - if (!TextUtils.isEmpty(mViewModel.videoId)) { - holder.quoteContentTv.setTextWithHighlightedTextWrappedInsideWrapper( - text = comment ?: "", - copyClickedText = true) - } else { - holder.quoteContentTv.text = comment - } - } else { - holder.quoteContainer.visibility = View.GONE - } - if (parentUser?.active == true) { - holder.quoteContentTv.setOnLongClickListener(View.OnLongClickListener { - isChildLongClick = true - parentUser.comment?.replace(RatingEditActivity.LABEL_REPLACE_REGEX.toRegex(), "")?.copyTextAndToast() - return@OnLongClickListener true - }) - } - if (parentUser?.badge != null) { - holder.quoteAuthorBadgeSdv.visibility = View.VISIBLE - ImageUtils.display(holder.quoteAuthorBadgeSdv, parentUser.badge!!.icon) - } else { - holder.quoteAuthorBadgeSdv.visibility = View.GONE - } - val key = when (mEntrance) { "(答案详情-评论列表)" -> "回答详情-评论管理" "(文章详情-评论列表)" -> "社区文章详情-评论管理" diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt new file mode 100644 index 0000000000..492b4e543b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt @@ -0,0 +1,74 @@ +package com.gh.gamecenter.qa.dialog + +import android.app.Dialog +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.FragmentTransaction +import com.gh.base.fragment.BaseDialogFragment +import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.DialogChooseForumBinding +import com.gh.gamecenter.entity.CommunityEntity +import com.gh.gamecenter.forum.select.ForumSelectFragment +import com.halo.assistant.HaloApp + +class ChooseForumDialogFragment : BaseDialogFragment() { + private lateinit var binding: DialogChooseForumBinding + var onSelectCallback: ((entity: CommunityEntity) -> Unit)? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = DialogChooseForumBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val beginTransaction = childFragmentManager.beginTransaction() + val forumSelectFragment = childFragmentManager.findFragmentByTag(ForumSelectFragment::class.java.simpleName) as? ForumSelectFragment + ?: ForumSelectFragment() + forumSelectFragment.onSelectCallback = { + onSelectCallback?.invoke(it) + dismissAllowingStateLoss() + } + beginTransaction.replace(binding.container.id, forumSelectFragment, ForumSelectFragment::class.java.simpleName) + beginTransaction.commitAllowingStateLoss() + binding.closeIv.setOnClickListener { dismissAllowingStateLoss() } + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val createDialog = super.onCreateDialog(savedInstanceState) + createDialog.setCanceledOnTouchOutside(true) + + val window = createDialog.window + window?.setGravity(Gravity.BOTTOM) + window?.setWindowAnimations(R.style.community_publication_animation) + return createDialog + } + + override fun onStart() { + super.onStart() + val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels + val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT + dialog?.window?.setLayout(width, height) + } + + + companion object { + fun show(activity: AppCompatActivity, onSelectCallback: ((entity: CommunityEntity) -> Unit)) { + var fragment = activity.supportFragmentManager.findFragmentByTag(ChooseForumDialogFragment::class.java.name) as? ChooseForumDialogFragment + if (fragment == null) { + fragment = ChooseForumDialogFragment() + fragment.onSelectCallback = onSelectCallback + fragment.show(activity.supportFragmentManager, ChooseForumDialogFragment::class.java.name) + } else { + fragment.onSelectCallback = onSelectCallback + val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction() + transaction.show(fragment) + transaction.commit() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/MoreFunctionPanelDialog.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/MoreFunctionPanelDialog.kt new file mode 100644 index 0000000000..e81cf7afa2 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/MoreFunctionPanelDialog.kt @@ -0,0 +1,193 @@ +package com.gh.gamecenter.qa.dialog + +import android.app.Dialog +import android.os.Bundle +import android.view.* +import android.widget.LinearLayout +import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.fragment.app.FragmentTransaction +import com.gh.base.fragment.BaseDialogFragment +import com.gh.common.util.MtaHelper +import com.gh.common.util.ShareUtils +import com.gh.common.util.dip2px +import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.DialogGameDetailMoreBinding +import com.gh.gamecenter.entity.MenuItemEntity +import com.halo.assistant.HaloApp + +class MoreFunctionPanelDialog : BaseDialogFragment(), View.OnTouchListener { + + private lateinit var binding: DialogGameDetailMoreBinding + private lateinit var mGestureDetector: GestureDetector + private var mInitPositionY = 0f + var menuItems: ArrayList = arrayListOf() + var title: String = "" + var shareUrl: String = "" + var shareUtils: ShareUtils? = null + var onItemClickCallback: ((menuItem: MenuItemEntity) -> Unit)? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = DialogGameDetailMoreBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.gameNameTv.text = title + binding.gameNameTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_666666)) + binding.gameIconView.visibility = View.GONE + binding.feedbackTv.visibility = View.GONE + binding.copyrightTv.visibility = View.GONE + mGestureDetector = GestureDetector(requireContext(), SingleTapConfirm()) + binding.dragClose.setOnTouchListener(this) + binding.shareWechatTv.setOnClickListener { + shareUtils?.wechatShare() + MtaHelper.onEvent("内容分享", "微信好友", shareUtils?.title) + } + binding.sharePyquanTv.setOnClickListener { + shareUtils?.wechatMomentsShare() + MtaHelper.onEvent("内容分享", "微信朋友圈", shareUtils?.title) + } + binding.shareQqTv.setOnClickListener { + shareUtils?.qqShare() + MtaHelper.onEvent("内容分享", "QQ好友", shareUtils?.title) + } + binding.shareQqzoneTv.setOnClickListener { + shareUtils?.qZoneShare() + MtaHelper.onEvent("内容分享", "QQ空间", shareUtils?.title) + } + binding.shareWeiboTv.setOnClickListener { + shareUtils?.sinaWeiboShare() + MtaHelper.onEvent("内容分享", "新浪微博", shareUtils?.title) + } + binding.shareSmsTv.setOnClickListener { + shareUtils?.shortMessageShare() + MtaHelper.onEvent("内容分享", "短信", shareUtils?.title) + } + binding.copyLinkTv.setOnClickListener { + shareUtils?.copyLink(shareUrl) + MtaHelper.onEvent("内容分享", "复制链接", shareUtils?.title) + } + binding.cancelTv.setOnClickListener { + dismissAllowingStateLoss() + } + addActionItem() + } + + private fun addActionItem() { + menuItems.forEachIndexed { _, menuItemEntity -> + val itemView = createItemView(menuItemEntity) + itemView.setOnClickListener { + onItemClickCallback?.invoke(menuItemEntity) + dismissAllowingStateLoss() + } + binding.actionContainer.addView(itemView) + } + } + + private fun createItemView(itemEntity: MenuItemEntity): View { + val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) + params.leftMargin = 16f.dip2px() + return TextView(requireContext()).apply { + textSize = 11f + text = itemEntity.text + setTextColor(ContextCompat.getColor(requireContext(), if (itemEntity.isEnable) R.color.text_666666 else R.color.text_999999)) + includeFontPadding = false + gravity = Gravity.CENTER + layoutParams = params + compoundDrawablePadding = 8f.dip2px() + setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(requireContext(), itemEntity.normalIcon), null, null) + } + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val createDialog = super.onCreateDialog(savedInstanceState) + createDialog.setCanceledOnTouchOutside(true) + + val window = createDialog.window + window?.setGravity(Gravity.BOTTOM) + window?.setWindowAnimations(R.style.community_publication_animation) + return createDialog + } + + override fun onTouch(v: View, event: MotionEvent): Boolean { + if (mGestureDetector.onTouchEvent(event) && binding.root.y == 0F) { + v.performClick() + return true + } + when (event.action) { + MotionEvent.ACTION_DOWN -> { + mInitPositionY = binding.root.y - event.rawY + } + MotionEvent.ACTION_MOVE -> { + val offsetY = event.rawY + mInitPositionY + val dialogY = binding.root.y + if (dialogY + offsetY > 0) { + binding.root.animate() + .y(offsetY) + .setDuration(0) + .start() + } else { + resetDialogPosition() + } + } + MotionEvent.ACTION_CANCEL, + MotionEvent.ACTION_UP, + MotionEvent.ACTION_OUTSIDE -> { + if (binding.root.y >= binding.root.height / 2) { + dismissAllowingStateLoss() + } else { + resetDialogPosition(300) + } + } + else -> return false + } + return true + } + + private fun resetDialogPosition(duration: Long = 0) { + binding.root.animate() + .y(0F) + .setDuration(duration) + .start() + } + + override fun onStart() { + super.onStart() + val width = HaloApp.getInstance().application.resources.displayMetrics.widthPixels + val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT + dialog?.window?.setLayout(width, height) + } + + private class SingleTapConfirm : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapUp(event: MotionEvent): Boolean { + return true + } + } + + companion object { + @JvmStatic + fun showMoreDialog(activity: AppCompatActivity, menuItems: ArrayList, title: String, shareUtils: ShareUtils, onItemClickCallback: (menuItem: MenuItemEntity) -> Unit) { + if (menuItems.isNullOrEmpty()) return + var fragment = activity.supportFragmentManager.findFragmentByTag(MoreFunctionPanelDialog::class.java.name) as? MoreFunctionPanelDialog + if (fragment == null) { + fragment = MoreFunctionPanelDialog() + fragment.menuItems = menuItems + fragment.title = title + fragment.shareUtils = shareUtils + fragment.onItemClickCallback = onItemClickCallback + fragment.show(activity.supportFragmentManager, MoreFunctionPanelDialog::class.java.name) + } else { + fragment.menuItems = menuItems + fragment.title = title + fragment.shareUtils = shareUtils + fragment.onItemClickCallback = onItemClickCallback + val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction() + transaction.show(fragment) + transaction.commit() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt index b4dc0764e1..d6c483307c 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/draft/CommunityDraftWrapperActivity.kt @@ -7,6 +7,7 @@ import androidx.fragment.app.Fragment import com.gh.base.BaseActivity_TabLayout import com.gh.gamecenter.qa.article.draft.ArticleDraftFragment import com.gh.gamecenter.qa.answer.draft.AnswerDraftFragment +import com.gh.gamecenter.qa.questions.draft.QuestionDraftFragment class CommunityDraftWrapperActivity : BaseActivity_TabLayout() { @@ -16,13 +17,13 @@ class CommunityDraftWrapperActivity : BaseActivity_TabLayout() { } override fun initFragmentList(fragments: MutableList) { - fragments.add(AnswerDraftFragment()) fragments.add(ArticleDraftFragment()) + fragments.add(QuestionDraftFragment()) } override fun initTabTitleList(tabTitleList: MutableList) { - tabTitleList.add("回答草稿") tabTitleList.add("帖子草稿") + tabTitleList.add("问题草稿") } companion object { diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt index ed85877375..2394e6536a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerFragment.kt @@ -1,14 +1,38 @@ package com.gh.gamecenter.qa.editor +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView.ItemDecoration +import com.gh.common.util.viewModelProvider +import com.gh.common.view.CustomDividerItemDecoration +import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment import com.gh.gamecenter.qa.entity.AnswerEntity class AnswerFragment : ListFragment() { private var mAdapter: AnswerAdapter? = null + private var mAnswerType: InsertAnswerWrapperActivity.AnswerType = InsertAnswerWrapperActivity.AnswerType.MINE_ANSWER + + override fun onCreate(savedInstanceState: Bundle?) { + mAnswerType = arguments?.getSerializable(InsertAnswerWrapperActivity.KEY_ANSWER_TYPE) as InsertAnswerWrapperActivity.AnswerType + super.onCreate(savedInstanceState) + } + + override fun provideListViewModel(): AnswerViewModel { + return viewModelProvider(AnswerViewModel.Factory(mAnswerType)) + } override fun provideListAdapter(): AnswerAdapter { if (mAdapter == null) mAdapter = AnswerAdapter(requireContext(), mEntrance) return mAdapter!! } + + override fun getItemDecoration(): ItemDecoration? { + val insetDivider = ContextCompat.getDrawable(requireContext(), R.drawable.divider_item_line) + val itemDecoration = CustomDividerItemDecoration(requireContext(), notDecorateTheLastItem = true) + itemDecoration.setDrawable(insetDivider!!) + return itemDecoration + } + } diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt index d58b92526a..640d2b2139 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/AnswerViewModel.kt @@ -2,16 +2,29 @@ package com.gh.gamecenter.qa.editor import android.app.Application import androidx.annotation.Keep +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.entity.UserEntity 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 com.lightgame.utils.Utils import io.reactivex.Observable @Keep -class AnswerViewModel(application: Application) : ListViewModel(application) { +class AnswerViewModel(application: Application, private val answerType: InsertAnswerWrapperActivity.AnswerType) : ListViewModel(application) { + + override fun provideDataObservable(page: Int): Observable> { - return RetrofitManager.getInstance(getApplication()).api.getCollectionAnswer(UserManager.getInstance().userId, page) + + return if (answerType == InsertAnswerWrapperActivity.AnswerType.MINE_ANSWER) { + RetrofitManager.getInstance(getApplication()).api.getMyAnswers(UserManager.getInstance().userId, page, + HaloApp.getInstance().channel, Utils.getTime(getApplication())) + } else { + RetrofitManager.getInstance(getApplication()).api.getCollectionAnswer(UserManager.getInstance().userId, page) + } } override fun mergeResultLiveData() { @@ -28,6 +41,20 @@ class AnswerViewModel(application: Application) : ListViewModel create(modelClass: Class): T { + return AnswerViewModel(HaloApp.getInstance().application, answerType) as T + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt index d09f452741..db2ab8784a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleFragment.kt @@ -1,14 +1,37 @@ package com.gh.gamecenter.qa.editor +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import com.gh.common.util.viewModelProvider +import com.gh.common.view.CustomDividerItemDecoration +import com.gh.gamecenter.R import com.gh.gamecenter.baselist.ListFragment import com.gh.gamecenter.qa.entity.ArticleEntity class ArticleFragment : ListFragment() { private var mAdapter: ArticleAdapter? = null + private var mArticleType: InsertArticleWrapperActivity.ArticleType = InsertArticleWrapperActivity.ArticleType.MINE_ARTICLE + + override fun onCreate(savedInstanceState: Bundle?) { + mArticleType = arguments?.getSerializable(InsertArticleWrapperActivity.KEY_ARTICLE_TYPE) as InsertArticleWrapperActivity.ArticleType + super.onCreate(savedInstanceState) + } + + override fun provideListViewModel(): ArticleViewModel { + return viewModelProvider(ArticleViewModel.Factory(mArticleType)) + } override fun provideListAdapter(): ArticleAdapter { - if (mAdapter == null) mAdapter = ArticleAdapter(context!!, mEntrance) + if (mAdapter == null) mAdapter = ArticleAdapter(requireContext(), mEntrance) return mAdapter!! } + + override fun getItemDecoration(): RecyclerView.ItemDecoration? { + val insetDivider = ContextCompat.getDrawable(requireContext(), R.drawable.divider_item_line) + val itemDecoration = CustomDividerItemDecoration(requireContext(), notDecorateTheLastItem = true) + itemDecoration.setDrawable(insetDivider!!) + return itemDecoration + } } diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt index d0346d0927..e6bd143144 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/ArticleViewModel.kt @@ -2,17 +2,25 @@ package com.gh.gamecenter.qa.editor import android.app.Application import androidx.annotation.Keep +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.entity.UserEntity import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.qa.entity.ArticleEntity import com.gh.gamecenter.retrofit.RetrofitManager +import com.halo.assistant.HaloApp import io.reactivex.Observable @Keep -class ArticleViewModel(application: Application) : ListViewModel(application) { +class ArticleViewModel(application: Application, private val articleType: InsertArticleWrapperActivity.ArticleType) : ListViewModel(application) { override fun provideDataObservable(page: Int): Observable> { - return RetrofitManager.getInstance(getApplication()).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page) + return if (articleType == InsertArticleWrapperActivity.ArticleType.MINE_ARTICLE) { + RetrofitManager.getInstance(HaloApp.getInstance().application).api.getMyArticle(UserManager.getInstance().userId, page) + } else { + RetrofitManager.getInstance(getApplication()).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page) + } } override fun mergeResultLiveData() { @@ -29,7 +37,21 @@ class ArticleViewModel(application: Application) : ListViewModel create(modelClass: Class): T { + return ArticleViewModel(HaloApp.getInstance().application, articleType) as T + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt index 34b8de4b63..05ebef7ec4 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertAnswerWrapperActivity.kt @@ -3,37 +3,35 @@ package com.gh.gamecenter.qa.editor import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import com.gh.base.BaseActivity_TabLayout +import com.gh.gamecenter.R class InsertAnswerWrapperActivity : BaseActivity_TabLayout() { - private lateinit var mFragment: LinkFragment - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setNavigationTitle("插入回答") - } + override fun getLayoutId(): Int = R.layout.activity_tablayout_no_title_viewpager override fun initFragmentList(fragments: MutableList?) { - mFragment = LinkFragment() - fragments?.add(mFragment) - fragments?.add(AnswerFragment()) + fragments?.add(AnswerFragment().with(bundleOf(KEY_ANSWER_TYPE to AnswerType.MINE_ANSWER))) + fragments?.add(AnswerFragment().with(bundleOf(KEY_ANSWER_TYPE to AnswerType.COLLECTION_ANSWER))) } override fun initTabTitleList(tabTitleList: MutableList?) { - tabTitleList?.add("输入链接") + tabTitleList?.add("我的回答") tabTitleList?.add("收藏回答") } - override fun onPageSelected(position: Int) { - super.onPageSelected(position) - mFragment.onPageChanged(position) - } - companion object { + const val KEY_ANSWER_TYPE = "AnswerType" + fun getIntent(context: Context): Intent { return Intent(context, InsertAnswerWrapperActivity::class.java) } } + + enum class AnswerType { + MINE_ANSWER, + COLLECTION_ANSWER + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt index 6a7af842fa..44cfdce631 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/InsertArticleWrapperActivity.kt @@ -3,37 +3,36 @@ package com.gh.gamecenter.qa.editor import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import com.gh.base.BaseActivity_TabLayout +import com.gh.gamecenter.R class InsertArticleWrapperActivity : BaseActivity_TabLayout() { - private lateinit var mFragment: LinkFragment + override fun getLayoutId(): Int = R.layout.activity_tablayout_no_title_viewpager - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setNavigationTitle("插入帖子") - } - - override fun initFragmentList(fragments: MutableList?) { - mFragment = LinkFragment() - fragments?.add(mFragment) - fragments?.add(ArticleFragment()) + override fun initFragmentList(fragments: MutableList?) { + fragments?.add(ArticleFragment().with(bundleOf(KEY_ARTICLE_TYPE to ArticleType.MINE_ARTICLE))) + fragments?.add(ArticleFragment().with(bundleOf(KEY_ARTICLE_TYPE to ArticleType.COLLECTION_ARTICLE))) } override fun initTabTitleList(tabTitleList: MutableList?) { - tabTitleList?.add("输入链接") + tabTitleList?.add("我的帖子") tabTitleList?.add("收藏帖子") } - override fun onPageSelected(position: Int) { - super.onPageSelected(position) - mFragment.onPageChanged(position) - } companion object { + const val KEY_ARTICLE_TYPE = "ArticleType" + fun getIntent(context: Context): Intent { return Intent(context, InsertArticleWrapperActivity::class.java) } } + + enum class ArticleType { + MINE_ARTICLE, + COLLECTION_ARTICLE + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt b/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt index 07528712e4..09361c5e1a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/entity/AnswerEntity.kt @@ -40,6 +40,7 @@ class AnswerEntity() : Parcelable { @SerializedName("sequence_id") var sequenceId: String? = null + @SerializedName("brief", alternate = ["content"]) var brief: String? = null @SerializedName("title") @@ -108,6 +109,10 @@ class AnswerEntity() : Parcelable { @Ignore var description: String? = "" + @Ignore + @SerializedName("popular_answer") + var popularAnswer: AnswerEntity? = null + fun getPassVideos(): List { val passVideos = arrayListOf() for (video in videos) { diff --git a/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionDraftEntity.kt b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionDraftEntity.kt new file mode 100644 index 0000000000..12c7439724 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionDraftEntity.kt @@ -0,0 +1,20 @@ +package com.gh.gamecenter.qa.entity + +import android.os.Parcelable +import com.gh.gamecenter.entity.CommunityEntity +import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class QuestionDraftEntity( + @SerializedName("_id") + var id: String = "", + @SerializedName("community_id") + var communityId:String="", + var bbs: CommunityEntity? = null, + var title: String = "", + var description: String = "", + var images: ArrayList = arrayListOf(), + var videos: ArrayList = arrayListOf(), + var tags: List = arrayListOf() +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt index 4cbceaa194..9964c94d11 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/entity/QuestionsDetailEntity.kt @@ -29,7 +29,11 @@ data class QuestionsDetailEntity(var id: String? = null, var me: MeEntity = MeEntity(), @SerializedName("follow_count") private var followCount: Int = 0, - var user: UserEntity = UserEntity()) : Parcelable { + var user: UserEntity = UserEntity(), + //提交问题用 + @SerializedName("draft_id") + var draftId: String = "" +) : Parcelable { fun getFollowCount(): Int { return if (followCount == 0) 1 else { diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java index 7aa2d3edf7..fcd491ca7a 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/AnswerViewHolder.java @@ -127,10 +127,10 @@ public class AnswerViewHolder extends BaseRecyclerViewHolder { mContent.setText(entity.getBrief()); mQuestionTitle.setVisibility(View.VISIBLE); mQuestionTitle.setText(entity.getQuestions().getTitle()); - mVotecount.setText(mVotecount.getContext().getString(R.string.ask_vote_count, NumberUtils.transSimpleCount(entity.getVote()))); - // 3.6.3 产品说把右下角的社区名字换成时间, 评论隐藏掉 + String commentText = String.format("%s评论 · %s点赞 · %s", NumberUtils.transSimpleCount(entity.getCommentCount()), NumberUtils.transSimpleCount(entity.getVote()), NewsUtils.getFormattedTime(entity.getTime())); + mVotecount.setText(commentText); mCommunityName.setVisibility(View.VISIBLE); - mCommunityName.setText(NewsUtils.getFormattedTime(entity.getTime())); + mCommunityName.setText(entity.getCommunityName()); mCommentCount.setVisibility(View.GONE); // mCommentCount.setText(String.format("%s 评论", NumberUtils.transSimpleCount(entity.getCommentCount()))); // mCommunityName.setText(entity.getCommunityName()); diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt index ad7cbd6075..f54168b096 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/detail/QuestionsDetailFragment.kt @@ -4,7 +4,6 @@ import android.app.Activity import android.app.Dialog import android.content.Intent import android.graphics.Color -import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.os.Parcelable import android.text.TextUtils @@ -14,15 +13,14 @@ import android.view.View import android.view.Window import android.widget.ImageView import android.widget.LinearLayout -import android.widget.PopupWindow import android.widget.TextView +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.RecyclerView import butterknife.BindView import com.ethanhua.skeleton.Skeleton -import com.gh.base.ToolBarActivity import com.gh.base.fragment.BaseDialogWrapperFragment import com.gh.base.fragment.BaseFragment import com.gh.common.TimeElapsedHelper @@ -46,6 +44,7 @@ import com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.qa.answer.fold.AnswerFoldActivity +import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog import com.gh.gamecenter.qa.entity.AnswerDraftEntity import com.gh.gamecenter.qa.entity.Questions import com.gh.gamecenter.qa.entity.QuestionsDetailEntity @@ -418,88 +417,55 @@ class QuestionsDetailFragment : private fun showMoreItemDialog() { if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { mQuestionsDetailEntity?.let { questionEntity -> - val view = LayoutInflater.from(context).inflate(R.layout.menu_answer_detail_more_new, null) - val popupWindow = PopupWindow( - view, - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - popupWindow.apply { - setBackgroundDrawable(ColorDrawable(0)) - isTouchable = true - isFocusable = true - isOutsideTouchable = true - } - view.measure(0, 0) - val viewWidth = view.measuredWidth - popupWindow.showAsDropDown((activity as ToolBarActivity).menu.getItem(2).actionView, -viewWidth - 10, 10) - val container = view.findViewById(R.id.container) val entities = ArrayList() - entities.add(MenuItemEntity("首页", R.drawable.menu_more_home)) if (questionEntity.user.id != UserManager.getInstance().userId) { - entities.add(MenuItemEntity("投诉", R.drawable.ic_menu_gamedetail_feedback)) + entities.add(MenuItemEntity("投诉", R.drawable.icon_gamedetail_copyright)) } if (questionEntity.me.isModerator) { - entities.add(MenuItemEntity("编辑", R.drawable.menu_more_edit)) + entities.add(MenuItemEntity("编辑", R.drawable.icon_more_panel_edit)) } - entities.add(MenuItemEntity("分享", R.drawable.icon_share_gray)) if (questionEntity.me.isModerator || questionEntity.user.id == UserManager.getInstance().userId) { - entities.add(MenuItemEntity("删除", R.drawable.menu_more_delete)) + entities.add(MenuItemEntity("删除", R.drawable.icon_more_panel_delete)) } + val shareIcon = if (questionEntity.images.isNotEmpty()) { + questionEntity.images[0] + } else { + getString(R.string.share_ghzs_logo) + } + var description = questionEntity.description + if (TextUtils.isEmpty(description)) { + description = getString(R.string.ask_share_default_summary) + } + val shareUrl = if (isPublishEnv()) { + getString(R.string.share_questions_url, questionEntity.id) + } else { + getString(R.string.share_questions_url_dev, questionEntity.id) + } + val shareUtils = ShareUtils.getInstance(activity) + shareUtils.shareParamsDetail( + activity, + shareUrl, + shareIcon, + getString(R.string.ask_share_questions_title, questionEntity.title, questionEntity.answersCount), + description, + ShareUtils.ShareEntrance.askNormal, + questionEntity.id, null) + MoreFunctionPanelDialog.showMoreDialog(requireActivity() as AppCompatActivity, entities, questionEntity.title + ?: "",shareUtils) { + when (it.text) { + "投诉" -> { + SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", + "问题投诉(" + questionEntity.id + "):") + } + "编辑" -> { + val intent = QuestionEditActivity.getManagerIntent(requireContext(), mQuestionsDetailEntity!!) + startActivityForResult(intent, QUESTIONS_EDIT_REQUEST) + } - entities.forEachIndexed { index, item -> - val menuItem = createMenuItem(index, item) - container.addView(menuItem) - menuItem.setOnClickListener { - popupWindow.dismiss() - when (item.text) { - "首页" -> { - DirectUtils.directToCommunity(requireContext(), questionEntity.community) - MtaHelper.onEvent("回到首页", "问题详情", questionEntity.community.name + "+" + StringUtils.combineTwoString(questionEntity.title, questionEntity.id)) - } - "投诉" -> { - SuggestionActivity.startSuggestionActivity(context, SuggestType.normal, "report", - "问题投诉(" + questionEntity.id + "):") - } - "编辑" -> { - val intent = QuestionEditActivity.getManagerIntent(requireContext(), mQuestionsDetailEntity!!) - startActivityForResult(intent, QUESTIONS_EDIT_REQUEST) - } - "分享" -> { -// GdtHelper.logAction(ActionType.SHARE, -// GdtHelper.CONTENT_TYPE, "QUESTION", -// GdtHelper.CONTENT_ID, mQuestionsId) - - popupWindow.dismiss() - val shareIcon = if (questionEntity.images.isNotEmpty()) { - questionEntity.images[0] - } else { - getString(R.string.share_ghzs_logo) - } - var description = questionEntity.description - if (TextUtils.isEmpty(description)) { - description = getString(R.string.ask_share_default_summary) - } - val shareUrl = if (isPublishEnv()) { - getString(R.string.share_questions_url, questionEntity.id) - } else { - getString(R.string.share_questions_url_dev, questionEntity.id) - } - ShareUtils.getInstance(activity).showShareWindows( - activity, - view, - shareUrl, - shareIcon, - getString(R.string.ask_share_questions_title, questionEntity.title, questionEntity.answersCount), - description, - ShareUtils.ShareEntrance.askNormal, - questionEntity.id) - } - "删除" -> { - DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除问题后,其中的所有回答都将被删除", "取消", "删除", {}, { - mListViewModel.moderatorsHideQuestion() - }) - } + "删除" -> { + DialogUtils.showNewAlertDialog(requireContext(), "提示", "删除问题后,其中的所有回答都将被删除", "取消", "删除", {}, { + mListViewModel.moderatorsHideQuestion() + }) } } } diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftActivity.kt new file mode 100644 index 0000000000..349eee17ab --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftActivity.kt @@ -0,0 +1,17 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.gh.common.util.EntranceUtils +import com.gh.gamecenter.NormalActivity + +class QuestionDraftActivity : NormalActivity() { + + companion object { + fun getIntent(context: Context): Intent { + val bundle = Bundle() + return getTargetIntent(context, QuestionDraftActivity::class.java, QuestionDraftFragment::class.java, bundle) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftAdapter.kt new file mode 100644 index 0000000000..7cd8821a95 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftAdapter.kt @@ -0,0 +1,71 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.content.Context +import android.text.TextUtils +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.gh.base.BaseRecyclerViewHolder +import com.gh.common.constant.ItemViewType +import com.gh.common.util.DialogUtils +import com.gh.gamecenter.R +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder +import com.gh.gamecenter.baselist.ListAdapter +import com.gh.gamecenter.databinding.CommunityQuestionDraftItemBinding +import com.gh.gamecenter.qa.entity.QuestionDraftEntity + +class QuestionDraftAdapter(val context: Context, val mViewModel: QuestionDraftViewModel?,private val selectCallback: (QuestionDraftEntity) -> Unit) : ListAdapter(context) { + + override fun areItemsTheSame(oldItem: QuestionDraftEntity, newItem: QuestionDraftEntity): Boolean { + return !TextUtils.isEmpty(oldItem.id) && oldItem.id == newItem.id + } + + override fun areContentsTheSame(oldItem: QuestionDraftEntity, newItem: QuestionDraftEntity): Boolean { + return oldItem == newItem + } + + override fun getItemViewType(position: Int): Int { + return if (position == itemCount - 1) { + ItemViewType.ITEM_FOOTER + } else 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_question_draft_item, parent, false) + QuestionDraftViewHolder(CommunityQuestionDraftItemBinding.bind(view)) + } + } + } + + override fun getItemCount(): Int { + return if (mEntityList == null || mEntityList.isEmpty()) 0 else mEntityList.size + FOOTER_ITEM_COUNT + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is QuestionDraftViewHolder) { + val entity = mEntityList[position] + holder.binding.data = entity + holder.binding.articleDraftDelete.setOnClickListener { + DialogUtils.showAlertDialog(mContext, "警告", "确定要删除问题草稿吗?删除之后不可恢复", + "确定", "取消", DialogUtils.ConfirmListener { + mViewModel?.deleteDraft(entity.id) + }, null) + } + holder.itemView.setOnClickListener { + selectCallback.invoke(entity) + } + } else if (holder is FooterViewHolder) { + holder.initItemPadding() + holder.initFooterViewHolder(mIsLoading, isNetworkError, mIsOver, R.string.ask_loadover_hint) + } + } + + class QuestionDraftViewHolder(val binding: CommunityQuestionDraftItemBinding) : BaseRecyclerViewHolder(binding.root) +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftFragment.kt new file mode 100644 index 0000000000..1921561f7a --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftFragment.kt @@ -0,0 +1,94 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.RecyclerView +import com.gh.common.util.ToastUtils +import com.gh.common.util.checkStoragePermissionBeforeAction +import com.gh.common.util.viewModelProvider +import com.gh.common.view.CustomDividerItemDecoration +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.EBReuse +import com.gh.gamecenter.qa.article.edit.ArticleEditActivity +import com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity +import com.gh.gamecenter.qa.entity.ArticleDetailEntity +import com.gh.gamecenter.qa.entity.ArticleDraftEntity +import com.gh.gamecenter.qa.entity.QuestionDraftEntity +import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity +import org.greenrobot.eventbus.Subscribe +import org.greenrobot.eventbus.ThreadMode + +class QuestionDraftFragment : ListFragment() { + + var mAdapter: QuestionDraftAdapter? = null + lateinit var mViewModel: QuestionDraftViewModel + + override fun provideListAdapter(): ListAdapter<*> { + return mAdapter ?: QuestionDraftAdapter(requireContext(), mViewModel) { + if (activity is CommunityDraftWrapperActivity) { + checkStoragePermissionBeforeAction { + val intent = QuestionEditActivity.getDraftIntent(requireContext(), it) + startActivity(intent) + } + } else { + checkStoragePermissionBeforeAction { + val intent = Intent() + intent.putExtra(QuestionDraftEntity::class.java.simpleName, it) + requireActivity().setResult(Activity.RESULT_OK, intent) + requireActivity().finish() + } + } + }.apply { + mAdapter = this + } + } + + override fun provideListViewModel(): QuestionDraftViewModel { + mViewModel = viewModelProvider() + return mViewModel + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (activity is QuestionDraftActivity) { + setNavigationTitle("问题草稿") + } + mViewModel.deleteDraftSuccess.observe(this, Observer { pair -> + if (pair.second) { + val draftId = pair.first + val index = mAdapter?.entityList?.indexOfFirst { it.id == draftId } ?: -1 + if (index >= 0) { + mAdapter?.entityList?.removeAt(index) + if (mAdapter?.entityList.isNullOrEmpty()) { + mListViewModel.load(LoadType.REFRESH) + } else { + mAdapter?.notifyItemRemoved(index) + } + + ToastUtils.showToast("删除成功") + } + + } + }) + } + + override fun getItemDecoration(): RecyclerView.ItemDecoration? { + val insetDivider = ContextCompat.getDrawable(requireContext(), R.drawable.divider_item_line_space_16) + val itemDecoration = CustomDividerItemDecoration(requireContext(), notDecorateTheLastItem = true) + itemDecoration.setDrawable(insetDivider!!) + return itemDecoration + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onEventMainThread(reuse: EBReuse) { + if (QuestionEditActivity.QUESTION_DRAFT_CHANGE_TAG == reuse.type) { + mBaseHandler.postDelayed({ mListViewModel.load(LoadType.REFRESH) }, 100) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftViewModel.kt new file mode 100644 index 0000000000..6b720870cf --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/draft/QuestionDraftViewModel.kt @@ -0,0 +1,46 @@ +package com.gh.gamecenter.qa.questions.draft + +import android.annotation.SuppressLint +import android.app.Application +import androidx.lifecycle.MutableLiveData +import com.gh.common.util.observableToMain +import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.manager.UserManager +import com.gh.gamecenter.qa.entity.QuestionDraftEntity +import com.gh.gamecenter.retrofit.Response +import com.gh.gamecenter.retrofit.RetrofitManager +import com.halo.assistant.HaloApp +import io.reactivex.Observable +import okhttp3.ResponseBody +import retrofit2.HttpException + +class QuestionDraftViewModel(application: Application) : ListViewModel(application) { + val deleteDraftSuccess = MutableLiveData>() + private val api = RetrofitManager.getInstance(HaloApp.getInstance().application).api + + override fun provideDataObservable(page: Int): Observable> { + return api.getQuestionDrafts(UserManager.getInstance().userId) + } + + override fun mergeResultLiveData() { + mResultLiveData.addSource(mListLiveData) { mResultLiveData.postValue(it) } + } + + @SuppressLint("CheckResult") + fun deleteDraft(draftId: String) { + api.deleteQuestionDraft(UserManager.getInstance().userId, draftId) + .compose(observableToMain()) + .subscribe(object :Response(){ + override fun onResponse(response: ResponseBody?) { + super.onResponse(response) + deleteDraftSuccess.postValue(Pair(draftId, true)) + } + + override fun onFailure(e: HttpException?) { + super.onFailure(e) + deleteDraftSuccess.postValue(Pair(draftId, false)) + } + }) + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt index e8a6f3a2f8..9d56d6a714 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditActivity.kt @@ -9,24 +9,18 @@ import android.graphics.Color import android.graphics.LinearGradient import android.graphics.Shader import android.os.Bundle +import android.os.Message import android.text.Editable +import android.text.TextUtils import android.text.TextWatcher -import android.view.KeyEvent -import android.view.MenuItem -import android.view.View -import android.view.Window +import android.view.* import android.widget.EditText -import android.widget.ProgressBar -import android.widget.RelativeLayout import androidx.core.content.ContextCompat import androidx.core.widget.addTextChangedListener import androidx.databinding.DataBindingUtil import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders -import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.gh.base.ToolBarActivity -import com.gh.base.fragment.BaseDialogWrapperFragment import com.gh.base.fragment.WaitingDialogFragment import com.gh.common.AppExecutor import com.gh.common.util.* @@ -39,16 +33,23 @@ import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.MyVideoEntity import com.gh.gamecenter.entity.NotificationUgc import com.gh.gamecenter.entity.Permissions +import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.mvvm.Status -import com.gh.gamecenter.qa.article.edit.ArticleSelectGameAdapter -import com.gh.gamecenter.qa.article.edit.ArticleTagsSelectFragment +import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity +import com.gh.gamecenter.qa.article.draft.ArticleDraftActivity +import com.gh.gamecenter.qa.article.edit.ArticleEditActivity +import com.gh.gamecenter.qa.dialog.ChooseForumDialogFragment import com.gh.gamecenter.qa.editor.VideoActivity import com.gh.gamecenter.qa.entity.CommunityVideoEntity +import com.gh.gamecenter.qa.entity.QuestionDraftEntity import com.gh.gamecenter.qa.entity.QuestionsDetailEntity +import com.gh.gamecenter.qa.questions.draft.QuestionDraftActivity import com.gh.gamecenter.qa.questions.edit.pic.QuestionsEditPicAdapter import com.gh.gamecenter.qa.questions.edit.tip.QuestionTitleTipAdapter import com.lightgame.utils.Util_System_Keyboard +import com.lightgame.utils.Utils import com.zhihu.matisse.Matisse +import org.greenrobot.eventbus.EventBus import org.json.JSONObject import kotlin.math.abs @@ -65,10 +66,12 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { private var mUploadImageCancelDialog: Dialog? = null private var mKeyboardHeightProvider: KeyboardHeightProvider? = null private lateinit var picAdapter: QuestionsEditPicAdapter + private lateinit var mMenuDraft: MenuItem private lateinit var mMenuPost: MenuItem private var mIsExtendedKeyboardShow = false private var mOffset = 0 private var mTagsSelectFragment: TagsSelectFragment? = null + private var mPostDraftsCount: Int = 0 private val mSaveTitleKey = "title" private val mSaveContentKey = "content" @@ -95,6 +98,25 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { duration = RichEditor.formatVideoDuration(videoEntity.length), status = videoEntity.status)) } + } else if (requestCode == QUESTION_DRAFT_REQUEST_CODE && resultCode == RESULT_OK) { + val draftEntity = data?.getParcelableExtra(QuestionDraftEntity::class.java.simpleName) + if (draftEntity != null) { + mViewModel.questionDraftEntity = draftEntity + setQuestionDraft(draftEntity) + mViewModel.getQuestionDraftContent(draftEntity.id) + } + } + } + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + if (msg.what == 1) { + if (mViewModel.communityEntity != null + && !mViewModel.title.isNullOrEmpty() + && !mViewModel.content.isNullOrEmpty()) { + mViewModel.saveQuestionDraft(SaveDraftType.AUTO) + } + mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) } } @@ -103,6 +125,7 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { setToolbarMenu(R.menu.menu_question_post) mToolbar.navigationIcon = null + mMenuDraft = mToolbar.menu.findItem(R.id.menu_draft) mMenuPost = mToolbar.menu.findItem(R.id.menu_question_post) mViewModel = ViewModelProviders.of(this).get(QuestionEditViewModel::class.java) if (savedInstanceState != null) { @@ -126,25 +149,25 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { if (intent != null) { val communityEntity = intent.getParcelableExtra(CommunityEntity::class.java.simpleName) val detailEntity = intent.getParcelableExtra(QuestionsDetailEntity::class.java.simpleName) - if (detailEntity != null) { // 问题编辑 - mViewModel.questionEntity = detailEntity - mViewModel.communityEntity = detailEntity.community - mViewModel.communityEntity?.icon = detailEntity.community.game?.getIcon() - mViewModel.communityEntity?.iconSubscript = detailEntity.community.game?.iconSubscript - setForumName() - mViewModel.content = detailEntity.description - mViewModel.picList.postValue(ArrayList(detailEntity.images)) - mViewModel.isModeratorPatch = intent.getBooleanExtra(EntranceUtils.KEY_QUESTION_MODERATOR_PATCH, false) - val videos = detailEntity.videos - if (videos.isNotEmpty()) mViewModel.videoLiveData.postValue(detailEntity.videos[0]) - if (mViewModel.title.isNullOrEmpty()) mViewModel.title = detailEntity.title - } else { // 新增问题 - var searchKey = intent.getStringExtra(EntranceUtils.KEY_QUESTIONS_SEARCH_KEY) - if (!searchKey.isNullOrEmpty() && searchKey.length > QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) - searchKey = searchKey.substring(0, QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) - if (mViewModel.title.isNullOrEmpty()) mViewModel.title = searchKey - mViewModel.isFromSearch = intent.getBooleanExtra(QuestionEditViewModel.QUESTION_FORM_SEARCH, false) - if (communityEntity == null) showSelectGameDialog() + val draftEntity = intent.getParcelableExtra(QuestionDraftEntity::class.java.simpleName) + when { + detailEntity != null -> { // 问题编辑 + setPatchContent(detailEntity) + } + draftEntity != null -> { //草稿编辑 + mViewModel.questionDraftEntity = draftEntity + setQuestionDraft(draftEntity) + mViewModel.getQuestionDraftContent(draftEntity.id) + mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) + } + else -> { // 新增问题 + var searchKey = intent.getStringExtra(EntranceUtils.KEY_QUESTIONS_SEARCH_KEY) + if (!searchKey.isNullOrEmpty() && searchKey.length > QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) + searchKey = searchKey.substring(0, QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH) + if (mViewModel.title.isNullOrEmpty()) mViewModel.title = searchKey + mViewModel.isFromSearch = intent.getBooleanExtra(QuestionEditViewModel.QUESTION_FORM_SEARCH, false) + mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong()) + } } if (communityEntity != null) { @@ -152,7 +175,6 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { setForumName() mBinding.chooseForumTv.isEnabled = false mBinding.chooseForumTv.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) - if (!mViewModel.isFromSearch) mViewModel.checkQuestionDraft() } } @@ -195,6 +217,7 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { mBinding.questionseditContent.filters = arrayOf(TextHelper.getFilter(300, "内容最多300个字")) mBinding.questionseditContent.addTextChangedListener { mBinding.editorTextNumTv.text = "${mBinding.questionseditContent.text.length}/300" + checkPostButtonEnable() } mBinding.questionseditContent.setOnTouchListener { v, event -> closeExtendedKeyboard() @@ -229,10 +252,42 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { mBinding.suggestPicRv.addItemDecoration(SpacingItemDecoration(bottom = DisplayUtils.dip2px(10f))) mBinding.suggestPicRv.adapter = picAdapter initEditorInsertContainer() - + // 增加提问时, 如果searchKey不为空 光标跳到最后 + mBaseHandler.postDelayed({ + mBinding.questionseditTitle.setSelection(mBinding.questionseditTitle.text.toString().length) + }, 50) observeData() } + private fun setPatchContent(detailEntity: QuestionsDetailEntity) { + mMenuDraft.isVisible = false + mViewModel.questionEntity = detailEntity + mViewModel.communityEntity = detailEntity.community + mViewModel.communityEntity?.icon = detailEntity.community.game?.getIcon() + mViewModel.communityEntity?.iconSubscript = detailEntity.community.game?.iconSubscript + mViewModel.content = detailEntity.description + mViewModel.picList.postValue(ArrayList(detailEntity.images)) + mViewModel.isModeratorPatch = intent.getBooleanExtra(EntranceUtils.KEY_QUESTION_MODERATOR_PATCH, false) + val videos = detailEntity.videos + if (videos.isNotEmpty()) mViewModel.videoLiveData.postValue(detailEntity.videos[0]) + if (mViewModel.title.isNullOrEmpty()) mViewModel.title = detailEntity.title + setForumName() + } + + private fun setQuestionDraft(draftEntity: QuestionDraftEntity) { + mViewModel.communityEntity = draftEntity.bbs + mViewModel.communityEntity?.icon = draftEntity.bbs?.game?.getIcon() + mViewModel.communityEntity?.iconSubscript = draftEntity.bbs?.game?.iconSubscript + mViewModel.title = draftEntity.title + mViewModel.content = draftEntity.description + mViewModel.picList.postValue(draftEntity.images) + val videos = draftEntity.videos + if (videos.isNotEmpty()) mViewModel.videoLiveData.postValue(videos[0]) + mBinding.questionseditTitle.setText(mViewModel.title) + mBinding.questionseditContent.setText(mViewModel.content) + setForumName() + } + private fun observeData() { mViewModel.moderatorPostLiveData.observe(this, Observer { if (it?.status == Status.SUCCESS) { @@ -266,6 +321,41 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { toast(R.string.post_failure_hint) } }) + mViewModel.postQuestionDrafts.observe(this, Observer { pair -> + if (pair != null) { + when (pair.first) { + SaveDraftType.EXIT -> { + if (pair.second) { + Utils.toast(this, "问题已保存到草稿箱") + EventBus.getDefault().post(EBReuse(ArticleEditActivity.ARTICLE_DRAFT_CHANGE_TAG)) + finish() + } + } + SaveDraftType.AUTO -> { + if (pair.second) { + if (mPostDraftsCount >= AnswerEditActivity.SAVE_DRAFTS_TOAST_COUNT) { + mPostDraftsCount = 0 + Utils.toast(this, "问题已保存到草稿箱") + } else { + mPostDraftsCount++ + } + } + } + SaveDraftType.SKIP -> { + if (pair.second) { + Utils.toast(this, "问题已保存到草稿箱") + startActivityForResult(ArticleDraftActivity.getIntent(this), ArticleEditActivity.ARTICLE_DRAFT_REQUEST_CODE) + } else { + Utils.toast(this, "问题草稿保存失败") + } + } + } + } + }) + mViewModel.questionDraftsContent.observe(this, Observer { + mViewModel.questionDraftEntity = it + setQuestionDraft(it) + }) // Process dialog mViewModel.processDialog.observe(this, Observer { it -> @@ -327,10 +417,9 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { picAdapter.notifyDataSetChanged() }) - // 增加提问时, 如果searchKey不为空 光标跳到最后 - mBaseHandler.postDelayed({ - mBinding.questionseditTitle.setSelection(mBinding.questionseditTitle.text.toString().length) - }, 50) + mViewModel.notSelectForum.observe(this, Observer { + if (it) showSelectGameDialog() + }) } private fun changeAddLabel(isLabelContainerShow: Boolean) { @@ -417,23 +506,30 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { } override fun onMenuItemClick(menuItem: MenuItem?): Boolean { - if (mViewModel.isModeratorPatch) { - if (checkSameFromQuestionData()) { - toast("内容没有变化") + if (menuItem?.itemId == R.id.menu_question_post) { + if (mViewModel.isModeratorPatch) { + if (checkSameFromQuestionData()) { + toast("内容没有变化") + } else { + mViewModel.selectedTags.addAll(mViewModel.questionEntity?.tags!!) + DialogUtils.showAlertDialog(this, "修改问题", + if (mViewModel.questionEntity!!.me.moderatorPermissions.updateQuestion == Permissions.REPORTER) + "你的操作将提交给小编审核,确定提交吗?" else "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)", + "确定", "取消", DialogUtils.ConfirmListener { + mViewModel.uploadPicAndPatchQuestion(false) + }, null) + } } else { - mViewModel.selectedTags.addAll(mViewModel.questionEntity?.tags!!) - DialogUtils.showAlertDialog(this, "修改问题", - if (mViewModel.questionEntity!!.me.moderatorPermissions.updateQuestion == Permissions.REPORTER) - "你的操作将提交给小编审核,确定提交吗?" else "你的操作将立即生效,确定提交吗?(你的管理权限为:高级)", - "确定", "取消", DialogUtils.ConfirmListener { - mViewModel.uploadPicAndPatchQuestion(false) - }, null) + if (mViewModel.checkTitleAndLoadTitleTag()) { + mTagsSelectFragment?.postQuestion() + } } - } else { - if (mViewModel.checkTitleAndLoadTitleTag()) { - mTagsSelectFragment?.postQuestion() + } else if (menuItem?.itemId == R.id.menu_draft) { + if (checkDraft(SaveDraftType.SKIP)) { + startActivityForResult(QuestionDraftActivity.getIntent(this), QUESTION_DRAFT_REQUEST_CODE) } } + return false } @@ -457,32 +553,15 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { } private fun showSelectGameDialog() { - val selectGameDialog = Dialog(this) - val view = View.inflate(this, R.layout.dialog_article_game, null) - val recyclerView = view.findViewById(R.id.dialog_game_list) - val back = view.findViewById(R.id.dialog_back) - val loading = view.findViewById(R.id.dialog_loading) - - back.setOnClickListener { - selectGameDialog.cancel() - } - recyclerView.layoutManager = GridLayoutManager(this, 4) - recyclerView.adapter = ArticleSelectGameAdapter(this, loading) { - mViewModel.communityEntity = CommunityEntity(it.id, it.name, icon = it.game.icon, iconSubscript = it.game.iconSubscript) + ChooseForumDialogFragment.show(this) { + mViewModel.communityEntity = it if (mViewModel.questionEntity != null) { mViewModel.questionEntity?.community?.id = it.id mViewModel.questionEntity?.community?.name = it.name } setForumName() - if (!mViewModel.isFromSearch) mViewModel.checkQuestionDraft() mBinding.vm = mViewModel - selectGameDialog.cancel() } - - selectGameDialog.requestWindowFeature(Window.FEATURE_NO_TITLE) - selectGameDialog.setCanceledOnTouchOutside(false) - selectGameDialog.setContentView(view) - selectGameDialog.show() } // Limits of EditText @@ -527,8 +606,6 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { } // 需要检查的内容,其中任意一个不为空都要打开提示弹窗 val imgList = mViewModel.picList.value - val title = mBinding.questionseditTitle.text.toString().trim() - val content = mBinding.questionseditContent.text.toString().trim() if (mViewModel.isModeratorPatch) { if (checkSameFromQuestionData()) { @@ -538,21 +615,62 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { , "确定退出修改?已编辑的内容将丢失" , "继续编辑", " 退出", null) { finish() } return true - } else if (imgList != null && imgList.size > 0 || title.isNotEmpty() || content.isNotEmpty()) { - if (mViewModel.questionEntity == null && !mViewModel.isFromSearch) { - mViewModel.saveQuestionDraft() - toast("问题草稿已保存") + } + + //问题发布 + if (mViewModel.questionEntity == null && mViewModel.questionDraftEntity == null) { + if (mViewModel.communityEntity != null && (!imgList.isNullOrEmpty() || !mViewModel.title.isNullOrEmpty() || !mViewModel.content.isNullOrEmpty())) { + DialogUtils.showNewAlertDialog(this, "提示", "是否保存内容再退出?", "不保存", "保存并退出", Gravity.CENTER, true, { + finish() + }, { + mViewModel.saveQuestionDraft(SaveDraftType.EXIT) + }) + return true + } + } + + //问题编辑,需要判断是否修改过 + if (mViewModel.questionEntity != null) { + return if (mViewModel.questionEntity?.community?.id != mViewModel.communityEntity?.id + || mViewModel.questionEntity?.title != mViewModel.title + || mViewModel.questionEntity?.description != mViewModel.content) { + showBackDialog() + true + } else false + } + + return !checkDraft(SaveDraftType.EXIT) + } + + private fun checkDraft(saveType: SaveDraftType): Boolean { + val draftEntity = mViewModel.questionDraftEntity ?: return true + if (draftEntity.title.isEmpty() && draftEntity.description.isEmpty()) return true + if (saveType == SaveDraftType.SKIP) { + //判断是否修改了草稿,修改了需自动保存无需提示 + if (draftEntity.bbs?.id != mViewModel.communityEntity?.id + || draftEntity.title != mViewModel.title + || draftEntity.description != mViewModel.content) { + mViewModel.saveQuestionDraft(SaveDraftType.AUTO) + return true + } + } else if (saveType == SaveDraftType.EXIT) { + //退出页面需判断是否修改了草稿,修改了需弹窗提示 + if (draftEntity.bbs?.id != mViewModel.communityEntity?.id + || draftEntity.title != mViewModel.title + || draftEntity.description != mViewModel.content) { + showBackDialog() return false } - - DialogUtils.showCancelAlertDialog(this, "提示" - , if (mViewModel.questionEntity == null) "确定放弃提问吗?" else "确定放弃修改吗?" - , "再想想", " 放弃", null) { finish() } - return true - } else if (mViewModel.questionEntity == null && !mViewModel.isFromSearch) { - mViewModel.cleanCurrentCommunityDraft() } - return false + return true + } + + private fun showBackDialog() { + DialogUtils.showNewAlertDialog(this, "提示", "是否保存修改内容用于下次编辑?", "不保存", "保存并退出", Gravity.CENTER, true,{ + finish() + }, { + mViewModel.saveQuestionDraft(SaveDraftType.EXIT) + }) } private fun checkSameFromQuestionData(): Boolean { @@ -608,6 +726,9 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { companion object { const val QUESTION_POSTED_TAG = "QUESTION_POSTED_TAG" + const val QUESTION_DRAFT_REQUEST_CODE = 105 + const val QUESTION_DRAFT_CHANGE_TAG = "ANSWER_DRAFT_CHANGE_TAG" + const val SAVE_DRAFTS_INTERVAL_TIME = 15000 // searchKey 补充到标题(新增问题) fun getIntent(context: Context, searchKey: String?): Intent { @@ -644,5 +765,19 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { return intent } + //编辑草稿 + @JvmStatic + fun getDraftIntent(context: Context, questionDraftEntity: QuestionDraftEntity): Intent { + val intent = Intent(context, QuestionEditActivity::class.java) + intent.putExtra(QuestionDraftEntity::class.java.simpleName, questionDraftEntity) + return intent + } + + } + + enum class SaveDraftType { + EXIT, // 退出时保存 + AUTO, // 自动保存 + SKIP // 跳转至草稿箱时保存 } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt index 45160ee519..34bae5b4d1 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/QuestionEditViewModel.kt @@ -1,5 +1,6 @@ package com.gh.gamecenter.qa.questions.edit +import android.annotation.SuppressLint import android.app.Application import android.net.Uri import android.provider.MediaStore @@ -12,11 +13,16 @@ import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.entity.CommunityEntity import com.gh.gamecenter.entity.Permissions +import com.gh.gamecenter.entity.User import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.mvvm.Resource +import com.gh.gamecenter.qa.article.edit.ArticleEditActivity +import com.gh.gamecenter.qa.entity.ArticleDraftEntity import com.gh.gamecenter.qa.entity.CommunityVideoEntity +import com.gh.gamecenter.qa.entity.QuestionDraftEntity import com.gh.gamecenter.qa.entity.QuestionsDetailEntity +import com.gh.gamecenter.retrofit.BiResponse import com.gh.gamecenter.retrofit.Response import com.gh.gamecenter.retrofit.RetrofitManager import com.gh.gamecenter.retrofit.service.ApiService @@ -49,6 +55,9 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica val postLiveData = MediatorLiveData>() val moderatorPostLiveData = MediatorLiveData>() val videoLiveData = MutableLiveData() + val notSelectForum = MutableLiveData() + val postQuestionDrafts = MediatorLiveData>() + val questionDraftsContent = MutableLiveData() var uploadImageSubscription: Disposable? = null @@ -57,9 +66,10 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica var content: String? = "" // picList 纯粹用于展示,可以包含本地和网络地址的图片 - val picList = MediatorLiveData>() + val picList = MediatorLiveData>() var defaultTags: MutableList = ArrayList() var questionEntity: QuestionsDetailEntity? = null + var questionDraftEntity: QuestionDraftEntity? = null val selectedTags: MutableList = ArrayList() val selectedTagsChange = MediatorLiveData() @@ -105,11 +115,6 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica * 根据问题标题获取相应标签(问题编辑无需获取) */ fun checkTitleAndLoadTitleTag(): Boolean { - if (TextUtils.isEmpty(communityEntity?.id) || TextUtils.isEmpty(communityEntity?.name)) { - Utils.toast(getApplication(), "论坛不能为空") - return false - } - if (TextUtils.isEmpty(title)) { Utils.toast(getApplication(), "标题不能为空") return false @@ -122,6 +127,13 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica Utils.toast(getApplication(), "标题至少${QUESTION_TITLE_MIN_LENGTH}个字") return false } + if (questionEntity != null && questionEntity?.title == title && questionEntity?.description == content) return false + + if (TextUtils.isEmpty(communityEntity?.id) || TextUtils.isEmpty(communityEntity?.name)) { + Utils.toast(getApplication(), "论坛不能为空") + notSelectForum.postValue(true) + return false + } // 检查标题结尾是否存在问号,没则主动加上 if (title!!.length <= QUESTION_TITLE_MAX_LENGTH) { @@ -139,31 +151,10 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica // 检查标题长度限制 title?.trim() if (title!!.length < QUESTION_TITLE_MIN_LENGTH) return false + if (questionEntity != null && questionEntity?.title == title && questionEntity?.description == content) return false return true } - /** - * 根据问题标题获取相应标签(标签默认选中) - */ - private fun loadTitleTags() { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true)) - mApiService - .getQuestionTagsByTitle(communityEntity?.id, UrlFilterUtils.getFilterQuery("title", title)) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Response>() { - override fun onResponse(response: List?) { - titleTags.postValue(response) - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - } - - override fun onFailure(e: HttpException?) { - processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) - Utils.toast(getApplication(), R.string.request_failure_normal_hint) - } - }) - } - /** * 选择动作(选中标签/移除已选中的标签) */ @@ -352,7 +343,9 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica entity.images = successfullyUploadedPicList val video: CommunityVideoEntity? = videoLiveData.value if (video != null) entity.videos = arrayListOf(video) - + if (!questionDraftEntity?.id.isNullOrEmpty()) { + entity.draftId = questionDraftEntity?.id ?: "" + } val observable = if (questionEntity != null) { if (!isModeratorPatch) { questionEntity?.images = entity.images @@ -383,16 +376,18 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica override fun onResponse(response: ResponseBody?) { processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false)) MtaHelper.onEvent("发表问题", "提交成功", communityEntity?.name) - val data = response?.string() + val data = response?.string() ?: "" postLiveData.postValue(Resource.success(data)) EventBus.getDefault().post(EBReuse(QuestionEditActivity.QUESTION_POSTED_TAG)) - if (questionEntity == null && !isFromSearch) cleanCurrentCommunityDraft() if (questionEntity == null) { tryWithDefaultCatch { EnergyTaskHelper.postEnergyTask("post_question", JSONObject(data).optString("_id")) } } + if (!questionDraftEntity?.id.isNullOrEmpty()) { + EventBus.getDefault().post(EBReuse(QuestionEditActivity.QUESTION_DRAFT_CHANGE_TAG)) + } } override fun onFailure(e: HttpException?) { @@ -439,65 +434,63 @@ class QuestionEditViewModel(application: Application) : AndroidViewModel(applica }) } - fun cleanCurrentCommunityDraft() { - val draftKey = getDraftKey() - if (draftKey.isNullOrEmpty()) { - //Utils.toast(getApplication(), "删除草稿失败") - return + @SuppressLint("CheckResult") + fun saveQuestionDraft(saveType: QuestionEditActivity.SaveDraftType) { + val body = getQuestionBody() + val observable = if (!questionDraftEntity?.id.isNullOrEmpty()) { + mApiService.updateQuestionDraft(UserManager.getInstance().userId, questionDraftEntity?.id, body) + } else { + mApiService.addQuestionDraft(UserManager.getInstance().userId, body) } - SPUtils.remove(draftKey) + observable + .compose(singleToMain()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + val string = data.string() + if (!string.isNullOrEmpty() && questionDraftEntity?.id.isNullOrEmpty()) { + if (questionDraftEntity == null) questionDraftEntity = QuestionDraftEntity() + questionDraftEntity?.id = JSONObject(string).getString("_id") + } + postQuestionDrafts.postValue(Pair(saveType, true)) + } + + override fun onFailure(exception: Exception) { + super.onFailure(exception) + postQuestionDrafts.postValue(Pair(saveType, false)) + } + }) } - fun saveQuestionDraft() { - val draftKey = getDraftKey() - if (draftKey.isNullOrEmpty()) { - Utils.toast(getApplication(), "保存草稿失败") - return - } - - val draftJson = JSONObject() - draftJson.put("title", title) - draftJson.put("content", content) - draftJson.put("images", JSONArray(picList.value)) - SPUtils.setString(draftKey, draftJson.toString()) + private fun getQuestionBody(): RequestBody { + val draftEntity = QuestionDraftEntity( + communityId = communityEntity?.id ?: "", + tags = selectedTags.toList(), + images = picList.value ?: arrayListOf(), + videos = if (videoLiveData.value != null) arrayListOf(videoLiveData.value!!) else arrayListOf(), + title = title ?: "", + description = content ?: "" + ) + return draftEntity.toRequestBody() } - fun checkQuestionDraft() { - val draftKey = getDraftKey() - if (draftKey.isNullOrEmpty()) { - Utils.toast(getApplication(), "获取草稿失败") - return - } + @SuppressLint("CheckResult") + fun getQuestionDraftContent(draftId: String) { + processDialog.postValue(WaitingDialogFragment.WaitingDialogData("加载中...", true)) + mApiService.getQuestionDraft(UserManager.getInstance().userId, draftId) + .compose(singleToMain()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: QuestionDraftEntity) { + questionDraftsContent.postValue(data) + processDialog.postValue(WaitingDialogFragment.WaitingDialogData("加载中...", false)) + } - val draft = SPUtils.getString(draftKey, "") - if (draft.isNullOrEmpty()) return - val draftJson = JSONObject(draft) - - val draftTitle = draftJson.optString("title") - if (draftTitle.isNotEmpty()) title = draftTitle - - val draftContent = draftJson.optString("content") - if (draftContent.isNotEmpty()) content = draftContent - - val draftImages = draftJson.optJSONArray("images") - if (draftImages != null) { - val images = ArrayList() - for (i in 0 until draftImages.length()) { - val img = draftImages.getString(i) - if (img.isNotEmpty() && File(img).exists()) { - images.add(img) - } - } - if (images.isNotEmpty()) picList.postValue(images) - } + override fun onFailure(exception: Exception) { + super.onFailure(exception) + processDialog.postValue(WaitingDialogFragment.WaitingDialogData("加载中...", false)) + } + }) } - private fun getDraftKey(): String? { - if (communityEntity?.id.isNullOrEmpty()) return null - return QUESTION_DRAFT_KEY + communityEntity?.id - } - - companion object { const val QUESTION_TAG_MAX_COUNT = 5 const val PIC_MAX_AMOUNT = 30 diff --git a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt index 710c57be20..b6429d9921 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/questions/edit/TagsSelectFragment.kt @@ -223,28 +223,25 @@ class TagsSelectFragment : BaseFragment() { // 添加标签 val mDefaultTag = mViewModel?.defaultTags ?: ArrayList() - if (mViewModel?.questionEntity == null) { - val mTitleTag = (mViewModel?.titleTags?.value ?: ArrayList()) as MutableList - // 添加默认标签(如果标题标签与默认标签重复则选中) - for (s in mDefaultTag.reversed()) { - val contains = mTitleTag.contains(s) - addTag(s, contains) - if (contains) mTitleTag.remove(s) + val tags = when { + mViewModel?.questionEntity != null -> { + mViewModel?.questionEntity?.tags ?: arrayListOf() } - // 未匹配到默认标签的默认选中在前排 - for (s in mTitleTag) { - addTag(s, true) + mViewModel?.questionDraftEntity != null -> { + mViewModel?.questionDraftEntity?.tags ?: arrayListOf() } - } else { - val tags = mViewModel?.questionEntity?.tags ?: ArrayList() - for (s in mDefaultTag) { - if (!tags.contains(s)) - addTag(s, false) - } - for (s in tags.reversed()) { - addTag(s, true) + else -> { + arrayListOf() } } + + for (s in mDefaultTag) { + if (!tags.contains(s)) + addTag(s, false) + } + for (s in tags.reversed()) { + addTag(s, true) + } } private fun showAddTagDialog() { diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java index 24c20a1bac..88c1c5bddd 100644 --- a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java +++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java @@ -100,6 +100,7 @@ import com.gh.gamecenter.qa.entity.CommunitySelectEntity; import com.gh.gamecenter.qa.entity.CommunitySelectOpenEntity; import com.gh.gamecenter.qa.entity.EditorInsertDefaultEntity; import com.gh.gamecenter.qa.entity.InviteEntity; +import com.gh.gamecenter.qa.entity.QuestionDraftEntity; import com.gh.gamecenter.qa.entity.QuestionHistoryDetailEntity; import com.gh.gamecenter.qa.entity.QuestionHistoryEntity; import com.gh.gamecenter.qa.entity.Questions; @@ -108,6 +109,7 @@ import com.gh.gamecenter.qa.entity.QuestionsIndexEntity; import com.gh.gamecenter.qa.entity.SearchHottestEntity; import com.gh.gamecenter.qa.entity.SearchNewestEntity; import com.gh.gamecenter.qa.entity.SuggestedFollowEntity; +import com.gh.gamecenter.retrofit.Response; import com.google.gson.JsonObject; import java.util.ArrayList; @@ -2808,4 +2810,34 @@ public interface ApiService { */ @GET("shop/orders/roll_notices") Single> getRollNotices(); + + /** + * 新增一个问题草稿 + */ + @POST("users/{user_id}/question_drafts") + Single addQuestionDraft(@Path("user_id") String userId, @Body RequestBody body); + + /** + * 获取单个问题草稿 + */ + @GET("users/{user_id}/question_drafts/{draft_id}") + Single getQuestionDraft(@Path("user_id") String userId, @Path("draft_id") String draftId); + + /** + * 修改一个问题草稿 + */ + @POST("users/{user_id}/question_drafts/{draft_id}") + Single updateQuestionDraft(@Path("user_id") String userId, @Path("draft_id") String draftId, @Body RequestBody body); + + /** + * 获取问题草稿列表 + */ + @GET("users/{user_id}/question_drafts") + Observable> getQuestionDrafts(@Path("user_id") String userId); + + /** + * 删除单个问题草稿 + */ + @DELETE("users/{user_id}/question_drafts/{draft_id}") + Observable deleteQuestionDraft(@Path("user_id") String userId, @Path("draft_id") String draftId); } \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/ic_alert_dialog_close.png b/app/src/main/res/drawable-xxhdpi/ic_alert_dialog_close.png new file mode 100644 index 0000000000..8a4adefd49 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_alert_dialog_close.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_article_detail_star_bottom_bar.png b/app/src/main/res/drawable-xxhdpi/ic_article_detail_star_bottom_bar.png new file mode 100644 index 0000000000..509d7429cf Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_article_detail_star_bottom_bar.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_article_detail_stared_bottom_bar.png b/app/src/main/res/drawable-xxhdpi/ic_article_detail_stared_bottom_bar.png new file mode 100644 index 0000000000..5380afb700 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_article_detail_stared_bottom_bar.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_choose_forum_close.png b/app/src/main/res/drawable-xxhdpi/ic_choose_forum_close.png new file mode 100644 index 0000000000..fd52b88a13 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_choose_forum_close.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_enable.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_enable.png new file mode 100644 index 0000000000..6c718a6c43 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_enable.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_unenable.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_unenable.png new file mode 100644 index 0000000000..4941b41334 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_panel_close_comment_unenable.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_delete.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_delete.png new file mode 100644 index 0000000000..60bdc0689d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_panel_delete.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_edit.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_edit.png new file mode 100644 index 0000000000..109b3681fa Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_panel_edit.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence.png new file mode 100644 index 0000000000..a9cb83d527 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence_unenable.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence_unenable.png new file mode 100644 index 0000000000..ad304944b5 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_panel_essence_unenable.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_panel_fold.png b/app/src/main/res/drawable-xxhdpi/icon_more_panel_fold.png new file mode 100644 index 0000000000..d28d86c5bc Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_panel_fold.png differ diff --git a/app/src/main/res/drawable/divider_item_line.xml b/app/src/main/res/drawable/divider_item_line.xml new file mode 100644 index 0000000000..321d4fc36a --- /dev/null +++ b/app/src/main/res/drawable/divider_item_line.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/divider_item_line_space_16.xml b/app/src/main/res/drawable/divider_item_line_space_16.xml new file mode 100644 index 0000000000..3343904cb8 --- /dev/null +++ b/app/src/main/res/drawable/divider_item_line_space_16.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_tablayout_no_title_viewpager.xml b/app/src/main/res/layout/activity_tablayout_no_title_viewpager.xml new file mode 100644 index 0000000000..cbcdeaadd3 --- /dev/null +++ b/app/src/main/res/layout/activity_tablayout_no_title_viewpager.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/ask_answer_item.xml b/app/src/main/res/layout/ask_answer_item.xml index 3b1bfe88e4..d03b0d021d 100644 --- a/app/src/main/res/layout/ask_answer_item.xml +++ b/app/src/main/res/layout/ask_answer_item.xml @@ -1,25 +1,24 @@ + android:paddingLeft="16dp" + android:paddingTop="13dp" + android:paddingRight="16dp" + android:paddingBottom="16dp"> @@ -48,7 +46,9 @@ android:id="@+id/ask_answer_item_usericon" style="@style/frescoCircleStyle" android:layout_width="20dp" - android:layout_height="20dp" /> + android:layout_height="20dp" + app:roundingBorderColor="@color/black_alpha_10" + app:roundingBorderWidth="0.5dp" /> + app:layout_constraintRight_toLeftOf="@+id/sdv_user_badge" + app:layout_constraintTop_toTopOf="@id/ask_answer_item_usericon_container" /> + tools:visibility="visible" /> + tools:visibility="visible" /> + app:layout_constraintTop_toBottomOf="@id/ask_answer_item_content" /> + app:layout_constraintTop_toBottomOf="@id/ask_answer_item_content" /> + app:layout_constraintTop_toBottomOf="@id/ask_answer_item_content" /> \ No newline at end of file diff --git a/app/src/main/res/layout/collection_comunity_article_item.xml b/app/src/main/res/layout/collection_comunity_article_item.xml index 767d987475..dc58fac470 100644 --- a/app/src/main/res/layout/collection_comunity_article_item.xml +++ b/app/src/main/res/layout/collection_comunity_article_item.xml @@ -16,22 +16,20 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/reuse_listview_item_style" - android:paddingTop="5dp" - android:paddingBottom="10dp"> + android:paddingLeft="16dp" + android:paddingTop="13dp" + android:paddingRight="16dp" + android:paddingBottom="16dp"> @@ -58,6 +56,8 @@ imageIcon="@{data.user.icon}" android:layout_width="20dp" android:layout_height="20dp" + app:roundingBorderColor="@color/black_alpha_10" + app:roundingBorderWidth="0.5dp" fresco:roundAsCircle="true" /> + app:layout_constraintTop_toTopOf="@id/user_icon_container" + fresco:text="我的名字很长很长有十二字" /> + fresco:visibility="visible" /> + fresco:visibility="visible" /> + - - - - + app:layout_constraintTop_toBottomOf="@id/content" /> + app:layout_constraintTop_toBottomOf="@id/content" /> diff --git a/app/src/main/res/layout/comment_item.xml b/app/src/main/res/layout/comment_item.xml index cb9b9e528e..b167911666 100644 --- a/app/src/main/res/layout/comment_item.xml +++ b/app/src/main/res/layout/comment_item.xml @@ -72,7 +72,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="4dp" - android:layout_marginRight="4dp" android:background="@drawable/button_round_2496ff" android:includeFontPadding="false" android:paddingLeft="4dp" @@ -95,6 +94,7 @@ android:layout_width="16dp" android:layout_height="16dp" android:layout_marginRight="2dp" + android:layout_marginLeft="4dp" android:visibility="gone" app:layout_constrainedWidth="true" app:layout_constraintBottom_toBottomOf="@+id/comment_user_name" diff --git a/app/src/main/res/layout/community_answer_item.xml b/app/src/main/res/layout/community_answer_item.xml index b549164a28..2edbf2bd19 100644 --- a/app/src/main/res/layout/community_answer_item.xml +++ b/app/src/main/res/layout/community_answer_item.xml @@ -194,6 +194,78 @@ app:layout_constraintTop_toBottomOf="@+id/content" app:offset="40dp" /> + + + + + + + + + + + - + @@ -15,67 +16,62 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/reuse_listview_item_style" - android:paddingLeft="20dp" - android:paddingBottom="14dp"> + android:paddingLeft="16dp" + android:paddingTop="20dp" + android:paddingRight="16dp" + android:paddingBottom="16dp"> - - - + android:textSize="11sp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/article_draft_title" + tools:text="地下城与勇士" /> - - + app:layout_constraintTop_toBottomOf="@+id/article_draft_title" /> \ No newline at end of file diff --git a/app/src/main/res/layout/community_question_draft_item.xml b/app/src/main/res/layout/community_question_draft_item.xml new file mode 100644 index 0000000000..8b46456535 --- /dev/null +++ b/app/src/main/res/layout/community_question_draft_item.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_choose_forum.xml b/app/src/main/res/layout/dialog_choose_forum.xml new file mode 100644 index 0000000000..30b893105c --- /dev/null +++ b/app/src/main/res/layout/dialog_choose_forum.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_game_detail_more.xml b/app/src/main/res/layout/dialog_game_detail_more.xml index 9fbbbb6b7d..445ecaba03 100644 --- a/app/src/main/res/layout/dialog_game_detail_more.xml +++ b/app/src/main/res/layout/dialog_game_detail_more.xml @@ -13,6 +13,7 @@ android:descendantFocusability="blocksDescendants"> - - - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/handle_view"> + + + + + + app:layout_constraintTop_toBottomOf="@+id/title_container" /> + tools:text="内容内容内容内容内容内容" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_answer_detail.xml b/app/src/main/res/layout/fragment_answer_detail.xml index bde3362a44..1fbc502a6c 100644 --- a/app/src/main/res/layout/fragment_answer_detail.xml +++ b/app/src/main/res/layout/fragment_answer_detail.xml @@ -159,11 +159,10 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginRight="16dp" - android:layout_marginBottom="5dp" android:maxLength="12" android:textColor="@color/text_333333" android:textSize="14sp" - android:layout_marginTop="10dp" + app:layout_constraintBottom_toTopOf="@+id/sdv_user_badge" app:layout_constraintLeft_toRightOf="@id/user_icon_iv" app:layout_constraintRight_toLeftOf="@+id/follow_tv" app:layout_constraintTop_toTopOf="@+id/user_icon_iv" @@ -271,7 +270,7 @@ + layout="@layout/piece_article_input_container" /> - - - - - - - - + android:layout_height="match_parent"> + android:layout_height="488dp" + android:layout_gravity="bottom" + android:background="@drawable/game_detail_more_dialog_background"> - + android:layout_height="48dp"> + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_comment.xml b/app/src/main/res/layout/fragment_comment.xml index 556034f6e8..094a1bb3b3 100644 --- a/app/src/main/res/layout/fragment_comment.xml +++ b/app/src/main/res/layout/fragment_comment.xml @@ -7,7 +7,7 @@ @@ -26,18 +26,16 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="@color/text_333333" - android:textSize="14sp" - android:textStyle="bold" + android:textSize="16sp" tools:text="35条评论" /> + android:src="@drawable/ic_choose_forum_close" /> - + android:layout_height="match_parent"> - - + android:orientation="vertical" + android:visibility="gone" + tools:visibility="visible"> - + android:gravity="center" + app:layout_behavior="com.gh.common.view.FixAppBarLayoutBehavior"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:fitsSystemWindows="true" + app:contentScrim="@color/white" + app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:scrimAnimationDuration="0" + app:scrimVisibleHeightTrigger="80dp" + app:titleEnabled="false"> + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:orientation="vertical" + app:layout_collapseMode="pin"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_marginRight="4dp" + android:includeFontPadding="false" + android:text="最新回复" + android:textColor="@color/text_999999" + android:textSize="12sp" /> + android:id="@+id/filterArrow" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/ic_filter_down" /> - + + - - - + android:layout_height="match_parent" + android:overScrollMode="never" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - - - - - - - - - - - - - - - - - - + + - - - + + + @@ -272,5 +270,14 @@ app:layout_constraintTop_toTopOf="@id/floorHintTv" tools:text="999" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/item_article_detail_content.xml b/app/src/main/res/layout/item_article_detail_content.xml index 720d85df36..9e2ab44ec4 100644 --- a/app/src/main/res/layout/item_article_detail_content.xml +++ b/app/src/main/res/layout/item_article_detail_content.xml @@ -42,10 +42,10 @@ android:id="@+id/userIconIv" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:avatar_width="32dp" - app:badge_width="12dp" android:layout_marginLeft="12dp" android:layout_marginTop="7dp" + app:avatar_width="32dp" + app:badge_width="12dp" app:border_color="@color/transparent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -56,8 +56,8 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="2dp" - android:layout_marginRight="16dp" android:layout_marginTop="8dp" + android:layout_marginRight="16dp" app:layout_constraintLeft_toRightOf="@id/userIconIv" app:layout_constraintRight_toLeftOf="@+id/followBtn" app:layout_constraintTop_toTopOf="@+id/userIconIv"> @@ -127,10 +127,10 @@ android:layout_marginLeft="2dp" android:layout_marginTop="53dp" android:layout_marginRight="20dp" + android:layout_marginBottom="8dp" android:includeFontPadding="false" android:textColor="@color/text_999999" android:textSize="11sp" - android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="@id/userIconIv" app:layout_constraintLeft_toRightOf="@id/userIconIv" tools:text="发布于1分钟前" /> @@ -184,120 +184,5 @@ android:paddingBottom="20dp" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/new_comment_item.xml b/app/src/main/res/layout/new_comment_item.xml new file mode 100644 index 0000000000..8abaf440db --- /dev/null +++ b/app/src/main/res/layout/new_comment_item.xml @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/piece_article_input_container.xml b/app/src/main/res/layout/piece_article_input_container.xml index d14b9a809e..55373f0738 100644 --- a/app/src/main/res/layout/piece_article_input_container.xml +++ b/app/src/main/res/layout/piece_article_input_container.xml @@ -5,6 +5,7 @@ android:id="@+id/bottomContainer" android:layout_width="match_parent" android:layout_height="50dp" + android:background="@color/white" android:layout_alignParentBottom="true" tools:showIn="@layout/fragment_article_detail"> @@ -20,7 +21,7 @@ android:maxLines="1" android:paddingLeft="16dp" android:paddingRight="16dp" - android:textColor="@color/AAAAAA" + android:textColor="@color/text_cccccc" android:textSize="14sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" @@ -40,8 +41,8 @@ @@ -52,25 +53,54 @@ android:gravity="center" android:text="赞同" android:textColor="@color/text_666666" - android:textSize="11sp" /> + android:textSize="10sp" /> + + + + + + + + @@ -81,7 +111,7 @@ android:gravity="center" android:text="评论" android:textColor="@color/text_666666" - android:textSize="11sp" /> + android:textSize="10sp" /> \ No newline at end of file diff --git a/app/src/main/res/layout/piece_comment_typing_container.xml b/app/src/main/res/layout/piece_comment_typing_container.xml index 77063d4886..065dc5b25c 100644 --- a/app/src/main/res/layout/piece_comment_typing_container.xml +++ b/app/src/main/res/layout/piece_comment_typing_container.xml @@ -41,7 +41,7 @@ android:layout_height="wrap_content" android:background="@android:color/transparent" android:drawablePadding="4dp" - android:hint="写评论" + android:hint="说点什么吧" android:lineSpacingExtra="4dp" android:textColor="@color/text_333333" android:textColorHint="@color/theme_font" diff --git a/app/src/main/res/layout/piece_comment_typing_container_dark.xml b/app/src/main/res/layout/piece_comment_typing_container_dark.xml index c15ea66e8e..daeed3f1b7 100644 --- a/app/src/main/res/layout/piece_comment_typing_container_dark.xml +++ b/app/src/main/res/layout/piece_comment_typing_container_dark.xml @@ -40,7 +40,7 @@ android:layout_height="wrap_content" android:background="@android:color/transparent" android:drawablePadding="4dp" - android:hint="写评论" + android:hint="说点什么吧" android:lineSpacingExtra="4dp" android:textColor="@color/white" android:textColorHint="@color/text_666666" diff --git a/app/src/main/res/layout/piece_community_vote_and_comment.xml b/app/src/main/res/layout/piece_community_vote_and_comment.xml index cad102fa39..40367d5bc8 100644 --- a/app/src/main/res/layout/piece_community_vote_and_comment.xml +++ b/app/src/main/res/layout/piece_community_vote_and_comment.xml @@ -11,7 +11,7 @@ android:id="@+id/comment_count_container" android:layout_width="0dp" android:layout_height="wrap_content" - android:background="@drawable/reuse_listview_item_style" + android:background="@color/white" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/vote_count_container" app:layout_constraintTop_toTopOf="parent"> @@ -37,7 +37,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_gravity="center" - android:background="@drawable/reuse_listview_item_style" + android:background="@color/white" android:gravity="center" app:layout_constraintBottom_toBottomOf="@id/comment_count_container" app:layout_constraintLeft_toRightOf="@id/comment_count_container" diff --git a/app/src/main/res/menu/menu_answer_post.xml b/app/src/main/res/menu/menu_answer_post.xml index c4792fb7e9..bf5a8a317b 100644 --- a/app/src/main/res/menu/menu_answer_post.xml +++ b/app/src/main/res/menu/menu_answer_post.xml @@ -3,11 +3,10 @@ xmlns:app = "http://schemas.android.com/apk/res-auto" > + android:title="草稿" + app:showAsAction="always" /> - + 资讯 首页 我的光环 - 写评论 + 说点什么吧 发送 发表评论... 发表评论...