diff --git a/.idea/misc.xml b/.idea/misc.xml index 93a9df2..da7759f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -38,7 +38,7 @@ - + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6950428..48b8f7d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,7 +15,8 @@ android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> - + () { @Override - public void onClick(UploadInformation item) { + 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)); - startActivity(i); + + 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/SyncActivity.java b/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java index c4a3cda..0ec56f0 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/SyncActivity.java @@ -6,6 +6,8 @@ import android.content.Intent; 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.ImageButton; import android.widget.ImageView; import android.widget.TextView; @@ -42,8 +44,8 @@ import lu.circl.mispbump.security.DiffieHellman; */ public class SyncActivity extends AppCompatActivity { - // layout - private CoordinatorLayout layout; + // rootLayout + private CoordinatorLayout rootLayout; private ImageView qrCodeView, bottomSheetIcon; private TextView bottomSheetText; private ImageButton prevButton, nextButton; @@ -86,8 +88,8 @@ public class SyncActivity extends AppCompatActivity { } private void initializeViews() { - // Root Layout - layout = findViewById(R.id.rootLayout); + + rootLayout = findViewById(R.id.rootLayout); // prev button prevButton = findViewById(R.id.prevButton); @@ -196,7 +198,7 @@ public class SyncActivity extends AppCompatActivity { } }); } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { - Snackbar.make(layout, "Invalid key", Snackbar.LENGTH_SHORT).show(); + Snackbar.make(rootLayout, "Invalid key", Snackbar.LENGTH_SHORT).show(); cameraFragment.setReadQrEnabled(true); } break; @@ -218,7 +220,7 @@ public class SyncActivity extends AppCompatActivity { }); } catch (JsonSyntaxException e) { - Snackbar.make(layout, "Sync information unreadable", Snackbar.LENGTH_SHORT).show(); + Snackbar.make(rootLayout, "Sync information unreadable", Snackbar.LENGTH_SHORT).show(); cameraFragment.setReadQrEnabled(true); } break; @@ -403,7 +405,7 @@ public class SyncActivity extends AppCompatActivity { bottomSheetIcon.animate() .scaleY(1f) .scaleX(1f) - .setDuration(250); + .setDuration(500); bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); bottomSheetBehavior.setSwipeable(true); diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadInformationActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadInformationActivity.java index a211e58..48e7496 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/UploadInformationActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/UploadInformationActivity.java @@ -1,11 +1,22 @@ package lu.circl.mispbump.activities; -import androidx.appcompat.app.AppCompatActivity; - -import android.content.Intent; +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; @@ -15,15 +26,23 @@ 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() { @@ -32,8 +51,106 @@ public class UploadInformationActivity extends AppCompatActivity { } 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 980dafa..bba9499 100644 --- a/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java +++ b/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java @@ -52,7 +52,7 @@ public class UploadInfoAdapter extends RecyclerView.Adapter { - void onClick(T item); + void onClick(View v, T item); } diff --git a/app/src/main/res/anim/scale_vertical.xml b/app/src/main/res/anim/scale_vertical.xml new file mode 100644 index 0000000..3c3b766 --- /dev/null +++ b/app/src/main/res/anim/scale_vertical.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_error_outline.xml b/app/src/main/res/drawable/ic_error_outline.xml index 93db179..694bd6e 100644 --- a/app/src/main/res/drawable/ic_error_outline.xml +++ b/app/src/main/res/drawable/ic_error_outline.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/ic_info_outline.xml b/app/src/main/res/drawable/ic_info_outline.xml index af0d4d0..c3c23fd 100644 --- a/app/src/main/res/drawable/ic_info_outline.xml +++ b/app/src/main/res/drawable/ic_info_outline.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/layout/activity_upload_information.xml b/app/src/main/res/layout/activity_upload_information.xml index a0f7358..017a195 100644 --- a/app/src/main/res/layout/activity_upload_information.xml +++ b/app/src/main/res/layout/activity_upload_information.xml @@ -1,22 +1,71 @@ - + android:elevation="6dp" + app:elevation="6dp"> - + + + + + + + + + + + + + + android:layout_gravity="bottom|end" + android:layout_margin="16dp" + android:src="@drawable/ic_cloud_upload"/> - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/row_upload_information.xml b/app/src/main/res/layout/row_upload_information.xml index f7a5b45..32d35a2 100644 --- a/app/src/main/res/layout/row_upload_information.xml +++ b/app/src/main/res/layout/row_upload_information.xml @@ -4,15 +4,20 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/header" + android:id="@+id/rootLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white" android:foreground="?attr/selectableItemBackground" - android:layout_marginBottom="1dp"> + android:layout_marginBottom="1dp" + android:padding="8dp" + android:transitionName="root"> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index cc2e9fc..d7be4be 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -11,6 +11,9 @@ #FFFFFF #80FFFFFF + + #BDBDBD + #4CAF50 #FB8C00 #E53935 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 6aba1c4..45a61b0 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -5,6 +5,17 @@ @color/colorPrimary @color/colorPrimaryDark @color/colorAccent + + true + + + + + + + + @transition/simple + @transition/simple