From 9c5036204c66c455578693425cf70559f72d7f4d Mon Sep 17 00:00:00 2001 From: Cris Barreiro Date: Fri, 2 Aug 2024 10:04:18 +0200 Subject: [PATCH] Add a fullscreen dialog for Duck Player info in landscape --- .../app/browser/BrowserTabFragment.kt | 62 ++++++++++++++++--- .../duckplayer/api/DuckPlayerBottomSheet.kt | 15 +++++ .../duckplayer/api/DuckPlayerFragment.kt | 55 ++++++++++++++++ 3 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerFragment.kt diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index b9d6cf32b94b..3197ec4bdc5e 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -22,7 +22,11 @@ import android.annotation.SuppressLint import android.app.Activity.RESULT_OK import android.app.ActivityOptions import android.app.PendingIntent -import android.content.* +import android.content.ActivityNotFoundException +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent import android.content.pm.ActivityInfo import android.content.pm.PackageManager import android.content.pm.ResolveInfo @@ -31,7 +35,12 @@ import android.graphics.Color import android.graphics.Typeface import android.graphics.drawable.ColorDrawable import android.net.Uri -import android.os.* +import android.os.Build +import android.os.Bundle +import android.os.Environment +import android.os.Handler +import android.os.Looper +import android.os.Message import android.print.PrintAttributes import android.print.PrintManager import android.provider.MediaStore @@ -40,8 +49,14 @@ import android.text.Spannable import android.text.SpannableString import android.text.Spanned import android.text.style.StyleSpan -import android.view.* -import android.view.View.* +import android.view.ContextMenu +import android.view.KeyEvent +import android.view.MenuItem +import android.view.View +import android.view.View.GONE +import android.view.View.OnFocusChangeListener +import android.view.View.VISIBLE +import android.view.ViewGroup import android.view.ViewGroup.LayoutParams import android.view.inputmethod.EditorInfo import android.webkit.PermissionRequest @@ -53,7 +68,9 @@ import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebView.FindListener import android.webkit.WebView.HitTestResult -import android.webkit.WebView.HitTestResult.* +import android.webkit.WebView.HitTestResult.IMAGE_TYPE +import android.webkit.WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE +import android.webkit.WebView.HitTestResult.UNKNOWN_TYPE import android.widget.EditText import android.widget.FrameLayout import android.widget.TextView @@ -68,13 +85,21 @@ import androidx.core.net.toUri import androidx.core.text.HtmlCompat import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY import androidx.core.text.toSpannable -import androidx.core.view.* +import androidx.core.view.doOnLayout +import androidx.core.view.isInvisible +import androidx.core.view.isVisible +import androidx.core.view.postDelayed import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment import androidx.fragment.app.commitNow import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.transaction -import androidx.lifecycle.* +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.distinctUntilChanged +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.webkit.JavaScriptReplyProxy import androidx.webkit.WebMessageCompat @@ -156,7 +181,11 @@ import com.duckduckgo.app.browser.viewstate.SavedSiteChangedViewState import com.duckduckgo.app.browser.webshare.WebShareChooser import com.duckduckgo.app.browser.webview.WebContentDebugging import com.duckduckgo.app.browser.webview.WebViewBlobDownloadFeature -import com.duckduckgo.app.cta.ui.* +import com.duckduckgo.app.cta.ui.Cta +import com.duckduckgo.app.cta.ui.CtaViewModel +import com.duckduckgo.app.cta.ui.DaxBubbleCta +import com.duckduckgo.app.cta.ui.HomePanelCta +import com.duckduckgo.app.cta.ui.OnboardingDaxDialogCta import com.duckduckgo.app.di.AppCoroutineScope import com.duckduckgo.app.fire.fireproofwebsite.data.FireproofWebsiteEntity import com.duckduckgo.app.fire.fireproofwebsite.data.website @@ -251,6 +280,7 @@ import com.duckduckgo.downloads.api.DownloadsFileActions import com.duckduckgo.downloads.api.FileDownloader import com.duckduckgo.downloads.api.FileDownloader.PendingFileDownload import com.duckduckgo.duckplayer.api.DuckPlayerBottomSheet +import com.duckduckgo.duckplayer.api.DuckPlayerFragment import com.duckduckgo.duckplayer.api.DuckPlayerSettingsNoParams import com.duckduckgo.js.messaging.api.JsCallbackData import com.duckduckgo.js.messaging.api.JsMessageCallback @@ -287,10 +317,16 @@ import javax.inject.Inject import javax.inject.Named import javax.inject.Provider import kotlin.coroutines.CoroutineContext -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.Runnable +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.json.JSONObject import timber.log.Timber @@ -1546,7 +1582,13 @@ class BrowserTabFragment : is Command.LaunchScreen -> launchScreen(it.screen, it.payload) is Command.HideOnboardingDaxDialog -> hideOnboardingDaxDialog(it.onboardingCta) is Command.OpenDuckPlayerSettings -> globalActivityStarter.start(binding.root.context, DuckPlayerSettingsNoParams) - is Command.OpenDuckPlayerInfo -> DuckPlayerBottomSheet.newInstance().show(childFragmentManager, null) + is Command.OpenDuckPlayerInfo -> { + if (context?.resources?.configuration?.orientation == Configuration.ORIENTATION_LANDSCAPE) { + DuckPlayerFragment.newInstance().show(childFragmentManager, null) + } else { + DuckPlayerBottomSheet.newInstance().show(childFragmentManager, null) + } + } else -> { // NO OP } diff --git a/duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerBottomSheet.kt b/duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerBottomSheet.kt index 7526d49410d9..5de73c696f63 100644 --- a/duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerBottomSheet.kt +++ b/duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerBottomSheet.kt @@ -1,5 +1,7 @@ package com.duckduckgo.duckplayer.api +import android.app.Dialog +import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -7,6 +9,8 @@ import android.view.ViewGroup import com.airbnb.lottie.LottieCompositionFactory import com.airbnb.lottie.LottieDrawable import com.duckduckgo.duckplayer.api.databinding.BottomSheetDuckPlayerBinding +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment class DuckPlayerBottomSheet : BottomSheetDialogFragment() { @@ -29,6 +33,17 @@ class DuckPlayerBottomSheet : BottomSheetDialogFragment() { return binding.root } + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog + dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED + return dialog + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + dismiss() + } + companion object { fun newInstance(): DuckPlayerBottomSheet = DuckPlayerBottomSheet() diff --git a/duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerFragment.kt b/duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerFragment.kt new file mode 100644 index 000000000000..32b09a1c9b41 --- /dev/null +++ b/duckplayer/duckplayer-api/src/main/java/com/duckduckgo/duckplayer/api/DuckPlayerFragment.kt @@ -0,0 +1,55 @@ +package com.duckduckgo.duckplayer.api + +import android.content.res.Configuration +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams +import android.view.WindowManager +import androidx.fragment.app.DialogFragment +import com.airbnb.lottie.LottieCompositionFactory +import com.airbnb.lottie.LottieDrawable +import com.duckduckgo.duckplayer.api.databinding.BottomSheetDuckPlayerBinding + +class DuckPlayerFragment : DialogFragment() { + + private lateinit var binding: BottomSheetDuckPlayerBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + binding = BottomSheetDuckPlayerBinding.inflate(inflater, container, false) + LottieCompositionFactory.fromRawRes(context, R.raw.duckplayer) + binding.duckPlayerAnimation.setAnimation(R.raw.duckplayer) + binding.duckPlayerAnimation.playAnimation() + binding.duckPlayerAnimation.repeatCount = LottieDrawable.INFINITE + binding.dismissButton.setOnClickListener { + dismiss() + } + return binding.root + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(STYLE_NO_TITLE, com.duckduckgo.mobile.android.R.style.Widget_DuckDuckGo_DialogFullScreen) + } + override fun onStart() { + super.onStart() + dialog?.window?.let { window -> + window.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) + } + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + dismiss() + } + companion object { + fun newInstance(): DuckPlayerFragment = + DuckPlayerFragment() + } +}