commit 03cc5454ac41dc24f89499f4396e345efcc1f941 Author: Joel Date: Tue Mar 9 16:49:48 2021 +0100 initial git version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..174a743 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +ZoomHelper \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..22c4ded --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d5d35ec --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..481ea0c --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,40 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "de.joel.zoomhelper" + minSdkVersion 16 + targetSdkVersion 30 + versionCode 1 + versionName '0.2' + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'com.google.android.material:material:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'com.android.support:design:28.0.0' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/de/joel/zoomhelper/ExampleInstrumentedTest.java b/app/src/androidTest/java/de/joel/zoomhelper/ExampleInstrumentedTest.java new file mode 100644 index 0000000..c19b376 --- /dev/null +++ b/app/src/androidTest/java/de/joel/zoomhelper/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package de.joel.zoomhelper; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("de.joel.zoomhelper", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8acc3b5 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..1eebeba Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/de/joel/zoomhelper/MainActivity.java b/app/src/main/java/de/joel/zoomhelper/MainActivity.java new file mode 100644 index 0000000..ea66455 --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/MainActivity.java @@ -0,0 +1,504 @@ +package de.joel.zoomhelper; + +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Bundle; +import android.util.AttributeSet; +import android.util.Base64; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ListPopupWindow; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Objects; + +class InstantAutoComplete extends AutoCompleteTextView { + + public InstantAutoComplete(Context context) { + super(context); + } + public InstantAutoComplete(Context arg0, AttributeSet arg1) { + super(arg0, arg1); + } + + public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) { + super(arg0, arg1, arg2); + } + @Override + public boolean enoughToFilter() { + return true; + } + +} + +public class MainActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + watchMeetingNameBox(); + fillDropdownMeetingName(); + if (getLastMeeting() != -1) { + try { + fillMeeting(getLastMeeting()); + } + catch (IndexOutOfBoundsException e) { + AlertDialog.Builder dialog=new AlertDialog.Builder(this); + dialog.setMessage("Daten wurden zurückgesetzt, da die Config-Struktur nochmal verändert wurde."); + dialog.setTitle("Hinweis"); + AlertDialog alertDialog=dialog.create(); + alertDialog.show(); + setLastMeeting(-1); + saveMeetingList(new ArrayList<>()); + } + } + watchSaveIcon(); + watchAttIcon(); + watchDeleteIcon(); + watchNewIcon(); + watchShareIcon(); + } + + private void watchShareIcon() { + ImageView ShareIcon = findViewById(R.id.imageShare); + ShareIcon.setOnClickListener(v -> { + shareMeeting(createCurrMeetingFromUI()); + }); + } + + private void shareMeeting(Meeting meeting) { + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, meeting.info()); + sendIntent.setType("text/plain"); + + Intent shareIntent = Intent.createChooser(sendIntent, null); + startActivity(shareIntent); + } + + private void watchNewIcon() { + ImageView AddIcon = findViewById(R.id.imageAdd); + AddIcon.setOnClickListener(v -> { + fillBlank(); + }); + } + + private void watchAttIcon() { + ImageView AttIcon = findViewById(R.id.imageAttend); + AttIcon.setOnClickListener(v -> { + btnJoin_onClick(null); + }); + } + + private void watchDeleteIcon() { + ImageView trashIcon = findViewById(R.id.imageTrash); + trashIcon.setOnClickListener(v -> { + removeMeeting(getLastMeeting()); + }); + } + + private void removeMeeting(int meeting) { + ArrayList meetings = getMeetings(); + if (meetings.size() > 0) { + meetings.remove(meeting); + saveMeetingList(meetings); + + if (meetings.size() > 1) { + fillDropdownMeetingName(); + if (getLastMeeting() > meetings.size()-1) { + setLastMeeting(meetings.size()-1); + fillMeeting(getLastMeeting()); + } + } else if (meetings.size() == 1) { + setLastMeeting(0); + fillDropdownMeetingName(); + fillMeeting(getLastMeeting()); + } else { + setLastMeeting(-1); + fillDropdownMeetingName(); + fillBlank(); + } + } + } + + private void fillBlank() { + EditText editMeetingName = findViewById(R.id.TextMeetingName); + EditText editID = findViewById(R.id.textBoxID); + EditText editPW = findViewById(R.id.editTextTextPassword2); + AutoCompleteTextView editName = findViewById(R.id.textBoxName); + EditText editAtt = findViewById(R.id.editAtt); + + editMeetingName.setText(""); + editID.setText(""); + editPW.setText(""); + editName.setText(""); + editName.setAdapter(null); + editAtt.setText(""); + } + + private void watchSaveIcon() { + ImageView saveIcon = findViewById(R.id.imageSave); + saveIcon.setOnClickListener(v -> { + saveAllMeetings(); + }); + } + + public void watchMeetingNameBox() { + EditText meetingNameBox = findViewById(R.id.TextMeetingName); + meetingNameBox.setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus) { + fillWithSelectedMeeting(); + } + + }); + } + + public void fillWithSelectedMeeting() { + AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); + int search = searchMeetingInList(getMeetings(), textMeetingName.getText().toString()); + if (search != -1) { + fillMeeting(search); + } + } + + @SuppressLint("ClickableViewAccessibility") + public void fillDropdownMeetingName() { + ArrayList meetings = getMeetings(); + + String[] meetingNames = new String[meetings.size()]; + for (int i = 0; i < meetings.size(); i++) { + meetingNames[i] = meetings.get(i).meetingName; + } + + AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); + ImageView dropdown = findViewById(R.id.image); + ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, meetingNames); + textMeetingName.setAdapter(adapter); + + textMeetingName.setOnTouchListener((View.OnTouchListener) (paramView, paramMotionEvent) -> { + adapter.getFilter().filter(null); + textMeetingName.showDropDown(); + return false; + }); + + textMeetingName.setOnItemClickListener((arg0, view, arg2, arg3) -> { + fillWithSelectedMeeting(); + }); + + dropdown.setOnClickListener(v -> { + textMeetingName.showDropDown(); + adapter.getFilter().filter(null); + }); + } + + public void fillDropdownAttendeeName(int meetingIndex) { + Meeting meeting = getMeetings().get(meetingIndex); + ArrayList attendees = meeting.attendees; + + String attNames[] = new String[attendees.size()]; + for (int i = 0; i < attendees.size(); i++) { + attNames[i] = attendees.get(i).name; + } + + AutoCompleteTextView textName = findViewById(R.id.textBoxName); + ImageView dropdown = findViewById(R.id.image2); + ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, attNames); + textName.setAdapter(adapter); + + textName.setOnItemClickListener((arg0, view, arg2, arg3) -> { + fillWithSelectedAtt(); + }); + + dropdown.setOnClickListener(v -> { + textName.showDropDown(); + adapter.getFilter().filter(null); + }); + } + + private void fillWithSelectedAtt() { + AutoCompleteTextView textName = findViewById(R.id.textBoxName); + EditText editAtt = findViewById(R.id.editAtt); + int found = getMeetings().get(getLastMeeting()).searchAttendee(textName.getText().toString()); + editAtt.setText(getMeetings().get(getLastMeeting()).attendees.get(found).num); + } + + public void fillMeeting(int id) { + ArrayList meetings = getMeetings(); + + EditText editMeetingName = findViewById(R.id.TextMeetingName); + EditText editID = findViewById(R.id.textBoxID); + EditText editPW = findViewById(R.id.editTextTextPassword2); + EditText editName = findViewById(R.id.textBoxName); + EditText editAtt = findViewById(R.id.editAtt); + + editID.setError(null); + editID.clearFocus(); + + editMeetingName.setText(meetings.get(id).meetingName); + editID.setText(meetings.get(id).meetingID); + editPW.setText(meetings.get(id).meetingPWD); + editName.setText(meetings.get(id).attendees.get(meetings.get(id).lastAtt).name); + editAtt.setText(meetings.get(id).attendees.get(meetings.get(id).lastAtt).num); + + fillDropdownAttendeeName(id); + } + + + private void launchZoomUrl(String url) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + if (intent.resolveActivity(getPackageManager()) != null) { + startActivity(intent); + } + } + + private String buildZoomURL(String confno, String pwd, String name, String attendees) { + if (!Objects.equals(attendees, "")) { + return "zoomus://zoom.us/join?confno=" + confno.replace(" ", "") + "&pwd=" + pwd + "&uname=" + name + " (" + attendees + ")"; + } else + return "zoomus://zoom.us/join?confno=" + confno.replace(" ", "") + "&pwd=" + pwd + "&uname=" + name; + } + + public String meetingsToString(ArrayList listMeetings) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objOutputStream = null; + try { + objOutputStream = new ObjectOutputStream(byteArrayOutputStream); + } catch (IOException e) { + e.printStackTrace(); + } + for (Object obj : listMeetings) { + + try { + objOutputStream.writeObject(obj); + } catch (IOException e) { + e.printStackTrace(); + } + try { + objOutputStream.reset(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + objOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return Base64.encodeToString(byteArrayOutputStream.toByteArray(), 0); + } + + + public ArrayList stringToMeetings(String string) { + byte[] bytes = Base64.decode(string, 0); + + ArrayList listMeetings = new ArrayList(); + ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ObjectInputStream obj = null; + try { + obj = new ObjectInputStream(bis); + } catch (IOException e) { + e.printStackTrace(); + } + try { + while (bis.available() != -1) { + //Read object from file + Meeting meeting = (Meeting) obj.readObject(); + listMeetings.add(meeting); + } + } catch (EOFException ex) { + //ex.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return listMeetings; + } + + public void saveMeetingList(ArrayList meetingList) { + SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); + SharedPreferences.Editor prefsEditor = mPrefs.edit(); + prefsEditor.putString("Meetings", meetingsToString(meetingList)); + prefsEditor.commit(); + } + + public void setLastMeeting(int id) { + SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); + SharedPreferences.Editor prefsEditor = mPrefs.edit(); + prefsEditor.putInt("LastMeeting", id); + prefsEditor.commit(); + } + + public int getLastMeeting() { + SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); + return mPrefs.getInt("LastMeeting", -1); + } + + + public ArrayList getMeetings() { + SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); + String value = mPrefs.getString("Meetings", ""); + ArrayList meetingList; + if (value.equals("")) { + meetingList = new ArrayList<>(); + } else { + meetingList = stringToMeetings(value); + } + return meetingList; + } + + public int searchMeetingInList(ArrayList meetings, String name) { + int found = -1; + for (int i = 0; i < meetings.size(); i++) { + if (meetings.get(i).meetingName.equals(name)) { + found = i; + break; + } + } + return found; + } + + public void btnSave_onClick(View view) { + saveAllMeetings(); + } + + + public void btnJoin_onClick(View view) { + saveAllMeetings(); + Meeting currMeeting = createCurrMeetingFromUI(); + String url = buildZoomURL(currMeeting.meetingID, currMeeting.meetingPWD, currMeeting.attendees.get(currMeeting.lastAtt).name, currMeeting.attendees.get(currMeeting.lastAtt).num); + launchZoomUrl(url); + } + + public Meeting createCurrMeetingFromUI() { + EditText editMeetingName = findViewById(R.id.TextMeetingName); + EditText editID = findViewById(R.id.textBoxID); + EditText editPW = findViewById(R.id.editTextTextPassword2); + EditText editName = findViewById(R.id.textBoxName); + EditText editAtt = findViewById(R.id.editAtt); + + Meeting currMeeting = new Meeting(editMeetingName.getText().toString(), editID.getText().toString(), editPW.getText().toString(), editName.getText().toString(), editAtt.getText().toString()); + return currMeeting; + } + + public void saveAllMeetings() { + ArrayList listMeetings = getMeetings(); + Meeting currMeetingUI = createCurrMeetingFromUI(); + + if (currMeetingUI.meetingID.equals("")) { + EditText editID = findViewById(R.id.textBoxID); + editID.requestFocus(); + editID.setError("Meeting kann nicht ohne ID gespeichert werden!"); + return; + } + else if (currMeetingUI.meetingName.equals("")) { + EditText editMName = findViewById(R.id.TextMeetingName); + editMName.setText(currMeetingUI.meetingID); + currMeetingUI.meetingName = currMeetingUI.meetingID; + } + + + int foundCurr = searchMeetingInList(listMeetings, currMeetingUI.meetingName); + if (foundCurr == -1) { + listMeetings.add(currMeetingUI); + if (listMeetings.size() == 1) { + setLastMeeting(0); + } else { + setLastMeeting(listMeetings.size() - 1); + } + + } else { + Meeting currMeeting = getMeetings().get(foundCurr); + currMeeting.meetingID = currMeetingUI.meetingID; + currMeeting.meetingPWD = currMeetingUI.meetingPWD; + currMeeting.updateAttendee(currMeetingUI.attendees.get(0).name, currMeetingUI.attendees.get(0).num); + listMeetings.set(foundCurr, currMeeting); + setLastMeeting(foundCurr); + } + saveMeetingList(listMeetings); + fillDropdownMeetingName(); + } + +} + + +class Attendee implements Serializable { + public String name; + public String num; + + public Attendee(String name, String num) { + this.name = name; + this.num = num; + } +} + +class Meeting implements Serializable { + public String meetingName; + public String meetingID; + public String meetingPWD; + public ArrayList attendees; + public int lastAtt; + + public Meeting(String meetingName, String meetingID, String meetingPWD, String nameAttendee, String numAttendee) { + this.meetingName = meetingName; + this.meetingID = meetingID; + this.meetingPWD = meetingPWD; + this.attendees = new ArrayList<>(); + Attendee attendee = new Attendee(nameAttendee, numAttendee); + this.attendees.add(attendee); + this.lastAtt = 0; + } + + public void addAttendee(String name, String num) { + Attendee attendee = new Attendee(name, num); + this.attendees.add(attendee); + this.lastAtt = attendees.size() - 1; + } + + public int searchAttendee(String name) { + int found = -1; + for (int i = 0; i < this.attendees.size(); i++) { + if (this.attendees.get(i).name.equals(name)) { + found = i; + break; + } + } + return found; + } + + public void updateAttendee(String name, String num) { + + int found = searchAttendee(name); + + if (found == -1) { + addAttendee(name, num); + } else { + this.attendees.get(found).num = num; + } + } + + public String info() { + return "Meeting Name: " + this.meetingName + "\n" + + "Meeting-ID: " + this.meetingID + "\n" + + "Kenncode: " + this.meetingPWD; + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/clipboard.png b/app/src/main/res/drawable/clipboard.png new file mode 100644 index 0000000..9bc320f Binary files /dev/null and b/app/src/main/res/drawable/clipboard.png differ diff --git a/app/src/main/res/drawable/eyeoff.png b/app/src/main/res/drawable/eyeoff.png new file mode 100644 index 0000000..9b7ba5d Binary files /dev/null and b/app/src/main/res/drawable/eyeoff.png differ diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/iconfinder_check_7124119_32.png b/app/src/main/res/drawable/iconfinder_check_7124119_32.png new file mode 100644 index 0000000..853c1ef Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_check_7124119_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_eye_7124182_32.png b/app/src/main/res/drawable/iconfinder_eye_7124182_32.png new file mode 100644 index 0000000..6733412 Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_eye_7124182_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_login_7124097_32.png b/app/src/main/res/drawable/iconfinder_login_7124097_32.png new file mode 100644 index 0000000..309f2ff Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_login_7124097_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_pencil_7124178_32.png b/app/src/main/res/drawable/iconfinder_pencil_7124178_32.png new file mode 100644 index 0000000..58182bd Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_pencil_7124178_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_phone_7124181_32.png b/app/src/main/res/drawable/iconfinder_phone_7124181_32.png new file mode 100644 index 0000000..49f3390 Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_phone_7124181_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_pluscircle_7124019_32.png b/app/src/main/res/drawable/iconfinder_pluscircle_7124019_32.png new file mode 100644 index 0000000..03db53a Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_pluscircle_7124019_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_save_7124134_32.png b/app/src/main/res/drawable/iconfinder_save_7124134_32.png new file mode 100644 index 0000000..077368c Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_save_7124134_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_share_7124186_32.png b/app/src/main/res/drawable/iconfinder_share_7124186_32.png new file mode 100644 index 0000000..e0f58b0 Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_share_7124186_32.png differ diff --git a/app/src/main/res/drawable/iconfinder_trash_7124159_32.png b/app/src/main/res/drawable/iconfinder_trash_7124159_32.png new file mode 100644 index 0000000..9e65436 Binary files /dev/null and b/app/src/main/res/drawable/iconfinder_trash_7124159_32.png differ diff --git a/app/src/main/res/drawable/show_password_selector.xml b/app/src/main/res/drawable/show_password_selector.xml new file mode 100644 index 0000000..b59ce6d --- /dev/null +++ b/app/src/main/res/drawable/show_password_selector.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..98b5f93 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + +