Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for contributing to DeArrow #5889

Merged
merged 1 commit into from
Apr 11, 2024
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
9 changes: 7 additions & 2 deletions app/src/main/java/com/github/libretube/api/ExternalApi.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.github.libretube.api

import com.github.libretube.api.obj.DeArrowBody
import com.github.libretube.api.obj.PipedInstance
import com.github.libretube.api.obj.SubmitSegmentResponse
import com.github.libretube.obj.update.UpdateInfo
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Query
Expand All @@ -23,15 +25,18 @@
@POST("$SB_API_URL/api/skipSegments")
suspend fun submitSegment(
@Query("videoID") videoId: String,
@Query("userID") userID: String,
@Query("userAgent") userAgent: String,
@Query("startTime") startTime: Float,
@Query("endTime") endTime: Float,
@Query("category") category: String,
@Query("userAgent") userAgent: String,
@Query("userID") userID: String,
@Query("duration") duration: Float? = null,
@Query("description") description: String = ""
): List<SubmitSegmentResponse>

@POST("$SB_API_URL/api/branding")
suspend fun submitDeArrow(@Body body: DeArrowBody)

Check failure on line 38 in app/src/main/java/com/github/libretube/api/ExternalApi.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Parameter should start on a newline Raw Output: app/src/main/java/com/github/libretube/api/ExternalApi.kt:38:31: error: Parameter should start on a newline (standard:parameter-list-wrapping)

Check failure on line 38 in app/src/main/java/com/github/libretube/api/ExternalApi.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Newline expected after opening parenthesis Raw Output: app/src/main/java/com/github/libretube/api/ExternalApi.kt:38:31: error: Newline expected after opening parenthesis (standard:function-signature)

Check failure on line 38 in app/src/main/java/com/github/libretube/api/ExternalApi.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Missing newline before ")" Raw Output: app/src/main/java/com/github/libretube/api/ExternalApi.kt:38:54: error: Missing newline before ")" (standard:parameter-list-wrapping)

Check failure on line 38 in app/src/main/java/com/github/libretube/api/ExternalApi.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Newline expected before closing parenthesis Raw Output: app/src/main/java/com/github/libretube/api/ExternalApi.kt:38:54: error: Newline expected before closing parenthesis (standard:function-signature)

/**
* @param score: 0 for downvote, 1 for upvote, 20 for undoing previous vote (if existent)
*/
Expand Down
23 changes: 23 additions & 0 deletions app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.github.libretube.api.obj

import kotlinx.serialization.Serializable

@Serializable
data class DeArrowBody(
val videoID: String,
val userID: String,
val userAgent: String,
val title: DeArrowSubmitTitle?,
val thumbnail: DeArrowSubmitThumbnail?,
val downvote: Boolean = false

Check failure on line 12 in app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Missing trailing comma before ")" Raw Output: app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt:12:34: error: Missing trailing comma before ")" (standard:trailing-comma-on-declaration-site)
)

@Serializable
data class DeArrowSubmitTitle(
val title: String

Check failure on line 17 in app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Missing trailing comma before ")" Raw Output: app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt:17:22: error: Missing trailing comma before ")" (standard:trailing-comma-on-declaration-site)
)

@Serializable
data class DeArrowSubmitThumbnail(
val timestamp: Float

Check failure on line 22 in app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Missing trailing comma before ")" Raw Output: app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt:22:25: error: Missing trailing comma before ")" (standard:trailing-comma-on-declaration-site)
)

Check failure on line 23 in app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 File must end with a newline (\n) Raw Output: app/src/main/java/com/github/libretube/api/obj/DeArrowBody.kt:23:1: error: File must end with a newline (\n) (standard:final-newline)
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ object PreferenceKeys {
const val MAX_CONCURRENT_DOWNLOADS = "max_parallel_downloads"
const val DISABLE_VIDEO_IMAGE_PROXY = "disable_video_image_proxy"
const val CONTRIBUTE_TO_SB = "sb_contribute_key"
const val CONTRIBUTE_TO_DEARROW = "dearrow_contribute_key"

/**
* History
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.github.libretube.ui.dialogs

import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.obj.DeArrowBody
import com.github.libretube.api.obj.DeArrowSubmitThumbnail
import com.github.libretube.api.obj.DeArrowSubmitTitle
import com.github.libretube.constants.IntentData
import com.github.libretube.databinding.DialogSubmitDearrowBinding
import com.github.libretube.extensions.toastFromMainDispatcher
import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.util.TextUtils
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class SubmitDeArrowDialog: DialogFragment() {

Check failure on line 23 in app/src/main/java/com/github/libretube/ui/dialogs/SubmitDeArrowDialog.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Missing spacing before ":" Raw Output: app/src/main/java/com/github/libretube/ui/dialogs/SubmitDeArrowDialog.kt:23:26: error: Missing spacing before ":" (standard:colon-spacing)
private var videoId: String = ""
private var currentPosition: Long = 0

private var _binding: DialogSubmitDearrowBinding? = null
private val binding get() = _binding!!

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
videoId = it.getString(IntentData.videoId)!!
currentPosition = it.getLong(IntentData.currentPosition)
}
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
_binding = DialogSubmitDearrowBinding.inflate(layoutInflater)

binding.dearrowTitle.typingEnabled = true
binding.thumbnailTime.setText(currentPosition.toString())

binding.titleCheckbox.setOnCheckedChangeListener { _, isChecked ->
binding.dearrowTitle.isEnabled = isChecked
}
binding.thumbnailTimeCheckbox.setOnCheckedChangeListener { _, isChecked ->
binding.thumbnailTimeInputLayout.isEnabled = isChecked
}

lifecycleScope.launch { fetchDeArrowData() }

return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
.setPositiveButton(R.string.okay, null)
.setNegativeButton(R.string.cancel, null)
.show()
.apply {
getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
lifecycleScope.launch { submitDeArrow() }
}
}
}

private suspend fun fetchDeArrowData() {
val data = try {
withContext(Dispatchers.IO) {
RetrofitInstance.api.getDeArrowContent(videoId)
}.getOrElse(videoId) { return }
} catch (e: Exception) {
return
}

binding.dearrowTitle.items = data.titles.map { it.title }
}

private suspend fun submitDeArrow() {
val context = requireContext().applicationContext
requireDialog().hide()

val userID = PreferenceHelper.getSponsorBlockUserID()
val userAgent = TextUtils.getUserAgent(context)
val title = binding.dearrowTitle.text
.takeIf { it.isNotEmpty() && binding.titleCheckbox.isChecked }
?.let { DeArrowSubmitTitle(it) }
val thumbnail = binding.thumbnailTime.text.toString().toFloatOrNull()
?.takeIf { binding.thumbnailTimeCheckbox.isChecked }
?.let { DeArrowSubmitThumbnail(it) }
val requestBody = DeArrowBody(videoId, userID, userAgent, title, thumbnail)

try {
// https://wiki.sponsor.ajay.app/w/API_Docs/DeArrow
withContext(Dispatchers.IO) {
RetrofitInstance.externalApi.submitDeArrow(requestBody)
}
context.toastFromMainDispatcher(R.string.success)
} catch (e: Exception) {
context.toastFromMainDispatcher(e.localizedMessage.orEmpty())
}

dialog?.dismiss()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.github.libretube.databinding.DialogSubmitSegmentBinding
import com.github.libretube.extensions.TAG
import com.github.libretube.extensions.toastFromMainDispatcher
import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.util.TextUtils
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.lang.Exception
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -86,14 +87,14 @@ class SubmitSegmentDialog : DialogFragment() {

val categories = resources.getStringArray(R.array.sponsorBlockSegments)
val category = categories[binding.segmentCategory.selectedItemPosition]
val userAgent = "${context.packageName}/${BuildConfig.VERSION_NAME}"
val userAgent = TextUtils.getUserAgent(context)
val uuid = PreferenceHelper.getSponsorBlockUserID()
val duration = duration?.let { it.toFloat() / 1000 }

try {
withContext(Dispatchers.IO) {
RetrofitInstance.externalApi
.submitSegment(videoId, startTime, endTime, category, userAgent, uuid, duration)
.submitSegment(videoId, uuid, userAgent, startTime, endTime, category, duration)
}
context.toastFromMainDispatcher(R.string.segment_submitted)
} catch (e: Exception) {
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/java/com/github/libretube/ui/views/DropdownMenu.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.libretube.ui.views

import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ArrayAdapter
Expand Down Expand Up @@ -37,6 +38,22 @@ class DropdownMenu(
get() = adapter.getPosition(binding.autoCompleteTextView.text.toString())
set(index) = binding.autoCompleteTextView.setText(adapter.getItem(index), false)

val text get() = binding.autoCompleteTextView.text.toString()

override fun setEnabled(enabled: Boolean) {
binding.textInputLayout.isEnabled = enabled
}

override fun isEnabled(): Boolean {
return binding.textInputLayout.isEnabled
}

var typingEnabled: Boolean
set(enabled) {
binding.autoCompleteTextView.inputType = if (enabled) InputType.TYPE_CLASS_TEXT else InputType.TYPE_NULL
}
get() = binding.autoCompleteTextView.inputType != InputType.TYPE_NULL

init {
context.obtainStyledAttributes(attributeSet, R.styleable.DropdownMenu, 0, 0).use {
binding.textInputLayout.hint = it.getString(R.styleable.DropdownMenu_hint)
Expand Down
36 changes: 24 additions & 12 deletions app/src/main/java/com/github/libretube/ui/views/OnlinePlayerView.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.libretube.ui.views

import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.view.Window
import androidx.core.os.bundleOf
Expand All @@ -19,6 +20,7 @@ import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.helpers.WindowHelper
import com.github.libretube.obj.BottomSheetItem
import com.github.libretube.ui.base.BaseActivity
import com.github.libretube.ui.dialogs.SubmitDeArrowDialog
import com.github.libretube.ui.dialogs.SubmitSegmentDialog
import com.github.libretube.ui.interfaces.OnlinePlayerOptions
import com.github.libretube.ui.models.PlayerViewModel
Expand Down Expand Up @@ -162,21 +164,31 @@ class OnlinePlayerView(

binding.sbSubmit.isVisible = PreferenceHelper.getBoolean(PreferenceKeys.CONTRIBUTE_TO_SB, false)
binding.sbSubmit.setOnClickListener {
val currentPosition = player?.currentPosition?.takeIf { it != C.TIME_UNSET } ?: 0
val duration = player?.duration?.takeIf { it != C.TIME_UNSET }
val videoId = PlayingQueue.getCurrent()?.url?.toID() ?: return@setOnClickListener

val bundle = bundleOf(
IntentData.currentPosition to currentPosition,
IntentData.duration to duration,
IntentData.videoId to videoId
)
val newSubmitSegmentDialog = SubmitSegmentDialog()
newSubmitSegmentDialog.arguments = bundle
newSubmitSegmentDialog.show((context as BaseActivity).supportFragmentManager, null)
val submitSegmentDialog = SubmitSegmentDialog()
submitSegmentDialog.arguments = buildSbBundleArgs() ?: return@setOnClickListener
submitSegmentDialog.show((context as BaseActivity).supportFragmentManager, null)
}

binding.dearrowSubmit.isVisible = PreferenceHelper.getBoolean(PreferenceKeys.CONTRIBUTE_TO_DEARROW, false)
binding.dearrowSubmit.setOnClickListener {
val submitDialog = SubmitDeArrowDialog()
submitDialog.arguments = buildSbBundleArgs() ?: return@setOnClickListener
submitDialog.show((context as BaseActivity).supportFragmentManager, null)
}
}

private fun buildSbBundleArgs(): Bundle? {
val currentPosition = player?.currentPosition?.takeIf { it != C.TIME_UNSET } ?: 0
val duration = player?.duration?.takeIf { it != C.TIME_UNSET }
val videoId = PlayingQueue.getCurrent()?.url?.toID() ?: return null

return bundleOf(
IntentData.currentPosition to currentPosition,
IntentData.duration to duration,
IntentData.videoId to videoId
)
}

override fun getWindow(): Window = currentWindow ?: activity.window

override fun hideController() {
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/com/github/libretube/util/TextUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.icu.text.RelativeDateTimeFormatter
import android.net.Uri
import android.os.Build
import android.text.format.DateUtils
import com.github.libretube.BuildConfig
import com.github.libretube.R
import java.time.Instant
import java.time.LocalDateTime
Expand Down Expand Up @@ -98,4 +99,8 @@ object TextUtils {
if (text.length <= maxLength) return text
return text.take(maxLength) + "…"
}

fun getUserAgent(context: Context): String {
return "${context.packageName}/${BuildConfig.VERSION_NAME}"
}
}
18 changes: 18 additions & 0 deletions app/src/main/res/drawable/ic_dearrow.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="36"
android:viewportHeight="36">

<path
android:fillColor="#00000000"
android:pathData="m34.221,18.268c0,4.489 -2.217,8.289 -5.096,11.231 -2.879,2.941 -6.599,4.643 -10.994,4.643 -4.394,0 -8.799,-1.002 -11.678,-3.944 -2.879,-2.941 -4.674,-7.441 -4.674,-11.93 0,-4.489 2.32,-8.453 5.199,-11.395 2.879,-2.941 6.761,-5.099 11.154,-5.099 4.393,0 8.466,1.963 11.345,4.904 2.88,2.941 4.745,7.101 4.745,11.589z"
android:strokeWidth="2.96196"
android:strokeColor="#000000" />

<path
android:fillColor="#000000"
android:pathData="m21.223,17.841c0,1.643 -1.378,3.027 -3.022,3.027 -1.643,0 -2.918,-1.383 -2.918,-3.027 0,-1.643 1.275,-2.982 2.918,-2.982 1.643,0 3.022,1.338 3.022,2.982z"
android:strokeWidth="0.616691" />

</vector>
59 changes: 59 additions & 0 deletions app/src/main/res/layout/dialog_submit_dearrow.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingHorizontal="15dp"
android:paddingTop="15dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/contribute_to_dearrow"
android:textSize="24sp" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/title_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:checked="true"
android:text="@string/title" />

<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/thumbnail_time_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/thumbnail_time" />

</LinearLayout>

<com.github.libretube.ui.views.DropdownMenu
android:id="@+id/dearrow_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hint="@string/title"
app:icon="@drawable/ic_label" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/thumbnail_time_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/thumbnail_time">

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

</LinearLayout>
9 changes: 9 additions & 0 deletions app/src/main/res/layout/exo_styled_player_control_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@
app:track="@drawable/player_switch_track"
app:trackTint="#88ffffff" />

<ImageButton
android:id="@+id/dearrow_submit"
style="@style/PlayerControlTop"
android:layout_marginEnd="2dp"
android:src="@drawable/ic_dearrow"
android:tooltipText="@string/contribute_to_dearrow"
android:visibility="gone"
app:tint="@android:color/white" />

<ImageButton
android:id="@+id/sb_submit"
style="@style/PlayerControlTop"
Expand Down
Loading
Loading