mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-13 13:50:30 +05:30
feat: share dialog redesign (including copy link feature)
This commit is contained in:
parent
47bae051ee
commit
fadd2d31af
@ -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"
|
||||
|
@ -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)
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
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"
|
||||
)
|
||||
|
||||
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 (shareObjectType == ShareObjectType.VIDEO && binding.timeCodeSwitch.isChecked) {
|
||||
url += "&t=${binding.timeStamp.text}"
|
||||
if (customInstanceUrl != null) {
|
||||
binding.customInstance.isVisible = true
|
||||
binding.customInstance.text = customInstanceUrl.host
|
||||
}
|
||||
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
.putExtra(Intent.EXTRA_TEXT, url)
|
||||
.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.timeStampSwitchLayout.isVisible = true
|
||||
binding.timeCodeSwitch.isChecked = PreferenceHelper.getBoolean(
|
||||
PreferenceKeys.SHARE_WITH_TIME_CODE,
|
||||
false
|
||||
)
|
||||
binding.timeCodeSwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
binding.timeStampLayout.isVisible = 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.timeStampLayout.isVisible = true
|
||||
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))
|
||||
.setView(binding.root)
|
||||
.setPositiveButton(R.string.share) { _, _ ->
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
.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)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
// 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"
|
||||
|
@ -4,15 +4,51 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="25dp">
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingTop="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="25dp"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/share_host_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/youtube"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/youtube" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/piped"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/piped" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/custom_instance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
tools:text="kavin.rocks"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/time_stamp_switch_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
@ -29,10 +65,9 @@
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/timeStampLayout"
|
||||
android:id="@+id/time_stamp_input_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="25dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:hint="@string/time_code"
|
||||
android:visibility="gone">
|
||||
@ -45,4 +80,38 @@
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/share_link_card"
|
||||
style="@style/Widget.Material3.CardView.Elevated"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="?selectableItemBackground"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/copy_link"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginVertical="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/link_preview"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
tools:text="https://youtu.be/abcdefghijgk" />
|
||||
|
||||
<ImageView
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_copy" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
Loading…
Reference in New Issue
Block a user