diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..25c2334
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 43f699e..ad28876 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -42,6 +42,9 @@ dependencies {
implementation 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
implementation 'com.google.zxing:core:3.4.0'
+ // external
+ implementation 'me.saket:inboxrecyclerview:1.0.0-rc1'
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 48b8f7d..1f3a32c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,10 +1,11 @@
-
-
-
+
+
-
-
-
+
-
+
-
+
-
+
+ android:label="@string/login"/>
+
+
+
+ android:parentActivityName=".activities.HomeActivity"
+ android:screenOrientation="portrait"
+ android:theme="@style/AppTheme.Translucent"/>
+
+
+
+
+
+ android:theme="@style/AppTheme.Translucent"/>
\ No newline at end of file
diff --git a/app/src/main/java/lu/circl/mispbump/RecyclerViewItemTransition.java b/app/src/main/java/lu/circl/mispbump/RecyclerViewItemTransition.java
deleted file mode 100644
index 8b1e789..0000000
--- a/app/src/main/java/lu/circl/mispbump/RecyclerViewItemTransition.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package lu.circl.mispbump;
-
-import android.animation.Animator;
-import android.animation.ValueAnimator;
-import android.transition.Transition;
-import android.transition.TransitionValues;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-
-
-public class RecyclerViewItemTransition extends Transition {
-
- private static final String PROPNAME_ELEVATION = "customtransition:change_elevation:toolbar";
-
- private void captureTransitionValues(TransitionValues transitionValues) {
- transitionValues.values.put(PROPNAME_ELEVATION, transitionValues.view.getElevation());
- }
-
- @Override
- public void captureStartValues(@NonNull TransitionValues transitionValues) {
- captureTransitionValues(transitionValues);
- }
-
- @Override
- public void captureEndValues(@NonNull TransitionValues transitionValues) {
- captureTransitionValues(transitionValues);
- }
-
- @Override
- public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
- if (null == startValues || null == endValues) {
- return null;
- }
-
- final View view = endValues.view;
-
- int startElevation = 0;
- int endElevation = 6;
-
- ValueAnimator anim = ValueAnimator.ofFloat(startElevation, endElevation);
-
- anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (float) animation.getAnimatedValue();
- view.setElevation(t);
- }
- });
-
- return anim;
- }
-}
diff --git a/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java b/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java
index 9ddae93..7b97cd6 100644
--- a/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java
+++ b/app/src/main/java/lu/circl/mispbump/activities/HomeActivity.java
@@ -2,12 +2,12 @@ package lu.circl.mispbump.activities;
import android.content.Intent;
import android.os.Bundle;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
-import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityOptionsCompat;
@@ -15,7 +15,6 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.gson.Gson;
import java.util.List;
@@ -27,11 +26,13 @@ import lu.circl.mispbump.models.UploadInformation;
public class HomeActivity extends AppCompatActivity {
- private View rootView;
- private PreferenceManager preferenceManager;
+ public static String EXTRA_UPLOAD_INFO = "uploadInformation";
+ private List uploadInformationList;
+ private PreferenceManager preferenceManager;
private RecyclerView recyclerView;
private UploadInfoAdapter uploadInfoAdapter;
+ private TextView emptyRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -40,76 +41,10 @@ public class HomeActivity extends AppCompatActivity {
preferenceManager = PreferenceManager.getInstance(this);
- init();
+ initViews();
initRecyclerView();
}
-
- private void init() {
- rootView = findViewById(R.id.rootLayout);
-
- // populate Toolbar (Actionbar)
- Toolbar myToolbar = findViewById(R.id.toolbar);
- setSupportActionBar(myToolbar);
-
- ActionBar ab = getSupportActionBar();
- if (ab != null) {
- ab.setDisplayHomeAsUpEnabled(false);
- }
-
- FloatingActionButton sync_fab = findViewById(R.id.home_fab);
- sync_fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(new Intent(HomeActivity.this, SyncActivity.class));
- }
- });
- }
-
- private void initRecyclerView() {
- recyclerView = findViewById(R.id.recyclerView);
- recyclerView.setLayoutManager(new LinearLayoutManager(HomeActivity.this));
-
- uploadInfoAdapter = new UploadInfoAdapter(HomeActivity.this);
-
- uploadInfoAdapter.setOnRecyclerItemClickListener(new OnRecyclerItemClickListener() {
- @Override
- public void onClick(final View v, UploadInformation item) {
- Intent i = new Intent(HomeActivity.this, UploadInformationActivity.class);
- i.putExtra(UploadInformationActivity.EXTRA_UPLOAD_INFO_KEY, new Gson().toJson(item));
-
- ActivityOptionsCompat options = ActivityOptionsCompat.makeClipRevealAnimation(v.findViewById(R.id.rootLayout), (int) v.getX(), (int) v.getY(), v.getWidth(), v.getHeight());
- startActivity(i, options.toBundle());
- }
- });
-
- recyclerView.setAdapter(uploadInfoAdapter);
- }
-
- private void refreshRecyclerView() {
- List uploadInformationList = preferenceManager.getUploadInformation();
- TextView empty = findViewById(R.id.empty);
-
- // no sync information available
- if (uploadInformationList == null) {
- empty.setVisibility(View.VISIBLE);
- recyclerView.setVisibility(View.GONE);
- return;
- }
-
- // sync information available
- empty.setVisibility(View.GONE);
- recyclerView.setVisibility(View.VISIBLE);
- uploadInfoAdapter.setItems(uploadInformationList);
- }
-
-
- @Override
- protected void onResume() {
- super.onResume();
- refreshRecyclerView();
- }
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
@@ -131,4 +66,63 @@ public class HomeActivity extends AppCompatActivity {
// invoke superclass to handle unrecognized item (eg. homeAsUp)
return super.onOptionsItemSelected(item);
}
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ Log.d("DEBUG", "onResume()");
+
+ refreshRecyclerView();
+ }
+
+
+ private void initViews() {
+ emptyRecyclerView = findViewById(R.id.empty);
+
+ Toolbar myToolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(myToolbar);
+
+ FloatingActionButton syncFab = findViewById(R.id.home_fab);
+ syncFab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(HomeActivity.this, SyncActivity.class));
+ }
+ });
+ }
+
+ private void initRecyclerView() {
+ recyclerView = findViewById(R.id.recyclerView);
+ recyclerView.setLayoutManager(new LinearLayoutManager(HomeActivity.this));
+ uploadInfoAdapter = new UploadInfoAdapter(HomeActivity.this);
+ uploadInfoAdapter.setOnRecyclerPositionClickListener(onRecyclerItemClickListener());
+ recyclerView.setAdapter(uploadInfoAdapter);
+ }
+
+ private void refreshRecyclerView() {
+ uploadInformationList = preferenceManager.getUploadInformationList();
+
+ if (uploadInformationList.isEmpty()) {
+ emptyRecyclerView.setVisibility(View.VISIBLE);
+ recyclerView.setVisibility(View.GONE);
+ } else {
+ emptyRecyclerView.setVisibility(View.GONE);
+ recyclerView.setVisibility(View.VISIBLE);
+ uploadInfoAdapter.setItems(uploadInformationList);
+ }
+ }
+
+ private OnRecyclerItemClickListener onRecyclerItemClickListener() {
+ return new OnRecyclerItemClickListener() {
+ @Override
+ public void onClick(View v, Integer index) {
+ Intent i = new Intent(HomeActivity.this, UploadInfoActivity.class);
+ i.putExtra(UploadInfoActivity.EXTRA_UPLOAD_INFO_UUID, uploadInformationList.get(index).getUuid());
+
+ ActivityOptionsCompat options = ActivityOptionsCompat.makeClipRevealAnimation(v.findViewById(R.id.rootLayout), (int) v.getX(), (int) v.getY(), v.getWidth(), v.getHeight());
+ startActivity(i, options.toBundle());
+ }
+ };
+ }
}
diff --git a/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java b/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java
index af341b9..3eda757 100644
--- a/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java
+++ b/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java
@@ -7,6 +7,10 @@ import androidx.appcompat.app.AppCompatActivity;
import lu.circl.mispbump.auxiliary.PreferenceManager;
import lu.circl.mispbump.models.restModels.User;
+/**
+ * This activity navigates to the next activity base on the user status.
+ * This is the first activity that gets loaded when the user starts the app.
+ */
public class StartUpActivity extends AppCompatActivity {
@Override
diff --git a/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java b/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java
index 0ec56f0..472df9f 100644
--- a/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java
+++ b/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java
@@ -1,13 +1,11 @@
package lu.circl.mispbump.activities;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.content.Intent;
+import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.BounceInterpolator;
+import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@@ -17,7 +15,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
-import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.snackbar.Snackbar;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@@ -25,309 +22,308 @@ import com.google.gson.JsonSyntaxException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
+import java.util.List;
import lu.circl.mispbump.R;
+import lu.circl.mispbump.auxiliary.DialogManager;
import lu.circl.mispbump.auxiliary.PreferenceManager;
import lu.circl.mispbump.auxiliary.QrCodeGenerator;
import lu.circl.mispbump.auxiliary.RandomString;
import lu.circl.mispbump.fragments.CameraFragment;
-import lu.circl.mispbump.customViews.ExtendedBottomSheetBehavior;
-import lu.circl.mispbump.fragments.SyncOptionsFragment;
+import lu.circl.mispbump.fragments.UploadSettingsFragment;
import lu.circl.mispbump.models.SyncInformation;
import lu.circl.mispbump.models.UploadInformation;
import lu.circl.mispbump.security.DiffieHellman;
-/**
- * This class provides the sync functionality.
- * It collects the necessary information, guides through the process and finally completes with
- * the upload to the misp instance.
- */
public class SyncActivity extends AppCompatActivity {
- // rootLayout
- private CoordinatorLayout rootLayout;
- private ImageView qrCodeView, bottomSheetIcon;
- private TextView bottomSheetText;
- private ImageButton prevButton, nextButton;
- private ExtendedBottomSheetBehavior bottomSheetBehavior;
+ enum SyncState {
+ PUBLIC_KEY,
+ DATA
+ }
+
+ enum UiState {
+ PUBLIC_KEY_SHOW,
+ PUBLIC_KEY_SHOW_AND_RECEIVED,
+ SYNC_INFO_SHOW,
+ SYNC_INFO_SHOW_AND_RECEIVED
+ }
+
+ private SyncState currentSyncState;
- // dependencies
private PreferenceManager preferenceManager;
+ private UploadInformation uploadInformation;
+ private QrCodeGenerator qrCodeGenerator;
private DiffieHellman diffieHellman;
- private UploadInformation uploadInformation;
+ private boolean foreignPublicKeyReceived, foreignSyncInfoReceived;
- // fragments
+ // Fragments
private CameraFragment cameraFragment;
- private SyncOptionsFragment syncOptionsFragment;
- // qr codes
- private QrCodeGenerator qrCodeGenerator;
- private Bitmap publicKeyQr, syncInfoQr;
+ // Views
+ private CoordinatorLayout rootLayout;
+ private FrameLayout qrFrame;
+ private ImageView qrCode;
+ private TextView qrHint;
+ private ImageButton prevButton, nextButton;
- private SyncState currentSyncState = SyncState.settings;
+ private Bitmap publicKeyQrCode, syncInfoQrCode;
- private enum SyncState {
- settings(0),
- publicKeyExchange(1),
- dataExchange(2);
-
-
- private final int value;
-
- SyncState(final int value) {
- this.value = value;
- }
- }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sync);
- initializeViews();
+
+ init();
+ initViews();
+
+ switchState(SyncState.PUBLIC_KEY);
}
- private void initializeViews() {
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ switch (currentSyncState) {
+ case PUBLIC_KEY:
+ // TODO warn that sync is maybe not complete ... ?
+ break;
+ case DATA:
+ switchState(SyncState.PUBLIC_KEY);
+ break;
+ }
+ }
+
+ private void init() {
+ preferenceManager = PreferenceManager.getInstance(SyncActivity.this);
+ diffieHellman = DiffieHellman.getInstance();
+
+ qrCodeGenerator = new QrCodeGenerator(SyncActivity.this);
+ publicKeyQrCode = qrCodeGenerator.generateQrCode(DiffieHellman.publicKeyToString(diffieHellman.getPublicKey()));
+
+ uploadInformation = new UploadInformation();
+ }
+
+ private void initViews() {
rootLayout = findViewById(R.id.rootLayout);
- // prev button
+ qrFrame = findViewById(R.id.qrFrame);
+ qrCode = findViewById(R.id.qrCode);
+ qrHint = findViewById(R.id.qrHint);
+
prevButton = findViewById(R.id.prevButton);
prevButton.setOnClickListener(onPrevClicked);
- // next button
nextButton = findViewById(R.id.nextButton);
nextButton.setOnClickListener(onNextClicked);
-
- // QR Code View
- qrCodeView = findViewById(R.id.qrcode);
- qrCodeGenerator = new QrCodeGenerator(SyncActivity.this);
-
- bottomSheetIcon = findViewById(R.id.bottomSheetIcon);
- bottomSheetText = findViewById(R.id.bottomSheetText);
-
- diffieHellman = DiffieHellman.getInstance();
- preferenceManager = PreferenceManager.getInstance(this);
-
- View bottomSheet = findViewById(R.id.bottomSheet);
- bottomSheetBehavior = (ExtendedBottomSheetBehavior) BottomSheetBehavior.from(bottomSheet);
- bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
- bottomSheetBehavior.setSwipeable(false);
- bottomSheetBehavior.setHideable(false);
-
- publicKeyQr = generatePublicKeyQr();
-
- switchState(SyncState.settings);
}
- /**
- * Called when "next button" is pressed
- */
- private View.OnClickListener onNextClicked = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- switch (currentSyncState) {
- case settings:
- uploadInformation = new UploadInformation();
- uploadInformation.setAllowSelfSigned(syncOptionsFragment.getAllowSelfSigned());
- uploadInformation.setPush(syncOptionsFragment.getPush());
- uploadInformation.setPull(syncOptionsFragment.getPull());
- uploadInformation.setCached(syncOptionsFragment.getCache());
+ private void switchState(SyncState state) {
+ switchFragment(state);
+ displayQr(state);
- switchState(SyncState.publicKeyExchange);
- break;
-
- case publicKeyExchange:
- switchState(SyncState.dataExchange);
- break;
-
- case dataExchange:
- Intent upload = new Intent(SyncActivity.this, UploadActivity.class);
- upload.putExtra(UploadActivity.EXTRA_UPLOAD_INFO, new Gson().toJson(uploadInformation));
- startActivity(upload);
- overridePendingTransition(R.anim.slide_in_right, android.R.anim.slide_out_right);
- finish();
- break;
- }
+ switch (state) {
+ case PUBLIC_KEY:
+ if (foreignPublicKeyReceived) {
+ switchUiState(UiState.PUBLIC_KEY_SHOW_AND_RECEIVED);
+ cameraFragment.setReadQrEnabled(false);
+ } else {
+ switchUiState(UiState.PUBLIC_KEY_SHOW);
+ cameraFragment.setReadQrEnabled(true);
+ }
+ break;
+ case DATA:
+ if (foreignSyncInfoReceived) {
+ switchUiState(UiState.SYNC_INFO_SHOW_AND_RECEIVED);
+ cameraFragment.setReadQrEnabled(false);
+ } else {
+ switchUiState(UiState.SYNC_INFO_SHOW);
+ cameraFragment.setReadQrEnabled(true);
+ }
+ break;
}
- };
- /**
- * Called when "prev button" is clicked
- */
+ currentSyncState = state;
+ }
+
+ private void switchFragment(SyncState state) {
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+ String camTag = CameraFragment.class.getSimpleName();
+ String settingsTag = UploadSettingsFragment.class.getSimpleName();
+
+ switch (state) {
+ case PUBLIC_KEY:
+ case DATA:
+ cameraFragment = (CameraFragment) fragmentManager.findFragmentByTag(camTag);
+ if (cameraFragment != null) {
+ fragmentTransaction.show(cameraFragment);
+ } else {
+ cameraFragment = new CameraFragment();
+ cameraFragment.setOnQrAvailableListener(onReadQrCode);
+ fragmentTransaction.add(R.id.fragmentContainer, cameraFragment, camTag);
+ }
+
+ UploadSettingsFragment uploadSettingsFragment = (UploadSettingsFragment) fragmentManager.findFragmentByTag(settingsTag);
+ if (uploadSettingsFragment != null) {
+ fragmentTransaction.hide(uploadSettingsFragment);
+ }
+
+ fragmentTransaction.commit();
+ break;
+ }
+ }
+
+ private void displayQr(SyncState state) {
+ switch (state) {
+ case PUBLIC_KEY:
+ qrCode.setImageBitmap(publicKeyQrCode);
+ qrFrame.setVisibility(View.VISIBLE);
+ break;
+ case DATA:
+ qrCode.setImageBitmap(syncInfoQrCode);
+ qrFrame.setVisibility(View.VISIBLE);
+ break;
+ }
+ }
+
+ private void switchUiState(final UiState state) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ switch (state) {
+ case PUBLIC_KEY_SHOW:
+ prevButton.setImageDrawable(getDrawable(R.drawable.ic_close));
+ prevButton.setVisibility(View.VISIBLE);
+ nextButton.setVisibility(View.INVISIBLE);
+ qrReceivedFeedback(false);
+ break;
+ case PUBLIC_KEY_SHOW_AND_RECEIVED:
+ prevButton.setImageDrawable(getDrawable(R.drawable.ic_close));
+ nextButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_forward));
+ prevButton.setVisibility(View.VISIBLE);
+ nextButton.setVisibility(View.VISIBLE);
+ cameraFragment.disablePreview();
+ qrReceivedFeedback(true);
+ break;
+ case SYNC_INFO_SHOW:
+ prevButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_back));
+ nextButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_forward));
+ nextButton.setVisibility(View.INVISIBLE);
+ prevButton.setVisibility(View.VISIBLE);
+ cameraFragment.enablePreview();
+ qrReceivedFeedback(false);
+ break;
+ case SYNC_INFO_SHOW_AND_RECEIVED:
+ prevButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_back));
+ nextButton.setImageDrawable(getDrawable(R.drawable.ic_check));
+ nextButton.setVisibility(View.VISIBLE);
+ prevButton.setVisibility(View.VISIBLE);
+ cameraFragment.disablePreview();
+ qrReceivedFeedback(true);
+ break;
+ }
+ }
+ });
+ }
+
+ // listener
+
private View.OnClickListener onPrevClicked = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (currentSyncState) {
- case settings:
+ case PUBLIC_KEY:
finish();
break;
-
- case publicKeyExchange:
- switchState(SyncState.settings);
- break;
-
- case dataExchange:
- switchState(SyncState.publicKeyExchange);
+ case DATA:
+ switchState(SyncState.PUBLIC_KEY);
break;
}
}
};
- /**
- * Called when the camera fragment detects a qr code
- */
- private CameraFragment.QrScanCallback onQrCodeScanned = new CameraFragment.QrScanCallback() {
+ private View.OnClickListener onNextClicked = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ switch (currentSyncState) {
+ case PUBLIC_KEY:
+ switchState(SyncState.DATA);
+ break;
+
+ case DATA:
+ uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.PENDING);
+ preferenceManager.addUploadInformation(uploadInformation);
+
+ Intent i = new Intent(SyncActivity.this, UploadInfoActivity.class);
+ i.putExtra(UploadInfoActivity.EXTRA_UPLOAD_INFO_UUID, uploadInformation.getUuid());
+ startActivity(i);
+ finish();
+ break;
+ }
+ }
+ };
+
+ private CameraFragment.QrScanCallback onReadQrCode = new CameraFragment.QrScanCallback() {
@Override
public void qrScanResult(String qrData) {
cameraFragment.setReadQrEnabled(false);
switch (currentSyncState) {
- case publicKeyExchange:
+ case PUBLIC_KEY:
try {
final PublicKey pk = DiffieHellman.publicKeyFromString(qrData);
diffieHellman.setForeignPublicKey(pk);
-
- syncInfoQr = generateSyncInfoQr();
-
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- nextButton.setVisibility(View.VISIBLE);
- cameraFragment.disablePreview();
- qrReceivedFeedback();
- }
- });
+ syncInfoQrCode = generateSyncInfoQr();
+ switchUiState(UiState.PUBLIC_KEY_SHOW_AND_RECEIVED);
+ foreignPublicKeyReceived = true;
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
Snackbar.make(rootLayout, "Invalid key", Snackbar.LENGTH_SHORT).show();
- cameraFragment.setReadQrEnabled(true);
+ switchUiState(UiState.PUBLIC_KEY_SHOW);
}
break;
- case dataExchange:
- cameraFragment.setReadQrEnabled(false);
-
+ case DATA:
try {
final SyncInformation remoteSyncInfo = new Gson().fromJson(diffieHellman.decrypt(qrData), SyncInformation.class);
- uploadInformation.setRemote(remoteSyncInfo);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- cameraFragment.disablePreview();
- nextButton.setVisibility(View.VISIBLE);
- qrReceivedFeedback();
+ List uploadInformationList = preferenceManager.getUploadInformationList();
+
+ if (uploadInformationList != null) {
+ for (final UploadInformation ui : uploadInformationList) {
+ if (ui.getRemote().organisation.uuid.equals(remoteSyncInfo.organisation.uuid)) {
+ DialogManager.syncAlreadyExistsDialog(SyncActivity.this, new DialogManager.IDialogFeedback() {
+ @Override
+ public void positive() {
+ uploadInformation.setUuid(ui.getUuid());
+ }
+
+ @Override
+ public void negative() {
+ finish();
+ }
+ });
+ }
}
- });
+ }
+ uploadInformation.setRemote(remoteSyncInfo);
+ switchUiState(UiState.SYNC_INFO_SHOW_AND_RECEIVED);
+ foreignSyncInfoReceived = true;
} catch (JsonSyntaxException e) {
Snackbar.make(rootLayout, "Sync information unreadable", Snackbar.LENGTH_SHORT).show();
- cameraFragment.setReadQrEnabled(true);
+ switchUiState(UiState.SYNC_INFO_SHOW);
}
break;
}
}
};
+ // aux
- private void switchUiState(SyncState state) {
-
- bottomSheetIcon.setVisibility(View.INVISIBLE);
- bottomSheetBehavior.setSwipeable(false);
- bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
-
- switch (state) {
- case settings:
- prevButton.setImageDrawable(getDrawable(R.drawable.ic_close));
- prevButton.setVisibility(View.VISIBLE);
- nextButton.setVisibility(View.VISIBLE);
- hideQrCode();
- break;
- case publicKeyExchange:
- prevButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_back));
- prevButton.setVisibility(View.VISIBLE);
-
- nextButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_forward));
- nextButton.setVisibility(View.GONE);
- showQrCode(publicKeyQr);
- break;
- case dataExchange:
- prevButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_back));
- prevButton.setVisibility(View.VISIBLE);
-
- nextButton.setImageDrawable(getDrawable(R.drawable.ic_cloud_upload));
- nextButton.setVisibility(View.GONE);
-
- cameraFragment.enablePreview();
- cameraFragment.setReadQrEnabled(true);
- showQrCode(syncInfoQr);
- break;
- }
- }
-
- private void switchState(SyncState state) {
-
- FragmentManager fragmentManager = getSupportFragmentManager();
- FragmentTransaction transaction = fragmentManager.beginTransaction();
-
- if (currentSyncState != state) {
- if (state.value < currentSyncState.value) {
- transaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
- } else {
- transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
- }
- }
-
- currentSyncState = state;
-
- switchUiState(currentSyncState);
-
- switch (currentSyncState) {
- case settings:
- String fragTag = SyncOptionsFragment.class.getSimpleName();
- syncOptionsFragment = (SyncOptionsFragment) fragmentManager.findFragmentByTag(fragTag);
-
- if (syncOptionsFragment == null) {
- syncOptionsFragment = new SyncOptionsFragment();
- }
-
- transaction.replace(R.id.sync_fragment_container, syncOptionsFragment, fragTag);
- transaction.commit();
- break;
-
- case publicKeyExchange:
- fragTag = CameraFragment.class.getSimpleName();
- cameraFragment = (CameraFragment) fragmentManager.findFragmentByTag(fragTag);
-
- if (cameraFragment == null) {
- cameraFragment = new CameraFragment();
- cameraFragment.setOnQrAvailableListener(onQrCodeScanned);
- }
-
- transaction.replace(R.id.sync_fragment_container, cameraFragment, fragTag);
- transaction.commit();
- break;
-
- case dataExchange:
- fragTag = CameraFragment.class.getSimpleName();
- cameraFragment = (CameraFragment) fragmentManager.findFragmentByTag(fragTag);
-
- if (cameraFragment == null) {
- cameraFragment = new CameraFragment();
- cameraFragment.setOnQrAvailableListener(onQrCodeScanned);
- }
-
- transaction.replace(R.id.sync_fragment_container, cameraFragment, fragTag);
- transaction.commit();
- break;
- }
- }
-
-
- private Bitmap generatePublicKeyQr() {
- return qrCodeGenerator.generateQrCode(DiffieHellman.publicKeyToString(diffieHellman.getPublicKey()));
- }
-
- private Bitmap generateSyncInfoQr() {
+ private SyncInformation generateLocalSyncInfo() {
SyncInformation syncInformation = new SyncInformation();
syncInformation.organisation = preferenceManager.getUserOrganisation().toSyncOrganisation();
syncInformation.syncUserAuthkey = new RandomString(40).nextString();
@@ -335,6 +331,12 @@ public class SyncActivity extends AppCompatActivity {
syncInformation.syncUserPassword = new RandomString(16).nextString();
syncInformation.syncUserEmail = preferenceManager.getUserInfo().email;
+ return syncInformation;
+ }
+
+ private Bitmap generateSyncInfoQr() {
+ SyncInformation syncInformation = generateLocalSyncInfo();
+
uploadInformation.setLocal(syncInformation);
// encrypt serialized content
@@ -344,80 +346,18 @@ public class SyncActivity extends AppCompatActivity {
return qrCodeGenerator.generateQrCode(encrypted);
}
-
- private void showQrCode(final Bitmap bitmap) {
+ private void qrReceivedFeedback(final boolean done) {
runOnUiThread(new Runnable() {
@Override
public void run() {
-
- qrCodeView.setImageBitmap(bitmap);
- qrCodeView.setAlpha(0f);
- qrCodeView.setVisibility(View.VISIBLE);
- qrCodeView.setScaleX(0.9f);
- qrCodeView.setScaleY(0.6f);
- qrCodeView.animate()
- .scaleX(1f)
- .scaleY(1f)
- .alpha(1f)
- .setDuration(250)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- qrCodeView.setVisibility(View.VISIBLE);
- }
- });
+ if (done) {
+ qrHint.setCompoundDrawablesWithIntrinsicBounds(getDrawable(R.drawable.ic_check_outline), null, null, null);
+ qrHint.setCompoundDrawableTintList(ColorStateList.valueOf(getColor(R.color.status_green)));
+ } else {
+ qrHint.setCompoundDrawablesWithIntrinsicBounds(getDrawable(R.drawable.ic_info_outline), null, null, null);
+ qrHint.setCompoundDrawableTintList(ColorStateList.valueOf(getColor(R.color.status_amber)));
+ }
}
});
}
-
- private void hideQrCode() {
-
- if (qrCodeView.getVisibility() == View.GONE) {
- return;
- }
-
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- qrCodeView.setAlpha(1f);
- qrCodeView.setVisibility(View.VISIBLE);
- qrCodeView.setScaleX(1f);
- qrCodeView.setScaleY(1f);
- qrCodeView.animate()
- .scaleX(0f)
- .scaleY(0f)
- .alpha(0f)
- .setDuration(250)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- qrCodeView.setVisibility(View.GONE);
- }
- });
- }
- });
- }
-
- private void qrReceivedFeedback() {
- bottomSheetIcon.setScaleX(0f);
- bottomSheetIcon.setScaleY(0f);
- bottomSheetIcon.setVisibility(View.VISIBLE);
- bottomSheetIcon.animate()
- .scaleY(1f)
- .scaleX(1f)
- .setDuration(500);
- bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
- bottomSheetBehavior.setSwipeable(true);
-
- switch (currentSyncState) {
- case publicKeyExchange:
- bottomSheetText.setText("Received public key from partner");
- break;
-
- case dataExchange:
- bottomSheetText.setText("Received sync information from partner");
- break;
- }
- }
-
}
diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java
index cbb8dc3..7bdcb49 100644
--- a/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java
+++ b/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java
@@ -1,5 +1,6 @@
package lu.circl.mispbump.activities;
+import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
@@ -9,9 +10,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
-import com.google.gson.Gson;
import java.io.IOException;
import java.util.List;
@@ -29,34 +28,67 @@ import lu.circl.mispbump.models.restModels.User;
public class UploadActivity extends AppCompatActivity {
- public static final String EXTRA_UPLOAD_INFO = "uploadInformation";
+ public static String EXTRA_UPLOAD_INFO = "uploadInformation";
private PreferenceManager preferenceManager;
- private MispRestClient restClient;
private UploadInformation uploadInformation;
private CoordinatorLayout rootLayout;
-
+ private MispRestClient restClient;
private UploadAction availableAction, orgAction, userAction, serverAction;
+ private boolean errorWhileUpload;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload);
+
+ preferenceManager = PreferenceManager.getInstance(UploadActivity.this);
+ restClient = MispRestClient.getInstance(this);
+
parseExtra();
- init();
+ initViews();
+ startUpload();
}
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+
+ if (item.getItemId() == android.R.id.home) {
+ saveCurrentState();
+ finish();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ saveCurrentState();
+ }
+
+
private void parseExtra() {
- String uploadInfoString = getIntent().getStringExtra(EXTRA_UPLOAD_INFO);
- uploadInformation = new Gson().fromJson(uploadInfoString, UploadInformation.class);
- assert uploadInformation != null;
+ Intent i = getIntent();
+
+ UUID currentUUID = (UUID) i.getSerializableExtra(EXTRA_UPLOAD_INFO);
+
+ for (UploadInformation ui : preferenceManager.getUploadInformationList()) {
+ if (ui.getUuid().compareTo(currentUUID) == 0) {
+ uploadInformation = ui;
+ return;
+ }
+ }
+
+ if (uploadInformation == null) {
+ throw new RuntimeException("Could not find UploadInfo with UUID {" + currentUUID.toString() + "}");
+ }
}
- private void init() {
- restClient = MispRestClient.getInstance(this);
- preferenceManager = PreferenceManager.getInstance(this);
-
+ private void initViews() {
rootLayout = findViewById(R.id.rootLayout);
// toolbar
@@ -68,32 +100,17 @@ public class UploadActivity extends AppCompatActivity {
ab.setDisplayHomeAsUpEnabled(true);
ab.setHomeAsUpIndicator(R.drawable.ic_close);
- // fab
- FloatingActionButton fab = findViewById(R.id.fab);
- fab.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startUpload();
- }
- });
-
availableAction = findViewById(R.id.availableAction);
orgAction = findViewById(R.id.orgAction);
userAction = findViewById(R.id.userAction);
serverAction = findViewById(R.id.serverAction);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- preferenceManager.addUploadInformation(uploadInformation);
- finish();
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
+ private void saveCurrentState() {
+ if (errorWhileUpload) {
+ uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE);
}
+ preferenceManager.addUploadInformation(uploadInformation);
}
/**
@@ -122,6 +139,7 @@ public class UploadActivity extends AppCompatActivity {
return syncUser;
}
+
private MispRestClient.AvailableCallback availableCallback = new MispRestClient.AvailableCallback() {
@Override
public void available() {
@@ -136,12 +154,15 @@ public class UploadActivity extends AppCompatActivity {
availableAction.setError(error);
uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE);
+ errorWhileUpload = true;
+
Snackbar sb = Snackbar.make(rootLayout, error, Snackbar.LENGTH_INDEFINITE);
sb.setAction("Retry", new View.OnClickListener() {
@Override
public void onClick(View v) {
availableAction.setError(null);
availableAction.setCurrentUploadState(UploadAction.UploadState.LOADING);
+ errorWhileUpload = false;
startUpload();
}
});
@@ -165,9 +186,9 @@ public class UploadActivity extends AppCompatActivity {
public void failure(String error) {
orgAction.setCurrentUploadState(UploadAction.UploadState.ERROR);
orgAction.setError(error);
+ errorWhileUpload = true;
uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE);
- preferenceManager.addUploadInformation(uploadInformation);
}
};
@@ -194,9 +215,9 @@ public class UploadActivity extends AppCompatActivity {
public void failure(String error) {
userAction.setCurrentUploadState(UploadAction.UploadState.ERROR);
userAction.setError(error);
+ errorWhileUpload = true;
uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE);
- preferenceManager.addUploadInformation(uploadInformation);
}
};
@@ -210,17 +231,16 @@ public class UploadActivity extends AppCompatActivity {
public void success(Server server) {
serverAction.setCurrentUploadState(UploadAction.UploadState.DONE);
uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.COMPLETE);
- preferenceManager.addUploadInformation(uploadInformation);
- finish();
+ saveCurrentState();
}
@Override
public void failure(String error) {
serverAction.setCurrentUploadState(UploadAction.UploadState.ERROR);
serverAction.setError(error);
+ errorWhileUpload = true;
uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.FAILURE);
- preferenceManager.addUploadInformation(uploadInformation);
}
};
diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java
new file mode 100644
index 0000000..71dec20
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java
@@ -0,0 +1,243 @@
+package lu.circl.mispbump.activities;
+
+import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.tabs.TabLayout;
+
+import java.util.UUID;
+
+import lu.circl.mispbump.R;
+import lu.circl.mispbump.auxiliary.PreferenceManager;
+import lu.circl.mispbump.fragments.UploadInfoFragment;
+import lu.circl.mispbump.fragments.UploadSettingsFragment;
+import lu.circl.mispbump.models.UploadInformation;
+
+public class UploadInfoActivity extends AppCompatActivity {
+
+ public static String EXTRA_UPLOAD_INFO_UUID = "uploadInformation";
+
+ private PreferenceManager preferenceManager;
+ private UploadInformation uploadInformation;
+ private ViewPagerAdapter viewPagerAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_upload_information_2);
+
+ preferenceManager = PreferenceManager.getInstance(UploadInfoActivity.this);
+
+ // tint statusBar
+ getWindow().setStatusBarColor(getColor(R.color.grey_light));
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+
+ parseExtra();
+ initToolbar();
+ initViewPager();
+ initViews();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_upload_info, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.delete:
+ // TODO delete
+ return true;
+
+ case android.R.id.home:
+ saveCurrentSettings();
+ finish();
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // refresh current uploadInformation
+ if (uploadInformation != null) {
+ uploadInformation = preferenceManager.getUploadInformation(uploadInformation.getUuid());
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ saveCurrentSettings();
+ }
+
+
+ private void parseExtra() {
+ Intent i = getIntent();
+
+ UUID currentUUID = (UUID) i.getSerializableExtra(EXTRA_UPLOAD_INFO_UUID);
+ uploadInformation = preferenceManager.getUploadInformation(currentUUID);
+
+ if (uploadInformation == null) {
+ throw new RuntimeException("Could not find UploadInformation with UUID {" + currentUUID.toString() + "}");
+ }
+ }
+
+ private void initToolbar() {
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar ab = getSupportActionBar();
+ assert ab != null;
+
+
+ TextView tv = findViewById(R.id.syncStatus);
+ int statusColor;
+ String statusText;
+ Drawable statusDrawable;
+
+ switch (uploadInformation.getCurrentSyncStatus()) {
+ case COMPLETE:
+ statusColor = getColor(R.color.status_green);
+ statusText = "Successfully uploaded";
+ statusDrawable = getDrawable(R.drawable.ic_check_outline);
+ break;
+
+ case FAILURE:
+ statusColor = getColor(R.color.status_red);
+ statusText = "Error while uploading";
+ statusDrawable = getDrawable(R.drawable.ic_error_outline);
+ break;
+
+ case PENDING:
+ statusColor = getColor(R.color.status_amber);
+ statusText = "Not uploaded yet";
+ statusDrawable = getDrawable(R.drawable.ic_pending);
+ break;
+
+ default:
+ statusColor = getColor(R.color.status_green);
+ statusText = "Successfully uploaded";
+ statusDrawable = getDrawable(R.drawable.ic_check_outline);
+ break;
+ }
+
+ tv.setText(statusText);
+ tv.setTextColor(statusColor);
+ tv.setCompoundDrawablesWithIntrinsicBounds(null, null, statusDrawable, null);
+ tv.setCompoundDrawableTintList(ColorStateList.valueOf(statusColor));
+
+ ab.setTitle(uploadInformation.getRemote().organisation.name);
+
+ ab.setDisplayShowTitleEnabled(true);
+ ab.setDisplayShowCustomEnabled(false);
+ ab.setDisplayHomeAsUpEnabled(true);
+ }
+
+ private void initViewPager() {
+ ViewPager viewPager = findViewById(R.id.viewPager);
+ TabLayout tabLayout = findViewById(R.id.tabLayout);
+
+ viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), uploadInformation);
+
+ viewPager.setAdapter(viewPagerAdapter);
+ tabLayout.setupWithViewPager(viewPager);
+ }
+
+ private void initViews() {
+ FloatingActionButton fab = findViewById(R.id.fab);
+
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ saveCurrentSettings();
+
+ Intent i = new Intent(UploadInfoActivity.this, UploadActivity.class);
+ i.putExtra(UploadActivity.EXTRA_UPLOAD_INFO, uploadInformation.getUuid());
+ startActivity(i);
+ }
+ });
+ }
+
+ private void saveCurrentSettings() {
+ uploadInformation.setAllowSelfSigned(viewPagerAdapter.uploadSettingsFragment.getAllowSelfSigned());
+ uploadInformation.setPull(viewPagerAdapter.uploadSettingsFragment.getPull());
+ uploadInformation.setPush(viewPagerAdapter.uploadSettingsFragment.getPush());
+ uploadInformation.setCached(viewPagerAdapter.uploadSettingsFragment.getCache());
+
+ preferenceManager.addUploadInformation(uploadInformation);
+ }
+
+
+ class ViewPagerAdapter extends FragmentPagerAdapter {
+
+ private UploadSettingsFragment uploadSettingsFragment;
+ private UploadInfoFragment uploadInfoFragment = new UploadInfoFragment();
+
+ ViewPagerAdapter(@NonNull FragmentManager fm, UploadInformation uploadInformation) {
+ super(fm, ViewPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
+ uploadSettingsFragment = new UploadSettingsFragment(uploadInformation);
+ }
+
+ @NonNull
+ @Override
+ public Fragment getItem(int position) {
+ switch (position) {
+ case 0:
+ return uploadSettingsFragment;
+
+ case 1:
+ return uploadInfoFragment;
+
+ default:
+ uploadSettingsFragment = new UploadSettingsFragment();
+ return uploadSettingsFragment;
+ }
+ }
+
+ @Nullable
+ @Override
+ public CharSequence getPageTitle(int position) {
+ switch (position) {
+ case 0:
+ return "Permissions";
+
+ case 1:
+ return "Credentials";
+
+ default:
+ return "N/A";
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return 2;
+ }
+ }
+}
diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadInformationActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadInformationActivity.java
deleted file mode 100644
index 48e7496..0000000
--- a/app/src/main/java/lu/circl/mispbump/activities/UploadInformationActivity.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package lu.circl.mispbump.activities;
-
-import android.animation.ValueAnimator;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Bundle;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.ActionBar;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
-import androidx.core.widget.ImageViewCompat;
-
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.gson.Gson;
-
-import lu.circl.mispbump.R;
-import lu.circl.mispbump.models.UploadInformation;
-
-public class UploadInformationActivity extends AppCompatActivity {
-
- public static String EXTRA_UPLOAD_INFO_KEY = "uploadInformation";
-
- private View rootLayout;
- private ImageView syncStatusIcon;
-
- private UploadInformation uploadInformation;
- private FloatingActionButton fab;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_upload_information);
-
-
- parseExtra();
- init();
- tintSystemBars();
- populateContent();
- }
-
- private void parseExtra() {
- String uploadInfo = getIntent().getStringExtra(EXTRA_UPLOAD_INFO_KEY);
- this.uploadInformation = new Gson().fromJson(uploadInfo, UploadInformation.class);
- }
-
- private void init() {
- rootLayout = findViewById(R.id.rootLayout);
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- actionBar.setHomeAsUpIndicator(R.drawable.ic_close);
- actionBar.setDisplayHomeAsUpEnabled(true);
-
- fab = findViewById(R.id.fab);
-
- syncStatusIcon = findViewById(R.id.syncStatus);
- }
-
- private void populateContent() {
- switch (uploadInformation.getCurrentSyncStatus()) {
- case COMPLETE:
- ImageViewCompat.setImageTintList(syncStatusIcon, ColorStateList.valueOf(getColor(R.color.status_green)));
- syncStatusIcon.setImageResource(R.drawable.ic_check_outline);
- fab.hide();
- break;
- case FAILURE:
- ImageViewCompat.setImageTintList(syncStatusIcon, ColorStateList.valueOf(getColor(R.color.status_red)));
- syncStatusIcon.setImageResource(R.drawable.ic_error_outline);
- break;
- case PENDING:
- ImageViewCompat.setImageTintList(syncStatusIcon, ColorStateList.valueOf(getColor(R.color.status_amber)));
- syncStatusIcon.setImageResource(R.drawable.ic_info_outline);
- break;
- }
-
- TextView name = findViewById(R.id.orgName);
- name.setText(uploadInformation.getRemote().organisation.name);
- }
-
- @Override
- protected void onPostCreate(@Nullable Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
-
- fab.show();
- }
-
- @Override
- public void postponeEnterTransition() {
- super.postponeEnterTransition();
- fab.show();
- }
-
- @Override
- public void startPostponedEnterTransition() {
- super.startPostponedEnterTransition();
- fab.show();
- }
-
- private void tintSystemBars() {
- // Initial colors of each system bar.
- final int statusBarColor = getColor(R.color.white);
- final int toolbarColor = getColor(R.color.white);
-
- // Desired final colors of each bar.
- final int statusBarToColor = getColor(R.color.colorPrimary);
- final int toolbarToColor = getColor(R.color.colorPrimary);
-
- ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
- anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- // Use animation position to blend colors.
- float position = animation.getAnimatedFraction();
-
- // Apply blended color to the status bar.
- int blended = blendColors(statusBarColor, statusBarToColor, position);
- getWindow().setStatusBarColor(blended);
-
- blended = blendColors(toolbarColor, toolbarToColor, position);
- getSupportActionBar().setBackgroundDrawable(new ColorDrawable(blended));
- }
- });
-
- anim.setDuration(500).start();
- }
-
- private int blendColors(int from, int to, float ratio) {
- final float inverseRatio = 1f - ratio;
-
- final float r = Color.red(to) * ratio + Color.red(from) * inverseRatio;
- final float g = Color.green(to) * ratio + Color.green(from) * inverseRatio;
- final float b = Color.blue(to) * ratio + Color.blue(from) * inverseRatio;
-
- return Color.rgb((int) r, (int) g, (int) b);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-}
diff --git a/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java b/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java
index bba9499..7dadcb7 100644
--- a/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java
+++ b/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java
@@ -5,6 +5,8 @@ import android.content.res.ColorStateList;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.widget.ImageViewCompat;
@@ -15,34 +17,30 @@ import java.util.List;
import lu.circl.mispbump.R;
import lu.circl.mispbump.interfaces.OnRecyclerItemClickListener;
import lu.circl.mispbump.models.UploadInformation;
-import lu.circl.mispbump.viewholders.UploadInfoListViewHolder;
-public class UploadInfoAdapter extends RecyclerView.Adapter {
+public class UploadInfoAdapter extends RecyclerView.Adapter {
private Context context;
private List items;
private OnRecyclerItemClickListener onRecyclerItemClickListener;
+ private OnRecyclerItemClickListener onRecyclerPositionClickListener;
public UploadInfoAdapter(Context context) {
this.context = context;
}
- public UploadInfoAdapter(Context context, List items) {
- this.context = context;
- this.items = items;
- }
@NonNull
@Override
- public UploadInfoListViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
+ public UploadInfoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_upload_information, viewGroup, false);
- return new UploadInfoListViewHolder(v);
+ return new UploadInfoAdapter.ViewHolder(v);
}
@Override
- public void onBindViewHolder(@NonNull final UploadInfoListViewHolder holder, int position) {
+ public void onBindViewHolder(@NonNull final UploadInfoAdapter.ViewHolder holder, final int position) {
final UploadInformation item = items.get(position);
@@ -60,7 +58,7 @@ public class UploadInfoAdapter extends RecyclerView.Adapter items) {
this.items = items;
+ notifyDataSetChanged();
}
+
+ // callbacks
+
public void setOnRecyclerItemClickListener(OnRecyclerItemClickListener onRecyclerItemClickListener) {
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
}
+ public void setOnRecyclerPositionClickListener(OnRecyclerItemClickListener onRecyclerPositionClickListener) {
+ this.onRecyclerPositionClickListener = onRecyclerPositionClickListener;
+ }
+
+ // viewHolder
+
+ static class ViewHolder extends RecyclerView.ViewHolder {
+ View rootView;
+ ImageView syncStatus;
+ TextView orgName, date;
+
+ ViewHolder(@NonNull View itemView) {
+ super(itemView);
+ rootView = itemView;
+ orgName = itemView.findViewById(R.id.orgName);
+ date = itemView.findViewById(R.id.date);
+ syncStatus = itemView.findViewById(R.id.syncStatus);
+ }
+ }
+
}
diff --git a/app/src/main/java/lu/circl/mispbump/auxiliary/DialogManager.java b/app/src/main/java/lu/circl/mispbump/auxiliary/DialogManager.java
index 54597d0..b09f3bf 100644
--- a/app/src/main/java/lu/circl/mispbump/auxiliary/DialogManager.java
+++ b/app/src/main/java/lu/circl/mispbump/auxiliary/DialogManager.java
@@ -20,6 +20,40 @@ import lu.circl.mispbump.security.DiffieHellman;
public class DialogManager {
+ public static void syncAlreadyExistsDialog(Context context, final IDialogFeedback callback) {
+ final AlertDialog.Builder adb = new AlertDialog.Builder(context);
+
+ adb.setTitle("Sync information already exists");
+ adb.setMessage("You already synced with this organisation, would you like to update the information?" +
+ "\nUpdating the information will reset the current authkey!");
+ adb.setPositiveButton("Update", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (callback != null) {
+ callback.positive();
+ }
+ }
+ });
+
+ adb.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (callback != null) {
+ callback.negative();
+ }
+ }
+ });
+
+ Activity act = (Activity) context;
+ act.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ adb.create().show();
+ }
+ });
+ }
+
+
public static void saveAndExitDialog(Context context, final IDialogFeedback callback) {
final AlertDialog.Builder adb = new AlertDialog.Builder(context);
diff --git a/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java b/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java
index 0374059..70b4677 100644
--- a/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java
+++ b/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java
@@ -322,120 +322,104 @@ public class PreferenceManager {
}
- public void setUploadInformationList(List uploadInformationList) {
- KeyStoreWrapper ksw = new KeyStoreWrapper(KeyStoreWrapper.UPLOAD_INFORMATION_ALIAS);
+ private List cachedUploadInformationList;
- try {
- String cipherText = ksw.encrypt(new Gson().toJson(uploadInformationList));
- SharedPreferences.Editor editor = preferences.edit();
- editor.putString(UPLOAD_INFO, cipherText);
- editor.apply();
- } catch (NoSuchPaddingException e) {
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- } catch (BadPaddingException e) {
- e.printStackTrace();
- } catch (IllegalBlockSizeException e) {
- e.printStackTrace();
- }
- }
-
- public List getUploadInformation() {
+ private void loadUploadInformationList() {
KeyStoreWrapper ksw = new KeyStoreWrapper(KeyStoreWrapper.UPLOAD_INFORMATION_ALIAS);
String storedUploadInfoString = preferences.getString(UPLOAD_INFO, null);
Type type = new TypeToken>() {}.getType();
- if (storedUploadInfoString == null) {
- return null;
+ if (storedUploadInfoString == null || storedUploadInfoString.isEmpty()) {
+ cachedUploadInformationList = new ArrayList<>();
+ } else {
+ try {
+ storedUploadInfoString = ksw.decrypt(storedUploadInfoString);
+ cachedUploadInformationList = new Gson().fromJson(storedUploadInfoString, type);
+ } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
}
+ }
+ private void saveUploadInformationList() {
try {
- storedUploadInfoString = ksw.decrypt(storedUploadInfoString);
- } catch (NoSuchPaddingException e) {
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (InvalidAlgorithmParameterException e) {
- e.printStackTrace();
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- } catch (BadPaddingException e) {
- e.printStackTrace();
- } catch (IllegalBlockSizeException e) {
+ KeyStoreWrapper ksw = new KeyStoreWrapper(KeyStoreWrapper.UPLOAD_INFORMATION_ALIAS);
+ String cipherText = ksw.encrypt(new Gson().toJson(cachedUploadInformationList));
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString(UPLOAD_INFO, cipherText);
+ editor.apply();
+ } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
+ }
- return new Gson().fromJson(storedUploadInfoString, type);
+ public List getUploadInformationList() {
+ if (cachedUploadInformationList == null) {
+ loadUploadInformationList();
+ }
+
+ return cachedUploadInformationList;
+ }
+
+ public void setUploadInformationList(List uploadInformationList) {
+ cachedUploadInformationList = uploadInformationList;
+ saveUploadInformationList();
+ }
+
+ public UploadInformation getUploadInformation(UUID uuid) {
+ if (cachedUploadInformationList == null) {
+ loadUploadInformationList();
+ }
+
+ for (UploadInformation ui : cachedUploadInformationList) {
+ if (ui.getUuid().compareTo(uuid) == 0) {
+ return ui;
+ }
+ }
+
+ return null;
}
public void addUploadInformation(UploadInformation uploadInformation) {
- List uploadInformationList = getUploadInformation();
-
- if (uploadInformationList == null) {
- uploadInformationList = new ArrayList<>();
- uploadInformationList.add(uploadInformation);
- setUploadInformationList(uploadInformationList);
- } else {
-
- // check if upload information already exists
- for (int i = 0; i < uploadInformationList.size(); i++) {
- if (uploadInformationList.get(i).getId().compareTo(uploadInformation.getId()) == 0) {
- uploadInformationList.set(i, uploadInformation);
- setUploadInformationList(uploadInformationList);
- return;
- }
- }
-
- uploadInformationList.add(uploadInformation);
- setUploadInformationList(uploadInformationList);
- }
- }
-
- public boolean containsUploadInformation(UUID uuid) {
- List uploadInformationList = getUploadInformation();
-
- if (uploadInformationList == null) {
- return false;
+ if (cachedUploadInformationList == null) {
+ loadUploadInformationList();
}
- for (UploadInformation ui : uploadInformationList) {
- if (ui.getId().compareTo(uuid) == 0) {
- return true;
+ // update if exists
+ for (int i = 0; i < cachedUploadInformationList.size(); i++) {
+ if (cachedUploadInformationList.get(i).getUuid().compareTo(uploadInformation.getUuid()) == 0) {
+ cachedUploadInformationList.set(i, uploadInformation);
+ saveUploadInformationList();
+ return;
}
}
- return false;
+ // else: add
+ cachedUploadInformationList.add(uploadInformation);
+ saveUploadInformationList();
}
- public boolean removeUploadInformation(UUID uuid) {
- Log.d("PREFS", "uuid to delete: " + uuid.toString());
+ public void removeUploadInformation(UUID uuid) {
+ if (cachedUploadInformationList == null) {
+ loadUploadInformationList();
+ }
- List uploadInformationList = getUploadInformation();
-
- for (UploadInformation ui : uploadInformationList) {
-
- Log.d("PREFS", "checking uuid: " + ui.getId().toString());
-
- if (ui.getId().compareTo(uuid) == 0) {
- if (uploadInformationList.size() == 1) {
+ for (UploadInformation ui : cachedUploadInformationList) {
+ if (ui.getUuid().compareTo(uuid) == 0) {
+ if (cachedUploadInformationList.size() == 1) {
clearUploadInformation();
} else {
- uploadInformationList.remove(ui);
- setUploadInformationList(uploadInformationList);
+ cachedUploadInformationList.remove(ui);
+ saveUploadInformationList();
}
- return true;
}
}
-
-
- return false;
}
public void clearUploadInformation() {
+ cachedUploadInformationList.clear();
+
KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.UPLOAD_INFORMATION_ALIAS);
keyStoreWrapper.deleteStoredKey();
diff --git a/app/src/main/java/lu/circl/mispbump/auxiliary/QrCodeGenerator.java b/app/src/main/java/lu/circl/mispbump/auxiliary/QrCodeGenerator.java
index b8a58c6..3f0b100 100644
--- a/app/src/main/java/lu/circl/mispbump/auxiliary/QrCodeGenerator.java
+++ b/app/src/main/java/lu/circl/mispbump/auxiliary/QrCodeGenerator.java
@@ -22,13 +22,10 @@ public class QrCodeGenerator {
}
public Bitmap generateQrCode(String content) {
- Point displaySize = new Point();
- callingActivity.getWindowManager().getDefaultDisplay().getSize(displaySize);
+ int size = getDisplaySize().x;
- int size = displaySize.x;
-
- if (displaySize.x > displaySize.y) {
- size = displaySize.y;
+ if (size > getDisplaySize().y) {
+ size = getDisplaySize().y;
}
size = (int)(size * 0.8);
@@ -48,6 +45,13 @@ public class QrCodeGenerator {
return null;
}
+ public Point getDisplaySize() {
+ Point displaySize = new Point();
+ callingActivity.getWindowManager().getDefaultDisplay().getSize(displaySize);
+
+ return displaySize;
+ }
+
private Bitmap createBitmap(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
@@ -55,7 +59,7 @@ public class QrCodeGenerator {
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
- pixels[offset + x] = matrix.get(x, y) ? 0xFF000000 : 0x99FFFFFF;
+ pixels[offset + x] = matrix.get(x, y) ? 0xFF000000 : 0x00FFFFFF;
}
}
diff --git a/app/src/main/java/lu/circl/mispbump/customViews/ExtendedViewPager.java b/app/src/main/java/lu/circl/mispbump/customViews/ExtendedViewPager.java
new file mode 100644
index 0000000..4bc6e95
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/customViews/ExtendedViewPager.java
@@ -0,0 +1,32 @@
+package lu.circl.mispbump.customViews;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.viewpager.widget.ViewPager;
+
+public class ExtendedViewPager extends ViewPager {
+
+ private boolean swipeEnabled;
+
+ public ExtendedViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return swipeEnabled && super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ return swipeEnabled && super.onTouchEvent(event);
+ }
+
+ public void setPagingEnabled(boolean enabled) {
+ this.swipeEnabled = enabled;
+ }
+}
diff --git a/app/src/main/java/lu/circl/mispbump/customViews/MaterialPreferenceSwitch.java b/app/src/main/java/lu/circl/mispbump/customViews/MaterialPreferenceSwitch.java
new file mode 100644
index 0000000..06d4ba5
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/customViews/MaterialPreferenceSwitch.java
@@ -0,0 +1,63 @@
+package lu.circl.mispbump.customViews;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import lu.circl.mispbump.R;
+
+public class MaterialPreferenceSwitch extends ConstraintLayout {
+
+ private View rootView;
+
+ private TextView titleView, subTitleView;
+ private Switch switchView;
+
+ public MaterialPreferenceSwitch(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ View view = LayoutInflater.from(context).inflate(R.layout.material_preference_switch, this);
+ rootView = view.findViewById(R.id.rootLayout);
+
+ TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaterialPreferenceSwitch);
+ String title = a.getString(R.styleable.MaterialPreferenceSwitch_title);
+ String subTitle = a.getString(R.styleable.MaterialPreferenceSwitch_subtitle);
+ a.recycle();
+
+ titleView = view.findViewById(R.id.material_preference_title);
+ titleView.setText(title);
+
+ subTitleView = view.findViewById(R.id.material_preference_subtitle);
+ subTitleView.setText(subTitle);
+
+ switchView = view.findViewById(R.id.material_preference_switch);
+
+ rootView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (switchView.isEnabled()) {
+ switchView.setChecked(!switchView.isChecked());
+ }
+ }
+ });
+ }
+
+ public void setEnabled(boolean enabled) {
+ switchView.setEnabled(enabled);
+ }
+
+ public void setChecked(boolean checked) {
+ switchView.setChecked(checked);
+ }
+
+ public boolean isChecked() {
+ return switchView.isChecked();
+ }
+
+}
diff --git a/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java b/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java
index 89ef1b6..5a93377 100644
--- a/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java
+++ b/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java
@@ -11,11 +11,12 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.widget.LinearLayoutCompat;
+import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.widget.ImageViewCompat;
import lu.circl.mispbump.R;
-public class UploadAction extends LinearLayoutCompat {
+public class UploadAction extends ConstraintLayout {
private Context context;
@@ -26,7 +27,7 @@ public class UploadAction extends LinearLayoutCompat {
ERROR
}
- private TextView errorView;
+ private TextView titleView, errorView;
private UploadState currentUploadState;
private ImageView stateView;
private ProgressBar progressBar;
@@ -41,20 +42,23 @@ public class UploadAction extends LinearLayoutCompat {
super(context, attrs);
this.context = context;
+ View baseView = LayoutInflater.from(context).inflate(R.layout.view_upload_action_2, this);
+
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.UploadAction);
- String title = a.getString(R.styleable.UploadAction_description);
+
+ titleView = baseView.findViewById(R.id.title);
+ titleView.setText(a.getString(R.styleable.UploadAction_description));
+
a.recycle();
- LayoutInflater inflater = LayoutInflater.from(context);
- View baseView = inflater.inflate(R.layout.view_upload_action, this);
+ errorView = baseView.findViewById(R.id.error);
+ stateView = baseView.findViewById(R.id.stateView);
+ progressBar = baseView.findViewById(R.id.progressBar);
+ }
- errorView = findViewById(R.id.error);
- TextView titleView = baseView.findViewById(R.id.title);
+ public void setTitle(String title) {
titleView.setText(title);
-
- stateView = findViewById(R.id.stateView);
- progressBar = findViewById(R.id.progressBar);
}
/**
@@ -75,12 +79,6 @@ public class UploadAction extends LinearLayoutCompat {
progressBar.setVisibility(GONE);
switch (state) {
- case PENDING:
- stateView.setVisibility(VISIBLE);
- stateView.setImageResource(R.drawable.ic_info_outline);
- ImageViewCompat.setImageTintList(stateView, ColorStateList.valueOf(context.getColor(R.color.status_amber)));
- break;
-
case LOADING:
stateView.setVisibility(GONE);
progressBar.setVisibility(VISIBLE);
@@ -97,6 +95,12 @@ public class UploadAction extends LinearLayoutCompat {
stateView.setImageResource(R.drawable.ic_error_outline);
ImageViewCompat.setImageTintList(stateView, ColorStateList.valueOf(context.getColor(R.color.status_red)));
break;
+
+ case PENDING:
+ stateView.setVisibility(VISIBLE);
+ stateView.setImageResource(R.drawable.ic_info_outline);
+ ImageViewCompat.setImageTintList(stateView, ColorStateList.valueOf(context.getColor(R.color.status_amber)));
+ break;
}
}
diff --git a/app/src/main/java/lu/circl/mispbump/fragments/CameraFragment.java b/app/src/main/java/lu/circl/mispbump/fragments/CameraFragment.java
index a0f9d62..f293c4c 100644
--- a/app/src/main/java/lu/circl/mispbump/fragments/CameraFragment.java
+++ b/app/src/main/java/lu/circl/mispbump/fragments/CameraFragment.java
@@ -73,10 +73,6 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
private int lastAccessedIndex = 0;
private Bitmap[] processQueue = new Bitmap[10];
- ImageProcessingThread() {
- Log.i(TAG, "Image worker thread created");
- }
-
void addToQueue(Bitmap bitmap) {
processQueue[lastAccessedIndex] = bitmap;
// circular array access
@@ -167,7 +163,6 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
@Override
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
- Log.i(TAG, "Width: " + width + "; height: " + height);
openCamera(width, height);
}
@@ -350,7 +345,6 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
} else if (notBigEnough.size() > 0) {
return Collections.max(notBigEnough, new CompareSizesByArea());
} else {
- Log.e(TAG, "Couldn't find any suitable preview size");
return choices[0];
}
}
@@ -359,8 +353,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_camera, container, false);
- hideCamView = v.findViewById(R.id.hideCam);
- hideCamView.setVisibility(View.GONE);
+// hideCamView = v.findViewById(R.id.hideCam);
initRenderScript();
setUpBarcodeDetector();
@@ -370,6 +363,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
autoFitTextureView = view.findViewById(R.id.texture);
+ hideCamView = view.findViewById(R.id.hideCam);
}
@Override
@@ -381,20 +375,6 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
public void onResume() {
super.onResume();
enablePreview();
-// startBackgroundThread();
-//
-// imageProcessingThread = new ImageProcessingThread();
-// imageProcessingThread.start();
-//
-// // When the screen is turned off and turned back on, the SurfaceTexture is already
-// // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
-// // a camera and start preview from here (otherwise, we wait until the surface is ready in
-// // the SurfaceTextureListener).
-// if (autoFitTextureView.isAvailable()) {
-// openCamera(autoFitTextureView.getWidth(), autoFitTextureView.getHeight());
-// } else {
-// autoFitTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
-// }
}
@Override
@@ -511,10 +491,6 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
Size[] sizes = map.getOutputSizes(SurfaceTexture.class);
- for (Size size : sizes) {
- Log.i(TAG, size.toString());
- }
-
// Danger, W.R.! Attempting to use too large a preview size could exceed the camera
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
// garbage capture data.
@@ -802,12 +778,6 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
public interface QrScanCallback {
void qrScanResult(String qrData);
}
-
- public interface CameraReadyCallback {
- void ready();
- }
-
- private CameraReadyCallback cameraReadyCallback;
private boolean readQrEnabled = true;
private BarcodeDetector barcodeDetector;
private RenderScript renderScript;
@@ -865,6 +835,18 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
}
public void disablePreview() {
+
+ if (hideCamView.getAlpha() == 1 && hideCamView.getVisibility() == View.VISIBLE) {
+ closeCamera();
+ stopBackgroundThread();
+
+ if (imageProcessingThread.isAlive()) {
+ imageProcessingThread.isRunning = false;
+ }
+
+ return;
+ }
+
hideCamView.setAlpha(0f);
hideCamView.setVisibility(View.VISIBLE);
hideCamView.animate()
@@ -896,19 +878,15 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
autoFitTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
- hideCamView.setAlpha(1f);
hideCamView.setVisibility(View.VISIBLE);
+ hideCamView.setAlpha(1f);
hideCamView.animate()
.alpha(0f)
- .setStartDelay(100)
.setDuration(1000)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
hideCamView.setVisibility(View.GONE);
- if (cameraReadyCallback != null) {
- cameraReadyCallback.ready();
- }
}
});
}
@@ -926,9 +904,5 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
public void setOnQrAvailableListener(QrScanCallback callback) {
qrResultCallback = callback;
}
-
- public void setCameraReadyCallback(CameraReadyCallback callback) {
- this.cameraReadyCallback = callback;
- }
}
diff --git a/app/src/main/java/lu/circl/mispbump/fragments/SyncFragmentAdapter.java b/app/src/main/java/lu/circl/mispbump/fragments/SyncFragmentAdapter.java
new file mode 100644
index 0000000..bb59154
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/fragments/SyncFragmentAdapter.java
@@ -0,0 +1,75 @@
+package lu.circl.mispbump.fragments;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+
+public class SyncFragmentAdapter extends FragmentPagerAdapter {
+
+ public CameraFragment cameraFragment_1, cameraFragment_2;
+ private UploadSettingsFragment uploadSettingsFragment;
+
+ public SyncFragmentAdapter(@NonNull FragmentManager fm) {
+ super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
+ }
+
+ private CameraFragment.QrScanCallback scanCallback;
+
+ @NonNull
+ @Override
+ public Fragment getItem(int position) {
+ switch (position) {
+ case 0:
+ if (cameraFragment_1 == null) {
+ cameraFragment_1 = new CameraFragment();
+ }
+
+ if (scanCallback != null) {
+ cameraFragment_1.setOnQrAvailableListener(scanCallback);
+ }
+
+ return cameraFragment_1;
+
+ case 1:
+ if (cameraFragment_2 == null) {
+ cameraFragment_2 = new CameraFragment();
+ }
+
+ if (scanCallback != null) {
+ cameraFragment_1.setOnQrAvailableListener(scanCallback);
+ }
+
+ return cameraFragment_2;
+
+ case 2:
+ if (uploadSettingsFragment == null) {
+ uploadSettingsFragment = new UploadSettingsFragment();
+ }
+
+ return uploadSettingsFragment;
+
+ default:
+ return new CameraFragment();
+ }
+ }
+
+ public void setQrReceivedCallback(CameraFragment.QrScanCallback qrScanCallback) {
+ this.scanCallback = qrScanCallback;
+ }
+
+ public void disableCameraPreview() {
+ if (cameraFragment_1 != null) {
+ cameraFragment_1.disablePreview();
+ }
+
+ if (cameraFragment_2 != null) {
+ cameraFragment_2.disablePreview();
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return 3;
+ }
+}
diff --git a/app/src/main/java/lu/circl/mispbump/fragments/UploadInfoFragment.java b/app/src/main/java/lu/circl/mispbump/fragments/UploadInfoFragment.java
new file mode 100644
index 0000000..cea77c9
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/fragments/UploadInfoFragment.java
@@ -0,0 +1,24 @@
+package lu.circl.mispbump.fragments;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+
+import lu.circl.mispbump.R;
+
+public class UploadInfoFragment extends Fragment {
+
+ public UploadInfoFragment () {}
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.fragment_upload_info, container, false);
+
+ return v;
+ }
+
+}
diff --git a/app/src/main/java/lu/circl/mispbump/fragments/SyncOptionsFragment.java b/app/src/main/java/lu/circl/mispbump/fragments/UploadSettingsFragment.java
similarity index 54%
rename from app/src/main/java/lu/circl/mispbump/fragments/SyncOptionsFragment.java
rename to app/src/main/java/lu/circl/mispbump/fragments/UploadSettingsFragment.java
index 81f289d..09a92fe 100644
--- a/app/src/main/java/lu/circl/mispbump/fragments/SyncOptionsFragment.java
+++ b/app/src/main/java/lu/circl/mispbump/fragments/UploadSettingsFragment.java
@@ -1,36 +1,63 @@
package lu.circl.mispbump.fragments;
import android.os.Bundle;
-import androidx.annotation.NonNull;
-
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Switch;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
import lu.circl.mispbump.R;
+import lu.circl.mispbump.customViews.MaterialPreferenceSwitch;
+import lu.circl.mispbump.models.UploadInformation;
-public class SyncOptionsFragment extends Fragment {
+public class UploadSettingsFragment extends Fragment {
- private Switch allowSelfSigned, push, pull, cache;
+ private MaterialPreferenceSwitch allowSelfSigned, push, pull, cache;
+ private UploadInformation uploadInformation;
+
+ public UploadSettingsFragment() {
+ }
+
+ public UploadSettingsFragment(UploadInformation uploadInformation) {
+ this.uploadInformation = uploadInformation;
+ }
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_sync_options, container, false);
+ View v = inflater.inflate(R.layout.fragment_upload_settings, container, false);
allowSelfSigned = v.findViewById(R.id.self_signed_switch);
push = v.findViewById(R.id.push_switch);
pull = v.findViewById(R.id.pull_switch);
cache = v.findViewById(R.id.cache_switch);
+ populateContent();
+
return v;
}
+ private void populateContent() {
+ if (uploadInformation == null) {
+ return;
+ }
+
+ allowSelfSigned.setChecked(uploadInformation.isAllowSelfSigned());
+ push.setChecked(uploadInformation.isPush());
+ pull.setChecked(uploadInformation.isPull());
+ cache.setChecked(uploadInformation.isCached());
+ }
+
+ public void setUploadInfo(UploadInformation uploadInfo) {
+ this.uploadInformation = uploadInfo;
+ }
+
public boolean getAllowSelfSigned() {
return allowSelfSigned.isChecked();
}
+
public void setAllowSelfSigned(boolean allowSelfSigned) {
this.allowSelfSigned.setChecked(allowSelfSigned);
}
@@ -38,6 +65,7 @@ public class SyncOptionsFragment extends Fragment {
public boolean getPush() {
return push.isChecked();
}
+
public void setPush(boolean push) {
this.push.setChecked(push);
}
@@ -45,6 +73,7 @@ public class SyncOptionsFragment extends Fragment {
public boolean getPull() {
return pull.isChecked();
}
+
public void setPull(boolean pull) {
this.pull.setChecked(pull);
}
@@ -52,6 +81,7 @@ public class SyncOptionsFragment extends Fragment {
public boolean getCache() {
return cache.isChecked();
}
+
public void setCache(boolean cache) {
this.cache.setChecked(cache);
}
diff --git a/app/src/main/java/lu/circl/mispbump/models/UploadInformation.java b/app/src/main/java/lu/circl/mispbump/models/UploadInformation.java
index 8c4cc59..036bbb2 100644
--- a/app/src/main/java/lu/circl/mispbump/models/UploadInformation.java
+++ b/app/src/main/java/lu/circl/mispbump/models/UploadInformation.java
@@ -2,14 +2,13 @@ package lu.circl.mispbump.models;
import androidx.annotation.NonNull;
-import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
-public class UploadInformation implements Serializable {
+public class UploadInformation {
public enum SyncStatus {
COMPLETE,
@@ -17,7 +16,7 @@ public class UploadInformation implements Serializable {
PENDING
}
- private UUID id;
+ private UUID uuid;
private SyncStatus currentSyncStatus = SyncStatus.PENDING;
@@ -29,19 +28,8 @@ public class UploadInformation implements Serializable {
private Date date;
public UploadInformation() {
- this(null, null);
- }
-
- public UploadInformation(SyncInformation local) {
- this(local, null);
- }
-
- public UploadInformation(SyncInformation local, SyncInformation remote) {
- id = UUID.randomUUID();
+ uuid = UUID.randomUUID();
date = Calendar.getInstance().getTime();
-
- this.local = local;
- this.remote = remote;
}
// getter and setter
@@ -67,11 +55,11 @@ public class UploadInformation implements Serializable {
return remote;
}
- public UUID getId() {
- return id;
+ public UUID getUuid() {
+ return uuid;
}
- public void setId(UUID id) {
- this.id = id;
+ public void setUuid(UUID uuid) {
+ this.uuid = uuid;
}
public void setDate() {
diff --git a/app/src/main/java/lu/circl/mispbump/viewholders/UploadInfoListViewHolder.java b/app/src/main/java/lu/circl/mispbump/viewholders/UploadInfoListViewHolder.java
deleted file mode 100644
index ce2b890..0000000
--- a/app/src/main/java/lu/circl/mispbump/viewholders/UploadInfoListViewHolder.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package lu.circl.mispbump.viewholders;
-
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import lu.circl.mispbump.R;
-
-public class UploadInfoListViewHolder extends RecyclerView.ViewHolder {
-
- public View rootView;
- public ImageView syncStatus;
- public TextView orgName, date;
-
- public UploadInfoListViewHolder(@NonNull View itemView) {
- super(itemView);
-
- rootView = itemView;
-
- orgName = itemView.findViewById(R.id.orgName);
- date = itemView.findViewById(R.id.date);
- syncStatus = itemView.findViewById(R.id.syncStatus);
- }
-}
diff --git a/app/src/main/res/drawable/ic_autorenew.xml b/app/src/main/res/drawable/ic_autorenew.xml
index 3bdee48..62aa67a 100644
--- a/app/src/main/res/drawable/ic_autorenew.xml
+++ b/app/src/main/res/drawable/ic_autorenew.xml
@@ -1,5 +1,9 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_error_outline.xml b/app/src/main/res/drawable/ic_error_outline.xml
index 694bd6e..622ae00 100644
--- a/app/src/main/res/drawable/ic_error_outline.xml
+++ b/app/src/main/res/drawable/ic_error_outline.xml
@@ -1,5 +1,9 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_pending.xml b/app/src/main/res/drawable/ic_pending.xml
new file mode 100644
index 0000000..b7695ae
--- /dev/null
+++ b/app/src/main/res/drawable/ic_pending.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/rect_rounded.xml b/app/src/main/res/drawable/rect_rounded.xml
new file mode 100644
index 0000000..fc92cfa
--- /dev/null
+++ b/app/src/main/res/drawable/rect_rounded.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_rect.xml b/app/src/main/res/drawable/rect_rounded_top.xml
similarity index 66%
rename from app/src/main/res/drawable/rounded_rect.xml
rename to app/src/main/res/drawable/rect_rounded_top.xml
index 8daefbc..7490f72 100644
--- a/app/src/main/res/drawable/rounded_rect.xml
+++ b/app/src/main/res/drawable/rect_rounded_top.xml
@@ -4,6 +4,6 @@
android:color="@color/white"/>
+ android:topLeftRadius="12dp"
+ android:topRightRadius="12dp"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml
index 5efa0f8..07e44a6 100644
--- a/app/src/main/res/layout/activity_home.xml
+++ b/app/src/main/res/layout/activity_home.xml
@@ -4,8 +4,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rootLayout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:animateLayoutChanges="true">
+ android:layout_height="match_parent">
+ android:theme="@style/ToolbarTheme"
+ app:popupTheme="@style/PopupTheme" />
+ android:layout_height="match_parent" />
+ app:layout_constraintTop_toBottomOf="@id/toolbar" />
-
-
+ android:layout_height="match_parent"/>
-
-
-
-
-
-
-
-
+ android:layout_gravity="center"
+ android:background="@drawable/rect_rounded"
+ android:backgroundTint="#99FFFFFF"
+ android:padding="8dp"
+ tools:layout_height="256dp"
+ tools:layout_width="256dp">
-
-
-
-
-
-
-
-
-
-
+ android:orientation="vertical"
+ android:gravity="center_vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_upload.xml b/app/src/main/res/layout/activity_upload.xml
index 37d81d9..ad95b5c 100644
--- a/app/src/main/res/layout/activity_upload.xml
+++ b/app/src/main/res/layout/activity_upload.xml
@@ -34,10 +34,10 @@
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
- app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
- app:title="Check if instance is available" />
+ app:layout_constraintEnd_toEndOf="parent"
+ app:description="Check if instance is available" />
+ app:layout_constraintEnd_toEndOf="parent"
+ app:description="Add organisation" />
+ app:description="Add sync user" />
+ app:description="Add sync server" />
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_upload_information.xml b/app/src/main/res/layout/activity_upload_information.xml
deleted file mode 100644
index 017a195..0000000
--- a/app/src/main/res/layout/activity_upload_information.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_upload_information_2.xml b/app/src/main/res/layout/activity_upload_information_2.xml
new file mode 100644
index 0000000..0e67559
--- /dev/null
+++ b/app/src/main/res/layout/activity_upload_information_2.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/custom_upload_info_title.xml b/app/src/main/res/layout/custom_upload_info_title.xml
new file mode 100644
index 0000000..c65743f
--- /dev/null
+++ b/app/src/main/res/layout/custom_upload_info_title.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_sync_options.xml b/app/src/main/res/layout/fragment_sync_options.xml
deleted file mode 100644
index 7b32505..0000000
--- a/app/src/main/res/layout/fragment_sync_options.xml
+++ /dev/null
@@ -1,147 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_upload_info.xml b/app/src/main/res/layout/fragment_upload_info.xml
new file mode 100644
index 0000000..e387c92
--- /dev/null
+++ b/app/src/main/res/layout/fragment_upload_info.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_upload_settings.xml b/app/src/main/res/layout/fragment_upload_settings.xml
new file mode 100644
index 0000000..3f525e9
--- /dev/null
+++ b/app/src/main/res/layout/fragment_upload_settings.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/material_preference_switch.xml b/app/src/main/res/layout/material_preference_switch.xml
new file mode 100644
index 0000000..c302a9c
--- /dev/null
+++ b/app/src/main/res/layout/material_preference_switch.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_upload_action.xml b/app/src/main/res/layout/view_upload_action.xml
index 9d88e7c..8ba6929 100644
--- a/app/src/main/res/layout/view_upload_action.xml
+++ b/app/src/main/res/layout/view_upload_action.xml
@@ -13,11 +13,13 @@
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textAppearance="@style/Text.Title"
+ android:layout_gravity="center_vertical"
+ android:layout_marginEnd="8dp" />
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_sync.xml b/app/src/main/res/menu/menu_upload_info.xml
similarity index 67%
rename from app/src/main/res/menu/menu_sync.xml
rename to app/src/main/res/menu/menu_upload_info.xml
index 7d4e56e..5ba86a6 100644
--- a/app/src/main/res/menu/menu_sync.xml
+++ b/app/src/main/res/menu/menu_upload_info.xml
@@ -2,8 +2,8 @@
\ No newline at end of file
diff --git a/app/src/main/res/transition/simple.xml b/app/src/main/res/transition/simple.xml
deleted file mode 100644
index f903d98..0000000
--- a/app/src/main/res/transition/simple.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 0f1622a..a0817fb 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -1,9 +1,18 @@
+
+
+
+
-
-
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index d7be4be..949f632 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -2,17 +2,17 @@
#047EB4
#023850
-
#12B3FA
- #8012B3FA
#33000000
-
#FFFFFF
#80FFFFFF
#BDBDBD
+ #F0F0F0
+
+ #000
#4CAF50
#FB8C00
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7738241..f614644 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -6,7 +6,6 @@
MISP Automation Key
No Information
Save Automation Key
- Home
Help
MISP Server URL\nPublic MISP URL\n\nMISP Automation key\nZu finden unter ...
Okay
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 45a61b0..492b408 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,21 +1,8 @@
-
-
-
+
-