mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 07:50:31 +05:30
import subscription
This commit is contained in:
parent
347179b59a
commit
6688e7a5de
@ -10,8 +10,8 @@ android {
|
||||
applicationId 'com.github.libretube'
|
||||
minSdk 21
|
||||
targetSdk 31
|
||||
versionCode 6
|
||||
versionName '0.2.4'
|
||||
versionCode 7
|
||||
versionName '0.2.5'
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
resValue "string", "app_name", "LibreTube"
|
||||
|
@ -16,23 +16,10 @@
|
||||
}
|
||||
],
|
||||
"attributes": [],
|
||||
"versionCode": 6,
|
||||
"versionName": "0.2.4",
|
||||
"versionCode": 7,
|
||||
"versionName": "0.2.5",
|
||||
"outputFile": "app-x86_64-release.apk"
|
||||
},
|
||||
{
|
||||
"type": "ONE_OF_MANY",
|
||||
"filters": [
|
||||
{
|
||||
"filterType": "ABI",
|
||||
"value": "arm64-v8a"
|
||||
}
|
||||
],
|
||||
"attributes": [],
|
||||
"versionCode": 6,
|
||||
"versionName": "0.2.4",
|
||||
"outputFile": "app-arm64-v8a-release.apk"
|
||||
},
|
||||
{
|
||||
"type": "ONE_OF_MANY",
|
||||
"filters": [
|
||||
@ -42,10 +29,23 @@
|
||||
}
|
||||
],
|
||||
"attributes": [],
|
||||
"versionCode": 6,
|
||||
"versionName": "0.2.4",
|
||||
"versionCode": 7,
|
||||
"versionName": "0.2.5",
|
||||
"outputFile": "app-x86-release.apk"
|
||||
},
|
||||
{
|
||||
"type": "ONE_OF_MANY",
|
||||
"filters": [
|
||||
{
|
||||
"filterType": "ABI",
|
||||
"value": "arm64-v8a"
|
||||
}
|
||||
],
|
||||
"attributes": [],
|
||||
"versionCode": 7,
|
||||
"versionName": "0.2.5",
|
||||
"outputFile": "app-arm64-v8a-release.apk"
|
||||
},
|
||||
{
|
||||
"type": "ONE_OF_MANY",
|
||||
"filters": [
|
||||
@ -55,8 +55,8 @@
|
||||
}
|
||||
],
|
||||
"attributes": [],
|
||||
"versionCode": 6,
|
||||
"versionName": "0.2.4",
|
||||
"versionCode": 7,
|
||||
"versionName": "0.2.5",
|
||||
"outputFile": "app-armeabi-v7a-release.apk"
|
||||
}
|
||||
],
|
||||
|
@ -7,6 +7,7 @@
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
@ -15,6 +15,7 @@ import android.view.*
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
@ -49,6 +50,11 @@ class MainActivity : AppCompatActivity() {
|
||||
RetrofitInstance.url=sharedPreferences.getString("instance", "https://pipedapi.kavin.rocks/")!!
|
||||
DynamicColors.applyToActivitiesIfAvailable(application)
|
||||
setContentView(R.layout.activity_main)
|
||||
when (sharedPreferences.getString("theme_togglee", "A")!!) {
|
||||
"A" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
"L" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||
"D" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||
}
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
|
||||
bottomNavigationView = findViewById(R.id.bottomNav)
|
||||
|
@ -52,8 +52,13 @@ interface PipedApi {
|
||||
@POST("unsubscribe")
|
||||
suspend fun unsubscribe(@Header("Authorization") token: String, @Body subscribe: Subscribe): Message
|
||||
|
||||
@POST("import")
|
||||
suspend fun importSubscriptions(@Header("Authorization") token: String, @Body channels: List<String>): Message
|
||||
|
||||
//only for fetching servers list
|
||||
@GET
|
||||
suspend fun getInstances(@Url url: String): List<Instances>
|
||||
|
||||
|
||||
|
||||
}
|
@ -125,4 +125,8 @@ class SearchFragment : Fragment() {
|
||||
requireActivity().window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
hideKeyboard()
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package com.github.libretube
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentValues.TAG
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
@ -15,67 +14,83 @@ import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.blankj.utilcode.util.UriUtils
|
||||
import com.github.libretube.obj.Subscribe
|
||||
import retrofit2.HttpException
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.*
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
|
||||
class Settings : PreferenceFragmentCompat() {
|
||||
val TAG = "Settings"
|
||||
companion object {
|
||||
lateinit var getContent: ActivityResultLauncher<String>
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
|
||||
|
||||
if (uri != null) {
|
||||
try{
|
||||
Log.d(TAG,UriUtils.uri2File(uri).toString())
|
||||
val file = UriUtils.uri2File(uri)
|
||||
var inputStream: InputStream? = null
|
||||
if (file.extension == "zip") {
|
||||
var zipfile = ZipFile(file)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
|
||||
var zipentry =
|
||||
zipfile.getEntry("Takeout/YouTube and YouTube Music/subscriptions/subscriptions.csv")
|
||||
// Open a specific media item using ParcelFileDescriptor.
|
||||
val resolver: ContentResolver =
|
||||
requireActivity()
|
||||
.contentResolver
|
||||
|
||||
inputStream = zipfile.getInputStream(zipentry)
|
||||
}else if(file.extension == "csv"){
|
||||
inputStream = file.inputStream()
|
||||
}
|
||||
val baos = ByteArrayOutputStream()
|
||||
|
||||
inputStream?.use { it.copyTo(baos) }
|
||||
|
||||
var subscriptions = baos.toByteArray().decodeToString()
|
||||
|
||||
var subscribedCount = 0
|
||||
|
||||
for (text in subscriptions.lines()) {
|
||||
if (text.take(24) != "Channel Id,Channel Url,C" && text.take(24).isNotEmpty()) {
|
||||
subscribe(text.take(24))
|
||||
subscribedCount++
|
||||
Log.d(TAG, "subscribed: " + text + " total: " + subscribedCount)
|
||||
// "rw" for read-and-write;
|
||||
// "rwt" for truncating or overwriting existing file contents.
|
||||
val readOnlyMode = "r"
|
||||
// uri - I have got from onActivityResult
|
||||
//uri = data.getData();
|
||||
val parcelFile = resolver.openFileDescriptor(uri, readOnlyMode)
|
||||
val fileReader = FileReader(parcelFile!!.fileDescriptor)
|
||||
val reader = BufferedReader(fileReader)
|
||||
var line: String?
|
||||
while (reader.readLine().also { line = it } != null) {
|
||||
Log.d(TAG,reader.readLine())
|
||||
}
|
||||
}
|
||||
reader.close()
|
||||
fileReader.close()
|
||||
}else{
|
||||
Log.d(TAG,UriUtils.uri2File(uri).toString())
|
||||
val file = UriUtils.uri2File(uri)
|
||||
var inputStream: InputStream? = null
|
||||
if (file.extension == "zip") {
|
||||
var zipfile = ZipFile(file)
|
||||
|
||||
Toast.makeText(
|
||||
context,
|
||||
"Subscribed to " + subscribedCount + " channels.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
var zipentry =
|
||||
zipfile.getEntry("Takeout/YouTube and YouTube Music/subscriptions/subscriptions.csv")
|
||||
|
||||
inputStream = zipfile.getInputStream(zipentry)
|
||||
}else if(file.extension == "csv"){
|
||||
inputStream = file.inputStream()
|
||||
}
|
||||
val baos = ByteArrayOutputStream()
|
||||
|
||||
inputStream?.use { it.copyTo(baos) }
|
||||
|
||||
var subscriptions = baos.toByteArray().decodeToString()
|
||||
var channels: MutableList<String> = emptyList<String>().toMutableList()
|
||||
var subscribedCount = 0
|
||||
for (text in subscriptions.lines().subList(1,subscriptions.lines().size)) {
|
||||
if (text.replace(" ","") != "") {
|
||||
val channel = text.split(",")[0]
|
||||
channels.add(channel)
|
||||
subscribedCount++
|
||||
Log.d(TAG, "subscribed: " + text + " total: " + subscribedCount)
|
||||
}
|
||||
}
|
||||
subscribe(channels)
|
||||
}
|
||||
}catch (e: Exception){
|
||||
Log.e(TAG,e.toString())
|
||||
Toast.makeText(
|
||||
context,
|
||||
R.string.error,
|
||||
@ -121,7 +136,9 @@ class Settings : PreferenceFragmentCompat() {
|
||||
//check StorageAccess
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
Log.d("myz", "" + Build.VERSION.SDK_INT)
|
||||
if (!Environment.isExternalStorageManager()) {
|
||||
if (ContextCompat.checkSelfPermission(this.requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
ActivityCompat.requestPermissions(
|
||||
this.requireActivity(), arrayOf(
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
@ -218,15 +235,12 @@ class Settings : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
|
||||
private fun subscribe(channel_id: String) {
|
||||
private fun subscribe(channels: List<String>) {
|
||||
fun run() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
val sharedPref = context?.getSharedPreferences("token", Context.MODE_PRIVATE)
|
||||
RetrofitInstance.api.subscribe(
|
||||
sharedPref?.getString("token", "")!!,
|
||||
Subscribe(channel_id)
|
||||
)
|
||||
RetrofitInstance.api.importSubscriptions(sharedPref?.getString("token", "")!!,channels)
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "IOException, you might not have internet connection")
|
||||
return@launchWhenCreated
|
||||
@ -234,9 +248,17 @@ class Settings : PreferenceFragmentCompat() {
|
||||
Log.e(TAG, "HttpException, unexpected response$e")
|
||||
return@launchWhenCreated
|
||||
}
|
||||
if(response.message == "ok"){
|
||||
Toast.makeText(
|
||||
context,
|
||||
R.string.importsuccess,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
run()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
<string name="region">Choose a region</string>
|
||||
<string name="login_register">Login/Register</string>
|
||||
<string name="please_login">Please Login or Register from the settings to show your Subscriptions!</string>
|
||||
<string name="importsuccess">Subscribed successfully!</string>
|
||||
<string name="subscribeIsEmpty">Subscribe to some channels first!</string>
|
||||
<string name="cannotDownload">Can\'t Download this stream!</string>
|
||||
<string name="dlcomplete">Download is completed!</string>
|
||||
|
@ -59,7 +59,7 @@
|
||||
app:key="grid"
|
||||
app:entries="@array/grid"
|
||||
app:entryValues="@array/grid"
|
||||
app:defaultValue=""
|
||||
app:defaultValue="@integer/grid_items"
|
||||
android:icon="@drawable/ic_column"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user