mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge branch 'master' into githubAccount
This commit is contained in:
commit
eaa1171095
8 changed files with 259 additions and 26 deletions
|
@ -199,6 +199,9 @@ dependencies {
|
||||||
|
|
||||||
// Library/extensions searching with Levenshtein distance
|
// Library/extensions searching with Levenshtein distance
|
||||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||||
|
|
||||||
|
// Git
|
||||||
|
implementation 'org.openl.jgit:org.eclipse.jgit:6.2.0.202206071550-openl'
|
||||||
}
|
}
|
||||||
|
|
||||||
task androidSourcesJar(type: Jar) {
|
task androidSourcesJar(type: Jar) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
|
||||||
val malApi = MALApi(0)
|
val malApi = MALApi(0)
|
||||||
val aniListApi = AniListApi(0)
|
val aniListApi = AniListApi(0)
|
||||||
val openSubtitlesApi = OpenSubtitlesApi(0)
|
val openSubtitlesApi = OpenSubtitlesApi(0)
|
||||||
|
val githubApi = GithubApi(0)
|
||||||
val indexSubtitlesApi = IndexSubtitleApi()
|
val indexSubtitlesApi = IndexSubtitleApi()
|
||||||
|
|
||||||
// used to login via app intent
|
// used to login via app intent
|
||||||
|
@ -22,7 +23,7 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
|
||||||
// this needs init with context and can be accessed in settings
|
// this needs init with context and can be accessed in settings
|
||||||
val accountManagers
|
val accountManagers
|
||||||
get() = listOf(
|
get() = listOf(
|
||||||
malApi, aniListApi, openSubtitlesApi, //nginxApi
|
malApi, aniListApi, openSubtitlesApi, githubApi //nginxApi
|
||||||
)
|
)
|
||||||
|
|
||||||
// used for active syncing
|
// used for active syncing
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
package com.lagradost.cloudstream3.syncproviders.providers
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.lagradost.cloudstream3.*
|
||||||
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
|
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||||
|
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||||
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
||||||
|
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI
|
||||||
|
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPIManager
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
|
import com.lagradost.nicehttp.RequestBodyTypes
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import org.eclipse.jgit.api.Git
|
||||||
|
import org.eclipse.jgit.transport.URIish
|
||||||
|
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.attribute.FileAttribute
|
||||||
|
|
||||||
|
|
||||||
|
class GithubApi(index: Int) : InAppAuthAPIManager(index){
|
||||||
|
override val idPrefix = "Github"
|
||||||
|
override val name = "Github"
|
||||||
|
override val icon = R.drawable.ic_github_logo
|
||||||
|
override val requiresPassword = true
|
||||||
|
override val createAccountUrl = "https://github.com/settings/tokens/new?description=Cloudstream+Backup&scopes=gist"
|
||||||
|
|
||||||
|
data class GithubOAuthEntity(
|
||||||
|
var repoUrl: String,
|
||||||
|
var token: String,
|
||||||
|
var userName: String,
|
||||||
|
var userAvatar: String,
|
||||||
|
var gistUrl: String
|
||||||
|
)
|
||||||
|
companion object {
|
||||||
|
const val GITHUB_USER_KEY: String = "github_user" // user data like profile
|
||||||
|
var currentSession: GithubOAuthEntity? = null
|
||||||
|
}
|
||||||
|
private fun getAuthKey(): GithubOAuthEntity? {
|
||||||
|
return getKey(accountId, GITHUB_USER_KEY)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
data class gistsElements (
|
||||||
|
@JsonProperty("git_pull_url") val gitUrl: String,
|
||||||
|
@JsonProperty("url") val gistUrl:String,
|
||||||
|
@JsonProperty("files") val files: Map<String, File>,
|
||||||
|
@JsonProperty("owner") val owner: OwnerData
|
||||||
|
)
|
||||||
|
data class OwnerData(
|
||||||
|
@JsonProperty("login") val userName: String,
|
||||||
|
@JsonProperty("avatar_url") val userAvatar : String
|
||||||
|
)
|
||||||
|
data class File (
|
||||||
|
@JsonProperty("content") val dataRaw: String?
|
||||||
|
)
|
||||||
|
|
||||||
|
private suspend fun initLogin(githubToken: String): Boolean{
|
||||||
|
val response = app.get("https://api.github.com/gists",
|
||||||
|
headers= mapOf(
|
||||||
|
Pair("Accept" , "application/vnd.github+json"),
|
||||||
|
Pair("Authorization", "token $githubToken"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!response.isSuccessful) { return false }
|
||||||
|
|
||||||
|
val repo = tryParseJson<List<gistsElements>>(response.text)?.filter {
|
||||||
|
it.files.keys.first() == "Cloudstream_Backup_data.txt"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repo?.isEmpty() == true){
|
||||||
|
val gitresponse = app.post("https://api.github.com/gists",
|
||||||
|
headers= mapOf(
|
||||||
|
Pair("Accept" , "application/vnd.github+json"),
|
||||||
|
Pair("Authorization", "token $githubToken"),
|
||||||
|
),
|
||||||
|
requestBody = """{"description":"Cloudstream private backup gist","public":false,"files":{"Cloudstream_Backup_data.txt":{"content":"initialization"}}}""".toRequestBody(
|
||||||
|
RequestBodyTypes.JSON.toMediaTypeOrNull()))
|
||||||
|
if (!gitresponse.isSuccessful) {return false}
|
||||||
|
tryParseJson<gistsElements>(gitresponse.text).let {
|
||||||
|
setKey(accountId, GITHUB_USER_KEY, GithubOAuthEntity(
|
||||||
|
token = githubToken,
|
||||||
|
repoUrl = it?.gitUrl?: run {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
userName = it.owner.userName,
|
||||||
|
userAvatar = it.owner.userAvatar,
|
||||||
|
gistUrl = it.gistUrl
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
repo?.first().let {
|
||||||
|
setKey(accountId, GITHUB_USER_KEY, GithubOAuthEntity(
|
||||||
|
token = githubToken,
|
||||||
|
repoUrl = it?.gitUrl?: run {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
userName = it.owner.userName,
|
||||||
|
userAvatar = it.owner.userAvatar,
|
||||||
|
gistUrl = it.gistUrl
|
||||||
|
))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
override suspend fun login(data: InAppAuthAPI.LoginData): Boolean {
|
||||||
|
switchToNewAccount()
|
||||||
|
val githubToken = data.password ?: throw IllegalArgumentException ("Requires Password")
|
||||||
|
try {
|
||||||
|
if (initLogin(githubToken)) {
|
||||||
|
registerAccount()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
|
switchToOldAccount()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLatestLoginData(): InAppAuthAPI.LoginData? {
|
||||||
|
val current = getAuthKey() ?: return null
|
||||||
|
return InAppAuthAPI.LoginData(email = current.repoUrl, password = current.token, username = current.userName, server = current.gistUrl)
|
||||||
|
}
|
||||||
|
override suspend fun initialize() {
|
||||||
|
currentSession = getAuthKey()
|
||||||
|
val repoUrl = currentSession?.repoUrl ?: return
|
||||||
|
val token = currentSession?.token ?: return
|
||||||
|
setKey(repoUrl, token)
|
||||||
|
}
|
||||||
|
override fun logOut() {
|
||||||
|
removeKey(accountId, GITHUB_USER_KEY)
|
||||||
|
removeAccountKeys()
|
||||||
|
currentSession = getAuthKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loginInfo(): AuthAPI.LoginInfo? {
|
||||||
|
return getAuthKey()?.let { user ->
|
||||||
|
AuthAPI.LoginInfo(
|
||||||
|
profilePicture = user.userAvatar,
|
||||||
|
name = user.userName,
|
||||||
|
accountIndex = accountIndex,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -124,8 +124,8 @@ class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubApi
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun login(data: InAppAuthAPI.LoginData): Boolean {
|
override suspend fun login(data: InAppAuthAPI.LoginData): Boolean {
|
||||||
val username = data.username ?: throw ErrorLoadingException("Requires Username")
|
val username = data.username ?: throw IllegalArgumentException ("Requires Username")
|
||||||
val password = data.password ?: throw ErrorLoadingException("Requires Password")
|
val password = data.password ?: throw IllegalArgumentException ("Requires Password")
|
||||||
switchToNewAccount()
|
switchToNewAccount()
|
||||||
try {
|
try {
|
||||||
if (initLogin(username, password)) {
|
if (initLogin(username, password)) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager
|
||||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.aniListApi
|
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.aniListApi
|
||||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.malApi
|
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.malApi
|
||||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.openSubtitlesApi
|
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.openSubtitlesApi
|
||||||
|
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.githubApi
|
||||||
import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
||||||
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI
|
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI
|
||||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API
|
import com.lagradost.cloudstream3.syncproviders.OAuth2API
|
||||||
|
@ -227,6 +228,8 @@ class SettingsAccount : PreferenceFragmentCompat() {
|
||||||
R.string.mal_key to malApi,
|
R.string.mal_key to malApi,
|
||||||
R.string.anilist_key to aniListApi,
|
R.string.anilist_key to aniListApi,
|
||||||
R.string.opensubtitles_key to openSubtitlesApi,
|
R.string.opensubtitles_key to openSubtitlesApi,
|
||||||
|
R.string.github_key to githubApi
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for ((key, api) in syncApis) {
|
for ((key, api) in syncApis) {
|
||||||
|
|
|
@ -13,23 +13,29 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.plugins.PLUGINS_KEY
|
import com.lagradost.cloudstream3.plugins.PLUGINS_KEY
|
||||||
import com.lagradost.cloudstream3.plugins.PLUGINS_KEY_LOCAL
|
import com.lagradost.cloudstream3.plugins.PLUGINS_KEY_LOCAL
|
||||||
|
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.githubApi
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_CACHED_LIST
|
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_CACHED_LIST
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_SHOULD_UPDATE_LIST
|
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_SHOULD_UPDATE_LIST
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_TOKEN_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_TOKEN_KEY
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_UNIXTIME_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_UNIXTIME_KEY
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_USER_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_USER_KEY
|
||||||
|
import com.lagradost.cloudstream3.syncproviders.providers.GithubApi
|
||||||
|
import com.lagradost.cloudstream3.syncproviders.providers.GithubApi.Companion.GITHUB_USER_KEY
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_CACHED_LIST
|
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_CACHED_LIST
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_REFRESH_TOKEN_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_REFRESH_TOKEN_KEY
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_SHOULD_UPDATE_LIST
|
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_SHOULD_UPDATE_LIST
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_TOKEN_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_TOKEN_KEY
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_UNIXTIME_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_UNIXTIME_KEY
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_USER_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_USER_KEY
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.OpenSubtitlesApi
|
|
||||||
import com.lagradost.cloudstream3.syncproviders.providers.OpenSubtitlesApi.Companion.OPEN_SUBTITLES_USER_KEY
|
import com.lagradost.cloudstream3.syncproviders.providers.OpenSubtitlesApi.Companion.OPEN_SUBTITLES_USER_KEY
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getDefaultSharedPrefs
|
import com.lagradost.cloudstream3.utils.DataStore.getDefaultSharedPrefs
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs
|
import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.mapper
|
import com.lagradost.cloudstream3.utils.DataStore.mapper
|
||||||
|
@ -38,12 +44,14 @@ import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.isDownloadDir
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager.isDownloadDir
|
||||||
|
import org.eclipse.jgit.api.Git
|
||||||
|
import org.eclipse.jgit.transport.URIish
|
||||||
|
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.lang.System.currentTimeMillis
|
import java.lang.System.currentTimeMillis
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object BackupUtils {
|
object BackupUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,9 +74,10 @@ object BackupUtils {
|
||||||
// The plugins themselves are not backed up
|
// The plugins themselves are not backed up
|
||||||
PLUGINS_KEY,
|
PLUGINS_KEY,
|
||||||
PLUGINS_KEY_LOCAL,
|
PLUGINS_KEY_LOCAL,
|
||||||
|
GITHUB_USER_KEY,
|
||||||
OPEN_SUBTITLES_USER_KEY,
|
OPEN_SUBTITLES_USER_KEY,
|
||||||
"nginx_user", // Nginx user key
|
"nginx_user", // Nginx user key
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/** false if blacklisted key */
|
/** false if blacklisted key */
|
||||||
|
@ -283,4 +292,61 @@ object BackupUtils {
|
||||||
setKeyRaw(it.key, it.value, isEditingAppSettings)
|
setKeyRaw(it.key, it.value, isEditingAppSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun FragmentActivity.backupGithub(){
|
||||||
|
val backup = this.getBackup()
|
||||||
|
ioSafe {
|
||||||
|
val tmpDir = createTempDir()
|
||||||
|
val gitUrl = githubApi.getLatestLoginData()?.email ?: throw IllegalArgumentException ("Requires Username")
|
||||||
|
val token = githubApi.getLatestLoginData()?.password ?: throw IllegalArgumentException ("Requires Username")
|
||||||
|
val git = Git.cloneRepository()
|
||||||
|
.setURI(gitUrl)
|
||||||
|
.setDirectory(tmpDir)
|
||||||
|
.setTimeout(30)
|
||||||
|
.setCredentialsProvider(
|
||||||
|
UsernamePasswordCredentialsProvider(token, "")
|
||||||
|
)
|
||||||
|
.call()
|
||||||
|
tmpDir.listFiles()?.first { it.name != ".git" }?.writeText(backup.toJson())
|
||||||
|
git.add()
|
||||||
|
.addFilepattern(".")
|
||||||
|
.call()
|
||||||
|
git.commit()
|
||||||
|
.setAll(true)
|
||||||
|
.setMessage("Update backup")
|
||||||
|
.call()
|
||||||
|
git.remoteAdd()
|
||||||
|
.setName("origin")
|
||||||
|
.setUri(URIish(gitUrl))
|
||||||
|
.call()
|
||||||
|
git.push()
|
||||||
|
.setRemote(gitUrl)
|
||||||
|
.setTimeout(30)
|
||||||
|
.setCredentialsProvider(
|
||||||
|
UsernamePasswordCredentialsProvider(token, "")
|
||||||
|
)
|
||||||
|
.call();
|
||||||
|
tmpDir.deleteRecursively()
|
||||||
|
}
|
||||||
|
showToast(
|
||||||
|
this,
|
||||||
|
R.string.backup_success,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FragmentActivity.restorePromptGithub() =
|
||||||
|
ioSafe {
|
||||||
|
val gistUrl = githubApi.getLatestLoginData()?.server ?: throw IllegalAccessException()
|
||||||
|
val jsondata = app.get(gistUrl).text
|
||||||
|
val dataraw = parseJson<GithubApi.gistsElements>(jsondata ?: "").files.values.first().dataRaw?: throw IllegalAccessException()
|
||||||
|
val data = parseJson<BackupFile>(dataraw)
|
||||||
|
this@restorePromptGithub.restore(
|
||||||
|
data,
|
||||||
|
restoreSettings = true,
|
||||||
|
restoreDataStore = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -465,6 +465,7 @@
|
||||||
<string name="anilist_key" translatable="false">anilist_key</string>
|
<string name="anilist_key" translatable="false">anilist_key</string>
|
||||||
<string name="mal_key" translatable="false">mal_key</string>
|
<string name="mal_key" translatable="false">mal_key</string>
|
||||||
<string name="opensubtitles_key" translatable="false">opensubtitles_key</string>
|
<string name="opensubtitles_key" translatable="false">opensubtitles_key</string>
|
||||||
|
<string name="github_key" translatable="false">github_key</string>
|
||||||
<string name="nginx_key" translatable="false">nginx_key</string>
|
<string name="nginx_key" translatable="false">nginx_key</string>
|
||||||
<string name="example_password">password123</string>
|
<string name="example_password">password123</string>
|
||||||
<string name="example_username">MyCoolUsername</string>
|
<string name="example_username">MyCoolUsername</string>
|
||||||
|
|
|
@ -1,27 +1,30 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
<Preference
|
<Preference
|
||||||
android:key="@string/mal_key"
|
android:key="@string/mal_key"
|
||||||
android:icon="@drawable/mal_logo" />
|
android:icon="@drawable/mal_logo" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="@string/anilist_key"
|
android:key="@string/anilist_key"
|
||||||
android:icon="@drawable/ic_anilist_icon" />
|
android:icon="@drawable/ic_anilist_icon" />
|
||||||
<Preference
|
<Preference
|
||||||
android:key="@string/opensubtitles_key"
|
android:key="@string/opensubtitles_key"
|
||||||
android:icon="@drawable/open_subtitles_icon" />
|
android:icon="@drawable/open_subtitles_icon" />
|
||||||
<!-- <Preference-->
|
<Preference
|
||||||
<!-- android:key="@string/nginx_key"-->
|
android:key="@string/github_key"
|
||||||
<!-- android:icon="@drawable/nginx" />-->
|
android:icon="@drawable/ic_github_logo" />
|
||||||
|
<!-- <Preference-->
|
||||||
|
<!-- android:key="@string/nginx_key"-->
|
||||||
|
<!-- android:icon="@drawable/nginx" />-->
|
||||||
|
|
||||||
<!-- <Preference-->
|
<!-- <Preference-->
|
||||||
<!-- android:title="@string/nginx_info_title"-->
|
<!-- android:title="@string/nginx_info_title"-->
|
||||||
<!-- android:icon="@drawable/nginx_question"-->
|
<!-- android:icon="@drawable/nginx_question"-->
|
||||||
<!-- android:summary="@string/nginx_info_summary">-->
|
<!-- android:summary="@string/nginx_info_summary">-->
|
||||||
<!-- <intent-->
|
<!-- <intent-->
|
||||||
<!-- android:action="android.intent.action.VIEW"-->
|
<!-- android:action="android.intent.action.VIEW"-->
|
||||||
<!-- android:data="https://www.sarlays.com/use-nginx-with-cloudstream/" />-->
|
<!-- android:data="https://www.sarlays.com/use-nginx-with-cloudstream/" />-->
|
||||||
<!-- </Preference>-->
|
<!-- </Preference>-->
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
Loading…
Add table
Add a link
Reference in a new issue