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 05d8cfd60d..5fb8624587 100644 Binary files a/app/src/main/res/drawable-xxhdpi/community_edit_article.webp and b/app/src/main/res/drawable-xxhdpi/community_edit_article.webp differ 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 0000000000..8383082598 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/community_edit_close.png differ diff --git a/app/src/main/res/drawable-xxhdpi/community_edit_close.webp b/app/src/main/res/drawable-xxhdpi/community_edit_close.webp deleted file mode 100644 index 2bd31942fc..0000000000 Binary files a/app/src/main/res/drawable-xxhdpi/community_edit_close.webp and /dev/null differ 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 d312d27892..c093c8cfa8 100644 Binary files a/app/src/main/res/drawable-xxhdpi/community_edit_question.webp and b/app/src/main/res/drawable-xxhdpi/community_edit_question.webp differ 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 0000000000..2a7459bff8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/community_edit_video.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_choose_activity.webp b/app/src/main/res/drawable-xxhdpi/ic_choose_activity.webp new file mode 100644 index 0000000000..38af24a83d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_choose_activity.webp differ 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 0000000000..f37d1eeb97 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_del_video.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_upload_video_btn.webp b/app/src/main/res/drawable-xxhdpi/icon_upload_video_btn.webp new file mode 100644 index 0000000000..1a9d18b696 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_upload_video_btn.webp differ 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 @@ + +