Release 0.0.3

- Improved non standard file picker response handling.
  (Should fix install module from storage on some devices,
  and notifying the user that their file manager is weird)
- Handle file picker returning http/https urls for files.
- Improved search icon padding for rounded corner phones
- Fixed card background being invisible on light theme
- Make install terminal light when light theme is on
- Added a switch to force the terminal to be always dark
 (to restore old behavior, default is false)
pull/1/head 0.0.3
Fox2Code 3 years ago
parent 1bc08e6ec5
commit 6a608ffbea

@ -10,8 +10,8 @@ android {
applicationId "com.fox2code.mmm"
minSdk 21
targetSdk 30
versionCode 2
versionName "0.0.2"
versionCode 3
versionName "0.0.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

@ -46,6 +46,12 @@
int d(java.lang.String, java.lang.String);
int d(java.lang.String, java.lang.String, java.lang.Throwable);
}
-assumenosideeffects class androidx.loader.app.LoaderManager {
static void enableDebugLogging(boolean);
}
-assumevalues class androidx.loader.app.LoaderManagerImpl {
static boolean DEBUG return false;
}
# This is just some proguard rules testes, might do a separate lib after
# Made to help optimise the libraries and not the app directly

@ -1,5 +1,6 @@
package com.fox2code.mmm;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Intent;
import android.content.SharedPreferences;
@ -70,6 +71,10 @@ public class MainApplication extends Application implements CompatActivity.Appli
return getSharedPreferences().getBoolean("pref_show_incompatible", false);
}
public static boolean isForceDarkTerminal() {
return getSharedPreferences().getBoolean("pref_force_dark_terminal", false);
}
public static boolean hasGottenRootAccess() {
return getSharedPreferences().getBoolean("has_root_access", false);
}
@ -118,6 +123,23 @@ public class MainApplication extends Application implements CompatActivity.Appli
return managerThemeResId;
}
@SuppressLint("NonConstantResourceId")
public boolean isLightTheme() {
switch (this.managerThemeResId) {
case R.style.Theme_MagiskModuleManager:
return (this.getResources().getConfiguration().uiMode
& Configuration.UI_MODE_NIGHT_MASK)
!= Configuration.UI_MODE_NIGHT_YES;
case R.style.Theme_MagiskModuleManager_Light:
return true;
case R.style.Theme_MagiskModuleManager_Dark:
return false;
default:
throw new IllegalStateException("Non manager theme!");
}
}
@Override
public void onCreate() {
INSTANCE = this;

@ -2,6 +2,7 @@ package com.fox2code.mmm;
import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
@ -11,6 +12,8 @@ import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
@ -250,7 +253,10 @@ public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdap
Resources.Theme theme = this.cardView.getContext().getTheme();
TypedValue value = new TypedValue();
theme.resolveAttribute(backgroundAttr, value, true);
this.cardView.setCardBackgroundColor(value.data);
@ColorInt int color = value.data;
// Fix card background being invisible on light theme
if (color == Color.WHITE) color = 0xFFF8F8F8;
this.cardView.setCardBackgroundColor(color);
} else {
this.cardView.setBackground(null);
}

@ -56,8 +56,8 @@ public enum NotificationType implements NotificationTypeCst {
CompatActivity compatActivity = CompatActivity.getCompatActivity(v);
final File module = new File(compatActivity.getCacheDir(),
"installer" + File.separator + "module.zip");
IntentHelper.openFileTo(compatActivity, module, (d, s) -> {
if (s) {
IntentHelper.openFileTo(compatActivity, module, (d, u, s) -> {
if (s == IntentHelper.RESPONSE_FILE) {
try {
boolean needPatch;
try (ZipFile zipFile = new ZipFile(d)) {
@ -86,6 +86,10 @@ public enum NotificationType implements NotificationTypeCst {
Toast.makeText(compatActivity,
R.string.invalid_format, Toast.LENGTH_SHORT).show();
}
} else if (s == IntentHelper.RESPONSE_URL) {
IntentHelper.openInstaller(compatActivity, u.toString(),
compatActivity.getString(
R.string.remote_install_title), null);
}
});
}, true) {

@ -2,6 +2,8 @@ package com.fox2code.mmm.installer;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
@ -40,9 +42,9 @@ public class InstallerActivity extends CompatActivity {
this.moduleCache = new File(this.getCacheDir(), "installer");
if (!this.moduleCache.exists() && !this.moduleCache.mkdirs())
Log.e(TAG, "Failed to mkdir module cache dir!");
super.onCreate(savedInstanceState);
this.setDisplayHomeAsUpEnabled(false);
this.setOnBackPressedCallback(DISABLE_BACK_BUTTON);
super.onCreate(savedInstanceState);
final Intent intent = this.getIntent();
final String target;
final String name;
@ -64,8 +66,21 @@ public class InstallerActivity extends CompatActivity {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setTitle(name);
setContentView(R.layout.installer);
int background;
int foreground;
if (MainApplication.getINSTANCE().isLightTheme() &&
!MainApplication.isForceDarkTerminal()) {
background = Color.WHITE;
foreground = Color.BLACK;
} else {
background = Color.BLACK;
foreground = Color.WHITE;
}
findViewById(R.id.install_horizontal_scroller)
.setBackground(new ColorDrawable(background));
this.progressIndicator = findViewById(R.id.progress_bar);
this.installerTerminal = new InstallerTerminal(findViewById(R.id.install_terminal));
this.installerTerminal = new InstallerTerminal(
findViewById(R.id.install_terminal), foreground);
this.progressIndicator.setVisibility(View.GONE);
this.progressIndicator.setIndeterminate(true);
if (urlMode) {

@ -16,21 +16,21 @@ public class InstallerTerminal extends RecyclerView.Adapter<InstallerTerminal.Te
private final RecyclerView recyclerView;
private final ArrayList<String> terminal;
private final Object lock = new Object();
private final int foreground;
public InstallerTerminal(RecyclerView recyclerView) {
public InstallerTerminal(RecyclerView recyclerView,int foreground) {
recyclerView.setLayoutManager(
new LinearLayoutManager(recyclerView.getContext()));
this.recyclerView = recyclerView;
this.foreground = foreground;
this.terminal = new ArrayList<>();
this.recyclerView.setBackground(
new ColorDrawable(Color.BLACK));
this.recyclerView.setAdapter(this);
}
@NonNull
@Override
public TextViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new TextViewHolder(new TextView(parent.getContext()));
return new TextViewHolder(new TextView(parent.getContext()), this.foreground);
}
@Override
@ -116,11 +116,11 @@ public class InstallerTerminal extends RecyclerView.Adapter<InstallerTerminal.Te
public static class TextViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
public TextViewHolder(@NonNull TextView itemView) {
public TextViewHolder(@NonNull TextView itemView,int foreground) {
super(itemView);
this.textView = itemView;
itemView.setTypeface(Typeface.MONOSPACE);
itemView.setTextColor(Color.WHITE);
itemView.setTextColor(foreground);
itemView.setTextSize(12);
itemView.setLines(1);
itemView.setText(" ");

@ -4,6 +4,7 @@ import android.os.Bundle;
import androidx.annotation.StyleRes;
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
@ -14,6 +15,7 @@ import com.fox2code.mmm.repo.RepoData;
import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.utils.IntentHelper;
import com.mikepenz.aboutlibraries.LibsBuilder;
import com.topjohnwu.superuser.internal.UiThreadHandler;
public class SettingsActivity extends CompatActivity {
@Override
@ -37,7 +39,9 @@ public class SettingsActivity extends CompatActivity {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getPreferenceManager().setSharedPreferencesName("mmm");
setPreferencesFromResource(R.xml.root_preferences, rootKey);
findPreference("pref_theme").setOnPreferenceChangeListener((preference, newValue) -> {
ListPreference themePreference = findPreference("pref_theme");
themePreference.setSummaryProvider(p -> themePreference.getEntry());
themePreference.setOnPreferenceChangeListener((preference, newValue) -> {
@StyleRes int themeResId;
switch (String.valueOf(newValue)) {
default:
@ -55,6 +59,9 @@ public class SettingsActivity extends CompatActivity {
CompatActivity.getCompatActivity(this).setThemeRecreate(themeResId);
return true;
});
if ("dark".equals(themePreference.getValue())) {
findPreference("pref_force_dark_terminal").setEnabled(false);
}
setRepoNameResolution("pref_repo_main", RepoManager.MAGISK_REPO,
"Magisk Modules Repo (Official)", RepoManager.MAGISK_REPO_HOMEPAGE);

@ -1,13 +1,16 @@
package com.fox2code.mmm.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
@ -15,12 +18,16 @@ import androidx.core.app.ActivityOptionsCompat;
import com.fox2code.mmm.Constants;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.R;
import com.fox2code.mmm.compat.CompatActivity;
import com.fox2code.mmm.installer.InstallerActivity;
import com.fox2code.mmm.markdown.MarkdownActivity;
import com.topjohnwu.superuser.io.SuFileInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -144,50 +151,78 @@ public class IntentHelper {
return (Activity) context;
}
public static final int RESPONSE_ERROR = 0;
public static final int RESPONSE_FILE = 1;
public static final int RESPONSE_URL = 2;
@SuppressLint("SdCardPath")
public static void openFileTo(CompatActivity compatActivity, File destination,
OnFileReceivedCallback callback) {
OnFileReceivedCallback callback) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT).setType("application/zip");
intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, false);
intent.addCategory(Intent.CATEGORY_OPENABLE);
Bundle param = ActivityOptionsCompat.makeCustomAnimation(compatActivity,
android.R.anim.fade_in, android.R.anim.fade_out).toBundle();
compatActivity.startActivityForResult(intent, param, (result, data) -> {
String name = destination.getName();
if (data == null || result != Activity.RESULT_OK) {
callback.onReceived(destination, false);
Uri uri = data == null ? null : data.getData();
if (uri == null || (result == Activity.RESULT_CANCELED && !((
ContentResolver.SCHEME_FILE.equals(uri.getScheme())
&& uri.getPath() != null &&
(uri.getPath().startsWith("/sdcard/") ||
uri.getPath().startsWith("/data/"))
) || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())))) {
callback.onReceived(destination, null, RESPONSE_ERROR);
return;
}
Uri uri = data.getData();
if (uri == null || "http".equals(uri.getScheme()) ||
Log.d("IntentHelper", "FilePicker returned " + uri.toString());
if ("http".equals(uri.getScheme()) ||
"https".equals(uri.getScheme())) {
callback.onReceived(destination, false);
callback.onReceived(destination, uri, RESPONSE_URL);
return;
}
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme()) ||
(result != Activity.RESULT_OK && result != Activity.RESULT_FIRST_USER)) {
Toast.makeText(compatActivity,
R.string.file_picker_wierd,
Toast.LENGTH_SHORT).show();
}
InputStream inputStream = null;
OutputStream outputStream = null;
boolean success = false;
try {
inputStream = compatActivity.getContentResolver()
.openInputStream(uri);
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
String path = uri.getPath();
if (path.startsWith("/sdcard/")) { // Fix file paths
path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + path.substring(7);
}
inputStream = SuFileInputStream.open(
new File(path).getAbsoluteFile());
} else {
inputStream = compatActivity.getContentResolver()
.openInputStream(uri);
}
outputStream = new FileOutputStream(destination);
Files.copy(inputStream, outputStream);
String newName = uri.getLastPathSegment();
if (newName.endsWith(".zip")) name = newName;
success = true;
} catch (Exception e) {
Log.e("IntentHelper", "fail copy", e);
Toast.makeText(compatActivity,
R.string.file_picker_failure,
Toast.LENGTH_SHORT).show();
} finally {
Files.closeSilently(inputStream);
Files.closeSilently(outputStream);
if (!success && destination.exists() && !destination.delete())
Log.e("IntentHelper", "Failed to delete artefact!");
}
callback.onReceived(destination, success);
callback.onReceived(destination, uri, success ? RESPONSE_FILE : RESPONSE_ERROR);
});
}
public interface OnFileReceivedCallback {
void onReceived(File target,boolean success);
void onReceived(File target,Uri uri,int response);
}
}

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M3,13h2v-2L3,11v2zM3,17h2v-2L3,15v2zM3,9h2L5,7L3,7v2zM7,13h14v-2L7,11v2zM7,17h14v-2L7,15v2zM7,7v2h14L21,7L7,7z"/>
</vector>

@ -35,8 +35,8 @@
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:gravity="center_vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

@ -8,6 +8,7 @@
<HorizontalScrollView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/install_horizontal_scroller"
android:background="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@ -15,6 +16,7 @@
app:layout_constraintTop_toTopOf="parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/install_terminal"
android:background="@null"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp" />

@ -8,7 +8,8 @@
android:layout_marginRight="8dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:gravity="center_vertical">
android:gravity="center_vertical"
android:background="@null">
<androidx.cardview.widget.CardView
android:id="@+id/card_view"
android:layout_gravity="center"

@ -37,4 +37,8 @@
<string name="source_code">Source code</string>
<string name="last_updated">Last update:</string>
<string name="magisk_builtin_module">Magisk builtin module</string>
<string name="force_dark_terminal_title">Force dark mode terminal</string>
<string name="file_picker_failure">Your current file picker failed to give access to the file.</string>
<string name="remote_install_title">Remote install</string>
<string name="file_picker_wierd">Your file picker returned a non standard response.</string>
</resources>

@ -1,5 +1,8 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.MagiskModuleManager.Light" parent="Theme.MaterialComponents.Light.DarkActionBar">
<item name="android:isLightTheme"
tools:targetApi="q">true</item>
<item name="isLightTheme">true</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
@ -22,6 +25,9 @@
<!-- Base application theme. -->
<style name="Theme.MagiskModuleManager.Dark" parent="Theme.MaterialComponents">
<item name="android:isLightTheme"
tools:targetApi="q">false</item>
<item name="isLightTheme">false</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>

@ -10,6 +10,12 @@
app:entries="@array/theme_values_names"
app:entryValues="@array/theme_values" />
<SwitchPreferenceCompat
app:defaultValue="false"
app:key="pref_force_dark_terminal"
app:icon="@drawable/ic_baseline_list_24"
app:title="@string/force_dark_terminal_title" />
<SwitchPreferenceCompat
app:defaultValue="false"
app:key="pref_showcase_mode"

@ -7,7 +7,7 @@ buildscript {
}
project.ext.latestAboutLibsRelease = "8.9.3"
dependencies {
classpath "com.android.tools.build:gradle:7.0.2"
classpath "com.android.tools.build:gradle:7.0.3"
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}"
// NOTE: Do not place your application dependencies here; they belong

Loading…
Cancel
Save