Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 2a97cba

Browse files
committed
Rework user interface, add blur view, fix landscape.
1 parent 7a6aa28 commit 2a97cba

File tree

9 files changed

+166
-23
lines changed

9 files changed

+166
-23
lines changed

app/src/main/java/com/fox2code/mmm/MainActivity.java

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@
33
import androidx.annotation.NonNull;
44
import androidx.appcompat.widget.SearchView;
55
import androidx.cardview.widget.CardView;
6+
import androidx.core.view.WindowInsetsCompat;
67
import androidx.recyclerview.widget.LinearLayoutManager;
78
import androidx.recyclerview.widget.RecyclerView;
89
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
910

11+
import android.content.res.Configuration;
1012
import android.content.res.Resources;
13+
import android.graphics.PixelFormat;
14+
import android.os.Build;
1115
import android.os.Bundle;
1216
import android.util.Log;
1317
import android.util.TypedValue;
1418
import android.view.View;
19+
import android.view.ViewGroup;
20+
import android.view.Window;
1521
import android.view.WindowManager;
1622
import android.view.inputmethod.EditorInfo;
23+
import android.widget.TextView;
1724

1825
import com.fox2code.mmm.compat.CompatActivity;
1926
import com.fox2code.mmm.installer.InstallerInitializer;
@@ -25,6 +32,9 @@
2532
import com.fox2code.mmm.utils.IntentHelper;
2633
import com.google.android.material.progressindicator.LinearProgressIndicator;
2734

35+
import eightbitlab.com.blurview.BlurView;
36+
import eightbitlab.com.blurview.RenderScriptBlur;
37+
2838
public class MainActivity extends CompatActivity implements SwipeRefreshLayout.OnRefreshListener,
2939
SearchView.OnQueryTextListener, SearchView.OnCloseListener {
3040
private static final String TAG = "MainActivity";
@@ -33,7 +43,11 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
3343
public LinearProgressIndicator progressIndicator;
3444
private ModuleViewAdapter moduleViewAdapter;
3545
private SwipeRefreshLayout swipeRefreshLayout;
46+
private int swipeRefreshLayoutOrigStartOffset;
47+
private int swipeRefreshLayoutOrigEndOffset;
3648
private long swipeRefreshBlocker = 0;
49+
private TextView actionBarPadding;
50+
private BlurView actionBarBlur;
3751
private RecyclerView moduleList;
3852
private CardView searchCard;
3953
private SearchView searchView;
@@ -55,10 +69,24 @@ protected void onCreate(Bundle savedInstanceState) {
5569
setContentView(R.layout.activity_main);
5670
this.setTitle(R.string.app_name);
5771
this.getWindow().setFlags(
58-
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
59-
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
72+
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
73+
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
74+
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
75+
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
76+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
77+
WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
78+
layoutParams.layoutInDisplayCutoutMode = // Support cutout in Android 9
79+
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
80+
this.getWindow().setAttributes(layoutParams);
81+
}
82+
this.actionBarPadding = findViewById(R.id.action_bar_padding);
83+
this.actionBarBlur = findViewById(R.id.action_bar_blur);
6084
this.progressIndicator = findViewById(R.id.progress_bar);
6185
this.swipeRefreshLayout = findViewById(R.id.swipe_refresh);
86+
this.swipeRefreshLayoutOrigStartOffset =
87+
this.swipeRefreshLayout.getProgressViewStartOffset();
88+
this.swipeRefreshLayoutOrigEndOffset =
89+
this.swipeRefreshLayout.getProgressViewEndOffset();
6290
this.swipeRefreshBlocker = Long.MAX_VALUE;
6391
this.moduleList = findViewById(R.id.module_list);
6492
this.searchCard = findViewById(R.id.search_card);
@@ -68,6 +96,11 @@ protected void onCreate(Bundle savedInstanceState) {
6896
this.moduleList.setLayoutManager(new LinearLayoutManager(this));
6997
this.moduleList.setItemViewCacheSize(4); // Default is 2
7098
this.swipeRefreshLayout.setOnRefreshListener(this);
99+
this.actionBarBlur.setupWith(this.moduleList).setFrameClearDrawable(
100+
this.getWindow().getDecorView().getBackground())
101+
.setBlurAlgorithm(new RenderScriptBlur(this))
102+
.setBlurRadius(5F).setBlurAutoUpdate(true)
103+
.setHasFixedTransformationMatrix(true);
71104
this.moduleList.addOnScrollListener(new RecyclerView.OnScrollListener() {
72105
@Override
73106
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
@@ -158,6 +191,7 @@ public void commonNext() {
158191
progressIndicator.setProgressCompat(PRECISION, true);
159192
progressIndicator.setVisibility(View.GONE);
160193
searchView.setEnabled(true);
194+
setActionBarBackground(null);
161195
});
162196
moduleViewListBuilder.appendRemoteModules();
163197
moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter);
@@ -175,12 +209,29 @@ private void cardIconifyUpdate() {
175209
TypedValue value = new TypedValue();
176210
theme.resolveAttribute(backgroundAttr, value, true);
177211
this.searchCard.setCardBackgroundColor(value.data);
178-
this.searchCard.setAlpha(iconified ? 0.70F : 1F);
212+
this.searchCard.setAlpha(iconified ? 0.80F : 1F);
179213
}
180214

181215
private void updateScreenInsets() {
182-
this.moduleViewListBuilder.setFooterPx(
183-
this.getNavigationBarHeight() + this.searchCard.getHeight());
216+
this.runOnUiThread(() -> this.updateScreenInsets(
217+
this.getResources().getConfiguration()));
218+
}
219+
220+
private void updateScreenInsets(Configuration configuration) {
221+
boolean landscape = configuration.orientation ==
222+
Configuration.ORIENTATION_LANDSCAPE;
223+
int statusBarHeight = getStatusBarHeight();
224+
int actionBarHeight = getActionBarHeight();
225+
int combinedBarsHeight = statusBarHeight + actionBarHeight;
226+
this.actionBarPadding.setMinHeight(combinedBarsHeight);
227+
this.swipeRefreshLayout.setProgressViewOffset(false,
228+
swipeRefreshLayoutOrigStartOffset + combinedBarsHeight,
229+
swipeRefreshLayoutOrigEndOffset + combinedBarsHeight);
230+
this.moduleViewListBuilder.setHeaderPx(actionBarHeight);
231+
this.moduleViewListBuilder.setFooterPx((landscape ? 0 :
232+
this.getNavigationBarHeight()) + this.searchCard.getHeight());
233+
this.moduleViewListBuilder.updateInsets();
234+
this.actionBarBlur.invalidate();
184235
}
185236

186237
@Override
@@ -234,6 +285,12 @@ else if (AppUpdateManager.getAppUpdateManager().checkUpdate(false))
234285
this.initMode = false;
235286
}
236287

288+
@Override
289+
public void onConfigurationChanged(@NonNull Configuration newConfig) {
290+
this.updateScreenInsets(newConfig);
291+
super.onConfigurationChanged(newConfig);
292+
}
293+
237294
@Override
238295
public void onRefresh() {
239296
if (this.swipeRefreshBlocker > System.currentTimeMillis() ||

app/src/main/java/com/fox2code/mmm/ModuleHolder.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public final class ModuleHolder implements Comparable<ModuleHolder> {
2424
public final String moduleId;
2525
public final NotificationType notificationType;
2626
public final Type separator;
27-
public final int footerPx;
27+
public int footerPx;
2828
public View.OnClickListener onClickListener;
2929
public LocalModuleInfo moduleInfo;
3030
public RepoModule repoModule;
@@ -34,32 +34,33 @@ public ModuleHolder(String moduleId) {
3434
this.moduleId = Objects.requireNonNull(moduleId);
3535
this.notificationType = null;
3636
this.separator = null;
37-
this.footerPx = 0;
37+
this.footerPx = -1;
3838
}
3939

4040
public ModuleHolder(NotificationType notificationType) {
4141
this.moduleId = "";
4242
this.notificationType = Objects.requireNonNull(notificationType);
4343
this.separator = null;
44-
this.footerPx = 0;
44+
this.footerPx = -1;
4545
}
4646

4747
public ModuleHolder(Type separator) {
4848
this.moduleId = "";
4949
this.notificationType = null;
5050
this.separator = separator;
51-
this.footerPx = 0;
51+
this.footerPx = -1;
5252
}
5353

54-
public ModuleHolder(int footerPx) {
54+
public ModuleHolder(int footerPx,boolean header) {
5555
this.moduleId = "";
5656
this.notificationType = null;
5757
this.separator = null;
5858
this.footerPx = footerPx;
59+
this.filterLevel = header ? 1 : 0;
5960
}
6061

6162
public boolean isModuleHolder() {
62-
return this.notificationType == null && this.separator == null && this.footerPx == 0;
63+
return this.notificationType == null && this.separator == null && this.footerPx == -1;
6364
}
6465

6566
public ModuleInfo getMainModuleInfo() {
@@ -115,7 +116,7 @@ public boolean hasFlag(int flag) {
115116
}
116117

117118
public Type getType() {
118-
if (this.footerPx != 0) {
119+
if (this.footerPx != -1) {
119120
return Type.FOOTER;
120121
} else if (this.separator != null) {
121122
return Type.SEPARATOR;
@@ -145,7 +146,7 @@ public Type getCompareType(Type type) {
145146

146147
public boolean shouldRemove() {
147148
return this.notificationType != null ? this.notificationType.shouldRemove() :
148-
this.footerPx == 0 && this.moduleInfo == null &&
149+
this.footerPx == -1 && this.moduleInfo == null &&
149150
(this.repoModule == null || !this.repoModule.repoData.isEnabled() ||
150151
(PropUtils.isLowQualityModule(this.repoModule.moduleInfo) &&
151152
!MainApplication.isDisableLowQualityModuleFilter()));
@@ -207,6 +208,7 @@ public int compareTo(ModuleHolder o) {
207208
}
208209

209210
public enum Type implements Comparator<ModuleHolder> {
211+
HEADER(R.string.loading, false, false),
210212
SEPARATOR(R.string.loading, false, false) {
211213
@Override
212214
@SuppressWarnings("ConstantConditions")

app/src/main/java/com/fox2code/mmm/ModuleViewAdapter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.topjohnwu.superuser.internal.UiThreadHandler;
2727

2828
import java.util.ArrayList;
29+
import java.util.Objects;
2930

3031
public final class ModuleViewAdapter extends RecyclerView.Adapter<ModuleViewAdapter.ViewHolder> {
3132
private static final boolean DEBUG = false;
@@ -182,14 +183,16 @@ public boolean update(ModuleHolder moduleHolder) {
182183
if (localModuleInfo == null || moduleInfo.versionCode >
183184
localModuleInfo.updateVersionCode) {
184185
this.creditText.setText((localModuleInfo == null ||
185-
moduleInfo.version.equals(localModuleInfo.version) ?
186+
Objects.equals(moduleInfo.version, localModuleInfo.version) ?
186187
moduleInfo.version : localModuleInfo.version + " (" +
187188
this.getString(R.string.module_last_update) +
188189
moduleInfo.version + ")") + " " +
189190
this.getString(R.string.module_by) + " " + moduleInfo.author);
190191
} else {
191192
this.creditText.setText(localModuleInfo.version + (
192-
localModuleInfo.version.equals(localModuleInfo.updateVersion) ?
193+
(localModuleInfo.updateVersion != null &&
194+
Objects.equals(localModuleInfo.version,
195+
localModuleInfo.updateVersion)) ?
193196
"" : " (" + this.getString(R.string.module_last_update) +
194197
localModuleInfo.updateVersion + ")") + " " +
195198
this.getString(R.string.module_by) + " " + localModuleInfo.author);

app/src/main/java/com/fox2code/mmm/ModuleViewListBuilder.java

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
public class ModuleViewListBuilder {
2525
private static final String TAG = "ModuleViewListBuilder";
26+
private static final Runnable RUNNABLE = () -> {};
2627
private final EnumSet<NotificationType> notifications = EnumSet.noneOf(NotificationType.class);
2728
private final HashMap<String, ModuleHolder> mappedModuleHolders = new HashMap<>();
2829
private final Object updateLock = new Object();
@@ -31,8 +32,10 @@ public class ModuleViewListBuilder {
3132
@NonNull
3233
private String query = "";
3334
private boolean updating;
35+
private int headerPx;
3436
private int footerPx;
3537
private ModuleSorter moduleSorter = ModuleSorter.UPDATE;
38+
private Runnable updateInsets = RUNNABLE;
3639

3740
public ModuleViewListBuilder(Activity activity) {
3841
this.activity = activity;
@@ -100,6 +103,7 @@ public void applyTo(final RecyclerView moduleList,final ModuleViewAdapter module
100103
this.updating = true;
101104
final ArrayList<ModuleHolder> moduleHolders;
102105
final int newNotificationsLen;
106+
final ModuleHolder[] headerFooter = new ModuleHolder[2];
103107
try {
104108
synchronized (this.updateLock) {
105109
// Build start
@@ -150,16 +154,20 @@ public void applyTo(final RecyclerView moduleList,final ModuleViewAdapter module
150154
}
151155
}
152156
Collections.sort(moduleHolders, this.moduleSorter);
153-
if (this.footerPx != 0) { // Footer is always last
154-
moduleHolders.add(new ModuleHolder(this.footerPx));
155-
}
157+
// Header is always first
158+
moduleHolders.add(0, headerFooter[0] =
159+
new ModuleHolder(this.headerPx, true));
160+
// Footer is always last
161+
moduleHolders.add(headerFooter[1] =
162+
new ModuleHolder(this.footerPx, false));
156163
Log.i(TAG, "Got " + moduleHolders.size() + " entries!");
157164
// Build end
158165
}
159166
} finally {
160167
this.updating = false;
161168
}
162169
this.activity.runOnUiThread(() -> {
170+
this.updateInsets = RUNNABLE;
163171
final EnumSet<NotificationType> oldNotifications =
164172
EnumSet.noneOf(NotificationType.class);
165173
boolean isTop = !moduleList.canScrollVertically(-1);
@@ -172,7 +180,8 @@ public void applyTo(final RecyclerView moduleList,final ModuleViewAdapter module
172180
oldNotifications.add(notificationType);
173181
if (!notificationType.special)
174182
oldNotificationsLen++;
175-
}
183+
} else if (moduleHolder.footerPx != -1)
184+
oldNotificationsLen++; // Fix header
176185
if (moduleHolder.separator == ModuleHolder.Type.INSTALLABLE)
177186
break;
178187
oldOfflineModulesLen++;
@@ -208,6 +217,13 @@ public void applyTo(final RecyclerView moduleList,final ModuleViewAdapter module
208217
}
209218
if (isTop) moduleList.scrollToPosition(0);
210219
if (isBottom) moduleList.scrollToPosition(newLen);
220+
this.updateInsets = () -> {
221+
headerFooter[0].footerPx = this.headerPx;
222+
headerFooter[1].footerPx = this.footerPx;
223+
notifySizeChanged(moduleViewAdapter, 0, 1, 1);
224+
notifySizeChanged(moduleViewAdapter,
225+
moduleHolders.size(), 1, 1);
226+
};
211227
});
212228
}
213229

@@ -281,11 +297,23 @@ public boolean setQueryChange(String query) {
281297
return true;
282298
}
283299

300+
public void setHeaderPx(int headerPx) {
301+
if (this.headerPx != headerPx) {
302+
synchronized (this.updateLock) {
303+
this.headerPx = headerPx;
304+
}
305+
}
306+
}
307+
284308
public void setFooterPx(int footerPx) {
285309
if (this.footerPx != footerPx) {
286310
synchronized (this.updateLock) {
287311
this.footerPx = footerPx;
288312
}
289313
}
290314
}
315+
316+
public void updateInsets() {
317+
this.updateInsets.run();
318+
}
291319
}

app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyWebAPI.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,17 @@ public void hideActionBar() {
165165

166166
/**
167167
* Show action bar if not visible, the action bar is only visible by default on notes.
168+
* Optional title param to set action bar title.
168169
*/
169170
@JavascriptInterface
170-
public void showActionBar() {
171+
public void showActionBar(final String title) {
171172
if (this.consumedAction) return;
172173
this.consumedAction = true;
173174
this.activity.runOnUiThread(() -> {
174175
this.activity.showActionBar();
176+
if (title != null && !title.isEmpty()) {
177+
this.activity.setTitle(title);
178+
}
175179
this.consumedAction = false;
176180
});
177181
}

0 commit comments

Comments
 (0)