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 - -