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
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
videoId = arguments?.getString("videoId")!!
val builder = MaterialAlertDialogBuilder(it)
// Get the layout inflater
binding = DialogAddtoplaylistBinding.inflate(layoutInflater)
videoId = arguments?.getString("videoId")!!
binding = DialogAddtoplaylistBinding.inflate(layoutInflater)
binding.title.text = ThemeHelper.getStyledAppName(requireContext())
token = PreferenceHelper.getToken()
token = PreferenceHelper.getToken()
if (token != "") fetchPlaylists()
if (token != "") fetchPlaylists()
binding.title.text = ThemeHelper.getStyledAppName(requireContext())
builder.setView(binding.root)
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
.show()
}
private fun fetchPlaylists() {

View File

@ -23,32 +23,30 @@ class CreatePlaylistDialog : DialogFragment() {
private lateinit var binding: DialogCreatePlaylistBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val builder = MaterialAlertDialogBuilder(it)
binding = DialogCreatePlaylistBinding.inflate(layoutInflater)
binding = DialogCreatePlaylistBinding.inflate(layoutInflater)
binding.title.text = ThemeHelper.getStyledAppName(requireContext())
binding.title.text = ThemeHelper.getStyledAppName(requireContext())
binding.cancelButton.setOnClickListener {
dismiss()
binding.cancelButton.setOnClickListener {
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()
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()
}
}
builder.setView(binding.root)
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
.show()
}
private fun createPlaylist(name: String) {

View File

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

View File

@ -19,27 +19,25 @@ class DeleteAccountDialog : DialogFragment() {
private lateinit var binding: DialogDeleteAccountBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val builder = MaterialAlertDialogBuilder(it)
binding = DialogDeleteAccountBinding.inflate(layoutInflater)
binding = DialogDeleteAccountBinding.inflate(layoutInflater)
binding.cancelButton.setOnClickListener {
dialog?.dismiss()
binding.cancelButton.setOnClickListener {
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 {
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())
binding.title.text = ThemeHelper.getStyledAppName(requireContext())
builder.setView(binding.root)
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
.show()
}
private fun deleteAccount(password: String) {

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@ import androidx.fragment.app.DialogFragment
import com.github.libretube.PIPED_FRONTEND_URL
import com.github.libretube.R
import com.github.libretube.YOUTUBE_FRONTEND_URL
import com.github.libretube.databinding.DialogShareBinding
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.CustomInstance
import com.github.libretube.extensions.await
@ -17,53 +18,58 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
class ShareDialog(
private val id: String,
private val isPlaylist: Boolean,
private val position: Long = 0L
private val position: Long? = null
) : DialogFragment() {
private var binding: DialogShareBinding? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
var shareOptions = arrayOf(
getString(R.string.piped),
getString(R.string.youtube)
var shareOptions = arrayOf(
getString(R.string.piped),
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
if (instanceUrl != "") shareOptions += getString(R.string.instance)
MaterialAlertDialogBuilder(requireContext())
.setTitle(context?.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
}
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))
)
return MaterialAlertDialogBuilder(requireContext())
.setTitle(context?.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
}
.show()
} ?: throw IllegalStateException("Activity cannot be null")
val path = if (!isPlaylist) "/watch?v=$id" else "/playlist?list=$id"
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

View File

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

View File

@ -37,6 +37,13 @@ class VideoOptionsDialog(
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
*/

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="copied">Copied</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="skip_buttons">Skip buttons</string>
<string name="skip_buttons_summary">Show buttons to skip to the next or previous video.</string>