mirror of https://github.com/MISP/misp-bump
parent
48674d130a
commit
be88d0e3a5
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
|
@ -0,0 +1,12 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="SuspiciousNameCombination" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<group names="x,width,left,right" />
|
||||
<group names="y,height,top,bottom" />
|
||||
<ignored>
|
||||
<option name="METHOD_MATCHER_CONFIG" value="java.io.PrintStream,println,java.io.PrintWriter,println,java.lang.System,identityHashCode,java.sql.PreparedStatement,set.*,java.sql.ResultSet,update.*,java.sql.SQLOutput,write.*,java.lang.Integer,compare.*,java.lang.Long,compare.*,java.lang.Short,compare,java.lang.Byte,compare,java.lang.Character,compare,java.lang.Boolean,compare,java.lang.Math,.*,java.lang.StrictMath,.*" />
|
||||
</ignored>
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
|
@ -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'
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="lu.circl.mispbump">
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
|
@ -15,36 +16,47 @@
|
|||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<activity android:name=".activities.UploadInformationActivity"
|
||||
android:label="Sync details"/>
|
||||
<activity
|
||||
android:name=".activities.UploadActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="Upload" />
|
||||
<activity android:name=".activities.PreferenceActivity" />
|
||||
|
||||
<activity android:name=".activities.StartUpActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.HomeActivity"
|
||||
android:label="@string/home" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.LoginActivity"
|
||||
android:label="@string/login" />
|
||||
android:label="@string/login"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.HomeActivity"
|
||||
android:label="@string/app_name"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.SyncActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/sync"
|
||||
android:parentActivityName=".activities.HomeActivity" />
|
||||
android:parentActivityName=".activities.HomeActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.Translucent"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.UploadInfoActivity"
|
||||
android:parentActivityName=".activities.HomeActivity"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.UploadActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="Upload"
|
||||
android:parentActivityName=".activities.HomeActivity"/>
|
||||
<activity
|
||||
android:name=".activities.PreferenceActivity"
|
||||
android:parentActivityName=".activities.HomeActivity"/>
|
||||
<activity
|
||||
android:name=".activities.ProfileActivity"
|
||||
android:label="Profile"
|
||||
android:parentActivityName=".activities.HomeActivity"
|
||||
android:theme="@style/AppTheme.Translucent" />
|
||||
android:theme="@style/AppTheme.Translucent"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<UploadInformation> 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<UploadInformation>() {
|
||||
@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<UploadInformation> 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<Integer> onRecyclerItemClickListener() {
|
||||
return new OnRecyclerItemClickListener<Integer>() {
|
||||
@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());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<UploadInformation> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<UploadInfoListViewHolder> {
|
||||
public class UploadInfoAdapter extends RecyclerView.Adapter<UploadInfoAdapter.ViewHolder> {
|
||||
|
||||
private Context context;
|
||||
private List<UploadInformation> items;
|
||||
|
||||
private OnRecyclerItemClickListener<UploadInformation> onRecyclerItemClickListener;
|
||||
private OnRecyclerItemClickListener<Integer> onRecyclerPositionClickListener;
|
||||
|
||||
|
||||
public UploadInfoAdapter(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public UploadInfoAdapter(Context context, List<UploadInformation> 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<UploadInfoListViewHo
|
|||
break;
|
||||
case PENDING:
|
||||
ImageViewCompat.setImageTintList(holder.syncStatus, ColorStateList.valueOf(context.getColor(R.color.status_amber)));
|
||||
holder.syncStatus.setImageResource(R.drawable.ic_info_outline);
|
||||
holder.syncStatus.setImageResource(R.drawable.ic_pending);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -70,6 +68,13 @@ public class UploadInfoAdapter extends RecyclerView.Adapter<UploadInfoListViewHo
|
|||
onRecyclerItemClickListener.onClick(view, item);
|
||||
}
|
||||
});
|
||||
|
||||
holder.rootView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
onRecyclerPositionClickListener.onClick(view, position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,12 +82,37 @@ public class UploadInfoAdapter extends RecyclerView.Adapter<UploadInfoListViewHo
|
|||
return items.size();
|
||||
}
|
||||
|
||||
|
||||
public void setItems(List<UploadInformation> items) {
|
||||
this.items = items;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
// callbacks
|
||||
|
||||
public void setOnRecyclerItemClickListener(OnRecyclerItemClickListener<UploadInformation> onRecyclerItemClickListener) {
|
||||
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
|
||||
}
|
||||
|
||||
public void setOnRecyclerPositionClickListener(OnRecyclerItemClickListener<Integer> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -322,120 +322,104 @@ public class PreferenceManager {
|
|||
}
|
||||
|
||||
|
||||
public void setUploadInformationList(List<UploadInformation> uploadInformationList) {
|
||||
KeyStoreWrapper ksw = new KeyStoreWrapper(KeyStoreWrapper.UPLOAD_INFORMATION_ALIAS);
|
||||
private List<UploadInformation> 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<UploadInformation> getUploadInformation() {
|
||||
private void loadUploadInformationList() {
|
||||
KeyStoreWrapper ksw = new KeyStoreWrapper(KeyStoreWrapper.UPLOAD_INFORMATION_ALIAS);
|
||||
String storedUploadInfoString = preferences.getString(UPLOAD_INFO, null);
|
||||
|
||||
Type type = new TypeToken<List<UploadInformation>>() {}.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<UploadInformation> getUploadInformationList() {
|
||||
if (cachedUploadInformationList == null) {
|
||||
loadUploadInformationList();
|
||||
}
|
||||
|
||||
return cachedUploadInformationList;
|
||||
}
|
||||
|
||||
public void setUploadInformationList(List<UploadInformation> 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<UploadInformation> 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<UploadInformation> 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<UploadInformation> 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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
<vector android:height="24dp" android:tint="#B4B4B4"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,6v3l4,-4 -4,-4v3c-4.42,0 -8,3.58 -8,8 0,1.57 0.46,3.03 1.24,4.26L6.7,14.8c-0.45,-0.83 -0.7,-1.79 -0.7,-2.8 0,-3.31 2.69,-6 6,-6zM18.76,7.74L17.3,9.2c0.44,0.84 0.7,1.79 0.7,2.8 0,3.31 -2.69,6 -6,6v-3l-4,4 4,4v-3c4.42,0 8,-3.58 8,-8 0,-1.57 -0.46,-3.03 -1.24,-4.26z"/>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,6v1.79c0,0.45 0.54,0.67 0.85,0.35l2.79,-2.79c0.2,-0.2 0.2,-0.51 0,-0.71l-2.79,-2.79c-0.31,-0.31 -0.85,-0.09 -0.85,0.36L12,4c-4.42,0 -8,3.58 -8,8 0,1.04 0.2,2.04 0.57,2.95 0.27,0.67 1.13,0.85 1.64,0.34 0.27,-0.27 0.38,-0.68 0.23,-1.04C6.15,13.56 6,12.79 6,12c0,-3.31 2.69,-6 6,-6zM17.79,8.71c-0.27,0.27 -0.38,0.69 -0.23,1.04 0.28,0.7 0.44,1.46 0.44,2.25 0,3.31 -2.69,6 -6,6v-1.79c0,-0.45 -0.54,-0.67 -0.85,-0.35l-2.79,2.79c-0.2,0.2 -0.2,0.51 0,0.71l2.79,2.79c0.31,0.31 0.85,0.09 0.85,-0.35L12,20c4.42,0 8,-3.58 8,-8 0,-1.04 -0.2,-2.04 -0.57,-2.95 -0.27,-0.67 -1.13,-0.85 -1.64,-0.34z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFF" android:pathData="M11,15h2v2h-2zM11,7h2v6h-2zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M12,7c0.55,0 1,0.45 1,1v4c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1L11,8c0,-0.55 0.45,-1 1,-1zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM13,17h-2v-2h2v2z"/>
|
||||
</vector>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM11.78,7h-0.06c-0.4,0 -0.72,0.32 -0.72,0.72v4.72c0,0.35 0.18,0.68 0.49,0.86l4.15,2.49c0.34,0.2 0.78,0.1 0.98,-0.24 0.21,-0.34 0.1,-0.79 -0.25,-0.99l-3.87,-2.3L12.5,7.72c0,-0.4 -0.32,-0.72 -0.72,-0.72z"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/white"/>
|
||||
<corners android:radius="12dp"/>
|
||||
</shape>
|
|
@ -4,6 +4,6 @@
|
|||
android:color="@color/white"/>
|
||||
|
||||
<corners
|
||||
android:topLeftRadius="10dp"
|
||||
android:topRightRadius="10dp"/>
|
||||
android:topLeftRadius="12dp"
|
||||
android:topRightRadius="12dp"/>
|
||||
</shape>
|
|
@ -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">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -15,25 +14,23 @@
|
|||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
android:background="@color/colorPrimary" />
|
||||
android:theme="@style/ToolbarTheme"
|
||||
app:popupTheme="@style/PopupTheme" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"/>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:drawableTop="@drawable/ic_sync_black_24dp"
|
||||
android:gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="64dp"
|
||||
android:text="@string/no_syncs_hint"/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
android:tint="@color/white"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/orgName"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
|
@ -8,90 +7,153 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
<FrameLayout
|
||||
android:id="@+id/fragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/sync_fragment_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" >
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qrcode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="64dp"
|
||||
android:contentDescription="@string/qr_code"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
app:layout_behavior=".customViews.ExtendedBottomSheetBehavior"
|
||||
android:id="@+id/bottomSheet"
|
||||
android:layout_width="match_parent"
|
||||
<FrameLayout
|
||||
android:id="@+id/qrFrame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/rounded_rect"
|
||||
android:backgroundTint="@color/colorPrimary"
|
||||
app:behavior_peekHeight="64dp">
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/rect_rounded"
|
||||
android:backgroundTint="#99FFFFFF"
|
||||
android:padding="8dp"
|
||||
tools:layout_height="256dp"
|
||||
tools:layout_width="256dp">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/prevButton"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_arrow_back" />
|
||||
|
||||
<ImageView
|
||||
android:visibility="invisible"
|
||||
android:id="@+id/bottomSheetIcon"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/ic_check_outline" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/nextButton"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_arrow_forward" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottomSheetText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:gravity="top"
|
||||
android:layout_gravity="center"
|
||||
android:text="Received public key from partner"
|
||||
android:textColor="@color/white" />
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qrCode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/qrHint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableStart="@drawable/ic_info_outline"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableTint="@color/status_amber"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp"
|
||||
android:text="Scan your partners QR code"
|
||||
android:textColor="@color/colorPrimaryDark"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/qrHint2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableStart="@drawable/ic_info_outline"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableTint="@color/colorPrimaryDark"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp"
|
||||
android:lines="2"
|
||||
android:text="Continue if your partner also scanned this QR code"
|
||||
android:textColor="@color/colorPrimaryDark"/>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/rect_rounded_top"
|
||||
android:backgroundTint="@color/colorPrimary"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/prevButton"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_arrow_back"/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/nextButton"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_arrow_forward"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!--<LinearLayout-->
|
||||
<!--app:layout_behavior=".customViews.ExtendedBottomSheetBehavior"-->
|
||||
<!--android:id="@+id/bottomSheet"-->
|
||||
<!--android:layout_width="match_parent"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:orientation="vertical"-->
|
||||
<!--android:background="@drawable/rect_rounded_top"-->
|
||||
<!--android:backgroundTint="@color/colorPrimary"-->
|
||||
<!--app:behavior_peekHeight="64dp">-->
|
||||
|
||||
<!--<LinearLayout-->
|
||||
<!--android:orientation="horizontal"-->
|
||||
<!--android:layout_width="match_parent"-->
|
||||
<!--android:layout_height="wrap_content">-->
|
||||
|
||||
<!--<ImageButton-->
|
||||
<!--android:id="@+id/prevButton"-->
|
||||
<!--android:layout_width="64dp"-->
|
||||
<!--android:layout_height="64dp"-->
|
||||
<!--android:background="?attr/selectableItemBackground"-->
|
||||
<!--android:padding="8dp"-->
|
||||
<!--app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!--app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!--app:srcCompat="@drawable/ic_arrow_back" />-->
|
||||
|
||||
<!--<ImageView-->
|
||||
<!--android:visibility="invisible"-->
|
||||
<!--android:id="@+id/bottomSheetIcon"-->
|
||||
<!--android:layout_weight="1"-->
|
||||
<!--android:layout_width="0dp"-->
|
||||
<!--android:layout_height="32dp"-->
|
||||
<!--android:layout_gravity="center_vertical"-->
|
||||
<!--android:src="@drawable/ic_check_outline" />-->
|
||||
|
||||
<!--<ImageButton-->
|
||||
<!--android:id="@+id/nextButton"-->
|
||||
<!--android:layout_width="64dp"-->
|
||||
<!--android:layout_height="64dp"-->
|
||||
<!--android:background="?attr/selectableItemBackground"-->
|
||||
<!--android:padding="8dp"-->
|
||||
<!--app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!--app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!--app:srcCompat="@drawable/ic_arrow_forward" />-->
|
||||
<!--</LinearLayout>-->
|
||||
|
||||
<!--<TextView-->
|
||||
<!--android:id="@+id/bottomSheetText"-->
|
||||
<!--android:layout_width="wrap_content"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:paddingStart="16dp"-->
|
||||
<!--android:paddingEnd="16dp"-->
|
||||
<!--android:paddingBottom="16dp"-->
|
||||
<!--android:gravity="top"-->
|
||||
<!--android:layout_gravity="center"-->
|
||||
<!--android:text="Received public key from partner"-->
|
||||
<!--android:textColor="@color/white" />-->
|
||||
<!--</LinearLayout>-->
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -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" />
|
||||
|
||||
<lu.circl.mispbump.customViews.UploadAction
|
||||
android:id="@+id/orgAction"
|
||||
|
@ -46,10 +46,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="Add organisation" />
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:description="Add organisation" />
|
||||
|
||||
<lu.circl.mispbump.customViews.UploadAction
|
||||
android:id="@+id/userAction"
|
||||
|
@ -61,7 +61,7 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="Add sync user" />
|
||||
app:description="Add sync user" />
|
||||
|
||||
<lu.circl.mispbump.customViews.UploadAction
|
||||
android:id="@+id/serverAction"
|
||||
|
@ -73,18 +73,18 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="Add sync server" />
|
||||
app:description="Add sync server" />
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
app:backgroundTint="@color/colorAccent"
|
||||
android:tint="@color/white"
|
||||
android:src="@drawable/ic_cloud_upload"/>
|
||||
<!--<com.google.android.material.floatingactionbutton.FloatingActionButton-->
|
||||
<!--android:id="@+id/fab"-->
|
||||
<!--android:layout_width="wrap_content"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:layout_gravity="bottom|end"-->
|
||||
<!--android:layout_margin="16dp"-->
|
||||
<!--app:backgroundTint="@color/colorAccent"-->
|
||||
<!--android:tint="@color/white"-->
|
||||
<!--android:src="@drawable/ic_cloud_upload"/>-->
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -1,71 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
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/rootLayout"
|
||||
android:transitionName="root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:elevation="6dp"
|
||||
app:elevation="6dp">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat"
|
||||
android:background="@color/white" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/syncStatus"
|
||||
android:transitionName="icon"
|
||||
android:transformPivotX="32dp"
|
||||
android:transformPivotY="32dp"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:tint="@color/status_green"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:src="@drawable/ic_check_outline"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/orgName"
|
||||
android:transitionName="title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAppearance="@style/Text.Title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/syncStatus"
|
||||
tools:text="Organisation Title" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@drawable/ic_cloud_upload"/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
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/rootLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:popupTheme="@style/PopupTheme"
|
||||
app:theme="@style/ToolbarTheme.Light"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/syncStatus"
|
||||
android:layout_marginTop="-12dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
tools:text="Successfully uploaded"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
|
||||
android:textColor="@color/status_green"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="72dp"
|
||||
android:drawableEnd="@drawable/ic_check_outline"
|
||||
android:drawableTint="@color/status_green"
|
||||
android:drawablePadding="8dp"/>
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:tabGravity="fill"
|
||||
app:tabMode="fixed"/>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_margin="16dp"/>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="8dp"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
||||
tools:drawableEnd="@drawable/ic_error_outline"
|
||||
tools:drawableTint="@color/status_red"
|
||||
tools:text="Sample title"/>
|
||||
|
||||
<ImageView
|
||||
android:src="@drawable/ic_error_outline"
|
||||
android:tint="@color/status_red"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,147 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/allow_self_signed"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:text="Allow self signed certificates"
|
||||
android:textColor="@android:color/primary_text_light"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/self_signed_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/share_events_desc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="Server certificate must not be from a trusted CA (not recomended)"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/self_signed_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/allow_self_signed" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/self_signed_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/share_events_desc"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/allow_self_signed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/push_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:text="Push"
|
||||
android:textColor="#000000"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/push_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/share_events_desc" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/push_desc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="Allow the upload of events and their attributes"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/push_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/push_title" />
|
||||
|
||||
|
||||
<Switch
|
||||
android:id="@+id/push_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/push_desc"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/push_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pull_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="Pull"
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintEnd_toStartOf="@+id/pull_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/push_desc" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pull_desc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="Allow the download of events and their attributes"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/pull_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pull_title" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/pull_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/pull_desc"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/pull_title" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/cache_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/cache_desc"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/cache_title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cache_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="Caching"
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintEnd_toStartOf="@+id/cache_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pull_desc" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cache_desc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="Allow the caching of events and their attributes"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/cache_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cache_title" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
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/rootLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
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"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<lu.circl.mispbump.customViews.MaterialPreferenceSwitch
|
||||
android:id="@+id/self_signed_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/text"
|
||||
app:subtitle="Server certificate must not be from a trusted CA (not recomended)"
|
||||
app:title="Allow self signed certificates"/>
|
||||
|
||||
<lu.circl.mispbump.customViews.MaterialPreferenceSwitch
|
||||
android:id="@+id/push_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/self_signed_switch"
|
||||
app:subtitle="Allow the upload of events and their attributes"
|
||||
app:title="Push"/>
|
||||
|
||||
<lu.circl.mispbump.customViews.MaterialPreferenceSwitch
|
||||
android:id="@+id/pull_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/push_switch"
|
||||
app:subtitle="Allow the download of events and their attributes"
|
||||
app:title="Pull"/>
|
||||
|
||||
<lu.circl.mispbump.customViews.MaterialPreferenceSwitch
|
||||
android:id="@+id/cache_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/pull_switch"
|
||||
app:subtitle="Allow the caching of events and their attributes"
|
||||
app:title="Cache"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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/rootLayout"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?attr/selectableItemBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/material_preference_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:textAppearance="@style/Text.Title"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_preference_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/material_preference_subtitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:textAppearance="@style/Text.SubTitle"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_preference_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/material_preference_title"
|
||||
tools:text="Subtitle" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/material_preference_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/material_preference_subtitle"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/material_preference_title" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -13,11 +13,13 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:textAppearance="@style/Text.Title"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="000"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/Text.Title"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/stateView"
|
||||
|
@ -36,6 +38,7 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:text="000"
|
||||
android:textAppearance="@style/Text.SubTitle"
|
||||
android:textColor="@color/status_red"
|
||||
android:layout_marginEnd="24dp"
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:foreground="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/stateView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_error_outline"
|
||||
android:tint="@color/black"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:visibility="gone"
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Title (upload action)" />
|
||||
|
||||
<TextView
|
||||
android:visibility="gone"
|
||||
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" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -2,8 +2,8 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/bla"
|
||||
android:id="@+id/delete"
|
||||
android:icon="@drawable/ic_delete_forever"
|
||||
android:title="delete"
|
||||
app:showAsAction="ifRoom"/>
|
||||
android:title="Remove"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<changeBounds/>
|
||||
<!--<fade-->
|
||||
<!--android:fadingMode="fade_in_out"/>-->
|
||||
|
||||
<!--<transition class="lu.circl.mispbump.RecyclerViewItemTransition"/>-->
|
||||
</transitionSet>
|
|
@ -1,9 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<attr name="title" format="string"/>
|
||||
<attr name="subtitle" format="string"/>
|
||||
|
||||
<declare-styleable name="MaterialPreferenceText">
|
||||
<attr name="pref_icon" format="integer"/>
|
||||
<attr name="title" format="string"/>
|
||||
<attr name="subtitle" format="string"/>
|
||||
<attr name="title"/>
|
||||
<attr name="subtitle"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MaterialPreferenceSwitch">
|
||||
<attr name="title"/>
|
||||
<attr name="subtitle"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="UploadAction">
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
<resources>
|
||||
<color name="colorPrimary">#047EB4</color>
|
||||
<color name="colorPrimaryDark">#023850</color>
|
||||
<!--<color name="colorPrimaryDark">#047EB4</color>-->
|
||||
<color name="colorAccent">#12B3FA</color>
|
||||
<color name="colorAccent_50">#8012B3FA</color>
|
||||
|
||||
<color name="dividerColor">#33000000</color>
|
||||
|
||||
<!-- colors -->
|
||||
<color name="white">#FFFFFF</color>
|
||||
<color name="white_50">#80FFFFFF</color>
|
||||
|
||||
<color name="grey">#BDBDBD</color>
|
||||
<color name="grey_light">#F0F0F0</color>
|
||||
|
||||
<color name="black">#000</color>
|
||||
|
||||
<color name="status_green">#4CAF50</color>
|
||||
<color name="status_amber">#FB8C00</color>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<string name="misp_automation_hint">MISP Automation Key</string>
|
||||
<string name="no_information">No Information</string>
|
||||
<string name="save_automation_key_hint">Save Automation Key</string>
|
||||
<string name="home" translatable="false">Home</string>
|
||||
<string name="menu_login_help_label">Help</string>
|
||||
<string name="login_help_text"><b>MISP Server URL</b>\nPublic MISP URL\n\n<b>MISP Automation key</b>\nZu finden unter ...</string>
|
||||
<string name="ok" translatable="false">Okay</string>
|
||||
|
|
|
@ -1,21 +1,8 @@
|
|||
<resources>
|
||||
<!-- Theme.MaterialComponents.Light.NoActionBar || Theme.AppCompat.Light.NoActionBar -->
|
||||
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
|
||||
<item name="android:windowContentTransitions">true</item>
|
||||
|
||||
<!-- specify enter and exit transitions -->
|
||||
<!-- options are: explode, slide, fade -->
|
||||
<!--<item name="android:windowEnterTransition">@transition/simple</item>-->
|
||||
<!--<item name="android:windowExitTransition">@transition/simple</item>-->
|
||||
|
||||
<!--specify shared element transitions -->
|
||||
<item name="android:windowSharedElementEnterTransition">@transition/simple</item>
|
||||
<item name="android:windowSharedElementExitTransition">@transition/simple</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Translucent">
|
||||
|
@ -23,13 +10,14 @@
|
|||
<item name="android:windowTranslucentStatus">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.FullScreenDialog" parent="Theme.MaterialComponents.Light.DialogWhenLarge">
|
||||
<item name="android:statusBarColor">@color/colorPrimaryDark</item>
|
||||
</style>
|
||||
<style name="PopupTheme" parent="ThemeOverlay.MaterialComponents.Light"/>
|
||||
|
||||
<style name="DialogAnimation">
|
||||
<item name="android:windowEnterAnimation">@anim/fade_in</item>
|
||||
<item name="android:windowExitAnimation">@anim/fade_out</item>
|
||||
<style name="ToolbarTheme" parent="ThemeOverlay.MaterialComponents.Dark.ActionBar"/>
|
||||
|
||||
<style name="ToolbarTheme.Light" parent="@style/ThemeOverlay.MaterialComponents.ActionBar">
|
||||
<item name="android:background">@color/white</item>
|
||||
<item name="colorControlNormal">#000</item>
|
||||
<item name="android:tint">#000</item>
|
||||
</style>
|
||||
|
||||
<style name="Text"/>
|
||||
|
|
Loading…
Reference in New Issue