mirror of
https://github.com/videolan/vlc-android
synced 2024-11-23 09:56:36 +08:00
Login to OpenSubtitles
This commit is contained in:
parent
e317f1f8f0
commit
c263543970
@ -1,6 +1,6 @@
|
||||
package org.videolan.resources.opensubtitles
|
||||
|
||||
import retrofit2.Response
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
@ -19,7 +19,10 @@ interface IOpenSubtitleService {
|
||||
): OpenSubV1
|
||||
|
||||
@POST("download")
|
||||
suspend fun queryDownloadUrl( @Body downloadLinkBody: DownloadLinkBody): Response<DownloadLink>
|
||||
suspend fun queryDownloadUrl( @Body downloadLinkBody: DownloadLinkBody): DownloadLink
|
||||
|
||||
@POST("login")
|
||||
fun login( @Body loginBody: LoginBody): Call<OpenSubtitleAccount>
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,6 @@ package org.videolan.resources.opensubtitles
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
data class QueryParameters(
|
||||
@field:Json(name = "query") val query: String,
|
||||
@field:Json(name = "episode") val episode: String,
|
||||
@field:Json(name = "season") val season: String
|
||||
)
|
||||
|
||||
|
||||
data class OpenSubV1(
|
||||
@field:Json(name = "data")
|
||||
val `data`: List<Data>,
|
||||
@ -166,31 +159,29 @@ data class DownloadLink(
|
||||
val resetTimeUtc: String
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class LoginResult(
|
||||
@Json(name = "base_url")
|
||||
val baseUrl: String,
|
||||
@Json(name = "status")
|
||||
val status: Int,
|
||||
@Json(name = "token")
|
||||
val token: String,
|
||||
@Json(name = "user")
|
||||
val user: User
|
||||
data class OpenSubtitleAccount(
|
||||
@field:Json(name = "base_url")
|
||||
val baseUrl: String?,
|
||||
@field:Json(name = "status")
|
||||
val status: Int?,
|
||||
@field:Json(name = "token")
|
||||
val token: String?,
|
||||
@field:Json(name = "user")
|
||||
val user: User?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class User(
|
||||
@Json(name = "allowed_downloads")
|
||||
val allowedDownloads: Int,
|
||||
@Json(name = "allowed_translations")
|
||||
val allowedTranslations: Int,
|
||||
@Json(name = "ext_installed")
|
||||
val extInstalled: Boolean,
|
||||
@Json(name = "level")
|
||||
val level: String,
|
||||
@Json(name = "user_id")
|
||||
val userId: Int,
|
||||
@Json(name = "vip")
|
||||
@field:Json(name = "allowed_downloads")
|
||||
val allowedDownloads: Int?,
|
||||
@field:Json(name = "allowed_translations")
|
||||
val allowedTranslations: Int?,
|
||||
@field:Json(name = "ext_installed")
|
||||
val extInstalled: Boolean?,
|
||||
@field:Json(name = "level")
|
||||
val level: String?,
|
||||
@field:Json(name = "user_id")
|
||||
val userId: Int?,
|
||||
@field:Json(name = "vip")
|
||||
val vip: Boolean?
|
||||
)
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.videolan.resources.opensubtitles
|
||||
|
||||
import retrofit2.Response
|
||||
|
||||
class OpenSubtitleRepository(private val openSubtitleService: IOpenSubtitleService) {
|
||||
|
||||
/*
|
||||
@ -41,8 +43,11 @@ class OpenSubtitleRepository(private val openSubtitleService: IOpenSubtitleServi
|
||||
}
|
||||
|
||||
suspend fun getDownloadLink(fileId: Long): DownloadLink {
|
||||
val query = openSubtitleService.queryDownloadUrl(DownloadLinkBody(fileId))
|
||||
return query.body() ?: throw Exception("No body")
|
||||
return openSubtitleService.queryDownloadUrl(DownloadLinkBody(fileId))
|
||||
}
|
||||
|
||||
fun login(username: String, password: String): Response<OpenSubtitleAccount> {
|
||||
return openSubtitleService.login(LoginBody(username, password)).execute()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* ************************************************************************
|
||||
* OpensubtitleUser.kt
|
||||
* *************************************************************************
|
||||
* Copyright © 2024 VLC authors and VideoLAN
|
||||
* Author: Nicolas POMEPUY
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
* **************************************************************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package main.java.org.videolan.resources.opensubtitles
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import org.videolan.resources.opensubtitles.OpenSubtitleAccount
|
||||
import org.videolan.tools.KEY_OPEN_SUBTITLES_USER
|
||||
import org.videolan.tools.putSingle
|
||||
|
||||
data class OpenSubtitlesUser(
|
||||
val logged: Boolean = false,
|
||||
val account: OpenSubtitleAccount? = null,
|
||||
val username: String = "",
|
||||
val errorMessage: String? = null
|
||||
) {
|
||||
fun isVip() = account?.user?.vip ?: false
|
||||
}
|
||||
|
||||
object OpenSubtitlesUserUtil {
|
||||
fun get(settings: SharedPreferences): OpenSubtitlesUser {
|
||||
settings.getString(KEY_OPEN_SUBTITLES_USER, "")?.let { userString ->
|
||||
val moshi = Moshi.Builder().build()
|
||||
val type = Types.newParameterizedType(OpenSubtitlesUser::class.java)
|
||||
val jsonAdapter: JsonAdapter<OpenSubtitlesUser> = moshi.adapter(type)
|
||||
return try {
|
||||
jsonAdapter.fromJson(userString) ?: OpenSubtitlesUser()
|
||||
} catch (e: Exception) {
|
||||
OpenSubtitlesUser()
|
||||
}
|
||||
}
|
||||
return OpenSubtitlesUser()
|
||||
}
|
||||
|
||||
fun save(settings: SharedPreferences, user: OpenSubtitlesUser) {
|
||||
val moshi = Moshi.Builder().build()
|
||||
val jsonAdapter = moshi.adapter(OpenSubtitlesUser::class.java)
|
||||
settings.putSingle(KEY_OPEN_SUBTITLES_USER, jsonAdapter.toJson(user))
|
||||
}
|
||||
}
|
@ -23,8 +23,8 @@
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:color="@color/orange300" />
|
||||
<item android:state_pressed="true" android:color="@color/orange300" />
|
||||
<item android:state_focused="true" android:color="@color/orange300" />
|
||||
<item android:state_selected="true" android:color="?attr/colorPrimary" />
|
||||
<item android:state_pressed="true" android:color="?attr/colorPrimary" />
|
||||
<item android:state_focused="true" android:color="?attr/colorPrimary" />
|
||||
<item android:color="?attr/colorControlNormal" />
|
||||
</selector>
|
11
application/resources/src/main/res/drawable/ic_account.xml
Normal file
11
application/resources/src/main/res/drawable/ic_account.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
|
||||
<path
|
||||
android:fillColor="@color/standard_selection_control_normal"
|
||||
android:pathData="M234,684Q285,645 348,622.5Q411,600 480,600Q549,600 612,622.5Q675,645 726,684Q761,643 780.5,591Q800,539 800,480Q800,347 706.5,253.5Q613,160 480,160Q347,160 253.5,253.5Q160,347 160,480Q160,539 179.5,591Q199,643 234,684ZM480,520Q421,520 380.5,479.5Q340,439 340,380Q340,321 380.5,280.5Q421,240 480,240Q539,240 579.5,280.5Q620,321 620,380Q620,439 579.5,479.5Q539,520 480,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q533,800 580,784.5Q627,769 666,740Q627,711 580,695.5Q533,680 480,680Q427,680 380,695.5Q333,711 294,740Q333,769 380,784.5Q427,800 480,800ZM480,440Q506,440 523,423Q540,406 540,380Q540,354 523,337Q506,320 480,320Q454,320 437,337Q420,354 420,380Q420,406 437,423Q454,440 480,440ZM480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380Q480,380 480,380ZM480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Q480,740 480,740Z" />
|
||||
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M9.31,6.71c-0.39,0.39 -0.39,1.02 0,1.41L13.19,12l-3.88,3.88c-0.39,0.39 -0.39,1.02 0,1.41 0.39,0.39 1.02,0.39 1.41,0l4.59,-4.59c0.39,-0.39 0.39,-1.02 0,-1.41L10.72,6.7c-0.38,-0.38 -1.02,-0.38 -1.41,0.01z"/>
|
||||
</vector>
|
@ -0,0 +1,9 @@
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/red500transparent25">
|
||||
</solid>
|
||||
<corners android:radius="8dp">
|
||||
</corners>
|
||||
|
||||
</shape>
|
@ -20,6 +20,7 @@
|
||||
<color name="orange800">#ff610a</color>
|
||||
<color name="orange900">#ff5014</color>
|
||||
|
||||
<color name="red500transparent25">#40ff0000</color>
|
||||
<color name="red500transparent">#b4ff0000</color>
|
||||
<color name="orange500transparent">#b4ff8800</color>
|
||||
<color name="orange500focus">#86ff8800</color>
|
||||
|
@ -716,6 +716,17 @@
|
||||
<string name="popup_playback">Playing in a Pop-Up window</string>
|
||||
<string name="popup_expand">Expand video</string>
|
||||
<string name="download_subtitles">Download subtitles</string>
|
||||
<string name="open_subtitles_login_title">Open subtitles login</string>
|
||||
<string name="open_subtitles_not_logged_in">You are not logged in</string>
|
||||
<string name="open_subtitles_logged_in">Welcome %1$s</string>
|
||||
<string name="open_subtitles_vip">You are a VIP OpenSubtitles user</string>
|
||||
<string name="open_subtitles_log_out">Log out</string>
|
||||
<string name="open_subtitles_username">Username</string>
|
||||
<string name="open_subtitles_password">Password</string>
|
||||
<string name="open_subtitles_is_vip">VIP account</string>
|
||||
<string name="open_subtitles_is_not_vip">Standard account</string>
|
||||
<string name="login_error">Invalid credentials</string>
|
||||
<string name="unknown_error">Unexpected error</string>
|
||||
<string name="browse_folder">Browse folder</string>
|
||||
<string name="listen">Listen</string>
|
||||
<string name="apply_to_bt">Apply to bluetooth device</string>
|
||||
|
@ -246,6 +246,10 @@ const val ALBUMS_SHOW_TRACK_NUMBER = "albums_show_track_number"
|
||||
//widgets
|
||||
const val WIDGETS_PREVIEW_PLAYING = "widgets_preview_playing"
|
||||
|
||||
//OpenSubtitles
|
||||
const val KEY_OPEN_SUBTITLES_USER = "open_subtitles_user"
|
||||
|
||||
|
||||
const val KEY_SAFE_MODE_PIN = "safe_mode_pin"
|
||||
const val KEY_RESTRICT_SETTINGS = "restrict_settings"
|
||||
const val KEY_SAFE_MODE = "safe_mode"
|
||||
|
@ -90,14 +90,14 @@
|
||||
android:contentDescription="@string/talkback_subtitle_history"
|
||||
android:selected="@{state == state.History}"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/movieName"
|
||||
app:layout_constraintEnd_toStartOf="@+id/sub_download_next"
|
||||
app:layout_constraintEnd_toStartOf="@+id/sub_login"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/sub_download_search"
|
||||
app:layout_constraintTop_toTopOf="@+id/movieName"
|
||||
app:srcCompat="@drawable/ic_history" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sub_download_next"
|
||||
android:id="@+id/sub_login"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
@ -106,10 +106,11 @@
|
||||
android:padding="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/movieName"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:selected="@{state == state.Login}"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/sub_download_history"
|
||||
app:layout_constraintTop_toTopOf="@+id/movieName"
|
||||
app:srcCompat="@drawable/ic_sub_next" />
|
||||
app:srcCompat="@drawable/ic_account" />
|
||||
|
||||
|
||||
<TextView
|
||||
@ -200,7 +201,7 @@
|
||||
android:visibility="@{state == state.Search ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/movieName">
|
||||
app:layout_constraintTop_toBottomOf="@+id/subs_download_list">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/name"
|
||||
@ -293,6 +294,124 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/seasonContainer" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView37"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/open_subtitles_login_title"
|
||||
android:textColor="?attr/font_default"
|
||||
android:textSize="16sp"
|
||||
android:visibility="@{state == state.Login ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cancel_button" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/loginDescription"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@{viewmodel.observableUser.get().logged ? @{@string/open_subtitles_logged_in(viewmodel.observableUser.get().username)} : @string/open_subtitles_not_logged_in}"
|
||||
android:visibility="@{state == state.Login ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView37" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vipDescription"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@{viewmodel.observableUser.get().isVip() ? @string/open_subtitles_is_vip : @string/open_subtitles_is_not_vip}"
|
||||
android:visibility="@{state == state.Login && viewmodel.observableUser.get().logged ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/rounded_corners_permissions_warning"
|
||||
android:padding="12dp"
|
||||
android:text="@{viewmodel.observableUser.get().errorMessage}"
|
||||
android:textSize="16sp"
|
||||
android:visibility="@{state == state.Login && !TextUtils.isEmpty(viewmodel.observableUser.get().errorMessage) ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/passwordContainer" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/usernameContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="@{state == state.Login && !viewmodel.observableUser.get().logged ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/vipDescription">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:focusable="true"
|
||||
android:hint="@string/open_subtitles_username"
|
||||
android:imeOptions="actionDone"
|
||||
android:nextFocusRight="@+id/search_button"
|
||||
android:nextFocusDown="@+id/search_button"
|
||||
android:nextFocusForward="@+id/search_button"
|
||||
android:visibility="@{state == state.Login ? View.VISIBLE : View.GONE}" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/passwordContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="@{state == state.Login && !viewmodel.observableUser.get().logged ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/usernameContainer">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:focusable="true"
|
||||
android:hint="@string/open_subtitles_password"
|
||||
android:imeOptions="actionDone"
|
||||
android:nextFocusRight="@+id/search_button"
|
||||
android:nextFocusDown="@+id/search_button"
|
||||
android:nextFocusForward="@+id/search_button"
|
||||
android:password="true"
|
||||
android:visibility="@{state == state.Login ? View.VISIBLE : View.GONE}" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/loginButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@{viewmodel.observableUser.get().logged ? @string/open_subtitles_log_out : @string/login}"
|
||||
android:visibility="@{state == state.Login ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/error" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.videolan.vlc.gui.dialogs
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Configuration
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
@ -23,15 +24,16 @@ import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||
import kotlinx.coroutines.channels.actor
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.withContext
|
||||
import main.java.org.videolan.resources.opensubtitles.OpenSubtitlesUser
|
||||
import main.java.org.videolan.resources.opensubtitles.OpenSubtitlesUserUtil
|
||||
import org.videolan.resources.opensubtitles.OpenSubtitleRepository
|
||||
import org.videolan.resources.util.parcelable
|
||||
import org.videolan.resources.util.parcelableList
|
||||
import org.videolan.tools.Settings
|
||||
import org.videolan.vlc.R
|
||||
import org.videolan.vlc.databinding.SubtitleDownloaderDialogBinding
|
||||
import org.videolan.vlc.gui.helpers.UiTools
|
||||
import org.videolan.vlc.gui.helpers.UiTools.deleteSubtitleDialog
|
||||
import org.videolan.vlc.gui.view.OnItemSelectListener
|
||||
import org.videolan.vlc.media.MediaUtils
|
||||
import org.videolan.vlc.util.VLCDownloadManager
|
||||
import org.videolan.vlc.viewmodels.SubtitlesModel
|
||||
|
||||
@ -46,6 +48,7 @@ class SubtitleDownloaderDialogFragment : VLCBottomSheetDialogFragment() {
|
||||
|
||||
override fun initialFocusedView(): View = binding.movieName
|
||||
|
||||
private lateinit var settings: SharedPreferences
|
||||
private lateinit var downloadAdapter: SubtitlesAdapter
|
||||
private lateinit var historyAdapter: SubtitlesAdapter
|
||||
private lateinit var binding: SubtitleDownloaderDialogBinding
|
||||
@ -112,10 +115,27 @@ class SubtitleDownloaderDialogFragment : VLCBottomSheetDialogFragment() {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
settings = Settings.getInstance(requireContext())
|
||||
binding = SubtitleDownloaderDialogBinding.inflate(inflater, container, false)
|
||||
binding.viewmodel = viewModel
|
||||
|
||||
binding.subLogin.setOnClickListener {
|
||||
state = SubDownloadDialogState.Login
|
||||
}
|
||||
|
||||
binding.loginButton.setOnClickListener {
|
||||
if (viewModel.observableUser.get()?.logged == true) {
|
||||
val user = OpenSubtitlesUser()
|
||||
OpenSubtitlesUserUtil.save(settings, user)
|
||||
viewModel.observableUser.set(user)
|
||||
}else {
|
||||
viewModel.login(
|
||||
settings,
|
||||
binding.username.text.toString(),
|
||||
binding.password.text.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.movieName.text = names ?: uris.lastPathSegment
|
||||
state = SubDownloadDialogState.Download
|
||||
@ -161,6 +181,7 @@ class SubtitleDownloaderDialogFragment : VLCBottomSheetDialogFragment() {
|
||||
})
|
||||
//todo
|
||||
viewModel.observableSearchHearingImpaired.set(false)
|
||||
viewModel.observableUser.set(OpenSubtitlesUserUtil.get(settings))
|
||||
|
||||
binding.retryButton.setOnClickListener {
|
||||
viewModel.onRefresh()
|
||||
@ -220,5 +241,6 @@ class SubtitleDownloaderDialogFragment : VLCBottomSheetDialogFragment() {
|
||||
enum class SubDownloadDialogState {
|
||||
Download,
|
||||
History,
|
||||
Search
|
||||
Search,
|
||||
Login
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.videolan.vlc.viewmodels
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.text.Html
|
||||
import android.text.Spanned
|
||||
@ -9,19 +10,25 @@ import androidx.core.text.toSpanned
|
||||
import androidx.databinding.Observable
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import androidx.databinding.ObservableField
|
||||
import androidx.lifecycle.*
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import main.java.org.videolan.resources.opensubtitles.OpenSubtitlesUser
|
||||
import main.java.org.videolan.resources.opensubtitles.OpenSubtitlesUserUtil
|
||||
import org.videolan.resources.opensubtitles.Data
|
||||
import org.videolan.resources.opensubtitles.OpenSubV1
|
||||
import org.videolan.resources.opensubtitles.OpenSubtitleClient
|
||||
import org.videolan.resources.opensubtitles.OpenSubtitleRepository
|
||||
import org.videolan.resources.util.NoConnectivityException
|
||||
import org.videolan.tools.CoroutineContextProvider
|
||||
import org.videolan.tools.FileUtils
|
||||
import org.videolan.tools.LocaleUtils
|
||||
import org.videolan.tools.Settings
|
||||
import org.videolan.tools.putSingle
|
||||
import org.videolan.vlc.BuildConfig
|
||||
@ -31,7 +38,28 @@ import org.videolan.vlc.gui.dialogs.SubtitleItem
|
||||
import org.videolan.vlc.repository.ExternalSubRepository
|
||||
import org.videolan.vlc.util.TextUtils
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
import java.util.MissingResourceException
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.MutableList
|
||||
import kotlin.collections.emptyList
|
||||
import kotlin.collections.filter
|
||||
import kotlin.collections.find
|
||||
import kotlin.collections.first
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.get
|
||||
import kotlin.collections.indices
|
||||
import kotlin.collections.isNotEmpty
|
||||
import kotlin.collections.joinToString
|
||||
import kotlin.collections.listOf
|
||||
import kotlin.collections.map
|
||||
import kotlin.collections.mutableListOf
|
||||
import kotlin.collections.orEmpty
|
||||
import kotlin.collections.plus
|
||||
import kotlin.collections.set
|
||||
import kotlin.collections.setOf
|
||||
import kotlin.collections.toList
|
||||
|
||||
private const val LAST_USED_LANGUAGES = "last_used_subtitles"
|
||||
|
||||
@ -41,6 +69,7 @@ class SubtitlesModel(private val context: Context, private val mediaUri: Uri, pr
|
||||
val observableSearchSeason = ObservableField<String>()
|
||||
val observableSearchLanguage = ObservableField<List<String>>()
|
||||
val observableSearchHearingImpaired = ObservableField<Boolean>()
|
||||
val observableUser = ObservableField<OpenSubtitlesUser>()
|
||||
private var previousSearchLanguage: List<String>? = null
|
||||
val manualSearchEnabled = ObservableBoolean(false)
|
||||
|
||||
@ -235,6 +264,24 @@ class SubtitlesModel(private val context: Context, private val mediaUri: Uri, pr
|
||||
return Settings.getInstance(context).getStringSet(LAST_USED_LANGUAGES, setOf(language))?.map { if (it.length > 2) migrateFromOld(it) ?: it else it } ?: emptyList()
|
||||
}
|
||||
|
||||
fun login(settings: SharedPreferences, username: String, password: String) {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val call = OpenSubtitleRepository.getInstance().login(username, password)
|
||||
if (call.isSuccessful) {
|
||||
val userResult = call.body()
|
||||
if (userResult != null) {
|
||||
val openSubtitlesUser = OpenSubtitlesUser(true, userResult, username = username)
|
||||
OpenSubtitlesUserUtil.save(settings, openSubtitlesUser)
|
||||
observableUser.set(openSubtitlesUser)
|
||||
return@withContext
|
||||
}
|
||||
}
|
||||
observableUser.set(OpenSubtitlesUser(false, null, errorMessage = if (call.code() == 401) context.getString(R.string.login_error) else context.getString(R.string.unknown_error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun migrateFromOld(it: String?): String? {
|
||||
return oldLanguagesMigration[it]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user