From fadd2d31af9b13bd77c59550f644f4dc23d7b4a8 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 15 Jul 2024 13:52:38 +0200 Subject: [PATCH] feat: share dialog redesign (including copy link feature) --- .../libretube/constants/PreferenceKeys.kt | 1 + .../libretube/ui/dialogs/ShareDialog.kt | 127 +++++++++++------- app/src/main/res/layout/dialog_share.xml | 121 +++++++++++++---- 3 files changed, 174 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt index 56fce5f7c..44fd2425d 100644 --- a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt +++ b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt @@ -122,6 +122,7 @@ object PreferenceKeys { const val CLEAR_WATCH_HISTORY = "clear_watch_history" const val CLEAR_WATCH_POSITIONS = "clear_watch_positions" const val SHARE_WITH_TIME_CODE = "share_with_time_code" + const val SELECTED_SHARE_HOST = "selected_share_host" const val CONFIRM_UNSUBSCRIBE = "confirm_unsubscribing" const val CLEAR_BOOKMARKS = "clear_bookmarks" const val MAX_CONCURRENT_DOWNLOADS = "max_parallel_downloads" diff --git a/app/src/main/java/com/github/libretube/ui/dialogs/ShareDialog.kt b/app/src/main/java/com/github/libretube/ui/dialogs/ShareDialog.kt index 704b3c265..08938b559 100644 --- a/app/src/main/java/com/github/libretube/ui/dialogs/ShareDialog.kt +++ b/app/src/main/java/com/github/libretube/ui/dialogs/ShareDialog.kt @@ -4,6 +4,7 @@ import android.app.Dialog import android.content.Intent import android.os.Bundle import androidx.core.view.isVisible +import androidx.core.widget.addTextChangedListener import androidx.fragment.app.DialogFragment import com.github.libretube.R import com.github.libretube.constants.IntentData @@ -13,11 +14,14 @@ import com.github.libretube.db.DatabaseHolder.Database import com.github.libretube.enums.ShareObjectType import com.github.libretube.extensions.parcelable import com.github.libretube.extensions.serializable +import com.github.libretube.helpers.ClipboardHelper import com.github.libretube.helpers.PreferenceHelper import com.github.libretube.obj.ShareData import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking +import okhttp3.HttpUrl +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull class ShareDialog : DialogFragment() { private lateinit var id: String @@ -34,72 +38,76 @@ class ShareDialog : DialogFragment() { } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - var shareOptions = arrayOf( - getString(R.string.piped), - getString(R.string.youtube) - ) - val instanceUrl = getCustomInstanceFrontendUrl() + val customInstanceUrl = getCustomInstanceFrontendUrl().toHttpUrlOrNull() val shareableTitle = shareData.currentChannel ?: shareData.currentVideo ?: shareData.currentPlaylist.orEmpty() - // add instanceUrl option if custom instance frontend url available - if (instanceUrl.isNotEmpty()) { - shareOptions += getString(R.string.instance) - } val binding = DialogShareBinding.inflate(layoutInflater) + binding.shareHostGroup.check( + when (PreferenceHelper.getInt(PreferenceKeys.SELECTED_SHARE_HOST, 0)) { + 0 -> binding.youtube.id + 1 -> binding.piped.id + else -> if (customInstanceUrl != null) binding.customInstance.id else 0 + } + ) + + binding.shareHostGroup.setOnCheckedChangeListener { _, _ -> + binding.linkPreview.text = generateLinkText(binding, customInstanceUrl) + PreferenceHelper.putInt( + PreferenceKeys.SELECTED_SHARE_HOST, when { + binding.youtube.isChecked -> 0 + binding.piped.isChecked -> 1 + else -> 2 + } + ) + } + + if (customInstanceUrl != null) { + binding.customInstance.isVisible = true + binding.customInstance.text = customInstanceUrl.host + } + if (shareObjectType == ShareObjectType.VIDEO) { + binding.timeStampSwitchLayout.isVisible = true + binding.timeCodeSwitch.isChecked = PreferenceHelper.getBoolean( + PreferenceKeys.SHARE_WITH_TIME_CODE, + false + ) + binding.timeCodeSwitch.setOnCheckedChangeListener { _, isChecked -> + binding.timeStampInputLayout.isVisible = isChecked + PreferenceHelper.putBoolean(PreferenceKeys.SHARE_WITH_TIME_CODE, isChecked) + binding.linkPreview.text = generateLinkText(binding, customInstanceUrl) + } + binding.timeStamp.addTextChangedListener { + binding.linkPreview.text = generateLinkText(binding, customInstanceUrl) + } + binding.timeStamp.setText((shareData.currentPosition ?: 0L).toString()) + if (binding.timeCodeSwitch.isChecked) { + binding.timeStampInputLayout.isVisible = true + } + } + + binding.copyLink.setOnClickListener { + ClipboardHelper.save(requireContext(), text = binding.linkPreview.text.toString()) + } + + binding.linkPreview.text = generateLinkText(binding, customInstanceUrl) + return MaterialAlertDialogBuilder(requireContext()) .setTitle(getString(R.string.share)) - .setItems(shareOptions) { _, which -> - val host = when (which) { - 0 -> PIPED_FRONTEND_URL - 1 -> YOUTUBE_FRONTEND_URL - // only available for custom instances - else -> instanceUrl - } - var url = when { - shareObjectType == ShareObjectType.VIDEO && host == YOUTUBE_FRONTEND_URL -> "$YOUTUBE_SHORT_URL/$id" - shareObjectType == ShareObjectType.VIDEO -> "$host/watch?v=$id" - shareObjectType == ShareObjectType.PLAYLIST -> "$host/playlist?list=$id" - else -> "$host/channel/$id" - } - - if (shareObjectType == ShareObjectType.VIDEO && binding.timeCodeSwitch.isChecked) { - url += "&t=${binding.timeStamp.text}" - } - + .setView(binding.root) + .setPositiveButton(R.string.share) { _, _ -> val intent = Intent(Intent.ACTION_SEND) - .putExtra(Intent.EXTRA_TEXT, url) + .putExtra(Intent.EXTRA_TEXT, binding.linkPreview.text) .putExtra(Intent.EXTRA_SUBJECT, shareableTitle) .setType("text/plain") val shareIntent = Intent.createChooser(intent, getString(R.string.shareTo)) requireContext().startActivity(shareIntent) } - .apply { - if (shareObjectType == ShareObjectType.VIDEO) { - setupTimeStampBinding(binding) - setView(binding.root) - } - } .show() } - private fun setupTimeStampBinding(binding: DialogShareBinding) { - binding.timeCodeSwitch.isChecked = PreferenceHelper.getBoolean( - PreferenceKeys.SHARE_WITH_TIME_CODE, - false - ) - binding.timeCodeSwitch.setOnCheckedChangeListener { _, isChecked -> - binding.timeStampLayout.isVisible = isChecked - PreferenceHelper.putBoolean(PreferenceKeys.SHARE_WITH_TIME_CODE, isChecked) - } - binding.timeStamp.setText((shareData.currentPosition ?: 0L).toString()) - if (binding.timeCodeSwitch.isChecked) { - binding.timeStampLayout.isVisible = true - } - } - // get the frontend url if it's a custom instance private fun getCustomInstanceFrontendUrl(): String { val instancePref = PreferenceHelper.getString( @@ -116,6 +124,27 @@ class ShareDialog : DialogFragment() { return customInstances.firstOrNull { it.apiUrl == instancePref }?.frontendUrl.orEmpty() } + private fun generateLinkText(binding: DialogShareBinding, customInstanceUrl: HttpUrl?): String { + val host = when { + binding.piped.isChecked -> PIPED_FRONTEND_URL + binding.youtube.isChecked -> YOUTUBE_FRONTEND_URL + // only available for custom instances + else -> customInstanceUrl!!.toString() + } + var url = when { + shareObjectType == ShareObjectType.VIDEO && host == YOUTUBE_FRONTEND_URL -> "$YOUTUBE_SHORT_URL/$id" + shareObjectType == ShareObjectType.VIDEO -> "$host/watch?v=$id" + shareObjectType == ShareObjectType.PLAYLIST -> "$host/playlist?list=$id" + else -> "$host/channel/$id" + } + + if (shareObjectType == ShareObjectType.VIDEO && binding.timeCodeSwitch.isChecked) { + url += "&t=${binding.timeStamp.text}" + } + + return url + } + companion object { const val YOUTUBE_FRONTEND_URL = "https://www.youtube.com" const val YOUTUBE_SHORT_URL = "https://youtu.be" diff --git a/app/src/main/res/layout/dialog_share.xml b/app/src/main/res/layout/dialog_share.xml index 436338da9..ea7f112ef 100644 --- a/app/src/main/res/layout/dialog_share.xml +++ b/app/src/main/res/layout/dialog_share.xml @@ -4,45 +4,114 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - android:paddingBottom="25dp"> + android:paddingHorizontal="20dp" + android:paddingTop="10dp"> - - - + android:orientation="vertical"> - + - + - + + + + + android:orientation="horizontal" + android:visibility="gone" + tools:visibility="visible"> - + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file