diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..7712161 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index c12874f..d05ffea 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "de.joel.zoomhelper" minSdkVersion 21 targetSdkVersion 30 - versionCode 14 - versionName '0.5' + versionCode 15 + versionName '0.5.1' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/de/joel/zoomhelper/APKDownloader.java b/app/src/main/java/de/joel/zoomhelper/APKDownloader.java new file mode 100644 index 0000000..e64b656 --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/APKDownloader.java @@ -0,0 +1,82 @@ +package de.joel.zoomhelper; + +import android.app.Activity; +import android.app.DownloadManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.Settings; +import android.util.Log; +import android.widget.Toast; + +import androidx.core.content.FileProvider; + +import java.io.File; +import java.util.Timer; +import java.util.TimerTask; + +public class APKDownloader { + public void downloadAPK(Context context, String fileName, Uri uri) { + Activity act = (Activity)context; + File destination = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), fileName); + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) { + if (!context.getPackageManager().canRequestPackageInstalls()) { + Toast.makeText(context, R.string.PleaseAllowUnknownSources, Toast.LENGTH_LONG).show(); + act.startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:de.joel.zoomhelper")), 101); + Timer timer = new Timer(true); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + if (context.getPackageManager().canRequestPackageInstalls()) { + act.finishActivity(101); + downloadAPK(context, fileName, uri); + timer.cancel(); + } + } + }, 0, 1000); + return; + } + } + + //Delete update file if exists + final Uri localUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", destination); + if (destination.exists()) { + //noinspection ResultOfMethodCallIgnored + destination.delete(); + } + + //Download Script + DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); + DownloadManager.Request request = new DownloadManager.Request(uri); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + Log.d("Desturi", localUri.getPath()); + request.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, fileName); + final long downloadID = downloadManager.enqueue(request); + + BroadcastReceiver onDownloadComplete = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + //Fetching the download id received with the broadcast + long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); + //Checking if the received broadcast is for our enqueued download by matching download id + if (downloadID == id) { + Intent install = new Intent(Intent.ACTION_VIEW); + install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); + install.setDataAndType(localUri, + downloadManager.getMimeTypeForDownloadedFile(downloadID)); + context.startActivity(install); + + context.unregisterReceiver(this); + } + } + }; + context.registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); + } +} diff --git a/app/src/main/java/de/joel/zoomhelper/Attendee.java b/app/src/main/java/de/joel/zoomhelper/Attendee.java new file mode 100644 index 0000000..efe95e1 --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/Attendee.java @@ -0,0 +1,30 @@ +package de.joel.zoomhelper; + +import java.io.Serializable; + +public class Attendee implements Serializable { + private static final long serialVersionUID = 6196688086302483907L; + private String name; + private String num; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNum() { + return num; + } + + public void setNum(String num) { + this.num = num; + } + + public Attendee(String name, String num) { + this.name = name; + this.num = num; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/joel/zoomhelper/InstantAutoComplete.java b/app/src/main/java/de/joel/zoomhelper/InstantAutoComplete.java new file mode 100644 index 0000000..439d723 --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/InstantAutoComplete.java @@ -0,0 +1,25 @@ +package de.joel.zoomhelper; + +import android.content.Context; +import android.util.AttributeSet; + +public class InstantAutoComplete extends androidx.appcompat.widget.AppCompatAutoCompleteTextView { + + 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 false; + } + +} \ No newline at end of file diff --git a/app/src/main/java/de/joel/zoomhelper/MainActivity.java b/app/src/main/java/de/joel/zoomhelper/MainActivity.java index b1988b2..fa53be2 100644 --- a/app/src/main/java/de/joel/zoomhelper/MainActivity.java +++ b/app/src/main/java/de/joel/zoomhelper/MainActivity.java @@ -1,22 +1,11 @@ package de.joel.zoomhelper; import android.annotation.SuppressLint; -import android.app.DownloadManager; -import android.content.BroadcastReceiver; import android.content.ClipData; import android.content.ClipboardManager; -import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; import android.net.Uri; -import android.os.Build; import android.os.Bundle; -import android.os.Environment; -import android.provider.Settings; -import android.util.AttributeSet; -import android.util.Base64; -import android.util.Log; import android.view.View; import android.widget.AutoCompleteTextView; import android.widget.EditText; @@ -27,7 +16,6 @@ import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.content.FileProvider; import androidx.core.content.pm.ShortcutInfoCompat; import androidx.core.content.pm.ShortcutManagerCompat; import androidx.core.graphics.drawable.IconCompat; @@ -37,353 +25,146 @@ import com.github.javiersantos.appupdater.enums.UpdateFrom; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.textfield.TextInputLayout; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.File; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import java.util.Objects; -import java.util.Timer; -import java.util.TimerTask; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN; - -class InstantAutoComplete extends androidx.appcompat.widget.AppCompatAutoCompleteTextView { - - 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 false; - } - -} - - public class MainActivity extends AppCompatActivity { - public boolean testing; - + private final MeetingsController meetingsController = new MeetingsController(this); + private final MeetingImportController meetingImportController = new MeetingImportController(meetingsController, this); @Override protected void onCreate(Bundle savedInstanceState) { - - Intent myIntent = getIntent(); // gets the previously created intent - String action = myIntent.getAction(); - String type = myIntent.getType(); - - - String meetingName = myIntent.getStringExtra("meetingName"); - boolean joinImmediately = myIntent.getBooleanExtra("joinImmediately", false); - testing = myIntent.getBooleanExtra("testing", false); - super.onCreate(savedInstanceState); + //get intent parameters + final Intent myIntent = getIntent(); + final String action = myIntent.getAction(); + final String type = myIntent.getType(); + final String meetingName = myIntent.getStringExtra("meetingName"); + boolean joinImmediately = myIntent.getBooleanExtra("joinImmediately", false); + //final boolean testing = myIntent.getBooleanExtra("testing", false); + setContentView(R.layout.activity_main); + + //views final ScrollView scrollview = findViewById(R.id.scrollArea); + final ImageView saveIcon = findViewById(R.id.imageSave); + final ImageView trashIcon = findViewById(R.id.imageTrash); + final ImageView AttIcon = findViewById(R.id.imageAttend); + final ImageView AddIcon = findViewById(R.id.imageAdd); + final EditText meetingID = findViewById(R.id.textBoxID); + final ImageView ShareIcon = findViewById(R.id.imageShare); + final ImageView ShortcutIcon = findViewById(R.id.imageCreateShortcut); + //add event listeners to views + saveIcon.setOnClickListener(v -> saveMeetingFromUI()); + trashIcon.setOnClickListener(v -> meetingsController.removeMeeting(meetingsController.searchMeetingInList(meetingsController.getMeetings(), createCurrMeetingFromUI().getMeetingName()))); + AttIcon.setOnClickListener(v -> btnJoin_onClick(null)); + AddIcon.setOnClickListener(v -> { + fillBlank(); + meetingID.requestFocus(); + }); + ShareIcon.setOnClickListener(v -> startActivity(createCurrMeetingFromUI().share())); + ShortcutIcon.setOnClickListener(v -> showCreateShortcutUI()); - int meetingIndex = searchMeetingInList(getMeetings(), meetingName); + //show alert if meeting from shortcut not found + final int meetingIndex = meetingsController.searchMeetingInList(meetingsController.getMeetings(), meetingName); if (meetingIndex == -1) { if (meetingName != null) { - AlertDialog.Builder dialog = new AlertDialog.Builder(this); + final AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setMessage(R.string.shortcutLaunchFailedText); dialog.setTitle(R.string.hint); - AlertDialog alertDialog = dialog.create(); + final AlertDialog alertDialog = dialog.create(); alertDialog.show(); } joinImmediately = false; } - if (meetingIndex <= getMeetings().size() && meetingIndex != -1) { - setLastMeeting(meetingIndex); - AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); + //adjust ui for meeting from shortcut + if (meetingIndex <= meetingsController.getMeetings().size() && meetingIndex != -1) { + meetingsController.setLastMeeting(meetingIndex); + final AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); textMeetingName.setEnabled(false); textMeetingName.setAdapter(null); - ImageView imageTrash = findViewById(R.id.imageTrash); - imageTrash.setVisibility(View.GONE); - TextInputLayout layoutMeetingName = findViewById(R.id.layoutMeetingName); + trashIcon.setVisibility(View.GONE); + final TextInputLayout layoutMeetingName = findViewById(R.id.layoutMeetingName); layoutMeetingName.setEndIconMode(TextInputLayout.END_ICON_NONE); } - - //watchMeetingNameBox(); fillDropdownMeetingName(); - if (getLastMeeting() != -1) { + + //fill ui with data from last selected meeting or show error if config version changed or index out of bounds + if (meetingsController.getLastMeeting() != -1) { try { - fillMeeting(getLastMeeting()); + fillMeeting(meetingsController.getLastMeeting()); scrollview.post(() -> scrollview.scrollTo(0, scrollview.getChildAt(0).getHeight())); } catch (IndexOutOfBoundsException e) { - AlertDialog.Builder dialog = new AlertDialog.Builder(this); + final AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setMessage(R.string.resetDataText); dialog.setTitle(R.string.hint); - AlertDialog alertDialog = dialog.create(); + final AlertDialog alertDialog = dialog.create(); alertDialog.show(); - setLastMeeting(-1); - saveMeetingList(new ArrayList<>()); + meetingsController.setLastMeeting(-1); + meetingsController.saveMeetingList(new ArrayList<>()); } } - watchSaveIcon(); - watchAttIcon(); - watchDeleteIcon(); - watchNewIcon(); - watchShareIcon(); - watchShortcutIcon(); + //handle meeting invitation text sent to ZoomHelper if (Intent.ACTION_SEND.equals(action) && type != null) { if ("text/plain".equals(type)) { - handleSendText(myIntent); // Handle text being sent + meetingImportController.handleSendText(myIntent); } } + //join meeting immediately, otherwise enable app updater if (joinImmediately) { - Meeting currMeeting = getMeetings().get(meetingIndex); - String url = buildZoomURL(currMeeting.meetingID, currMeeting.meetingPWD, currMeeting.attendees.get(currMeeting.lastAtt).name, currMeeting.attendees.get(currMeeting.lastAtt).num); - launchZoomUrl(url); + final Meeting currMeeting = meetingsController.getMeetings().get(meetingIndex); + new ZoomLink(this, currMeeting).launch(); } else { - AppUpdater appUpdater = new AppUpdater(this).setUpdateFrom(UpdateFrom.XML).setUpdateXML("https://baldaufwd.de/ZoomHelper/update.xml"); - appUpdater.setButtonUpdateClickListener((dialog, which) -> downloadAPK()); + final AppUpdater appUpdater = new AppUpdater(this).setUpdateFrom(UpdateFrom.XML).setUpdateXML("https://baldaufwd.de/ZoomHelper/update.xml"); + final APKDownloader apkDownloader = new APKDownloader(); + appUpdater.setButtonUpdateClickListener((dialog, which) -> apkDownloader.downloadAPK(this, "ZoomHelper.apk", Uri.parse("https://baldaufwd.de/ZoomHelper/ZoomHelper.apk"))); appUpdater.start(); } } @Override public void onWindowFocusChanged(boolean hasFocus) { + //check for importable meeting invitation from clipboard when ZoomHelper gained focus super.onWindowFocusChanged(hasFocus); if (hasFocus) { importFromClipboard(); } } - - /* private void watchImportIcon() { - ImageView ImportIcon = findViewById(R.id.imageImport); - ImportIcon.setOnClickListener(v -> importFromClipboard()); - } - - void importFromClipboard() { - Log.d("import", "ImportFromClipboard"); - ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE); - Log.d("clipboardManager", clipboard.toString()); - if (clipboard.hasPrimaryClip() && clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN)) { - String text = clipboard.getPrimaryClip().getItemAt(0).getText().toString(); - Log.d("text", text); - handleSendText(text); - } - } */ - private void importFromClipboard() { - LinearLayout layoutBegin = findViewById(R.id.layoutBegin); - ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE); + final LinearLayout layoutBegin = findViewById(R.id.layoutBegin); + final ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE); - Snackbar snackbar = Snackbar.make(layoutBegin,R.string.foundImportableMeetingClipboard,Snackbar.LENGTH_INDEFINITE).setDuration(7000); + final Snackbar snackbar = Snackbar.make(layoutBegin, R.string.foundImportableMeetingClipboard, Snackbar.LENGTH_INDEFINITE).setDuration(7000); snackbar.setAction(R.string.importMeeting, view -> { String text = clipboard.getPrimaryClip().getItemAt(0).getText().toString(); - handleSendText(text); + meetingImportController.handleSendText(text); ClipData clipData = ClipData.newPlainText("", ""); clipboard.setPrimaryClip(clipData); }); if (clipboard.hasPrimaryClip() && clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN)) { - String text = clipboard.getPrimaryClip().getItemAt(0).getText().toString(); - if (handleSendText(text, true)) { + final String text = clipboard.getPrimaryClip().getItemAt(0).getText().toString(); + if ( meetingImportController.handleSendText(text, true)) { snackbar.show(); } } } - - private void downloadAPK() { - String fileName = "ZoomHelper.apk"; - File destination = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), fileName); - -/* - if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED - || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - - // this will request for permission when user has not granted permission for the app - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); - downloadAPK(); - } else {*/ - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) { - if (!getPackageManager().canRequestPackageInstalls()) { - Toast.makeText(this, R.string.PleaseAllowUnknownSources, Toast.LENGTH_LONG).show(); - startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:de.joel.zoomhelper")), 101); - Timer timer = new Timer(true); - timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - if (getPackageManager().canRequestPackageInstalls()) { - finishActivity(101); - downloadAPK(); - timer.cancel(); - } - } - }, 0, 1000); - return; - } - } - - - //Delete update file if exists - final Uri localUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", destination); - if (destination.exists()) - //file.delete() - test this, I think sometimes it doesnt work - destination.delete(); - - //Download Script - DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); - Uri uri = Uri.parse("https://baldaufwd.de/ZoomHelper/ZoomHelper.apk"); - DownloadManager.Request request = new DownloadManager.Request(uri); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - Log.d("Desturi", localUri.getPath()); - request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, fileName); - final long downloadID = downloadManager.enqueue(request); - - BroadcastReceiver onDownloadComplete = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - //Fetching the download id received with the broadcast - long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); - //Checking if the received broadcast is for our enqueued download by matching download id - if (downloadID == id) { - Intent install = new Intent(Intent.ACTION_VIEW); - install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); - install.setDataAndType(localUri, - downloadManager.getMimeTypeForDownloadedFile(downloadID)); - startActivity(install); - - unregisterReceiver(this); - } - } - }; - registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); - } - //} - - private void handleSendText(Intent intent) { - String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); - handleSendText(sharedText); - } - - private void handleSendText(String sharedText) { - handleSendText(sharedText, false); - } - - private boolean handleSendText(String sharedText, boolean checkOnly) { - String meetingID = ""; - String meetingPWD = ""; - String meetingName = ""; - - if (sharedText != null) { - Matcher matcher = Pattern.compile("(?i)(?<=(Meeting-ID:)|(Meeting\\sID:)|(ID:)).+").matcher(sharedText); - if (matcher.find()) { - meetingID = matcher.group(0).trim(); - } - matcher = Pattern.compile("(?i)(?<=(Kenncode:)|(Passwort:)|(Passcode:)|(Password:)).+").matcher(sharedText); - if (matcher.find()) { - meetingPWD = matcher.group(0).trim(); - } - matcher = Pattern.compile("(?i)(?<=(Thema:)|(Meeting\\sName:)|(Topic:)).+").matcher(sharedText); - if (matcher.find()) { - meetingName = matcher.group(0).trim(); - } - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.app_name); - builder.setMessage(R.string.meetingAlreadyExists); - - if (meetingID.equals("")) { - builder.setMessage(R.string.importError); - builder.setPositiveButton(R.string.ok, (dialog, which) -> { - dialog.dismiss(); - }); - AlertDialog alert = builder.create(); - if (!checkOnly) alert.show(); - return false; - } else { - - Meeting mtgToImport = new Meeting(meetingName, meetingID, meetingPWD, "", ""); - - if (searchMeetingInList(getMeetings(), mtgToImport.meetingName) == -1 && !checkOnly) { - fillMeeting(mtgToImport); - } else { - builder.setPositiveButton(R.string.override, (dialog, which) -> { - int found = searchMeetingInList(getMeetings(), mtgToImport.meetingName); - importMeeting(mtgToImport, false); - fillMeeting(found); - dialog.dismiss(); - }); - builder.setNegativeButton(R.string.rename, (dialog, which) -> { - mtgToImport.meetingName = ""; - fillMeeting(mtgToImport); - dialog.dismiss(); - }); - AlertDialog alert = builder.create(); - if (!checkOnly) alert.show(); - return true; - } - } - - - /* AlertDialog.Builder builder = new AlertDialog.Builder(this); - - builder.setTitle(R.string.app_name); - - if (meetingID.equals("")) { - builder.setMessage(R.string.importError); - builder.setPositiveButton(R.string.ok, (dialog, which) -> { - dialog.dismiss(); - }); - } else { - builder.setMessage(getString(R.string.wantToimportMeeting) + "\n" + mtgToImport.info()); - - builder.setPositiveButton(R.string.yes, (dialog, which) -> { - dialog.dismiss(); - importMeetingToUI(mtgToImport); - }); - - builder.setNegativeButton(R.string.no, (dialog, which) -> { - dialog.dismiss(); - }); - } - - AlertDialog alert = builder.create(); - alert.show();*/ - } - return true; - } - - private void watchShortcutIcon() { - ImageView ShortcutIcon = findViewById(R.id.imageCreateShortcut); - ShortcutIcon.setOnClickListener(v -> showCreateShortcutUI()); - } - private void showCreateShortcutUI() { - int meeting = searchMeetingInList(getMeetings(), createCurrMeetingFromUI().meetingName); + final int meeting = meetingsController.searchMeetingInList(meetingsController.getMeetings(), createCurrMeetingFromUI().getMeetingName()); - AlertDialog.Builder builder = new AlertDialog.Builder(this); + final AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.app_name); @@ -395,11 +176,8 @@ public class MainActivity extends AppCompatActivity { showCreateShortcutUI(); }); - builder.setNegativeButton(R.string.cancel, (dialog, which) -> { - dialog.dismiss(); - }); - } - else { + builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); + } else { builder.setMessage(R.string.WantToJoinImmediately); builder.setPositiveButton(R.string.joinImmediately, (dialog, which) -> { dialog.dismiss(); @@ -411,25 +189,22 @@ public class MainActivity extends AppCompatActivity { createMeetingShortcut(meeting, false); }); } - AlertDialog alert = builder.create(); + final AlertDialog alert = builder.create(); alert.show(); - - //createMeetingShortcut(searchMeetingInList(getMeetings(), createCurrMeetingFromUI().meetingName), false); } private void createMeetingShortcut(int meetingIndex, boolean joinImmediately) { - - Meeting meeting = getMeetings().get(meetingIndex); + final Meeting meeting = meetingsController.getMeetings().get(meetingIndex); if (ShortcutManagerCompat.isRequestPinShortcutSupported(this)) { - ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(this, meeting.meetingName) - .setShortLabel(meeting.meetingName) - .setLongLabel(meeting.meetingName) + ShortcutInfoCompat shortcutInfo = new ShortcutInfoCompat.Builder(this, meeting.getMeetingName()) + .setShortLabel(meeting.getMeetingName()) + .setLongLabel(meeting.getMeetingName()) .setIcon(IconCompat.createWithResource(this, R.mipmap.ic_launcher)) .setIntents(new Intent[]{ new Intent(this, MainActivity.class) .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) - .putExtra("meetingName", meeting.meetingName) + .putExtra("meetingName", meeting.getMeetingName()) .putExtra("joinImmediately", joinImmediately) .setAction("LOCATION_SHORTCUT"), }) @@ -440,87 +215,12 @@ public class MainActivity extends AppCompatActivity { } } - - 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); - EditText meetingID = findViewById(R.id.textBoxID); - AddIcon.setOnClickListener(v -> { - fillBlank(); - meetingID.requestFocus(); - }); - } - - 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(searchMeetingInList(getMeetings(), createCurrMeetingFromUI().meetingName))); - } - - private void removeMeeting(int meeting) { - ArrayList meetings = getMeetings(); - if (meetings.size() > 0 && meeting != -1) { - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - - builder.setTitle(R.string.app_name); - builder.setMessage(getString(R.string.suretoremove, meetings.get(meeting).meetingName)); - - builder.setPositiveButton(R.string.yes, (dialog, which) -> { - dialog.dismiss(); - 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(); - } - }); - - builder.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss()); - - AlertDialog alert = builder.create(); - alert.show(); - - } - } - - - 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); + public void fillBlank() { + final EditText editMeetingName = findViewById(R.id.TextMeetingName); + final EditText editID = findViewById(R.id.textBoxID); + final EditText editPW = findViewById(R.id.editTextTextPassword2); + final AutoCompleteTextView editName = findViewById(R.id.textBoxName); + final EditText editAtt = findViewById(R.id.editAtt); editMeetingName.setText(""); editID.setText(""); @@ -530,24 +230,9 @@ public class MainActivity extends AppCompatActivity { editAtt.setText(""); } - private void watchSaveIcon() { - ImageView saveIcon = findViewById(R.id.imageSave); - saveIcon.setOnClickListener(v -> saveMeetingFromUI()); - } - - 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()); + final AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); + final int search = meetingsController.searchMeetingInList(meetingsController.getMeetings(), textMeetingName.getText().toString()); if (search != -1) { fillMeeting(search); } @@ -555,354 +240,107 @@ public class MainActivity extends AppCompatActivity { @SuppressLint("ClickableViewAccessibility") public void fillDropdownMeetingName() { - ArrayList meetings = getMeetings(); + final ArrayList meetings = meetingsController.getMeetings(); String[] meetingNames = new String[meetings.size()]; for (int i = 0; i < meetings.size(); i++) { - meetingNames[i] = meetings.get(i).meetingName; + meetingNames[i] = meetings.get(i).getMeetingName(); } - AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); - //ImageView dropdown = findViewById(R.id.iconDropdownMeetingName); - AutoSuggestAdapter adapter = new AutoSuggestAdapter(this, android.R.layout.simple_dropdown_item_1line); + final AutoCompleteTextView textMeetingName = findViewById(R.id.TextMeetingName); + final AutoSuggestAdapter adapter = new AutoSuggestAdapter(this, android.R.layout.simple_dropdown_item_1line); adapter.setData(Arrays.asList(meetingNames)); textMeetingName.setAdapter(adapter); textMeetingName.setOnTouchListener((paramView, paramMotionEvent) -> false); textMeetingName.setOnItemClickListener((arg0, view, arg2, arg3) -> fillWithSelectedMeeting()); - - /*dropdown.setOnClickListener(v -> { - textMeetingName.showDropDown(); - adapter.getFilter().filter(null); - });*/ } @SuppressLint("ClickableViewAccessibility") public void fillDropdownAttendeeName(int meetingIndex) { - Meeting meeting = getMeetings().get(meetingIndex); - ArrayList attendees = meeting.attendees; + final Meeting meeting = meetingsController.getMeetings().get(meetingIndex); + final ArrayList attendees = meeting.getAttendees(); String[] attNames = new String[attendees.size()]; for (int i = 0; i < attendees.size(); i++) { - attNames[i] = attendees.get(i).name; + attNames[i] = attendees.get(i).getName(); } - AutoCompleteTextView textName = findViewById(R.id.textBoxName); - //ImageView dropdown = findViewById(R.id.iconDropdownAttName); - AutoSuggestAdapter adapter = new AutoSuggestAdapter(this, android.R.layout.simple_dropdown_item_1line); + final AutoCompleteTextView textName = findViewById(R.id.textBoxName); + final AutoSuggestAdapter adapter = new AutoSuggestAdapter(this, android.R.layout.simple_dropdown_item_1line); + adapter.setData(Arrays.asList(attNames)); textName.setAdapter(adapter); textName.setOnTouchListener((paramView, paramMotionEvent) -> false); - textName.setOnItemClickListener((arg0, view, arg2, arg3) -> fillWithSelectedAtt(meetingIndex)); - /*dropdown.setOnClickListener(v -> { - textName.showDropDown(); - adapter.getFilter().filter(null); - });*/ } private void fillWithSelectedAtt(int meetingIndex) { - AutoCompleteTextView textName = findViewById(R.id.textBoxName); - EditText editAtt = findViewById(R.id.editAtt); - int found = getMeetings().get(meetingIndex).searchAttendee(textName.getText().toString()); - editAtt.setText(getMeetings().get(meetingIndex).attendees.get(found).num); + final AutoCompleteTextView textName = findViewById(R.id.textBoxName); + final EditText editAtt = findViewById(R.id.editAtt); + final int found = meetingsController.getMeetings().get(meetingIndex).searchAttendee(textName.getText().toString()); + editAtt.setText(meetingsController.getMeetings().get(meetingIndex).getAttendees().get(found).getNum()); } - public void fillMeeting(Meeting meeting) { - 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); + final EditText editMeetingName = findViewById(R.id.TextMeetingName); + final EditText editID = findViewById(R.id.textBoxID); + final EditText editPW = findViewById(R.id.editTextTextPassword2); + final EditText editName = findViewById(R.id.textBoxName); + final EditText editAtt = findViewById(R.id.editAtt); editID.setError(null); editID.clearFocus(); - editMeetingName.setText(meeting.meetingName); - editID.setText(meeting.meetingID); - editPW.setText(meeting.meetingPWD); - editName.setText(meeting.attendees.get(meeting.lastAtt).name); - editAtt.setText(meeting.attendees.get(meeting.lastAtt).num); + editMeetingName.setText(meeting.getMeetingName()); + editID.setText(meeting.getMeetingID()); + editPW.setText(meeting.getMeetingPWD()); + editName.setText(meeting.getAttendees().get(meeting.getLastAtt()).getName()); + editAtt.setText(meeting.getAttendees().get(meeting.getLastAtt()).getNum()); } public void fillMeeting(int id) { - fillMeeting(getMeetings().get(id)); + fillMeeting(meetingsController.getMeetings().get(id)); fillDropdownAttendeeName(id); } - - private void launchZoomUrl(String url) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - if (intent.resolveActivity(getPackageManager()) != null) { - startActivity(intent); - } - if (testing) { - //For Debugging: Show URL in Alert - AlertDialog.Builder dialog = new AlertDialog.Builder(this); - dialog.setMessage(url); - dialog.setTitle("Zoom URL (for testing)"); - AlertDialog alertDialog = dialog.create(); - alertDialog.show(); - } - } - - - private String buildZoomURL(String confno, String pwd, String name, String attendees) { - Uri.Builder builder = new Uri.Builder(); - builder.scheme("zoomus") - .authority("zoom.us") - .appendPath("join") - .appendQueryParameter("confno", confno.replace(" ", "")) - .appendQueryParameter("pwd", pwd); - - if (!Objects.equals(attendees, "")) { - builder.appendQueryParameter("uname", name + " (" + attendees + ")"); - } else - builder.appendQueryParameter("uname", name); - return builder.build().toString(); - } - - 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 { - if (objOutputStream == null) throw new AssertionError(); - objOutputStream.writeObject(obj); - } catch (IOException e) { - e.printStackTrace(); - } - try { - objOutputStream.reset(); - } catch (IOException e) { - e.printStackTrace(); - } - } - try { - if (objOutputStream == null) throw new AssertionError(); - 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 - if (obj == null) throw new AssertionError(); - Meeting meeting = (Meeting) obj.readObject(); - listMeetings.add(meeting); - } - } catch (EOFException ex) { - //ex.printStackTrace(); - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - } - return listMeetings; - } - - @SuppressLint("ApplySharedPref") - public void saveMeetingList(ArrayList meetingList) { - SharedPreferences mPrefs = getPreferences(MODE_PRIVATE); - SharedPreferences.Editor prefsEditor = mPrefs.edit(); - prefsEditor.putString("Meetings", meetingsToString(meetingList)); - prefsEditor.commit(); - } - - @SuppressLint("ApplySharedPref") - 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) { saveMeetingFromUI(); } - public void btnJoin_onClick(View view) { saveMeetingFromUI(); - Meeting currMeeting = createCurrMeetingFromUI(); - String url = buildZoomURL(currMeeting.meetingID, currMeeting.meetingPWD, currMeeting.attendees.get(currMeeting.lastAtt).name, currMeeting.attendees.get(currMeeting.lastAtt).num); - launchZoomUrl(url); + final Meeting currMeeting = createCurrMeetingFromUI(); + new ZoomLink(this, currMeeting).launch(); } 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); + final EditText editMeetingName = findViewById(R.id.TextMeetingName); + final EditText editID = findViewById(R.id.textBoxID); + final EditText editPW = findViewById(R.id.editTextTextPassword2); + final EditText editName = findViewById(R.id.textBoxName); + final EditText editAtt = findViewById(R.id.editAtt); return new Meeting(editMeetingName.getText().toString(), editID.getText().toString(), editPW.getText().toString(), editName.getText().toString(), editAtt.getText().toString()); } - - public void importMeeting(Meeting meeting, boolean updateAttendee) { - ArrayList listMeetings = getMeetings(); - int foundCurr = searchMeetingInList(listMeetings, meeting.meetingName); - if (foundCurr == -1) { - listMeetings.add(meeting); - if (listMeetings.size() == 1) { - setLastMeeting(0); - } else { - setLastMeeting(listMeetings.size() - 1); - } - - } else { - Meeting currMeeting = getMeetings().get(foundCurr); - currMeeting.meetingID = meeting.meetingID; - currMeeting.meetingPWD = meeting.meetingPWD; - if (updateAttendee) - currMeeting.updateAttendee(meeting.attendees.get(0).name, meeting.attendees.get(0).num); - listMeetings.set(foundCurr, currMeeting); - setLastMeeting(foundCurr); - } - saveMeetingList(listMeetings); - fillDropdownMeetingName(); - fillDropdownAttendeeName(getLastMeeting()); - Toast.makeText(getApplicationContext(), "Meeting gespeichert", Toast.LENGTH_SHORT).show(); - } - - public void importMeeting(Meeting meeting) { - importMeeting(meeting, true); - } - public void saveMeetingFromUI() { - Meeting currMeetingUI = createCurrMeetingFromUI(); + final Meeting currMeetingUI = createCurrMeetingFromUI(); - if (currMeetingUI.meetingID.equals("")) { - EditText editID = findViewById(R.id.textBoxID); + if (currMeetingUI.getMeetingID().equals("")) { + final EditText editID = findViewById(R.id.textBoxID); editID.requestFocus(); - editID.setError("Meeting kann nicht ohne ID gespeichert werden!"); + editID.setError(getString(R.string.meetingWithoutID)); return; - } else if (currMeetingUI.meetingName.equals("")) { - EditText editMName = findViewById(R.id.TextMeetingName); - editMName.setText(currMeetingUI.meetingID); - currMeetingUI.meetingName = currMeetingUI.meetingID; + } else if (currMeetingUI.getMeetingName().equals("")) { + final EditText editMName = findViewById(R.id.TextMeetingName); + editMName.setText(currMeetingUI.getMeetingID()); + currMeetingUI.setMeetingName(currMeetingUI.getMeetingID()); } - importMeeting(currMeetingUI); - } - -} - - -class Attendee implements Serializable { - private static final long serialVersionUID = 6196688086302483907L; - public String name; - public String num; - - public Attendee(String name, String num) { - this.name = name; - this.num = num; - } -} - -class Meeting implements Serializable { - private static final long serialVersionUID = 2606722401897866931L; - 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; - this.lastAtt = found; - } - } - - public String info() { - return "Meeting Name: " + this.meetingName + "\n" + - "Meeting-ID: " + this.meetingID + "\n" + - "Kenncode: " + this.meetingPWD; + meetingImportController.importMeeting(createCurrMeetingFromUI()); } } \ No newline at end of file diff --git a/app/src/main/java/de/joel/zoomhelper/Meeting.java b/app/src/main/java/de/joel/zoomhelper/Meeting.java new file mode 100644 index 0000000..ab37c2a --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/Meeting.java @@ -0,0 +1,109 @@ +package de.joel.zoomhelper; + +import android.content.Intent; + +import java.io.Serializable; +import java.util.ArrayList; + +public class Meeting implements Serializable { + private static final long serialVersionUID = 2606722401897866931L; + private String meetingName; + private String meetingID; + private String meetingPWD; + private ArrayList attendees; + private int lastAtt; + + public String getMeetingName() { + return meetingName; + } + + public void setMeetingName(String meetingName) { + this.meetingName = meetingName; + } + + public String getMeetingID() { + return meetingID; + } + + public void setMeetingID(String meetingID) { + this.meetingID = meetingID; + } + + public String getMeetingPWD() { + return meetingPWD; + } + + public void setMeetingPWD(String meetingPWD) { + this.meetingPWD = meetingPWD; + } + + public ArrayList getAttendees() { + return attendees; + } + + public void setAttendees(ArrayList attendees) { + this.attendees = attendees; + } + + public int getLastAtt() { + return lastAtt; + } + + public void setLastAtt(int lastAtt) { + this.lastAtt = 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).getName().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).setNum(num); + this.lastAtt = found; + } + } + + public String info() { + return "Meeting Name: " + this.meetingName + "\n" + + "Meeting-ID: " + this.meetingID + "\n" + + "Kenncode: " + this.meetingPWD; + } + + public Intent share() { + final Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, this.info()); + sendIntent.setType("text/plain"); + + return Intent.createChooser(sendIntent, null); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/joel/zoomhelper/MeetingImportController.java b/app/src/main/java/de/joel/zoomhelper/MeetingImportController.java new file mode 100644 index 0000000..8e955b9 --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/MeetingImportController.java @@ -0,0 +1,118 @@ +package de.joel.zoomhelper; + +import android.content.Intent; +import android.widget.Toast; + +import androidx.appcompat.app.AlertDialog; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MeetingImportController { + private final MeetingsController meetingsController; + private final MainActivity act; + + public MeetingImportController(MeetingsController meetingsController, MainActivity act) { + this.meetingsController = meetingsController; + this.act = act; + } + + public void handleSendText(Intent intent) { + final String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); + handleSendText(sharedText); + } + + public void handleSendText(String sharedText) { + handleSendText(sharedText, false); + } + + public boolean handleSendText(String sharedText, boolean checkOnly) { + String meetingID = ""; + String meetingPWD = ""; + String meetingName = ""; + + if (sharedText != null) { + Matcher matcher = Pattern.compile("(?i)(?<=(Meeting-ID:)|(Meeting\\sID:)|(ID:)).+").matcher(sharedText); + if (matcher.find()) { + meetingID = Objects.requireNonNull(matcher.group(0)).trim(); + } + matcher = Pattern.compile("(?i)(?<=(Kenncode:)|(Passwort:)|(Passcode:)|(Password:)).+").matcher(sharedText); + if (matcher.find()) { + meetingPWD = Objects.requireNonNull(matcher.group(0)).trim(); + } + matcher = Pattern.compile("(?i)(?<=(Thema:)|(Meeting\\sName:)|(Topic:)).+").matcher(sharedText); + if (matcher.find()) { + meetingName = Objects.requireNonNull(matcher.group(0)).trim(); + } + + final AlertDialog.Builder builder = new AlertDialog.Builder(act); + builder.setTitle(R.string.app_name); + builder.setMessage(R.string.meetingAlreadyExists); + + if (meetingID.equals("")) { + builder.setMessage(R.string.importError); + builder.setPositiveButton(R.string.ok, (dialog, which) -> dialog.dismiss()); + final AlertDialog alert = builder.create(); + if (!checkOnly) alert.show(); + return false; + } else { + + final Meeting mtgToImport = new Meeting(meetingName, meetingID, meetingPWD, "", ""); + + if (meetingsController.searchMeetingInList(meetingsController.getMeetings(), mtgToImport.getMeetingName()) == -1 && !checkOnly) { + act.fillMeeting(mtgToImport); + } else { + builder.setPositiveButton(R.string.override, (dialog, which) -> { + final int found = meetingsController.searchMeetingInList(meetingsController.getMeetings(), mtgToImport.getMeetingName()); + importMeeting(mtgToImport, false); + act.fillMeeting(found); + dialog.dismiss(); + }); + builder.setNegativeButton(R.string.rename, (dialog, which) -> { + mtgToImport.setMeetingName(""); + act.fillMeeting(mtgToImport); + dialog.dismiss(); + }); + final AlertDialog alert = builder.create(); + if (!checkOnly) alert.show(); + return true; + } + } + } + return true; + } + + public void importMeeting(Meeting meeting, boolean updateAttendee) { + final ArrayList listMeetings = meetingsController.getMeetings(); + final int foundCurr = meetingsController.searchMeetingInList(listMeetings, meeting.getMeetingName()); + + if (foundCurr == -1) { + listMeetings.add(meeting); + if (listMeetings.size() == 1) { + meetingsController.setLastMeeting(0); + } else { + meetingsController.setLastMeeting(listMeetings.size() - 1); + } + + } else { + final Meeting currMeeting = meetingsController.getMeetings().get(foundCurr); + currMeeting.setMeetingID(meeting.getMeetingID()); + currMeeting.setMeetingPWD(meeting.getMeetingPWD()); + if (updateAttendee) + currMeeting.updateAttendee(meeting.getAttendees().get(0).getName(), meeting.getAttendees().get(0).getNum()); + listMeetings.set(foundCurr, currMeeting); + meetingsController.setLastMeeting(foundCurr); + } + meetingsController.saveMeetingList(listMeetings); + act.fillDropdownMeetingName(); + act.fillDropdownAttendeeName(meetingsController.getLastMeeting()); + Toast.makeText(act, R.string.meetingSaved, Toast.LENGTH_SHORT).show(); + } + + public void importMeeting(Meeting meeting) { + importMeeting(meeting, true); + } + +} diff --git a/app/src/main/java/de/joel/zoomhelper/MeetingsController.java b/app/src/main/java/de/joel/zoomhelper/MeetingsController.java new file mode 100644 index 0000000..2007592 --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/MeetingsController.java @@ -0,0 +1,172 @@ +package de.joel.zoomhelper; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Base64; + +import androidx.appcompat.app.AlertDialog; + +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.util.ArrayList; + +public class MeetingsController { + private final Context context; + private final Activity activity; + + public MeetingsController(Context context) { + this.context = context; + this.activity = (Activity) context; + } + + + + 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 { + if (objOutputStream == null) throw new AssertionError(); + objOutputStream.writeObject(obj); + } catch (IOException e) { + e.printStackTrace(); + } + try { + objOutputStream.reset(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + if (objOutputStream == null) throw new AssertionError(); + 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 + if (obj == null) throw new AssertionError(); + Meeting meeting = (Meeting) obj.readObject(); + listMeetings.add(meeting); + } + } catch (EOFException ex) { + //ex.printStackTrace(); + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } + return listMeetings; + } + + @SuppressLint("ApplySharedPref") + public void saveMeetingList(ArrayList meetingList) { + SharedPreferences mPrefs = activity.getPreferences(Context.MODE_PRIVATE); + SharedPreferences.Editor prefsEditor = mPrefs.edit(); + prefsEditor.putString("Meetings", meetingsToString(meetingList)); + prefsEditor.commit(); + } + + @SuppressLint("ApplySharedPref") + public void setLastMeeting(int id) { + SharedPreferences mPrefs = activity.getPreferences(Context.MODE_PRIVATE); + SharedPreferences.Editor prefsEditor = mPrefs.edit(); + prefsEditor.putInt("LastMeeting", id); + prefsEditor.commit(); + } + + public int getLastMeeting() { + SharedPreferences mPrefs = activity.getPreferences(Context.MODE_PRIVATE); + return mPrefs.getInt("LastMeeting", -1); + } + + + public ArrayList getMeetings() { + SharedPreferences mPrefs = activity.getPreferences(Context.MODE_PRIVATE); + String value = mPrefs.getString("Meetings", ""); + ArrayList meetingList; + if (value.equals("")) { + meetingList = new ArrayList<>(); + } else { + meetingList = stringToMeetings(value); + } + return meetingList; + } + + public void removeMeeting(int meeting) { + MainActivity act = (MainActivity)context; + ArrayList meetings = getMeetings(); + if (meetings.size() > 0 && meeting != -1) { + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + + builder.setTitle(R.string.app_name); + builder.setMessage(context.getString(R.string.suretoremove, meetings.get(meeting).getMeetingName())); + + builder.setPositiveButton(R.string.yes, (dialog, which) -> { + dialog.dismiss(); + meetings.remove(meeting); + saveMeetingList(meetings); + + if (meetings.size() > 1) { + act.fillDropdownMeetingName(); + if (getLastMeeting() > meetings.size() - 1) { + setLastMeeting(meetings.size() - 1); + act.fillMeeting(getLastMeeting()); + } + } else if (meetings.size() == 1) { + setLastMeeting(0); + act.fillDropdownMeetingName(); + act.fillMeeting(getLastMeeting()); + } else { + setLastMeeting(-1); + act.fillDropdownMeetingName(); + act.fillBlank(); + } + }); + + builder.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss()); + + AlertDialog alert = builder.create(); + alert.show(); + + } + } + + public int searchMeetingInList(ArrayList meetings, String name) { + int found = -1; + for (int i = 0; i < meetings.size(); i++) { + if (meetings.get(i).getMeetingName().equals(name)) { + found = i; + break; + } + } + return found; + } +} \ No newline at end of file diff --git a/app/src/main/java/de/joel/zoomhelper/ZoomLink.java b/app/src/main/java/de/joel/zoomhelper/ZoomLink.java new file mode 100644 index 0000000..bdf7479 --- /dev/null +++ b/app/src/main/java/de/joel/zoomhelper/ZoomLink.java @@ -0,0 +1,51 @@ +package de.joel.zoomhelper; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; + +import java.util.Objects; + +public class ZoomLink { + private final Meeting meeting; + private final Context context; + + public ZoomLink(Context context, Meeting meeting) { + this.meeting = meeting; + this.context = context; + } + + + + + private String buildZoomURL() { + Uri.Builder builder = new Uri.Builder(); + builder.scheme("zoomus") + .authority("zoom.us") + .appendPath("join") + .appendQueryParameter("confno", this.meeting.getMeetingID().replace(" ", "")) + .appendQueryParameter("pwd", this.meeting.getMeetingPWD()); + + if (!Objects.equals(this.meeting.getAttendees().get(this.meeting.getLastAtt()).getNum(), "")) { + builder.appendQueryParameter("uname", this.meeting.getAttendees().get(this.meeting.getLastAtt()).getName() + " (" + this.meeting.getAttendees().get(this.meeting.getLastAtt()).getNum() + ")"); + } else + builder.appendQueryParameter("uname", this.meeting.getAttendees().get(this.meeting.getLastAtt()).getName()); + return builder.build().toString(); + } + + public void launch() { + String url = buildZoomURL(); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + if (intent.resolveActivity(context.getPackageManager()) != null) { + context.startActivity(intent); + } + /*if (testing) { + //For Debugging: Show URL in Alert + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + dialog.setMessage(url); + dialog.setTitle("Zoom URL (for testing)"); + AlertDialog alertDialog = dialog.create(); + alertDialog.show(); + }*/ + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 66514bd..dbe7cea 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -28,7 +28,7 @@ Dialog immer anzeigen Möchtest du das folgende Meeting importieren? "Dieser Text entspricht keinem für ZoomHelper bekannten Meetingeinladungs-Muster " - ok + OK Meeting unter diesem Namen existiert schon. Bitte umbenennen, ansonsten wird es beim Speichern überschrieben überschreiben umbenennen @@ -39,5 +39,7 @@ Du musst das Meeting zunächst speichern, bevor du eine Verknüpfung dazu erstellen kannst Meeting speichern abbrechen + Meeting gespeichert + Meeting kann nicht ohne ID gespeichert werden! \ No newline at end of file