Skip to content

Commit afb62c0

Browse files
allow reinstall for local modules
fixes #50 also, lots of fixes yours truly forgot to commit separately Signed-off-by: androidacy-user <opensource@androidacy.com>
1 parent 2c77c95 commit afb62c0

13 files changed

Lines changed: 285 additions & 26 deletions

File tree

app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ sentry {
392392

393393
autoInstallation {
394394
enabled.set(true)
395-
sentryVersion.set("6.18.1")
395+
sentryVersion.set("6.25.0")
396396
}
397397

398398
includeDependenciesReport.set(true)

app/src/main/kotlin/com/fox2code/mmm/MainActivity.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis
328328
// clear search view
329329
searchView.setQuery("", false)
330330
searchView.clearFocus()
331+
// reset reboot and search card
332+
searchCard.animate().translationY(0f).setInterpolator(DecelerateInterpolator(2f))
333+
.start()
334+
rebootFab.animate().translationY(0f).setInterpolator(DecelerateInterpolator(2f))
331335
}
332336

333337
R.id.installed_menu_item -> {
@@ -346,6 +350,10 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis
346350
// set search view to cleared
347351
searchView.setQuery("", false)
348352
searchView.clearFocus()
353+
// reset reboot and search card
354+
searchCard.animate().translationY(0f).setInterpolator(DecelerateInterpolator(2f))
355+
.start()
356+
rebootFab.animate().translationY(0f).setInterpolator(DecelerateInterpolator(2f))
349357
}
350358
}
351359
true
@@ -712,6 +720,8 @@ class MainActivity : FoxActivity(), OnRefreshListener, SearchView.OnQueryTextLis
712720
progressIndicator!!.visibility = View.VISIBLE
713721
progressIndicator!!.setProgressCompat(0, false)
714722
swipeRefreshBlocker = System.currentTimeMillis() + 5000L
723+
724+
MainApplication.INSTANCE!!.repoModules.clear()
715725
// this.swipeRefreshLayout.setRefreshing(true); ??
716726
Thread({
717727
cleanDnsCache() // Allow DNS reload from network

app/src/main/kotlin/com/fox2code/mmm/NotificationType.kt

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import java.io.File
2929
import java.io.FileOutputStream
3030
import java.io.IOException
3131
import java.io.InputStreamReader
32+
import java.util.Date
3233
import java.util.zip.ZipFile
3334

3435

@@ -45,8 +46,27 @@ enum class NotificationType constructor(
4546
DEBUG(
4647
R.string.debug_build,
4748
R.drawable.ic_baseline_bug_report_24,
48-
com.google.android.material.R.attr.colorSecondary,
49-
com.google.android.material.R.attr.colorOnSecondary
49+
com.google.android.material.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary,
50+
// on click show a toast formatted with commit hash and build date, plus number of days before expiration (builds expire 30 days after build date)
51+
View.OnClickListener { v: View ->
52+
val buildTime = BuildConfig.BUILD_TIME
53+
val buildTimeDays = (System.currentTimeMillis() - buildTime) / 86400000
54+
// builddatepretty is created from build_time as YYYY-MM-DD
55+
val sdf = android.icu.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.US)
56+
val netDate = Date(buildTime)
57+
val buildDatePretty = sdf.format(netDate)
58+
val toastText = v.context.getString(
59+
R.string.debug_build_toast,
60+
BuildConfig.COMMIT_HASH,
61+
buildDatePretty,
62+
30 - buildTimeDays
63+
)
64+
Toast.makeText(
65+
v.context,
66+
toastText,
67+
Toast.LENGTH_LONG
68+
).show()
69+
}
5070
) {
5171
override fun shouldRemove(): Boolean {
5272
return !BuildConfig.DEBUG
@@ -56,7 +76,7 @@ enum class NotificationType constructor(
5676
@JvmStatic
5777
SHOWCASE_MODE(
5878
R.string.showcase_mode, R.drawable.ic_baseline_lock_24,
59-
androidx.appcompat.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary
79+
com.google.android.material.R.attr.colorPrimary, com.google.android.material.R.attr.colorOnPrimary
6080
) {
6181
override fun shouldRemove(): Boolean {
6282
return !MainApplication.isShowcaseMode
@@ -175,7 +195,7 @@ enum class NotificationType constructor(
175195
compatActivity.cacheDir,
176196
"installer" + File.separator + "module.zip"
177197
)
178-
IntentHelper.openFileTo(compatActivity, module, { d: File, u: Uri, s: Int ->
198+
IntentHelper.openFileTo(compatActivity, module) { d: File, u: Uri, s: Int ->
179199
if (s == IntentHelper.RESPONSE_FILE) {
180200
try {
181201
if (needPatch(d)) {
@@ -217,7 +237,7 @@ enum class NotificationType constructor(
217237
InstallerInitializer.peekMagiskPath() == null
218238
)
219239
}
220-
})
240+
}
221241
},
222242
false
223243
) {

app/src/main/kotlin/com/fox2code/mmm/manager/LocalModuleInfo.kt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
package com.fox2code.mmm.manager
66

7+
import com.fox2code.mmm.MainApplication
78
import com.fox2code.mmm.markdown.MarkdownUrlLinker.Companion.urlLinkify
8-
import com.fox2code.mmm.utils.FastException
9+
import com.fox2code.mmm.repo.RepoModule
910
import com.fox2code.mmm.utils.io.PropUtils
1011
import com.fox2code.mmm.utils.io.net.Http
1112
import org.json.JSONObject
@@ -24,6 +25,18 @@ class LocalModuleInfo(id: String?) : ModuleInfo(id!!) {
2425
var updateZipUrl: String? = null
2526
private var updateChangeLogUrl: String? = null
2627

28+
var remoteModuleInfo: RepoModule? = null
29+
get() {
30+
if (field == null) {
31+
try {
32+
field = MainApplication.INSTANCE!!.repoModules[id]
33+
} catch (e: IOException) {
34+
// ignore
35+
}
36+
}
37+
return field
38+
}
39+
2740
@JvmField
2841
var updateChangeLog = ""
2942

@@ -53,12 +66,20 @@ class LocalModuleInfo(id: String?) : ModuleInfo(id!!) {
5366
desc = desc.substring(0, 1000)
5467
}
5568
updateChangeLog = desc
56-
} catch (ioe: IOException) {
69+
} catch (ioe: Exception) {
5770
updateChangeLog = ""
71+
updateChecksum = null
72+
updateVersion = null
73+
updateVersionCode = Long.MIN_VALUE
5874
}
5975
updateChecksum = jsonUpdate.optString("checksum")
6076
val updateZipUrlForReals = updateZipUrl
61-
if (updateZipUrlForReals!!.isEmpty()) throw FastException.INSTANCE
77+
if (updateZipUrlForReals!!.isEmpty()) {
78+
updateVersion = null
79+
updateVersionCode = Long.MIN_VALUE
80+
updateZipUrl = null
81+
updateChangeLog = ""
82+
}
6283
updateVersion = PropUtils.shortenVersionName(
6384
updateZipUrlForReals.trim { it <= ' ' }, updateVersionCode
6485
)

app/src/main/kotlin/com/fox2code/mmm/module/ActionButtonType.kt

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package com.fox2code.mmm.module
66
import android.annotation.SuppressLint
77
import android.content.DialogInterface
88
import android.net.Uri
9+
import android.text.Html
910
import android.text.Spanned
1011
import android.widget.TextView
1112
import android.widget.Toast
@@ -382,6 +383,154 @@ enum class ActionButtonType {
382383
) { _: DialogInterface?, _: Int -> }
383384
.create().show()
384385
}
386+
},
387+
REMOTE {
388+
@Suppress("NAME_SHADOWING")
389+
override fun doAction(button: Chip, moduleHolder: ModuleHolder) {
390+
Timber.d("doAction: remote module for %s", moduleHolder.moduleInfo?.name ?: "null")
391+
// that module is from remote repo
392+
val name: String? = if (moduleHolder.moduleInfo != null) {
393+
moduleHolder.moduleInfo!!.name
394+
} else {
395+
moduleHolder.repoModule?.moduleInfo?.name
396+
}
397+
// positive button executes install logic and says reinstall. negative button does nothing
398+
TrackHelper.track().event("remote_module", name).with(INSTANCE!!.getTracker())
399+
val madb = MaterialAlertDialogBuilder(button.context)
400+
madb.setTitle(R.string.remote_module)
401+
val moduleInfo: ModuleInfo = if (moduleHolder.mainModuleInfo != null) {
402+
moduleHolder.mainModuleInfo
403+
} else {
404+
moduleHolder.repoModule?.moduleInfo ?: return
405+
}
406+
var updateZipUrl = moduleHolder.updateZipUrl
407+
if (updateZipUrl.isNullOrEmpty()) {
408+
// try repoModule.zipUrl
409+
val repoModule = moduleHolder.repoModule
410+
if (repoModule?.zipUrl.isNullOrEmpty()) {
411+
Timber.e("No repo update zip url for %s", moduleInfo.name)
412+
} else {
413+
updateZipUrl = repoModule?.zipUrl
414+
}
415+
// next try localModuleInfo.updateZipUrl
416+
if (updateZipUrl.isNullOrEmpty()) {
417+
val localModuleInfo = moduleHolder.moduleInfo
418+
if (localModuleInfo != null) {
419+
updateZipUrl = localModuleInfo.updateZipUrl
420+
} else {
421+
Timber.e("No local update zip url for %s", moduleInfo.name)
422+
}
423+
}
424+
if (updateZipUrl.isNullOrEmpty()) {
425+
Timber.e("No update zip url at all for %s", moduleInfo.name)
426+
// last ditch effort try moduleinfo
427+
updateZipUrl = moduleHolder.moduleInfo?.updateZipUrl
428+
}
429+
// LAST LAST ditch effort try localModuleInfo.remoteModuleInfo.zipUrl
430+
if (updateZipUrl.isNullOrEmpty()) {
431+
val localModuleInfo = moduleHolder.moduleInfo
432+
if (localModuleInfo != null) {
433+
updateZipUrl = localModuleInfo.remoteModuleInfo?.zipUrl
434+
} else {
435+
Timber.e("No local update zip url for %s", moduleInfo.name)
436+
}
437+
}
438+
}
439+
if (!updateZipUrl.isNullOrEmpty()) {
440+
madb.setMessage(Html.fromHtml(button.context.getString(R.string.remote_message, name), Html.FROM_HTML_MODE_COMPACT))
441+
madb.setPositiveButton(
442+
R.string.reinstall
443+
) { _: DialogInterface?, _: Int ->
444+
Timber.d("Set moduleinfo to %s", moduleInfo.name)
445+
val name: String? = if (moduleHolder.moduleInfo != null) {
446+
moduleHolder.moduleInfo!!.name
447+
} else {
448+
moduleHolder.repoModule?.moduleInfo?.name
449+
}
450+
Timber.d("doAction: remote module for %s", name)
451+
TrackHelper.track().event("view_update_install", name)
452+
.with(INSTANCE!!.getTracker())
453+
// Androidacy manage the selection between download and install
454+
if (isAndroidacyLink(updateZipUrl)) {
455+
Timber.d("Androidacy link detected")
456+
openUrlAndroidacy(
457+
button.context,
458+
updateZipUrl,
459+
true,
460+
moduleInfo.name,
461+
moduleInfo.config
462+
)
463+
return@setPositiveButton
464+
}
465+
val hasRoot = peekMagiskPath() != null && !isShowcaseMode
466+
val builder = MaterialAlertDialogBuilder(button.context)
467+
builder.setTitle(moduleInfo.name).setCancelable(true)
468+
.setIcon(R.drawable.ic_baseline_extension_24)
469+
var desc: CharSequence? = moduleInfo.description
470+
var markwon: Markwon? = null
471+
val localModuleInfo = moduleHolder.moduleInfo
472+
if (localModuleInfo != null && localModuleInfo.updateChangeLog.isNotEmpty()) {
473+
markwon = INSTANCE!!.getMarkwon()
474+
// Re-render each time in cse of config changes
475+
desc = markwon!!.toMarkdown(localModuleInfo.updateChangeLog)
476+
}
477+
if (desc.isNullOrEmpty()) {
478+
builder.setMessage(R.string.no_desc_found)
479+
} else {
480+
builder.setMessage(desc)
481+
}
482+
Timber.i("URL: %s", updateZipUrl)
483+
builder.setNegativeButton(R.string.download_module) { _: DialogInterface?, _: Int ->
484+
openCustomTab(
485+
button.context,
486+
updateZipUrl
487+
)
488+
}
489+
if (hasRoot) {
490+
builder.setPositiveButton(if (moduleHolder.hasUpdate()) R.string.update_module else R.string.install_module) { _: DialogInterface?, _: Int ->
491+
val updateZipChecksum = moduleHolder.updateZipChecksum
492+
openInstaller(
493+
button.context,
494+
updateZipUrl,
495+
moduleInfo.name,
496+
moduleInfo.config,
497+
updateZipChecksum,
498+
moduleInfo.mmtReborn
499+
)
500+
}
501+
}
502+
ExternalHelper.INSTANCE.injectButton(
503+
builder,
504+
{ Uri.parse(updateZipUrl) },
505+
moduleHolder.updateZipRepo
506+
)
507+
val dim5dp = FoxDisplay.dpToPixel(5f)
508+
builder.setBackgroundInsetStart(dim5dp).setBackgroundInsetEnd(dim5dp)
509+
val alertDialog = builder.show()
510+
for (i in -3..-1) {
511+
val alertButton = alertDialog.getButton(i)
512+
if (alertButton != null && alertButton.paddingStart > dim5dp) {
513+
alertButton.setPadding(dim5dp, dim5dp, dim5dp, dim5dp)
514+
}
515+
}
516+
if (markwon != null) {
517+
val messageView =
518+
alertDialog.window!!.findViewById<TextView>(android.R.id.message)
519+
markwon.setParsedMarkdown(messageView, (desc as Spanned?)!!)
520+
}
521+
}
522+
} else {
523+
madb.setMessage(button.context.getString(R.string.remote_message_no_update, name))
524+
}
525+
madb.setNegativeButton(R.string.cancel, null)
526+
madb.create().show()
527+
}
528+
529+
override fun update(button: Chip, moduleHolder: ModuleHolder) {
530+
val icon: Int = R.drawable.baseline_cloud_download_24
531+
button.chipIcon = button.context.getDrawable(icon)
532+
button.setText(R.string.online)
533+
}
385534
};
386535

387536
@DrawableRes

0 commit comments

Comments
 (0)