Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
125 changes: 77 additions & 48 deletions app/src/main/java/com/github/libretube/ui/dialogs/ShareDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}
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.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
}
)

if (shareObjectType == ShareObjectType.VIDEO && binding.timeCodeSwitch.isChecked) {
url += "&t=${binding.timeStamp.text}"
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))
.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(
Expand All @@ -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"
Expand Down
119 changes: 94 additions & 25 deletions app/src/main/res/layout/dialog_share.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="25dp"
android:orientation="horizontal"
android:orientation="vertical"
tools:ignore="UselessParent">

<TextView
android:layout_width="0dp"
<RadioGroup
android:id="@+id/share_host_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:text="@string/share_with_time" />
android:orientation="vertical">

<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/timeCodeSwitch"
android:layout_width="wrap_content"
<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:layout_gravity="center" />
android:orientation="horizontal"
android:visibility="gone"
tools:visibility="visible">

</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:text="@string/share_with_time" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/timeStampLayout"
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">
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/timeCodeSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/timeStamp"
</LinearLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/time_stamp_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
android:layout_marginTop="5dp"
android:hint="@string/time_code"
android:visibility="gone">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/timeStamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />

</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">

</com.google.android.material.textfield.TextInputLayout>
<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>