diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java index 7aa53e5d..a606190c 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java @@ -50,6 +50,7 @@ public class Entry { private static final int DEFAULT_PERIOD = 30; private static final String JSON_SECRET = "secret"; + private static final String JSON_ISSUER = "issuer"; private static final String JSON_LABEL = "label"; private static final String JSON_PERIOD = "period"; private static final String JSON_COUNTER = "counter"; @@ -66,6 +67,7 @@ public class Entry { private TokenCalculator.HashAlgorithm algorithm = TokenCalculator.DEFAULT_ALGORITHM; private byte[] secret; private long counter; + private String issuer; private String label; private String currentOTP; private boolean visible = false; @@ -77,21 +79,23 @@ public class Entry { public Entry(){} - public Entry(OTPType type, String secret, int period, int digits, String label, TokenCalculator.HashAlgorithm algorithm, List tags) { + public Entry(OTPType type, String secret, int period, int digits, String issuer, String label, TokenCalculator.HashAlgorithm algorithm, List tags) { this.type = type; this.secret = new Base32().decode(secret.toUpperCase()); this.period = period; this.digits = digits; + this.issuer = issuer; this.label = label; this.algorithm = algorithm; this.tags = tags; } - public Entry(OTPType type, String secret, long counter, int digits, String label, TokenCalculator.HashAlgorithm algorithm, List tags) { + public Entry(OTPType type, String secret, long counter, int digits, String issuer, String label, TokenCalculator.HashAlgorithm algorithm, List tags) { this.type = type; this.secret = new Base32().decode(secret.toUpperCase()); this.counter = counter; this.digits = digits; + this.issuer = issuer; this.label = label; this.algorithm = algorithm; this.tags = tags; @@ -124,10 +128,6 @@ public class Entry { String algorithm = uri.getQueryParameter("algorithm"); List tags = uri.getQueryParameters("tags"); - if (issuer != null){ - label = issuer +" - "+label; - } - if (type == OTPType.HOTP) { if (counter != null) { this.counter = Long.parseLong(counter); @@ -142,6 +142,7 @@ public class Entry { } } + this.issuer = issuer; this.label = label; this.secret = new Base32().decode(secret.toUpperCase()); @@ -169,6 +170,13 @@ public class Entry { this.secret = new Base32().decode(jsonObj.getString(JSON_SECRET).toUpperCase()); this.label = jsonObj.getString(JSON_LABEL); + try { + this.issuer = jsonObj.getString(JSON_ISSUER); + } catch (JSONException e) { + // Older backup version did not save issuer and label separately + this.issuer = ""; + } + try { this.type = OTPType.valueOf(jsonObj.getString(JSON_TYPE)); } catch(Exception e) { @@ -227,6 +235,7 @@ public class Entry { public JSONObject toJSON() throws JSONException { JSONObject jsonObj = new JSONObject(); jsonObj.put(JSON_SECRET, new String(new Base32().encode(getSecret()))); + jsonObj.put(JSON_ISSUER, getIssuer()); jsonObj.put(JSON_LABEL, getLabel()); jsonObj.put(JSON_DIGITS, getDigits()); jsonObj.put(JSON_TYPE, getType().toString()); @@ -268,6 +277,14 @@ public class Entry { this.secret = secret; } + public String getIssuer() { + return issuer; + } + + public void setIssuer(String issuer) { + this.issuer = issuer; + } + public String getLabel() { return label; } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java index 3e6ccc1a..1de03462 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java @@ -371,6 +371,51 @@ public class EntriesCardAdapter extends RecyclerView.Adapter return true; } + public void editEntryIssuer(final int pos) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + + int marginSmall = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_small); + int marginMedium = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_medium); + + final EditText input = new EditText(context); + input.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + input.setText(displayedEntries.get(pos).getIssuer()); + input.setSingleLine(); + + FrameLayout container = new FrameLayout(context); + container.setPaddingRelative(marginMedium, marginSmall, marginMedium, 0); + container.addView(input); + + builder.setTitle(R.string.dialog_title_rename) + .setView(container) + .setPositiveButton(R.string.button_save, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + int realIndex = getRealIndex(pos); + String newIssuer = input.getEditableText().toString(); + + displayedEntries.get(pos).setIssuer(newIssuer); + if (sortMode == SortMode.LABEL) { + displayedEntries = sortEntries(displayedEntries); + notifyDataSetChanged(); + } else { + notifyItemChanged(pos); + } + + Entry e = entries.get(realIndex); + e.setIssuer(newIssuer); + + DatabaseHelper.saveDatabase(context, entries, encryptionKey); + } + }) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) {} + }) + .create() + .show(); + } + public void editEntryLabel(final int pos) { AlertDialog.Builder builder = new AlertDialog.Builder(context); @@ -585,7 +630,10 @@ public class EntriesCardAdapter extends RecyclerView.Adapter public boolean onMenuItemClick(MenuItem item) { int id = item.getItemId(); - if (id == R.id.menu_popup_editLabel) { + if (id == R.id.menu_popup_editIssuer) { + editEntryIssuer(pos); + return true; + } else if (id == R.id.menu_popup_editLabel) { editEntryLabel(pos); return true; } else if(id == R.id.menu_popup_changeImage) { diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java index 4c470860..06e2df6d 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java @@ -64,6 +64,7 @@ public class EntryViewHolder extends RecyclerView.ViewHolder private ImageView visibleImg; private ImageView thumbnailImg; private TextView value; + private TextView issuer; private TextView label; private TextView counter; private TextView tags; @@ -81,6 +82,7 @@ public class EntryViewHolder extends RecyclerView.ViewHolder thumbnailFrame = v.findViewById(R.id.thumbnailFrame); thumbnailImg = v.findViewById(R.id.thumbnailImg); coverLayout = v.findViewById(R.id.coverLayout); + issuer = v.findViewById(R.id.textViewIssuer); label = v.findViewById(R.id.textViewLabel); tags = v.findViewById(R.id.textViewTags); counterLayout = v.findViewById(R.id.counterLayout); @@ -149,6 +151,14 @@ public class EntryViewHolder extends RecyclerView.ViewHolder final String tokenFormatted = Tools.formatToken(entry.getCurrentOTP(), settings.getTokenSplitGroupSize()); + String issuerText = entry.getIssuer(); + if (!TextUtils.isEmpty(issuerText)) { + issuer.setText(entry.getIssuer()); + issuer.setVisibility(View.VISIBLE); + } else { + issuer.setVisibility(View.GONE); + } + label.setText(entry.getLabel()); value.setText(tokenFormatted); // save the unformatted token to the tag of this TextView for copy/paste diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/ManualEntryDialog.java b/app/src/main/java/org/shadowice/flocke/andotp/View/ManualEntryDialog.java index 52fae359..c2af36b4 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/ManualEntryDialog.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/ManualEntryDialog.java @@ -59,6 +59,7 @@ public class ManualEntryDialog { View inputView = callingActivity.getLayoutInflater().inflate(R.layout.dialog_manual_entry, container, false); final Spinner typeInput = inputView.findViewById(R.id.manual_type); + final EditText issuerInput = inputView.findViewById(R.id.manual_issuer); final EditText labelInput = inputView.findViewById(R.id.manual_label); final EditText secretInput = inputView.findViewById(R.id.manual_secret); final EditText counterInput = inputView.findViewById(R.id.manual_counter); @@ -192,6 +193,7 @@ public class ManualEntryDialog { Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem(); TokenCalculator.HashAlgorithm algorithm = (TokenCalculator.HashAlgorithm) algorithmInput.getSelectedItem(); + String issuer = issuerInput.getText().toString(); String label = labelInput.getText().toString(); String secret = secretInput.getText().toString(); int digits = Integer.parseInt(digitsInput.getText().toString()); @@ -199,7 +201,7 @@ public class ManualEntryDialog { if (type == Entry.OTPType.TOTP || type == Entry.OTPType.STEAM) { int period = Integer.parseInt(periodInput.getText().toString()); - Entry e = new Entry(type, secret, period, digits, label, algorithm, tagsAdapter.getActiveTags()); + Entry e = new Entry(type, secret, period, digits, issuer, label, algorithm, tagsAdapter.getActiveTags()); e.updateOTP(); e.setLastUsed(System.currentTimeMillis()); adapter.addEntry(e); @@ -209,7 +211,7 @@ public class ManualEntryDialog { } else if (type == Entry.OTPType.HOTP) { long counter = Long.parseLong(counterInput.getText().toString()); - Entry e = new Entry(type, secret, counter, digits, label, algorithm, tagsAdapter.getActiveTags()); + Entry e = new Entry(type, secret, counter, digits, issuer, label, algorithm, tagsAdapter.getActiveTags()); e.updateOTP(); e.setLastUsed(System.currentTimeMillis()); adapter.addEntry(e); diff --git a/app/src/main/res/layout/component_card.xml b/app/src/main/res/layout/component_card.xml index 1149c3d9..9adeba80 100644 --- a/app/src/main/res/layout/component_card.xml +++ b/app/src/main/res/layout/component_card.xml @@ -105,6 +105,15 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values/strings_main.xml b/app/src/main/res/values/strings_main.xml index 7fb51cf5..fc1cedf3 100644 --- a/app/src/main/res/values/strings_main.xml +++ b/app/src/main/res/values/strings_main.xml @@ -26,6 +26,7 @@ Period Digits Counter + Issuer Label Algorithm Tags @@ -47,6 +48,7 @@ Label Last used + Edit issuer Edit label Change image Edit tags