0
0
mirror of https://github.com/TrianguloY/UrlChecker.git synced 2024-09-19 20:02:16 +02:00

modules are now described in a separate data list, for better configuration

modules can now be enabled/disabled from a specific activity
This commit is contained in:
TrianguloY 2020-08-02 18:09:00 +02:00
parent b85d89708b
commit 19b51024f0
18 changed files with 285 additions and 170 deletions

View File

@ -11,7 +11,9 @@
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault"
android:usesCleartextTraffic="true">
<activity android:name=".MainDialog"
<activity android:name=".activities.ModulesActivity"></activity>
<activity
android:name=".dialogs.MainDialog"
android:excludeFromRecents="true"
android:noHistory="true"
android:theme="@android:style/Theme.DeviceDefault.Dialog">
@ -25,7 +27,7 @@
<data android:scheme="https" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -1,81 +0,0 @@
package com.trianguloy.urlchecker;
import android.content.Context;
import android.content.SharedPreferences;
import com.trianguloy.urlchecker.modules.AsciiModule;
import com.trianguloy.urlchecker.modules.BaseModule;
import com.trianguloy.urlchecker.modules.OpenModule;
import com.trianguloy.urlchecker.modules.RedirectModule;
import com.trianguloy.urlchecker.modules.TextInputModule;
import com.trianguloy.urlchecker.modules.VirusTotalModule;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Manager of all the modules
*/
public class ModuleManager {
// ------------------- configuration -------------------
/**
* list of registered modules
*/
private static final Map<String, Class<? extends BaseModule>> modules = new HashMap<>();
static {
// TODO: auto-load with reflection?
modules.put("ascii", AsciiModule.class);
modules.put("redirect", RedirectModule.class);
modules.put("virustotal", VirusTotalModule.class);
}
// ------------------- class -------------------
private static final String PREF_NAME = "MM";
private static final String PREF_SUFFIX = "_en";
/**
* @return the uninitialized top module
*/
static BaseModule getTopModule() {
return new TextInputModule();
}
/**
* Returns the uninitialized middle modules
*
* @param cntx base context (for the sharedpref)
* @return the list, may be empty
*/
public static List<BaseModule> getMiddleModules(Context cntx) {
List<BaseModule> enabled = new ArrayList<>();
SharedPreferences prefs = cntx.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
// for each module
for (Map.Entry<String, Class<? extends BaseModule>> module : modules.entrySet()) {
// check if enabled
if (prefs.getBoolean(module.getKey() + PREF_SUFFIX, true)) {
// and return
try {
enabled.add(module.getValue().newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
return enabled;
}
/**
* @return the uninitialized bottom module
*/
static BaseModule getBottomModule() {
return new OpenModule();
}
}

View File

@ -1,4 +1,4 @@
package com.trianguloy.urlchecker;
package com.trianguloy.urlchecker.activities;
import android.app.Activity;
import android.content.Intent;
@ -6,6 +6,8 @@ import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import com.trianguloy.urlchecker.R;
/**
* The activity to show when clicking the desktop shortcut (when 'opening' the app)
*/
@ -19,6 +21,7 @@ public class MainActivity extends Activity {
/**
* ButtonClick
*
* @param view which button
*/
public void onClick(View view) {
@ -26,6 +29,9 @@ public class MainActivity extends Activity {
case R.id.btn_debug:
openGoogle();
break;
case R.id.btn_config:
startActivity(new Intent(this, ModulesActivity.class));
break;
}
}

View File

@ -0,0 +1,55 @@
package com.trianguloy.urlchecker.activities;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.TextView;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.modules.ModuleData;
import com.trianguloy.urlchecker.modules.ModuleManager;
import com.trianguloy.urlchecker.utilities.GenericPref;
import java.util.List;
/**
* An activity that shows the list of modules that can be enabled/disabled
*/
public class ModulesActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_modules);
initialize();
}
private void initialize() {
LinearLayout ll = findViewById(R.id.list);
List<ModuleData> modules = ModuleData.toggleableModules;
for (ModuleData module : modules) {
// inflate
View views = getLayoutInflater().inflate(R.layout.conf_module, ll, false);
ll.addView(views); // separated to return the inflated view instead of the parent
// configure
Switch enabled = views.findViewById(R.id.enable);
final GenericPref.Bool enabled_pref = ModuleManager.getEnabledPrefOfModule(module, this);
enabled.setChecked(enabled_pref.get());
enabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
enabled_pref.set(isChecked);
}
});
((TextView) views.findViewById(R.id.label)).setText(module.name);
}
}
}

View File

@ -1,4 +1,4 @@
package com.trianguloy.urlchecker;
package com.trianguloy.urlchecker.dialogs;
import android.app.Activity;
import android.net.Uri;
@ -9,6 +9,10 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.trianguloy.urlchecker.BuildConfig;
import com.trianguloy.urlchecker.modules.ModuleData;
import com.trianguloy.urlchecker.modules.ModuleManager;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.modules.BaseModule;
import java.util.ArrayList;
@ -25,6 +29,7 @@ public class MainDialog extends Activity {
* to avoid infinite loops when setting urls
*/
boolean onSettingUrl = false;
private LinearLayout ll_mods;
/**
* A module changed the url
@ -78,6 +83,9 @@ public class MainDialog extends Activity {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.dialog_main);
// get views
ll_mods = findViewById(R.id.middle_modules);
// initialize
initializeModules();
@ -92,15 +100,14 @@ public class MainDialog extends Activity {
modules.clear();
// top module
initializeModule(ModuleManager.getTopModule(), findViewById(R.id.top_module));
initializeModule(ModuleData.topModule);
// middle modules
final List<BaseModule> middleModules = ModuleManager.getMiddleModules(this);
LinearLayout ll_mods = findViewById(R.id.middle_modules);
for (BaseModule module : middleModules) {
final List<ModuleData> middleModules = ModuleManager.getMiddleModules(this);
for (ModuleData module : middleModules) {
// set title
String name = module.getName();
String name = module.name;
if (name != null) {
final TextView title = new TextView(this);
title.setText(name + ":");
@ -108,25 +115,30 @@ public class MainDialog extends Activity {
}
// set content
initializeModule(module,
getLayoutInflater().inflate(module.getLayoutBase(), ll_mods)
);
initializeModule(module);
}
// bottom module
initializeModule(ModuleManager.getBottomModule(), findViewById(R.id.bottom_module));
initializeModule(ModuleData.bottomModule);
}
/**
* Initializes a module by registering with this dialog and adding to the list
*
* @param module which module to initialize
* @param views the views of that module
* @param moduleData which module to initialize
*/
private void initializeModule(BaseModule module, View views) {
module.registerDialog(this);
module.initialize(views);
modules.add(module);
private void initializeModule(ModuleData moduleData) {
try {
// enabled, add
BaseModule module = moduleData.dialogClass.getDeclaredConstructor(MainDialog.class).newInstance(this);
View views = getLayoutInflater().inflate(module.getLayoutBase(), ll_mods,false);
ll_mods.addView(views); // separated to return the inflated view instead of the parent
module.onInitialize(views);
modules.add(module);
} catch (Exception e) {
// can't add module
e.printStackTrace();
}
}
/**

View File

@ -5,6 +5,7 @@ import android.view.View;
import android.widget.TextView;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.dialogs.MainDialog;
import java.util.ArrayList;
import java.util.List;
@ -16,9 +17,8 @@ public class AsciiModule extends BaseModule {
private TextView txt_ascii;
@Override
public String getName() {
return "Ascii checker";
public AsciiModule(MainDialog dialog) {
super(dialog);
}
@Override
@ -27,7 +27,7 @@ public class AsciiModule extends BaseModule {
}
@Override
public void initialize(View views) {
public void onInitialize(View views) {
txt_ascii = views.findViewById(R.id.ascii);
}
@ -44,7 +44,7 @@ public class AsciiModule extends BaseModule {
if (messages.isEmpty()) {
// no messages, all good
txt_ascii.setText("Good url");
txt_ascii.setText("No issues found");
txt_ascii.setBackgroundColor(Color.TRANSPARENT);
} else {
// messages to show, concatenate them

View File

@ -1,47 +1,32 @@
package com.trianguloy.urlchecker.modules;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import com.trianguloy.urlchecker.MainDialog;
import com.trianguloy.urlchecker.dialogs.MainDialog;
/**
* Base class for a module.
* All modules need to have {@link #registerDialog(MainDialog)} and {@link #initialize(View)} called before use
*/
public abstract class BaseModule {
// ------------------- private data -------------------
private MainDialog dialog;
// ------------------- initialization -------------------
/**
* Initializes this module by registering this dialog
*
* @param cntx MainDialog
*/
public void registerDialog(MainDialog cntx) {
this.dialog = cntx;
public BaseModule(MainDialog dialog) {
this.dialog = dialog;
}
// ------------------- abstract functions -------------------
/**
* @return the name of this module (shown to the user)
*/
public abstract String getName();
/**
* @return the layout resource of this module
*/
public abstract int getLayoutBase();
/**
* Initializes this module from the given views (generated from {@link #getLayoutBase()})
*
* @param views
*/
public abstract void initialize(View views);
/**
* Notification of a new url, on this callback you can't call {@link #setUrl(String)}
*
@ -49,7 +34,14 @@ public abstract class BaseModule {
*/
public abstract void onNewUrl(String url);
// ------------------- protected utilities -------------------
/**
* Initializes this module from the given views (generated from {@link #getLayoutBase()})
*
* @param views
*/
public abstract void onInitialize(View views);
// ------------------- utilities -------------------
/**
* @return this activity context
@ -74,7 +66,4 @@ public abstract class BaseModule {
dialog.setUrl(url, this);
}
// ------------------- private data -------------------
private MainDialog dialog;
}

View File

@ -0,0 +1,48 @@
package com.trianguloy.urlchecker.modules;
import java.util.ArrayList;
import java.util.List;
/**
* If instantiated contains the information about a module.
* Statically contains the available modules
*/
public class ModuleData {
// ------------------- configuration -------------------
public final static List<ModuleData> toggleableModules = new ArrayList<>();
public final static ModuleData bottomModule = new ModuleData(OpenModule.class);
public final static ModuleData topModule = new ModuleData(TextInputModule.class);
// ------------------- initialization -------------------
static {
// TODO: auto-load with reflection?
add(AsciiModule.class, "ascii", "Ascii checker");
add(RedirectModule.class, "redirect", "Redirection");
add(VirusTotalModule.class, "virustotal", "VirusTotal");
}
public static void add(Class<? extends BaseModule> dialogClass, String id, String name) {
toggleableModules.add(new ModuleData(dialogClass, id, name));
}
// ------------------- struct -------------------
public final Class<? extends BaseModule> dialogClass;
public final String id;
public final String name;
public ModuleData(Class<? extends BaseModule> dialogClass, String id, String name) {
this.dialogClass = dialogClass;
this.id = id;
this.name = name;
}
public ModuleData(Class<? extends BaseModule> dialogClass) {
this.dialogClass = dialogClass;
id = name = null;
}
}

View File

@ -0,0 +1,52 @@
package com.trianguloy.urlchecker.modules;
import android.content.Context;
import com.trianguloy.urlchecker.utilities.GenericPref;
import java.util.ArrayList;
import java.util.List;
/**
* Manager of all the modules
*/
public class ModuleManager {
// ------------------- class -------------------
private static final String PREF_SUFFIX = "_en";
/**
* Status of modules by default (true=enabled, false=disabled)
*/
private static final boolean ENABLED_DEFAULT = true;
public static GenericPref.Bool getEnabledPrefOfModule(ModuleData module, Context cntx) {
final GenericPref.Bool enabledPref = new GenericPref.Bool(module.id + PREF_SUFFIX, ENABLED_DEFAULT);
enabledPref.init(cntx);
return enabledPref;
}
/**
* Returns the uninitialized middle modules
*
* @param cntx base context (for the sharedpref)
* @return the list, may be empty
*/
public static List<ModuleData> getMiddleModules(Context cntx) {
List<ModuleData> enabled = new ArrayList<>();
// check each module
for (ModuleData module : ModuleData.toggleableModules) {
if (getEnabledPrefOfModule(module, cntx).get()) {
try {
// enabled, add
enabled.add(module);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return enabled;
}
}

View File

@ -9,6 +9,7 @@ import android.widget.ImageButton;
import android.widget.PopupMenu;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.dialogs.MainDialog;
import com.trianguloy.urlchecker.utilities.LastOpened;
import com.trianguloy.urlchecker.utilities.PackageUtilities;
import com.trianguloy.urlchecker.utilities.UrlUtilities;
@ -28,9 +29,8 @@ public class OpenModule extends BaseModule implements View.OnClickListener, Popu
private Menu menu;
private PopupMenu popup;
@Override
public String getName() {
return null; // not used
public OpenModule(MainDialog dialog) {
super(dialog);
}
@Override
@ -39,7 +39,7 @@ public class OpenModule extends BaseModule implements View.OnClickListener, Popu
}
@Override
public void initialize(View views) {
public void onInitialize(View views) {
btn_open = views.findViewById(R.id.open);
btn_open.setOnClickListener(this);
btn_openWith = views.findViewById(R.id.open_with);

View File

@ -5,6 +5,7 @@ import android.widget.Button;
import android.widget.Toast;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.dialogs.MainDialog;
import java.io.IOException;
import java.net.HttpURLConnection;
@ -25,9 +26,8 @@ public class RedirectModule extends BaseModule implements View.OnClickListener {
*/
private Stack<String> urls = new Stack<>();
@Override
public String getName() {
return "Redirection";
public RedirectModule(MainDialog dialog) {
super(dialog);
}
@Override
@ -36,7 +36,7 @@ public class RedirectModule extends BaseModule implements View.OnClickListener {
}
@Override
public void initialize(View views) {
public void onInitialize(View views) {
check = views.findViewById(R.id.check);
check.setOnClickListener(this);
undo = views.findViewById(R.id.undo);

View File

@ -6,6 +6,7 @@ import android.view.View;
import android.widget.EditText;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.dialogs.MainDialog;
/**
* This module shows the current url and allows manual editing
@ -15,18 +16,18 @@ public class TextInputModule extends BaseModule implements TextWatcher {
private EditText edtxt_url;
private boolean editByCode = false;
@Override
public String getName() {
return null; // not used
public TextInputModule(MainDialog dialog) {
super(dialog);
}
@Override
public int getLayoutBase() {
return R.layout.module_text;
}
@Override
public void initialize(View views) {
public void onInitialize(View views) {
edtxt_url = views.findViewById(R.id.url);
edtxt_url.addTextChangedListener(this);
}

View File

@ -7,6 +7,7 @@ import android.widget.ImageButton;
import android.widget.TextView;
import com.trianguloy.urlchecker.R;
import com.trianguloy.urlchecker.dialogs.MainDialog;
import com.trianguloy.urlchecker.utilities.UrlUtilities;
import com.trianguloy.urlchecker.utilities.VirusTotalUtility;
@ -22,9 +23,8 @@ public class VirusTotalModule extends BaseModule implements View.OnClickListener
private boolean scanning = false;
private VirusTotalUtility.InternalReponse result = null;
@Override
public String getName() {
return "VirusTotal";
public VirusTotalModule(MainDialog dialog) {
super(dialog);
}
@Override
@ -33,7 +33,7 @@ public class VirusTotalModule extends BaseModule implements View.OnClickListener
}
@Override
public void initialize(View views) {
public void onInitialize(View views) {
btn_scan = views.findViewById(R.id.scan);
txt_result = views.findViewById(R.id.result);

View File

@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".MainActivity">
tools:context=".activities.MainActivity">
<TextView
android:layout_width="match_parent"
@ -19,4 +19,11 @@
android:onClick="onClick"
android:text="Open google" />
<Button
android:id="@+id/btn_config"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Configure" />
</LinearLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context=".activities.ModulesActivity">
<LinearLayout
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"></LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/label"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical" />
<ImageView
android:id="@+id/imageView"
android:layout_width="2dp"
android:layout_height="match_parent"
android:background="@android:color/darker_gray"
android:scaleType="centerInside" />
<Switch
android:id="@+id/enable"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -6,33 +6,16 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp"
tools:context="com.trianguloy.urlchecker.MainDialog">
tools:context="com.trianguloy.urlchecker.dialogs.MainDialog">
<LinearLayout
android:id="@+id/middle_modules"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/top_module"
layout="@layout/module_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/middle_modules"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<include
android:id="@+id/bottom_module"
layout="@layout/module_open"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.0'
classpath 'com.android.tools.build:gradle:4.0.1'
// NOTE: Do not place your application dependencies here; they belong