diff --git a/README.md b/README.md index c69fe09d..4118864b 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Please refer to [CONTRIBUTING.md](/CONTRIBUTING.md) for details. ## Contact -Do not hesitate to contact us for any matter, either by sending an email to `thmmynolife@gmail.com`, or by joining our [Discord server][discord-server]. +Do not hesitate to contact us for any matter, either by sending an email to [thmmynolife@gmail.com](mailto:thmmynolife@gmail.com), or by joining our [Discord server][discord-server]. **Legal attribution: Google Play and the Google Play logo are trademarks of Google Inc.* diff --git a/app/build.gradle b/app/build.gradle index 1e2b74e7..253c028b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,9 +41,9 @@ dependencies { implementation 'com.android.support:support-v4:27.1.1' implementation 'com.android.support:cardview-v7:27.1.1' implementation 'com.android.support:recyclerview-v7:27.1.1' - implementation 'com.google.firebase:firebase-core:16.0.1' - implementation 'com.google.firebase:firebase-messaging:17.1.0' - implementation 'com.crashlytics.sdk.android:crashlytics:2.9.4' + implementation 'com.google.firebase:firebase-core:16.0.3' + implementation 'com.google.firebase:firebase-messaging:17.3.0' + implementation 'com.crashlytics.sdk.android:crashlytics:2.9.5' implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.squareup.picasso:picasso:2.5.2' implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2cb20bf0..6432f0c6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -121,7 +121,7 @@ + android:theme="@style/AppTheme.PreferenceTheme"> diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java index 5a0f32b3..f950a1d3 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java @@ -12,9 +12,12 @@ import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.Toast; +import com.google.firebase.analytics.FirebaseAnalytics; + import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.main.MainActivity; import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; import timber.log.Timber; import static gr.thmmy.mthmmy.session.SessionManager.BANNED_USER; @@ -163,6 +166,7 @@ public class LoginActivity extends BaseActivity { Toast.makeText(getApplicationContext(), "Welcome, " + sessionManager.getUsername() + "!", Toast.LENGTH_LONG) .show(); + BaseApplication.getInstance().logFirebaseAnalyticsEvent(FirebaseAnalytics.Event.LOGIN, null); //Go to main Intent intent = new Intent(LoginActivity.this, MainActivity.class); startActivity(intent); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java index d5d8f593..75d0bea8 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java @@ -286,9 +286,11 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo if (pLastPost.contains("by")) { pLastPost = pLastPost.substring(0, pLastPost.indexOf("by")) + "\n" + pLastPost.substring(pLastPost.indexOf("by")); - } else { + } else if (pLastPost.contains("από")) { pLastPost = pLastPost.substring(0, pLastPost.indexOf("από")) + "\n" + pLastPost.substring(pLastPost.indexOf("από")); + } else { + Timber.wtf("Board parsing about to fail. pLastPost came with: %s", pLastPost); } pLastPostUrl = topicColumns.last().select("a:has(img)").first().attr("href"); parsedTopics.add(new Topic(pTopicUrl, pSubject, pStartedBy, pLastPost, pLastPostUrl, diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java index 33025dfa..1709db82 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java @@ -6,7 +6,6 @@ import android.support.annotation.NonNull; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java index 0f44a511..433ba13c 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java @@ -1,7 +1,6 @@ package gr.thmmy.mthmmy.activities.settings; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import gr.thmmy.mthmmy.R; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index dca30b72..8ba2bae3 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -201,6 +201,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo paginationEnabled(false); + Timber.i("Starting initial topic load"); viewModel.loadUrl(topicPageUrl); } @@ -501,10 +502,13 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo public void onDeleteTaskFinished(boolean result) { progressBar.setVisibility(ProgressBar.GONE); - if (result) + if (result) { + Timber.i("Post deleted successfully"); viewModel.reloadPage(); - else + } else { + Timber.w("Failed to delete post"); Toast.makeText(getBaseContext(), "Delete failed!", Toast.LENGTH_SHORT).show(); + } } }); viewModel.setReplyFinishListener(new ReplyTask.ReplyTaskCallbacks() { @@ -524,15 +528,18 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo progressBar.setVisibility(ProgressBar.GONE); if (success) { + Timber.i("Post reply successful"); replyFAB.show(); bottomNavBar.setVisibility(View.VISIBLE); viewModel.setWritingReply(false); if ((postsList.get(postsList.size() - 1).getPostNumber() + 1) % 15 == 0) { + Timber.i("Reply was posted in new page. Switching to last page."); viewModel.loadUrl(ParseHelpers.getBaseURL(viewModel.getTopicUrl()) + "." + 2147483647); } else { viewModel.reloadPage(); } } else { + Timber.w("Post reply unsuccessful"); Toast.makeText(getBaseContext(), "Post failed!", Toast.LENGTH_SHORT).show(); recyclerView.getChildAt(postsList.size() - 1).setAlpha(1); recyclerView.getChildAt(postsList.size() - 1).setEnabled(true); @@ -567,6 +574,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo progressBar.setVisibility(ProgressBar.GONE); if (result) { + Timber.i("Post edit successful"); postsList.get(position).setPostType(Post.TYPE_POST); topicAdapter.notifyItemChanged(position); replyFAB.show(); @@ -574,6 +582,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo viewModel.setEditingPost(false); viewModel.reloadPage(); } else { + Timber.i("Post edit unsuccessful"); Toast.makeText(getBaseContext(), "Edit failed!", Toast.LENGTH_SHORT).show(); recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setAlpha(1); recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setEnabled(true); @@ -632,9 +641,11 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo progressBar.setVisibility(ProgressBar.GONE); switch (resultCode) { case SUCCESS: + Timber.i("Successfully loaded topic with URL %s", viewModel.getTopicUrl()); paginationEnabled(true); break; case NETWORK_ERROR: + Timber.w("Network error on loaded page"); if (viewModel.getPostsList().getValue() == null) { // no page has been loaded yet. Give user the ability to refresh recyclerView.setVisibility(View.GONE); @@ -656,6 +667,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo } break; case UNAUTHORIZED: + Timber.w("Requested topic was unauthorized"); recyclerView.setVisibility(View.GONE); TextView errorTextview = findViewById(R.id.error_textview); errorTextview.setText(getString(R.string.unauthorized_topic_error)); @@ -663,7 +675,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo break; default: //Parse failed - should never happen - Timber.d("Parse failed!"); //TODO report ParseException!!! + Timber.wtf("Parse failed!"); //TODO report ParseException!!! Toast.makeText(getBaseContext(), "Fatal Error", Toast.LENGTH_SHORT).show(); finish(); break; @@ -672,6 +684,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo viewModel.getPrepareForReplyResult().observe(this, prepareForReplyResult -> { progressBar.setVisibility(ProgressBar.GONE); if (prepareForReplyResult != null && prepareForReplyResult.isSuccessful()) { + Timber.i("Prepare for reply successful"); //prepare for a reply viewModel.setWritingReply(true); postsList.add(Post.newQuickReply()); @@ -680,12 +693,14 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo replyFAB.hide(); bottomNavBar.setVisibility(View.GONE); } else { + Timber.i("Prepare for reply unsuccessful"); Snackbar.make(findViewById(R.id.main_content), getString(R.string.generic_network_error), Snackbar.LENGTH_SHORT).show(); } }); viewModel.getPrepareForEditResult().observe(this, result -> { progressBar.setVisibility(ProgressBar.GONE); if (result != null && result.isSuccessful()) { + Timber.i("Prepare for edit successful"); viewModel.setEditingPost(true); postsList.get(result.getPosition()).setPostType(Post.TYPE_EDIT); topicAdapter.notifyItemChanged(result.getPosition()); @@ -693,6 +708,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo replyFAB.hide(); bottomNavBar.setVisibility(View.GONE); } else { + Timber.i("Prepare for edit unsuccessful"); Snackbar.make(findViewById(R.id.main_content), getString(R.string.generic_network_error), Snackbar.LENGTH_SHORT).show(); } }); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java index 6563a715..e6970a80 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java @@ -1,9 +1,7 @@ package gr.thmmy.mthmmy.activities.topic; import android.graphics.Color; -import android.util.Log; -import org.jsoup.Connection; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -249,6 +247,10 @@ public class TopicParser { p_deletePostURL = postDelete.attr("href"); } + Element postEdit = thisRow.select("a:has(img[alt='Αλλαγή'])").first(); + if (postEdit != null) + p_editPostURL = postEdit.attr("href"); + //Finds post's submit date Element postDate = thisRow.select("div.smalltext:matches(στις:)").first(); p_postDate = postDate.text(); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java index f3523953..0a9486b1 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java @@ -38,6 +38,7 @@ public class DeleteTask extends AsyncTask { //Response response = client.newCall(delete).execute(); switch (Posting.replyStatus(response)) { case SUCCESSFUL: + BaseApplication.getInstance().logFirebaseAnalyticsEvent("post_deletion", null); return true; default: Timber.e("Something went wrong. Request string: %s", delete.toString()); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java index f9fe5444..3b5b46f0 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java @@ -51,6 +51,7 @@ public class EditTask extends AsyncTask { Response response = client.newCall(post).execute(); switch (replyStatus(response)) { case SUCCESSFUL: + BaseApplication.getInstance().logFirebaseAnalyticsEvent("post_editing", null); return true; case NEW_REPLY_WHILE_POSTING: //TODO this... diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java index 7259d580..5864e635 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java @@ -9,7 +9,6 @@ import org.jsoup.select.Selector; import java.io.IOException; -import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForEditResult; import gr.thmmy.mthmmy.base.BaseApplication; import okhttp3.OkHttpClient; import okhttp3.Request; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java index 69bd0035..0b527421 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java @@ -54,6 +54,7 @@ public class ReplyTask extends AsyncTask { Response response = client.newCall(post).execute(); switch (replyStatus(response)) { case SUCCESSFUL: + BaseApplication.getInstance().logFirebaseAnalyticsEvent("post_creation", null); return true; case NEW_REPLY_WHILE_POSTING: //TODO this... diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java index 0a5cf821..7c5e5d1f 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java @@ -107,7 +107,6 @@ public class TopicTask extends AsyncTask { return new TopicTaskResult(ResultCode.SUCCESS, topicTitle, replyPageUrl, newPostsList, loadedPageTopicId, currentPageIndex, pageCount, focusedPostIndex, topicTreeAndMods, topicViewers); } catch (IOException e) { - Timber.i(e, "IO Exception"); return new TopicTaskResult(ResultCode.NETWORK_ERROR, null, null, null, 0, 0, 0, 0, null, null); } catch (Exception e) { @@ -115,7 +114,7 @@ public class TopicTask extends AsyncTask { return new TopicTaskResult(ResultCode.UNAUTHORIZED, null, null, null, 0, 0, 0, 0, null, null); } else { - Timber.e(e, "Parsing Error"); + Timber.e(e, "Topic parse failed"); return new TopicTaskResult(ResultCode.PARSING_ERROR, null, null, null, 0, 0, 0, 0, null, null); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java index 570160d3..c713da1f 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java @@ -1,10 +1,7 @@ package gr.thmmy.mthmmy.activities.topic.tasks; -import android.util.SparseArray; - import java.util.ArrayList; -import gr.thmmy.mthmmy.activities.topic.tasks.TopicTask; import gr.thmmy.mthmmy.model.Post; public class TopicTaskResult { diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index 61a02884..ce93b6b1 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -5,20 +5,17 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ResolveInfo; -import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.app.AlertDialog; +import android.support.design.widget.FloatingActionButton; import android.support.v7.content.res.AppCompatResources; import android.support.v7.preference.PreferenceManager; import android.support.v7.widget.AppCompatButton; +import android.support.v7.widget.AppCompatTextView; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; @@ -37,12 +34,8 @@ import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -73,12 +66,15 @@ public class UploadActivity extends BaseActivity { */ public static final String BUNDLE_UPLOAD_CATEGORY = "UPLOAD_CATEGORY"; private static final String uploadIndexUrl = "https://www.thmmy.gr/smf/index.php?action=tpmod;dl=upload"; - private static final String uploadedFrommThmmyPromptHtml = "
uploaded from mTHMMY"; - private static final int REQUEST_CODE_CHOOSE_FILE = 8; - private static final int REQUEST_CODE_CAMERA = 4; - private static final int REQUEST_CODE_FIELDS_BUILDER = 74; + private static final String uploadedFromThmmyPromptHtml = "
uploaded from mTHMMY"; + /** + * Request codes used in activities for result (AFR) calls + */ + private static final int AFR_REQUEST_CODE_CHOOSE_FILE = 8; + private static final int AFR_REQUEST_CODE_CAMERA = 4; + private static final int AFR_REQUEST_CODE_FIELDS_BUILDER = 74; - private static ArrayList uploadRootCategories = new ArrayList<>(); + private ArrayList uploadRootCategories = new ArrayList<>(); private ParseUploadPageTask parseUploadPageTask; private ArrayList bundleCategory; private String categorySelected = "-1"; @@ -94,8 +90,7 @@ public class UploadActivity extends BaseActivity { private EditText uploadTitle; private EditText uploadDescription; private AppCompatButton titleDescriptionBuilderButton; - private AppCompatButton selectFileButton; - //private static AppCompatButton titleDescriptionBuilderButton; + private AppCompatTextView filenameHolder; @Override protected void onCreate(Bundle savedInstanceState) { @@ -141,7 +136,7 @@ public class UploadActivity extends BaseActivity { titleDescriptionBuilderButton = findViewById(R.id.upload_title_description_builder); titleDescriptionBuilderButton.setOnClickListener(view -> { if (categorySelected.equals("-1")) { - Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show(); + Toast.makeText(view.getContext(), "Please choose a category first", Toast.LENGTH_SHORT).show(); return; } @@ -186,65 +181,62 @@ public class UploadActivity extends BaseActivity { } //Fixes course and semester - maybeCourse = maybeCourse.replaceAll("-", "").replace("(ΝΠΣ)", "").trim(); - maybeSemester = maybeSemester.replaceAll("-", "").trim().substring(0, 1); + String course = maybeCourse.replaceAll("-", "").replace("(ΝΠΣ)", "").trim(); + String semester = maybeSemester.replaceAll("-", "").trim().substring(0, 1); Intent intent = new Intent(UploadActivity.this, UploadFieldsBuilderActivity.class); Bundle builderExtras = new Bundle(); - builderExtras.putString(BUNDLE_UPLOAD_FIELD_BUILDER_COURSE, maybeCourse); - builderExtras.putString(BUNDLE_UPLOAD_FIELD_BUILDER_SEMESTER, maybeSemester); + builderExtras.putString(BUNDLE_UPLOAD_FIELD_BUILDER_COURSE, course); + builderExtras.putString(BUNDLE_UPLOAD_FIELD_BUILDER_SEMESTER, semester); intent.putExtras(builderExtras); - startActivityForResult(intent, REQUEST_CODE_FIELDS_BUILDER); + startActivityForResult(intent, AFR_REQUEST_CODE_FIELDS_BUILDER); }); titleDescriptionBuilderButton.setEnabled(false); uploadTitle = findViewById(R.id.upload_title); uploadDescription = findViewById(R.id.upload_description); - selectFileButton = findViewById(R.id.upload_select_file_button); + filenameHolder = findViewById(R.id.upload_filename); + Drawable filenameDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_attach_file_white_24dp); + filenameHolder.setCompoundDrawablesRelativeWithIntrinsicBounds(filenameDrawable, null, null, null); + + AppCompatButton selectFileButton = findViewById(R.id.upload_select_file_button); Drawable selectStartDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_insert_drive_file_white_24dp); selectFileButton.setCompoundDrawablesRelativeWithIntrinsicBounds(selectStartDrawable, null, null, null); selectFileButton.setOnClickListener(v -> { - final CharSequence[] options = {"Take photo", "Choose file", - "Cancel"}; - AlertDialog.Builder builder = new AlertDialog.Builder(UploadActivity.this); - builder.setTitle("Upload file"); - builder.setItems(options, (dialog, item) -> { - if (options[item].equals("Take photo")) { - /*Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - startActivityForResult(intent, REQUEST_CODE_CAMERA);*/ - - Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - takePhotoIntent.putExtra("return-data", true); - takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(UploadsHelper.getTempFile(this))); - - Intent targetedIntent = new Intent(takePhotoIntent); - List resInfo = this.getPackageManager().queryIntentActivities(takePhotoIntent, 0); - for (ResolveInfo resolveInfo : resInfo) { - String packageName = resolveInfo.activityInfo.packageName; - targetedIntent.setPackage(packageName); - } - startActivityForResult(takePhotoIntent, REQUEST_CODE_CAMERA); + String[] mimeTypes = {"image/jpeg", "text/html", "image/png", "image/jpg", "image/gif", + "application/pdf", "application/rar", "application/x-tar", "application/zip", + "application/msword", "image/vnd.djvu", "application/gz", "application/tar.gz"}; - } else if (options[item].equals("Choose file")) { - String[] mimeTypes = {"image/jpeg", "text/html", "image/png", "image/jpg", "image/gif", - "application/pdf", "application/rar", "application/x-tar", "application/zip", - "application/msword", "image/vnd.djvu", "application/gz", "application/tar.gz"}; + Intent intent = new Intent(Intent.ACTION_GET_CONTENT) + //.setType("*/*") + .setType("image/jpeg") + .putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes); - Intent intent = new Intent(Intent.ACTION_GET_CONTENT) - //.setType("*/*") - .setType("image/jpeg") - .putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes); + startActivityForResult(intent, AFR_REQUEST_CODE_CHOOSE_FILE); + }); - startActivityForResult(intent, REQUEST_CODE_CHOOSE_FILE); - } else if (options[item].equals("Cancel")) { - dialog.dismiss(); - } - }); - builder.show(); + AppCompatButton takePhotoButton = findViewById(R.id.upload_take_photo_button); + Drawable takePhotoDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_photo_camera_white_24dp); + takePhotoButton.setCompoundDrawablesRelativeWithIntrinsicBounds(takePhotoDrawable, null, null, null); + takePhotoButton.setOnClickListener(v -> { + Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + takePhotoIntent.putExtra("return-data", true); + takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(UploadsHelper.getCacheFile(this))); + + Intent targetedIntent = new Intent(takePhotoIntent); + List resInfo = this.getPackageManager().queryIntentActivities(takePhotoIntent, 0); + for (ResolveInfo resolveInfo : resInfo) { + String packageName = resolveInfo.activityInfo.packageName; + targetedIntent.setPackage(packageName); + } + startActivityForResult(takePhotoIntent, AFR_REQUEST_CODE_CAMERA); }); - findViewById(R.id.upload_upload_button).setOnClickListener(view -> { + FloatingActionButton uploadFAB = findViewById(R.id.upload_fab); + uploadFAB.setOnClickListener(view -> { + progressBar.setVisibility(View.VISIBLE); + String uploadTitleText = uploadTitle.getText().toString(); String uploadDescriptionText = uploadDescription.getText().toString(); @@ -252,39 +244,40 @@ public class UploadActivity extends BaseActivity { uploadTitle.setError("Required"); } if (fileUri == null) { - selectFileButton.setError("Required"); + Toast.makeText(view.getContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show(); } if (categorySelected.equals("-1")) { Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show(); } if (categorySelected.equals("-1") || uploadTitleText.equals("") || fileUri == null) { + progressBar.setVisibility(View.GONE); return; } - String tmpDescriptionText = uploadDescriptionText; - SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(view.getContext()); if (sharedPrefs.getBoolean(UPLOADING_APP_SIGNATURE_ENABLE_KEY, true)) { - tmpDescriptionText += uploadedFrommThmmyPromptHtml; + uploadDescriptionText += uploadedFromThmmyPromptHtml; } String tempFilePath = null; if (uploadFilename != null) { + //File should be uploaded with a certain name. Temporarily copies the file and renames it tempFilePath = UploadsHelper.createTempFile(this, fileUri, uploadFilename); if (tempFilePath == null) { //Something went wrong, abort + Toast.makeText(this, "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show(); + progressBar.setVisibility(View.GONE); return; } } try { - final String finalTempFilePath = tempFilePath; new MultipartUploadRequest(view.getContext(), uploadIndexUrl) .setUtf8Charset() .addParameter("tp-dluploadtitle", uploadTitleText) .addParameter("tp-dluploadcat", categorySelected) - .addParameter("tp-dluploadtext", tmpDescriptionText) + .addParameter("tp-dluploadtext", uploadDescriptionText) .addFileToUpload(tempFilePath == null ? fileUri.toString() : tempFilePath @@ -302,68 +295,46 @@ public class UploadActivity extends BaseActivity { public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse, Exception exception) { Toast.makeText(context, "Upload failed", Toast.LENGTH_SHORT).show(); - if (finalTempFilePath != null) { - if (!UploadsHelper.deleteTempFile(finalTempFilePath)) { - Toast.makeText(context, "Failed to delete temporary file", Toast.LENGTH_SHORT).show(); - } - } + UploadsHelper.deleteTempFiles(); + progressBar.setVisibility(View.GONE); } @Override public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) { - if (finalTempFilePath != null) { - if (!UploadsHelper.deleteTempFile(finalTempFilePath)) { - Toast.makeText(context, "Failed to delete temporary file", Toast.LENGTH_SHORT).show(); - } - } + Toast.makeText(context, "Upload completed successfully", Toast.LENGTH_SHORT).show(); + UploadsHelper.deleteTempFiles(); + BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null); + + uploadTitle.setText(null); + uploadDescription.setText(null); + fileUri = null; + filenameHolder.setText(null); + filenameHolder.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); } @Override public void onCancelled(Context context, UploadInfo uploadInfo) { - if (finalTempFilePath != null) { - if (!UploadsHelper.deleteTempFile(finalTempFilePath)) { - Toast.makeText(context, "Failed to delete temporary file", Toast.LENGTH_SHORT).show(); - } - } + Toast.makeText(context, "Upload canceled", Toast.LENGTH_SHORT).show(); + + UploadsHelper.deleteTempFiles(); + progressBar.setVisibility(View.GONE); } }) .startUpload(); } catch (Exception exception) { Timber.e(exception, "AndroidUploadService: %s", exception.getMessage()); + progressBar.setVisibility(View.GONE); } }); if (uploadRootCategories.isEmpty()) { + //Parses the uploads page parseUploadPageTask = new ParseUploadPageTask(); parseUploadPageTask.execute(uploadIndexUrl); } else { - String[] tmpSpinnerArray = new String[uploadRootCategories.size()]; - for (int i = 0; i < uploadRootCategories.size(); ++i) { - tmpSpinnerArray[i] = uploadRootCategories.get(i).getCategoryTitle(); - } - - ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(BaseApplication.getInstance().getApplicationContext(), - android.R.layout.simple_spinner_dropdown_item, tmpSpinnerArray); - spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - rootCategorySpinner.setAdapter(spinnerArrayAdapter); - - //Sets bundle selection - if (bundleCategory != null) { - int bundleSelectionIndex = -1, currentIndex = 0; - for (UploadCategory category : uploadRootCategories) { - if (bundleCategory.get(0).contains(category.getCategoryTitle())) { - bundleSelectionIndex = currentIndex; - break; - } - ++currentIndex; - } - - if (bundleSelectionIndex != -1) { - rootCategorySpinner.setSelection(bundleSelectionIndex, true); - bundleCategory.remove(0); - } - } - + //Renders the already parsed data + updateUIElements(); titleDescriptionBuilderButton.setEnabled(true); } } @@ -392,15 +363,16 @@ public class UploadActivity extends BaseActivity { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_CODE_CHOOSE_FILE && data != null) { - if (resultCode == Activity.RESULT_CANCELED) { + if (requestCode == AFR_REQUEST_CODE_CHOOSE_FILE) { + if (resultCode == Activity.RESULT_CANCELED || data == null) { return; } fileUri = data.getData(); if (fileUri != null) { String filename = UploadsHelper.filenameFromUri(this, fileUri); - selectFileButton.setText(filename); + filenameHolder.setText(filename); + filenameHolder.setVisibility(View.VISIBLE); filename = filename.toLowerCase(); if (filename.endsWith(".jpg")) { @@ -422,38 +394,40 @@ public class UploadActivity extends BaseActivity { fileIcon = "blank.gif"; } } - } else if (requestCode == REQUEST_CODE_CAMERA) { + } else if (requestCode == AFR_REQUEST_CODE_CAMERA) { if (resultCode == Activity.RESULT_CANCELED) { return; } Bitmap bitmap; - File cacheImageFile = UploadsHelper.getTempFile(this); - if (resultCode == Activity.RESULT_OK) { - fileUri = Uri.fromFile(cacheImageFile); - fileIcon = "jpg_image.gif"; - - bitmap = UploadsHelper.getImageResized(this, fileUri); - int rotation = UploadsHelper.getRotation(this, fileUri); - bitmap = UploadsHelper.rotate(bitmap, rotation); - - try { - FileOutputStream out = new FileOutputStream(cacheImageFile); - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); - out.flush(); - out.close(); - } catch (Exception e) { - e.printStackTrace(); - } + File cacheImageFile = UploadsHelper.getCacheFile(this); - String newFilename = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.FRANCE). - format(new Date()); - fileUri = Uri.parse(UploadsHelper.createTempFile(this, fileUri, newFilename)); + Uri cacheFileUri = Uri.fromFile(cacheImageFile); + fileIcon = "jpg_image.gif"; - newFilename += ".jpg"; - selectFileButton.setText(newFilename); + bitmap = UploadsHelper.getImageResized(this, cacheFileUri); + int rotation = UploadsHelper.getRotation(this, cacheFileUri); + bitmap = UploadsHelper.rotate(bitmap, rotation); + + try { + FileOutputStream out = new FileOutputStream(cacheImageFile); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); + out.flush(); + out.close(); + } catch (Exception e) { + e.printStackTrace(); } - } else if (requestCode == REQUEST_CODE_FIELDS_BUILDER) { + + String newFilename = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.FRANCE). + format(new Date()); + fileUri = Uri.parse(UploadsHelper.createTempFile(this, cacheFileUri, newFilename)); + + newFilename += ".jpg"; + filenameHolder.setText(newFilename); + filenameHolder.setVisibility(View.VISIBLE); + + UploadsHelper.deleteCacheFiles(this); + } else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) { if (resultCode == Activity.RESULT_CANCELED) { return; } @@ -499,8 +473,8 @@ public class UploadActivity extends BaseActivity { } ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(getApplicationContext(), - android.R.layout.simple_spinner_dropdown_item, tmpSpinnerArray); - spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_item, tmpSpinnerArray); + spinnerArrayAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item); AppCompatSpinnerWithoutDefault subSpinner = new AppCompatSpinnerWithoutDefault(categoriesSpinners.getContext()); subSpinner.setPromptId(R.string.upload_spinners_hint); @@ -578,7 +552,7 @@ public class UploadActivity extends BaseActivity { UploadCategory secondLevelCategory = firstLevelCategory.getSubCategories().get(firstLevelCategory.getSubCategories().size() - 1); secondLevelCategory.addSubCategory(categoryValue, categoryText); } else if (categoryText.startsWith("---- ")) { - //This is a level three subcategory + //This is a level four subcategory UploadCategory rootLevelCategory = uploadRootCategories.get(uploadRootCategories.size() - 1); UploadCategory firstLevelCategory = rootLevelCategory.getSubCategories().get(rootLevelCategory.getSubCategories().size() - 1); UploadCategory secondLevelCategory = firstLevelCategory.getSubCategories().get(firstLevelCategory.getSubCategories().size() - 1); @@ -593,36 +567,39 @@ public class UploadActivity extends BaseActivity { @Override protected void postExecution(ResultCode result) { - String[] tmpSpinnerArray = new String[uploadRootCategories.size()]; - for (int i = 0; i < uploadRootCategories.size(); ++i) { - tmpSpinnerArray[i] = uploadRootCategories.get(i).getCategoryTitle(); - } + updateUIElements(); + titleDescriptionBuilderButton.setEnabled(true); + progressBar.setVisibility(ProgressBar.GONE); + } + } + + private void updateUIElements() { + String[] tmpSpinnerArray = new String[uploadRootCategories.size()]; + for (int i = 0; i < uploadRootCategories.size(); ++i) { + tmpSpinnerArray[i] = uploadRootCategories.get(i).getCategoryTitle(); + } ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(BaseApplication.getInstance().getApplicationContext(), - android.R.layout.simple_spinner_dropdown_item, tmpSpinnerArray); - spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_item, tmpSpinnerArray); + spinnerArrayAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item); rootCategorySpinner.setAdapter(spinnerArrayAdapter); - //Sets bundle selection - if (bundleCategory != null) { - int bundleSelectionIndex = -1, currentIndex = 0; + //Sets bundle selection + if (bundleCategory != null) { + int bundleSelectionIndex = -1, currentIndex = 0; - for (UploadCategory category : uploadRootCategories) { - if (bundleCategory.get(0).contains(category.getCategoryTitle())) { - bundleSelectionIndex = currentIndex; - break; - } - ++currentIndex; - } - - if (bundleSelectionIndex != -1) { - rootCategorySpinner.setSelection(bundleSelectionIndex, true); - bundleCategory.remove(0); + for (UploadCategory category : uploadRootCategories) { + if (bundleCategory.get(0).contains(category.getCategoryTitle())) { + bundleSelectionIndex = currentIndex; + break; } + ++currentIndex; } - titleDescriptionBuilderButton.setEnabled(true); - progressBar.setVisibility(ProgressBar.GONE); + if (bundleSelectionIndex != -1) { + rootCategorySpinner.setSelection(bundleSelectionIndex, true); + bundleCategory.remove(0); + } } } } \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java index 0cd8eb70..c5ab4829 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java @@ -87,7 +87,7 @@ public class UploadFieldsBuilderActivity extends AppCompatActivity { //Initialize toolbar Toolbar toolbar = findViewById(R.id.toolbar); - toolbar.setTitle("Upload fields builder"); + toolbar.setTitle(R.string.upload_fields_builder_toolbar_title); setSupportActionBar(toolbar); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -215,263 +215,300 @@ public class UploadFieldsBuilderActivity extends AppCompatActivity { @Nullable private String getGreeklishOrMinifiedCourseName(boolean greeklish) { - //TODO fill missing values - if (course.contains("Συστήματα Υπολογιστών (Υπολογιστικά Συστήματα)")) { - return greeklish ? "sys_ypologistwn" : "Συσ. Υπολογιστών"; - } else if (course.contains("Τεχνική Μηχανική")) { - return greeklish ? "texn_mhxan" : "Τεχν. Μηχαν."; - } else if (course.contains("Διαφορικές Εξισώσεις")) { - return greeklish ? "diaforikes" : "Διαφορικές"; - } else if (course.contains("Θεωρία Πιθανοτήτων και Στατιστική")) { - return greeklish ? "pithanothtes" : "Πιθανότητες"; - } else if (course.contains("Εφαρμοσμένα Μαθηματικά Ι")) { - return greeklish ? "efarmosmena_math_I" : "Εφαρμοσμένα 1"; - } else if (course.contains("Ηλεκτρικά Κυκλώματα ΙΙ")) { - return greeklish ? "kyklwmata_II" : "Κυκλώματα 2"; - } else if (course.contains("Ηλεκτρολογικά Υλικά")) { - return greeklish ? "ylika" : "Ηλεκτρ. Υλικά"; - } else if (course.contains("Ηλεκτρομαγνητικό Πεδίο Ι")) { - return greeklish ? "pedio_I" : "Πεδίο 1"; - } else if (course.contains("Θεωρία Σημάτων και Γραμμικών Συστημάτων")) { - return greeklish ? "analog_shma" : "Σύματα & Συστήματα"; - } else if (course.contains("Προγραμματιστικές Τεχνικές")) { - return greeklish ? "cpp" : "Προγραμματ. Τεχν."; - } else if (course.contains("Αριθμητική Ανάλυση")) { - return greeklish ? "arith_anal" : "Αριθμ. Ανάλυση"; - } else if (course.contains("Αρχιτεκτονική Υπολογιστών")) { - return greeklish ? "arx_ypologistwn" : "Αρχ. Υπολογιστών"; - } else if (course.contains("Εισαγωγή στην Ενεργειακή Τεχνολογία Ι")) { - return greeklish ? "EET_I" : "ΕΕΤ 1"; - } else if (course.contains("Ηλεκτρικά Κυκλώματα ΙΙΙ")) { - return greeklish ? "kyklwmata_I" : "Κυκλώματα 3"; - } else if (course.contains("Ηλεκτρομαγνητικό Πεδίο ΙΙ")) { - return greeklish ? "pedio_II" : "Πεδίο 2"; - } else if (course.contains("Στοχαστικό Σήμα")) { - return greeklish ? "stox_shma" : "Στοχ. Σήμα"; + if (course.contains("Ψηφιακή Επεξεργασία Σήματος")) { + return greeklish ? "PSES" : "ΨΕΣ"; + } else if (course.contains("Ψηφιακή Επεξεργασία Εικόνας")) { + return greeklish ? "psee" : "ΨΕΕ"; + } else if (course.contains("Ψηφιακές Τηλεπικοινωνίες ΙΙ")) { + return greeklish ? "pshf_thlep_II" : "Ψηφιακές Τηλεπ. 2"; + } else if (course.contains("Ψηφιακές Τηλεπικοινωνίες Ι")) { + return greeklish ? "pshf_thlep_I" : "Ψηφιακές Τηλεπ. 1"; + } else if (course.contains("Ψηφιακά Φίλτρα")) { + return greeklish ? "filtra" : "Φίλτρα"; + } else if (course.contains("Ψηφιακά Συστήματα ΙΙΙ")) { + return greeklish ? "pshfiaka_III" : "Ψηφιακά 3"; + } else if (course.contains("Ψηφιακά Συστήματα ΙΙ")) { + return greeklish ? "pshfiaka_II" : "Ψηφιακά 2"; } else if (course.contains("Ψηφιακά Συστήματα Ι")) { return greeklish ? "pshfiaka_I" : "Ψηφιακά 1"; - } else if (course.contains("Αναλογικές Τηλεπικοινωνίες (πρώην Τηλεπικοινωνιακά Συστήματα Ι)")) { - return greeklish ? "anal_thlep" : "Αναλογικές Τηλεπ."; - } else if (course.contains("Διάδοση Ηλεκτρομαγνητικού Κύματος Ι (πρώην Πεδίο ΙΙΙ)")) { - return greeklish ? "diadosi_1" : "Διάδοση 1"; - } else if (course.contains("Δομές Δεδομένων")) { - return greeklish ? "dom_dedomenwn" : "Δομ. Δεδομ."; - } else if (course.contains("Εισαγωγή στην Ενεργειακή Τεχνολογία ΙΙ")) { - return greeklish ? "EET_2" : "ΕΕΤ2"; - } else if (course.contains("Ηλεκτρικές Μετρήσεις Ι")) { - return greeklish ? "metrhseis_1" : "Μετρήσεις 1"; - } else if (course.contains("Ηλεκτρονική ΙΙ")) { - return greeklish ? "hlektronikh_2" : "Ηλεκτρονική 2"; - } else if (course.contains("Συστήματα Αυτομάτου Ελέγχου Ι")) { - return greeklish ? "SAE_1" : "ΣΑΕ 1"; - } else if (course.contains("Γραμμική Άλγεβρα")) { - return greeklish ? "grammikh_algebra" : "Γραμμ. Άλγεβρ."; - } else if (course.contains("Δομημένος Προγραμματισμός")) { - return greeklish ? "C" : "Δομ. Προγραμμ."; - } else if (course.contains("Λογική Σχεδίαση")) { - return greeklish ? "logiki_sxediash" : "Λογική Σχεδίαση"; - } else if (course.contains("Λογισμός Ι")) { - return greeklish ? "logismos_I" : "Λογισμός 1"; - } else if (course.contains("Τεχνικές Σχεδίασης με Η/Υ")) { - return greeklish ? "sxedio" : "Σχέδιο"; + } else if (course.contains("Φωτονική Τεχνολογία")) { + return greeklish ? "fwtonikh" : "Φωτονική"; } else if (course.contains("Φυσική Ι")) { return greeklish ? "fysikh_I" : "Φυσική 1"; - } else if (course.contains("Αντικειμενοστραφής Προγραμματισμός")) { - return greeklish ? "OOP" : "Αντικειμενοστραφής"; - } else if (course.contains("Εφαρμοσμένη Θερμοδυναμική")) { - return greeklish ? "thermodynamikh" : "Θερμοδυναμική"; - } else if (course.contains("Ηλεκτρικά Κυκλώματα Ι")) { - return greeklish ? "kyklwmata_I" : "Κυκλώματα 1"; - } else if (course.contains("Λογισμός ΙΙ")) { - return greeklish ? "logismos_II" : "Λογισμός 2"; - } else if (course.contains("Οργάνωση Υπολογιστών")) { - return greeklish ? "org_ypol" : "Οργάνωση Υπολ."; - } else if (course.contains("Ηλεκτρονική Ι")) { - return greeklish ? "hlektronikh_1" : "Ηλεκτρονική 1"; - } else if (course.contains("Διακριτά μαθηματικά")) { - return greeklish ? "diakrita" : "Διακριτά Μαθηματικά"; - } else if (course.contains("Σήματα και Συστήματα")) { - return greeklish ? "analog_shma" : "Σύματα & Συστήματα"; - } else if (course.contains("Εισαγωγή στις εφαρμογές Πυρηνικής Τεχνολογίας")) { - return greeklish ? "Intro_Purhnikh_Texn" : "Εισ. Πυρηνικη Τεχν."; - } else if (course.contains("Επιχειρησιακή Έρευνα")) { - return greeklish ? "epixeirisiaki" : "Επιχειρησιακή Έρευνα"; - } else if (course.contains("Ημιαγωγά Υλικά: Θεωρία-Διατάξεις")) { - return greeklish ? "Hmiagwga_Ylika" : "Ημιαγωγά Υλικά"; - } else if (course.contains("Μετάδοση Θερμότητας")) { - return greeklish ? "metadosi_therm" : "Μετάδοση Θερμ."; - } else if (course.contains("Συστήματα Ηλεκτρικής Ενέργειας Ι")) { - return greeklish ? "SHE_I" : "ΣΗΕ 1"; + } else if (course.contains("Υψηλές Τάσεις ΙΙΙ")) { + return greeklish ? "ypshles_III" : "Υψηλές 3"; + } else if (course.contains("Υψηλές Τάσεις ΙΙ")) { + return greeklish ? "ypshles_II" : "Υψηλές 2"; } else if (course.contains("Υψηλές Τάσεις Ι")) { return greeklish ? "ypshles_I" : "Υψηλές 1"; - } else if (course.contains("Θεωρία και Τεχνολογία Πυρηνικών Αντιδραστήρων")) { - return greeklish ? "texn_antidrasthrwn" : "Τεχνολογία Αντιδραστήρων"; + } else if (course.contains("Υψηλές Τάσεις 4")) { + return greeklish ? "ypshles_IV" : "Υψηλές 4"; + } else if (course.contains("Υπολογιστικός Ηλεκτρομαγνητισμός")) { + return greeklish ? "ypologistikos_HM" : "Υπολογιστικός Η/Μ"; + } else if (course.contains("Υπολογιστικές Μέθοδοι στα Ενεργειακά Συστήματα")) { + return greeklish ? "ymes" : "ΥΜΕΣ"; + } else if (course.contains("Τηλεπικοινωνιακή Ηλεκτρονική")) { + return greeklish ? "tilep_ilektr" : "Τηλεπ. Ηλεκτρ."; + } else if (course.contains("Τηλεοπτικά Συστήματα")) { + return greeklish ? "tileoptika" : "Τηλεοπτικά"; + } else if (course.contains("Τεχνολογία Λογισμικού")) { + return greeklish ? "SE" : "Τεχνολογία Λογισμικού"; } else if (course.contains("Τεχνολογία Ηλεκτροτεχνικών Υλικών")) { return greeklish ? "Hlektrotexnika_Ylika" : "Ηλεκτροτεχνικά Υλικά"; - } else if (course.contains("Ηλεκτρικές Μηχανές Α'")) { - return greeklish ? "mhxanes_A" : "Μηχανές Α"; - } else if (course.contains("Σταθμοί Παραγωγής Ηλεκτρικής Ενέργειας")) { - return greeklish ? "SPHE" : "ΣΠΗΕ"; - } else if (course.contains("Συστήματα Ηλεκτρικής Ενέργειας ΙΙ")) { - return greeklish ? "SHE_II" : "ΣΗΕ 2"; - } else if (course.contains("Υψηλές Τάσεις ΙΙ")) { - return greeklish ? "ypshles_II" : "Υψηλές 2"; - } else if (course.contains("Αρχές Οικονομίας")) { - return greeklish ? "arx_oikonomias" : "Αρχές Οικονομίας"; - } else if (course.contains("Διανεμημένη Παραγωγή")) { - return greeklish ? "dian_paragwgh" : "Διανεμημένη Παραγωγή"; - } else if (course.contains("Διαχείριση Συστημάτων Ηλεκτρικής Ενέργειας")) { - return greeklish ? "dshe" : "ΔΣΗΕ"; - } else if (course.contains("Υψηλές Τάσεις ΙΙΙ")) { - return greeklish ? "ypshles_III" : "Υψηλές 3"; - } else if (course.contains("Ανάλυση Συστημάτων Ηλεκτρικής Ενέργειας")) { - return greeklish ? "ASHE" : "ΑΣΗΕ"; - } else if (course.contains("Ηλεκτρικές Μηχανές Β'")) { - return greeklish ? "mhxanes_B" : "Μηχανές Β"; - } else if (course.contains("Ηλεκτρονικά Ισχύος Ι")) { - return greeklish ? "isxyos_I" : "Ισχύος 1"; + } else if (course.contains("Τεχνολογία Ήχου και Εικόνας")) { + return greeklish ? "texn_hxoy_eikonas" : "Τεχνολογία Ήχου και Εικόνας"; + } else if (course.contains("Τεχνική Μηχανική")) { + return greeklish ? "texn_mhxan" : "Τεχν. Μηχαν."; + } else if (course.contains("Τεχνικές μη Καταστρεπτικών Δοκιμών")) { + return greeklish ? "non_destructive_tests" : "Μη Καταστρεπτικές Δοκιμές"; + } else if (course.contains("Τεχνικές Σχεδίασης με Η/Υ")) { + return greeklish ? "sxedio" : "Σχέδιο"; + } else if (course.contains("Τεχνικές Κωδικοποίησης")) { + return greeklish ? "texn_kwdikopoihshs" : "Τεχνικές Κωδικοποίησης"; + } else if (course.contains("Τεχνικές Βελτιστοποίησης")) { + return greeklish ? "veltistopoihsh" : "Βελτιστοποίηση"; + } else if (course.contains("Σύνθεση Τηλεπικοινωνιακών Διατάξεων")) { + return greeklish ? "synth_thlep_diataksewn" : "Σύνθεση Τηλεπ. Διατάξεων"; + } else if (course.contains("Σύνθεση Ενεργών και Παθητικών Κυκλωμάτων")) { + return greeklish ? "synthesh" : "Σύνθεση"; + } else if (course.contains("Σχεδίαση Συστημάτων VLSI")) { + return greeklish ? "VLSI" : "VLSI"; + } else if (course.contains("Συστήματα Υπολογιστών (Υπολογιστικά Συστήματα)")) { + return greeklish ? "sys_ypologistwn" : "Συσ. Υπολογιστών"; + } else if (course.contains("Συστήματα Πολυμέσων και Εικονική Πραγματικότητα")) { + return greeklish ? "polymesa" : "Πολυμέσα"; + } else if (course.contains("Συστήματα Μικροϋπολογιστών")) { + return greeklish ? "mikro_I" : "Μίκρο 1"; + } else if (course.contains("Συστήματα Ηλεκτροκίνησης")) { + return greeklish ? "hlektrokinhsh" : "Ηλεκτροκίνηση"; } else if (course.contains("Συστήματα Ηλεκτρικής Ενέργειας ΙΙΙ")) { return greeklish ? "SHE_III" : "ΣΗΕ 3"; + } else if (course.contains("Συστήματα Ηλεκτρικής Ενέργειας ΙΙ")) { + return greeklish ? "SHE_II" : "ΣΗΕ 2"; + } else if (course.contains("Συστήματα Ηλεκτρικής Ενέργειας Ι")) { + return greeklish ? "SHE_I" : "ΣΗΕ 1"; + } else if (course.contains("Συστήματα Αυτομάτου Ελέγχου ΙΙI")) { + return greeklish ? "SAE_III" : "ΣΑΕ 3"; + } else if (course.contains("Συστήματα Αυτομάτου Ελέγχου ΙΙ")) { + return greeklish ? "SAE_II" : "ΣΑΕ 2"; + } else if (course.contains("Συστήματα Αυτομάτου Ελέγχου Ι")) { + return greeklish ? "SAE_1" : "ΣΑΕ 1"; + } else if (course.contains("Στοχαστικό Σήμα")) { + return greeklish ? "stox_shma" : "Στοχ. Σήμα"; + } else if (course.contains("Σταθμοί Παραγωγής Ηλεκτρικής Ενέργειας")) { + return greeklish ? "SPHE" : "ΣΠΗΕ"; } else if (course.contains("Σερβοκινητήρια Συστήματα")) { return greeklish ? "servo" : "Σέρβο"; - } else if (course.contains("Συστήματα Ηλεκτροκίνησης")) { - return greeklish ? "hlektrokinhsh" : "Ηλεκτροκίνηση"; - } else if (course.contains("Υπολογιστικές Μέθοδοι στα Ενεργειακά Συστήματα")) { - return greeklish ? "ymes" : "ΥΜΕΣ"; - } else if (course.contains("Υψηλές Τάσεις 4")) { - return greeklish ? "ypshles_IV" : "Υψηλές 4"; - } else if (course.contains("Ηλεκτρικές Μηχανές Γ'")) { - return greeklish ? "mhxanes_C" : "Μηχανές Γ"; - } else if (course.contains("Ηλεκτρική Οικονομία")) { - return greeklish ? "hlektr_oikonomia" : "Ηλεκτρική Οικονομία"; - } else if (course.contains("Ηλεκτρονικά Ισχύος ΙΙ")) { - return greeklish ? "isxyos_II" : "Ισχύος 2"; - } else if (course.contains("Ανάλυση και Σχεδίαση Αλγορίθμων")) { - return greeklish ? "algorithms" : "Αλγόριθμοι"; - } else if (course.contains("Διακριτά Μαθηματικά")) { - return greeklish ? "diakrita" : "Διακριτά Μαθηματικά"; - } else if (course.contains("Κβαντική Φυσική")) { - return greeklish ? "kvantikh" : "Κβαντική"; + } else if (course.contains("Σήματα και Συστήματα")) { + return greeklish ? "analog_shma" : "Σύματα & Συστήματα"; } else if (course.contains("Ρομποτική")) { return greeklish ? "rompotikh" : "Ρομποτική"; - } else if (course.contains("Τεχνικές Βελτιστοποίησης")) { - return greeklish ? "veltistopoihsh" : "Βελτιστοποίηση"; - } else if (course.contains("Ηλεκτρικές Μετρήσεις ΙΙ")) { - return greeklish ? "metrhseis_II" : "Μετρήσεις 2"; - } else if (course.contains("Ηλεκτρονική ΙΙΙ")) { - return greeklish ? "hlektronikh_III" : "Ηλεκτρονική 3"; - } else if (course.contains("Συστήματα Αυτομάτου Ελέγχου ΙΙ")) { - return greeklish ? "SAE_II" : "ΣΑΕ 2"; - } else if (course.contains("Ψηφιακά Συστήματα ΙΙ")) { - return greeklish ? "pshfiaka_II" : "Ψηφιακά 2"; - } else if (course.contains("Ανάλυση Χρονοσειρών")) { - return greeklish ? "xronoseires" : "Χρονοσειρές"; - } else if (course.contains("Θεωρία Υπολογισμών και Αλγορίθμων")) { - return greeklish ? "thya" : "ΘΥΑ"; - } else if (course.contains("Παράλληλα και Κατανεμημένα Συστήματα")) { - return greeklish ? "parallhla" : "Παράλληλα"; - } else if (course.contains("Προγραμματιζόμενα Κυκλώματα ASIC")) { - return greeklish ? "asic" : "ASIC"; } else if (course.contains("Προσομοίωση και Μοντελοποίηση Συστημάτων")) { return greeklish ? "montelopoihsh" : "Μοντελοποίηση"; - } else if (course.contains("Συστήματα Αυτομάτου Ελέγχου ΙΙI")) { - return greeklish ? "SAE_III" : "ΣΑΕ 3"; - } else if (course.contains("Σύνθεση Ενεργών και Παθητικών Κυκλωμάτων")) { - return greeklish ? "synthesh" : "Σύνθεση"; - } else if (course.contains("Δίκτυα Υπολογιστών Ι")) { - return greeklish ? "diktya_I" : "Δίκτυα 1"; - } else if (course.contains("Λειτουργικά Συστήματα")) { - return greeklish ? "OS" : "Λειτουργικά"; - } else if (course.contains("Συστήματα Μικροϋπολογιστών")) { - return greeklish ? "mikro_I" : "Μίκρο 1"; - } else if (course.contains("Ασαφή Συστήματα")) { - return greeklish ? "asafh" : "Ασαφή"; - } else if (course.contains("Γραφική με Υπολογιστές")) { - return greeklish ? "grafikh" : "Γραφική"; - } else if (course.contains("Ενσωματωμένα Συστήματα Πραγματικού Χρόνου")) { - return greeklish ? "enswmatwmena" : "Ενσωματωμένα"; - } else if (course.contains("Τηλεπικοινωνιακή Ηλεκτρονική")) { - return greeklish ? "tilep_ilektr" : "Τηλεπ. Ηλεκτρ."; - } else if (course.contains("Ψηφιακά Συστήματα ΙΙΙ")) { - return greeklish ? "pshfiaka_III" : "Ψηφιακά 3"; - } else if (course.contains("Ψηφιακή Επεξεργασία Εικόνας")) { - return greeklish ? "psee" : "ΨΕΕ"; - } else if (course.contains("Δίκτυα Υπολογιστών ΙΙ")) { - return greeklish ? "diktya_II" : "Δίκτυα 2"; - } else if (course.contains("Μικροεπεξεργαστές και Περιφερειακά")) { - return greeklish ? "mikro_II" : "Μίκρο 2"; - } else if (course.contains("Τεχνολογία Λογισμικού")) { - return greeklish ? "SE" : "Τεχνολογία Λογισμικού"; - } else if (course.contains("Ψηφιακά Φίλτρα")) { - return greeklish ? "filtra" : "Φίλτρα"; - } else if (course.contains("Αναγνώριση Προτύπων")) { - return greeklish ? "protipa" : "Αναγνώριση Προτύπων"; - } else if (course.contains("Ασφάλεια Πληροφοριακών Συστημάτων")) { - return greeklish ? "asfaleia" : "Ασφάλεια"; - } else if (course.contains("Βάσεις Δεδομένων")) { - return greeklish ? "vaseis" : "Βάσεις"; - } else if (course.contains("Βιομηχανική Πληροφορική")) { - return greeklish ? "viomix_plir" : "Βιομηχανική Πληρ"; - } else if (course.contains("Ευφυή Συστήματα Ρομπότ")) { - return greeklish ? "eufuh" : "Ευφυή"; - } else if (course.contains("Συστήματα Πολυμέσων και Εικονική Πραγματικότητα")) { - return greeklish ? "polymesa" : "Πολυμέσα"; - } else if (course.contains("Σχεδίαση Συστημάτων VLSI")) { - return greeklish ? "VLSI" : "VLSI"; - } else if (course.contains("Ακουστική Ι")) { - return greeklish ? "akoystikh_I" : "Ακουστική 1"; - } else if (course.contains("Εφαρμοσμένα Μαθηματικά ΙΙ")) { - return greeklish ? "efarmosmena_math_II" : "Εφαρμοσμένα 2"; - } else if (course.contains("Ηλεκτρακουστική Ι")) { - return greeklish ? "hlektroakoystikh_I" : "Ηλεκτροακουστική 1"; - } else if (course.contains("Οπτική Ι")) { - return greeklish ? "optikh_I" : "Οπτική 1"; - } else if (course.contains("Διάδοση Η/Μ Κύματος ΙΙ")) { - return greeklish ? "diadosi_II" : "Διάδοση 2"; - } else if (course.contains("Ψηφιακές Τηλεπικοινωνίες Ι")) { - return greeklish ? "pshf_thlep_I" : "Ψηφιακές Τηλεπ. 1"; - } else if (course.contains("Ακουστική ΙΙ")) { - return greeklish ? "akoystikh_II" : "Ακουστική 2"; - } else if (course.contains("Βιοϊατρική Τεχνολογία")) { - return greeklish ? "vioiatriki" : "Βιοιατρική"; - } else if (course.contains("Ηλεκτρακουστική ΙΙ")) { - return greeklish ? "hlektroakoystikh_II" : "Ηλεκτροακουστική 2"; + } else if (course.contains("Προηγμένες Τεχνικές Επεξεργασίας Σήματος")) { + return greeklish ? "ptes" : "ΠΤΕΣ"; + } else if (course.contains("Προγραμματιστικές Τεχνικές")) { + return greeklish ? "cpp" : "Προγραμματ. Τεχν."; + } else if (course.contains("Προγραμματιζόμενα Κυκλώματα ASIC")) { + return greeklish ? "asic" : "ASIC"; + } else if (course.contains("Παράλληλα και Κατανεμημένα Συστήματα")) { + return greeklish ? "parallhla" : "Παράλληλα"; + } else if (course.contains("Οργάνωση και Διοίκηση Εργοστασίων")) { + return greeklish ? "organ_dioik_ergostasiwn" : "Οργάνωση και Διοίκηση Εργοστασίων"; + } else if (course.contains("Οργάνωση Υπολογιστών")) { + return greeklish ? "org_ypol" : "Οργάνωση Υπολ."; } else if (course.contains("Οπτική ΙΙ")) { return greeklish ? "optikh_II" : "Οπτική 2"; - } else if (course.contains("Ασύρματος Τηλεπικοινωνία Ι")) { - return greeklish ? "asyrmatos_I" : "Ασύρματος 1"; + } else if (course.contains("Οπτική Ι")) { + return greeklish ? "optikh_I" : "Οπτική 1"; + } else if (course.contains("Οπτικές Επικοινωνίες")) { + return greeklish ? "optikes_thlep" : "Οπτικές Τηλεπ."; + } else if (course.contains("Μικροκύματα II")) { + return greeklish ? "mikrokymata_II" : "Μικροκύματα 2"; } else if (course.contains("Μικροκύματα I")) { return greeklish ? "mikrokymata_I" : "Μικροκύματα 1"; - } else if (course.contains("Ψηφιακές Τηλεπικοινωνίες ΙΙ")) { - return greeklish ? "pshf_thlep_II" : "Ψηφιακές Τηλεπ. 2"; - } else if (course.contains("Ψηφιακή Επεξεργασία Σήματος")) { - return greeklish ? "PSES" : "ΨΕΣ"; - } else if (course.contains("Εισαγωγή στην Πολιτική Οικονομία")) { - return greeklish ? "polit_oik" : "Πολιτική Οικονομία"; + } else if (course.contains("Μικροκυματική Τηλεπισκόπηση")) { + return greeklish ? "thlepiskophsh" : "Τηλεπισκόπηση"; + } else if (course.contains("Μικροεπεξεργαστές και Περιφερειακά")) { + return greeklish ? "mikro_II" : "Μίκρο 2"; + } else if (course.contains("Μετάδοση Θερμότητας")) { + return greeklish ? "metadosi_therm" : "Μετάδοση Θερμ."; + } else if (course.contains("Λογισμός ΙΙ")) { + return greeklish ? "logismos_II" : "Λογισμός 2"; + } else if (course.contains("Λογισμός Ι")) { + return greeklish ? "logismos_I" : "Λογισμός 1"; + } else if (course.contains("Λογική Σχεδίαση")) { + return greeklish ? "logiki_sxediash" : "Λογική Σχεδίαση"; + } else if (course.contains("Λειτουργικά Συστήματα")) { + return greeklish ? "OS" : "Λειτουργικά"; + } else if (course.contains("Κινητές και Δορυφορικές Επικοινωνίες")) { + return greeklish ? "kinhtes_doryforikes_epik" : "Κινητές & Δορυφορικές Επικοινωνίες"; + } else if (course.contains("Κβαντική Φυσική")) { + return greeklish ? "kvantikh" : "Κβαντική"; + } else if (course.contains("Θεωρία και Τεχνολογία Πυρηνικών Αντιδραστήρων")) { + return greeklish ? "texn_antidrasthrwn" : "Τεχνολογία Αντιδραστήρων"; + } else if (course.contains("Θεωρία Υπολογισμών και Αλγορίθμων")) { + return greeklish ? "thya" : "ΘΥΑ"; } else if (course.contains("Θεωρία Σκέδασης")) { return greeklish ? "skedash" : "Σκέδαση"; - } else if (course.contains("Προηγμένες Τεχνικές Επεξεργασίας Σήματος")) { - return greeklish ? "ptes" : "ΠΤΕΣ"; - } else if (course.contains("Τηλεοπτικά Συστήματα")) { - return greeklish ? "tileoptika" : "Τηλεοπτικά"; - } else if (course.contains("Ασύρματος Τηλεπικοινωνία ΙΙ")) { - return greeklish ? "asyrmatos_II" : "Ασύρματος 2"; - } else if (course.contains("Δίκτυα Τηλεπικοινωνιών")) { - return greeklish ? "diktya_thlep" : "Δίκτυα Τηλέπ."; + } else if (course.contains("Θεωρία Σημάτων και Γραμμικών Συστημάτων")) { + return greeklish ? "analog_shma" : "Σύματα & Συστήματα"; } else if (course.contains("Θεωρία Πληροφοριών")) { return greeklish ? "theoria_plir" : "Θεωρία Πληρ."; - } else if (course.contains("Οπτικές Επικοινωνίες")) { - return greeklish ? "optikes_thlep" : "Οπτικές Τηλεπ."; + } else if (course.contains("Θεωρία Πιθανοτήτων και Στατιστική")) { + return greeklish ? "pithanothtes" : "Πιθανότητες"; + } else if (course.contains("Ημιαγωγά Υλικά: Θεωρία-Διατάξεις")) { + return greeklish ? "Hmiagwga_Ylika" : "Ημιαγωγά Υλικά"; + } else if (course.contains("Ηλεκτρονική ΙΙΙ")) { + return greeklish ? "hlektronikh_III" : "Ηλεκτρονική 3"; + } else if (course.contains("Ηλεκτρονική ΙΙ")) { + return greeklish ? "hlektronikh_2" : "Ηλεκτρονική 2"; + } else if (course.contains("Ηλεκτρονική Ι")) { + return greeklish ? "hlektronikh_1" : "Ηλεκτρονική 1"; + } else if (course.contains("Ηλεκτρονικές Διατάξεις και Μετρήσεις")) { + return greeklish ? "hlektron_diatakseis_metrhseis" : "Ηλεκτρονικές Διατάξεις και Μετρήσεις"; + } else if (course.contains("Ηλεκτρονικά Ισχύος ΙΙ")) { + return greeklish ? "isxyos_II" : "Ισχύος 2"; + } else if (course.contains("Ηλεκτρονικά Ισχύος Ι")) { + return greeklish ? "isxyos_I" : "Ισχύος 1"; + } else if (course.contains("Ηλεκτρομαγνητικό Πεδίο ΙΙ")) { + return greeklish ? "pedio_II" : "Πεδίο 2"; + } else if (course.contains("Ηλεκτρομαγνητικό Πεδίο Ι")) { + return greeklish ? "pedio_I" : "Πεδίο 1"; + } else if (course.contains("Ηλεκτρομαγνητική Συμβατότητα")) { + return greeklish ? "HM_symvatothta" : "H/M Συμβατότητα"; + } else if (course.contains("Ηλεκτρολογικά Υλικά")) { + return greeklish ? "ylika" : "Ηλεκτρ. Υλικά"; + } else if (course.contains("Ηλεκτρική Οικονομία")) { + return greeklish ? "hlektr_oikonomia" : "Ηλεκτρική Οικονομία"; + } else if (course.contains("Ηλεκτρικές Μηχανές Γ'")) { + return greeklish ? "mhxanes_C" : "Μηχανές Γ"; + } else if (course.contains("Ηλεκτρικές Μηχανές Β'")) { + return greeklish ? "mhxanes_B" : "Μηχανές Β"; + } else if (course.contains("Ηλεκτρικές Μηχανές Α'")) { + return greeklish ? "mhxanes_A" : "Μηχανές Α"; + } else if (course.contains("Ηλεκτρικές Μετρήσεις ΙΙ")) { + return greeklish ? "metrhseis_II" : "Μετρήσεις 2"; + } else if (course.contains("Ηλεκτρικές Μετρήσεις Ι")) { + return greeklish ? "metrhseis_1" : "Μετρήσεις 1"; + } else if (course.contains("Ηλεκτρικά Κυκλώματα ΙΙΙ")) { + return greeklish ? "kyklwmata_I" : "Κυκλώματα 3"; + } else if (course.contains("Ηλεκτρικά Κυκλώματα ΙΙ")) { + return greeklish ? "kyklwmata_II" : "Κυκλώματα 2"; + } else if (course.contains("Ηλεκτρικά Κυκλώματα Ι")) { + return greeklish ? "kyklwmata_I" : "Κυκλώματα 1"; + } else if (course.contains("Ηλεκτρακουστική ΙΙ")) { + return greeklish ? "hlektroakoystikh_II" : "Ηλεκτροακουστική 2"; + } else if (course.contains("Ηλεκτρακουστική Ι")) { + return greeklish ? "hlektroakoystikh_I" : "Ηλεκτροακουστική 1"; + } else if (course.contains("Εφαρμοσμένη Θερμοδυναμική")) { + return greeklish ? "thermodynamikh" : "Θερμοδυναμική"; + } else if (course.contains("Εφαρμοσμένα Μαθηματικά ΙΙ")) { + return greeklish ? "efarmosmena_math_II" : "Εφαρμοσμένα 2"; + } else if (course.contains("Εφαρμοσμένα Μαθηματικά Ι")) { + return greeklish ? "efarmosmena_math_I" : "Εφαρμοσμένα 1"; + } else if (course.contains("Εφαρμογές Τηλεπικοινωνιακών Διατάξεων")) { + return greeklish ? "efarm_thlep_diataksewn" : "Εφαρμογές Τηλεπ. Διατάξεων"; + } else if (course.contains("Ευφυή Συστήματα Ρομπότ")) { + return greeklish ? "eufuh" : "Ευφυή"; } else if (course.contains("Ευρυζωνικά Δίκτυα")) { return greeklish ? "eyryzwnika" : "Ευρυζωνικά"; - } else if (course.contains("Τεχνικές μη Καταστρεπτικών Δοκιμών")) { - return greeklish ? "non_destructive_tests" : "Μη Καταστρεπτικές Δοκιμές"; - } else if (course.contains("Φωτονική Τεχνολογία")) { - return greeklish ? "fwtonikh" : "Φωτονική"; - } else if (course.contains("Μικροκυματική Τηλεπισκόπηση")) { - return greeklish ? "thlepiskophsh" : "Τηλεπισκόπηση"; - } else if (course.contains("Μικροκύματα II")) { - return greeklish ? "mikrokymata_II" : "Μικροκύματα 2"; + } else if (course.contains("Επιχειρησιακή Έρευνα")) { + return greeklish ? "epixeirisiaki" : "Επιχειρησιακή Έρευνα"; + } else if (course.contains("Ενσωματωμένα Συστήματα Πραγματικού Χρόνου")) { + return greeklish ? "enswmatwmena" : "Ενσωματωμένα"; + } else if (course.contains("Εισαγωγή στις εφαρμογές Πυρηνικής Τεχνολογίας")) { + return greeklish ? "Intro_Purhnikh_Texn" : "Εισ. Πυρηνικη Τεχν."; + } else if (course.contains("Εισαγωγή στην Πολιτική Οικονομία")) { + return greeklish ? "polit_oik" : "Πολιτική Οικονομία"; + } else if (course.contains("Εισαγωγή στην Ενεργειακή Τεχνολογία ΙΙ")) { + return greeklish ? "EET_2" : "ΕΕΤ2"; + } else if (course.contains("Εισαγωγή στην Ενεργειακή Τεχνολογία Ι")) { + return greeklish ? "EET_I" : "ΕΕΤ 1"; + } else if (course.contains("Ειδικές Κεραίες, Σύνθεση Κεραιών")) { + return greeklish ? "eidikes_keraies" : "Ειδικές Κεραίες, Σύνθεση Κεραιών"; + } else if (course.contains("Ειδικές Αρχιτεκτονικές Υπολογιστών")) { + return greeklish ? "eidikes_arx_ypolog" : "Ειδικές Αρχιτεκτονικές Υπολογιστών"; + } else if (course.contains("Ειδικά Κεφάλαια Συστημάτων Ηλεκτρικής Ενέργειας")) { + return greeklish ? "ekshe" : "ΕΚΣΗΕ"; + } else if (course.contains("Ειδικά Κεφάλαια Ηλεκτρομαγνητικού Πεδίου Ι")) { + return greeklish ? "eidika_kef_HM_pedioy_I" : "Ειδικά Κεφάλαια Ηλεκτρομαγνητικού Πεδίου Ι"; + } else if (course.contains("Ειδικά Κεφάλαια Διαφορικών Εξισώσεων")) { + return greeklish ? "eidika_kef_diaf_eksis" : "Ειδικά Κεφάλαια Διαφορικών Εξισώσεων"; + } else if (course.contains("Δομημένος Προγραμματισμός")) { + return greeklish ? "C" : "Δομ. Προγραμμ."; + } else if (course.contains("Δομές Δεδομένων")) { + return greeklish ? "dom_dedomenwn" : "Δομ. Δεδομ."; + } else if (course.contains("Διαχείριση Συστημάτων Ηλεκτρικής Ενέργειας")) { + return greeklish ? "dshe" : "ΔΣΗΕ"; + } else if (course.contains("Διαφορικές Εξισώσεις")) { + return greeklish ? "diaforikes" : "Διαφορικές"; + } else if (course.contains("Διανεμημένη Παραγωγή")) { + return greeklish ? "dian_paragwgh" : "Διανεμημένη Παραγωγή"; + } else if (course.contains("Διακριτά μαθηματικά")) { + return greeklish ? "diakrita" : "Διακριτά Μαθηματικά"; + } else if (course.contains("Διακριτά Μαθηματικά")) { + return greeklish ? "diakrita" : "Διακριτά Μαθηματικά"; + } else if (course.contains("Διάδοση Ηλεκτρομαγνητικού Κύματος Ι (πρώην Πεδίο ΙΙΙ)")) { + return greeklish ? "diadosi_1" : "Διάδοση 1"; + } else if (course.contains("Διάδοση Η/Μ Κύματος ΙΙ")) { + return greeklish ? "diadosi_II" : "Διάδοση 2"; + } else if (course.contains("Δίκτυα Υπολογιστών ΙΙ")) { + return greeklish ? "diktya_II" : "Δίκτυα 2"; + } else if (course.contains("Δίκτυα Υπολογιστών Ι")) { + return greeklish ? "diktya_I" : "Δίκτυα 1"; + } else if (course.contains("Δίκτυα Τηλεπικοινωνιών")) { + return greeklish ? "diktya_thlep" : "Δίκτυα Τηλέπ."; + } else if (course.contains("Γραφική με Υπολογιστές")) { + return greeklish ? "grafikh" : "Γραφική"; + } else if (course.contains("Γραμμική Άλγεβρα")) { + return greeklish ? "grammikh_algebra" : "Γραμμ. Άλγεβρ."; + } else if (course.contains("Γεωηλεκτρομαγνητισμός")) { + return greeklish ? "geohlektromagnitismos" : "Γεωηλεκτρομαγνητισμός"; + } else if (course.contains("Βιοϊατρική Τεχνολογία")) { + return greeklish ? "vioiatriki" : "Βιοιατρική"; + } else if (course.contains("Βιομηχανική Πληροφορική")) { + return greeklish ? "viomix_plir" : "Βιομηχανική Πληρ"; + } else if (course.contains("Βιομηχανικά Ηλεκτρονικά")) { + return greeklish ? "bhomix_hlektronika" : "Βιομηχανικά Ηλεκτρονικά"; + } else if (course.contains("Βάσεις Δεδομένων")) { + return greeklish ? "vaseis" : "Βάσεις"; + } else if (course.contains("Ασύρματος Τηλεπικοινωνία ΙΙ")) { + return greeklish ? "asyrmatos_II" : "Ασύρματος 2"; + } else if (course.contains("Ασύρματος Τηλεπικοινωνία Ι")) { + return greeklish ? "asyrmatos_I" : "Ασύρματος 1"; + } else if (course.contains("Ασφάλεια Πληροφοριακών Συστημάτων")) { + return greeklish ? "asfaleia" : "Ασφάλεια"; + } else if (course.contains("Ασαφή Συστήματα")) { + return greeklish ? "asafh" : "Ασαφή"; + } else if (course.contains("Αρχιτεκτονική Υπολογιστών")) { + return greeklish ? "arx_ypologistwn" : "Αρχ. Υπολογιστών"; + } else if (course.contains("Αρχές Παράλληλης Επεξεργασίας")) { + return greeklish ? "arxes_parall_epeksergasias" : "Αρχές Παράλληλης Επεξεργασίας"; + } else if (course.contains("Αρχές Οικονομίας")) { + return greeklish ? "arx_oikonomias" : "Αρχές Οικονομίας"; + } else if (course.contains("Αριθμητική Ανάλυση")) { + return greeklish ? "arith_anal" : "Αριθμ. Ανάλυση"; + } else if (course.contains("Αξιοπιστία Συστημάτων")) { + return greeklish ? "aksiopistia_systhmatwn" : "Αξιοπιστία Συστημάτων"; + } else if (course.contains("Αντικειμενοστραφής Προγραμματισμός")) { + return greeklish ? "OOP" : "Αντικειμενοστραφής"; + } else if (course.contains("Αναλογικές Τηλεπικοινωνίες (πρώην Τηλεπικοινωνιακά Συστήματα Ι)")) { + return greeklish ? "anal_thlep" : "Αναλογικές Τηλεπ."; + } else if (course.contains("Αναγνώριση Προτύπων")) { + return greeklish ? "protipa" : "Αναγνώριση Προτύπων"; + } else if (course.contains("Ανάλυση και Σχεδίαση Αλγορίθμων")) { + return greeklish ? "algorithms" : "Αλγόριθμοι"; + } else if (course.contains("Ανάλυση Χρονοσειρών")) { + return greeklish ? "xronoseires" : "Χρονοσειρές"; + } else if (course.contains("Ανάλυση Συστημάτων Ηλεκτρικής Ενέργειας")) { + return greeklish ? "ASHE" : "ΑΣΗΕ"; + } else if (course.contains("Ανάλυση Ηλεκτρικών Κυκλωμάτων με Υπολογιστή")) { + return greeklish ? "analysh_hlektr_kykl" : "Ανάλυση Ηλεκτρικ. Κυκλ. με Υπολογιστή"; + } else if (course.contains("Ακουστική ΙΙ")) { + return greeklish ? "akoystikh_II" : "Ακουστική 2"; + } else if (course.contains("Ακουστική Ι")) { + return greeklish ? "akoystikh_I" : "Ακουστική 1"; } else { return null; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java index 9a2be209..9529d402 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java @@ -8,6 +8,7 @@ import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.net.Uri; +import android.os.Environment; import android.provider.OpenableColumns; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -25,7 +26,7 @@ import timber.log.Timber; class UploadsHelper { private static final int DEFAULT_MIN_WIDTH_QUALITY = 400; - private static final String TEMP_IMAGE_NAME = "tempUploadFile.jpg"; + private static final String CACHE_IMAGE_NAME = "tempUploadFile.jpg"; @NonNull static String filenameFromUri(Context context, Uri uri) { @@ -53,7 +54,7 @@ class UploadsHelper { static String createTempFile(Context context, Uri fileUri, String newFilename) { String oldFilename = filenameFromUri(context, fileUri); String fileExtension = oldFilename.substring(oldFilename.indexOf(".")); - String destinationFilename = android.os.Environment.getExternalStorageDirectory().getPath() + + String destinationFilename = Environment.getExternalStorageDirectory().getPath() + File.separatorChar + "~tmp_mThmmy_uploads" + File.separatorChar + newFilename + fileExtension; File tempDirectory = new File(android.os.Environment.getExternalStorageDirectory().getPath() + @@ -99,16 +100,35 @@ class UploadsHelper { return destinationFilename; } - static File getTempFile(Context context) { - File imageFile = new File(context.getExternalCacheDir(), TEMP_IMAGE_NAME); + static File getCacheFile(Context context) { + File imageFile = new File(context.getExternalCacheDir(), CACHE_IMAGE_NAME); //noinspection ResultOfMethodCallIgnored imageFile.getParentFile().mkdirs(); return imageFile; } - static boolean deleteTempFile(String destinationFilename) { - File file = new File(destinationFilename); - return file.delete(); + @SuppressWarnings("ResultOfMethodCallIgnored") + static void deleteTempFiles() { + File tempFilesDirectory = new File(Environment.getExternalStorageDirectory().getPath() + + File.separatorChar + "~tmp_mThmmy_uploads"); + + if (tempFilesDirectory.isDirectory()) { + String[] tempFilesArray = tempFilesDirectory.list(); + for (String tempFile : tempFilesArray) { + new File(tempFilesDirectory, tempFile).delete(); + } + tempFilesDirectory.delete(); + } + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + static void deleteCacheFiles(Context context) { + File cacheFilesDirectory = context.getExternalCacheDir(); + assert cacheFilesDirectory != null; + String[] tempFilesArray = cacheFilesDirectory.list(); + for (String tempFile : tempFilesArray) { + new File(cacheFilesDirectory, tempFile).delete(); + } } /** diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java index 94521fc9..df678e29 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -7,7 +7,6 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -45,12 +44,12 @@ import java.util.ArrayList; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.AboutActivity; import gr.thmmy.mthmmy.activities.LoginActivity; -import gr.thmmy.mthmmy.activities.upload.UploadActivity; import gr.thmmy.mthmmy.activities.bookmarks.BookmarkActivity; import gr.thmmy.mthmmy.activities.downloads.DownloadsActivity; import gr.thmmy.mthmmy.activities.main.MainActivity; import gr.thmmy.mthmmy.activities.profile.ProfileActivity; import gr.thmmy.mthmmy.activities.settings.SettingsActivity; +import gr.thmmy.mthmmy.activities.upload.UploadActivity; import gr.thmmy.mthmmy.model.Bookmark; import gr.thmmy.mthmmy.model.ThmmyFile; import gr.thmmy.mthmmy.services.DownloadHelper; diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java index 95a1ab1d..34c6d2f9 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Bundle; import android.support.v4.content.ContextCompat; import android.util.DisplayMetrics; import android.widget.ImageView; @@ -12,6 +13,7 @@ import android.widget.ImageView; import com.franmontiel.persistentcookiejar.PersistentCookieJar; import com.franmontiel.persistentcookiejar.cache.SetCookieCache; import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; +import com.google.firebase.analytics.FirebaseAnalytics; import com.jakewharton.picasso.OkHttp3Downloader; import com.mikepenz.fontawesome_typeface_library.FontAwesome; import com.mikepenz.iconics.IconicsDrawable; @@ -22,7 +24,6 @@ import com.squareup.picasso.Picasso; import net.gotev.uploadservice.UploadService; import net.gotev.uploadservice.okhttp.OkHttpStack; -import java.io.IOException; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -31,16 +32,17 @@ import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.session.SessionManager; import gr.thmmy.mthmmy.utils.CrashReportingTree; import okhttp3.HttpUrl; -import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; -import okhttp3.Response; import timber.log.Timber; public class BaseApplication extends Application { private static BaseApplication baseApplication; //BaseApplication singleton - // Client & SessionManager + //FirebaseAnalytics + private FirebaseAnalytics firebaseAnalytics; + + //Client & SessionManager private OkHttpClient client; private SessionManager sessionManager; @@ -59,32 +61,31 @@ public class BaseApplication extends Application { super.onCreate(); baseApplication = this; //init singleton - if (BuildConfig.DEBUG) { + if (BuildConfig.DEBUG) Timber.plant(new Timber.DebugTree()); - } else { + else Timber.plant(new CrashReportingTree()); - } + + // Analytics init + firebaseAnalytics = FirebaseAnalytics.getInstance(this); SharedPreferences sharedPrefs = getSharedPreferences(SHARED_PREFS_NAME, MODE_PRIVATE); SharedPrefsCookiePersistor sharedPrefsCookiePersistor = new SharedPrefsCookiePersistor(getApplicationContext()); PersistentCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor); client = new OkHttpClient.Builder() .cookieJar(cookieJar) - .addInterceptor(new Interceptor() { - @Override - public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - HttpUrl oldUrl = chain.request().url(); - if (Objects.equals(chain.request().url().host(), "www.thmmy.gr")) { - if (!oldUrl.toString().contains("theme=4")) { - //Probably works but needs more testing: - HttpUrl newUrl = oldUrl.newBuilder().addQueryParameter("theme", "4").build(); - request = request.newBuilder().url(newUrl).build(); - } + .addInterceptor(chain -> { + Request request = chain.request(); + HttpUrl oldUrl = chain.request().url(); + if (Objects.equals(chain.request().url().host(), "www.thmmy.gr")) { + if (!oldUrl.toString().contains("theme=4")) { + //Probably works but needs more testing: + HttpUrl newUrl = oldUrl.newBuilder().addQueryParameter("theme", "4").build(); + request = request.newBuilder().url(newUrl).build(); } - return chain.proceed(request); - } + return chain.proceed(request); + }) .connectTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) @@ -130,6 +131,12 @@ public class BaseApplication extends Application { dpWidth = displayMetrics.widthPixels / displayMetrics.density; } + public void logFirebaseAnalyticsEvent(String event, Bundle params) { + firebaseAnalytics.logEvent(event, params); + } + + //Getters + public OkHttpClient getClient() { return client; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java index 1e1a5c31..65b5a426 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java +++ b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java @@ -41,6 +41,7 @@ public class DownloadHelper { request.setDestinationInExternalPublicDir(SAVE_DIR.getName(), fileName); request.allowScanningByMediaScanner(); + BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_download", null); downloadManager.enqueue(request); } catch (Exception e) { Toast.makeText(applicationContext, "Download failed...", Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/CrashReporter.java b/app/src/main/java/gr/thmmy/mthmmy/utils/CrashReporter.java new file mode 100644 index 00000000..81b06769 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/CrashReporter.java @@ -0,0 +1,42 @@ +package gr.thmmy.mthmmy.utils; + +import com.crashlytics.android.Crashlytics; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import gr.thmmy.mthmmy.utils.parsing.ParseHelpers; + +public class CrashReporter { + private static final int STRING_BATCH_LENGTH = 250; + + private CrashReporter() {} + + public static void reportDocument(Document document, String key) { + String documentString = document.toString(); + + ParseHelpers.Language language = ParseHelpers.Language.getLanguage(document); + Elements postRows; + if (language.is(ParseHelpers.Language.GREEK)) + postRows = document.select("form[id=quickModForm]>table>tbody>tr:matches(στις)"); + else + postRows = document.select("form[id=quickModForm]>table>tbody>tr:matches(on)"); + for (Element thisRow : postRows) { + String subject = thisRow.select("div[id^=subject_]").first().select("a").first().text(); + documentString = documentString.replace(subject, "subject"); + String post = thisRow.select("div").select(".post").first().text(); + documentString = documentString.replace(post, "post"); + } + + int batchCount = documentString.length() / STRING_BATCH_LENGTH; + for (int i = 0; i < batchCount; i++) { + String batch; + if (i != batchCount - 1) + batch = documentString.substring(i * STRING_BATCH_LENGTH, (i + 1) * STRING_BATCH_LENGTH); + else + batch = documentString.substring(i * STRING_BATCH_LENGTH); + Crashlytics.setString(key + "_" + i + 1, batch); + } + } +} diff --git a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java index c44d917a..96cecf4a 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java +++ b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java @@ -22,6 +22,7 @@ import gr.thmmy.mthmmy.base.BaseActivity; import gr.thmmy.mthmmy.model.Post; import gr.thmmy.mthmmy.session.SessionManager; import gr.thmmy.mthmmy.utils.parsing.ParseHelpers; +import timber.log.Timber; public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTaskCompleted, PrepareForReply.OnPrepareForReplyFinished, PrepareForEditTask.OnPrepareEditFinished { @@ -85,6 +86,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa public void reloadPage() { if (topicUrl == null) throw new NullPointerException("No topic task has been requested yet!"); + Timber.i("Reloading page"); loadUrl(topicUrl); } @@ -93,6 +95,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa throw new NullPointerException("No page has been loaded yet!"); int pageRequested = pageIndicatorIndex.getValue() - 1; if (pageRequested != currentPageIndex - 1) { + Timber.i("Changing to page " + pageRequested + 1); loadUrl(ParseHelpers.getBaseURL(topicUrl) + "." + String.valueOf(pageRequested * 15)); pageIndicatorIndex.setValue(pageRequested + 1); } else { @@ -105,6 +108,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa throw new NullPointerException("Topic task has not finished yet!"); stopLoading(); setPageIndicatorIndex(pageCount, true); + Timber.i("Preparing for reply"); currentPrepareForReplyTask = new PrepareForReply(prepareForReplyCallbacks, this, replyPageUrl.getValue()); currentPrepareForReplyTask.execute(toQuoteList.toArray(new Integer[0])); @@ -122,11 +126,13 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa includeAppSignature = prefs.getBoolean(SettingsActivity.POSTING_APP_SIGNATURE_ENABLE_KEY, true); } toQuoteList.clear(); + Timber.i("Posting reply"); new ReplyTask(replyFinishListener, includeAppSignature).execute(subject, reply, replyForm.getNumReplies(), replyForm.getSeqnum(), replyForm.getSc(), replyForm.getTopic()); } public void deletePost(String postDeleteUrl) { + Timber.i("Deleting post"); new DeleteTask(deleteTaskCallbacks).execute(postDeleteUrl); } @@ -134,6 +140,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa if (replyPageUrl.getValue() == null) throw new NullPointerException("Topic task has not finished yet!"); stopLoading(); + Timber.i("Preparing for edit"); currentPrepareForEditTask = new PrepareForEditTask(prepareForEditCallbacks, this, position, replyPageUrl.getValue()); currentPrepareForEditTask.execute(postEditURL); @@ -143,6 +150,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa if (prepareForEditResult.getValue() == null) throw new NullPointerException("Edit preparation was not found!"); PrepareForEditResult editResult = prepareForEditResult.getValue(); + Timber.i("Editing post"); new EditTask(editTaskCallbacks, position).execute(editResult.getCommitEditUrl(), message, editResult.getNumReplies(), editResult.getSeqnum(), editResult.getSc(), subject, editResult.getTopic()); } @@ -154,15 +162,18 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa */ public void stopLoading() { if (currentTopicTask != null && currentTopicTask.getStatus() == AsyncTask.Status.RUNNING) { + Timber.i("Canceling topic task"); currentTopicTask.cancel(true); pageIndicatorIndex.setValue(currentPageIndex); topicTaskObserver.onTopicTaskCancelled(); } if (currentPrepareForEditTask != null && currentPrepareForEditTask.getStatus() == AsyncTask.Status.RUNNING) { + Timber.i("Canceling prepare for edit task"); currentPrepareForEditTask.cancel(true); prepareForEditCallbacks.onPrepareEditCancelled(); } if (currentPrepareForReplyTask != null && currentPrepareForReplyTask.getStatus() == AsyncTask.Status.RUNNING) { + Timber.i("Canceling prepare for reply task"); currentPrepareForReplyTask.cancel(true); prepareForReplyCallbacks.onPrepareForReplyCancelled(); } diff --git a/app/src/main/res/drawable/ic_attach_file_white_24dp.xml b/app/src/main/res/drawable/ic_attach_file_white_24dp.xml new file mode 100644 index 00000000..4834305b --- /dev/null +++ b/app/src/main/res/drawable/ic_attach_file_white_24dp.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/drawable/ic_photo_camera_white_24dp.xml b/app/src/main/res/drawable/ic_photo_camera_white_24dp.xml new file mode 100644 index 00000000..9835771a --- /dev/null +++ b/app/src/main/res/drawable/ic_photo_camera_white_24dp.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/layout/activity_upload.xml b/app/src/main/res/layout/activity_upload.xml index c80c3ada..d2f81b4c 100644 --- a/app/src/main/res/layout/activity_upload.xml +++ b/app/src/main/res/layout/activity_upload.xml @@ -23,7 +23,7 @@ app:popupTheme="@style/ToolbarTheme" /> - - - - - - - + android:inputType="textMultiLine" /> - - + + + + + + + + + + + + - + - + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_upload_fields_builder.xml b/app/src/main/res/layout/activity_upload_fields_builder.xml index 80966eaa..af3daae6 100644 --- a/app/src/main/res/layout/activity_upload_fields_builder.xml +++ b/app/src/main/res/layout/activity_upload_fields_builder.xml @@ -37,6 +37,7 @@ android:id="@+id/upload_fields_builder_content_linear" android:layout_width="match_parent" android:layout_height="wrap_content" + android:focusableInTouchMode="true" android:orientation="vertical"> + \ No newline at end of file diff --git a/app/src/main/res/layout/spinner_item.xml b/app/src/main/res/layout/spinner_item.xml new file mode 100644 index 00000000..1fb5f1c4 --- /dev/null +++ b/app/src/main/res/layout/spinner_item.xml @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index 628b2a36..e16ea522 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -24,6 +24,10 @@ true true @android:color/transparent + + + diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml index e1c4971b..ea1b50c0 100644 --- a/app/src/main/res/values-w820dp/dimens.xml +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -9,5 +9,6 @@ 144dp 64dp 40dp + 16sp 24sp diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index f823f8e5..c022ce31 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -7,6 +7,7 @@ 36dp 16dp 10dp + 16sp 24sp 24dp 4dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 993d0ef1..4b8013a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -114,13 +114,11 @@ Upload - Select the correct category for the file - Fill in the title and description\nor - build them automatically + Generate title and description Title Description - Select file to upload - Upload + Select file + Take photo Select a category @@ -134,7 +132,8 @@ September Select year Year - Build + Generate + Upload fields generator Settings diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 69d9b065..90595469 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -24,7 +24,11 @@ + +