diff --git a/build.gradle b/build.gradle
index c7c0881a..7ec96733 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,6 +8,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.0.5'
+ classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44.2'
}
}
@@ -15,6 +16,7 @@ apply plugin: 'com.android.application'
apply plugin: 'checkstyle'
apply plugin: 'pmd'
apply plugin: 'com.github.spotbugs'
+apply plugin: 'com.google.dagger.hilt.android'
apply from: 'coverage.gradle'
// enable verbose lint warnings
@@ -412,6 +414,8 @@ dependencies {
implementation 'androidx.core:core:1.7.0'
implementation 'androidx.activity:activity:1.4.0'
implementation 'androidx.fragment:fragment:1.4.1'
+ implementation 'com.google.dagger:hilt-android:2.44.2'
+ annotationProcessor "com.google.dagger:hilt-compiler:2.44.2"
compileOnly 'com.github.spotbugs:spotbugs-annotations:4.5.3'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
testImplementation 'junit:junit:4.13.2'
diff --git a/src/androidTestMedicmobilegammaDebug/java/org/medicmobile/webapp/mobile/LoginTests.java b/src/androidTestMedicmobilegammaDebug/java/org/medicmobile/webapp/mobile/LoginTests.java
index 92ed8e95..f7a18f43 100644
--- a/src/androidTestMedicmobilegammaDebug/java/org/medicmobile/webapp/mobile/LoginTests.java
+++ b/src/androidTestMedicmobilegammaDebug/java/org/medicmobile/webapp/mobile/LoginTests.java
@@ -40,6 +40,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
+import org.medicmobile.webapp.mobile.components.settings_dialog.SettingsDialogActivity;
import java.util.Locale;
@LargeTest
diff --git a/src/androidTestUnbrandedDebug/java/org/medicmobile/webapp/mobile/SettingsDialogActivityTest.java b/src/androidTestUnbrandedDebug/java/org/medicmobile/webapp/mobile/SettingsDialogActivityTest.java
index d7011b80..43de12f1 100644
--- a/src/androidTestUnbrandedDebug/java/org/medicmobile/webapp/mobile/SettingsDialogActivityTest.java
+++ b/src/androidTestUnbrandedDebug/java/org/medicmobile/webapp/mobile/SettingsDialogActivityTest.java
@@ -39,6 +39,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
+import org.medicmobile.webapp.mobile.components.settings_dialog.SettingsDialogActivity;
import java.util.Locale;
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index e9d68e7d..6b611219 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -26,7 +26,8 @@
-->
-
-
diff --git a/src/main/java/org/medicmobile/webapp/mobile/ChtAndroidApplication.java b/src/main/java/org/medicmobile/webapp/mobile/ChtAndroidApplication.java
new file mode 100644
index 00000000..9b80c9d8
--- /dev/null
+++ b/src/main/java/org/medicmobile/webapp/mobile/ChtAndroidApplication.java
@@ -0,0 +1,9 @@
+package org.medicmobile.webapp.mobile;
+
+import android.app.Application;
+
+import dagger.hilt.android.HiltAndroidApp;
+
+@HiltAndroidApp
+public class ChtAndroidApplication extends Application {
+}
diff --git a/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java b/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java
index dafa0975..91d58887 100644
--- a/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java
+++ b/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java
@@ -34,6 +34,8 @@
import androidx.core.content.ContextCompat;
+import org.medicmobile.webapp.mobile.SettingsStore.SettingsException;
+
import java.util.Arrays;
import java.util.Optional;
diff --git a/src/main/java/org/medicmobile/webapp/mobile/OpenSettingsDialogFragment.java b/src/main/java/org/medicmobile/webapp/mobile/OpenSettingsDialogFragment.java
index bc688d76..8419bec5 100644
--- a/src/main/java/org/medicmobile/webapp/mobile/OpenSettingsDialogFragment.java
+++ b/src/main/java/org/medicmobile/webapp/mobile/OpenSettingsDialogFragment.java
@@ -11,6 +11,8 @@
import androidx.annotation.Nullable;
+import org.medicmobile.webapp.mobile.components.settings_dialog.SettingsDialogActivity;
+
import java.time.Clock;
@SuppressLint("ValidFragment")
diff --git a/src/main/java/org/medicmobile/webapp/mobile/SettingsDialogActivity.java b/src/main/java/org/medicmobile/webapp/mobile/SettingsDialogActivity.java
deleted file mode 100644
index 796b06df..00000000
--- a/src/main/java/org/medicmobile/webapp/mobile/SettingsDialogActivity.java
+++ /dev/null
@@ -1,364 +0,0 @@
-package org.medicmobile.webapp.mobile;
-
-import static org.medicmobile.webapp.mobile.MedicLog.trace;
-import static org.medicmobile.webapp.mobile.MedicLog.error;
-import static org.medicmobile.webapp.mobile.SimpleJsonClient2.redactUrl;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import androidx.fragment.app.FragmentActivity;
-
-import org.medicmobile.webapp.mobile.adapters.FilterableListAdapter;
-import org.medicmobile.webapp.mobile.dialogs.ConfirmServerSelectionDialog;
-import org.medicmobile.webapp.mobile.listeners.TextChangedListener;
-import org.medicmobile.webapp.mobile.util.AsyncExecutor;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-public class SettingsDialogActivity extends FragmentActivity {
- private static final int STATE_LIST = 1;
- private static final int STATE_FORM = 2;
- private SettingsStore settings;
- private ServerRepo serverRepo;
- private int state;
-
- @Override public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- trace(this, "onCreate()");
-
- this.settings = SettingsStore.in(this);
- this.serverRepo = new ServerRepo(this, this.settings);
-
- displayServerSelectList();
- }
-
-//> STATE CHANGE HANDLERS
- private void displayServerSelectList() {
- state = STATE_LIST;
-
- setContentView(R.layout.server_select_list);
-
- ListView list = findViewById(R.id.lstServers);
-
- List servers = serverRepo.getServers();
- ServerMetadataAdapter adapter = ServerMetadataAdapter.createInstance(this, servers);
- list.setAdapter(adapter);
- list.setOnItemClickListener(new ServerClickListener(adapter));
-
- TextView seachBox = findViewById(R.id.instanceSearchBox);
- seachBox.addTextChangedListener(new TextChangedListener() {
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- adapter.getFilter().filter(s.toString());
- }
- });
- }
-
- private void displayCustomServerForm() {
- state = STATE_FORM;
-
- setContentView(R.layout.custom_server_form);
-
- if(!this.settings.hasWebappSettings()) {
- cancelButton().setVisibility(View.GONE);
- }
-
- text(R.id.txtAppUrl, settings.getAppUrl());
- }
-
-//> EVENT HANDLERS
- public void verifyAndSave(View view) {
- trace(this, "verifyAndSave()");
-
- submitButton().setEnabled(false);
- cancelButton().setEnabled(false);
-
- String appUrl = text(R.id.txtAppUrl);
-
- AsyncExecutor asyncExecutor = new AsyncExecutor();
- asyncExecutor.executeAsync(new AppUrlVerifier(appUrl), (result) -> {
- trace(
- this,
- "SettingsDialogActivity :: Executing verification callback, result isOkay=%s, appUrl=%s",
- result.isOk, result.appUrl
- );
-
- if (result.isOk) {
- saveSettings(new WebappSettings(result.appUrl));
- serverRepo.save(result.appUrl);
- return;
- }
- showError(R.id.txtAppUrl, result.failure);
- submitButton().setEnabled(true);
- cancelButton().setEnabled(true);
- });
- }
-
- public void cancelSettingsEdit(View view) {
- trace(this, "cancelSettingsEdit()");
- backToWebview();
- }
-
- @Override public void onBackPressed() {
- switch(state) {
- case STATE_LIST:
- if(this.settings.hasWebappSettings()) {
- backToWebview();
- return;
- }
- break;
- case STATE_FORM:
- displayServerSelectList();
- return;
- }
- super.onBackPressed();
- }
-
-//> PRIVATE HELPERS
- private void backToWebview() {
- startActivity(new Intent(this, EmbeddedBrowserActivity.class));
- finish();
- }
-
- private void saveSettings(WebappSettings s) {
- try {
- settings.updateWith(s);
- this.backToWebview();
- } catch(IllegalSettingsException ex) {
- trace(ex, "Tried to save illegal setting.");
- for(IllegalSetting error : ex.errors) {
- showError(error);
- }
- } catch(SettingsException ex) {
- trace(ex, "Problem saving settings.");
- submitButton().setError(ex.getMessage());
- }
- }
-
- private Button cancelButton() {
- return (Button) findViewById(R.id.btnCancelSettings);
- }
-
- private Button submitButton() {
- return (Button) findViewById(R.id.btnSaveSettings);
- }
-
- private String text(int componentId) {
- EditText field = (EditText) findViewById(componentId);
- return field.getText().toString();
- }
-
- private void text(int componentId, String value) {
- EditText field = (EditText) findViewById(componentId);
- field.setText(value);
- }
-
- private void showError(IllegalSetting error) {
- showError(error.componentId, error.errorStringId);
- }
-
- private void showError(int componentId, int stringId) {
- TextView field = (TextView) findViewById(componentId);
- field.setError(getString(stringId));
- }
-
-//> INNER CLASSES
- class ServerClickListener implements OnItemClickListener {
- private final ServerMetadataAdapter serverMetadataAdapter;
-
- public ServerClickListener(ServerMetadataAdapter serverMetadataAdapter) {
- this.serverMetadataAdapter = serverMetadataAdapter;
- }
-
- public void onItemClick(AdapterView> parent, final View view, int position, long id) {
- ServerMetadata server = serverMetadataAdapter.getServerMetadata(position);
- if (server.url == null) {
- displayCustomServerForm();
- } else {
- new ConfirmServerSelectionDialog(
- server.name,
- () -> saveSettings(new WebappSettings(server.url))
- ).show(getSupportFragmentManager());
- }
- }
- }
-
- static class ServerMetadataAdapter extends FilterableListAdapter {
- private ServerMetadataAdapter(Context context, List