diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b2652aa..847368a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,8 +15,6 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
-
-
@@ -31,7 +29,7 @@
android:name=".activities.HomeActivity"
android:label="@string/app_name" />
uploadInformationList = preferenceManager.getUploadInformationList();
+
+ final List uploadInformationList = preferenceManager.getUploadInformationList();
for (final UploadInformation ui : uploadInformationList) {
if (ui.getRemote().organisation.uuid.equals(remoteSyncInfo.organisation.uuid)) {
@@ -274,7 +275,8 @@ public class ExchangeActivity extends AppCompatActivity {
@Override
public void negative() {
// replace credentials too
- preferenceManager.removeUploadInformation(ui.getUuid());
+ uploadInformationList.remove(ui);
+ preferenceManager.setUploadInformationList(uploadInformationList);
}
});
diff --git a/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java b/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java
deleted file mode 100644
index 373596b..0000000
--- a/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java
+++ /dev/null
@@ -1,357 +0,0 @@
-package lu.circl.mispbump.activities;
-
-import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentTransaction;
-
-import com.google.android.material.snackbar.Snackbar;
-import com.google.gson.Gson;
-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.models.SyncInformation;
-import lu.circl.mispbump.models.UploadInformation;
-import lu.circl.mispbump.security.DiffieHellman;
-
-public class SyncActivity extends AppCompatActivity {
-
- 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;
-
- private PreferenceManager preferenceManager;
- private UploadInformation uploadInformation;
- private QrCodeGenerator qrCodeGenerator;
- private DiffieHellman diffieHellman;
-
- private boolean foreignPublicKeyReceived, foreignSyncInfoReceived;
-
- // Fragments
- private CameraFragment cameraFragment;
-
- // Views
- private CoordinatorLayout rootLayout;
- private FrameLayout qrFrame;
- private ImageView qrCode;
- private TextView qrHint;
- private ImageButton prevButton, nextButton;
-
- private Bitmap publicKeyQrCode, syncInfoQrCode;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_sync);
-
- init();
- initViews();
-
- switchState(SyncState.PUBLIC_KEY);
- }
-
- @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);
-
- qrFrame = findViewById(R.id.qrFrame);
- qrCode = findViewById(R.id.qrCode);
- qrHint = findViewById(R.id.qrInfo);
-
- prevButton = findViewById(R.id.prevButton);
- prevButton.setOnClickListener(onPrevClicked);
-
- nextButton = findViewById(R.id.nextButton);
- nextButton.setOnClickListener(onNextClicked);
- }
-
- private void switchState(SyncState state) {
- switchFragment(state);
- displayQr(state);
-
- 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;
- }
-
- currentSyncState = state;
- }
-
- private void switchFragment(SyncState state) {
- FragmentManager fragmentManager = getSupportFragmentManager();
- FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
-
- String camTag = CameraFragment.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);
- }
-
- 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 PUBLIC_KEY:
- finish();
- break;
- case DATA:
- switchState(SyncState.PUBLIC_KEY);
- break;
- }
- }
- };
-
- 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 PUBLIC_KEY:
- try {
- final PublicKey pk = DiffieHellman.publicKeyFromString(qrData);
- diffieHellman.setForeignPublicKey(pk);
- syncInfoQrCode = generateSyncInfoQr();
- switchUiState(UiState.PUBLIC_KEY_SHOW_AND_RECEIVED);
- foreignPublicKeyReceived = true;
- } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
- Snackbar.make(rootLayout, "Invalid key", Snackbar.LENGTH_SHORT).show();
- switchUiState(UiState.PUBLIC_KEY_SHOW);
- }
- break;
-
- case DATA:
- try {
- final SyncInformation remoteSyncInfo = new Gson().fromJson(diffieHellman.decrypt(qrData), SyncInformation.class);
-
- 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();
- switchUiState(UiState.SYNC_INFO_SHOW);
- }
- break;
- }
- }
- };
-
- // aux
-
- private SyncInformation generateLocalSyncInfo() {
- SyncInformation syncInformation = new SyncInformation();
- syncInformation.organisation = preferenceManager.getUserOrganisation().toSyncOrganisation();
- syncInformation.syncUserAuthkey = new RandomString(40).nextString();
- syncInformation.baseUrl = preferenceManager.getServerUrl();
- 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
- String encrypted = diffieHellman.encrypt(new Gson().toJson(syncInformation));
-
- // generate QR code
- return qrCodeGenerator.generateQrCode(encrypted);
- }
-
- private void qrReceivedFeedback(final boolean done) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- 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)));
- }
- }
- });
- }
-}
diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java
index 71dec20..9911846 100644
--- a/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java
+++ b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java
@@ -1,14 +1,10 @@
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;
@@ -27,27 +23,30 @@ 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.UploadCredentialsFragment;
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";
+ public static String EXTRA_UPLOAD_INFO_UUID = "uploadInformationUuid";
private PreferenceManager preferenceManager;
private UploadInformation uploadInformation;
private ViewPagerAdapter viewPagerAdapter;
+ private FloatingActionButton fab;
+
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_upload_information_2);
+ setContentView(R.layout.activity_upload_information);
preferenceManager = PreferenceManager.getInstance(UploadInfoActivity.this);
// tint statusBar
- getWindow().setStatusBarColor(getColor(R.color.grey_light));
+ getWindow().setStatusBarColor(getColor(R.color.white));
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
parseExtra();
@@ -56,6 +55,23 @@ public class UploadInfoActivity extends AppCompatActivity {
initViews();
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // refresh current uploadInformation
+ if (uploadInformation != null) {
+ uploadInformation = preferenceManager.getUploadInformation(uploadInformation.getUuid());
+ initContent();
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ saveCurrentSettings();
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_upload_info, menu);
@@ -79,22 +95,6 @@ public class UploadInfoActivity extends AppCompatActivity {
}
}
- @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();
@@ -114,47 +114,9 @@ public class UploadInfoActivity extends AppCompatActivity {
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.setHomeAsUpIndicator(R.drawable.ic_close);
ab.setDisplayShowTitleEnabled(true);
- ab.setDisplayShowCustomEnabled(false);
ab.setDisplayHomeAsUpEnabled(true);
}
@@ -163,18 +125,19 @@ public class UploadInfoActivity extends AppCompatActivity {
TabLayout tabLayout = findViewById(R.id.tabLayout);
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), uploadInformation);
-
viewPager.setAdapter(viewPagerAdapter);
+
+ viewPager.addOnPageChangeListener(onPageChangeListener());
+
tabLayout.setupWithViewPager(viewPager);
}
private void initViews() {
- FloatingActionButton fab = findViewById(R.id.fab);
-
+ fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
-
+ // for the UploadActivity to have the latest settings of this UploadInfoObject
saveCurrentSettings();
Intent i = new Intent(UploadInfoActivity.this, UploadActivity.class);
@@ -184,6 +147,26 @@ public class UploadInfoActivity extends AppCompatActivity {
});
}
+ private void initContent() {
+ switch (uploadInformation.getCurrentSyncStatus()) {
+ case COMPLETE:
+
+ break;
+
+ case FAILURE:
+
+ break;
+
+ case PENDING:
+
+ break;
+
+ default:
+
+ break;
+ }
+ }
+
private void saveCurrentSettings() {
uploadInformation.setAllowSelfSigned(viewPagerAdapter.uploadSettingsFragment.getAllowSelfSigned());
uploadInformation.setPull(viewPagerAdapter.uploadSettingsFragment.getPull());
@@ -194,14 +177,39 @@ public class UploadInfoActivity extends AppCompatActivity {
}
+ private ViewPager.OnPageChangeListener onPageChangeListener() {
+ return new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ if (position == 0) {
+ float scale = (1 - positionOffset);
+ fab.setScaleX(scale);
+ fab.setScaleY(scale);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+
+ }
+ };
+ }
+
+
class ViewPagerAdapter extends FragmentPagerAdapter {
private UploadSettingsFragment uploadSettingsFragment;
- private UploadInfoFragment uploadInfoFragment = new UploadInfoFragment();
+ private UploadCredentialsFragment uploadCredentialsFragment;
ViewPagerAdapter(@NonNull FragmentManager fm, UploadInformation uploadInformation) {
super(fm, ViewPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
uploadSettingsFragment = new UploadSettingsFragment(uploadInformation);
+ uploadCredentialsFragment = new UploadCredentialsFragment(uploadInformation);
}
@NonNull
@@ -212,7 +220,7 @@ public class UploadInfoActivity extends AppCompatActivity {
return uploadSettingsFragment;
case 1:
- return uploadInfoFragment;
+ return uploadCredentialsFragment;
default:
uploadSettingsFragment = new UploadSettingsFragment();
@@ -225,7 +233,7 @@ public class UploadInfoActivity extends AppCompatActivity {
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
- return "Permissions";
+ return "Settings";
case 1:
return "Credentials";
diff --git a/app/src/main/java/lu/circl/mispbump/customViews/MaterialPasswordView.java b/app/src/main/java/lu/circl/mispbump/customViews/MaterialPasswordView.java
new file mode 100644
index 0000000..1bc09e8
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/customViews/MaterialPasswordView.java
@@ -0,0 +1,94 @@
+package lu.circl.mispbump.customViews;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.text.method.PasswordTransformationMethod;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import lu.circl.mispbump.R;
+
+public class MaterialPasswordView extends ConstraintLayout {
+
+ private TextView titleView, passwordView;
+ private OnCopyClickListener onCopyClickListener;
+
+
+ public MaterialPasswordView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ View view = LayoutInflater.from(context).inflate(R.layout.material_password_view, this);
+
+ TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaterialPasswordView);
+ final String title = a.getString(R.styleable.MaterialPasswordView_title);
+ final String password = a.getString(R.styleable.MaterialPasswordView_password);
+ a.recycle();
+
+ ImageButton copyButton = view.findViewById(R.id.copy);
+ copyButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onCopyClickListener.onClick(title, getPassword());
+ }
+ });
+
+ titleView = view.findViewById(R.id.material_password_title);
+ titleView.setText(title);
+
+ passwordView = view.findViewById(R.id.material_password);
+ passwordView.setTransformationMethod(new PasswordTransformationMethod());
+ passwordView.setText(password);
+
+ ImageButton visibleToggle = findViewById(R.id.visibleToggle);
+ visibleToggle.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (passwordView.getTransformationMethod() == null) {
+ passwordView.setTransformationMethod(new PasswordTransformationMethod());
+ } else {
+ passwordView.setTransformationMethod(null);
+ }
+ }
+ });
+ }
+
+
+ public void setTitle(String title) {
+ titleView.setText(title);
+ }
+
+ public String getTitle() {
+ return titleView.getText().toString();
+ }
+
+ public void setPassword(String password) {
+ passwordView.setText(password);
+ }
+
+ public String getPassword() {
+ return passwordView.getText().toString();
+ }
+
+ public void setPasswordVisible(boolean visible) {
+ if (!visible) {
+ passwordView.setTransformationMethod(new PasswordTransformationMethod());
+ } else {
+ passwordView.setTransformationMethod(null);
+ }
+ }
+
+
+ public void addOnCopyClickedListener(OnCopyClickListener listener) {
+ onCopyClickListener = listener;
+ }
+
+
+ public interface OnCopyClickListener {
+ void onClick(String title, String password);
+ }
+}
diff --git a/app/src/main/java/lu/circl/mispbump/customViews/MaterialPreferenceText.java b/app/src/main/java/lu/circl/mispbump/customViews/MaterialPreferenceText.java
index dce0ec5..5baf106 100644
--- a/app/src/main/java/lu/circl/mispbump/customViews/MaterialPreferenceText.java
+++ b/app/src/main/java/lu/circl/mispbump/customViews/MaterialPreferenceText.java
@@ -2,18 +2,16 @@ package lu.circl.mispbump.customViews;
import android.content.Context;
import android.content.res.TypedArray;
-
-import androidx.annotation.Nullable;
-import androidx.constraintlayout.widget.ConstraintLayout;
-
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
import lu.circl.mispbump.R;
public class MaterialPreferenceText extends ConstraintLayout {
@@ -33,7 +31,12 @@ public class MaterialPreferenceText extends ConstraintLayout {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaterialPreferenceText);
icon = view.findViewById(R.id.material_preference_src);
- icon.setImageResource(a.getResourceId(R.styleable.MaterialPreferenceText_pref_icon, 0x0));
+ int imageRes = a.getResourceId(R.styleable.MaterialPreferenceText_pref_icon, 0x0);
+ if (imageRes != 0x0){
+ icon.setImageResource(imageRes);
+ } else {
+ icon.setVisibility(GONE);
+ }
title = view.findViewById(R.id.material_preference_title);
title.setText(a.getString(R.styleable.MaterialPreferenceText_title));
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 5a93377..0453070 100644
--- a/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java
+++ b/app/src/main/java/lu/circl/mispbump/customViews/UploadAction.java
@@ -10,7 +10,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
-import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.widget.ImageViewCompat;
@@ -42,7 +41,7 @@ public class UploadAction extends ConstraintLayout {
super(context, attrs);
this.context = context;
- View baseView = LayoutInflater.from(context).inflate(R.layout.view_upload_action_2, this);
+ View baseView = LayoutInflater.from(context).inflate(R.layout.view_upload_action, this);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.UploadAction);
diff --git a/app/src/main/java/lu/circl/mispbump/fragments/UploadCredentialsFragment.java b/app/src/main/java/lu/circl/mispbump/fragments/UploadCredentialsFragment.java
new file mode 100644
index 0000000..9248200
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/fragments/UploadCredentialsFragment.java
@@ -0,0 +1,62 @@
+package lu.circl.mispbump.fragments;
+
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.fragment.app.Fragment;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import lu.circl.mispbump.R;
+import lu.circl.mispbump.customViews.MaterialPasswordView;
+import lu.circl.mispbump.customViews.MaterialPreferenceText;
+import lu.circl.mispbump.models.UploadInformation;
+
+public class UploadCredentialsFragment extends Fragment {
+
+ private View rootLayout;
+ private UploadInformation uploadInformation;
+
+ public UploadCredentialsFragment() {}
+ public UploadCredentialsFragment(UploadInformation uploadInformation) {
+ this.uploadInformation = uploadInformation;
+ }
+
+ private MaterialPasswordView.OnCopyClickListener onCopyClickListener = new MaterialPasswordView.OnCopyClickListener() {
+ @Override
+ public void onClick(String title, String password) {
+ ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText(title, password);
+ clipboard.setPrimaryClip(clip);
+ Snackbar.make(rootLayout, "Copied to clipboard", Snackbar.LENGTH_LONG).show();
+ }
+ };
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.fragment_upload_credentials, container, false);
+
+ rootLayout = v.findViewById(R.id.rootLayout);
+
+ MaterialPreferenceText baseUrl = v.findViewById(R.id.baseUrl);
+ baseUrl.setSubtitle(uploadInformation.getRemote().baseUrl);
+
+ MaterialPasswordView authkey = v.findViewById(R.id.authkey);
+ authkey.setPassword(uploadInformation.getRemote().syncUserAuthkey);
+ authkey.addOnCopyClickedListener(onCopyClickListener);
+
+ MaterialPasswordView password = v.findViewById(R.id.password);
+ password.setPassword(uploadInformation.getRemote().syncUserPassword);
+ password.addOnCopyClickedListener(onCopyClickListener);
+
+ return v;
+ }
+
+}
diff --git a/app/src/main/res/drawable/ic_cloud_upload.xml b/app/src/main/res/drawable/ic_cloud_upload.xml
index 55dbbae..ca7e848 100644
--- a/app/src/main/res/drawable/ic_cloud_upload.xml
+++ b/app/src/main/res/drawable/ic_cloud_upload.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/app/src/main/res/drawable/ic_eye.xml b/app/src/main/res/drawable/ic_eye.xml
new file mode 100644
index 0000000..198d161
--- /dev/null
+++ b/app/src/main/res/drawable/ic_eye.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_file_copy.xml b/app/src/main/res/drawable/ic_file_copy.xml
new file mode 100644
index 0000000..2eb397f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_file_copy.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_sync.xml b/app/src/main/res/layout/activity_exchange.xml
similarity index 100%
rename from app/src/main/res/layout/activity_sync.xml
rename to app/src/main/res/layout/activity_exchange.xml
diff --git a/app/src/main/res/layout/activity_upload.xml b/app/src/main/res/layout/activity_upload.xml
index ad95b5c..c457432 100644
--- a/app/src/main/res/layout/activity_upload.xml
+++ b/app/src/main/res/layout/activity_upload.xml
@@ -6,6 +6,7 @@
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:animateLayoutChanges="true"
tools:context=".activities.UploadActivity">
+ android:layout_height="match_parent"
+ android:animateLayoutChanges="true">
@@ -19,21 +18,6 @@
app:popupTheme="@style/PopupTheme"
app:theme="@style/ToolbarTheme.Light"/>
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/fragment_upload_credentials.xml b/app/src/main/res/layout/fragment_upload_credentials.xml
new file mode 100644
index 0000000..92380fd
--- /dev/null
+++ b/app/src/main/res/layout/fragment_upload_credentials.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
index 3f525e9..03504b4 100644
--- a/app/src/main/res/layout/fragment_upload_settings.xml
+++ b/app/src/main/res/layout/fragment_upload_settings.xml
@@ -2,7 +2,6 @@
@@ -20,7 +19,7 @@
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="This Organisation will have the following rights on your MISP instance"
- android:textAppearance="@style/Text.Title"
+ android:textAppearance="@style/TextAppearance.MaterialComponents.Overline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
diff --git a/app/src/main/res/layout/material_password_view.xml b/app/src/main/res/layout/material_password_view.xml
new file mode 100644
index 0000000..7a166d6
--- /dev/null
+++ b/app/src/main/res/layout/material_password_view.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
index c302a9c..addb71a 100644
--- a/app/src/main/res/layout/material_preference_switch.xml
+++ b/app/src/main/res/layout/material_preference_switch.xml
@@ -21,7 +21,7 @@
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
- android:textAppearance="@style/Text.Title"
+ android:textAppearance="@style/AppTheme.TextAppearance.ListTitle"
app:layout_constraintEnd_toStartOf="@id/material_preference_switch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
@@ -37,7 +37,7 @@
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
- android:textAppearance="@style/Text.SubTitle"
+ android:textAppearance="@style/AppTheme.TextAppearance.ListSubtitle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/material_preference_switch"
app:layout_constraintStart_toStartOf="parent"
diff --git a/app/src/main/res/layout/material_preference_text.xml b/app/src/main/res/layout/material_preference_text.xml
index bc74b07..24690b2 100644
--- a/app/src/main/res/layout/material_preference_text.xml
+++ b/app/src/main/res/layout/material_preference_text.xml
@@ -9,7 +9,7 @@
android:focusableInTouchMode="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:foreground="?attr/selectableItemBackground">
+ android:foreground="?attr/selectableItemBackgroundBorderless">
@@ -52,10 +46,7 @@
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
- android:textAppearance="@style/Text.SubTitle"
- android:clickable="false"
- android:focusable="false"
- android:focusableInTouchMode="false"
+ android:textAppearance="@style/AppTheme.TextAppearance.ListSubtitle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/material_preference_src"
diff --git a/app/src/main/res/layout/row_upload_information.xml b/app/src/main/res/layout/row_upload_information.xml
index 32d35a2..1afda2c 100644
--- a/app/src/main/res/layout/row_upload_information.xml
+++ b/app/src/main/res/layout/row_upload_information.xml
@@ -8,10 +8,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
- android:foreground="?attr/selectableItemBackground"
+ android:foreground="?attr/selectableItemBackgroundBorderless"
android:layout_marginBottom="1dp"
- android:padding="8dp"
- android:transitionName="root">
+ android:padding="8dp">
-
+ android:padding="16dp"
+ android:foreground="?attr/selectableItemBackground">
-
+
-
-
-
-
-
-
+
+
+
-
\ No newline at end of file
+ android:id="@+id/error"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/title"
+ tools:text="Error" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_upload_action_2.xml b/app/src/main/res/layout/view_upload_action_2.xml
deleted file mode 100644
index c8b56e1..0000000
--- a/app/src/main/res/layout/view_upload_action_2.xml
+++ /dev/null
@@ -1,47 +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 a0817fb..2de5bd2 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -5,7 +5,7 @@
-
+
@@ -15,6 +15,11 @@
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f614644..f60dae6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -12,4 +12,7 @@
QR code
Synchronization
You have not synced any MISP instances yet
+
+
+ Hello blank fragment
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 492b408..320d19d 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -20,14 +20,14 @@
- #000
-
+
-
-