Skip to content

Commit

Permalink
Merge pull request #9 from Mygod/master
Browse files Browse the repository at this point in the history
sync
  • Loading branch information
acocalypso authored Jan 28, 2024
2 parents d83be32 + 7f42182 commit e156deb
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 59 deletions.
4 changes: 3 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ android {
extra["reactmap.githubReleases"] as String
} else "null")
resourceConfigurations.addAll(arrayOf("en-rUS", "pl"))
ndk.abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a"))
}

buildTypes {
Expand Down Expand Up @@ -65,9 +66,10 @@ dependencies {
implementation(libs.browser)
implementation(libs.core.ktx)
implementation(libs.firebase.analytics)
implementation(libs.firebase.crashlytics)
implementation(libs.firebase.crashlytics.ndk) // without Play console we need to use ndk to see native crashes
implementation(libs.fragment.ktx)
implementation(libs.hiddenapibypass)
implementation(libs.material)
implementation(libs.play.services.location)
implementation(libs.lifecycle.common)
implementation(libs.timber)
Expand Down
56 changes: 25 additions & 31 deletions app/src/main/java/be/mygod/reactmap/ConfigDialogFragment.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package be.mygod.reactmap

import android.Manifest
import android.app.AlertDialog
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Parcelable
import android.widget.ArrayAdapter
import android.widget.AutoCompleteTextView
import android.widget.LinearLayout
import android.widget.Switch
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.content.edit
import androidx.core.net.toUri
import be.mygod.reactmap.App.Companion.app
Expand All @@ -19,6 +18,7 @@ import be.mygod.reactmap.util.AlertDialogFragment
import be.mygod.reactmap.util.Empty
import be.mygod.reactmap.util.readableMessage
import be.mygod.reactmap.webkit.ReactMapHttpEngine
import com.google.android.material.materialswitch.MaterialSwitch
import kotlinx.parcelize.Parcelize

class ConfigDialogFragment : AlertDialogFragment<ConfigDialogFragment.Arg, Empty>() {
Expand All @@ -31,7 +31,7 @@ class ConfigDialogFragment : AlertDialogFragment<ConfigDialogFragment.Arg, Empty

private lateinit var historyUrl: Set<String?>
private lateinit var urlEdit: AutoCompleteTextView
private lateinit var followerSwitch: Switch
private lateinit var followerSwitch: MaterialSwitch

private val requestLocation = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
if (it.any { (_, v) -> v }) {
Expand All @@ -47,39 +47,33 @@ class ConfigDialogFragment : AlertDialogFragment<ConfigDialogFragment.Arg, Empty
}

override fun AlertDialog.Builder.prepare(listener: DialogInterface.OnClickListener) {
historyUrl = app.pref.getStringSet(KEY_HISTORY_URL, null) ?: setOf("https://${BuildConfig.DEFAULT_DOMAIN}")
val context = requireContext()
urlEdit = AutoCompleteTextView(context).apply {
isFocusedByDefault = true
setAdapter(ArrayAdapter(context, android.R.layout.select_dialog_item, historyUrl.toTypedArray()))
setText(app.activeUrl)
}
followerSwitch = Switch(context).apply {
text = context.getText(R.string.config_switch_webhook_follow_location)
isChecked = BackgroundLocationReceiver.enabled && (context.checkSelfPermission(
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) &&
context.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) ==
PackageManager.PERMISSION_GRANTED
setOnCheckedChangeListener { _, isChecked ->
if (isChecked) requestLocation.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION))
}
}
setView(LinearLayout(context).apply {
orientation = LinearLayout.VERTICAL
addView(urlEdit, LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
addView(followerSwitch, LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
})
setView(R.layout.dialog_config)
setTitle(R.string.config_dialog_title)
if (arg.welcome) setMessage(R.string.config_welcome)
setPositiveButton(android.R.string.ok, listener)
setNegativeButton(android.R.string.cancel, null)
}

override fun onCreateDialog(savedInstanceState: Bundle?) = super.onCreateDialog(savedInstanceState).apply {
create()
historyUrl = app.pref.getStringSet(KEY_HISTORY_URL, null) ?: setOf("https://${BuildConfig.DEFAULT_DOMAIN}")
val context = requireContext()
urlEdit = findViewById(android.R.id.edit)!!
urlEdit.setAdapter(ArrayAdapter(context, android.R.layout.select_dialog_item, historyUrl.toTypedArray()))
urlEdit.setText(app.activeUrl)
followerSwitch = findViewById(android.R.id.switch_widget)!!
followerSwitch.isChecked = BackgroundLocationReceiver.enabled && (context.checkSelfPermission(
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) &&
context.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) ==
PackageManager.PERMISSION_GRANTED
followerSwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) requestLocation.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION))
}
}

override val ret get() = try {
val uri = urlEdit.text!!.toString().toUri().let {
require("https".equals(it.scheme, true)) { getText(R.string.error_https_only) }
Expand Down
11 changes: 8 additions & 3 deletions app/src/main/java/be/mygod/reactmap/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package be.mygod.reactmap

import android.app.AlertDialog
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
Expand All @@ -11,10 +10,10 @@ import android.system.Os
import android.system.OsConstants
import android.view.WindowManager
import android.webkit.WebView
import android.widget.Switch
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.core.content.edit
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.commit
Expand All @@ -28,6 +27,7 @@ import be.mygod.reactmap.util.UnblockCentral
import be.mygod.reactmap.util.UpdateChecker
import be.mygod.reactmap.util.readableMessage
import be.mygod.reactmap.webkit.ReactMapFragment
import com.google.android.material.materialswitch.MaterialSwitch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -131,9 +131,14 @@ class MainActivity : FragmentActivity() {
ACTION_RESTART_GAME -> AlertDialog.Builder(this).apply {
setTitle(R.string.restart_game_dialog_title)
setMessage(R.string.restart_game_dialog_message)
val switch = Switch(this@MainActivity).apply {
val switch = MaterialSwitch(this@MainActivity).apply {
setText(R.string.pip_phone_enter_split)
isChecked = isInMultiWindowMode
val padding = context.obtainStyledAttributes(intArrayOf(
com.google.android.material.R.attr.dialogPreferredPadding)).use {
it.getDimensionPixelOffset(0, 0)
}
setPadding(padding, 0, padding, 0)
}
setView(switch)
setPositiveButton(R.string.restart_game_standard) { _, _ ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package be.mygod.reactmap.util

import android.app.Activity
import android.app.AlertDialog
import android.content.DialogInterface
import android.os.Bundle
import android.os.Parcelable
import androidx.appcompat.app.AlertDialog
import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.setFragmentResult
import androidx.fragment.app.setFragmentResultListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.parcelize.Parcelize

/**
Expand Down Expand Up @@ -54,7 +55,7 @@ abstract class AlertDialogFragment<Arg : Parcelable, Ret : Parcelable> :
fun key(resultKey: String = javaClass.name) = args().putString(KEY_RESULT, resultKey)

override fun onCreateDialog(savedInstanceState: Bundle?): AlertDialog =
AlertDialog.Builder(requireContext()).also { it.prepare(this) }.create()
MaterialAlertDialogBuilder(requireContext()).also { it.prepare(this) }.create()

override fun onClick(dialog: DialogInterface?, which: Int) {
setFragmentResult(resultKey ?: return, Bundle().apply {
Expand Down
32 changes: 28 additions & 4 deletions app/src/main/java/be/mygod/reactmap/webkit/ReactMapFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package be.mygod.reactmap.webkit
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.JsonWriter
import android.util.Log
Expand All @@ -13,13 +14,15 @@ import android.webkit.ConsoleMessage
import android.webkit.RenderProcessGoneDetail
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.net.toUri
import androidx.core.os.bundleOf
import androidx.core.view.WindowCompat
Expand All @@ -33,6 +36,7 @@ import be.mygod.reactmap.R
import be.mygod.reactmap.follower.BackgroundLocationReceiver
import be.mygod.reactmap.util.CreateDynamicDocument
import be.mygod.reactmap.util.findErrorStream
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.analytics.FirebaseAnalytics
import kotlinx.coroutines.launch
import org.json.JSONArray
Expand All @@ -50,10 +54,10 @@ import java.util.Locale
class ReactMapFragment @JvmOverloads constructor(private var overrideUri: Uri? = null) : Fragment() {
companion object {
private val filenameExtractor = "filename=(\"([^\"]+)\"|[^;]+)".toRegex(RegexOption.IGNORE_CASE)
private val vendorJsMatcher = "/vendor-[0-9a-f]{8}\\.js".toRegex()
private val vendorJsMatcher = "/vendor-[0-9a-z]{8}\\.js".toRegex(RegexOption.IGNORE_CASE)
private val flyToMatcher = "/@/([0-9.-]+)/([0-9.-]+)(?:/([0-9.-]+))?/?".toRegex()
private val mapHijacker = "(?<=[\\n\\r\\s,])this(?=.callInitHooks\\(\\)[,;][\\n\\r\\s]*this._zoomAnimated\\s*=)"
.toRegex()
.toPattern()
private val supportedHosts = setOf("discordapp.com", "discord.com", "telegram.org", "oauth.telegram.org")
}

Expand Down Expand Up @@ -180,6 +184,13 @@ class ReactMapFragment @JvmOverloads constructor(private var overrideUri: Uri? =
} else if (vendorJsMatcher.matchEntire(path) != null) handleVendorJs(request) else null
}

override fun onReceivedError(view: WebView?, request: WebResourceRequest, error: WebResourceError) {
if (!request.isForMainFrame) return
Snackbar.make(web, "${error.description} (${error.errorCode})", Snackbar.LENGTH_INDEFINITE).apply {
setAction(R.string.web_refresh) { web.reload() }
}.show()
}

override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail): Boolean {
if (detail.didCrash()) {
Timber.w(Exception("WebView crashed @ priority ${detail.rendererPriorityAtExit()}"))
Expand All @@ -205,7 +216,9 @@ class ReactMapFragment @JvmOverloads constructor(private var overrideUri: Uri? =
}
loadUrl(activeUrl)
}
return web
return CoordinatorLayout(activity).apply {
addView(web, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
}
}

private fun buildResponse(request: WebResourceRequest, transform: (Reader) -> String) = try {
Expand Down Expand Up @@ -266,7 +279,18 @@ class ReactMapFragment @JvmOverloads constructor(private var overrideUri: Uri? =
response
}
private fun handleVendorJs(request: WebResourceRequest) = buildResponse(request) { reader ->
mapHijacker.replace(reader.readText(), "(window._hijackedMap=this)")
val response = reader.readText()
val matcher = mapHijacker.matcher(response)
if (matcher.find()) (if (Build.VERSION.SDK_INT >= 34) StringBuilder().also {
matcher.appendReplacement(it, "(window._hijackedMap=this)")
matcher.appendTail(it)
} else StringBuffer().also {
matcher.appendReplacement(it, "(window._hijackedMap=this)")
matcher.appendTail(it)
}).toString() else {
Timber.w(Exception("vendor.js unmatched"))
response
}
}

override fun onDestroyView() {
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/res/layout/dialog_config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="?dialogPreferredPadding"
android:paddingEnd="?dialogPreferredPadding">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatAutoCompleteTextView
android:id="@android:id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:focusedByDefault="true"
android:inputType="textUri"
tools:text="https://www.reactmap.dev"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@android:id/switch_widget"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/config_switch_webhook_follow_location"
android:layout_marginTop="16dp"/>
</LinearLayout>
3 changes: 1 addition & 2 deletions app/src/main/res/layout/layout_main.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
4 changes: 0 additions & 4 deletions app/src/main/res/values-night/theme.xml

This file was deleted.

1 change: 1 addition & 0 deletions app/src/main/res/values-pl/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@
<string name="error_webhook_human_not_found">Użytkownik nieznaleziony - brak dostępu do powiadomień</string>

<string name="pip_phone_enter_split">Włącz podzielony ekran</string>
<string name="web_refresh">Odśwież</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
<string name="error_webhook_human_not_found">Human not found</string>

<string name="pip_phone_enter_split">Enter split screen</string>
<string name="web_refresh">Refresh</string>
</resources>
7 changes: 1 addition & 6 deletions app/src/main/res/values/theme.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<style
name="Theme.DeviceDefault.DayNight.NoActionBar"
parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
<item name="android:windowLightStatusBar">true</item>
</style>
<style name="Theme.ReactMap" parent="@style/Theme.DeviceDefault.DayNight.NoActionBar">
<style name="Theme.ReactMap" parent="@style/Theme.Material3.DynamicColors.DayNight">
<item name="android:windowSplashScreenAnimatedIcon" tools:targetApi="s">@mipmap/splash</item>
<item name="android:windowSplashscreenContent" tools:targetApi="o">@mipmap/splash</item>
</style>
Expand Down
14 changes: 8 additions & 6 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
[versions]
activity = "1.8.2"
agp = "8.3.0-beta01"
agp = "8.3.0-beta02"
androidx-test-ext-junit = "1.1.5"
browser = "1.8.0-beta01"
core = "1.12.0"
crashlytics = "2.9.9"
desugar = "2.0.4"
espresso-core = "3.5.1"
firebase = "32.7.0"
firebase = "32.7.1"
fragment = "1.6.2"
hiddenapibypass = "4.3"
junit = "4.13.2"
kotlin = "1.9.22"
lifecycle = "2.7.0-rc02"
lifecycle = "2.7.0"
google-services = "4.4.0"
play-services-location = "21.0.1"
material = "1.11.0"
play-services-location = "21.1.0"
timber = "5.0.1"
work = "2.9.0"
gradle-versions = "0.50.0"
gradle-versions = "0.51.0"

[libraries]
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
Expand All @@ -28,11 +29,12 @@ desugar = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics" }
firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase" }
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics" }
firebase-crashlytics-ndk = { group = "com.google.firebase", name = "firebase-crashlytics-ndk" }
fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragment" }
hiddenapibypass = { group = "org.lsposed.hiddenapibypass", name = "hiddenapibypass", version.ref = "hiddenapibypass" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
lifecycle-common = { group = "androidx.lifecycle", name = "lifecycle-common", version.ref = "lifecycle" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
play-services-location = { group = "com.google.android.gms", name = "play-services-location", version.ref = "play-services-location" }
timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" }
work = { group = "androidx.work", name = "work-runtime", version.ref = "work" }
Expand Down

0 comments on commit e156deb

Please sign in to comment.