From 942af39b2d36a76bfd2e525400a4a38d7188349c Mon Sep 17 00:00:00 2001 From: jack <1484288157@qq.com> Date: Wed, 12 May 2021 16:55:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E8=87=B4=E5=AE=8C=E6=88=90=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E8=AE=BA=E5=9D=9B=E3=80=81=E9=80=89=E6=8B=A9=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E8=A7=86=E9=A2=91=E3=80=81=E9=A2=84=E8=A7=88=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E3=80=81=E5=8F=91=E8=A7=86=E9=A2=91UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 31 +- .../com/gh/base/BaseRichEditorActivity.kt | 32 +- .../com/gh/base/BaseRichEditorViewModel.kt | 27 ++ .../com/gh/common/util/EntranceUtils.java | 3 + .../gh/gamecenter/entity/LocalVideoEntity.kt | 13 + .../forum/home/ForumHomeFragment.kt | 14 +- .../qa/article/edit/ArticleEditActivity.kt | 16 +- .../qa/dialog/ChooseForumActivity.kt | 111 +++++++ .../qa/dialog/ChooseForumContainerAdapter.kt | 39 +++ .../qa/dialog/ChooseForumContainerFragment.kt | 53 ++++ .../dialog/ChooseForumContainerViewModel.kt | 20 ++ .../qa/dialog/ChooseForumDialogFragment.kt | 74 ----- .../gamecenter/qa/editor/LocalVideoAdapter.kt | 38 ++- .../qa/editor/LocalVideoFragment.kt | 51 ++- .../qa/editor/PreviewVideoActivity.kt | 34 ++ .../qa/editor/PreviewVideoFragment.kt | 180 +++++++++++ .../gh/gamecenter/qa/editor/VideoActivity.kt | 60 ++-- .../qa/questions/edit/QuestionEditActivity.kt | 36 ++- .../gamecenter/qa/video/PreviewVideoView.kt | 59 ++++ .../qa/video/publish/VideoPublishActivity.kt | 26 ++ .../qa/video/publish/VideoPublishFragment.kt | 293 ++++++++++++++++++ .../qa/video/publish/VideoPublishViewModel.kt | 9 + .../video/upload/view/UploadVideoActivity.kt | 5 +- .../video/upload/view/VideoFileEntity.kt | 5 +- .../community_edit_article.webp | Bin 4434 -> 7496 bytes .../drawable-xxhdpi/community_edit_close.png | Bin 0 -> 765 bytes .../drawable-xxhdpi/community_edit_close.webp | Bin 1788 -> 0 bytes .../community_edit_question.webp | Bin 4656 -> 7224 bytes .../drawable-xxhdpi/community_edit_video.webp | Bin 0 -> 6944 bytes .../drawable-xxhdpi/ic_choose_activity.webp | Bin 0 -> 1018 bytes .../main/res/drawable-xxhdpi/ic_del_video.png | Bin 0 -> 1921 bytes .../icon_upload_video_btn.webp | Bin 0 -> 1234 bytes .../main/res/drawable/bg_change_cover_btn.xml | 6 + .../border_round_stroke_0dot5_eee_999.xml | 13 + .../main/res/layout/activity_editor_video.xml | 61 +++- .../res/layout/activity_video_publish.xml | 46 +++ .../main/res/layout/community_edit_window.xml | 138 +++++---- .../main/res/layout/dialog_choose_forum.xml | 88 +++++- .../res/layout/fragment_preview_video.xml | 99 ++++++ .../res/layout/fragment_video_publish.xml | 278 +++++++++++++++++ .../main/res/layout/item_video_selector.xml | 19 ++ .../main/res/layout/layout_preview_video.xml | 38 +++ app/src/main/res/layout/local_video_item.xml | 19 +- app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/styles.xml | 7 + 45 files changed, 1798 insertions(+), 244 deletions(-) create mode 100644 app/src/main/java/com/gh/gamecenter/entity/LocalVideoEntity.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerAdapter.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt delete mode 100644 app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoActivity.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoFragment.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/video/PreviewVideoView.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishActivity.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishFragment.kt create mode 100644 app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishViewModel.kt create mode 100644 app/src/main/res/drawable-xxhdpi/community_edit_close.png delete mode 100644 app/src/main/res/drawable-xxhdpi/community_edit_close.webp create mode 100644 app/src/main/res/drawable-xxhdpi/community_edit_video.webp create mode 100644 app/src/main/res/drawable-xxhdpi/ic_choose_activity.webp create mode 100644 app/src/main/res/drawable-xxhdpi/ic_del_video.png create mode 100644 app/src/main/res/drawable-xxhdpi/icon_upload_video_btn.webp create mode 100644 app/src/main/res/drawable/bg_change_cover_btn.xml create mode 100644 app/src/main/res/drawable/border_round_stroke_0dot5_eee_999.xml create mode 100644 app/src/main/res/layout/activity_video_publish.xml create mode 100644 app/src/main/res/layout/fragment_preview_video.xml create mode 100644 app/src/main/res/layout/fragment_video_publish.xml create mode 100644 app/src/main/res/layout/item_video_selector.xml create mode 100644 app/src/main/res/layout/layout_preview_video.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5083acb860..9941e0158c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,15 +29,15 @@ - - + + - + @@ -76,9 +76,9 @@ android:icon="@mipmap/logo" android:label="@string/app_name" android:largeHeap="true" + android:networkSecurityConfig="@xml/network_security_config" android:resizeableActivity="true" android:theme="@style/AppCompatTheme.APP" - android:networkSecurityConfig="@xml/network_security_config" tools:replace="android:allowBackup" tools:targetApi="n"> @@ -514,6 +514,12 @@ android:theme="@style/Theme.Transparent" android:windowSoftInputMode="adjustNothing" /> + + + android:launchMode="singleTask" + android:screenOrientation="portrait" /> + + + + - + android:theme="@android:style/Theme.Dialog"/> : ToolBarAct super.onActivityResult(requestCode, resultCode, data) DialogUtils.fixWebViewKeyboardNotWorking(this) if (resultCode != Activity.RESULT_OK) return - var insertData: EditorInsertEntity? + val insertData: EditorInsertEntity? when (requestCode) { INSERT_ANSWER_CODE -> { val answer = data?.getParcelableExtra(AnswerEntity::class.java.simpleName) @@ -104,11 +106,17 @@ abstract class BaseRichEditorActivity : ToolBarAct REQUEST_CODE_IMAGE -> { if (data != null) mViewModel.uploadPic(data) } - VideoActivity.INSERT_VIDEO_CODE -> { - val video = data?.getParcelableExtra(MyVideoEntity::class.java.simpleName) - if (video != null) { - mRichEditor.focusEditor() - mRichEditor.insertCustomVideo(video) + INSERT_VIDEO_CODE -> { +// val video = data?.getParcelableExtra(MyVideoEntity::class.java.simpleName) +// if (video != null) { +// mRichEditor.focusEditor() +// mRichEditor.insertCustomVideo(video) +// } + val localVideoList = data?.getParcelableArrayListExtra(LocalVideoEntity::class.java.name) + ?: arrayListOf() + if (localVideoList.isNotEmpty()) { + mViewModel.localVideoList.addAll(localVideoList) + mViewModel.uploadVideo() } } } @@ -141,7 +149,7 @@ abstract class BaseRichEditorActivity : ToolBarAct observeData() } - private fun observeData(){ + private fun observeData() { mViewModel.chooseImagesUpload.observe(this, Observer { for (key in it.keys) { mRichEditor.insertPlaceholderImage(key) @@ -309,7 +317,7 @@ abstract class BaseRichEditorActivity : ToolBarAct object : EmptyCallback { override fun onCallback() { MtaHelper.onEvent(mtaEventName(), "插入链接", "插入链接-视频") - startActivityForResult(VideoActivity.getIntent(this@BaseRichEditorActivity), VideoActivity.INSERT_VIDEO_CODE) + startActivityForResult(VideoActivity.getIntent(this@BaseRichEditorActivity, 3), INSERT_VIDEO_CODE) } }) } @@ -426,6 +434,13 @@ abstract class BaseRichEditorActivity : ToolBarAct return super.handleBackPressed() } + override fun onDestroy() { + super.onDestroy() + val path = mViewModel.currentUploadingVideo?.filePath + if (path != null && UploadManager.isUploading(path)) { + UploadManager.cancelTask(path) + } + } private inner class OnCursorChangeListener { @JavascriptInterface @@ -500,5 +515,6 @@ abstract class BaseRichEditorActivity : ToolBarAct const val MAX_INPUT_TEXT_NUM = 10000 const val REQUEST_CODE_IMAGE = 120 + const val INSERT_VIDEO_CODE = 121 } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/base/BaseRichEditorViewModel.kt b/app/src/main/java/com/gh/base/BaseRichEditorViewModel.kt index eebfec6290..fad4da7044 100644 --- a/app/src/main/java/com/gh/base/BaseRichEditorViewModel.kt +++ b/app/src/main/java/com/gh/base/BaseRichEditorViewModel.kt @@ -8,9 +8,12 @@ import androidx.lifecycle.MutableLiveData import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.entity.ErrorEntity +import com.gh.gamecenter.entity.LocalVideoEntity import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity import com.gh.gamecenter.retrofit.RetrofitManager import com.gh.gamecenter.retrofit.service.ApiService +import com.gh.gamecenter.video.upload.OnUploadListener +import com.gh.gamecenter.video.upload.UploadManager import com.lightgame.utils.Utils import com.zhihu.matisse.Matisse import com.zhihu.matisse.internal.utils.PathUtils @@ -27,6 +30,8 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo val chooseImagesUploadSuccess = MutableLiveData>() var uploadImageSubscription: Disposable? = null val mapImages = HashMap() + val localVideoList = ArrayList() + var currentUploadingVideo: LocalVideoEntity? = null //检查图片是否符合规则并上传图片 fun uploadPic(data: Intent) { @@ -106,4 +111,26 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo } }) } + + fun uploadVideo() { + if (localVideoList.isEmpty()) return + currentUploadingVideo = localVideoList[0] + UploadManager.createUploadTask(currentUploadingVideo!!.filePath, object : OnUploadListener { + override fun onProgressChanged(uploadFilePath: String, currentSize: Long, totalSize: Long, speed: Long) { + val percent = currentSize * 100 / totalSize.toFloat() + Utils.log("上传中...${percent.roundTo(1)}%") + } + + override fun onUploadSuccess(uploadFilePath: String, url: String) { + Utils.log("上传完成:$uploadFilePath--$url") + localVideoList.remove(currentUploadingVideo!!) + currentUploadingVideo = null + uploadVideo() + } + + override fun onUploadFailure(uploadFilePath: String, errorMsg: String) { + + } + }) + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/util/EntranceUtils.java b/app/src/main/java/com/gh/common/util/EntranceUtils.java index 095ade8041..b8a4044abf 100644 --- a/app/src/main/java/com/gh/common/util/EntranceUtils.java +++ b/app/src/main/java/com/gh/common/util/EntranceUtils.java @@ -235,6 +235,9 @@ public class EntranceUtils { public static final String KEY_IS_QA_FEEDBACK = "is_qa_feedback"; public static final String KEY_IS_CLICK_RECEIVE_BTN = "is_click_receive_btn"; public static final String KEY_SHOW_QUICK_LOGIN = "show_quick_login"; + public static final String KEY_VIDEO_LIST = "video_list"; + public static final String KEY_CHOOSE_FORUM_TYPE = "choose_forum_type"; + public static final String KEY_CHOOSE_MAX_COUNT = "choose_max_count"; public static void jumpActivity(Context context, Bundle bundle) { bundle.putBoolean(KEY_REQUIRE_REDIRECT, true); diff --git a/app/src/main/java/com/gh/gamecenter/entity/LocalVideoEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/LocalVideoEntity.kt new file mode 100644 index 0000000000..56a46dfb80 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/LocalVideoEntity.kt @@ -0,0 +1,13 @@ +package com.gh.gamecenter.entity + +import android.net.Uri +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class LocalVideoEntity( + var filePath: String = "", + var poster: String = "", + var contentUri: Uri? = null, + var duration: Long = 0 +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/forum/home/ForumHomeFragment.kt b/app/src/main/java/com/gh/gamecenter/forum/home/ForumHomeFragment.kt index 6fb9a95271..fd199c9a78 100644 --- a/app/src/main/java/com/gh/gamecenter/forum/home/ForumHomeFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/forum/home/ForumHomeFragment.kt @@ -39,6 +39,7 @@ import com.gh.gamecenter.qa.CommunityFragment import com.gh.gamecenter.qa.article.edit.ArticleEditActivity import com.gh.gamecenter.qa.questions.edit.QuestionEditActivity import com.gh.gamecenter.qa.recommends.AskRecommendsSubjectPageAdapter +import com.gh.gamecenter.qa.video.publish.VideoPublishActivity import com.gh.gamecenter.user.UserViewModel import com.google.android.material.appbar.AppBarLayout import kotterknife.bindView @@ -330,7 +331,7 @@ class ForumHomeFragment : BaseLazyTabFragment() { window?.setWindowAnimations(R.style.community_publication_animation) dialog.setContentView(contentView, params) dialog.show() - contentView.findViewById(R.id.community_edit_article).setOnClickListener { + contentView.findViewById(R.id.community_edit_article_container).setOnClickListener { context?.ifLogin("论坛首页", action = { checkStoragePermissionBeforeAction { showRegulationTestDialogIfNeeded { @@ -341,7 +342,7 @@ class ForumHomeFragment : BaseLazyTabFragment() { } }) } - contentView.findViewById(R.id.community_edit_question).setOnClickListener { + contentView.findViewById(R.id.community_edit_question_container).setOnClickListener { context?.ifLogin("论坛首页", action = { checkStoragePermissionBeforeAction { showRegulationTestDialogIfNeeded { @@ -352,6 +353,15 @@ class ForumHomeFragment : BaseLazyTabFragment() { } }) } + contentView.findViewById(R.id.community_edit_video_container).setOnClickListener { + checkStoragePermissionBeforeAction { + showRegulationTestDialogIfNeeded { + MtaHelper.onEvent("论坛首页", "发布", "发视频") + startActivity(VideoPublishActivity.getIntent(requireContext())) + dialog.dismiss() + } + } + } contentView.findViewById(R.id.community_edit_close).setOnClickListener { dialog.dismiss() } 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 0cc778948d..c923e4b623 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 @@ -28,7 +28,7 @@ import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.manager.UserManager 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.dialog.ChooseForumActivity import com.gh.gamecenter.qa.entity.ArticleDetailEntity import com.gh.gamecenter.qa.entity.ArticleDraftEntity import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment @@ -79,12 +79,17 @@ class ArticleEditActivity : BaseRichEditorActivity(), Keyb override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (requestCode == ARTICLE_DRAFT_REQUEST_CODE && resultCode == Activity.RESULT_OK) { - val draftEntity = data?.getParcelableExtra(ArticleDraftEntity::class.java.simpleName) + if (data == null || resultCode != Activity.RESULT_OK) return + if (requestCode == ARTICLE_DRAFT_REQUEST_CODE) { + val draftEntity = data.getParcelableExtra(ArticleDraftEntity::class.java.simpleName) if (draftEntity != null) { mViewModel.draftEntity = draftEntity setArticleDraft() } + } else if (requestCode == ChooseForumActivity.CHOOSE_FORUM_REQUEST) { + val community = data.getParcelableExtra(EntranceUtils.KEY_COMMUNITY_DATA) + mViewModel.mSelectCommunityData = community + setGameName() } } @@ -418,10 +423,7 @@ class ArticleEditActivity : BaseRichEditorActivity(), Keyb } private fun showSelectGameDialog() { - ChooseForumDialogFragment.show(this) { - mViewModel.mSelectCommunityData = it - setGameName() - } + ChooseForumActivity.startChooseForumActivity(this) } private fun setGameName() { diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt new file mode 100644 index 0000000000..f4cf1d7894 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt @@ -0,0 +1,111 @@ +package com.gh.gamecenter.qa.dialog + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.core.widget.doOnTextChanged +import androidx.fragment.app.Fragment +import com.gh.base.BaseActivity +import com.gh.base.adapter.FragmentAdapter +import com.gh.common.util.DisplayUtils +import com.gh.common.util.EntranceUtils +import com.gh.common.util.doOnEnd +import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.DialogChooseForumBinding +import com.gh.gamecenter.entity.CommunityEntity + +class ChooseForumActivity : BaseActivity() { + private lateinit var binding: DialogChooseForumBinding + private var mSearchResultFragment: ChooseForumContainerFragment? = null + private val mTabTitleList = arrayListOf("我的关注", "热门论坛") + private val mFragmentsList: ArrayList = arrayListOf() + + override fun getLayoutId(): Int = R.layout.dialog_choose_forum + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + DisplayUtils.transparentStatusBar(this) + binding = DialogChooseForumBinding.bind(mContentView) + + initViewPager() + binding.searchEt.doOnTextChanged { _, _, _, _ -> + if (binding.searchEt.text.isNullOrEmpty()) { + switchUI(false) + } else { + switchUI(true) + mSearchResultFragment?.setSearchKey(binding.searchEt.text.toString()) + } + } + binding.closeIv.setOnClickListener { finish() } + binding.maskView.alpha = 0f + binding.maskView.animate().alpha(1f).setDuration(300).start() + binding.maskView.setOnClickListener { binding.closeIv.performClick() } + binding.forumContainer.translationY = (DisplayUtils.getScreenHeight()).toFloat() + binding.forumContainer.animate().translationY(0f).setDuration(300).start() + } + + private fun initViewPager() { + mFragmentsList.clear() + mFragmentsList.add(ChooseForumContainerFragment.getInstance(ChooseForumContainerFragment.ChooseForumType.ATTENTION)) + mFragmentsList.add(ChooseForumContainerFragment.getInstance(ChooseForumContainerFragment.ChooseForumType.HOT)) + binding.viewPager.offscreenPageLimit = mFragmentsList.size + binding.viewPager.adapter = FragmentAdapter(supportFragmentManager, mFragmentsList, mTabTitleList) + binding.tabLayout.setupWithViewPager(binding.viewPager) + binding.tabIndicator.setupWithTabLayout(binding.tabLayout) + binding.tabIndicator.setupWithViewPager(binding.viewPager) + binding.tabIndicator.setIndicatorWidth(20) + } + + private fun switchUI(isSearch: Boolean) { + if (isSearch) { + binding.tabContainer.visibility = View.GONE + binding.line.visibility = View.GONE + binding.viewPager.visibility = View.GONE + binding.searchResultContainer.visibility = View.VISIBLE + + if (mSearchResultFragment == null || mSearchResultFragment?.isAdded == false) { + val beginTransaction = supportFragmentManager.beginTransaction() + mSearchResultFragment = supportFragmentManager.findFragmentByTag(ChooseForumContainerFragment::class.java.simpleName) as? ChooseForumContainerFragment + ?: ChooseForumContainerFragment.getInstance(ChooseForumContainerFragment.ChooseForumType.SEARCH) as ChooseForumContainerFragment + beginTransaction.replace(binding.searchResultContainer.id, mSearchResultFragment!!, ChooseForumContainerFragment::class.java.simpleName) + beginTransaction.commitAllowingStateLoss() + } + } else { + binding.tabContainer.visibility = View.VISIBLE + binding.line.visibility = View.VISIBLE + binding.viewPager.visibility = View.VISIBLE + binding.searchResultContainer.visibility = View.GONE + } + } + + fun chooseSuccess(community: CommunityEntity) { + val intent = Intent() + intent.putExtra(EntranceUtils.KEY_COMMUNITY_DATA, community) + setResult(Activity.RESULT_OK, intent) + finish() + } + + override fun finish() { + overridePendingTransition(0, 0) + binding.maskView.animate().alpha(0f).setDuration(300).start() + binding.root.animate() + .translationY(DisplayUtils.getScreenHeight().toFloat()) + .setDuration(300) + .doOnEnd { + super.finish() + } + .start() + } + + companion object { + const val CHOOSE_FORUM_REQUEST = 10 + + fun startChooseForumActivity(context: Activity) { + val intent = Intent(context, ChooseForumActivity::class.java) + context.overridePendingTransition(0, 0) + context.startActivityForResult(intent, CHOOSE_FORUM_REQUEST) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerAdapter.kt new file mode 100644 index 0000000000..17eb6129c1 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerAdapter.kt @@ -0,0 +1,39 @@ +package com.gh.gamecenter.qa.dialog + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.gh.base.BaseRecyclerViewHolder +import com.gh.common.util.MtaHelper +import com.gh.common.util.goneIf +import com.gh.gamecenter.baselist.ListAdapter +import com.gh.gamecenter.databinding.ForumItemBinding +import com.gh.gamecenter.entity.CommunityEntity +import com.gh.gamecenter.entity.ForumEntity +import com.gh.gamecenter.forum.detail.ForumDetailActivity +import com.gh.gamecenter.qa.entity.CommunitySelectEntity + +class ChooseForumContainerAdapter(content: Context, val onSelectCallback: ((entity: CommunityEntity) -> Unit)? = null) : ListAdapter(content) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return ForumItemViewHolder(ForumItemBinding.inflate(LayoutInflater.from(mContext), parent, false)) + } + + override fun getItemCount(): Int = mEntityList.size + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is ForumItemViewHolder) { + val forumEntity = mEntityList[position] + holder.binding.entity = forumEntity + holder.binding.forumIcon.displayGameIcon(forumEntity.game.getIcon(), forumEntity.game.iconSubscript) + holder.binding.followTv.visibility = View.GONE + holder.itemView.setOnClickListener { + onSelectCallback?.invoke(CommunityEntity(forumEntity.id, forumEntity.name, icon = forumEntity.game.getIcon(), iconSubscript = forumEntity.game.iconSubscript)) + } + } + } + + class ForumItemViewHolder(val binding: ForumItemBinding) : BaseRecyclerViewHolder(binding.root) +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt new file mode 100644 index 0000000000..c08df92906 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt @@ -0,0 +1,53 @@ +package com.gh.gamecenter.qa.dialog + +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.RecyclerView +import com.gh.common.util.EntranceUtils +import com.gh.gamecenter.baselist.ListAdapter +import com.gh.gamecenter.baselist.ListFragment +import com.gh.gamecenter.entity.CommunityEntity +import com.gh.gamecenter.entity.ForumEntity + +class ChooseForumContainerFragment : ListFragment() { + + private var mAdapter: ChooseForumContainerAdapter? = null + private var type: String = "" + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + type = arguments?.getString(EntranceUtils.KEY_CHOOSE_FORUM_TYPE) ?: "" + } + + override fun provideListAdapter(): ListAdapter<*> { + return mAdapter ?: ChooseForumContainerAdapter(requireContext()) { + if (requireActivity() is ChooseForumActivity) { + (requireActivity() as ChooseForumActivity).chooseSuccess(it) + } + }.apply { + mAdapter = this + } + } + + fun setSearchKey(key: String) { + + } + + override fun isAutomaticLoad(): Boolean = type != ChooseForumType.SEARCH.value + + override fun getItemDecoration(): RecyclerView.ItemDecoration? = null + + companion object { + fun getInstance(type: ChooseForumType): Fragment { + return ChooseForumContainerFragment().with(bundleOf(EntranceUtils.KEY_CHOOSE_FORUM_TYPE to type.value)) + } + } + + enum class ChooseForumType(val value: String) { + ATTENTION("attention"), + HOT("hot"), + SEARCH("search") + } +} diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt new file mode 100644 index 0000000000..ca56c64108 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt @@ -0,0 +1,20 @@ +package com.gh.gamecenter.qa.dialog + +import android.app.Application +import com.gh.gamecenter.baselist.ListViewModel +import com.gh.gamecenter.entity.ForumEntity +import com.gh.gamecenter.manager.UserManager +import com.gh.gamecenter.retrofit.RetrofitManager +import com.gh.gamecenter.retrofit.service.ApiService +import io.reactivex.Observable + +class ChooseForumContainerViewModel(application: Application) : ListViewModel(application) { + private val mApi: ApiService = RetrofitManager.getInstance(getApplication()).api + override fun provideDataObservable(page: Int): Observable> { + return mApi.getFollowsForum(UserManager.getInstance().userId) + } + + override fun mergeResultLiveData() { + mResultLiveData.addSource>(mListLiveData) { mResultLiveData.postValue(it) } + } +} \ No newline at end of file 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 deleted file mode 100644 index 492b4e543b..0000000000 --- a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumDialogFragment.kt +++ /dev/null @@ -1,74 +0,0 @@ -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/editor/LocalVideoAdapter.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/LocalVideoAdapter.kt index 146aeff7fa..d0851e313e 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/LocalVideoAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/LocalVideoAdapter.kt @@ -1,25 +1,23 @@ package com.gh.gamecenter.qa.editor +import android.content.Context import android.database.Cursor import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity import com.gh.base.BaseRecyclerViewHolder +import com.gh.common.util.ImageUtils import com.gh.common.util.TimeUtils +import com.gh.common.util.ToastUtils import com.gh.gamecenter.R import com.gh.gamecenter.databinding.LocalVideoItemBinding -import com.gh.gamecenter.databinding.PhotoPosterItemBinding -import com.gh.gamecenter.video.upload.view.UploadVideoActivity -import com.gh.gamecenter.video.videomanager.VideoManagerActivity import com.halo.assistant.HaloApp import com.zhihu.matisse.internal.entity.Item import com.zhihu.matisse.internal.entity.SelectionSpec import com.zhihu.matisse.internal.ui.adapter.RecyclerViewCursorAdapter import com.zhihu.matisse.internal.utils.PathUtils -class LocalVideoAdapter : RecyclerViewCursorAdapter(null) { - private val mImageResize = HaloApp.getInstance().application.resources.displayMetrics.widthPixels / 3 +class LocalVideoAdapter(val context: Context, val maxChooseSize: Int, val callback: (ArrayList) -> Unit) : RecyclerViewCursorAdapter(null) { + private val mSelectedVideoList = arrayListOf() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocalVideoPreviewViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.local_video_item, parent, false) @@ -27,22 +25,34 @@ class LocalVideoAdapter : RecyclerViewCursorAdapter } override fun onBindViewHolder(holder: LocalVideoPreviewViewHolder, cursor: Cursor?, position: Int) { - val item = Item.valueOf(cursor) - SelectionSpec.getInstance().imageEngine.loadThumbnail( - HaloApp.getInstance().application, mImageResize, null, - holder.binding.preview, item.contentUri) + ImageUtils.display(holder.binding.preview, "file:///${PathUtils.getPath(context, item.contentUri)}") holder.binding.durationTv.text = TimeUtils.formatVideoDuration(item.duration / 1000) + holder.binding.checkImageView.isChecked = mSelectedVideoList.contains(item) holder.itemView.setOnClickListener { - val path = PathUtils.getPath(holder.itemView.context, item.contentUri) - val intent = UploadVideoActivity.getIntent(holder.itemView.context, path, "本地视频", "", "") - (holder.itemView.context as AppCompatActivity).startActivityForResult(intent, VideoActivity.INSERT_VIDEO_CODE) + if (mSelectedVideoList.contains(item)) { + mSelectedVideoList.remove(item) + notifyItemChanged(position) + callback.invoke(mSelectedVideoList) + } else { + if (mSelectedVideoList.size < maxChooseSize) { + mSelectedVideoList.add(item) + notifyItemChanged(position) + callback.invoke(mSelectedVideoList) + } else { + ToastUtils.showToast("至多选择${maxChooseSize}条视频") + } + } } } override fun getItemViewType(position: Int, cursor: Cursor?): Int { return 0 } + + fun getSelectedVideoList(): ArrayList { + return mSelectedVideoList + } } class LocalVideoPreviewViewHolder(val binding: LocalVideoItemBinding) : BaseRecyclerViewHolder(binding.root) diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/LocalVideoFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/LocalVideoFragment.kt index abefa8c9f3..a8f59a1bcb 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/LocalVideoFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/LocalVideoFragment.kt @@ -8,12 +8,19 @@ import android.view.LayoutInflater import android.view.View import androidx.recyclerview.widget.GridLayoutManager import com.gh.base.fragment.BaseFragment +import com.gh.common.util.EntranceUtils import com.gh.common.util.dip2px +import com.gh.common.util.toColor +import com.gh.common.util.toDrawable import com.gh.common.view.GridSpacingItemDecoration +import com.gh.gamecenter.R import com.gh.gamecenter.databinding.ActivityEditorVideoBinding +import com.gh.gamecenter.entity.LocalVideoEntity import com.gh.gamecenter.video.upload.view.UploadVideoActivity +import com.shuyu.gsyvideoplayer.GSYVideoManager import com.zhihu.matisse.internal.entity.Album import com.zhihu.matisse.internal.model.AlbumMediaCollection +import com.zhihu.matisse.internal.utils.PathUtils class LocalVideoFragment : BaseFragment(), AlbumMediaCollection.AlbumMediaCallbacks { lateinit var binding: ActivityEditorVideoBinding @@ -31,10 +38,38 @@ class LocalVideoFragment : BaseFragment(), AlbumMediaCollection.AlbumMediaC super.onCreate(savedInstanceState) binding.reuseTvNoneData.text = "暂无数据~" binding.listRv.layoutManager = GridLayoutManager(requireContext(), 3) - binding.listRv.addItemDecoration(GridSpacingItemDecoration(3, 1F.dip2px(), false)) - mAdapter = LocalVideoAdapter() + binding.listRv.addItemDecoration(GridSpacingItemDecoration(3, 4F.dip2px(), false)) + val maxChooseCount = arguments?.getInt(EntranceUtils.KEY_CHOOSE_MAX_COUNT, 1) + mAdapter = LocalVideoAdapter(requireContext(), maxChooseCount ?: 1) { + binding.previewTv.isEnabled = it.isNotEmpty() + binding.confirmTv.isEnabled = it.isNotEmpty() + if (it.isEmpty()) { + binding.previewTv.setTextColor(R.color.text_cccccc.toColor()) + binding.confirmTv.alpha = 0.6f + } else { + binding.previewTv.setTextColor(R.color.text_666666.toColor()) + binding.confirmTv.alpha = 1f + } + binding.numTv.text = "${it.size}/${mAdapter.maxChooseSize}" + } + binding.numTv.text = "0/${mAdapter.maxChooseSize}" binding.listRv.adapter = mAdapter binding.listRefresh.isEnabled = false + + binding.previewTv.setOnClickListener { + val intent = PreviewVideoActivity.getIntent(requireContext(), mAdapter.getSelectedVideoList()) + requireActivity().startActivityForResult(intent, PREVIEW_VIDEO) + } + binding.confirmTv.setOnClickListener { + val localVideoList = arrayListOf() + mAdapter.getSelectedVideoList().forEach { + localVideoList.add(LocalVideoEntity(PathUtils.getPath(requireContext(), it.uri))) + } + val intent = Intent() + intent.putExtra(LocalVideoEntity::class.java.name, localVideoList) + requireActivity().setResult(Activity.RESULT_OK, intent) + requireActivity().finish() + } } override fun onAlbumMediaReset() { @@ -60,11 +95,9 @@ class LocalVideoFragment : BaseFragment(), AlbumMediaCollection.AlbumMediaC override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (data != null && requestCode == VideoActivity.INSERT_VIDEO_CODE) { - if (resultCode == UploadVideoActivity.RESULT_CODE_VIDEO) { - requireActivity().setResult(Activity.RESULT_OK, data) - requireActivity().finish() - } + if (data != null) { + requireActivity().setResult(Activity.RESULT_OK, data) + requireActivity().finish() } } @@ -73,4 +106,8 @@ class LocalVideoFragment : BaseFragment(), AlbumMediaCollection.AlbumMediaC mAlbumMediaCollection?.onDestroy() } + companion object { + const val PREVIEW_VIDEO = 100 + } + } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoActivity.kt new file mode 100644 index 0000000000..45421caa37 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoActivity.kt @@ -0,0 +1,34 @@ +package com.gh.gamecenter.qa.editor + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.gh.base.BaseActivity +import com.gh.common.util.DisplayUtils +import com.gh.common.util.EntranceUtils +import com.gh.gamecenter.R +import com.zhihu.matisse.internal.entity.Item + +class PreviewVideoActivity : BaseActivity() { + override fun getLayoutId(): Int { + return R.layout.activity_amway + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + DisplayUtils.transparentStatusBar(this) + + val containerFragment = supportFragmentManager.findFragmentByTag(PreviewVideoFragment::class.java.simpleName) + ?: PreviewVideoFragment().with(intent.extras) + // 若 placeholder 外层为 RelativeLayout 的话,会出现莫名的偏移 + supportFragmentManager.beginTransaction().replace(R.id.placeholder, containerFragment, PreviewVideoFragment::class.java.simpleName).commitAllowingStateLoss() + } + + companion object { + fun getIntent(context: Context,videos:ArrayList): Intent { + val intent = Intent(context, PreviewVideoActivity::class.java) + intent.putExtra(EntranceUtils.KEY_VIDEO_LIST,videos) + return intent + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoFragment.kt new file mode 100644 index 0000000000..7ccf0c0972 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/PreviewVideoFragment.kt @@ -0,0 +1,180 @@ +package com.gh.gamecenter.qa.editor + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder +import com.facebook.drawee.generic.RoundingParams +import com.facebook.drawee.view.SimpleDraweeView +import com.gh.base.fragment.BaseFragment +import com.gh.base.fragment.WaitingDialogFragment +import com.gh.common.util.* +import com.gh.common.view.GridSpacingItemColorDecoration +import com.gh.gamecenter.CropImageActivity +import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.FragmentPreviewVideoBinding +import com.gh.gamecenter.databinding.ItemVideoSelectorBinding +import com.gh.gamecenter.entity.LocalVideoEntity +import com.gh.gamecenter.video.poster.PosterEditActivity +import com.gh.gamecenter.video.upload.view.UploadVideoActivity +import com.lightgame.adapter.BaseRecyclerAdapter +import com.shuyu.gsyvideoplayer.GSYVideoManager +import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder +import com.zhihu.matisse.internal.entity.Item +import com.zhihu.matisse.internal.utils.PathUtils + +class PreviewVideoFragment : BaseFragment() { + private lateinit var mBinding: FragmentPreviewVideoBinding + private var mVideoItems: ArrayList = arrayListOf() + private var mProcessingDialog: WaitingDialogFragment? = null + private lateinit var mVideoSelectorAdapter: VideoSelectorAdapter + private val mLocalVideoList = arrayListOf() + override fun getLayoutId(): Int = 0 + + override fun getInflatedLayout(): View { + mBinding = FragmentPreviewVideoBinding.inflate(LayoutInflater.from(requireContext()), null, false) + return mBinding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + mVideoItems = arguments?.getParcelableArrayList(EntranceUtils.KEY_VIDEO_LIST) + ?: arrayListOf() + if (mVideoItems.isNotEmpty()) { + mVideoItems.forEach { + val localVideoEntity = LocalVideoEntity( + PathUtils.getPath(requireContext(), it.uri), + contentUri = it.contentUri, + duration = it.duration + ) + mLocalVideoList.add(localVideoEntity) + } + initVideo(mLocalVideoList[0]) + } + mBinding.numTv.text = "(1/${mVideoItems.size})" + mVideoSelectorAdapter = VideoSelectorAdapter(requireContext(), mLocalVideoList) { entity, position -> + mBinding.videoView.release() + mBinding.numTv.text = "(${position + 1}/${mVideoItems.size})" + initVideo(entity) + } + mBinding.videoSelectorRv.adapter = mVideoSelectorAdapter + mBinding.videoSelectorRv.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false) + mBinding.videoSelectorRv.addItemDecoration(GridSpacingItemColorDecoration(requireContext(), 8, 0, R.color.transparent)) + mBinding.confirmTv.setOnClickListener { + val intent = Intent() + intent.putExtra(LocalVideoEntity::class.java.name, mLocalVideoList) + requireActivity().setResult(Activity.RESULT_OK, intent) + requireActivity().finish() + } + + mBinding.changeCoverTv.setOnClickListener { + val item = mVideoItems[mVideoSelectorAdapter.selectPosition] + val intent = PosterEditActivity.getIntentByPath(requireContext(), PathUtils.getPath(requireContext(), item.uri)) + startActivityForResult(intent, UploadVideoActivity.REQUEST_CODE_IMAGE_CROP) + } + mBinding.backBtn.setOnClickListener { requireActivity().finish() } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (data == null || resultCode != Activity.RESULT_OK) return + if (requestCode == UploadVideoActivity.REQUEST_CODE_IMAGE_CROP) { + val imagePath = data.getStringExtra(CropImageActivity.RESULT_CLIP_PATH) ?: "" + if (imagePath.isNotEmpty()) { + uploadImage(imagePath) + } + } + } + + private fun uploadImage(imagePath: String) { + mProcessingDialog = WaitingDialogFragment.newInstance("图片上传中...", false) + mProcessingDialog?.show(requireActivity().supportFragmentManager, WaitingDialogFragment::class.java.name) + UploadImageUtils.uploadImage(UploadImageUtils.UploadType.poster, imagePath, object : UploadImageUtils.OnUploadImageListener { + override fun onSuccess(imageUrl: String) { + mProcessingDialog?.dismiss() + mLocalVideoList[mVideoSelectorAdapter.selectPosition].poster = imageUrl + mBinding.videoView.updateThumb(imageUrl) + } + + override fun onError(e: Throwable?) { + mProcessingDialog?.dismiss() + ToastUtils.showToast("上传失败") + } + + override fun onProgress(total: Long, progress: Long) {} + }) + } + + private fun initVideo(entity: LocalVideoEntity) { + GSYVideoOptionBuilder() + .setIsTouchWiget(false) + .setUrl(entity.filePath) + .setRotateViewAuto(false) + .setCacheWithPlay(false) + .setRotateWithSystem(false) + .setReleaseWhenLossAudio(true) + .setLooping(false) + .setShowFullAnimation(false) + .build(mBinding.videoView) + if (entity.poster.isNotEmpty()) { + mBinding.videoView.updateThumb(entity.poster) + } else { + mBinding.videoView.updateThumb("file:///${PathUtils.getPath(requireContext(), entity.contentUri)}") + } + } + + class VideoSelectorAdapter(context: Context, val localVideoList: ArrayList, val callback: (LocalVideoEntity, Int) -> Unit) : BaseRecyclerAdapter(context) { + var selectPosition: Int = 0 + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return VideoSelectorViewHolder(ItemVideoSelectorBinding.inflate(LayoutInflater.from(mContext), parent, false)) + } + + override fun getItemCount(): Int = localVideoList.size + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is VideoSelectorViewHolder) { + val item = localVideoList[position] + setPreviewBorder(holder.binding.preview, selectPosition == position) + ImageUtils.display(holder.binding.preview, "file:///${PathUtils.getPath(mContext, item.contentUri)}") + holder.binding.root.setOnClickListener { + selectPosition = position + callback.invoke(localVideoList[selectPosition], selectPosition) + notifyDataSetChanged() + } + } + } + + private fun setPreviewBorder(view: SimpleDraweeView, isSelected: Boolean) { + val params = RoundingParams() + params.setBorder(if (isSelected) R.color.white.toColor() else R.color.transparent.toColor(), 1f.dip2px().toFloat()) + params.setCornersRadius(4f.dip2px().toFloat()) + val build = GenericDraweeHierarchyBuilder.newInstance(mContext.resources) + .setRoundingParams(params) + .build() + view.hierarchy = build + } + } + + class VideoSelectorViewHolder(val binding: ItemVideoSelectorBinding) : RecyclerView.ViewHolder(binding.root) + + override fun onResume() { + super.onResume() + GSYVideoManager.onResume() + } + + override fun onPause() { + super.onPause() + GSYVideoManager.onPause() + } + + override fun onDestroy() { + super.onDestroy() + GSYVideoManager.releaseAllVideos() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/editor/VideoActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/editor/VideoActivity.kt index d4034d8471..584b3d3e8e 100644 --- a/app/src/main/java/com/gh/gamecenter/qa/editor/VideoActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/qa/editor/VideoActivity.kt @@ -17,6 +17,7 @@ import androidx.viewpager.widget.ViewPager import com.gh.base.ToolBarActivity import com.gh.base.adapter.FragmentAdapter import com.gh.base.fragment.BaseFragment_TabLayout +import com.gh.common.util.EntranceUtils import com.gh.common.util.viewModelProvider import com.gh.common.view.TabIndicatorView import com.gh.gamecenter.R @@ -48,6 +49,7 @@ class VideoActivity : ToolBarActivity(), AlbumCollection.AlbumCallbacks { private lateinit var mAlbumsSpinner: VideoAlbumsSpanner private lateinit var mAlbumsAdapter: VideoAlbumsAdapter private val mAlbumCollection = AlbumCollection() + private var mIsFirstAlbumLoad = true override fun getLayoutId(): Int = R.layout.activity_video_tablayout_viewpager @@ -55,11 +57,13 @@ class VideoActivity : ToolBarActivity(), AlbumCollection.AlbumCallbacks { super.onCreate(savedInstanceState) mViewModel = viewModelProvider() - mViewModel.obsListData.observe(this, Observer { - initViewPager() - initAlbumsSpinner() - }) - mViewModel.load(LoadType.REFRESH) +// mViewModel.obsListData.observe(this, Observer { +// initViewPager() +// initAlbumsSpinner() +// }) +// mViewModel.load(LoadType.REFRESH) + initViewPager() + initAlbumsSpinner() } private fun initAlbumsSpinner() { @@ -95,19 +99,22 @@ class VideoActivity : ToolBarActivity(), AlbumCollection.AlbumCallbacks { mAlbumCollection.loadAlbums() } - override fun onAlbumLoad(cursor: Cursor?) { - mAlbumsAdapter.swapCursor(cursor) - mBaseHandler.post { - cursor?.moveToPosition(mAlbumCollection.currentSelection) - val album = Album.valueOf(cursor) - if (album.isAll && SelectionSpec.getInstance().capture) { - album.addCaptureCount() - } - if (mLocalVideoFragment?.isAdded == true) { - mLocalVideoFragment?.loadVideos(album) + if (mIsFirstAlbumLoad) { + mIsFirstAlbumLoad = false + mAlbumsAdapter.swapCursor(cursor) + mBaseHandler.post { + cursor?.moveToPosition(mAlbumCollection.currentSelection) + val album = Album.valueOf(cursor) + if (album.isAll && SelectionSpec.getInstance().capture) { + album.addCaptureCount() + } + if (mLocalVideoFragment?.isAdded == true) { + mLocalVideoFragment?.loadVideos(album) + } } } + } override fun onAlbumReset() { @@ -115,14 +122,15 @@ class VideoActivity : ToolBarActivity(), AlbumCollection.AlbumCallbacks { } private fun initViewPager() { - if (!mViewModel.obsListData.value.isNullOrEmpty()) { + /*if (!mViewModel.obsListData.value.isNullOrEmpty()) { mTabTitleList.add("视频库") mFragmentsList.add(OnlineVideoFragment()) } else { mTabIndicatorView.visibility = View.GONE - } + }*/ + mTabIndicatorView.visibility = View.GONE mTabTitleList.add("本地视频") - mLocalVideoFragment = LocalVideoFragment() + mLocalVideoFragment = LocalVideoFragment().apply { arguments = intent.extras } mFragmentsList.add(mLocalVideoFragment!!) mViewPager.offscreenPageLimit = mFragmentsList.size mViewPager.adapter = FragmentAdapter(supportFragmentManager, mFragmentsList, mTabTitleList) @@ -146,9 +154,11 @@ class VideoActivity : ToolBarActivity(), AlbumCollection.AlbumCallbacks { private fun provideTabView(tabTitle: String): View { val binding = TabItemChooseVideoBinding.inflate(LayoutInflater.from(this), null, false) binding.tabTitle.text = tabTitle - if (mViewModel.obsListData.value.isNullOrEmpty()) { - binding.tabTitle.setTextColor(ContextCompat.getColor(this, R.color.text_333333)) - } +// if (mViewModel.obsListData.value.isNullOrEmpty()) { +// binding.tabTitle.setTextColor(ContextCompat.getColor(this, R.color.text_333333)) +// } + binding.tabTitle.setTextColor(ContextCompat.getColor(this, R.color.text_333333)) + binding.tabTitle.textSize = 16f if (tabTitle == "本地视频") { binding.tabArrow.visibility = View.VISIBLE binding.root.setOnTouchListener { _, _ -> @@ -169,10 +179,10 @@ class VideoActivity : ToolBarActivity(), AlbumCollection.AlbumCallbacks { } companion object { - const val INSERT_VIDEO_CODE = 414 - - fun getIntent(context: Context): Intent { - return Intent(context, VideoActivity::class.java) + fun getIntent(context: Context, maxChooseCount: Int = 1): Intent { + return Intent(context, VideoActivity::class.java).apply { + putExtra(EntranceUtils.KEY_CHOOSE_MAX_COUNT, maxChooseCount) + } } } } \ 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 60a988cb5a..df9294cf9e 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 @@ -20,6 +20,7 @@ import androidx.core.widget.addTextChangedListener import androidx.databinding.DataBindingUtil import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders +import com.gh.base.BaseRichEditorActivity.Companion.INSERT_VIDEO_CODE import com.gh.base.ToolBarActivity import com.gh.base.fragment.WaitingDialogFragment import com.gh.common.AppExecutor @@ -38,7 +39,7 @@ 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.article.edit.ArticleEditActivity -import com.gh.gamecenter.qa.dialog.ChooseForumDialogFragment +import com.gh.gamecenter.qa.dialog.ChooseForumActivity import com.gh.gamecenter.qa.editor.VideoActivity import com.gh.gamecenter.qa.entity.CommunityVideoEntity import com.gh.gamecenter.qa.entity.QuestionDraftEntity @@ -84,12 +85,12 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { @SuppressLint("Recycle") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - - if (requestCode == MEDIA_STORE_REQUEST && resultCode == RESULT_OK) { + if (data == null || resultCode != Activity.RESULT_OK) return + if (requestCode == MEDIA_STORE_REQUEST) { val selectedPics = Matisse.obtainResult(data) mViewModel.validatePic(selectedPics) - } else if (requestCode == VideoActivity.INSERT_VIDEO_CODE && resultCode == RESULT_OK) { - val videoEntity = data?.getParcelableExtra(MyVideoEntity::class.java.simpleName) + } else if (requestCode == INSERT_VIDEO_CODE) { + val videoEntity = data.getParcelableExtra(MyVideoEntity::class.java.simpleName) if (videoEntity != null) { mViewModel.videoLiveData.postValue(CommunityVideoEntity( id = videoEntity.id, @@ -98,13 +99,22 @@ 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) + } else if (requestCode == QUESTION_DRAFT_REQUEST_CODE) { + val draftEntity = data.getParcelableExtra(QuestionDraftEntity::class.java.simpleName) if (draftEntity != null) { mViewModel.questionDraftEntity = draftEntity setQuestionDraft(draftEntity) mViewModel.getQuestionDraftContent(draftEntity.id) } + } else if (requestCode == ChooseForumActivity.CHOOSE_FORUM_REQUEST) { + val community = data.getParcelableExtra(EntranceUtils.KEY_COMMUNITY_DATA) + mViewModel.communityEntity = community + if (mViewModel.questionEntity != null) { + mViewModel.questionEntity?.community?.id = community?.id ?: "" + mViewModel.questionEntity?.community?.name = community?.name ?: "" + } + setForumName() + mBinding.vm = mViewModel } } @@ -494,7 +504,7 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { object : EmptyCallback { override fun onCallback() { MtaHelper.onEvent("发表问题", "插入链接", "插入视频") - startActivityForResult(VideoActivity.getIntent(this@QuestionEditActivity), VideoActivity.INSERT_VIDEO_CODE) + startActivityForResult(VideoActivity.getIntent(this@QuestionEditActivity), INSERT_VIDEO_CODE) } }) } @@ -574,15 +584,7 @@ class QuestionEditActivity : ToolBarActivity(), KeyboardHeightObserver { } private fun showSelectGameDialog() { - ChooseForumDialogFragment.show(this) { - mViewModel.communityEntity = it - if (mViewModel.questionEntity != null) { - mViewModel.questionEntity?.community?.id = it.id - mViewModel.questionEntity?.community?.name = it.name - } - setForumName() - mBinding.vm = mViewModel - } + ChooseForumActivity.startChooseForumActivity(this) } // Limits of EditText diff --git a/app/src/main/java/com/gh/gamecenter/qa/video/PreviewVideoView.kt b/app/src/main/java/com/gh/gamecenter/qa/video/PreviewVideoView.kt new file mode 100644 index 0000000000..71e8e94f15 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/video/PreviewVideoView.kt @@ -0,0 +1,59 @@ +package com.gh.gamecenter.qa.video + +import android.content.Context +import android.net.Uri +import android.util.AttributeSet +import android.view.Surface +import android.view.View +import android.widget.ImageView +import com.facebook.drawee.view.SimpleDraweeView +import com.gh.common.util.ImageUtils +import com.gh.gamecenter.R +import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer +import com.squareup.picasso.Picasso + +class PreviewVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : StandardGSYVideoPlayer(context, attrs) { + + var thumbImage: SimpleDraweeView = findViewById(R.id.thumbImage) + + override fun getLayoutId(): Int { + return R.layout.layout_preview_video + } + + + /******************* 下方两个重载方法,在播放开始前不屏蔽封面,不需要可屏蔽 ********************/ + + override fun onSurfaceUpdated(surface: Surface) { + super.onSurfaceUpdated(surface) + if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) { + mThumbImageViewLayout.visibility = View.INVISIBLE + } + } + + fun updateThumb(url: String) { + ImageUtils.display(thumbImage, url) + } + + override fun setViewShowState(view: View?, visibility: Int) { + if (view === mThumbImageViewLayout && visibility != View.VISIBLE) { + return + } + super.setViewShowState(view, visibility) + } + + /********************************各类UI的状态显示*********************************************/ + + override fun touchSurfaceMoveFullLogic(absDeltaX: Float, absDeltaY: Float) { + super.touchSurfaceMoveFullLogic(absDeltaX, absDeltaY) + //不给触摸快进,如果需要,屏蔽下方代码即可 + mChangePosition = false + //不给触摸音量,如果需要,屏蔽下方代码即可 + mChangeVolume = false + //不给触摸亮度,如果需要,屏蔽下方代码即可 + mBrightness = false + } + + override fun touchDoubleUp() { + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishActivity.kt new file mode 100644 index 0000000000..adf1a5b69f --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishActivity.kt @@ -0,0 +1,26 @@ +package com.gh.gamecenter.qa.video.publish + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import com.gh.gamecenter.NormalActivity +import com.gh.gamecenter.R + +class VideoPublishActivity : NormalActivity() { + override fun getLayoutId(): Int = R.layout.activity_video_publish + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + mToolbar.navigationIcon = null + findViewById(R.id.backBtn).setOnClickListener { finish() } + } + + companion object { + @JvmStatic + fun getIntent(context: Context): Intent { + return getTargetIntent(context, VideoPublishActivity::class.java, VideoPublishFragment::class.java) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishFragment.kt new file mode 100644 index 0000000000..8c32d62cd7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishFragment.kt @@ -0,0 +1,293 @@ +package com.gh.gamecenter.qa.video.publish + +import android.app.Activity +import android.content.Intent +import android.media.MediaMetadataRetriever +import android.media.ThumbnailUtils +import android.net.Uri +import android.os.Bundle +import android.provider.MediaStore +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import androidx.core.content.ContextCompat +import androidx.core.widget.doOnTextChanged +import com.gh.base.BaseRichEditorActivity +import com.gh.common.runOnUiThread +import com.gh.common.util.* +import com.gh.gamecenter.CropImageActivity +import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.FragmentVideoPublishBinding +import com.gh.gamecenter.entity.CommunityEntity +import com.gh.gamecenter.entity.LocalVideoEntity +import com.gh.gamecenter.entity.VideoEntity +import com.gh.gamecenter.normal.NormalFragment +import com.gh.gamecenter.qa.dialog.ChooseForumActivity +import com.gh.gamecenter.qa.editor.VideoActivity +import com.gh.gamecenter.video.poster.PosterEditActivity +import com.gh.gamecenter.video.upload.OnUploadListener +import com.gh.gamecenter.video.upload.UploadManager +import com.gh.gamecenter.video.upload.view.VideoFileEntity +import com.lightgame.download.FileUtils +import java.io.File + +class VideoPublishFragment : NormalFragment() { + + private lateinit var mBinding: FragmentVideoPublishBinding + private lateinit var mViewModel: VideoPublishViewModel + private var mVideoFileEntity: VideoFileEntity? = null + private lateinit var mMenuDraft: MenuItem + private lateinit var mMenuPost: MenuItem + + override fun getLayoutId(): Int = 0 + + override fun getInflatedLayout(): View { + mBinding = FragmentVideoPublishBinding.inflate(LayoutInflater.from(requireContext()), null, false) + return mBinding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setNavigationTitle("发视频") + initMenu(R.menu.menu_answer_post) + mMenuDraft = getItemMenu(R.id.menu_draft) + mMenuPost = getItemMenu(R.id.menu_answer_post) + mViewModel = viewModelProvider() + + mBinding.title.filters = arrayOf(TextHelper.getFilter(50, "标题最多50个字")) + mBinding.title.doOnTextChanged { text, start, count, after -> + if (text?.contains("\n") == true) { + mBinding.title.setText(text.toString().replace("\n", "")) + mBinding.title.setSelection(start) + return@doOnTextChanged + } + if (PatternUtils.isHasSpace(text.toString())) { + mBinding.title.setText(PatternUtils.replaceSpace(text.toString())) + mBinding.title.setSelection(start) + return@doOnTextChanged + } + checkPostButtonEnable() + } + + mBinding.uploadButton.setOnClickListener { + PermissionHelper.checkStoragePermissionBeforeAction(requireActivity(), object : EmptyCallback { + override fun onCallback() { + startActivityForResult(VideoActivity.getIntent(requireContext(), 1), BaseRichEditorActivity.INSERT_VIDEO_CODE) + } + }) + } + mBinding.videoPosterPatchHint.setOnClickListener { startMediaStore() } + mBinding.forumContainer.setOnClickListener { + ChooseForumActivity.startChooseForumActivity(requireActivity()) + } + mBinding.chooseActivityContainer.setOnClickListener { + //选择活动 + } + mBinding.deleteVideoIv.setOnClickListener { + + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (data == null || resultCode != Activity.RESULT_OK) return + if (requestCode == BaseRichEditorActivity.INSERT_VIDEO_CODE) { + val localVideoList = data.getParcelableArrayListExtra(LocalVideoEntity::class.java.name) + ?: arrayListOf() + if (localVideoList.isNotEmpty()) { + initUpload(localVideoList[0]) + } + } else if (requestCode == REQUEST_CODE_IMAGE_CROP) { + val imagePath = data.getStringExtra(CropImageActivity.RESULT_CLIP_PATH) + mBinding.videoPoster.setImageURI("file://$imagePath") + mVideoFileEntity?.poster = imagePath ?: "" + } else if (requestCode == ChooseForumActivity.CHOOSE_FORUM_REQUEST) { + val community = data.getParcelableExtra(EntranceUtils.KEY_COMMUNITY_DATA) + mViewModel.communityEntity = community + setForumName() + } + } + + private fun initUpload(localVideoEntity: LocalVideoEntity) { + val videoPath = localVideoEntity.filePath + if (videoPath.isEmpty() || !File(videoPath).exists()) { + handleFileNotFound() + return + } + if (localVideoEntity.poster.isNotEmpty()) { + ImageUtils.display(mBinding.videoPoster, localVideoEntity.poster) + } else { + val thumbnail = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.MINI_KIND) + mBinding.videoPoster.setImageBitmap(thumbnail) + } + + mBinding.uploadButton.visibility = View.GONE + mBinding.videoPosterMask.visibility = View.GONE + mBinding.pauseButton.setOnClickListener { + when { + UploadManager.isUploading(videoPath) -> { + mBinding.uploadStatus.text = "上传已暂停" + mBinding.uploadInfoContainer.visibility = View.VISIBLE + mBinding.uploadSpeed.visibility = View.GONE + mBinding.pauseButton.setImageResource(R.drawable.upload_resume) + mBinding.pauseButton.visibility = View.VISIBLE + UploadManager.cancelTask(videoPath) + } + File(videoPath).exists() -> { + mBinding.uploadStatus.text = "视频上传中..." + mBinding.uploadInfoContainer.visibility = View.VISIBLE + mBinding.pauseButton.setImageResource(R.drawable.upload_pause) + mBinding.pauseButton.visibility = View.VISIBLE + createUploadTask(videoPath) + } + else -> { + handleFileNotFound() + toast("上传失败,视频文件不存在") + } + } + } + val videoFile = File(videoPath) + val retriever = MediaMetadataRetriever() + val fileUri = Uri.fromFile(videoFile) + retriever.setDataSource(requireContext(), fileUri) + val time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) ?: "0" + val timeInSecond = java.lang.Long.parseLong(time) / 1000 + retriever.release() + + var format = "" + tryWithDefaultCatch { + val mimeType = FileUtils.getFileMimeType(requireContext(), videoPath) + if (mimeType != null) { + val split = mimeType.split("/") + format = if (split.count() >= 2) { + split[1] + } else { + mimeType + } + } + } + + mVideoFileEntity = VideoFileEntity(videoPath, null, localVideoEntity.poster, timeInSecond, videoFile.length(), format) + createUploadTask(videoPath) + } + + private fun createUploadTask(videoPath: String) { + mBinding.uploadStatus.text = "视频上传中..." + UploadManager.createUploadTask(videoPath, object : OnUploadListener { + override fun onProgressChanged(uploadFilePath: String, currentSize: Long, totalSize: Long, speed: Long) { + runOnUiThread { + mBinding.uploadInfoContainer.visibility = View.VISIBLE + mBinding.uploadStatus.text = "视频上传中..." + mBinding.uploadSpeed.visibility = View.VISIBLE + mBinding.pauseButton.visibility = View.VISIBLE + mBinding.uploadSpeed.text = (SpeedUtils.getSpeed(speed) + "预计还需" + SpeedUtils.getRemainTime(totalSize, currentSize, speed)) + mBinding.uploadProgress.update(((360 * currentSize) / totalSize).toInt(), "") + } + } + + override fun onUploadSuccess(uploadFilePath: String, url: String) { + runOnUiThread { + handleUploadSuccess(url) + } + } + + override fun onUploadFailure(uploadFilePath: String, errorMsg: String) { + runOnUiThread { + if (!File(uploadFilePath).exists()) { + handleFileNotFound() + toast("上传失败,视频文件不存在") + } else { + mBinding.uploadStatus.text = "网络错误,中断上传" + mBinding.pauseButton.setImageResource(R.drawable.upload_resume) + mBinding.pauseButton.visibility = View.VISIBLE + toast("网络错误,请检查网络正常后再重试") + } + mBinding.uploadSpeed.visibility = View.GONE + } + } + }) + } + + private fun handleFileNotFound() { + mBinding.uploadButton.visibility = View.VISIBLE + mBinding.uploadInfoContainer.visibility = View.GONE + mBinding.videoPosterMask.visibility = View.VISIBLE + } + + private fun handleUploadSuccess(url: String) { + mBinding.uploadButton.visibility = View.GONE + mBinding.uploadInfoContainer.visibility = View.GONE + mBinding.videoPosterMask.visibility = View.GONE + mBinding.videoPosterPatchHint.visibility = View.VISIBLE + mBinding.uploadProgress.update(360, "") + mVideoFileEntity?.url = url + } + + private fun setForumName() { + if (mViewModel.communityEntity != null) { + mBinding.chooseForumTv.text = mViewModel.communityEntity?.name + mBinding.forumIconView.visibility = View.VISIBLE + mBinding.forumIconView.displayGameIcon(mViewModel.communityEntity?.icon, mViewModel.communityEntity?.iconSubscript) + mBinding.forumContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_shape_f8_radius_4) + mBinding.chooseForumTv.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(requireContext(), R.drawable.ic_article_edit_choose_forum_arrow_gray), null) + mBinding.chooseForumTv.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_333333)) + } + } + + private fun checkPostButtonEnable() { + + } + + override fun onMenuItemClick(menuItem: MenuItem?) { + super.onMenuItemClick(menuItem) + when (menuItem?.itemId) { + R.id.menu_answer_post -> { + + } + R.id.menu_draft -> { + + } + } + } + + private fun startMediaStore() { + try { + PermissionHelper.checkStoragePermissionBeforeAction(requireContext(), object : EmptyCallback { + override fun onCallback() { + var intent: Intent? = null + when { + mVideoFileEntity?.url?.isNotEmpty() == true -> { + val videoEntity = VideoEntity(length = mVideoFileEntity?.length + ?: 0, url = mVideoFileEntity?.url ?: "") + intent = PosterEditActivity.getIntentByVideo(requireContext(), videoEntity) + } + mVideoFileEntity?.path?.isNotEmpty() == true -> { + intent = PosterEditActivity.getIntentByPath(requireContext(), mVideoFileEntity?.url + ?: "") + } + else -> { + throwExceptionInDebug("video not found") + } + } + startActivityForResult(intent, REQUEST_CODE_IMAGE_CROP) + } + }) + } catch (e: Exception) { + toast(R.string.media_image_hint) + e.printStackTrace() + } + } + + override fun onDestroy() { + super.onDestroy() + val path = mVideoFileEntity?.path + if (path != null && UploadManager.isUploading(path)) { + UploadManager.cancelTask(path) + } + } + + companion object { + const val REQUEST_CODE_IMAGE_CROP = 101 + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishViewModel.kt new file mode 100644 index 0000000000..41a3cd9508 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/qa/video/publish/VideoPublishViewModel.kt @@ -0,0 +1,9 @@ +package com.gh.gamecenter.qa.video.publish + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import com.gh.gamecenter.entity.CommunityEntity + +class VideoPublishViewModel(application: Application) : AndroidViewModel(application) { + var communityEntity: CommunityEntity? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/video/upload/view/UploadVideoActivity.kt b/app/src/main/java/com/gh/gamecenter/video/upload/view/UploadVideoActivity.kt index 927256cc0f..2f7a74b5b4 100644 --- a/app/src/main/java/com/gh/gamecenter/video/upload/view/UploadVideoActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/video/upload/view/UploadVideoActivity.kt @@ -584,7 +584,8 @@ class UploadVideoActivity : ToolBarActivity() { } else { val localVideoPoster = application.cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".jpg" try { - val bmp = ThumbnailUtils.createVideoThumbnail(mVideoFileEntity?.path ?: "", MediaStore.Images.Thumbnails.MINI_KIND) + val bmp = ThumbnailUtils.createVideoThumbnail(mVideoFileEntity?.path + ?: "", MediaStore.Images.Thumbnails.MINI_KIND) // bmp 可能为空 FileOutputStream(localVideoPoster).use { out -> bmp?.compress(Bitmap.CompressFormat.PNG, 100, out) @@ -728,7 +729,7 @@ class UploadVideoActivity : ToolBarActivity() { } } } - mVideoFileEntity = VideoFileEntity(videoPath, null, timeInSecond, videoFile.length(), format) + mVideoFileEntity = VideoFileEntity(videoPath, null, "", timeInSecond, videoFile.length(), format) createUploadTask(videoPath) } diff --git a/app/src/main/java/com/gh/gamecenter/video/upload/view/VideoFileEntity.kt b/app/src/main/java/com/gh/gamecenter/video/upload/view/VideoFileEntity.kt index 58dc296f92..0161bb4d02 100644 --- a/app/src/main/java/com/gh/gamecenter/video/upload/view/VideoFileEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/video/upload/view/VideoFileEntity.kt @@ -3,7 +3,8 @@ package com.gh.gamecenter.video.upload.view data class VideoFileEntity( val path: String, var url: String?, - val length: Long, - val size: Long, + var poster: String, + var length: Long = 0, + var size: Long = 0, val format: String ) \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/community_edit_article.webp b/app/src/main/res/drawable-xxhdpi/community_edit_article.webp index 05d8cfd60dd97c2dba226753f15f70555da02f22..5fb8624587ee1de8eb52699ee3d2a4e7a91ca90e 100644 GIT binary patch literal 7496 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 Y)DMIo7d-%1>_>u|uG}F=000000FgY-ivR!s diff --git a/app/src/main/res/drawable-xxhdpi/community_edit_close.png b/app/src/main/res/drawable-xxhdpi/community_edit_close.png new file mode 100644 index 0000000000000000000000000000000000000000..8383082598e06159325153f2c77345529c1b194d GIT binary patch literal 765 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKw1|+Ti+$;i8jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(;Zvw#`F1}W^m|1ySwfhpb7#W5s< z_3bRjyh8>8uCp(#-co%eG~wbr?y%S`+PgHu8Na;^?F#xo$z$D9mE`Juju|?RJsZ>i z%`Q~fR#TpSR4GAl14jgl4wD#T_W@J42NgDUk4klK6@9tmef0hJ-(O#r{5o{{>it{W zYA5tveaC+P!h@HQ-nAx^`Z`p4*lX>@yN`NbHnDfK{+i6byVNgi-{PA&-%RG8-~V@8 zMC_c0Cmu}g{4mKc zp^e20vk$FeUhZ_gZ7GBI!i)Uf{N+ElzjEBIy~X|N6ZN&5=e_*i`R1(^_vsE*DV>^& z4T&{OQn81eT3d~^3}jRsE+?*LsJk&2Hzjn(Q{SU;w$?x2>-G=e^bk`-271W+4s24g~U8!;s5jf0x&*rdYrHLlI(JQPIH3N;hA&S`TDE1 j@ot7CiU!vQVagx4ePUWaIG8>O03|(7S3j3^P67Zb-qhqbnbH)i z+$&94S|-f(L21m|(k|XA&9|{${&G;-bLnf8UzCyOTo=1j#&)(A!CD#2K!fO{j6QL) zk;!P$Re@wQQgBi*Pr)emS^=d!#-D=95%L)10Kd-Sz85oYkgBI$o#@OV50S@RG`Zbi#;kX-lYn5`cC4KZ@e3>oA=Tv z;C$(k^(5UVGP;7<44r}``&?jwPy+AFTr>TAx^BqWIFB{kZgn*6~)iZA{&*`k)hQOBgtpdtF#s!q7!3Z`0jm zN@23s^v@~SH=Z!x&ARO{2De@23Ybn-`PJfI9>Uf|785e^*R0l;tkjz%Ke8wkN;@!G1N4K~1N5-`LBHixaCRcW;e&B- z00qwiyz$hH??E7Yo*}dI0Yyh45D8Ff49O$}e5b!UU-Q2nPENGo<}WnsGPfcFN->VQ zpn0HW(Aq`Y6xKL!?veSvn8nFCaB8d7A==q!iB3}={E=KWm;eC&|0fLfm5nZTM4i3) zT`}rALTCR3?4ITK4V2#dhjmD}p9lJ;nqt&SYPj)-@IO&=>IRsHja2Vf{$1{0MRMgn zV?Cx~$G^)Ti7DxS_|73`f;@zdI?Z$fD#&$s!buk>@kqLOW97jgwv)}=G#svxfzNyx zawJJDe0ulY=)VW!l+`1Mo3S8M0Cv+o^ZPE`JS_e$6Y zSV#X*n9E?LJpWgY*XW`QDqazPcKAUY4!Z-8?ArLV-Ur^J`ppr7}66Gjwr1h-T zdDkxq68yS3_7C=MBWBQ$$fb>`;1`Nj!LRe7#^_B0{sI2>8T_ z({0sr^oxufv#(qLV$~p@JJsa~-ik}VcVSxj+G&r$n99s(DbK$@5g zvwjfx+3eKXY(ve;O(r@4GldZL3D=it_;d7;(h=;`v} z4nO|!e%JwYUS6=odK6<9H^AonP4}$B*DZ6GI7srJYYfjU#N%?lJRm{#VVvdOc>xv8 zlpKE*vaC*h-Kx4)e5#YTqTiYLc{cKxrdf7GH$)uq%4-v6VWk-e{whbcgA~~FP@x%+ zeq-MVqJOXbv{177yTMe0K5Jb@tC;Zo5Q@yJ7M13I_jEoXzKDh_mikH)*?7v(A}_bi zW0j*B47&cK$TS$LK)@&g8COC49!Ow!p&LbWmp$s9`4x=v>`sgLl= zMpx3>3^8<{+YG<|65?NQWRS4q2U}DewQKvG%c@ebdnDtSu~dI}3TS66ECI35S*7^o zUgE?CG;>knzY0lR42zW+T`SRw@;w^`4-GAOJ@da=9i`(ROXSW3Cl&sgMqa{loJzE@ e=bQmnUwrj`dW-JvJE-96-&%iLqiIK}0002_KaUas diff --git a/app/src/main/res/drawable-xxhdpi/community_edit_question.webp b/app/src/main/res/drawable-xxhdpi/community_edit_question.webp index d312d27892a13c02d7842754ed274915a6406f72..c093c8cfa8b9147184f52ce4ae04c11676ffbea5 100644 GIT binary patch literal 7224 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 G5r6=_y(m=x literal 4656 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 diff --git a/app/src/main/res/drawable-xxhdpi/community_edit_video.webp b/app/src/main/res/drawable-xxhdpi/community_edit_video.webp new file mode 100644 index 0000000000000000000000000000000000000000..2a7459bff8e36b368c6aa808a4f1bbba79428c26 GIT binary patch literal 6944 zcmV+*8{gzoNk&E(8vp=TMM6+kP&il$0000G0002L006%L06|PpNSqA-009|=ZQC}G z?Id0QU)&=i`X7GKc@MG#pnnBiX?S*yg0^j#m_O_t3=uH_BE1c*N_1`8c5IU*p(4w6 z_t>^=+gh`=WY3a4^8;+#wrv|_E5C*NexLV?$nSf{Gy9QOL`FnR0A1U*6iH6Em}QYq z|NkkH$;`|w4aAGcsLWQZCGXrm4G|MC0cW`o&vDE<_;2sfcsYhPL*x#Q1?Z~J_cgKXbJtWPdi}4LfO_1-3J-l7-T=8Ign=84y2+|S!+i} z3uBvsOiVPkp$%RHct$`g3p!{7mWZrUCHO8#`zul4lx|LwD_S87Ah z=BVj~+h~xJ;Z@)8n|$pr>OOq$SNKNX^_zX^>wh;@SBJArFZ&t{4RSb7ztdCq>CJn- z`nUL!pZQnUSLb)=u(`dtg{CFm{(XMH)jj;$FaI^4{qs*=x0z;XJn0q|sc2dzWZv~7 zzWvpG{g$uw>>qsm>Uwc@3JXth!q8}5{}aCb)qVcxE4=d8KXY|*4js^;m^7Mi{!`rd zkKX%F{^f2kN8E!$Z34u|+B<*t>#iQaH^1;#K7M74u|F5KI%{TNWZ(DuK_1BW{Kvn0 zYQQ;m?SRyc&fwCtNB{WemSHFzaGu4)>j}+Uf3*koBY*G{mNDBIeJin;tY7RG zdtg8Phd+3`Od(cwX4=~tCcfrR@$mk!e}6k;(#&*Qvul>n$OK>W$9sTZe}!~#(}~Vo zyG4_ejmQ`M$sXj7zpoaRwu0PcW1Gn|p~=u&e~}0JgD;!Ws-%>C=d6tenwwhV>Y#;uk*99%s++{Fs3+a~jkU5ao1S5w-^Hs?2F+N^#1i@}Tk z+Tm;DXrn<)jL>-W4KIh!|5IEqw?h;}%b88K`MNI0*ZhOq92|F=AtR;+-{^wyfq!#F zW*MQ*K_>eNU;UDJ;m=)hYacnYL4!tUc*7UGB;N7+(K5r>cZvoX8JYBzU6MC{^)uWu zgVB=XO+zNk&297LE(-tb-(G28V3L!~qG=jU^y2mO#V?Eh@;7g1t}u+F*Uk)+NpoR* z=1*W4>l`?KZ6FiV7riWA{_Qgiv+9hdv9_4t9WKjP|IUGNa*%dtG7Xxn@4hhn!H+M- z%nXv_4Z>u|J1>nt^Bipt5BwdG{UYcGvw zLXKwJ25kzZ*IgRVQ>aZ&=FF(bvrFTdsA##%HnPSGm&OZMvS!+;Nb| z<#81W@)(n#n@eMYBzN6%GP*P(M?0&m?ZR9dgLYZ#*!k(wNFIAj$pxEQI-@qqHeDvk zwrp#6Zq_c3tS$e&*=3h)=cG#{os<6=*(KCnwYi`>?_}t53GMz@);3)pZF&;^_wPFj z*Tcd+{BP)LxEleRf2~Fu0jF6Fx*9gaZmS*0YGlA-hksd(tAX7vmRm&rwi-8xTdZXA z?^ffM$uj>pt8p`Hs)e`9Vc{IDv;h%*wi>?xky0zIx&kQD{$w?7X+;4nPU?!tNwu&N z_}Xd++)-KR7$Bp? zGo-XZ_*T{;w;-*QZmR_q#1E`RL{PzE(4GwnDDtkgxIz?AT6CAJS^-4yb^ln2f82OR5kOi+*(iu8ivH$JD{+0JD2fO&R}m3W ze9cN+i6SDR3|~u?j^9*Y>2i3_U;hxd?l2w6iJNL_{_{7w9NznfZ|BO;V^9TEH&fH? z7k$m8@aX;jf?NARn2td@tUmjtFNJsfa~w9f%zx@ z?Dh&{40DZX+N>>56oo4P^h;j?Z~ZNwhT9p-8YG>fqG+$`6R&#o@ZJ1_e+swuBV&I6 zrAkGVs=xd0hi`tvix_5%^%|4)R14X+MW6eZ?|tar`#axvH8ZxGVTg{QC=_k^x8LER zd-i8$Y-boU_UE)0QILA)*M8Vu?lZ>B3_I7(+807CRM0nm(?j;`c{4MZSuhMa9El>^ zlx;U(?IC-4HZz%A|}T&=e=#yU(B=b)^$Nw(GN-}X>FeSJ0C zs}mVmoDozxyXwu)AExKeJ7o-vgB@9;ARTBU?|9uq^!y#NF=Lz@bmDZ@s2raY`NYHX zicZZK>loXt9ScEXW@8s0`0zvX>;qTY8N-Zq5W1777_!b{sb?Q}SU&Kq7LA!cjB#WrI*=%*-ri$(@FX5{z|5)>-C#f9OBmf6t!2ZxrD~oNdk=Gpc3AI@=HY#$WbFKYHKv zN9Q+w;C6ep&Men8GsZaFa(?z5F$}Y1wl6l*eC{v({Ga>V|B3tJbI)F$=YPpi88b7KM6%{|2P|4?MG(;p&CQF~_T6SeUWzGF*pan@oE(EGNrbHJ?oe6* zK}4J|O%Nk8(6qBik<&~qS{-bf24+$uggkBm0TC1vG);qSTju6=ckHN~KW3pM+O6H0 z)Pf+QS$py3_Ih$SOfMZrQd9@Vc9tk2XrViiQUF0vn5AiOAWSp|+}m&>XfrS{jG{$H z9&00wpfwuAXvvTX^^Pi{q|l*ZOp+zr9+Q+dhzyM!%m^A9JQgHQl+150|gh`_jMuo>1&Km7vh(Wel^Z0GB0WreJHlqgxHh<6B_$4 zWIHa#PM`%rJ365!Lb_6B&=3sSk9)KeXxW~~`Q4G#u+7O}$bQ_romktPJl5v%I-|uP z`*BZqYTxe69-GXZO-_z`z5}N_^kmyDD%LOncr|YM8-pkJR)czBMH3&kJ z%mbZQnSZlCdf)dxum92dfPZlFk@hA1v-TbRN$YI>&;LKD1ONU_53xPgJ-{~i!W`+} zckH9Jy{dPzzz603)4x;wq^2o)XN}*5ub2A(e;EGB>rMVw{eQYIbAM0&;P(dpUHuEw zC)oe(Kd_(c*Zva7Zfp2=u?jJ+g1OkHnW>W+T56GAv*7gW6=q}XjtjUe-47C!1p6#@ z>`tw{k2QeEVl+v`80>X1@~|$|`;zhH8yQDw4YzJ*ee*rnIguW%Dg*U(4HgjXLngjD zCE3()>6x5MyfNmmPcmX+uWstKm6h}pR^Km~Sp(xKt?3mUc`cQ>#-s6r<#mUx8NRrYWRROGIDxi{{ z(;bxCsc2!u{2Qn5RP5l&+NT8fXrAVPFZXS|32|7C&t?vT_~qYD&DsUz)GR=QX(jH% znZmzjahy$7RK@R6Q)WC^x>fu_(5M{O>2JThIBgRDHvh0EFB7AT7ui!=6VCfa0092` zoZO>zK!{+|r&e6g57y}fIW1YbegNZ-t4#EUC|$nQRZs_b*Yr5Ku0LN>o7-(sE(^yK znhN<}5dZk6cp#WM$n%#HMap)o-P2_kmRkGy>g~0h8uNHV^`(o?D%Q>q_;2b-Z%F4X zZ_@x&f?D(2u!?)fMgLZAz>rSOS~rjxh(l{akLC_`5Ya+PTg}p5# z1H)z3iz|Sq+YW3Rl~$W= zGiL+lHho6=88Ts{?T8Zi`s{Yy*2zcJ(AerpB*%BjZpDE{|Mtbo&D9U!57cf}({>+06zD&9f2e{PZYQj>M0^ z9b>IkWnS+W)sdhc>MCHJ%bsm|=sICBMq=J3Z+h6{ig_1UMVKw_g%tR*K?6}Itgxi} z7)BwdBB3)-s2a1@ch(OHHY@CIXc&LNiB%72m`v&vtOH1=KWjC~{opVl8N^7*7Iv%x z<`dEYpD+bbs}33GSo<$I8#h_b1R#ougyJX?<8cYi>3|8H%1cZA84r8vu}Su*A}hXnKAmt-aWeHHq|-(>x7GG z{`>av>`w0Xi>=~D7u`8=NdiL{xOgLD_cFcdy6P|2!|nNlg&rJRz|Xx!&nyPKzwOn2 z*x&5ra)kxulH&jXx$k@NHQqXr5}&9~r8e2;R(NUdl()YhvkQ=VwmhB+47kVb81>j}r#PlT#Smw&#*pC30uk626Ihoc2a zDVt&+f4-iG$w3};g0*cgfao{Hga*XC%D!j5qbgCO%3#+i%fGAT$L2Ri8A_tjfRn@$ zX$MNR-g*}5-HrP_$}47(qPcD>@2`$9Lau!KtxK-Hwa|@`ETU6@@NdUzoac3EKo+pH z5TR1ySx=U_xnELC*ar=)VEKSA7VpTrasj=kffr8HDB#2xfS*hiW8w{D6X3#dahdWq z$nWmBwXMM2M!{r+5uX3xGv5-cz-i95TWTiNNu=I8$PNFY?agEm((*-^$;ooMxcTsG zBrHL%ezuUJ@R>53HDCl3pCLiwP%p`sf6IZHhT+Ov{mvA}XdRvzNA$w!WK*z#^dJ^J zjja8uA((I)GY?>xF`(C`jovw|h9mSU-{>)SM2Gu}*<-)-GEyeNuZ5Ud8`6W9U%men zk4?-8*i=ThSB{A5LK2zlHlBJq9jR$7pmU!V~s z>u?UCb8pAoIKFjlYdzS|Oc%9b=saIgy_RY}EeSG>Z5EICmyj z!)*5O96WZI1MQ)oa|%%=U0eW8QI1$qgI&*GemI}fJR>z6;{CE9pYy*q{ws8vWA52qS($b%vXxh!&omaPZ(cPq682QY~GHF#;HQp7`17$8>k&kc|Y4 zWY+u>KaV`j$CX*7Pn}pO+jivYO-WB|+DW8%p#if3q{TADIdQG3uZQ^IY>*J3J|a^} zYe7ID$Zvd2*|q3Ltj6nO?U9rnFl=`=vsoCZLAU z({=Fi=DSME_ak*_txw@4v=-Ip<<_ot<-0g*QjG7mWVnzfw^8jyr2;2GYjN%_r>(2V z2U3AXGBkKXk&hg-tb*6DZ{VT8tmPMo@L%iZ?Hf-i$!#J`-Mm-2XK_4OfXgL$y5Q>y znjZh407Hg0Vvq7Avx#ZI-)rVNR`%r8{e=5u_i?|yHoLBQtM=tGz#tIar=A5O{~Hq5 zg$q~0^U8*UPDRZ6BYYNh6p)da%kazxCWKg#1vwbnw6N+ElrBJN`%iznh>%j~ihE63 z`xXJUJW<1$5z-i`YRyTvh};F+*?$AjR481AFLAWCm@zKbM<$C&MO9F?N(PdBy^Rr^ z@Cz8Y;Xd7c!=Q}=?=xYc_6#boxS0!9A%u>4wtOC@5ROC$)L$H|DOWB4&A%Dukf-zl zyJK3ifjfksJZ=r^ZTSaK&D5Z!Ja?XMa6HBFshXQdJ>8lTtQK1(Fw@ zUt4)i1BIg#PRFp&L1w6zBN{5lf2V;xA<{E~lQ{pBUE{OV)Cv5#6T7QKi@cows5BxN z=)55q?MxVuz8U$Hqsg6+x`(c2<&>390UX^1HC!CBB^L&{G&0*tbe@JVBUWDmt0sM= zN)yNMH$dK2Y8K~ae$d8Xl?cgD|5R$*46b=w8R!iG0&$E^0~_;Y_=wdBM!+^8C{&0AQRyY zTTn*vut{HUEJW1UG-D-E(V@x2TG$~ZByW%=pQ?X-SvfK@bI@(TOuP0K7UkZ?9C%ql zCw_0D{G)N}g47Da(%YXN@Kmj)bzEWwTq9HY{#Yh4LxE3A`EzA{kxw(d!NYpv3su4+ znR0|MEbK!8C)*~>0=x=A013#PhFU#(75TY{24@pqUO)&UAH~#g6TwM$#2EDrtc2PE md)FuGE1Q!px@b?={yt_8U60NqKn{!q^o#@Np&0N0000120jI?5&VBlU|vcEZ7UNT=l_P#>XvR^wE;vpZQvV+TU%x5dF*T$5IMZ?ps&|T7y|8RA$x))tH-vnp`4Sk_wgsIK4*59e^N7z=z7Ftp2Crj$o&2E=|4`?D=p%feGQJP~ z&}aERZideZX8asthR-<%W{v_@P&gps0ssI|5CEM4Dlh;r06vj8m`J6gA|Wn2_yDjH z32XqdB|%eO7X2s85{CW{7aydV&3J%xfb#*+ThIggPf(Xam;LW!fA9FKDb30_eQZFE z1#l0e%<#QE><{Dt>j1Kw`I;Lh=3#k@HZ?b13c-U}Ei4_Ghw$zCY%A{6qaH5 z9a^3oh4;kNL;wK(`+EC}!5{t&keJbpF-dfDwKf_Oa;$+~ShM?V%|JYJJt%2kOBrq< z=@*M-iu?5sEtL@dxkJY>v;`Net6;+xRtzy@E-&unf&m!L=-1r_Itw+j7sPyM27Iqd zSz`@sl}m;0KaYT~h0T$+TC|FG>d&04bCz1@l_;c~bwBCLhU`HnBD)_om%|n7@44&B zMyMHBy>yYfwEtX`^7+}uL;*T0DcHvAGTWPxS6(3C#8J~*uGd2j5E_-0n!P`rT_@Ev zM38uHz`62IWuE5y%SEU;)Mi~IGJB83IjVd!FzHej;WcsP_W9Ap$-GF;Kpx>U25KZ3 z^n~AQyQQ(L{KEk}qaW=XhvLQeLA2YUFaVMGI|)*LYBDe28i>kfkhZg#OL3+H(I|o| zj(a+$RXkUlfH!|KUDspj=EAX73DAOTUDUrdAJRpq>K2UtPzzCI=u1@*Jv<0m9r_lhnV2GS`kv-(#J(b8P#|RP_!#QA!$-OuJY+=tcp!I^ zlf1PtNGy#w_0B#$kR}h5Rk~JzZB|(6-={aeFeZzpxaab25*%#!>LFO}Ar@bkc6YCX z_z%jEi@s!}^Npg59|RhP%YLnH+>FrJjk_r{@3^1dOSy}cu*5J*DTOON)dHkI4LVUC zN)~!}W&0oF{C9C}E`2LjjsS}}**adjyH@rd20Hj8Wm;S=c^KbvaoVZiNdk;iDi#kY o5*P`T;eqfz7}bQ-&4!Ram%~xA&Udc}*eG}k@cdvF!X$tI0E7(PHUIzs literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_del_video.png b/app/src/main/res/drawable-xxhdpi/ic_del_video.png new file mode 100644 index 0000000000000000000000000000000000000000..f37d1eeb974e1e9e744e0cf96a636a1fcc855eea GIT binary patch literal 1921 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 w$|{o5Yrk2fT0;HnV;-9j7Co%XHq)$ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/bg_change_cover_btn.xml b/app/src/main/res/drawable/bg_change_cover_btn.xml new file mode 100644 index 0000000000..1d2e5fd0e9 --- /dev/null +++ b/app/src/main/res/drawable/bg_change_cover_btn.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_round_stroke_0dot5_eee_999.xml b/app/src/main/res/drawable/border_round_stroke_0dot5_eee_999.xml new file mode 100644 index 0000000000..2e24f2006c --- /dev/null +++ b/app/src/main/res/drawable/border_round_stroke_0dot5_eee_999.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_editor_video.xml b/app/src/main/res/layout/activity_editor_video.xml index fbf97bbd5c..7eface2233 100644 --- a/app/src/main/res/layout/activity_editor_video.xml +++ b/app/src/main/res/layout/activity_editor_video.xml @@ -6,22 +6,71 @@ android:background="@color/white" android:orientation="vertical"> - - + android:layout_marginLeft="2dp" + android:layout_marginRight="2dp"> - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/community_edit_window.xml b/app/src/main/res/layout/community_edit_window.xml index 857ab0022d..590c50dbf9 100644 --- a/app/src/main/res/layout/community_edit_window.xml +++ b/app/src/main/res/layout/community_edit_window.xml @@ -6,87 +6,103 @@ - + app:layout_constraintTop_toTopOf="parent"> - + + + + + + - + + + + + + + + - - - + app:layout_constraintStart_toEndOf="@+id/community_edit_question_container" + app:layout_constraintTop_toTopOf="parent"> + + + + + + - - - + app:layout_constraintRight_toRightOf="parent" /> \ 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 index 30b893105c..29dbff9d52 100644 --- a/app/src/main/res/layout/dialog_choose_forum.xml +++ b/app/src/main/res/layout/dialog_choose_forum.xml @@ -2,14 +2,23 @@ + android:layout_height="match_parent" + android:background="@color/transparent" + android:focusable="true" + android:focusableInTouchMode="true"> + + + android:background="@drawable/game_detail_more_dialog_background"> - + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@+id/line" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_preview_video.xml b/app/src/main/res/layout/fragment_preview_video.xml new file mode 100644 index 0000000000..53ee8687d7 --- /dev/null +++ b/app/src/main/res/layout/fragment_preview_video.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_video_publish.xml b/app/src/main/res/layout/fragment_video_publish.xml new file mode 100644 index 0000000000..bfe9e6002e --- /dev/null +++ b/app/src/main/res/layout/fragment_video_publish.xml @@ -0,0 +1,278 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_video_selector.xml b/app/src/main/res/layout/item_video_selector.xml new file mode 100644 index 0000000000..34fa87a15e --- /dev/null +++ b/app/src/main/res/layout/item_video_selector.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_preview_video.xml b/app/src/main/res/layout/layout_preview_video.xml new file mode 100644 index 0000000000..333348787d --- /dev/null +++ b/app/src/main/res/layout/layout_preview_video.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/local_video_item.xml b/app/src/main/res/layout/local_video_item.xml index e5b3c1bd23..4819f1391d 100644 --- a/app/src/main/res/layout/local_video_item.xml +++ b/app/src/main/res/layout/local_video_item.xml @@ -8,20 +8,33 @@ + app:roundingBorderColor="@color/black_alpha_10" + app:roundingBorderWidth="0.5dp" /> + #0D000000 #1A000000 #4D000000 + #99000000 #66000000 #80000000 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 417428d210..06a72e0c7f 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -69,6 +69,13 @@ + +