mirror of
https://github.com/Hamza417/Inure.git
synced 2026-03-13 10:19:43 +08:00
Build41
- Fixed a few UI and animation issues.
This commit is contained in:
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@@ -12,7 +12,6 @@
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/hidden-api" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
|
||||
@@ -134,6 +134,7 @@ dependencies {
|
||||
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
|
||||
implementation "com.github.topjohnwu.libsu:service:${libsuVersion}"
|
||||
implementation "com.github.topjohnwu.libsu:nio:${libsuVersion}"
|
||||
implementation 'eu.chainfire:libsuperuser:1.1.1'
|
||||
|
||||
// Room
|
||||
implementation "androidx.room:room-ktx:2.4.3"
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
<ul>
|
||||
<li>Added <i>Legacy</i> transitions back to reuse the old code base.</li>
|
||||
<li>Implemented <i>Usage Stats</i> <b>App Info </b>panel.</li>
|
||||
<li>Added framework for reading other app's shared preference files (root).</li>
|
||||
</ul>
|
||||
|
||||
<h4>Bug Fixes</h4>
|
||||
|
||||
<ul>
|
||||
<li>Fixed a few UI issues.</li>
|
||||
<li>Fixed a few animation issues.</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
@@ -33,5 +33,4 @@ public class AppOps {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package app.simple.inure.apk.sharedPrefs;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import eu.chainfire.libsuperuser.Shell;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static final String TAG = Utils.class.getSimpleName();
|
||||
private static final String FAVORITES_KEY = "FAVORITES_KEY";
|
||||
private static final String VERSION_CODE_KEY = "VERSION_CODE";
|
||||
public static final String BACKUP_PREFIX = "BACKUP_";
|
||||
private static final String TAG_ROOT_DIALOG = "RootDialog";
|
||||
private static final String PREF_SHOW_SYSTEM_APPS = "SHOW_SYSTEM_APPS";
|
||||
public static final String CMD_FIND_XML_FILES = "find /data/data/%s -type f -name \\*.xml";
|
||||
public static final String CMD_CHOWN = "chown %s.%s \"%s\"";
|
||||
public static final String CMD_CAT_FILE = "cat \"%s\"";
|
||||
public static final String CMD_CP = "cp \"%s\" \"%s\"";
|
||||
public static final String TMP_FILE = ".temp";
|
||||
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
|
||||
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
private static final String PACKAGE_NAME_PATTERN = "^[a-zA-Z_$][\\w$]*(?:\\.[a-zA-Z_$][\\w$]*)*$";
|
||||
|
||||
public static List <String> findXmlFiles(final String packageName) throws Shell.ShellDiedException {
|
||||
Log.d(TAG, String.format("findXmlFiles(%s)", packageName));
|
||||
List <String> files = Shell.Pool.SU.run(String.format(CMD_FIND_XML_FILES, packageName));
|
||||
Log.d(TAG, "files: " + Arrays.toString(files.toArray()));
|
||||
return files;
|
||||
}
|
||||
}
|
||||
@@ -120,6 +120,7 @@ object PreferencesSearchConstants {
|
||||
|
||||
private val developmentData = arrayListOf(
|
||||
PreferenceSearchModel(R.drawable.ic_main_app_icon_regular, R.string.setup, R.string.desc_not_available, none, none, development),
|
||||
PreferenceSearchModel(R.drawable.ic_app_icon_preferences, R.string.preferences, R.string.desc_not_available, none, none, development),
|
||||
PreferenceSearchModel(R.drawable.ic_code, R.string.use_webview_xml_viewer, R.string.desc_not_available, toggleable, none, development),
|
||||
PreferenceSearchModel(R.drawable.ic_preference_indicators, R.string.hide_preferences_indicators, R.string.desc_not_available, none, none, development),
|
||||
)
|
||||
|
||||
@@ -25,17 +25,19 @@ public class DynamicCornerEditText extends TypeFaceEditText {
|
||||
}
|
||||
|
||||
private void setProps(AttributeSet attrs) {
|
||||
setFocusableInTouchMode(true);
|
||||
setFocusable(true);
|
||||
setSaveEnabled(true);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);
|
||||
if (!isInEditMode()) {
|
||||
setFocusableInTouchMode(true);
|
||||
setFocusable(true);
|
||||
setSaveEnabled(true);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);
|
||||
}
|
||||
|
||||
LayoutBackground.setBackground(getContext(), this, attrs, 2F);
|
||||
setBackground(false, ThemeManager.INSTANCE.getTheme().getViewGroupTheme().getViewerBackground());
|
||||
ViewUtils.INSTANCE.addShadow(this);
|
||||
}
|
||||
|
||||
LayoutBackground.setBackground(getContext(), this, attrs, 2F);
|
||||
setBackground(false, ThemeManager.INSTANCE.getTheme().getViewGroupTheme().getViewerBackground());
|
||||
ViewUtils.INSTANCE.addShadow(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@ import app.simple.inure.decorations.overscroll.RecyclerViewConstants.overScrollR
|
||||
import app.simple.inure.decorations.overscroll.RecyclerViewConstants.overScrollTranslationMagnitude
|
||||
import app.simple.inure.preferences.AccessibilityPreferences
|
||||
import app.simple.inure.themes.manager.ThemeManager
|
||||
import app.simple.inure.util.ConditionUtils.invert
|
||||
import app.simple.inure.util.StatusBarHeight
|
||||
|
||||
/**
|
||||
@@ -31,8 +32,12 @@ class CustomHorizontalRecyclerView(context: Context, attrs: AttributeSet?) : Rec
|
||||
}
|
||||
|
||||
isLandscape = StatusBarHeight.isLandscape(context)
|
||||
if (AccessibilityPreferences.isAnimationReduced())
|
||||
layoutAnimation = null
|
||||
|
||||
if (isInEditMode.invert()) {
|
||||
if (AccessibilityPreferences.isAnimationReduced()) {
|
||||
layoutAnimation = null
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
recycle()
|
||||
}
|
||||
@@ -46,15 +51,17 @@ class CustomHorizontalRecyclerView(context: Context, attrs: AttributeSet?) : Rec
|
||||
|
||||
setHasFixedSize(true)
|
||||
|
||||
if (AccessibilityPreferences.isDividerEnabled()) {
|
||||
val divider = DividerItemDecoration(context, DividerItemDecoration.HORIZONTAL)
|
||||
if (isInEditMode.invert()) {
|
||||
if (AccessibilityPreferences.isDividerEnabled()) {
|
||||
val divider = DividerItemDecoration(context, DividerItemDecoration.HORIZONTAL)
|
||||
|
||||
divider.setDrawable(ShapeDrawable().apply {
|
||||
intrinsicHeight = 1
|
||||
paint.color = ThemeManager.theme.viewGroupTheme.dividerBackground
|
||||
})
|
||||
divider.setDrawable(ShapeDrawable().apply {
|
||||
intrinsicHeight = 1
|
||||
paint.color = ThemeManager.theme.viewGroupTheme.dividerBackground
|
||||
})
|
||||
|
||||
addItemDecoration(divider)
|
||||
addItemDecoration(divider)
|
||||
}
|
||||
}
|
||||
|
||||
this.edgeEffectFactory = object : RecyclerView.EdgeEffectFactory() {
|
||||
@@ -129,8 +136,11 @@ class CustomHorizontalRecyclerView(context: Context, attrs: AttributeSet?) : Rec
|
||||
override fun setAdapter(adapter: Adapter<*>?) {
|
||||
super.setAdapter(adapter)
|
||||
adapter?.stateRestorationPolicy = Adapter.StateRestorationPolicy.ALLOW
|
||||
if (!AccessibilityPreferences.isAnimationReduced())
|
||||
scheduleLayoutAnimation()
|
||||
if (isInEditMode.invert()) {
|
||||
if (!AccessibilityPreferences.isAnimationReduced()) {
|
||||
scheduleLayoutAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T : HorizontalListViewHolder> RecyclerView.forEachVisibleHolder(action: (T) -> Unit) {
|
||||
|
||||
@@ -92,7 +92,9 @@ public class DynamicRippleLinearLayoutWithFactor extends LinearLayout implements
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
ThemeManager.INSTANCE.addListener(this);
|
||||
app.simple.inure.preferences.SharedPreferences.INSTANCE.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
if (!isInEditMode()) {
|
||||
app.simple.inure.preferences.SharedPreferences.INSTANCE.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -117,10 +117,23 @@ open class BaseActivity : AppCompatActivity(), ThemeChangedListener, android.con
|
||||
enterTransition = MaterialElevationScale(true)
|
||||
reenterTransition = MaterialElevationScale(false)
|
||||
}
|
||||
PopupTransitionType.SHARED_AXIS -> {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
PopupTransitionType.SHARED_AXIS_X -> {
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
}
|
||||
PopupTransitionType.SHARED_AXIS_Y -> {
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, true)
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Y, true)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
|
||||
}
|
||||
PopupTransitionType.SHARED_AXIS_Z -> {
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
}
|
||||
PopupTransitionType.THROUGH -> {
|
||||
exitTransition = MaterialFadeThrough()
|
||||
|
||||
@@ -143,21 +143,37 @@ abstract class ScopedFragment : Fragment(), SharedPreferences.OnSharedPreference
|
||||
PopupTransitionType.FADE -> {
|
||||
exitTransition = Fade()
|
||||
enterTransition = Fade()
|
||||
returnTransition = Fade()
|
||||
reenterTransition = Fade()
|
||||
}
|
||||
PopupTransitionType.ELEVATION -> {
|
||||
exitTransition = MaterialElevationScale(false)
|
||||
enterTransition = MaterialElevationScale(true)
|
||||
reenterTransition = MaterialElevationScale(false)
|
||||
exitTransition = MaterialElevationScale(false)
|
||||
returnTransition = MaterialElevationScale(false)
|
||||
reenterTransition = MaterialElevationScale(true)
|
||||
}
|
||||
PopupTransitionType.SHARED_AXIS -> {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
PopupTransitionType.SHARED_AXIS_X -> {
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||
}
|
||||
PopupTransitionType.SHARED_AXIS_Y -> {
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, true)
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Y, true)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
|
||||
}
|
||||
PopupTransitionType.SHARED_AXIS_Z -> {
|
||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||
}
|
||||
PopupTransitionType.THROUGH -> {
|
||||
exitTransition = MaterialFadeThrough()
|
||||
enterTransition = MaterialFadeThrough()
|
||||
returnTransition = MaterialFadeThrough()
|
||||
reenterTransition = MaterialFadeThrough()
|
||||
}
|
||||
}
|
||||
|
||||
182
app/src/main/java/app/simple/inure/models/AppEntry.java
Normal file
182
app/src/main/java/app/simple/inure/models/AppEntry.java
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Simon Marquis (http://www.simon-marquis.fr)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package app.simple.inure.models;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import app.simple.inure.apk.sharedPrefs.Utils;
|
||||
|
||||
public class AppEntry {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final ApplicationInfo mInfo;
|
||||
/**
|
||||
* File of the application
|
||||
*/
|
||||
private final File mApkFile;
|
||||
/**
|
||||
* Label of the application
|
||||
*/
|
||||
private String mLabel;
|
||||
/**
|
||||
* Value used to sort the list of applications
|
||||
*/
|
||||
private String mSortingValue;
|
||||
/**
|
||||
* Detect if app is starred by user
|
||||
*/
|
||||
private boolean isFavorite;
|
||||
/**
|
||||
* Char value used by indexed ListView
|
||||
*/
|
||||
private char headerChar;
|
||||
/**
|
||||
* Uri of the app icon
|
||||
*/
|
||||
private Uri mIconUri;
|
||||
|
||||
public AppEntry(ApplicationInfo info, Context context) {
|
||||
mInfo = info;
|
||||
isFavorite = Utils.isFavorite(mInfo.packageName, context);
|
||||
mApkFile = new File(info.sourceDir);
|
||||
loadLabels(context);
|
||||
buildIconUri(mInfo);
|
||||
}
|
||||
|
||||
public ApplicationInfo getApplicationInfo() {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String getSortingValue() {
|
||||
return mSortingValue;
|
||||
}
|
||||
|
||||
private void buildIconUri(ApplicationInfo info) {
|
||||
Uri.Builder builder = new Uri.Builder();
|
||||
builder.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE);
|
||||
builder.authority(info.packageName);
|
||||
builder.appendPath(Integer.toString(info.icon));
|
||||
mIconUri = builder.build();
|
||||
}
|
||||
|
||||
public Uri getIconUri() {
|
||||
return mIconUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public void setFavorite(boolean isFavorite) {
|
||||
this.isFavorite = isFavorite;
|
||||
// IMPORTANT! also update the char used for sorting
|
||||
mSortingValue = (isFavorite ? " " : "") + mLabel;
|
||||
headerChar = formatChar(mLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the labels
|
||||
*
|
||||
* @param ctx .
|
||||
*/
|
||||
private void loadLabels(Context ctx) {
|
||||
if (mLabel == null) {
|
||||
if (!mApkFile.exists()) {
|
||||
mLabel = mInfo.packageName;
|
||||
} else {
|
||||
PackageManager pm = ctx.getPackageManager();
|
||||
CharSequence label = null;
|
||||
if (pm != null) {
|
||||
label = mInfo.loadLabel(pm);
|
||||
}
|
||||
mLabel = label != null ? label.toString() : mInfo.packageName;
|
||||
}
|
||||
|
||||
// replace false spaces O_o
|
||||
mLabel = mLabel.replaceAll("\\s", " ");
|
||||
}
|
||||
|
||||
if (mSortingValue == null) {
|
||||
mSortingValue = (isFavorite ? " " : "") + mLabel;
|
||||
}
|
||||
|
||||
headerChar = formatChar(mLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a char from a string to index the entry
|
||||
*
|
||||
* @param s .
|
||||
* @return .
|
||||
*/
|
||||
private char formatChar(String s) {
|
||||
if (isFavorite) {
|
||||
return '☆';
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(s)) {
|
||||
return '#';
|
||||
}
|
||||
|
||||
char c = Character.toUpperCase(s.charAt(0));
|
||||
|
||||
// Number
|
||||
if (c >= '0' && c <= '9') {
|
||||
return '#';
|
||||
}
|
||||
|
||||
// Letter
|
||||
if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
|
||||
return c;
|
||||
}
|
||||
|
||||
// Accented letter
|
||||
switch (c) {
|
||||
case 'À':
|
||||
case 'Á':
|
||||
case 'Â':
|
||||
case 'Ã':
|
||||
case 'Ä':
|
||||
return 'A';
|
||||
case 'É':
|
||||
case 'È':
|
||||
case 'Ê':
|
||||
case 'Ë':
|
||||
return 'E';
|
||||
}
|
||||
|
||||
// Everything else
|
||||
return '#';
|
||||
}
|
||||
|
||||
public char getHeaderChar() {
|
||||
return headerChar;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@ class PopupTransitionType(view: View) : BasePopupWindow() {
|
||||
|
||||
private val fade: DynamicRippleTextView
|
||||
private val elevation: DynamicRippleTextView
|
||||
private val sharedAxis: DynamicRippleTextView
|
||||
private val sharedAxisX: DynamicRippleTextView
|
||||
private val sharedAxisY: DynamicRippleTextView
|
||||
private val sharedAxisZ: DynamicRippleTextView
|
||||
private val through: DynamicRippleTextView
|
||||
|
||||
init {
|
||||
@@ -21,18 +23,28 @@ class PopupTransitionType(view: View) : BasePopupWindow() {
|
||||
|
||||
fade = contentView.findViewById(R.id.popup_fade)
|
||||
elevation = contentView.findViewById(R.id.popup_elevation)
|
||||
sharedAxis = contentView.findViewById(R.id.popup_shared_axis)
|
||||
sharedAxisX = contentView.findViewById(R.id.popup_shared_axis_x)
|
||||
sharedAxisY = contentView.findViewById(R.id.popup_shared_axis_y)
|
||||
sharedAxisZ = contentView.findViewById(R.id.popup_shared_axis_z)
|
||||
through = contentView.findViewById(R.id.popup_through)
|
||||
|
||||
sharedAxisX.text = contentView.context.getString(R.string.shared_axis, "X")
|
||||
sharedAxisY.text = contentView.context.getString(R.string.shared_axis, "Y")
|
||||
sharedAxisZ.text = contentView.context.getString(R.string.shared_axis, "Z")
|
||||
|
||||
fade.onClick(FADE)
|
||||
elevation.onClick(ELEVATION)
|
||||
sharedAxis.onClick(SHARED_AXIS)
|
||||
sharedAxisX.onClick(SHARED_AXIS_X)
|
||||
sharedAxisY.onClick(SHARED_AXIS_Y)
|
||||
sharedAxisZ.onClick(SHARED_AXIS_Z)
|
||||
through.onClick(THROUGH)
|
||||
|
||||
when (BehaviourPreferences.getTransitionType()) {
|
||||
FADE -> fade.isSelected = true
|
||||
ELEVATION -> elevation.isSelected = true
|
||||
SHARED_AXIS -> sharedAxis.isSelected = true
|
||||
SHARED_AXIS_X -> sharedAxisX.isSelected = true
|
||||
SHARED_AXIS_Y -> sharedAxisY.isSelected = true
|
||||
SHARED_AXIS_Z -> sharedAxisZ.isSelected = true
|
||||
THROUGH -> through.isSelected = true
|
||||
}
|
||||
|
||||
@@ -49,7 +61,9 @@ class PopupTransitionType(view: View) : BasePopupWindow() {
|
||||
companion object {
|
||||
const val FADE = 0
|
||||
const val ELEVATION = 1
|
||||
const val SHARED_AXIS = 2
|
||||
const val THROUGH = 3
|
||||
const val SHARED_AXIS_X = 2
|
||||
const val SHARED_AXIS_Y = 3
|
||||
const val SHARED_AXIS_Z = 4
|
||||
const val THROUGH = 5
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ object BehaviourPreferences {
|
||||
private const val marquee = "is_marquee_on"
|
||||
private const val skipLoading = "skip_main_loading_screen"
|
||||
|
||||
const val transitionType = "transition_type"
|
||||
const val transitionType = "panel_transition_type"
|
||||
const val arcType = "arc_type"
|
||||
const val stiffness = "scrolling_stiffness"
|
||||
const val dampingRatio = "scrolling_damping_ratio"
|
||||
|
||||
@@ -57,7 +57,6 @@ class Preferences : SearchBarScopedFragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
startPostponedEnterTransition()
|
||||
|
||||
preferencesViewModel.getPreferences().observe(viewLifecycleOwner) {
|
||||
|
||||
@@ -110,7 +110,9 @@ class BehaviourScreen : ScopedFragment() {
|
||||
transitionType.text = when (BehaviourPreferences.getTransitionType()) {
|
||||
PopupTransitionType.FADE -> getString(R.string.fade)
|
||||
PopupTransitionType.ELEVATION -> getString(R.string.elevation)
|
||||
PopupTransitionType.SHARED_AXIS -> getString(R.string.shared_axis)
|
||||
PopupTransitionType.SHARED_AXIS_X -> getString(R.string.shared_axis, "X")
|
||||
PopupTransitionType.SHARED_AXIS_Y -> getString(R.string.shared_axis, "Y")
|
||||
PopupTransitionType.SHARED_AXIS_Z -> getString(R.string.shared_axis, "Z")
|
||||
PopupTransitionType.THROUGH -> getString(R.string.through)
|
||||
else -> getString(R.string.unknown)
|
||||
}
|
||||
|
||||
@@ -129,37 +129,4 @@ object FileUtils {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun removeLastPathSegment(uri: Uri): Uri? {
|
||||
var strValue = uri.path
|
||||
if (strValue == File.separator) return uri
|
||||
if (strValue!!.endsWith(File.separator)) {
|
||||
strValue = strValue.substring(0, strValue.length - 1)
|
||||
}
|
||||
val index = strValue.lastIndexOf('/')
|
||||
if (index > 0) {
|
||||
strValue = strValue.substring(0, index)
|
||||
}
|
||||
return Uri.Builder()
|
||||
.scheme(uri.scheme)
|
||||
.authority(uri.authority)
|
||||
.path(strValue)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun getSanitizedPath(name: String): String {
|
||||
var name = name
|
||||
name = name.replace("[/]+".toRegex(), File.separator)
|
||||
if (name.startsWith("./")) name = name.substring(2) else if (name.startsWith(File.separator)) name = name.substring(1)
|
||||
if (name.endsWith(File.separator)) name = name.substring(0, name.length - 1)
|
||||
return name
|
||||
}
|
||||
|
||||
fun addSegmentAtEnd(uri: Uri, lastPathSegment: String): Uri? {
|
||||
return Uri.Builder()
|
||||
.scheme(uri.scheme)
|
||||
.authority(uri.authority)
|
||||
.path(uri.path + File.separator.toString() + lastPathSegment)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class SharedPreferencesViewModel(packageInfo: PackageInfo, application: Applicat
|
||||
}
|
||||
|
||||
with(fileSystemManager?.getFile(path)) {
|
||||
val list = this?.list()?.asList() as ArrayList<String>?
|
||||
val list = this?.list()?.toList() as ArrayList<String>?
|
||||
sharedPrefsFiles.postValue(list!!)
|
||||
}
|
||||
}.getOrElse {
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
android:id="@+id/pref_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/header_padding"
|
||||
android:layout_marginVertical="@dimen/popup_padding"
|
||||
android:layout_margin="@dimen/popup_padding"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/popup_padding">
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/header_padding"
|
||||
android:padding="@dimen/popup_padding"
|
||||
android:translationZ="1dp">
|
||||
|
||||
<app.simple.inure.decorations.theme.ThemeIcon
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<app.simple.inure.decorations.theme.ThemeLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/white"
|
||||
android:clipChildren="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="@dimen/panel_padding_horizontal">
|
||||
@@ -12,11 +13,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@android:color/white"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/header_padding"
|
||||
android:background="@android:color/white"
|
||||
android:translationZ="1dp">
|
||||
|
||||
<app.simple.inure.decorations.theme.ThemeIcon
|
||||
@@ -81,4 +82,4 @@
|
||||
app:isFastScrollRequired="false"
|
||||
app:statusBarPaddingRequired="false" />
|
||||
|
||||
</LinearLayout>
|
||||
</app.simple.inure.decorations.theme.ThemeLinearLayout>
|
||||
@@ -1,9 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<app.simple.inure.decorations.theme.ThemeLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/white"
|
||||
android:clipChildren="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="@dimen/panel_padding_horizontal">
|
||||
@@ -12,9 +13,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@android:color/white"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:background="@android:color/white"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/header_padding"
|
||||
android:translationZ="1dp">
|
||||
@@ -78,4 +79,4 @@
|
||||
app:isFastScrollRequired="false"
|
||||
app:statusBarPaddingRequired="false" />
|
||||
|
||||
</LinearLayout>
|
||||
</app.simple.inure.decorations.theme.ThemeLinearLayout>
|
||||
@@ -38,7 +38,33 @@
|
||||
app:appFontStyle="bold" />
|
||||
|
||||
<app.simple.inure.decorations.ripple.DynamicRippleTextView
|
||||
android:id="@+id/popup_shared_axis"
|
||||
android:id="@+id/popup_shared_axis_x"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/lato_bold"
|
||||
android:paddingHorizontal="30dp"
|
||||
android:paddingVertical="20dp"
|
||||
android:layout_marginBottom="@dimen/popup_item_gap_length"
|
||||
android:text="@string/shared_axis"
|
||||
app:textColorStyle="primary"
|
||||
android:textSize="@dimen/popup_text_size"
|
||||
app:appFontStyle="bold" />
|
||||
|
||||
<app.simple.inure.decorations.ripple.DynamicRippleTextView
|
||||
android:id="@+id/popup_shared_axis_y"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/lato_bold"
|
||||
android:paddingHorizontal="30dp"
|
||||
android:paddingVertical="20dp"
|
||||
android:layout_marginBottom="@dimen/popup_item_gap_length"
|
||||
android:text="@string/shared_axis"
|
||||
app:textColorStyle="primary"
|
||||
android:textSize="@dimen/popup_text_size"
|
||||
app:appFontStyle="bold" />
|
||||
|
||||
<app.simple.inure.decorations.ripple.DynamicRippleTextView
|
||||
android:id="@+id/popup_shared_axis_z"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/lato_bold"
|
||||
|
||||
@@ -566,7 +566,7 @@
|
||||
<string name="the_app_has_crashed">應用程式已當機!</string>
|
||||
<string name="fade">淡入</string>
|
||||
<string name="elevation">高度</string>
|
||||
<string name="shared_axis">已共用的座標軸</string>
|
||||
<string name="shared_axis">已共用的座標軸 %1$s</string>
|
||||
<string name="through">穿過</string>
|
||||
<string name="transition_type">轉換類型</string>
|
||||
<string name="transition_type_desc">轉換類型將在切換面板時體現</string>
|
||||
|
||||
@@ -569,7 +569,7 @@
|
||||
<string name="the_app_has_crashed">The app has crashed!</string>
|
||||
<string name="fade">Fade</string>
|
||||
<string name="elevation">Elevation</string>
|
||||
<string name="shared_axis">Shared Axis</string>
|
||||
<string name="shared_axis">Shared Axis %1$s</string>
|
||||
<string name="through">Through</string>
|
||||
<string name="transition_type">Transition Type</string>
|
||||
<string name="transition_type_desc">Type of transition to be played when panel is switched.</string>
|
||||
|
||||
1
hidden-api/.gitignore
vendored
1
hidden-api/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/build
|
||||
@@ -1,44 +0,0 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.inure.hidden_api'
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
minSdk 23
|
||||
targetSdk 33
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
||||
annotationProcessor 'dev.rikka.tools.refine:annotation-processor:3.1.1'
|
||||
compileOnly 'dev.rikka.tools.refine:annotation:3.1.1'
|
||||
}
|
||||
21
hidden-api/proguard-rules.pro
vendored
21
hidden-api/proguard-rules.pro
vendored
@@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.inure.hidden_api
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.inure.hidden_api.test", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest>
|
||||
|
||||
</manifest>
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.inure.hidden_api
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
include ':app'
|
||||
rootProject.name = "Inure"
|
||||
include ':hidden-api'
|
||||
|
||||
Reference in New Issue
Block a user