mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-21 08:19:33 +00:00
Compare commits
16
Commits
latency-test
...
1.9.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1658072b1a | ||
|
|
b6e88b20cb | ||
|
|
f4af50b2cb | ||
|
|
00c47f4c70 | ||
|
|
11649a236a | ||
|
|
ff712196cc | ||
|
|
6c57f3f261 | ||
|
|
626f8d00d1 | ||
|
|
45ecc71749 | ||
|
|
3d60bd3d53 | ||
|
|
e40af4c49b | ||
|
|
e0a31694af | ||
|
|
c8994c2484 | ||
|
|
35c8428f08 | ||
|
|
bca761f26a | ||
|
|
79c06ca629 |
No files matched your search
+9
-10
@@ -1,5 +1,4 @@
|
|||||||
import groovy.json.JsonSlurper
|
import groovy.json.JsonSlurper
|
||||||
import java.io.IOException
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
@@ -16,7 +15,7 @@ plugins {
|
|||||||
id("org.jetbrains.kotlin.plugin.compose")
|
id("org.jetbrains.kotlin.plugin.compose")
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentGeodeVersion = "5.10.1"
|
val currentGeodeVersion = "5.11.2"
|
||||||
|
|
||||||
abstract class DownloadVersionMetadataTask : DefaultTask() {
|
abstract class DownloadVersionMetadataTask : DefaultTask() {
|
||||||
@get:Input
|
@get:Input
|
||||||
@@ -248,9 +247,9 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.geode.launcher"
|
applicationId = "com.geode.launcher"
|
||||||
minSdk = 23
|
minSdk = 23
|
||||||
targetSdk = 36
|
targetSdk = 37
|
||||||
versionCode = 30
|
versionCode = 31
|
||||||
versionName = "1.8.0"
|
versionName = "1.9.0"
|
||||||
|
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
@@ -331,7 +330,7 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace = "com.geode.launcher"
|
namespace = "com.geode.launcher"
|
||||||
ndkVersion = "29.0.14206865"
|
ndkVersion = "30.0.16248370"
|
||||||
}
|
}
|
||||||
|
|
||||||
androidComponents {
|
androidComponents {
|
||||||
@@ -348,8 +347,8 @@ androidComponents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation (platform("androidx.compose:compose-bom:2026.08.00"))
|
implementation (platform("androidx.compose:compose-bom:2026.09.00"))
|
||||||
implementation ("androidx.core:core-ktx:1.19.0")
|
implementation ("androidx.core:core-ktx:1.19.1")
|
||||||
implementation ("androidx.compose.ui:ui")
|
implementation ("androidx.compose.ui:ui")
|
||||||
implementation ("androidx.compose.material3:material3")
|
implementation ("androidx.compose.material3:material3")
|
||||||
implementation ("androidx.compose.ui:ui-tooling-preview")
|
implementation ("androidx.compose.ui:ui-tooling-preview")
|
||||||
@@ -368,8 +367,8 @@ dependencies {
|
|||||||
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.11.0")
|
implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.11.0")
|
||||||
implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
|
implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
|
||||||
|
|
||||||
implementation ("com.mikepenz:multiplatform-markdown-renderer-android:0.45.0")
|
implementation ("com.mikepenz:multiplatform-markdown-renderer-android:0.46.0")
|
||||||
implementation ("com.mikepenz:multiplatform-markdown-renderer-m3:0.45.0")
|
implementation ("com.mikepenz:multiplatform-markdown-renderer-m3:0.46.0")
|
||||||
implementation ("androidx.browser:browser:1.10.0")
|
implementation ("androidx.browser:browser:1.10.0")
|
||||||
debugImplementation ("androidx.compose.ui:ui-tooling")
|
debugImplementation ("androidx.compose.ui:ui-tooling")
|
||||||
coreLibraryDesugaring ("com.android.tools:desugar_jdk_libs:2.1.5")
|
coreLibraryDesugaring ("com.android.tools:desugar_jdk_libs:2.1.5")
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".GeometryDashActivity"
|
android:name=".GeometryDashActivity"
|
||||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard"
|
android:configChanges="fontScale|layoutDirection|density|smallestScreenSize|screenSize|uiMode|screenLayout|orientation|navigation|keyboardHidden|keyboard|locale"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="landscape"
|
||||||
@@ -233,6 +233,26 @@
|
|||||||
<data android:scheme="geode-launcher" android:host="main" />
|
<data android:scheme="geode-launcher" android:host="main" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
|
<activity-alias
|
||||||
|
android:name=".MainActivityGreen"
|
||||||
|
android:enabled="false"
|
||||||
|
android:exported="true"
|
||||||
|
android:icon="@mipmap/ic_launcher_green"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:targetActivity=".MainActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="geode-launcher" android:host="main" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity-alias>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".UserDirectoryProvider"
|
android:name=".UserDirectoryProvider"
|
||||||
|
|||||||
@@ -2,33 +2,106 @@ package com.customRobTop
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.provider.DocumentsContract
|
||||||
|
import android.provider.OpenableColumns
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import com.customRobTop.contracts.ImportFileActivityContract
|
||||||
|
import com.customRobTop.contracts.ShareFileActivityContract
|
||||||
import com.geode.launcher.R
|
import com.geode.launcher.R
|
||||||
|
import com.geode.launcher.utils.DownloadUtils
|
||||||
|
import com.geode.launcher.utils.LaunchUtils
|
||||||
|
import org.cocos2dx.lib.Cocos2dxGLSurfaceView
|
||||||
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.closeIMEKeyboard
|
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.closeIMEKeyboard
|
||||||
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.openIMEKeyboard
|
import org.cocos2dx.lib.Cocos2dxGLSurfaceView.Companion.openIMEKeyboard
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.OutputStream
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
|
|
||||||
@Suppress("unused", "UNUSED_PARAMETER")
|
@Suppress("unused", "UNUSED_PARAMETER")
|
||||||
object BaseRobTopActivity {
|
object BaseRobTopActivity {
|
||||||
|
const val KEYBOARD_INPUT_MULTILINE = 1
|
||||||
|
const val KEYBOARD_INPUT_NUMERIC = 4
|
||||||
|
const val KEYBOARD_INPUT_PASSWORD = 2
|
||||||
|
const val LEVEL_EXTENSION: String = ".gdlvl"
|
||||||
|
|
||||||
private var isLoaded = false
|
private var isLoaded = false
|
||||||
var blockBackButton = false
|
var blockBackButton = false
|
||||||
private var keyboardActive = false
|
private var keyboardActive = false
|
||||||
|
var curKeyboardInputFlags = 0
|
||||||
|
|
||||||
var isPaused = false
|
var isPaused = false
|
||||||
|
|
||||||
lateinit var me: WeakReference<Activity>
|
lateinit var me: WeakReference<Activity>
|
||||||
private var shouldResumeSound = true
|
private var shouldResumeSound = true
|
||||||
|
|
||||||
fun setCurrentActivity(currentActivity: Activity) {
|
private var pendingExportPaths = emptyList<String>()
|
||||||
|
|
||||||
|
private lateinit var importFileActivityContract: ActivityResultLauncher<Unit>
|
||||||
|
private lateinit var shareFileActivityContract: ActivityResultLauncher<String>
|
||||||
|
private lateinit var shareFolderActivityContract: ActivityResultLauncher<Uri?>
|
||||||
|
|
||||||
|
fun setCurrentActivity(currentActivity: AppCompatActivity) {
|
||||||
me = WeakReference(currentActivity)
|
me = WeakReference(currentActivity)
|
||||||
|
|
||||||
|
importFileActivityContract = currentActivity.registerForActivityResult(ImportFileActivityContract()) { uris ->
|
||||||
|
val filePaths = copyPickedFiles(uris)
|
||||||
|
|
||||||
|
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.filesPicked(filePaths.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shareFileActivityContract = currentActivity.registerForActivityResult(ShareFileActivityContract()) { uri ->
|
||||||
|
val currentlyPending = pendingExportPaths
|
||||||
|
pendingExportPaths = emptyList()
|
||||||
|
|
||||||
|
val exportPath = currentlyPending.firstOrNull()
|
||||||
|
if (exportPath == null || uri == null) {
|
||||||
|
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.fileShareFinished(false)
|
||||||
|
}
|
||||||
|
return@registerForActivityResult
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = saveToDocument(exportPath, uri)
|
||||||
|
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.fileShareFinished(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shareFolderActivityContract = currentActivity.registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
|
||||||
|
val currentlyPending = pendingExportPaths
|
||||||
|
pendingExportPaths = emptyList()
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.fileShareFinished(false)
|
||||||
|
}
|
||||||
|
return@registerForActivityResult
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = saveToFolder(currentlyPending, uri) > 0
|
||||||
|
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.fileShareFinished(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("HardwareIds")
|
@SuppressLint("HardwareIds")
|
||||||
@@ -87,6 +160,18 @@ object BaseRobTopActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getClipboardString(): String {
|
||||||
|
me.get()?.run {
|
||||||
|
val manager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clip = manager.primaryClip
|
||||||
|
if (clip != null && clip.itemCount > 0) {
|
||||||
|
return clip.getItemAt(0).coerceToText(this).toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun sendMail(subject: String, body: String, to: String) {
|
fun sendMail(subject: String, body: String, to: String) {
|
||||||
me.get()?.runOnUiThread {
|
me.get()?.runOnUiThread {
|
||||||
@@ -264,4 +349,164 @@ object BaseRobTopActivity {
|
|||||||
level = DeprecationLevel.HIDDEN
|
level = DeprecationLevel.HIDDEN
|
||||||
)
|
)
|
||||||
fun logEvent(event: String) {}
|
fun logEvent(event: String) {}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun setKeyboardInputFlags(flags: Int) {
|
||||||
|
curKeyboardInputFlags = flags
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun pickImportFiles() {
|
||||||
|
try {
|
||||||
|
importFileActivityContract.launch(Unit)
|
||||||
|
} catch (_: ActivityNotFoundException) {
|
||||||
|
me.get()?.apply {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
R.string.no_activity_found,
|
||||||
|
Toast.LENGTH_SHORT,
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyPickedFiles(uris: List<Uri>): List<String> {
|
||||||
|
val me = me.get() ?: return emptyList()
|
||||||
|
|
||||||
|
val importsDir = File(LaunchUtils.getSaveDirectory(me), "imports")
|
||||||
|
importsDir.mkdirs()
|
||||||
|
|
||||||
|
return uris.mapIndexedNotNull { index, uri ->
|
||||||
|
val displayName = displayName(uri)
|
||||||
|
?: "import_$index$LEVEL_EXTENSION"
|
||||||
|
if (!displayName.endsWith(LEVEL_EXTENSION)) {
|
||||||
|
return@mapIndexedNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputFile = File(importsDir, displayName)
|
||||||
|
var counter = 2
|
||||||
|
while (outputFile.exists()) {
|
||||||
|
outputFile = File(importsDir, "${counter}_$displayName")
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
me.contentResolver.openInputStream(uri)?.use { input ->
|
||||||
|
outputFile.outputStream().use { output ->
|
||||||
|
DownloadUtils.copyFile(input, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFile.absolutePath
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
outputFile.delete()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun displayName(uri: Uri): String? {
|
||||||
|
me.get()?.contentResolver?.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null)?.use { cursorQuery ->
|
||||||
|
if (cursorQuery.moveToFirst()) {
|
||||||
|
val displayName = cursorQuery.getString(0)
|
||||||
|
if (displayName.isNotEmpty()) {
|
||||||
|
return File(displayName).name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun shareFiles(files: Array<String>) {
|
||||||
|
pendingExportPaths = files.toList()
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (files.size == 1) {
|
||||||
|
shareFileActivityContract.launch(files.first())
|
||||||
|
return
|
||||||
|
} else if (files.size > 1) {
|
||||||
|
shareFolderActivityContract.launch(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (_: ActivityNotFoundException) {
|
||||||
|
me.get()?.apply {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
R.string.no_activity_found,
|
||||||
|
Toast.LENGTH_SHORT,
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cocos2dxGLSurfaceView.cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.fileShareFinished(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveToFolder(exportPaths: List<String>, treeUri: Uri): Int {
|
||||||
|
val uri = DocumentsContract.buildDocumentUriUsingTree(treeUri, DocumentsContract.getTreeDocumentId(treeUri))
|
||||||
|
|
||||||
|
val me = me.get() ?: return 0
|
||||||
|
|
||||||
|
return exportPaths.count { path ->
|
||||||
|
val filename = File(path).name
|
||||||
|
val documentUri = DocumentsContract.createDocument(me.contentResolver, uri, "application/octet-stream", filename)
|
||||||
|
?: return@count false
|
||||||
|
|
||||||
|
saveToDocument(path, documentUri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveToDocument(exportPath: String, uri: Uri): Boolean {
|
||||||
|
try {
|
||||||
|
FileInputStream(exportPath).use { inputStream ->
|
||||||
|
openOutput(uri).use { outputStream ->
|
||||||
|
if (outputStream != null) {
|
||||||
|
DownloadUtils.copyFile(inputStream, outputStream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureLevelExtension(uri)
|
||||||
|
return true
|
||||||
|
} catch (_: IOException) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openOutput(uri: Uri): OutputStream? {
|
||||||
|
val me = me.get() ?: return null
|
||||||
|
return try {
|
||||||
|
me.contentResolver.openOutputStream(uri, "wt")
|
||||||
|
} catch (_: IOException) {
|
||||||
|
me.contentResolver.openOutputStream(uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ensureLevelExtension(uri: Uri) {
|
||||||
|
val displayName = displayName(uri)
|
||||||
|
if (displayName == null || displayName.endsWith(LEVEL_EXTENSION)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val me = me.get() ?: return
|
||||||
|
|
||||||
|
val extensionIdx = displayName.lastIndexOf(".gdlvl.")
|
||||||
|
val substring = if (extensionIdx < 0) {
|
||||||
|
displayName + LEVEL_EXTENSION
|
||||||
|
} else {
|
||||||
|
displayName.substring(0, extensionIdx + 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DocumentsContract.renameDocument(me.contentResolver, uri, substring)
|
||||||
|
} catch (_: IOException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -55,4 +55,16 @@ object JniToCpp {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
external fun videoAdShowed()
|
external fun videoAdShowed()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun filesPicked(files: Array<String>)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun fileShareFinished(success: Boolean)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun textInputCaretToEnd()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
external fun textInputDone()
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.customRobTop.contracts
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
|
|
||||||
|
class ImportFileActivityContract : ActivityResultContract<Unit, List<Uri>>() {
|
||||||
|
override fun createIntent(
|
||||||
|
context: Context,
|
||||||
|
input: Unit
|
||||||
|
): Intent {
|
||||||
|
return Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "*/*"
|
||||||
|
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parseResult(
|
||||||
|
resultCode: Int,
|
||||||
|
intent: Intent?
|
||||||
|
): List<Uri> {
|
||||||
|
if (resultCode != Activity.RESULT_OK || intent == null) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val clipData = intent.clipData
|
||||||
|
return if (clipData != null) {
|
||||||
|
List(clipData.itemCount) { i -> clipData.getItemAt(i).uri }
|
||||||
|
} else {
|
||||||
|
val intentData = intent.data
|
||||||
|
if (intentData != null)
|
||||||
|
listOf(intentData)
|
||||||
|
else
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.customRobTop.contracts
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.DocumentsContract
|
||||||
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ShareFileActivityContract : ActivityResultContract<String, Uri?>() {
|
||||||
|
override fun createIntent(
|
||||||
|
context: Context,
|
||||||
|
input: String
|
||||||
|
): Intent {
|
||||||
|
return Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "application/octet-stream"
|
||||||
|
putExtra(Intent.EXTRA_TITLE, File(input).name)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
putExtra(DocumentsContract.EXTRA_INITIAL_URI,
|
||||||
|
DocumentsContract.buildDocumentUri("com.android.externalstorage.documents", "primary:Download")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun parseResult(
|
||||||
|
resultCode: Int,
|
||||||
|
intent: Intent?
|
||||||
|
): Uri? {
|
||||||
|
if (resultCode != Activity.RESULT_OK || intent == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return intent.data
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -171,7 +171,8 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
tryLoadLibrary(gdPackageInfo, Constants.FMOD_LIB_NAME)
|
tryLoadLibrary(gdPackageInfo, Constants.FMOD_LIB_NAME)
|
||||||
tryLoadLibrary(gdPackageInfo, Constants.COCOS_LIB_NAME)
|
tryLoadLibrary(gdPackageInfo, Constants.COCOS_LIB_NAME)
|
||||||
|
|
||||||
if (GamePackageUtils.getGameVersionCode(packageManager) >= 39L) {
|
val gameVersionCode = GamePackageUtils.getGameVersionCode(packageManager)
|
||||||
|
if (gameVersionCode >= 39L) {
|
||||||
// this fix requires geode v3, which is 2.206+
|
// this fix requires geode v3, which is 2.206+
|
||||||
// there is a short period in which 2.206 users will still have geode v2, but whatever. ig
|
// there is a short period in which 2.206 users will still have geode v2, but whatever. ig
|
||||||
LauncherFix.enableExceptionsRenaming()
|
LauncherFix.enableExceptionsRenaming()
|
||||||
@@ -182,6 +183,9 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
loadInternalMods()
|
loadInternalMods()
|
||||||
|
|
||||||
val baseView = createView()
|
val baseView = createView()
|
||||||
|
if (gameVersionCode >= 42L) {
|
||||||
|
mGLSurfaceView?.sendNewCocosEvents = true
|
||||||
|
}
|
||||||
|
|
||||||
if (!GeodeUtils.handleSafeArea && Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
|
if (!GeodeUtils.handleSafeArea && Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
|
||||||
val frameLayoutParams = ViewGroup.LayoutParams(
|
val frameLayoutParams = ViewGroup.LayoutParams(
|
||||||
@@ -205,12 +209,22 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
left = 0, top = 0, right = 0, bottom = 0
|
left = 0, top = 0, right = 0, bottom = 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cocos2dxGLSurfaceView.onKeyboardInsets(insets)
|
||||||
|
|
||||||
WindowInsets.CONSUMED
|
WindowInsets.CONSUMED
|
||||||
}
|
}
|
||||||
|
|
||||||
frameLayout.addView(baseView)
|
frameLayout.addView(baseView)
|
||||||
setContentView(frameLayout)
|
setContentView(frameLayout)
|
||||||
} else {
|
} else {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
baseView.setOnApplyWindowInsetsListener { view, insets ->
|
||||||
|
Cocos2dxGLSurfaceView.onKeyboardInsets(insets)
|
||||||
|
return@setOnApplyWindowInsetsListener view.onApplyWindowInsets(insets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setContentView(baseView)
|
setContentView(baseView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,6 +511,10 @@ class GeometryDashActivity : AppCompatActivity(), Cocos2dxHelper.Cocos2dxHelperL
|
|||||||
editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
|
||||||
glSurfaceView.cocos2dxEditText = editText
|
glSurfaceView.cocos2dxEditText = editText
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
glSurfaceView.defaultFocusHighlightEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
return frameLayout
|
return frameLayout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,8 +104,10 @@ class MainActivity : ComponentActivity() {
|
|||||||
val gdInstalled = GamePackageUtils.isGameInstalled(packageManager)
|
val gdInstalled = GamePackageUtils.isGameInstalled(packageManager)
|
||||||
val geodeInstalled = LaunchUtils.isGeodeInstalled(this)
|
val geodeInstalled = LaunchUtils.isGeodeInstalled(this)
|
||||||
|
|
||||||
if (gdInstalled && geodeInstalled && intent.getBooleanExtra("restarted", false)) {
|
val restartImmediately = intent.getBooleanExtra("restarted", false)
|
||||||
onLaunch(this)
|
if (gdInstalled && geodeInstalled && restartImmediately) {
|
||||||
|
val withSafeMode = intent.getBooleanExtra("safe-mode", false)
|
||||||
|
onLaunch(this, withSafeMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ import android.provider.DocumentsContract
|
|||||||
import android.provider.DocumentsProvider
|
import android.provider.DocumentsProvider
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import com.geode.launcher.utils.ApplicationIcon
|
||||||
|
import com.geode.launcher.utils.IconUtils
|
||||||
import com.geode.launcher.utils.LaunchUtils
|
import com.geode.launcher.utils.LaunchUtils
|
||||||
|
import com.geode.launcher.utils.PreferenceUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
private val DEFAULT_ROOT_PROJECTION: Array<String> = arrayOf(
|
private val DEFAULT_ROOT_PROJECTION: Array<String> = arrayOf(
|
||||||
@@ -60,8 +63,17 @@ class UserDirectoryProvider : DocumentsProvider() {
|
|||||||
DocumentsContract.Root.FLAG_SUPPORTS_RECENTS or
|
DocumentsContract.Root.FLAG_SUPPORTS_RECENTS or
|
||||||
DocumentsContract.Root.FLAG_SUPPORTS_SEARCH
|
DocumentsContract.Root.FLAG_SUPPORTS_SEARCH
|
||||||
)
|
)
|
||||||
add(DocumentsContract.Root.COLUMN_TITLE, context.getString(R.string.app_name))
|
|
||||||
add(DocumentsContract.Root.COLUMN_ICON, R.drawable.geode_logo)
|
val selectedIconKey = PreferenceUtils.get(context).getString(PreferenceUtils.Key.SELECTED_ICON)
|
||||||
|
?: "geode"
|
||||||
|
val selectedIcon = ApplicationIcon.fromId(selectedIconKey)
|
||||||
|
val iconDetails = IconUtils.getIconDetails(selectedIcon)
|
||||||
|
|
||||||
|
val nameId = if (selectedIcon == ApplicationIcon.SAPPHIRE) R.string.application_icon_sapphire else R.string.app_name
|
||||||
|
val logoId = if (selectedIcon == ApplicationIcon.GEODE) R.drawable.geode_logo else iconDetails.iconId
|
||||||
|
|
||||||
|
add(DocumentsContract.Root.COLUMN_TITLE, context.getString(nameId))
|
||||||
|
add(DocumentsContract.Root.COLUMN_ICON, logoId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -408,7 +408,8 @@ fun LauncherUpdateIndicator(modifier: Modifier = Modifier) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevatedCard(modifier) {
|
// there's like a single pixel of the shadow that gets clipped without this...
|
||||||
|
ElevatedCard(modifier = modifier.padding(bottom = 1.dp)) {
|
||||||
Column(
|
Column(
|
||||||
// buttons add enough padding already, lower to compensate
|
// buttons add enough padding already, lower to compensate
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ object GamePackageUtils {
|
|||||||
39L to "2.206",
|
39L to "2.206",
|
||||||
40L to "2.2074", // ok
|
40L to "2.2074", // ok
|
||||||
41L to "2.2081",
|
41L to "2.2081",
|
||||||
|
42L to "2.209",
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -191,10 +191,16 @@ object GeodeUtils {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun restartGame() {
|
fun restartGame() {
|
||||||
|
restartGame(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun restartGame(safeMode: Boolean) {
|
||||||
activity.get()?.run {
|
activity.get()?.run {
|
||||||
packageManager.getLaunchIntentForPackage(packageName)?.also {
|
packageManager.getLaunchIntentForPackage(packageName)?.also {
|
||||||
val mainIntent = Intent.makeRestartActivityTask(it.component)
|
val mainIntent = Intent.makeRestartActivityTask(it.component)
|
||||||
mainIntent.putExtra("restarted", true)
|
mainIntent.putExtra("restarted", true)
|
||||||
|
mainIntent.putExtra("safe-mode", safeMode)
|
||||||
startActivity(mainIntent)
|
startActivity(mainIntent)
|
||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
@@ -794,7 +800,7 @@ object GeodeUtils {
|
|||||||
|
|
||||||
external fun internalKeyEvent(timestamp: Long, deviceId: Int, eventSource: Int, keyCode: Int, modifiers: Int, isDown: Boolean, repeatCount: Int)
|
external fun internalKeyEvent(timestamp: Long, deviceId: Int, eventSource: Int, keyCode: Int, modifiers: Int, isDown: Boolean, repeatCount: Int)
|
||||||
external fun internalTouchEvent(timestamp: Long, deviceId: Int, eventSource: Int, eventType: Int, ids: IntArray, xs: FloatArray, ys: FloatArray)
|
external fun internalTouchEvent(timestamp: Long, deviceId: Int, eventSource: Int, eventType: Int, ids: IntArray, xs: FloatArray, ys: FloatArray)
|
||||||
external fun internalScrollEvent(timestamp: Long, deviceId: Int, eventSource: Int, scrollX: Float, scrollY: Float)
|
external fun internalScrollEvent(timestamp: Long, deviceId: Int, eventSource: Int, scrollX: Float, scrollY: Float, mouseX: Float, mouseY: Float)
|
||||||
external fun internalJoystickEvent(timestamp: Long, deviceId: Int, eventSource: Int, leftX: FloatArray, leftY: FloatArray, rightX: FloatArray, rightY: FloatArray, hatX: FloatArray, hatY: FloatArray, leftTrigger: FloatArray, rightTrigger: FloatArray)
|
external fun internalJoystickEvent(timestamp: Long, deviceId: Int, eventSource: Int, leftX: FloatArray, leftY: FloatArray, rightX: FloatArray, rightY: FloatArray, hatX: FloatArray, hatY: FloatArray, leftTrigger: FloatArray, rightTrigger: FloatArray)
|
||||||
|
|
||||||
external fun inputDeviceAdded(deviceId: Int)
|
external fun inputDeviceAdded(deviceId: Int)
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ enum class ApplicationIcon {
|
|||||||
GEODE,
|
GEODE,
|
||||||
PRIDE,
|
PRIDE,
|
||||||
TRANS,
|
TRANS,
|
||||||
|
GREEN,
|
||||||
SAPPHIRE;
|
SAPPHIRE;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -53,6 +54,7 @@ enum class ApplicationIcon {
|
|||||||
"pride" -> PRIDE
|
"pride" -> PRIDE
|
||||||
"trans" -> TRANS
|
"trans" -> TRANS
|
||||||
"sapphire" -> SAPPHIRE
|
"sapphire" -> SAPPHIRE
|
||||||
|
"green" -> GREEN
|
||||||
else -> DEFAULT
|
else -> DEFAULT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,6 +65,7 @@ enum class ApplicationIcon {
|
|||||||
DEFAULT -> "default"
|
DEFAULT -> "default"
|
||||||
TRANS -> "trans"
|
TRANS -> "trans"
|
||||||
SAPPHIRE -> "sapphire"
|
SAPPHIRE -> "sapphire"
|
||||||
|
GREEN -> "green"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,5 +108,11 @@ object IconUtils {
|
|||||||
iconId = R.mipmap.ic_launcher_sapphire,
|
iconId = R.mipmap.ic_launcher_sapphire,
|
||||||
nameId = R.string.application_icon_sapphire,
|
nameId = R.string.application_icon_sapphire,
|
||||||
)
|
)
|
||||||
|
ApplicationIcon.GREEN -> ApplicationIconDetails(
|
||||||
|
id = id.toId(),
|
||||||
|
component = "MainActivityGreen",
|
||||||
|
iconId = R.mipmap.ic_launcher_green,
|
||||||
|
nameId = R.string.application_icon_green,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,11 +8,13 @@ import android.os.Build
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
import android.util.Log
|
import android.text.InputType
|
||||||
import android.view.InputDevice
|
import android.view.InputDevice
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
|
import android.view.WindowInsets
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.widget.AppCompatEditText
|
import androidx.appcompat.widget.AppCompatEditText
|
||||||
@@ -25,12 +27,54 @@ private const val HANDLER_CLOSE_IME_KEYBOARD = 3
|
|||||||
private const val MS_TO_NS = 1_000_000
|
private const val MS_TO_NS = 1_000_000
|
||||||
private const val SEC_TO_NS = 1_000_000_000.0
|
private const val SEC_TO_NS = 1_000_000_000.0
|
||||||
|
|
||||||
|
fun inputTypeForFlags(i: Int): Int {
|
||||||
|
if ((i and BaseRobTopActivity.KEYBOARD_INPUT_NUMERIC) != 0) {
|
||||||
|
return InputType.TYPE_NUMBER_FLAG_DECIMAL or InputType.TYPE_NUMBER_FLAG_SIGNED or InputType.TYPE_CLASS_NUMBER
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i and BaseRobTopActivity.KEYBOARD_INPUT_PASSWORD) != 0) {
|
||||||
|
return InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i and BaseRobTopActivity.KEYBOARD_INPUT_MULTILINE) != 0) {
|
||||||
|
return InputType.TYPE_TEXT_FLAG_MULTI_LINE or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES or InputType.TYPE_CLASS_TEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
return InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS or InputType.TYPE_CLASS_TEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
fun usesInlineKeyboard(): Boolean {
|
||||||
|
return Build.VERSION.SDK_INT >= 30
|
||||||
|
}
|
||||||
|
|
||||||
|
fun imeOptionsForFlags(i: Int): Int {
|
||||||
|
val i2 = if ((i and BaseRobTopActivity.KEYBOARD_INPUT_MULTILINE) == 0 || !usesInlineKeyboard())
|
||||||
|
EditorInfo.IME_ACTION_DONE else EditorInfo.IME_ACTION_NONE
|
||||||
|
|
||||||
|
return if (usesInlineKeyboard())
|
||||||
|
EditorInfo.IME_FLAG_NO_FULLSCREEN or EditorInfo.IME_FLAG_NO_EXTRACT_UI or i2
|
||||||
|
else i2
|
||||||
|
}
|
||||||
|
|
||||||
class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView
|
lateinit var cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView
|
||||||
private lateinit var handler: Handler
|
private lateinit var handler: Handler
|
||||||
private lateinit var cocos2dxTextInputWrapper: Cocos2dxTextInputWrapper
|
private lateinit var cocos2dxTextInputWrapper: Cocos2dxTextInputWrapper
|
||||||
|
|
||||||
|
private var keyboardVisible = false
|
||||||
|
private var keyboardHeight = 0
|
||||||
|
|
||||||
|
private var keyboardHideCheck = Runnable {
|
||||||
|
if (keyboardVisible) {
|
||||||
|
return@Runnable
|
||||||
|
}
|
||||||
|
|
||||||
|
cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
cocos2dxGLSurfaceView.cocos2dxRenderer.handleTextClosed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun openIMEKeyboard() {
|
fun openIMEKeyboard() {
|
||||||
val msg = Message()
|
val msg = Message()
|
||||||
@@ -50,6 +94,30 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
cocos2dxGLSurfaceView.queueEvent {
|
cocos2dxGLSurfaceView.queueEvent {
|
||||||
Cocos2dxAccelerometer.onSensorChanged(x, y, z, timestamp)
|
Cocos2dxAccelerometer.onSensorChanged(x, y, z, timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
|
fun onKeyboardInsets(windowInsets: WindowInsets) {
|
||||||
|
if (!cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val visible = windowInsets.isVisible(WindowInsets.Type.ime())
|
||||||
|
val offsetHeight = if (visible) windowInsets.getInsets(WindowInsets.Type.ime()).bottom else 0
|
||||||
|
|
||||||
|
if (visible == keyboardVisible && offsetHeight == keyboardHeight) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboardVisible = visible
|
||||||
|
keyboardHeight = offsetHeight
|
||||||
|
|
||||||
|
handler.removeCallbacks(keyboardHideCheck)
|
||||||
|
if (!visible) {
|
||||||
|
handler.postDelayed(keyboardHideCheck, 150L)
|
||||||
|
} else {
|
||||||
|
cocos2dxGLSurfaceView.cocos2dxRenderer.handleKeyboardWillShow(keyboardHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var cocos2dxRenderer: Cocos2dxRenderer
|
private lateinit var cocos2dxRenderer: Cocos2dxRenderer
|
||||||
@@ -65,6 +133,9 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
private set
|
private set
|
||||||
var supportsResizeEvents = false
|
var supportsResizeEvents = false
|
||||||
|
|
||||||
|
// 2.209+ events for keyboard and such
|
||||||
|
var sendNewCocosEvents = false
|
||||||
|
|
||||||
var cocos2dxEditText: AppCompatEditText? = null
|
var cocos2dxEditText: AppCompatEditText? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
@@ -85,9 +156,13 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
HANDLER_OPEN_IME_KEYBOARD -> {
|
HANDLER_OPEN_IME_KEYBOARD -> {
|
||||||
if (cocos2dxEditText?.requestFocus() == true) {
|
if (cocos2dxEditText?.requestFocus() == true) {
|
||||||
cocos2dxEditText?.apply {
|
cocos2dxEditText?.apply {
|
||||||
removeTextChangedListener(
|
removeTextChangedListener(cocos2dxTextInputWrapper)
|
||||||
cocos2dxTextInputWrapper
|
|
||||||
)
|
if (sendNewCocosEvents) {
|
||||||
|
inputType = inputTypeForFlags(BaseRobTopActivity.curKeyboardInputFlags)
|
||||||
|
imeOptions = imeOptionsForFlags(BaseRobTopActivity.curKeyboardInputFlags)
|
||||||
|
}
|
||||||
|
|
||||||
setText("")
|
setText("")
|
||||||
val text = msg.obj as String
|
val text = msg.obj as String
|
||||||
append(text)
|
append(text)
|
||||||
@@ -100,16 +175,13 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
cocos2dxEditText,
|
cocos2dxEditText,
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
Log.d("GLSurfaceView", "showSoftInput")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
HANDLER_CLOSE_IME_KEYBOARD -> {
|
HANDLER_CLOSE_IME_KEYBOARD -> {
|
||||||
cocos2dxEditText?.apply {
|
cocos2dxEditText?.apply {
|
||||||
removeTextChangedListener(
|
removeTextChangedListener(cocos2dxTextInputWrapper)
|
||||||
cocos2dxTextInputWrapper
|
|
||||||
)
|
|
||||||
(context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(
|
(context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(
|
||||||
windowToken,
|
windowToken,
|
||||||
0
|
0
|
||||||
@@ -117,8 +189,10 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestFocus()
|
requestFocus()
|
||||||
Log.d("GLSurfaceView", "HideSoftInput")
|
|
||||||
cocos2dxRenderer.handleTextClosed()
|
queueEvent {
|
||||||
|
cocos2dxRenderer.handleTextClosed()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else -> return
|
else -> return
|
||||||
@@ -297,6 +371,97 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun queueKeyboardEvent(keyCode: Int, event: KeyEvent, down: Boolean): Boolean {
|
||||||
|
val keypadCode = keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK
|
||||||
|
if (event.isSystem && !keypadCode) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keypadCode && BaseRobTopActivity.blockBackButton) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
queueEvent {
|
||||||
|
sendNextEventTimestamp(event.eventTime * MS_TO_NS)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useKeyboardEvents) {
|
||||||
|
if (down) {
|
||||||
|
queueEvent {
|
||||||
|
GeodeUtils.nativeKeyDown(keyCode, event.modifiers, event.repeatCount != 0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
queueEvent {
|
||||||
|
GeodeUtils.nativeKeyUp(keyCode, event.modifiers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controllerEventsEnabled) {
|
||||||
|
queueEvent {
|
||||||
|
GeodeUtils.internalKeyEvent(
|
||||||
|
event.eventTime * MS_TO_NS,
|
||||||
|
event.deviceId,
|
||||||
|
event.source,
|
||||||
|
event.keyCode,
|
||||||
|
event.modifiers,
|
||||||
|
down,
|
||||||
|
event.repeatCount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// geode events override native callbacks
|
||||||
|
if (useKeyboardEvents || controllerEventsEnabled) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendNewCocosEvents) {
|
||||||
|
if (KeyEvent.isGamepadButton(keyCode)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_ESCAPE && BaseRobTopActivity.blockBackButton) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// messy logic
|
||||||
|
val isRepeat = event.repeatCount > 0
|
||||||
|
if (keypadCode) {
|
||||||
|
if (down) {
|
||||||
|
if (isRepeat || BaseRobTopActivity.blockBackButton) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
queueEvent {
|
||||||
|
cocos2dxRenderer.handleKeyDown(keyCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val eventTimestamp = event.eventTime / 1000.0
|
||||||
|
|
||||||
|
val shiftPressed = event.isShiftPressed
|
||||||
|
val ctrlPressed = event.isCtrlPressed
|
||||||
|
val altPressed = event.isAltPressed
|
||||||
|
|
||||||
|
queueEvent {
|
||||||
|
cocos2dxRenderer.handleKeyboardEvent(
|
||||||
|
keyCode, down, isRepeat, eventTimestamp,
|
||||||
|
shiftPressed, ctrlPressed, altPressed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun legacyKeyDown(keyCode: Int, keyEvent: KeyEvent): Boolean {
|
private fun legacyKeyDown(keyCode: Int, keyEvent: KeyEvent): Boolean {
|
||||||
return when (keyCode) {
|
return when (keyCode) {
|
||||||
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_MENU -> {
|
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_MENU -> {
|
||||||
@@ -354,65 +519,19 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
if (!useKeyboardEvents && !controllerEventsEnabled) {
|
if (!queueKeyboardEvent(keyCode, event, true)) {
|
||||||
return legacyKeyDown(keyCode, event)
|
return legacyKeyDown(keyCode, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (keyCode) {
|
return true
|
||||||
// ignore system keys
|
|
||||||
KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_MUTE -> {
|
|
||||||
super.onKeyDown(keyCode, event)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
if (BaseRobTopActivity.blockBackButton) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
queueEvent {
|
|
||||||
sendNextEventTimestamp(event.eventTime * MS_TO_NS)
|
|
||||||
|
|
||||||
if (useKeyboardEvents) {
|
|
||||||
GeodeUtils.nativeKeyDown(keyCode, event.modifiers, event.repeatCount != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controllerEventsEnabled) {
|
|
||||||
GeodeUtils.internalKeyEvent(event.eventTime * MS_TO_NS, event.deviceId, event.source, event.keyCode, event.modifiers, true, event.repeatCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
if (!useKeyboardEvents && !controllerEventsEnabled) {
|
if (!queueKeyboardEvent(keyCode, event, false)) {
|
||||||
return super.onKeyUp(keyCode, event)
|
return super.onKeyUp(keyCode, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (keyCode) {
|
return true
|
||||||
KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_MUTE -> {
|
|
||||||
super.onKeyUp(keyCode, event)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
if (event.repeatCount != 0 || BaseRobTopActivity.blockBackButton) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
queueEvent {
|
|
||||||
sendNextEventTimestamp(event.eventTime * MS_TO_NS)
|
|
||||||
|
|
||||||
if (useKeyboardEvents) {
|
|
||||||
GeodeUtils.nativeKeyUp(keyCode, event.modifiers)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controllerEventsEnabled) {
|
|
||||||
GeodeUtils.internalKeyEvent(event.eventTime * MS_TO_NS, event.deviceId, event.source, event.keyCode, event.modifiers, false, event.repeatCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// i'm lazy.
|
// i'm lazy.
|
||||||
@@ -475,11 +594,15 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onGenericMotionEvent(event: MotionEvent?): Boolean {
|
override fun onGenericMotionEvent(event: MotionEvent?): Boolean {
|
||||||
if (!useKeyboardEvents && !controllerEventsEnabled) {
|
val hasGeodeEvents = useKeyboardEvents || controllerEventsEnabled
|
||||||
|
if (!hasGeodeEvents && !sendNewCocosEvents) {
|
||||||
return super.onGenericMotionEvent(event)
|
return super.onGenericMotionEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event?.action == MotionEvent.ACTION_SCROLL) {
|
if (event?.action == MotionEvent.ACTION_SCROLL) {
|
||||||
|
val mouseX = event.x
|
||||||
|
val mouseY = event.y
|
||||||
|
|
||||||
val scrollX = event.getAxisValue(MotionEvent.AXIS_HSCROLL)
|
val scrollX = event.getAxisValue(MotionEvent.AXIS_HSCROLL)
|
||||||
val scrollY = event.getAxisValue(MotionEvent.AXIS_VSCROLL)
|
val scrollY = event.getAxisValue(MotionEvent.AXIS_VSCROLL)
|
||||||
val timestamp = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
val timestamp = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||||
@@ -493,7 +616,11 @@ class Cocos2dxGLSurfaceView(context: Context) : GLSurfaceView(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (controllerEventsEnabled) {
|
if (controllerEventsEnabled) {
|
||||||
GeodeUtils.internalScrollEvent(timestamp, event.deviceId, event.source, scrollX, scrollY)
|
GeodeUtils.internalScrollEvent(timestamp, event.deviceId, event.source, scrollX, scrollY, mouseX, mouseY)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasGeodeEvents && sendNewCocosEvents) {
|
||||||
|
cocos2dxRenderer.handleScroll(mouseX, mouseY, scrollY, scrollX)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,29 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeKeyDown(keyCode: Int): Boolean
|
private external fun nativeKeyDown(keyCode: Int): Boolean
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
private external fun nativeKeyboardEvent(
|
||||||
|
keyCode: Int,
|
||||||
|
down: Boolean,
|
||||||
|
isRepeat: Boolean,
|
||||||
|
timestamp: Double,
|
||||||
|
shiftPressed: Boolean,
|
||||||
|
ctrlPressed: Boolean,
|
||||||
|
altPressed: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
private external fun nativeKeyboardWillShow(offset: Int)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeOnPause()
|
private external fun nativeOnPause()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeOnResume()
|
private external fun nativeOnResume()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
private external fun nativeScroll(x: Float, y: Float, scrollY: Float, scrollX: Float)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
private external fun nativeRender()
|
private external fun nativeRender()
|
||||||
|
|
||||||
@@ -133,6 +150,18 @@ class Cocos2dxRenderer(private var handler: Cocos2dxGLSurfaceView) : GLSurfaceVi
|
|||||||
nativeKeyDown(keyCode)
|
nativeKeyDown(keyCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun handleKeyboardWillShow(offset: Int) {
|
||||||
|
nativeKeyboardWillShow(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleKeyboardEvent(keyCode: Int, down: Boolean, isRepeat: Boolean, timestamp: Double, shiftPressed: Boolean, ctrlPressed: Boolean, altPressed: Boolean) {
|
||||||
|
nativeKeyboardEvent(keyCode, down, isRepeat, timestamp, shiftPressed, ctrlPressed, altPressed)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleScroll(x: Float, y: Float, scrollY: Float, scrollX: Float) {
|
||||||
|
nativeScroll(x, y, scrollY, scrollX)
|
||||||
|
}
|
||||||
|
|
||||||
fun handleOnPause() {
|
fun handleOnPause() {
|
||||||
nativeOnPause()
|
nativeOnPause()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import android.text.TextWatcher
|
|||||||
import android.widget.TextView.OnEditorActionListener
|
import android.widget.TextView.OnEditorActionListener
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import com.customRobTop.JniToCpp
|
||||||
|
|
||||||
class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView) : TextWatcher, OnEditorActionListener {
|
class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurfaceView) : TextWatcher, OnEditorActionListener {
|
||||||
private var originText: String? = null
|
private var originText: String? = null
|
||||||
@@ -19,21 +21,33 @@ class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurf
|
|||||||
this.originText = originText
|
this.originText = originText
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable) {
|
override fun afterTextChanged(editable: Editable) {
|
||||||
if (!isFullScreenEdit) {
|
if (isFullScreenEdit) {
|
||||||
var nModified = s.length - text!!.length
|
return
|
||||||
if (nModified > 0) {
|
|
||||||
cocos2dxGLSurfaceView.insertText(
|
|
||||||
s.subSequence(text!!.length, s.length).toString()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
while (nModified < 0) {
|
|
||||||
cocos2dxGLSurfaceView.deleteBackward()
|
|
||||||
nModified++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text = s.toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val cText = text ?: return
|
||||||
|
|
||||||
|
val str = editable.toString()
|
||||||
|
val unchanged = str.commonPrefixWith(cText)
|
||||||
|
|
||||||
|
var unchangedUntil = unchanged.length
|
||||||
|
if (unchangedUntil > 0 && unchangedUntil < str.length && Character.isLowSurrogate(str[unchangedUntil])) {
|
||||||
|
unchangedUntil--
|
||||||
|
}
|
||||||
|
|
||||||
|
val codePointLength = cText.codePointCount(unchangedUntil, cText.length)
|
||||||
|
repeat(codePointLength) {
|
||||||
|
cocos2dxGLSurfaceView.deleteBackward()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unchangedUntil < str.length) {
|
||||||
|
cocos2dxGLSurfaceView.insertText(
|
||||||
|
str.substring(unchangedUntil)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
text = str
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(
|
override fun beforeTextChanged(
|
||||||
@@ -47,22 +61,45 @@ class Cocos2dxTextInputWrapper(private val cocos2dxGLSurfaceView: Cocos2dxGLSurf
|
|||||||
|
|
||||||
override fun onTextChanged(pCharSequence: CharSequence, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(pCharSequence: CharSequence, start: Int, before: Int, count: Int) {}
|
||||||
override fun onEditorAction(textView: TextView, actionID: Int, keyEvent: KeyEvent?): Boolean {
|
override fun onEditorAction(textView: TextView, actionID: Int, keyEvent: KeyEvent?): Boolean {
|
||||||
if (cocos2dxGLSurfaceView.cocos2dxEditText == textView && isFullScreenEdit) {
|
val fullscreenIme = cocos2dxGLSurfaceView.cocos2dxEditText == textView && isFullScreenEdit
|
||||||
for (i in originText!!.length downTo 1) {
|
if (fullscreenIme) {
|
||||||
cocos2dxGLSurfaceView.deleteBackward()
|
|
||||||
}
|
|
||||||
var text = textView.text.toString()
|
var text = textView.text.toString()
|
||||||
if (!text.endsWith('\n')) {
|
if (originText != text || !cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
||||||
text += '\n'
|
if (cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
||||||
}
|
cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.textInputCaretToEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cocos2dxGLSurfaceView.insertText(text)
|
repeat(originText!!.length) {
|
||||||
|
cocos2dxGLSurfaceView.deleteBackward()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
||||||
|
if (!text.endsWith('\n')) {
|
||||||
|
text += '\n'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.isNotEmpty()) {
|
||||||
|
cocos2dxGLSurfaceView.insertText(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (actionID != 6) {
|
|
||||||
return false
|
if (fullscreenIme || actionID == EditorInfo.IME_ACTION_DONE) {
|
||||||
|
if (cocos2dxGLSurfaceView.sendNewCocosEvents) {
|
||||||
|
cocos2dxGLSurfaceView.queueEvent {
|
||||||
|
JniToCpp.textInputDone()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cocos2dxGLSurfaceView.requestFocus()
|
|
||||||
Cocos2dxGLSurfaceView.closeIMEKeyboard()
|
if (actionID == EditorInfo.IME_ACTION_DONE) {
|
||||||
|
cocos2dxGLSurfaceView.requestFocus()
|
||||||
|
Cocos2dxGLSurfaceView.closeIMEKeyboard()
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,28 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="1024"
|
android:viewportWidth="1366"
|
||||||
android:viewportHeight="1024">
|
android:viewportHeight="1366">
|
||||||
<group android:scaleX="0.75" android:scaleY="0.75" android:translateX="128" android:translateY="128">
|
<group>
|
||||||
<clip-path
|
<clip-path
|
||||||
android:pathData="M0,0h1024v1024h-1024z"/>
|
android:pathData="M0,0h1366v1366h-1366z"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M0,0h1024v1024h-1024z"
|
android:pathData="M0,0h1366v1366h-1366z"
|
||||||
android:fillColor="#F4D48E"/>
|
android:fillColor="#F4D48E"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M512,512m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
||||||
android:fillColor="#F4D48E"/>
|
android:fillColor="#F4D48E"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M719.5,289C618,241.7 526,152.5 320.5,152.5C115,152.5 3.5,248 -8.5,293C-20.5,338 -8.2,391.5 -13.5,390.5L-33,706.5H1145L1137.5,460C1115.5,426.8 1043.5,399 1007,391.5C970.5,384 822.5,337 719.5,289Z"
|
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
||||||
android:fillColor="#F4A47B"/>
|
android:fillColor="#F4A47B"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M561.5,514.5C488.5,476.5 341,402 214.5,402C88,402 30.3,440.7 -8.5,461.5C-47.3,482.3 -54,485.2 -59,486.5L-68.5,808L563.5,814.5L561.5,514.5Z"
|
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
||||||
android:fillColor="#E27880"/>
|
android:fillColor="#E27880"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1020.5,551C994,521.2 893.7,454.1 662.5,452.5C539.2,451.6 363,505.6 259,577.5C163.9,643.2 43,680 -13,686L-124,934.5H1187.5L1020.5,551Z"
|
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
||||||
android:fillColor="#B9588F"/>
|
android:fillColor="#B9588F"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M819.5,856C638,856 518,772.5 359,772.5C200,772.5 100,860.5 65,869L-94,949.5V1041.5L1177.5,1025.5L1032.5,738C1028,758 967.4,856 819.5,856Z"
|
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
||||||
android:fillColor="#714A9A"/>
|
android:fillColor="#714A9A"/>
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="1366"
|
||||||
|
android:viewportHeight="1366">
|
||||||
|
<group>
|
||||||
|
<clip-path
|
||||||
|
android:pathData="M0,0h1366v1366h-1366z"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M0,0h1366v1366h-1366z"
|
||||||
|
android:fillColor="#9EF4C3"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
||||||
|
android:fillColor="#9EF4C3"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
||||||
|
android:fillColor="#6DDBAD"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
||||||
|
android:fillColor="#64C780"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
||||||
|
android:fillColor="#46A47D"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
||||||
|
android:fillColor="#417563"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
|
|
||||||
@@ -1,28 +1,29 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="1024"
|
android:viewportWidth="1366"
|
||||||
android:viewportHeight="1024">
|
android:viewportHeight="1366">
|
||||||
<group android:scaleX="0.75" android:scaleY="0.75" android:translateX="128" android:translateY="128">
|
<group>
|
||||||
<clip-path
|
<clip-path
|
||||||
android:pathData="M0,0h1024v1024h-1024z"/>
|
android:pathData="M0,0h1366v1366h-1366z"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M0,0h1024v1024h-1024z"
|
android:pathData="M0,0h1366v1366h-1366z"
|
||||||
android:fillColor="#CC7C7C"/>
|
android:fillColor="#CC7C7C"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M512,512m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
||||||
android:fillColor="#CC7C7C"/>
|
android:fillColor="#CC7C7C"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M719.5,289C618,241.7 526,152.5 320.5,152.5C115,152.5 3.5,248 -8.5,293C-20.5,338 -8.2,391.5 -13.5,390.5L-33,706.5H1145L1137.5,460C1115.5,426.8 1043.5,399 1007,391.5C970.5,384 822.5,337 719.5,289Z"
|
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
||||||
android:fillColor="#C6B471"/>
|
android:fillColor="#C6B471"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M561.5,514.5C488.5,476.5 341,402 214.5,402C88,402 30.3,440.7 -8.5,461.5C-47.3,482.3 -54,485.2 -59,486.5L-68.5,808L563.5,814.5L561.5,514.5Z"
|
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
||||||
android:fillColor="#59AF7F"/>
|
android:fillColor="#59AF7F"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1020.5,551C994,521.2 893.7,454.1 662.5,452.5C539.2,451.6 363,505.6 259,577.5C163.9,643.2 43,680 -13,686L-124,934.5H1187.5L1020.5,551Z"
|
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
||||||
android:fillColor="#5F8CAB"/>
|
android:fillColor="#5F8CAB"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M819.5,856C638,856 518,772.5 359,772.5C200,772.5 100,860.5 65,869L-94,949.5V1041.5L1177.5,1025.5L1032.5,738C1028,758 967.4,856 819.5,856Z"
|
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
||||||
android:fillColor="#70558D"/>
|
android:fillColor="#70558D"/>
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
||||||
@@ -1,28 +1,29 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="1024"
|
android:viewportWidth="1366"
|
||||||
android:viewportHeight="1024">
|
android:viewportHeight="1366">
|
||||||
<group android:scaleX="0.75" android:scaleY="0.75" android:translateX="128" android:translateY="128">
|
<group>
|
||||||
<clip-path
|
<clip-path
|
||||||
android:pathData="M0,0h1024v1024h-1024z"/>
|
android:pathData="M0,0h1366v1366h-1366z"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M0,0h1024v1024h-1024z"
|
android:pathData="M0,0h1366v1366h-1366z"
|
||||||
android:fillColor="#65B8C2"/>
|
android:fillColor="#65B8C2"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M512,512m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
android:pathData="M598,683m-512,0a512,512 0,1 1,1024 0a512,512 0,1 1,-1024 0"
|
||||||
android:fillColor="#65B8C2"/>
|
android:fillColor="#65B8C2"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M719.5,289C618,241.7 526,152.5 320.5,152.5C115,152.5 3.5,248 -8.5,293C-20.5,338 -8.2,391.5 -13.5,390.5L-33,706.5H1145L1137.5,460C1115.5,426.8 1043.5,399 1007,391.5C970.5,384 822.5,337 719.5,289Z"
|
android:pathData="M873.8,459.7C752.5,412.3 642.7,323 397.2,323C151.8,323 18.6,418.7 4.3,463.8C-10.1,508.8 4.7,562.4 -1.7,561.4L-25,878H1382L1373,631.1C1346.8,597.8 1260.8,569.9 1217.2,562.4C1173.6,554.9 996.8,507.8 873.8,459.7Z"
|
||||||
android:fillColor="#DEA5CD"/>
|
android:fillColor="#DEA5CD"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M561.5,514.5C488.5,476.5 341,402 214.5,402C88,402 30.3,440.7 -8.5,461.5C-47.3,482.3 -54,485.2 -59,486.5L-68.5,808L563.5,814.5L561.5,514.5Z"
|
android:pathData="M647.9,685.4C569.9,647.4 412.4,573 277.3,573C142.1,573 80.5,611.7 39.1,632.4C-2.4,653.2 -9.5,656.1 -14.9,657.4L-25,978.5L650,985L647.9,685.4Z"
|
||||||
android:fillColor="#DEE8EA"/>
|
android:fillColor="#DEE8EA"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M1020.5,551C994,521.2 893.7,454.1 662.5,452.5C539.2,451.6 363,505.6 259,577.5C163.9,643.2 43,680 -13,686L-124,934.5H1187.5L1020.5,551Z"
|
android:pathData="M1362.1,728.7C1327,696.7 1194.3,624.7 888.5,623C725.4,622.1 492.3,679.9 354.7,757.1C228.9,827.6 68.9,867 -5.2,873.5L-152,1140H1583L1362.1,728.7Z"
|
||||||
android:fillColor="#C485BD"/>
|
android:fillColor="#C485BD"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M819.5,856C638,856 518,772.5 359,772.5C200,772.5 100,860.5 65,869L-94,949.5V1041.5L1177.5,1025.5L1032.5,738C1028,758 967.4,856 819.5,856Z"
|
android:pathData="M1107,1027.2C885.5,1027.2 739,943.6 544.9,943.6C350.9,943.6 228.8,1031.7 186.1,1040.2L-8,1120.8V1385L1376,1379L1367,909C1361.5,929 1287.6,1027.2 1107,1027.2Z"
|
||||||
android:fillColor="#259CB4"/>
|
android:fillColor="#259CB4"/>
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_green_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_monochrome_shadow"/>
|
||||||
|
</adaptive-icon>
|
||||||
@@ -338,6 +338,7 @@
|
|||||||
<string name="application_icon_pride">Pride</string>
|
<string name="application_icon_pride">Pride</string>
|
||||||
<string name="application_icon_trans">Transgender</string>
|
<string name="application_icon_trans">Transgender</string>
|
||||||
<string name="application_icon_sapphire">Sapphire</string>
|
<string name="application_icon_sapphire">Sapphire</string>
|
||||||
|
<string name="application_icon_green">Android</string>
|
||||||
<string name="application_icon_confirm">Change icon to %1$s?</string>
|
<string name="application_icon_confirm">Change icon to %1$s?</string>
|
||||||
<string name="application_icon_confirm_description">Geode Launcher will close itself to change the application icon.</string>
|
<string name="application_icon_confirm_description">Geode Launcher will close itself to change the application icon.</string>
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "9.4.0" apply false
|
id("com.android.application") version "9.4.1" apply false
|
||||||
id("com.android.library") version "9.4.0" apply false
|
id("com.android.library") version "9.4.1" apply false
|
||||||
id("org.jetbrains.kotlin.plugin.serialization") version "2.4.10" apply false
|
id("org.jetbrains.kotlin.plugin.serialization") version "2.4.21" apply false
|
||||||
id("org.jetbrains.kotlin.plugin.compose") version "2.4.10" apply false
|
id("org.jetbrains.kotlin.plugin.compose") version "2.4.21" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<Delete>("clean") {
|
tasks.register<Delete>("clean") {
|
||||||
|
|||||||
Reference in new issue
Block a user