diff --git a/.gitignore b/.gitignore index 69ad2a2..eebe7b6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ /yggdrasil/yggdrasil-sources.jar /app/src/main/assets/yggdrasil-0.3.8-linux-arm64 /app/src/main/assets/yggdrasil-0.3.8-linux-armhf +/.idea/ diff --git a/app/build.gradle b/app/build.gradle index 169cdac..21ed139 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "io.github.chronosx88.yggdrasil" minSdkVersion 15 targetSdkVersion 30 - versionCode 5 - versionName "1.5" + versionCode 6 + versionName "1.6" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" setProperty("archivesBaseName", project.getParent().name+"-"+versionName) } @@ -42,6 +42,10 @@ android { // but continue the build even when errors are found: abortOnError false } + packagingOptions { + exclude 'META-INF/LICENSE' + exclude 'META-INF/NOTICE' + } } task ndkBuild(type: Exec) { @@ -59,16 +63,18 @@ dependencies { implementation project(path: ':yggdrasil') implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation "androidx.preference:preference-ktx:1.1.1" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7' - implementation 'com.google.android.material:material:1.3.0-alpha02' + implementation 'com.google.android.material:material:1.3.0-alpha04' implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.hbb20:ccp:2.4.0' + implementation 'com.vincentbrison.openlibraries.android:dualcache:3.1.1' + implementation 'com.vincentbrison.openlibraries.android:dualcache-jsonserializer:3.1.1' - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.1' androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } \ No newline at end of file diff --git a/app/src/main/java/io/github/chronosx88/yggdrasil/PeerListActivity.kt b/app/src/main/java/io/github/chronosx88/yggdrasil/PeerListActivity.kt index 37f3fac..deab151 100644 --- a/app/src/main/java/io/github/chronosx88/yggdrasil/PeerListActivity.kt +++ b/app/src/main/java/io/github/chronosx88/yggdrasil/PeerListActivity.kt @@ -15,9 +15,13 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.hbb20.CCPCountry +import com.vincentbrison.openlibraries.android.dualcache.Builder +import com.vincentbrison.openlibraries.android.dualcache.SizeOf +import com.vincentbrison.openlibraries.android.dualcache.JsonSerializer import io.github.chronosx88.yggdrasil.models.PeerInfo import io.github.chronosx88.yggdrasil.models.Status import io.github.chronosx88.yggdrasil.models.config.DropDownAdapter +import io.github.chronosx88.yggdrasil.models.config.Peer import io.github.chronosx88.yggdrasil.models.config.SelectPeerInfoListAdapter import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringList2PeerInfoSet import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.ping @@ -39,6 +43,12 @@ class PeerListActivity : AppCompatActivity() { companion object { const val PEER_LIST_URL = "https://publicpeers.neilalexander.dev/publicnodes.json" + const val CACHE_NAME = "PEER_LIST_CACHE" + const val ONLINE_PEERINFO_LIST = "ONLINE_PEERINFO_LIST" + const val OFFLINE_PEERINFO_LIST = "OFFLINE_PEERINFO_LIST" + const val TEST_APP_VERSION = BuildConfig.VERSION_CODE; + const val RAM_MAX_SIZE = 100000 + const val DISK_MAX_SIZE = 100000 } fun downloadJson(link: String): String { @@ -51,8 +61,6 @@ class PeerListActivity : AppCompatActivity() { } } - var isLoading = true; - var popup: PopupWindow? = null var adapter: DropDownAdapter? = null @@ -67,6 +75,13 @@ class PeerListActivity : AppCompatActivity() { var peerList = findViewById(R.id.peerList) var adapter = SelectPeerInfoListAdapter(this, arrayListOf(), mutableSetOf()) peerList.adapter = adapter + var peerInfoListCache = Builder>(CACHE_NAME, TEST_APP_VERSION) + .enableLog() + .useReferenceInRam(RAM_MAX_SIZE, SizeOfPeerList()) + .useSerializerInDisk( + DISK_MAX_SIZE, true, + JsonSerializer(ArrayList().javaClass), baseContext + ).build(); GlobalScope.launch { try { @@ -94,7 +109,12 @@ class PeerListActivity : AppCompatActivity() { try { var address = InetAddress.getByName(url.host) var peerInfo = - PeerInfo(url.scheme, address, url.port, ccp.nameCode) + PeerInfo( + url.scheme, + address, + url.port, + ccp.nameCode + ) var ping = ping(address, url.port) peerInfo.ping = ping if(cp.contains(peerInfo)){ @@ -114,14 +134,38 @@ class PeerListActivity : AppCompatActivity() { } } } - } catch(e: FileNotFoundException){ + var allPeersList = adapter.getAllPeers() + var cachePeerInfoList = mutableListOf() + for(p in allPeersList){ + if(p.ping0){ + peerInfoListCache.put(ONLINE_PEERINFO_LIST, cachePeerInfoList.toList()) + } + } catch (e: FileNotFoundException){ e.printStackTrace() + var onlinePeerInfoList = peerInfoListCache.get(ONLINE_PEERINFO_LIST) + if(onlinePeerInfoList!=null) { + for (peerInfo in onlinePeerInfoList) { + var ping = ping(peerInfo.address, peerInfo.port) + peerInfo.ping = ping + if (cp.contains(peerInfo)) { + continue + } + withContext(Dispatchers.Main) { + adapter.addItem(peerInfo) + if (adapter.count % 5 == 0) { + adapter.sort() + } + } + } + } } var currentPeers = ArrayList(cp.sortedWith(compareBy { it.ping })) withContext(Dispatchers.Main) { adapter.addAll(0, currentPeers) - isLoading = false - adapter.setLoading(isLoading) } } catch (e: Throwable){ e.printStackTrace() @@ -150,7 +194,11 @@ class PeerListActivity : AppCompatActivity() { schemaInput.setOnClickListener { v-> onClickSchemaList(v) } - getPopupWindow(R.layout.spinner_item, resources.getStringArray(R.array.schemas), schemaInput); + getPopupWindow( + R.layout.spinner_item, + resources.getStringArray(R.array.schemas), + schemaInput + ); view.findViewById(R.id.ccp).setCountryForNameCode(countryCode) val ab: AlertDialog.Builder = AlertDialog.Builder(this) ab.setCancelable(true).setView(view) @@ -180,7 +228,7 @@ class PeerListActivity : AppCompatActivity() { try { var ping = ping(pi.address, pi.port) pi.ping = ping - } catch(e: Throwable){ + } catch (e: Throwable){ pi.ping = Int.MAX_VALUE } withContext(Dispatchers.Main) { @@ -235,9 +283,6 @@ class PeerListActivity : AppCompatActivity() { val saveButton = item .actionView.findViewById