Browse Source

Merge branch 'develop' into editor_view

pull/45/head
oogee 6 years ago
committed by GitHub
parent
commit
a67221563b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      README.md
  2. 6
      app/build.gradle
  3. 2
      app/src/main/AndroidManifest.xml
  4. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java
  5. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
  6. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
  7. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/settings/SettingsActivity.java
  8. 22
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  9. 6
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java
  10. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java
  11. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java
  12. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForEditTask.java
  13. 1
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java
  14. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java
  15. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTaskResult.java
  16. 219
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
  17. 501
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java
  18. 34
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
  19. 3
      app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
  20. 29
      app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
  21. 1
      app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java
  22. 42
      app/src/main/java/gr/thmmy/mthmmy/utils/CrashReporter.java
  23. 11
      app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
  24. 4
      app/src/main/res/drawable/ic_attach_file_white_24dp.xml
  25. 5
      app/src/main/res/drawable/ic_photo_camera_white_24dp.xml
  26. 99
      app/src/main/res/layout/activity_upload.xml
  27. 1
      app/src/main/res/layout/activity_upload_fields_builder.xml
  28. 14
      app/src/main/res/layout/spinner_dropdown_item.xml
  29. 14
      app/src/main/res/layout/spinner_item.xml
  30. 4
      app/src/main/res/values-v21/styles.xml
  31. 1
      app/src/main/res/values-w820dp/dimens.xml
  32. 1
      app/src/main/res/values/dimens.xml
  33. 11
      app/src/main/res/values/strings.xml
  34. 4
      app/src/main/res/values/styles.xml
  35. 2
      build.gradle

2
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.*

6
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'

2
app/src/main/AndroidManifest.xml

@ -121,7 +121,7 @@
<activity
android:name=".activities.settings.SettingsActivity"
android:parentActivityName=".activities.main.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
android:theme="@style/AppTheme.PreferenceTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.main.MainActivity" />

4
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);

4
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,

1
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;

1
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;

22
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,11 +502,14 @@ 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() {
@Override
@ -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();
}
});

6
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();

1
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java

@ -38,6 +38,7 @@ public class DeleteTask extends AsyncTask<String, Void, Boolean> {
//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());

1
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/EditTask.java

@ -51,6 +51,7 @@ public class EditTask extends AsyncTask<String, Void, Boolean> {
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...

1
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;

1
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/ReplyTask.java

@ -54,6 +54,7 @@ public class ReplyTask extends AsyncTask<String, Void, Boolean> {
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...

3
app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/TopicTask.java

@ -107,7 +107,6 @@ public class TopicTask extends AsyncTask<String, Void, TopicTaskResult> {
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<String, Void, TopicTaskResult> {
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);
}

3
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 {

219
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 = "<br /><div style=\"text-align: right;\"><span style=\"font-style: italic;\">uploaded from <a href=\"https://play.google.com/store/apps/details?id=gr.thmmy.mthmmy\">mTHMMY</a></span>";
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 = "<br /><div style=\"text-align: right;\"><span style=\"font-style: italic;\">uploaded from <a href=\"https://play.google.com/store/apps/details?id=gr.thmmy.mthmmy\">mTHMMY</a></span>";
/**
* 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<UploadCategory> uploadRootCategories = new ArrayList<>();
private ArrayList<UploadCategory> uploadRootCategories = new ArrayList<>();
private ParseUploadPageTask parseUploadPageTask;
private ArrayList<String> 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,47 +181,29 @@ 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<ResolveInfo> resInfo = this.getPackageManager().queryIntentActivities(takePhotoIntent, 0);
for (ResolveInfo resolveInfo : resInfo) {
String packageName = resolveInfo.activityInfo.packageName;
targetedIntent.setPackage(packageName);
}
startActivityForResult(takePhotoIntent, REQUEST_CODE_CAMERA);
} 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"};
@ -236,15 +213,30 @@ public class UploadActivity extends BaseActivity {
.setType("image/jpeg")
.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
startActivityForResult(intent, REQUEST_CODE_CHOOSE_FILE);
} else if (options[item].equals("Cancel")) {
dialog.dismiss();
}
startActivityForResult(intent, AFR_REQUEST_CODE_CHOOSE_FILE);
});
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<ResolveInfo> 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<String> 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,19 +394,19 @@ 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);
File cacheImageFile = UploadsHelper.getCacheFile(this);
Uri cacheFileUri = Uri.fromFile(cacheImageFile);
fileIcon = "jpg_image.gif";
bitmap = UploadsHelper.getImageResized(this, fileUri);
int rotation = UploadsHelper.getRotation(this, fileUri);
bitmap = UploadsHelper.getImageResized(this, cacheFileUri);
int rotation = UploadsHelper.getRotation(this, cacheFileUri);
bitmap = UploadsHelper.rotate(bitmap, rotation);
try {
@ -448,12 +420,14 @@ public class UploadActivity extends BaseActivity {
String newFilename = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.FRANCE).
format(new Date());
fileUri = Uri.parse(UploadsHelper.createTempFile(this, fileUri, newFilename));
fileUri = Uri.parse(UploadsHelper.createTempFile(this, cacheFileUri, newFilename));
newFilename += ".jpg";
selectFileButton.setText(newFilename);
}
} else if (requestCode == REQUEST_CODE_FIELDS_BUILDER) {
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<String> 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,14 +567,21 @@ public class UploadActivity extends BaseActivity {
@Override
protected void postExecution(ResultCode result) {
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<String> 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
@ -620,9 +601,5 @@ public class UploadActivity extends BaseActivity {
bundleCategory.remove(0);
}
}
titleDescriptionBuilderButton.setEnabled(true);
progressBar.setVisibility(ProgressBar.GONE);
}
}
}

501
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;
}

34
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();
}
}
/**

3
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;

29
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,20 +61,20 @@ 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 {
.addInterceptor(chain -> {
Request request = chain.request();
HttpUrl oldUrl = chain.request().url();
if (Objects.equals(chain.request().url().host(), "www.thmmy.gr")) {
@ -84,7 +86,6 @@ public class BaseApplication extends Application {
}
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;
}

1
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();

42
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);
}
}
}

11
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();
}

4
app/src/main/res/drawable/ic_attach_file_white_24dp.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
<path android:fillColor="#FFFFFF" android:pathData="M16.5,6v11.5c0,2.21 -1.79,4 -4,4s-4,-1.79 -4,-4V5c0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5v10.5c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V6H10v9.5c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5V5c0,-2.21 -1.79,-4 -4,-4S7,2.79 7,5v12.5c0,3.04 2.46,5.5 5.5,5.5s5.5,-2.46 5.5,-5.5V6h-1.5z"/>
</vector>

5
app/src/main/res/drawable/ic_photo_camera_white_24dp.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
<path android:fillColor="#FFFFFF" android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path android:fillColor="#FFFFFF" android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>

99
app/src/main/res/layout/activity_upload.xml

@ -23,7 +23,7 @@
app:popupTheme="@style/ToolbarTheme" />
</android.support.design.widget.AppBarLayout>
<ScrollView
<android.support.v4.widget.NestedScrollView
android:id="@+id/upload_outer_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -41,16 +41,6 @@
android:focusableInTouchMode="true"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:layout_marginTop="6dp"
android:gravity="center"
android:text="@string/upload_category_pre_text"
android:textAlignment="center"
android:textColor="@color/accent" />
<LinearLayout
android:id="@+id/upload_spinners"
android:layout_width="match_parent"
@ -68,25 +58,6 @@
android:prompt="@string/upload_spinners_hint" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:gravity="center"
android:text="@string/upload_title_description_pre_text"
android:textAlignment="center"
android:textColor="@color/accent" />
<android.support.v7.widget.AppCompatButton
android:id="@+id/upload_title_description_builder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:gravity="center"
android:text="@string/upload_title_description_builder"
android:textAlignment="center"
android:textColor="@color/accent" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -113,32 +84,69 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/upload_description_hint"
android:inputType="textMultiLine"
android:maxLines="3" />
android:inputType="textMultiLine" />
</android.support.design.widget.TextInputLayout>
<android.support.v7.widget.AppCompatButton
android:id="@+id/upload_title_description_builder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:gravity="center"
android:text="@string/upload_title_description_builder"
android:textAlignment="center"
android:textColor="@color/accent" />
<android.support.v7.widget.AppCompatTextView
android:id="@+id/upload_filename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:layout_marginTop="6dp"
android:drawablePadding="5dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="@color/primary_text"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<android.support.v7.widget.AppCompatButton
android:id="@+id/upload_select_file_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_gravity="end"
android:layout_marginEnd="16dp"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:text="@string/upload_select_file"
android:textColor="@color/primary_text" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<android.support.v7.widget.AppCompatButton
android:id="@+id/upload_upload_button"
android:id="@+id/upload_take_photo_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_gravity="end"
android:layout_marginEnd="16dp"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:text="@string/upload_upload_button"
android:textAlignment="center"
android:textColor="@color/accent" />
android:text="@string/upload_take_photo"
android:textColor="@color/primary_text" />
</LinearLayout>
</ScrollView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/progressBar"
@ -151,6 +159,15 @@
app:layout_anchorGravity="bottom|center"
app:mpb_indeterminateTint="@color/accent"
app:mpb_progressStyle="horizontal" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/upload_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/fab_margins"
android:layout_marginEnd="@dimen/fab_margins"
app:layout_behavior="gr.thmmy.mthmmy.utils.ScrollAwareFABBehavior"
app:srcCompat="@drawable/ic_file_upload_white_24dp" />
</android.support.design.widget.CoordinatorLayout>

1
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">
<TextView

14
app/src/main/res/layout/spinner_dropdown_item.xml

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingBottom="6dp"
android:paddingEnd="7dp"
android:paddingStart="7dp"
android:paddingTop="6dp"
android:singleLine="true"
android:textColor="@color/primary_text"
android:textSize="@dimen/medium_text" />

14
app/src/main/res/layout/spinner_item.xml

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:paddingBottom="6dp"
android:paddingEnd="7dp"
android:paddingStart="7dp"
android:paddingTop="6dp"
android:singleLine="true"
android:textColor="@color/primary_text"
android:textSize="@dimen/medium_text" />

4
app/src/main/res/values-v21/styles.xml

@ -24,6 +24,10 @@
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="AppTheme.PreferenceTheme" parent="AppTheme.NoActionBar">
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="colorControlActivated">@color/accent</item>
</style>
</resources>

1
app/src/main/res/values-w820dp/dimens.xml

@ -9,5 +9,6 @@
<dimen name="post_image_button">144dp</dimen>
<dimen name="fab_margins">64dp</dimen>
<dimen name="progress_bar_height">40dp</dimen>
<dimen name="medium_text">16sp</dimen>
<dimen name="big_text">24sp</dimen>
</resources>

1
app/src/main/res/values/dimens.xml

@ -7,6 +7,7 @@
<dimen name="post_image_button">36dp</dimen>
<dimen name="fab_margins">16dp</dimen>
<dimen name="progress_bar_height">10dp</dimen>
<dimen name="medium_text">16sp</dimen>
<dimen name="big_text">24sp</dimen>
<dimen name="editor_format_button_size">24dp</dimen>
<dimen name="editor_format_button_margin_between">4dp</dimen>

11
app/src/main/res/values/strings.xml

@ -114,13 +114,11 @@
<string name="upload_button">Upload</string>
<!--Upload Activity-->
<string name="upload_category_pre_text">Select the correct category for the file</string>
<string name="upload_title_description_pre_text">Fill in the title and description\nor</string>
<string name="upload_title_description_builder">build them automatically</string>
<string name="upload_title_description_builder">Generate title and description</string>
<string name="upload_title_hint">Title</string>
<string name="upload_description_hint">Description</string>
<string name="upload_select_file">Select file to upload</string>
<string name="upload_upload_button">Upload</string>
<string name="upload_select_file">Select file</string>
<string name="upload_take_photo">Take photo</string>
<string name="upload_spinners_hint">Select a category</string>
<!--Upload Fields Builder Activity-->
@ -134,7 +132,8 @@
<string name="upload_fields_builder_radio_button_sept">September</string>
<string name="upload_fields_builder_select_year_title">Select year</string>
<string name="upload_fields_builder_year_hint">Year</string>
<string name="upload_fields_builder_submit">Build</string>
<string name="upload_fields_builder_submit">Generate</string>
<string name="upload_fields_builder_toolbar_title">Upload fields generator</string>
<!--Settings Activity-->
<string name="action_settings">Settings</string>

4
app/src/main/res/values/styles.xml

@ -24,7 +24,11 @@
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.PreferenceTheme" parent="AppTheme.NoActionBar">
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="colorControlActivated">@color/accent</item>
</style>
<style name="PopupMenuStyle">

2
build.gradle

@ -8,7 +8,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.google.gms:google-services:4.0.1'
classpath 'io.fabric.tools:gradle:1.25.4'
}

Loading…
Cancel
Save