Merge pull request #1168 from Bnyro/master

Toggle for sharing with time code
This commit is contained in:
Bnyro 2022-08-26 09:38:18 +02:00 committed by GitHub
commit 3afdb9feaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 250 additions and 227 deletions

View File

@ -29,21 +29,17 @@ class AddToPlaylistDialog : DialogFragment() {
private lateinit var token: String private lateinit var token: String
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { videoId = arguments?.getString("videoId")!!
videoId = arguments?.getString("videoId")!! binding = DialogAddtoplaylistBinding.inflate(layoutInflater)
val builder = MaterialAlertDialogBuilder(it) binding.title.text = ThemeHelper.getStyledAppName(requireContext())
// Get the layout inflater
binding = DialogAddtoplaylistBinding.inflate(layoutInflater)
token = PreferenceHelper.getToken() token = PreferenceHelper.getToken()
if (token != "") fetchPlaylists() if (token != "") fetchPlaylists()
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
builder.setView(binding.root) .show()
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
} }
private fun fetchPlaylists() { private fun fetchPlaylists() {

View File

@ -23,32 +23,30 @@ class CreatePlaylistDialog : DialogFragment() {
private lateinit var binding: DialogCreatePlaylistBinding private lateinit var binding: DialogCreatePlaylistBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { binding = DialogCreatePlaylistBinding.inflate(layoutInflater)
val builder = MaterialAlertDialogBuilder(it)
binding = DialogCreatePlaylistBinding.inflate(layoutInflater)
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) binding.title.text = ThemeHelper.getStyledAppName(requireContext())
binding.cancelButton.setOnClickListener { binding.cancelButton.setOnClickListener {
dismiss() dismiss()
}
token = PreferenceHelper.getToken()
binding.createNewPlaylist.setOnClickListener {
// avoid creating the same playlist multiple times by spamming the button
binding.createNewPlaylist.setOnClickListener(null)
val listName = binding.playlistName.text.toString()
if (listName != "") {
createPlaylist(listName)
} else {
Toast.makeText(context, R.string.emptyPlaylistName, Toast.LENGTH_LONG).show()
} }
}
token = PreferenceHelper.getToken() return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
binding.createNewPlaylist.setOnClickListener { .show()
// avoid creating the same playlist multiple times by spamming the button
binding.createNewPlaylist.setOnClickListener(null)
val listName = binding.playlistName.text.toString()
if (listName != "") {
createPlaylist(listName)
} else {
Toast.makeText(context, R.string.emptyPlaylistName, Toast.LENGTH_LONG).show()
}
}
builder.setView(binding.root)
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
} }
private fun createPlaylist(name: String) { private fun createPlaylist(name: String) {

View File

@ -16,59 +16,57 @@ class CustomInstanceDialog : DialogFragment() {
private lateinit var binding: DialogCustomInstanceBinding private lateinit var binding: DialogCustomInstanceBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { binding = DialogCustomInstanceBinding.inflate(layoutInflater)
val builder = MaterialAlertDialogBuilder(it)
binding = DialogCustomInstanceBinding.inflate(layoutInflater)
binding.cancel.setOnClickListener { binding.cancel.setOnClickListener {
dismiss() dismiss()
} }
binding.addInstance.setOnClickListener { binding.addInstance.setOnClickListener {
val customInstance = CustomInstance( val customInstance = CustomInstance(
name = binding.instanceName.text.toString(), name = binding.instanceName.text.toString(),
apiUrl = binding.instanceApiUrl.text.toString(), apiUrl = binding.instanceApiUrl.text.toString(),
frontendUrl = binding.instanceFrontendUrl.text.toString() frontendUrl = binding.instanceFrontendUrl.text.toString()
) )
if ( if (
customInstance.name != "" && customInstance.name != "" &&
customInstance.apiUrl != "" && customInstance.apiUrl != "" &&
customInstance.frontendUrl != "" customInstance.frontendUrl != ""
) { ) {
try { try {
// check whether the URL is valid, otherwise catch // check whether the URL is valid, otherwise catch
URL(customInstance.apiUrl).toURI() URL(customInstance.apiUrl).toURI()
URL(customInstance.frontendUrl).toURI() URL(customInstance.frontendUrl).toURI()
Thread { Thread {
DatabaseHolder.db.customInstanceDao().insertAll(customInstance) DatabaseHolder.db.customInstanceDao().insertAll(customInstance)
}.start() }.start()
activity?.recreate() activity?.recreate()
dismiss() dismiss()
} catch (e: Exception) { } catch (e: Exception) {
// invalid URL // invalid URL
Toast.makeText(
context,
getString(R.string.invalid_url),
Toast.LENGTH_SHORT
).show()
}
} else {
// at least one empty input
Toast.makeText( Toast.makeText(
context, context,
context?.getString(R.string.empty_instance), getString(R.string.invalid_url),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} }
} else {
// at least one empty input
Toast.makeText(
context,
context?.getString(R.string.empty_instance),
Toast.LENGTH_SHORT
).show()
} }
}
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) binding.title.text = ThemeHelper.getStyledAppName(requireContext())
builder.setView(binding.root) return MaterialAlertDialogBuilder(requireContext())
builder.create() .setView(binding.root)
} ?: throw IllegalStateException("Activity cannot be null") .show()
} }
} }

View File

@ -19,27 +19,25 @@ class DeleteAccountDialog : DialogFragment() {
private lateinit var binding: DialogDeleteAccountBinding private lateinit var binding: DialogDeleteAccountBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { binding = DialogDeleteAccountBinding.inflate(layoutInflater)
val builder = MaterialAlertDialogBuilder(it)
binding = DialogDeleteAccountBinding.inflate(layoutInflater)
binding.cancelButton.setOnClickListener { binding.cancelButton.setOnClickListener {
dialog?.dismiss() dialog?.dismiss()
}
binding.deleteAccountConfirm.setOnClickListener {
if (binding.deletePassword.text.toString() != "") {
deleteAccount(binding.deletePassword.text.toString())
} else {
Toast.makeText(context, R.string.empty, Toast.LENGTH_SHORT).show()
} }
}
binding.deleteAccountConfirm.setOnClickListener { binding.title.text = ThemeHelper.getStyledAppName(requireContext())
if (binding.deletePassword.text.toString() != "") {
deleteAccount(binding.deletePassword.text.toString())
} else {
Toast.makeText(context, R.string.empty, Toast.LENGTH_SHORT).show()
}
}
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
builder.setView(binding.root) .show()
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
} }
private fun deleteAccount(password: String) { private fun deleteAccount(password: String) {

View File

@ -28,29 +28,27 @@ class DownloadDialog(
private lateinit var binding: DialogDownloadBinding private lateinit var binding: DialogDownloadBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { binding = DialogDownloadBinding.inflate(layoutInflater)
val builder = MaterialAlertDialogBuilder(it)
binding = DialogDownloadBinding.inflate(layoutInflater)
fetchAvailableSources() fetchAvailableSources()
PermissionHelper.requestReadWrite(requireActivity()) PermissionHelper.requestReadWrite(requireActivity())
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) binding.title.text = ThemeHelper.getStyledAppName(requireContext())
binding.audioRadio.setOnClickListener { binding.audioRadio.setOnClickListener {
binding.videoSpinner.visibility = View.GONE binding.videoSpinner.visibility = View.GONE
binding.audioSpinner.visibility = View.VISIBLE binding.audioSpinner.visibility = View.VISIBLE
} }
binding.videoRadio.setOnClickListener { binding.videoRadio.setOnClickListener {
binding.audioSpinner.visibility = View.GONE binding.audioSpinner.visibility = View.GONE
binding.videoSpinner.visibility = View.VISIBLE binding.videoSpinner.visibility = View.VISIBLE
} }
builder.setView(binding.root) return MaterialAlertDialogBuilder(requireContext())
builder.create() .setView(binding.root)
} ?: throw IllegalStateException("Activity cannot be null") .show()
} }
private fun fetchAvailableSources() { private fun fetchAvailableSources() {

View File

@ -21,40 +21,37 @@ class LoginDialog : DialogFragment() {
private lateinit var binding: DialogLoginBinding private lateinit var binding: DialogLoginBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { binding = DialogLoginBinding.inflate(layoutInflater)
val builder = MaterialAlertDialogBuilder(it)
// Get the layout inflater
binding = DialogLoginBinding.inflate(layoutInflater)
binding.login.setOnClickListener { binding.login.setOnClickListener {
if (binding.username.text.toString() != "" && binding.password.text.toString() != "") { if (binding.username.text.toString() != "" && binding.password.text.toString() != "") {
val login = val login =
Login(binding.username.text.toString(), binding.password.text.toString()) Login(binding.username.text.toString(), binding.password.text.toString())
login(login) login(login)
} else { } else {
Toast.makeText(context, R.string.empty, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.empty, Toast.LENGTH_SHORT).show()
}
} }
binding.register.setOnClickListener { }
if ( binding.register.setOnClickListener {
binding.username.text.toString() != "" && if (
binding.password.text.toString() != "" binding.username.text.toString() != "" &&
) { binding.password.text.toString() != ""
val login = Login( ) {
binding.username.text.toString(), val login = Login(
binding.password.text.toString() binding.username.text.toString(),
) binding.password.text.toString()
register(login) )
} else { register(login)
Toast.makeText(context, R.string.empty, Toast.LENGTH_SHORT).show() } else {
} Toast.makeText(context, R.string.empty, Toast.LENGTH_SHORT).show()
} }
}
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) binding.title.text = ThemeHelper.getStyledAppName(requireContext())
builder.setView(binding.root) return MaterialAlertDialogBuilder(requireContext())
builder.create() .setView(binding.root)
} ?: throw IllegalStateException("Activity cannot be null") .show()
} }
private fun login(login: Login) { private fun login(login: Login) {

View File

@ -14,25 +14,23 @@ class LogoutDialog : DialogFragment() {
private lateinit var binding: DialogLogoutBinding private lateinit var binding: DialogLogoutBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { binding = DialogLogoutBinding.inflate(layoutInflater)
val builder = MaterialAlertDialogBuilder(it)
binding = DialogLogoutBinding.inflate(layoutInflater)
val user = PreferenceHelper.getUsername() val user = PreferenceHelper.getUsername()
binding.user.text = binding.user.text =
binding.user.text.toString() + " (" + user + ")" binding.user.text.toString() + " (" + user + ")"
binding.logout.setOnClickListener { binding.logout.setOnClickListener {
Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.loggedout, Toast.LENGTH_SHORT).show()
PreferenceHelper.setToken("") PreferenceHelper.setToken("")
dialog?.dismiss() dialog?.dismiss()
activity?.recreate() activity?.recreate()
} }
binding.title.text = ThemeHelper.getStyledAppName(requireContext()) binding.title.text = ThemeHelper.getStyledAppName(requireContext())
builder.setView(binding.root) return MaterialAlertDialogBuilder(requireContext())
builder.create() .setView(binding.root)
} ?: throw IllegalStateException("Activity cannot be null") .show()
} }
} }

View File

@ -10,16 +10,14 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
class RequireRestartDialog : DialogFragment() { class RequireRestartDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { return MaterialAlertDialogBuilder(requireContext())
MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.require_restart)
.setTitle(R.string.require_restart) .setMessage(R.string.require_restart_message)
.setMessage(R.string.require_restart_message) .setPositiveButton(R.string.okay) { _, _ ->
.setPositiveButton(R.string.okay) { _, _ -> activity?.recreate()
activity?.recreate() ThemeHelper.restartMainActivity(requireContext())
ThemeHelper.restartMainActivity(requireContext()) }
} .setNegativeButton(R.string.cancel, null)
.setNegativeButton(R.string.cancel, null) .show()
.create()
} ?: throw IllegalStateException("Activity cannot be null")
} }
} }

View File

@ -7,6 +7,7 @@ import androidx.fragment.app.DialogFragment
import com.github.libretube.PIPED_FRONTEND_URL import com.github.libretube.PIPED_FRONTEND_URL
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.YOUTUBE_FRONTEND_URL import com.github.libretube.YOUTUBE_FRONTEND_URL
import com.github.libretube.databinding.DialogShareBinding
import com.github.libretube.db.DatabaseHolder import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.CustomInstance import com.github.libretube.db.obj.CustomInstance
import com.github.libretube.extensions.await import com.github.libretube.extensions.await
@ -17,53 +18,58 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
class ShareDialog( class ShareDialog(
private val id: String, private val id: String,
private val isPlaylist: Boolean, private val isPlaylist: Boolean,
private val position: Long = 0L private val position: Long? = null
) : DialogFragment() { ) : DialogFragment() {
private var binding: DialogShareBinding? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { var shareOptions = arrayOf(
var shareOptions = arrayOf( getString(R.string.piped),
getString(R.string.piped), getString(R.string.youtube)
getString(R.string.youtube) )
val instanceUrl = getCustomInstanceFrontendUrl()
// add instanceUrl option if custom instance frontend url available
if (instanceUrl != "") shareOptions += getString(R.string.instance)
if (position != null) {
binding = DialogShareBinding.inflate(layoutInflater)
binding!!.timeCodeSwitch.isChecked = PreferenceHelper.getBoolean(
PreferenceKeys.SHARE_WITH_TIME_CODE,
true
) )
val instanceUrl = getCustomInstanceFrontendUrl() }
// add instanceUrl option if custom instance frontend url available return MaterialAlertDialogBuilder(requireContext())
if (instanceUrl != "") shareOptions += getString(R.string.instance) .setTitle(context?.getString(R.string.share))
.setItems(
MaterialAlertDialogBuilder(requireContext()) shareOptions
.setTitle(context?.getString(R.string.share)) ) { _, which ->
.setItems( val host = when (which) {
shareOptions 0 -> PIPED_FRONTEND_URL
) { _, which -> 1 -> YOUTUBE_FRONTEND_URL
val host = when (which) { // only available for custom instances
0 -> PIPED_FRONTEND_URL else -> instanceUrl
1 -> YOUTUBE_FRONTEND_URL
// only available for custom instances
else -> instanceUrl
}
val path = if (!isPlaylist) "/watch?v=$id" else "/playlist?list=$id"
var url = "$host$path"
if (PreferenceHelper.getBoolean(
PreferenceKeys.SHARE_WITH_TIME_CODE,
true
)
) {
url += "?t=$position"
}
val intent = Intent()
intent.apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, url)
type = "text/plain"
}
context?.startActivity(
Intent.createChooser(intent, context?.getString(R.string.shareTo))
)
} }
.show() val path = if (!isPlaylist) "/watch?v=$id" else "/playlist?list=$id"
} ?: throw IllegalStateException("Activity cannot be null") var url = "$host$path"
if (binding != null && binding!!.timeCodeSwitch.isChecked) {
url += "?t=$position"
}
val intent = Intent()
intent.apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, url)
type = "text/plain"
}
context?.startActivity(
Intent.createChooser(intent, context?.getString(R.string.shareTo))
)
}
.setView(binding?.root)
.show()
} }
// get the frontend url if it's a custom instance // get the frontend url if it's a custom instance

View File

@ -18,27 +18,25 @@ class UpdateDialog(
) : DialogFragment() { ) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { return MaterialAlertDialogBuilder(requireContext())
MaterialAlertDialogBuilder(requireContext()) .setTitle(context?.getString(R.string.update_available, updateInfo.name))
.setTitle(context?.getString(R.string.update_available, updateInfo.name)) .setMessage(context?.getString(R.string.update_now))
.setMessage(context?.getString(R.string.update_now)) .setNegativeButton(R.string.cancel, null)
.setNegativeButton(R.string.cancel, null) .setPositiveButton(context?.getString(R.string.okay)) { _, _ ->
.setPositiveButton(context?.getString(R.string.okay)) { _, _ -> val downloadUrl = getDownloadUrl(updateInfo)
val downloadUrl = getDownloadUrl(updateInfo) Log.i("downloadUrl", downloadUrl.toString())
Log.i("downloadUrl", downloadUrl.toString()) if (downloadUrl != null) {
if (downloadUrl != null) { PermissionHelper.requestReadWrite(requireActivity())
PermissionHelper.requestReadWrite(requireActivity()) val intent = Intent(context, UpdateService::class.java)
val intent = Intent(context, UpdateService::class.java) intent.putExtra("downloadUrl", downloadUrl)
intent.putExtra("downloadUrl", downloadUrl) context?.startService(intent)
context?.startService(intent) } else {
} else { val uri = Uri.parse(updateInfo.html_url)
val uri = Uri.parse(updateInfo.html_url) val intent = Intent(Intent.ACTION_VIEW).setData(uri)
val intent = Intent(Intent.ACTION_VIEW).setData(uri) startActivity(intent)
startActivity(intent)
}
} }
.create() }
} ?: throw IllegalStateException("Activity cannot be null") .show()
} }
private fun getDownloadUrl(updateInfo: UpdateInfo): String? { private fun getDownloadUrl(updateInfo: UpdateInfo): String? {

View File

@ -37,6 +37,13 @@ class VideoOptionsDialog(
context?.getString(R.string.share) context?.getString(R.string.share)
) )
// remove the add to playlist option if not logged in
if (PreferenceHelper.getToken() == "") {
optionsList.remove(
context?.getString(R.string.addToPlaylist)
)
}
/** /**
* Check whether the player is running by observing the notification * Check whether the player is running by observing the notification
*/ */

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="25dp"
android:layout_marginBottom="15dp"
android:orientation="horizontal"
tools:ignore="UselessParent">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:text="@string/share_with_time" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/timeCodeSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
</FrameLayout>

View File

@ -283,7 +283,7 @@
<string name="error_occurred">Error</string> <string name="error_occurred">Error</string>
<string name="copied">Copied</string> <string name="copied">Copied</string>
<string name="downloadsucceeded">Download succeeded</string> <string name="downloadsucceeded">Download succeeded</string>
<string name="share_with_time">Share with start time</string> <string name="share_with_time">Share with time code</string>
<string name="export_subscriptions">Export Subscriptions</string> <string name="export_subscriptions">Export Subscriptions</string>
<string name="skip_buttons">Skip buttons</string> <string name="skip_buttons">Skip buttons</string>
<string name="skip_buttons_summary">Show buttons to skip to the next or previous video.</string> <string name="skip_buttons_summary">Show buttons to skip to the next or previous video.</string>