Skip to content

Commit

Permalink
Replace thread with CoroutineScope
Browse files Browse the repository at this point in the history
  • Loading branch information
SaeedDev94 committed Jan 16, 2025
1 parent 7b86912 commit 826d65e
Show file tree
Hide file tree
Showing 15 changed files with 561 additions and 201 deletions.
2 changes: 2 additions & 0 deletions app/src/main/java/io/github/saeeddev94/xray/Xray.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package io.github.saeeddev94.xray
import android.app.Application
import io.github.saeeddev94.xray.database.XrayDatabase
import io.github.saeeddev94.xray.repository.LinkRepository
import io.github.saeeddev94.xray.repository.ProfileRepository

class Xray : Application() {

private val xrayDatabase by lazy { XrayDatabase.ref(this) }
val linkRepository by lazy { LinkRepository(xrayDatabase.linkDao()) }
val profileRepository by lazy { ProfileRepository(xrayDatabase.profileDao()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ import android.widget.ProgressBar
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import io.github.saeeddev94.xray.R
import io.github.saeeddev94.xray.Settings
import io.github.saeeddev94.xray.databinding.ActivityAssetsBinding
import io.github.saeeddev94.xray.helper.DownloadHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.lang.Exception
Expand Down Expand Up @@ -92,47 +96,45 @@ class AssetsActivity : AppCompatActivity() {
progressBar.progress = 0

downloading = true
Thread {
DownloadHelper(url, file, object : DownloadHelper.DownloadListener {
override fun onProgress(progress: Int) {
runOnUiThread { progressBar.progress = progress }
}
DownloadHelper(lifecycleScope, url, file, object : DownloadHelper.DownloadListener {
override fun onProgress(progress: Int) {
progressBar.progress = progress
}

override fun onError(exception: Exception) {
runOnUiThread {
downloading = false
Toast.makeText(applicationContext, exception.message, Toast.LENGTH_SHORT).show()
setAssetStatus()
}
}
override fun onError(exception: Exception) {
downloading = false
Toast.makeText(applicationContext, exception.message, Toast.LENGTH_SHORT).show()
setAssetStatus()
}

override fun onComplete() {
runOnUiThread {
downloading = false
setAssetStatus()
}
}
}).start()
}.start()
override fun onComplete() {
downloading = false
setAssetStatus()
}
}).start()
}

private fun writeToFile(uri: Uri?, file: File) {
if (uri == null) return
Thread {
lifecycleScope.launch {
contentResolver.openInputStream(uri).use { input ->
FileOutputStream(file).use { output ->
input?.copyTo(output)
}
}
runOnUiThread { setAssetStatus() }
}.start()
withContext(Dispatchers.Main) {
setAssetStatus()
}
}
}

private fun delete(file: File) {
Thread {
lifecycleScope.launch {
file.delete()
runOnUiThread { setAssetStatus() }
}.start()
withContext(Dispatchers.Main) {
setAssetStatus()
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import android.view.View
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.github.saeeddev94.xray.R
import io.github.saeeddev94.xray.Settings
import io.github.saeeddev94.xray.adapter.ExcludeAdapter
import io.github.saeeddev94.xray.databinding.ActivityExcludeBinding
import io.github.saeeddev94.xray.dto.AppList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class ExcludeActivity : AppCompatActivity() {

Expand Down Expand Up @@ -93,7 +97,7 @@ class ExcludeActivity : AppCompatActivity() {
}

private fun getApps() {
Thread {
lifecycleScope.launch {
val selected = ArrayList<AppList>()
val unselected = ArrayList<AppList>()
packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS).forEach {
Expand All @@ -106,7 +110,7 @@ class ExcludeActivity : AppCompatActivity() {
val isSelected = Settings.excludedApps.contains(packageName)
if (isSelected) selected.add(app) else unselected.add(app)
}
runOnUiThread {
withContext(Dispatchers.Main) {
apps = ArrayList(selected + unselected)
filtered = apps.toMutableList()
excludedApps = Settings.excludedApps.split("\n").toMutableSet()
Expand All @@ -115,7 +119,7 @@ class ExcludeActivity : AppCompatActivity() {
appsList.adapter = excludeAdapter
appsList.layoutManager = LinearLayoutManager(applicationContext)
}
}.start()
}
}

private fun saveExcludedApps() {
Expand Down
130 changes: 126 additions & 4 deletions app/src/main/java/io/github/saeeddev94/xray/activity/LinksActivity.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package io.github.saeeddev94.xray.activity

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
Expand All @@ -20,19 +22,28 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.materialswitch.MaterialSwitch
import com.google.android.material.radiobutton.MaterialRadioButton
import io.github.saeeddev94.xray.R
import io.github.saeeddev94.xray.Settings
import io.github.saeeddev94.xray.adapter.LinkAdapter
import io.github.saeeddev94.xray.database.Link
import io.github.saeeddev94.xray.database.Profile
import io.github.saeeddev94.xray.databinding.ActivityLinksBinding
import io.github.saeeddev94.xray.helper.ConfigHelper
import io.github.saeeddev94.xray.helper.HttpHelper
import io.github.saeeddev94.xray.helper.LinkHelper
import io.github.saeeddev94.xray.viewmodel.LinkViewModel
import io.github.saeeddev94.xray.viewmodel.ProfileViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.net.URI
import kotlin.reflect.cast

class LinksActivity : AppCompatActivity() {

private val linkViewModel: LinkViewModel by viewModels()
private val profileViewModel: ProfileViewModel by viewModels()
private val adapter by lazy { LinkAdapter() }
private val linksRecyclerView by lazy { findViewById<RecyclerView>(R.id.linksRecyclerView) }
private var links: List<Link> = listOf()
Expand All @@ -52,10 +63,8 @@ class LinksActivity : AppCompatActivity() {
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
linkViewModel.links.collectLatest {
withContext(Dispatchers.Main) {
links = it
adapter.submitList(it)
}
links = it
adapter.submitList(it)
}
}
}
Expand All @@ -76,6 +85,112 @@ class LinksActivity : AppCompatActivity() {
}

private fun refreshLinks() {
Toast.makeText(applicationContext, "Getting update", Toast.LENGTH_SHORT).show()
lifecycleScope.launch {
val profiles = profileViewModel.activeLinks()
links.filter { it.isActive }.forEach { link ->
runCatching {
val content = HttpHelper.get(link.address).trim()
val newProfiles = if (link.type == Link.Type.Json) {
jsonProfile(link, content)
} else {
subscriptionProfiles(link, content)
}
if (newProfiles.isNotEmpty()) {
val linkProfiles = profiles.filter { it.linkId == link.id }
manageProfiles(link, linkProfiles, newProfiles)
}
}
}
withContext(Dispatchers.Main) {
setResult(RESULT_OK)
Toast.makeText(applicationContext, "Done", Toast.LENGTH_SHORT).show()
}
}
}

private suspend fun jsonProfile(link: Link, value: String): List<Profile> {
val list = arrayListOf<Profile>()
runCatching {
val error = ConfigHelper.isValid(applicationContext, value)
if (error.isEmpty()) {
val name = LinkHelper.remark(URI(link.address))
val config = JSONObject(value).toString(2)
val profile = Profile()
profile.linkId = link.id
profile.name = name
profile.config = config
list.add(profile)
}
}
return list.toList()
}

private suspend fun subscriptionProfiles(link: Link, value: String): List<Profile> {
return runCatching {
val decoded = LinkHelper.decodeBase64(value).trim()
decoded.split("\n")
.reversed()
.map { LinkHelper(it) }
.filter { it.isValid() }
.map { linkHelper ->
val profile = Profile()
profile.linkId = link.id
profile.config = linkHelper.json()
profile.name = linkHelper.remark()
profile
}.filter {
val error = ConfigHelper.isValid(applicationContext, it.config)
error.isEmpty()
}
}.getOrNull() ?: listOf()
}

private suspend fun manageProfiles(link: Link, linkProfiles: List<Profile>, newProfiles: List<Profile>) {
if (newProfiles.size >= linkProfiles.size) {
newProfiles.forEachIndexed { index, newProfile ->
if (index >= linkProfiles.size) {
newProfile.linkId = link.id
insertProfile(newProfile)
} else {
val linkProfile = linkProfiles[index]
updateProfile(linkProfile, newProfile)
}
}
return
}
linkProfiles.forEachIndexed { index, linkProfile ->
if (index >= newProfiles.size) {
deleteProfile(linkProfile)
} else {
val newProfile = newProfiles[index]
updateProfile(linkProfile, newProfile)
}
}
}

private suspend fun insertProfile(newProfile: Profile) {
profileViewModel.insert(newProfile)
profileViewModel.fixInsertIndex()
}

private suspend fun updateProfile(linkProfile: Profile, newProfile: Profile) {
Log.e("INJA", "updateProfile: ${linkProfile.name}, ${newProfile.name}")
linkProfile.name = newProfile.name
linkProfile.config = newProfile.config
profileViewModel.update(linkProfile)
}

private suspend fun deleteProfile(linkProfile: Profile) {
profileViewModel.delete(linkProfile)
profileViewModel.fixDeleteIndex(linkProfile.index)
withContext(Dispatchers.Main) {
val selectedProfile = Settings.selectedProfile
if (selectedProfile == linkProfile.id) {
Settings.selectedProfile = 0L
Settings.save(applicationContext)
}
}
}

private fun openLink(index: Int = -1, link: Link = Link()) {
Expand Down Expand Up @@ -137,7 +252,14 @@ class LinksActivity : AppCompatActivity() {

private fun deleteLink(link: Link) {
lifecycleScope.launch {
profileViewModel.linkProfiles(link.id)
.forEach { linkProfile ->
deleteProfile(linkProfile)
}
linkViewModel.delete(link)
withContext(Dispatchers.Main) {
setResult(RESULT_OK)
}
}
}
}
Loading

0 comments on commit 826d65e

Please sign in to comment.