diff --git a/app/build.gradle b/app/build.gradle
index f3d811c..7db9d48 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,10 +9,10 @@ android {
defaultConfig {
applicationId "com.nin0dev.vendroid"
- minSdk 21
+ minSdk 25
targetSdk 34
- versionCode 5
- versionName "1.2"
+ versionCode 7
+ versionName "1.4"
}
buildTypes {
@@ -37,6 +37,7 @@ dependencies {
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.activity:activity:1.9.1'
+ implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.android.volley:volley:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}
diff --git a/app/src/debug/res/xml/shortcuts.xml b/app/src/debug/res/xml/shortcuts.xml
new file mode 100644
index 0000000..7b9f82f
--- /dev/null
+++ b/app/src/debug/res/xml/shortcuts.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 871864a..def834c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,6 +14,11 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:targetApi="34">
+
@@ -27,6 +32,10 @@
android:exported="true"
android:launchMode="singleTask"
android:theme="@style/AppTheme">
+
+
@@ -50,4 +59,4 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/java/com/nin0dev/vendroid/HttpClient.kt b/app/src/main/java/com/nin0dev/vendroid/HttpClient.kt
index 570f245..301545c 100644
--- a/app/src/main/java/com/nin0dev/vendroid/HttpClient.kt
+++ b/app/src/main/java/com/nin0dev/vendroid/HttpClient.kt
@@ -25,7 +25,7 @@ object HttpClient {
val res = activity.resources
res.openRawResource(R.raw.vencord_mobile).use { `is` -> VencordMobileRuntime = readAsText(`is`) }
if (VencordRuntime != null) return
- if (sPrefs.getString("vencordLocation", Constants.JS_BUNDLE_URL) == Constants.JS_BUNDLE_URL || BuildConfig.DEBUG) { // user is debugging vencord or app, always redownload
+ if (sPrefs.getString("vencordLocation", Constants.JS_BUNDLE_URL) != Constants.JS_BUNDLE_URL || BuildConfig.DEBUG) { // user is debugging vencord or app, always redownload
Toast.makeText(activity, "Debugging app or Vencord, bundle will be redownloaded. Avoid using on limited networks", Toast.LENGTH_LONG).show()
vendroidFile.delete()
}
diff --git a/app/src/main/java/com/nin0dev/vendroid/MainActivity.kt b/app/src/main/java/com/nin0dev/vendroid/MainActivity.kt
index 7ef9160..b66c3f6 100644
--- a/app/src/main/java/com/nin0dev/vendroid/MainActivity.kt
+++ b/app/src/main/java/com/nin0dev/vendroid/MainActivity.kt
@@ -11,6 +11,7 @@ import android.os.Bundle
import android.os.StrictMode
import android.os.StrictMode.ThreadPolicy
import android.view.KeyEvent
+import android.view.View.VISIBLE
import android.view.WindowManager
import android.webkit.ValueCallback
import android.webkit.WebView
@@ -19,47 +20,60 @@ import com.android.volley.Request
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.gson.Gson
import com.nin0dev.vendroid.HttpClient.fetchVencord
import com.nin0dev.vendroid.Logger.e
+import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import pl.droidsonroids.gif.GifImageView
import java.io.IOException
+
+@Serializable
+data class UpdateData(val version: Int, val changelog: String)
+
class MainActivity : Activity() {
private var wvInitialized = false
private var wv: WebView? = null
@JvmField
var filePathCallback: ValueCallback?>? = null
+ @OptIn(ExperimentalSerializationApi::class)
fun checkUpdates(ignoreSetting: Boolean = false)
{
val sPrefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
if(sPrefs.getBoolean("checkVendroidUpdates", false) || ignoreSetting) {
val queue = Volley.newRequestQueue(this)
- val url = "https://raw.githubusercontent.com/VendroidEnhanced/UpdateTracker/main/vendroid"
+ val url = "https://vendroid.nin0.dev/api/updates"
val stringRequest = StringRequest(
- Request.Method.GET, url,
- { response ->
- if(Integer.parseInt(response.trim()) != BuildConfig.VERSION_CODE)
- {
- val madb = MaterialAlertDialogBuilder(this)
- madb.setTitle(getString(R.string.vendroid_update_available))
- madb.setMessage("To make sure that no unexpected bugs happen, it is recommended to update.")
- madb.setPositiveButton(getString(R.string.update), DialogInterface.OnClickListener { dialogInterface, i ->
- val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/VendroidEnhanced/Vendroid/releases/latest/download/app-release.apk"))
- startActivity(browserIntent)
- })
- madb.setNegativeButton(getString(R.string.later), DialogInterface.OnClickListener { _, _ -> })
- madb.show()
- }
- if(ignoreSetting && Integer.parseInt(response.trim()) == BuildConfig.VERSION_CODE) {
- showDiscordToast("No updates available", "MESSAGE")
- }
- },
- { error ->
- if (BuildConfig.DEBUG) {
- e("Network error during update check", error)
- }
- Toast.makeText(this, "Failed to check for updates", Toast.LENGTH_SHORT).show()
+ Request.Method.GET, url,
+ { response ->
+ val gson = Gson()
+ val updateData = gson.fromJson(response, UpdateData::class.java)
+ if(updateData.version != BuildConfig.VERSION_CODE)
+ {
+ val madb = MaterialAlertDialogBuilder(this)
+ madb.setTitle(getString(R.string.vendroid_update_available))
+ madb.setMessage("Changelog:\n" + updateData.changelog)
+ madb.setPositiveButton(getString(R.string.update), DialogInterface.OnClickListener { dialogInterface, i ->
+ val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/VendroidEnhanced/Vendroid/releases/latest/download/app-release.apk"))
+ startActivity(browserIntent)
+ })
+ madb.setNegativeButton(getString(R.string.later), DialogInterface.OnClickListener { _, _ -> })
+ madb.show()
}
+ if(ignoreSetting && updateData.version == BuildConfig.VERSION_CODE) {
+ showDiscordToast("No updates available", "MESSAGE")
+ }
+ },
+ { error ->
+ if (BuildConfig.DEBUG) {
+ e("Network error during update check", error)
+ }
+ Toast.makeText(this, "Failed to check for updates", Toast.LENGTH_SHORT).show()
+ }
)
stringRequest.setShouldCache(false);
queue.add(stringRequest)
@@ -75,9 +89,13 @@ class MainActivity : Activity() {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
window.navigationBarColor = Color.TRANSPARENT
val sPrefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
+ val editor = sPrefs.edit()
// https://developer.chrome.com/docs/devtools/remote-debugging/webviews/
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG)
setContentView(R.layout.activity_main)
+ if (sPrefs.getString("splash", "viggy") == "viggy") findViewById(R.id.viggy_gif).visibility = VISIBLE
+ else if (sPrefs.getString("splash", "viggy") == "shiggy") findViewById(R.id.shiggy_gif).visibility = VISIBLE
+ else if (sPrefs.getString("splash", "viggy") == "oneko") findViewById(R.id.oneko_gif).visibility = VISIBLE
wv = findViewById(R.id.webview)!!
explodeAndroid()
wv!!.setWebViewClient(VWebviewClient())
@@ -86,11 +104,18 @@ class MainActivity : Activity() {
s.javaScriptEnabled = true
s.domStorageEnabled = true
s.allowFileAccess = true
- wv?.addJavascriptInterface(VencordNative(this, wv!!), "VencordMobileNative")
- try {
- fetchVencord(this)
- } catch (ex: IOException) {
+ if(!sPrefs.getBoolean("safeMode", false)) {
+ wv?.addJavascriptInterface(VencordNative(this, wv!!), "VencordMobileNative")
+ try {
+ fetchVencord(this)
+ } catch (ex: IOException) {
+ }
+ }
+ else {
+ Toast.makeText(this, "Safe mode enabled, Vencord won't be loaded", Toast.LENGTH_SHORT).show()
+ editor.putBoolean("safeMode", false)
+ editor.apply()
}
val intent = intent
if (intent.action == Intent.ACTION_VIEW) {
@@ -117,36 +142,44 @@ class MainActivity : Activity() {
return super.onKeyDown(keyCode, event)
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent) {
- if (requestCode != FILECHOOSER_RESULTCODE || filePathCallback == null) return
- if (resultCode != RESULT_OK || intent == null) {
- filePathCallback!!.onReceiveValue(null)
- } else {
- var uris: Array?
- try {
- val clipData = intent.clipData
- if (clipData != null) { // multiple items
- uris = arrayOfNulls(clipData.itemCount)
- for (i in 0 until clipData.itemCount) {
- uris[i] = clipData.getItemAt(i).uri
+ override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
+ super.onActivityResult(requestCode, resultCode, intent)
+ try {
+ if(resultCode != RESULT_CANCELED) {
+ if (requestCode != FILECHOOSER_RESULTCODE || filePathCallback == null) return
+ if (resultCode != RESULT_OK || intent == null) {
+ filePathCallback!!.onReceiveValue(null)
+ } else {
+ var uris: Array?
+ try {
+ val clipData = intent.clipData
+ if (clipData != null) { // multiple items
+ uris = arrayOfNulls(clipData.itemCount)
+ for (i in 0 until clipData.itemCount) {
+ uris[i] = clipData.getItemAt(i).uri
+ }
+ } else { // single item
+ uris = arrayOf(intent.data)
+ }
+ } catch (ex: Exception) {
+ e("Error during file upload", ex)
+ uris = null
}
- } else { // single item
- uris = arrayOf(intent.data)
+ filePathCallback!!.onReceiveValue(uris)
}
- } catch (ex: Exception) {
- e("Error during file upload", ex)
- uris = null
+ filePathCallback = null
}
- filePathCallback!!.onReceiveValue(uris)
}
- filePathCallback = null
+ catch (ex: Exception) {
+ // it is well known that the best fix for the crash is to wrap the entire function in a try/catch block
+ }
}
private fun explodeAndroid() {
StrictMode.setThreadPolicy(
- ThreadPolicy.Builder() // trolley
- .permitNetwork()
- .build()
+ ThreadPolicy.Builder() // trolley
+ .permitNetwork()
+ .build()
)
}
diff --git a/app/src/main/java/com/nin0dev/vendroid/RecoveryActivity.kt b/app/src/main/java/com/nin0dev/vendroid/RecoveryActivity.kt
new file mode 100644
index 0000000..45bc602
--- /dev/null
+++ b/app/src/main/java/com/nin0dev/vendroid/RecoveryActivity.kt
@@ -0,0 +1,51 @@
+package com.nin0dev.vendroid
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.Color
+import android.os.Bundle
+import android.view.WindowManager
+import android.webkit.CookieManager
+import android.webkit.CookieSyncManager
+import android.webkit.WebView
+import android.widget.Button
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import com.google.android.material.card.MaterialCardView
+import com.google.android.material.snackbar.Snackbar
+
+class RecoveryActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
+ window.statusBarColor = Color.TRANSPARENT
+ window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
+ window.navigationBarColor = Color.TRANSPARENT
+
+ setContentView(R.layout.activity_recovery)
+
+ findViewById(R.id.start_normally).setOnClickListener {
+ finish()
+ startActivity(Intent(this, MainActivity::class.java))
+ }
+ findViewById(R.id.safe_mode).setOnClickListener {
+ val sPrefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
+ val e = sPrefs.edit()
+ e.putBoolean("safeMode", true)
+ e.apply()
+ finish()
+ startActivity(Intent(this, MainActivity::class.java))
+ }
+ findViewById(R.id.settings).setOnClickListener {
+ finish()
+ startActivity(Intent(this, SettingsActivity::class.java))
+ }
+
+ }
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/nin0dev/vendroid/SettingsActivity.kt b/app/src/main/java/com/nin0dev/vendroid/SettingsActivity.kt
index a6470e2..54a6e15 100644
--- a/app/src/main/java/com/nin0dev/vendroid/SettingsActivity.kt
+++ b/app/src/main/java/com/nin0dev/vendroid/SettingsActivity.kt
@@ -37,6 +37,11 @@ class SettingsActivity : AppCompatActivity() {
"ptb" -> findViewById(R.id.ptb).isChecked = true
"canary" -> findViewById(R.id.canary).isChecked = true
}
+ when (sPrefs.getString("splash", "viggy")) {
+ "viggy" -> findViewById(R.id.viggy).isChecked = true
+ "shiggy" -> findViewById(R.id.shiggy).isChecked = true
+ "oneko" -> findViewById(R.id.oneko).isChecked = true
+ }
if(sPrefs.getString("vencordLocation", "")?.isNotBlank() == true) {
findViewById(R.id.allow_custom_location).isChecked = true
val devbuildField = findViewById(R.id.custom_location)
@@ -71,6 +76,9 @@ class SettingsActivity : AppCompatActivity() {
if (findViewById(R.id.stable).isChecked) editor.putString("discordBranch", "stable")
if (findViewById(R.id.ptb).isChecked) editor.putString("discordBranch", "ptb")
if (findViewById(R.id.canary).isChecked) editor.putString("discordBranch", "canary")
+ if (findViewById(R.id.viggy).isChecked) editor.putString("splash", "viggy")
+ if (findViewById(R.id.shiggy).isChecked) editor.putString("splash", "shiggy")
+ if (findViewById(R.id.oneko).isChecked) editor.putString("splash", "oneko")
if (findViewById(R.id.allow_custom_location).isChecked && findViewById(R.id.custom_location).text.isNotBlank()) editor.putString("vencordLocation", findViewById(R.id.custom_location).text.toString())
editor.apply()
diff --git a/app/src/main/java/com/nin0dev/vendroid/VWebviewClient.kt b/app/src/main/java/com/nin0dev/vendroid/VWebviewClient.kt
index 7dc8566..999e489 100644
--- a/app/src/main/java/com/nin0dev/vendroid/VWebviewClient.kt
+++ b/app/src/main/java/com/nin0dev/vendroid/VWebviewClient.kt
@@ -8,9 +8,12 @@ import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
+import android.widget.Toast
import androidx.annotation.RequiresApi
import com.nin0dev.vendroid.Logger.e
+import java.io.File
import java.io.IOException
+import java.lang.Exception
import java.net.HttpURLConnection
import java.net.URL
@@ -26,8 +29,13 @@ class VWebviewClient : WebViewClient() {
}
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
- view.evaluateJavascript(HttpClient.VencordRuntime!!, null)
- view.evaluateJavascript(HttpClient.VencordMobileRuntime!!, null)
+ try {
+ HttpClient.VencordRuntime?.let { view.evaluateJavascript(it, null) }
+ HttpClient.VencordMobileRuntime?.let { view.evaluateJavascript(it, null) }
+ }
+ catch (e: Exception) {
+ Toast.makeText(view.context, "Couldn't load Vencord, try restarting the app.", Toast.LENGTH_LONG).show()
+ }
}
override fun onPageFinished(view: WebView, url: String) {
diff --git a/app/src/main/java/com/nin0dev/vendroid/WelcomeActivity.kt b/app/src/main/java/com/nin0dev/vendroid/WelcomeActivity.kt
index 950772b..5cca6af 100644
--- a/app/src/main/java/com/nin0dev/vendroid/WelcomeActivity.kt
+++ b/app/src/main/java/com/nin0dev/vendroid/WelcomeActivity.kt
@@ -27,25 +27,6 @@ class WelcomeActivity : AppCompatActivity() {
setContentView(R.layout.activity_welcome)
- val devbuildCheckbox = findViewById(R.id.allow_custom_location)
- devbuildCheckbox.setOnClickListener {
- if (devbuildCheckbox.isChecked) {
- MaterialAlertDialogBuilder(this)
- .setTitle("Warning")
- .setMessage("If you set a custom location, you will be loading and injecting Vencord from a different location. This feature is meant for developers ONLY. Never edit this setting if someone else asked you to, or if you don't know what you're doing! If you do set a custom location, you will not be able to ask for support in the Vencord support channel or in this project's issues. Are you sure you want to continue?")
- .setNegativeButton(resources.getString(R.string.no)) { _, _ ->
- devbuildCheckbox.isChecked = false
- }
- .setPositiveButton(resources.getString(R.string.yes)) { _, _ ->
- findViewById(R.id.custom_location).visibility = VISIBLE
- }
- .show()
- }
- else {
- findViewById(R.id.custom_location).visibility = GONE
- }
- }
-
findViewById(R.id.save_settings).setOnClickListener {
val sPrefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
val editor = sPrefs.edit()
@@ -54,7 +35,6 @@ class WelcomeActivity : AppCompatActivity() {
if (findViewById(R.id.stable).isChecked) editor.putString("discordBranch", "stable")
if (findViewById(R.id.ptb).isChecked) editor.putString("discordBranch", "ptb")
if (findViewById(R.id.canary).isChecked) editor.putString("discordBranch", "canary")
- if (findViewById(R.id.allow_custom_location).isChecked && findViewById(R.id.custom_location).text.isNotBlank()) editor.putString("vencordLocation", findViewById(R.id.custom_location).text.toString())
editor.apply()
finish()
diff --git a/app/src/main/res/drawable/oneko.gif b/app/src/main/res/drawable/oneko.gif
new file mode 100644
index 0000000..5fb66d1
Binary files /dev/null and b/app/src/main/res/drawable/oneko.gif differ
diff --git a/app/src/main/res/drawable/reset.xml b/app/src/main/res/drawable/reset.xml
new file mode 100644
index 0000000..3016471
--- /dev/null
+++ b/app/src/main/res/drawable/reset.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/shiggy.gif b/app/src/main/res/drawable/shiggy.gif
new file mode 100644
index 0000000..05e628d
Binary files /dev/null and b/app/src/main/res/drawable/shiggy.gif differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 3172543..217b0ec 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -13,11 +13,31 @@
android:orientation="vertical">
+ android:src="@drawable/viggy"
+ android:visibility="gone" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index 38f6cd2..0863bb1 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -40,6 +40,38 @@
android:enabled="false"
android:text="@string/autocheck_vencord" />
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+ android:layout_height="?attr/actionBarSize"
+ android:elevation="0dp"
+ app:layout_collapseMode="pin"
+ app:title="Vendroid Settings"
+ app:titleTextColor="@color/text" />
diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml
index 3905fe6..9187b9a 100644
--- a/app/src/main/res/layout/activity_welcome.xml
+++ b/app/src/main/res/layout/activity_welcome.xml
@@ -71,34 +71,6 @@
android:text="@string/canary" />
-
-
-
-
-
-
-
-
-
-
@@ -110,22 +82,13 @@
android:layout_height="wrap_content"
android:layout_width="match_parent">
-
-
-
-
-
+ android:layout_height="?attr/actionBarSize"
+ android:elevation="0dp"
+ app:layout_collapseMode="pin"
+ app:title="Welcome to Vendroid"
+ app:titleTextColor="@color/text" />
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index db3eb93..9e51c1b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -15,7 +15,19 @@
Custom location URL
No
Yes
- Vendroid update available
+ VendroidEnhanced update available
Update
Later
+ Viggy, by shoritsu
+ Shiggy, by naga_U
+ Oneko
+ Splash screen
+ Recovery mode
+ Cleared all cookies
+ Start normally
+ Don\'t do anything and start the app normally.
+ Safe mode
+ Use this option to launch the app and load Discord, but without Vencord or any VendroidEnhanced tweak injected.
+ Open settings
+ Configure VendroidEnhanced.
\ No newline at end of file
diff --git a/app/src/main/res/xml/shortcuts.xml b/app/src/main/res/xml/shortcuts.xml
new file mode 100644
index 0000000..a69e9ae
--- /dev/null
+++ b/app/src/main/res/xml/shortcuts.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file