diff --git a/app/build.gradle b/app/build.gradle index 603d2651..c73a3bd7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,8 +15,8 @@ android { applicationId "gr.thmmy.mthmmy" minSdkVersion 19 targetSdkVersion 29 - versionCode 25 - versionName "1.8.2" + versionCode 26 + versionName "1.8.3" archivesBaseName = "mTHMMY-v$versionName" buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\"" buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\"" @@ -91,7 +91,7 @@ dependencies { implementation 'com.google.android.material:material:1.1.0' implementation 'com.google.firebase:firebase-analytics:17.4.4' implementation 'com.google.firebase:firebase-crashlytics:17.1.1' - implementation 'com.google.firebase:firebase-messaging:20.2.3' + implementation 'com.google.firebase:firebase-messaging:20.2.4' implementation 'com.snatik:storage:2.1.0' implementation ('com.squareup.okhttp3:okhttp:3.12.12') { //TODO: Warning: OkHttp has dropped support for Android 19 since OkHttp 3.13! force = true //TODO: Remove when minSdkVersion >= 21 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7c7ab811..8b01d869 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -96,6 +96,7 @@ { - Toast.makeText(getApplicationContext(), BaseApplication.getFirebaseProjectId(), Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), BaseApplication.getFirebaseProjectId(), Toast.LENGTH_SHORT).show(); return true; }); } 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 d9aff7eb..f3304276 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java @@ -105,7 +105,7 @@ public class LoginActivity extends BaseActivity { } private void onLoginFailed() { - Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Login failed", Toast.LENGTH_LONG).show(); btnLogin.setEnabled(true); } @@ -166,7 +166,7 @@ public class LoginActivity extends BaseActivity { protected void onPostExecute(Integer result) { //Handle attempt result switch (result) { case SUCCESS: //Successful login - Toast.makeText(getApplicationContext(), + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Welcome, " + sessionManager.getUsername() + "!", Toast.LENGTH_LONG) .show(); BaseApplication.getInstance().logFirebaseAnalyticsEvent(FirebaseAnalytics.Event.LOGIN, null); @@ -180,30 +180,30 @@ public class LoginActivity extends BaseActivity { overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out); break; case WRONG_USER: - Toast.makeText(getApplicationContext(), + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Wrong username!", Toast.LENGTH_LONG).show(); inputUsername.requestFocus(); break; case WRONG_PASSWORD: - Toast.makeText(getApplicationContext(), + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Wrong password!", Toast.LENGTH_LONG).show(); inputPassword.requestFocus(); break; case BANNED_USER: - Toast.makeText(getApplicationContext(), + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "You are banned!", Toast.LENGTH_LONG).show(); inputPassword.requestFocus(); break; case FAILURE: - Toast.makeText(getApplicationContext(), + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Login failed...", Toast.LENGTH_LONG).show(); break; case CONNECTION_ERROR: - Toast.makeText(getApplicationContext(), + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Connection Error", Toast.LENGTH_LONG).show(); break; case EXCEPTION: - Toast.makeText(getApplicationContext(), + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Error", Toast.LENGTH_LONG).show(); break; 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 0623111f..a4ede049 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 @@ -28,6 +28,7 @@ import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.LoginActivity; import gr.thmmy.mthmmy.activities.create_content.CreateContentActivity; import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.model.Board; import gr.thmmy.mthmmy.model.Bookmark; import gr.thmmy.mthmmy.model.ThmmyPage; @@ -77,7 +78,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(Uri.parse(boardUrl)); if (!target.is(ThmmyPage.PageCategory.BOARD)) { Timber.e("Bundle came with a non board url!\nUrl:\n%s", boardUrl); - Toast.makeText(this, "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show(); finish(); } @@ -321,7 +322,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo pStarter = topicColumns.get(3).text(); pStats = "Replies: " + topicColumns.get(4).text() + ", Views: " + topicColumns.get(5).text(); - pLastPost = topicColumns.last().text(); + pLastPost = topicColumns.get(6).text(); Matcher matcher = pLastPostPattern.matcher(pLastPost); if (matcher.find()){ pLastPostDateTime = matcher.group(1); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java index 7054db43..107ed6ce 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BookmarksActivity.java @@ -19,6 +19,7 @@ import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.board.BoardActivity; import gr.thmmy.mthmmy.activities.topic.TopicActivity; import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.model.Bookmark; import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE; @@ -90,7 +91,7 @@ public class BookmarksActivity extends BaseActivity { return toggleNotification(bookmarkedTopic); case BookmarksFragment.INTERACTION_REMOVE_TOPIC_BOOKMARK: removeBookmark(bookmarkedTopic); - Toast.makeText(BookmarksActivity.this, "Bookmark removed", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show(); break; default: break; @@ -113,7 +114,7 @@ public class BookmarksActivity extends BaseActivity { return toggleNotification(bookmarkedBoard); case BookmarksFragment.INTERACTION_REMOVE_BOARD_BOOKMARK: removeBookmark(bookmarkedBoard); - Toast.makeText(BookmarksActivity.this, "Bookmark removed", Toast.LENGTH_SHORT).show(); + Toast.makeText(getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show(); break; default: break; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/create_content/CreateContentActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/create_content/CreateContentActivity.java index 29b0c699..ba14ff98 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/create_content/CreateContentActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/create_content/CreateContentActivity.java @@ -15,6 +15,7 @@ import com.google.android.material.textfield.TextInputLayout; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.settings.SettingsActivity; import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.session.SessionManager; import gr.thmmy.mthmmy.views.editorview.EditorView; import gr.thmmy.mthmmy.views.editorview.EmojiKeyboard; @@ -104,7 +105,7 @@ public class CreateContentActivity extends BaseActivity implements NewTopicTask. finish(); } else { Timber.w("New topic creation failed"); - Toast.makeText(getBaseContext(), "Failed to create new topic!", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Failed to create new topic!", Toast.LENGTH_LONG).show(); finish(); } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java index 2bb96af2..1327a2d0 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java @@ -78,7 +78,7 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter. ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(Uri.parse(downloadsUrl)); if (!target.is(ThmmyPage.PageCategory.DOWNLOADS)) { Timber.e("Bundle came with a non downloads url!\nUrl:\n%s", downloadsUrl); - Toast.makeText(this, "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show(); finish(); } } else downloadsUrl = downloadsIndexUrl; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java index b102c7f7..5d8aa004 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java @@ -31,6 +31,7 @@ import gr.thmmy.mthmmy.activities.profile.ProfileActivity; import gr.thmmy.mthmmy.activities.settings.SettingsActivity; import gr.thmmy.mthmmy.activities.topic.TopicActivity; import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.model.Board; import gr.thmmy.mthmmy.model.ThmmyPage; import gr.thmmy.mthmmy.model.TopicSummary; @@ -138,7 +139,7 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF super.onBackPressed(); return; } else { - Toast.makeText(getBaseContext(), "Press back again to exit!" + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Press back again to exit!" , Toast.LENGTH_SHORT).show(); } mBackPressed = System.currentTimeMillis(); @@ -278,10 +279,10 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF redirectIntent.putExtra(BUNDLE_DOWNLOADS_TITLE, ""); startActivity(redirectIntent); } else if (!page.is(ThmmyPage.PageCategory.INDEX)) { - Toast.makeText(this, "This thmmy sector is not yet supported.", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "This thmmy sector is not yet supported.", Toast.LENGTH_LONG).show(); } } else { - Toast.makeText(this, "This is not thmmy.", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "This is not thmmy.", Toast.LENGTH_LONG).show(); } } } 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 661ed1be..50b2b71d 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 @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; import gr.thmmy.mthmmy.R; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.base.BaseFragment; import gr.thmmy.mthmmy.model.TopicSummary; import gr.thmmy.mthmmy.session.InvalidSessionException; @@ -247,11 +248,11 @@ public class UnreadFragment extends BaseFragment { else{ hideProgressUI(); if (resultCode == NetworkResultCodes.NETWORK_ERROR) - Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error", Toast.LENGTH_SHORT).show(); else if (resultCode == SessionManager.INVALID_SESSION) - Toast.makeText(getContext(), "Session verification failed. Please try logging in again.", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Session verification failed. Please try logging in again.", Toast.LENGTH_LONG).show(); else - Toast.makeText(getContext(), "Unexpected error," + + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Unexpected error," + " please contact the developers with the details", Toast.LENGTH_LONG).show(); } } @@ -322,11 +323,11 @@ public class UnreadFragment extends BaseFragment { else{ hideProgressUI(); if (resultCode == NetworkResultCodes.NETWORK_ERROR) - Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error", Toast.LENGTH_SHORT).show(); else if (resultCode == SessionManager.INVALID_SESSION) - Toast.makeText(getContext(), "Session verification failed. Please try logging out and back in again", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Session verification failed. Please try logging out and back in again", Toast.LENGTH_LONG).show(); else - Toast.makeText(getContext(), "Unexpected error," + + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Unexpected error," + " please contact the developers with the details", Toast.LENGTH_LONG).show(); } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java index 223f36e9..82fd1eda 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java @@ -18,6 +18,7 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatDelegate; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -43,6 +44,7 @@ import gr.thmmy.mthmmy.activities.profile.stats.StatsFragment; import gr.thmmy.mthmmy.activities.profile.summary.SummaryFragment; import gr.thmmy.mthmmy.activities.topic.TopicActivity; import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.model.PostSummary; import gr.thmmy.mthmmy.model.ThmmyPage; import gr.thmmy.mthmmy.utils.Parcel; @@ -66,7 +68,7 @@ import static gr.thmmy.mthmmy.utils.ui.PhotoViewUtils.displayPhotoViewImage; * this user's avatar url using the key {@link #BUNDLE_PROFILE_THUMBNAIL_URL} and a String containing * the username using the key {@link #BUNDLE_PROFILE_USERNAME}. */ -public class ProfileActivity extends BaseActivity implements LatestPostsFragment.LatestPostsFragmentInteractionListener { +public class ProfileActivity extends BaseActivity implements LatestPostsFragment.LatestPostsFragmentInteractionListener, LatestPostsFragment.OnLoadingListener, StatsFragment.OnLoadingListener{ /** * The key to use when putting profile's url String to {@link ProfileActivity}'s Bundle. */ @@ -177,7 +179,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(Uri.parse(profileUrl)); if (!target.is(ThmmyPage.PageCategory.PROFILE)) { Timber.e("Bundle came with a non profile url!\nUrl:\n%s", profileUrl); - Toast.makeText(this, "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show(); finish(); } if (target.is(ThmmyPage.PageCategory.PROFILE_STATS)) { @@ -208,6 +210,24 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment startActivity(i); } + @Override + public void onLoadingLatestPosts(boolean loading) { + setBarVisibility(loading); + } + + @Override + public void onLoadingStats(boolean loading) { + setBarVisibility(loading); + } + + private void setBarVisibility (boolean visible){ + if(visible) + progressBar.setVisibility(ProgressBar.VISIBLE); + else + progressBar.setVisibility(ProgressBar.INVISIBLE); + + } + public void onProfileTaskStarted() { progressBar.setVisibility(ProgressBar.VISIBLE); if (pmFAB.getVisibility() != View.GONE) pmFAB.setEnabled(false); @@ -232,7 +252,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment .into(avatarView); } else - Timber.d("Will not load Glide image (invalid context)"); + Timber.i("Will not load Glide image (invalid context)"); } /** @@ -331,12 +351,11 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment } } else if (result == NetworkResultCodes.NETWORK_ERROR) { Timber.w("Network error while excecuting profile activity"); - Toast.makeText(getBaseContext(), "Network error" + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error" , Toast.LENGTH_LONG).show(); finish(); } else { - Timber.d("Parse failed!"); - Toast.makeText(getBaseContext(), "Fatal error!\n Aborting..." + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Fatal error!\n Aborting..." , Toast.LENGTH_LONG).show(); finish(); } @@ -356,13 +375,17 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment */ private void setupViewPager(ViewPager viewPager, Document profilePage) { ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); - adapter.addFrag(SummaryFragment.newInstance(profilePage), "SUMMARY"); - adapter.addFrag(LatestPostsFragment.newInstance(profileUrl), "LATEST POSTS"); - adapter.addFrag(StatsFragment.newInstance(profileUrl), "STATS"); + adapter.addFragment(SummaryFragment.newInstance(profilePage), "SUMMARY"); + LatestPostsFragment latestPostsFragment = LatestPostsFragment.newInstance(profileUrl); + latestPostsFragment.setOnLoadingListener(this); + adapter.addFragment(latestPostsFragment, "LATEST POSTS"); + StatsFragment statsFragment = StatsFragment.newInstance(profileUrl); + statsFragment.setOnLoadingListener(this); + adapter.addFragment(statsFragment, "STATS"); viewPager.setAdapter(adapter); } - private class ViewPagerAdapter extends FragmentPagerAdapter { + private static class ViewPagerAdapter extends FragmentPagerAdapter { private final List mFragmentList = new ArrayList<>(); private final List mFragmentTitleList = new ArrayList<>(); @@ -370,6 +393,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment super(manager); } + @NonNull @Override public Fragment getItem(int position) { return mFragmentList.get(position); @@ -380,7 +404,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment return mFragmentList.size(); } - void addFrag(Fragment fragment, String title) { + void addFragment(Fragment fragment, String title) { mFragmentList.add(fragment); mFragmentTitleList.add(title); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java index 2b5febed..e42e4095 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java @@ -9,6 +9,7 @@ import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; @@ -18,7 +19,6 @@ import gr.thmmy.mthmmy.base.BaseFragment; import gr.thmmy.mthmmy.model.PostSummary; import gr.thmmy.mthmmy.model.TopicSummary; import gr.thmmy.mthmmy.views.ReactiveWebView; -import me.zhanghai.android.materialprogressbar.MaterialProgressBar; /** * {@link RecyclerView.Adapter} that can display a {@link TopicSummary} and makes a call to the @@ -27,7 +27,6 @@ import me.zhanghai.android.materialprogressbar.MaterialProgressBar; class LatestPostsAdapter extends RecyclerView.Adapter { private static final int VIEW_TYPE_EMPTY = -1; private static final int VIEW_TYPE_ITEM = 0; - private static final int VIEW_TYPE_LOADING = 1; private final Context context; private final LatestPostsFragment.LatestPostsFragmentInteractionListener interactionListener; private final ArrayList parsedTopicSummaries; @@ -39,60 +38,45 @@ class LatestPostsAdapter extends RecyclerView.Adapter { this.parsedTopicSummaries = parsedTopicSummaries; } - interface OnLoadMoreListener { - void onLoadMore(); - } - @Override public int getItemViewType(int position) { if (parsedTopicSummaries.get(position) == null && position == 0) return VIEW_TYPE_EMPTY; - return parsedTopicSummaries.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM; + return VIEW_TYPE_ITEM; } + @NonNull @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - if (viewType == VIEW_TYPE_EMPTY) { - View view = LayoutInflater.from(parent.getContext()). - inflate(R.layout.fragment_profile_latest_posts_empty_message, parent, false); - return new RecyclerView.ViewHolder(view){}; - } + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == VIEW_TYPE_ITEM) { View view = LayoutInflater.from(parent.getContext()). inflate(R.layout.fragment_profile_latest_posts_row, parent, false); return new LatestPostViewHolder(view); - } else if (viewType == VIEW_TYPE_LOADING) { + } else { // viewType == VIEW_TYPE_EMPTY View view = LayoutInflater.from(parent.getContext()). - inflate(R.layout.recycler_loading_item, parent, false); - return new LoadingViewHolder(view); + inflate(R.layout.fragment_profile_latest_posts_empty_message, parent, false); + return new RecyclerView.ViewHolder(view){}; } - return null; } @SuppressLint("ClickableViewAccessibility") @Override - public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { - if (holder instanceof LatestPostViewHolder) { - PostSummary topic = parsedTopicSummaries.get(position); - final LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder; - - latestPostViewHolder.postTitle.setText(topic.getSubject()); - latestPostViewHolder.postDate.setText(topic.getDateTime()); - latestPostViewHolder.post.setBackgroundColor(Color.argb(1, 255, 255, 255)); - latestPostViewHolder.post.loadDataWithBaseURL("file:///android_asset/" - , topic.getPost(), "text/html", "UTF-8", null); - - latestPostViewHolder.latestPostsRow.setOnClickListener(v -> { - if (interactionListener != null) { - // Notify the active callbacks interface (the activity, if the - // fragment is attached to one) that a post has been selected. - interactionListener.onLatestPostsFragmentInteraction( - parsedTopicSummaries.get(holder.getAdapterPosition())); - } - }); - } else if (holder instanceof LoadingViewHolder) { - LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder; - loadingViewHolder.progressBar.setIndeterminate(true); - } + public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) { + PostSummary topic = parsedTopicSummaries.get(position); + final LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder; + latestPostViewHolder.postTitle.setText(topic.getSubject()); + latestPostViewHolder.postDate.setText(topic.getDateTime()); + latestPostViewHolder.post.setBackgroundColor(Color.argb(1, 255, 255, 255)); + latestPostViewHolder.post.loadDataWithBaseURL("file:///android_asset/" + , topic.getPost(), "text/html", "UTF-8", null); + + latestPostViewHolder.latestPostsRow.setOnClickListener(v -> { + if (interactionListener != null) { + // Notify the active callbacks interface (the activity, if the + // fragment is attached to one) that a post has been selected. + interactionListener.onLatestPostsFragmentInteraction( + parsedTopicSummaries.get(holder.getAdapterPosition())); + } + }); } @Override @@ -108,19 +92,10 @@ class LatestPostsAdapter extends RecyclerView.Adapter { LatestPostViewHolder(View itemView) { super(itemView); - latestPostsRow = itemView.findViewById(R.id.latest_posts_row); + latestPostsRow = itemView.findViewById(R.id.latest_posts_row_head); postTitle = itemView.findViewById(R.id.title); postDate = itemView.findViewById(R.id.date); post = itemView.findViewById(R.id.post); } } - - private static class LoadingViewHolder extends RecyclerView.ViewHolder { - final MaterialProgressBar progressBar; - - LoadingViewHolder(View itemView) { - super(itemView); - progressBar = itemView.findViewById(R.id.recycler_progress_bar); - } - } } \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java index c89234ec..939a1fbd 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java @@ -5,9 +5,8 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ProgressBar; -import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -26,7 +25,6 @@ import gr.thmmy.mthmmy.base.BaseFragment; import gr.thmmy.mthmmy.model.PostSummary; import gr.thmmy.mthmmy.utils.parsing.ParseException; import gr.thmmy.mthmmy.utils.parsing.ParseHelpers; -import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import okhttp3.Request; import okhttp3.Response; import timber.log.Timber; @@ -34,7 +32,7 @@ import timber.log.Timber; /** * Use the {@link LatestPostsFragment#newInstance} factory method to create an instance of this fragment. */ -public class LatestPostsFragment extends BaseFragment implements LatestPostsAdapter.OnLoadMoreListener { +public class LatestPostsFragment extends BaseFragment { /** * The key to use when putting profile's url String to {@link LatestPostsFragment}'s Bundle. */ @@ -49,12 +47,13 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap private int pagesLoaded = 0; private String profileUrl; private LatestPostsTask profileLatestPostsTask; - private MaterialProgressBar progressBar; private boolean isLoadingMore; private boolean userHasPosts = true; private static final int visibleThreshold = 5; private int lastVisibleItem, totalItemCount; + private OnLoadingListener onLoadingListener; + public LatestPostsFragment() { // Required empty public constructor } @@ -86,18 +85,15 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.fragment_profile_latest_posts, container, false); latestPostsAdapter = new LatestPostsAdapter(this.getContext(), fragmentInteractionListener, parsedTopicSummaries); - RecyclerView mainContent = rootView.findViewById(R.id.profile_latest_posts_recycler); - mainContent.setAdapter(latestPostsAdapter); + RecyclerView recyclerView = rootView.findViewById(R.id.profile_latest_posts_recycler); + recyclerView.setAdapter(latestPostsAdapter); final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); - mainContent.setLayoutManager(layoutManager); - DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mainContent.getContext(), - layoutManager.getOrientation()); - mainContent.addItemDecoration(dividerItemDecoration); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setItemViewCacheSize(15); - //latestPostsAdapter.setOnLoadMoreListener(); - mainContent.addOnScrollListener(new RecyclerView.OnScrollListener() { + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); totalItemCount = layoutManager.getItemCount(); lastVisibleItem = layoutManager.findLastVisibleItemPosition(); @@ -109,20 +105,15 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap } } }); - progressBar = rootView.findViewById(R.id.progressBar); return rootView; } - @Override public void onLoadMore() { if (pagesLoaded < numberOfPages) { - parsedTopicSummaries.add(null); - latestPostsAdapter.notifyItemInserted(parsedTopicSummaries.size() - 1); - //Load data profileLatestPostsTask = new LatestPostsTask(); profileLatestPostsTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, profileUrl + ";sa=showPosts;start=" + pagesLoaded * 15); - ++pagesLoaded; + pagesLoaded++; } } @@ -147,6 +138,14 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap void onLatestPostsFragmentInteraction(PostSummary postSummary); } + public interface OnLoadingListener { + void onLoadingLatestPosts(boolean loading); + } + + public void setOnLoadingListener(OnLoadingListener onLoadingListener) { + this.onLoadingListener = onLoadingListener; + } + /** * An {@link AsyncTask} that handles asynchronous fetching of a profile page and parsing this * user's latest posts. @@ -154,8 +153,16 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap * parameter!

*/ private class LatestPostsTask extends AsyncTask { + private ArrayList fetchedParsedTopicSummaries; + + @Override protected void onPreExecute() { - if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE); + onLoadingListener.onLoadingLatestPosts(true); + } + + public LatestPostsTask() { + super(); + fetchedParsedTopicSummaries = new ArrayList<>(); } protected Boolean doInBackground(String... profileUrl) { @@ -175,11 +182,12 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap protected void onPostExecute(Boolean result) { if (Boolean.FALSE.equals(result)) - Timber.e(new ParseException("Parsing failed(latest posts)"),"ParseException"); - - progressBar.setVisibility(ProgressBar.INVISIBLE); - latestPostsAdapter.notifyDataSetChanged(); + Timber.e(new ParseException("Parsing failed (latest posts)"),"ParseException"); //TODO: This is inaccurate (e.g. can also have an I/O cause) + int prevSize = parsedTopicSummaries.size(); + parsedTopicSummaries.addAll(fetchedParsedTopicSummaries); + latestPostsAdapter.notifyItemRangeInserted(prevSize, parsedTopicSummaries.size() - prevSize); isLoadingMore = false; + onLoadingListener.onLoadingLatestPosts(false); } //TODO: better parse error handling (ParseException etc.) @@ -191,14 +199,10 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap latestPostsRows = latestPostsPage. select("td:has(table:Contains(Εμφάνιση μηνυμάτων)):not([style]) > table"); - //Removes loading item - if (isLoadingMore) - parsedTopicSummaries.remove(parsedTopicSummaries.size() - 1); - if (!latestPostsRows.select("td:contains(Sorry, no matches were found)").isEmpty() || !latestPostsRows.select("td:contains(Δυστυχώς δεν βρέθηκε τίποτα)").isEmpty()){ userHasPosts = false; - parsedTopicSummaries.add(null); + fetchedParsedTopicSummaries.add(null); return true; } @@ -219,15 +223,17 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap else { pTopicTitle = rowHeader.first().text().replaceAll("\\u00a0","").trim(); pTopicUrl = rowHeader.first().select("a").last().attr("href"); - pDateTime = rowHeader.last().text(); + pDateTime = rowHeader.last().text().replaceAll("(on: )|(στις: )",""); } pPost = ParseHelpers.youtubeEmbeddedFix(row.select("div.post").first()); //Add stuff to make it work in WebView //style.css - pPost = ("" + pPost); + pPost = ("" + + "" + + pPost); - parsedTopicSummaries.add(new PostSummary(pTopicUrl, pTopicTitle, pDateTime, pPost)); + fetchedParsedTopicSummaries.add(new PostSummary(pTopicUrl, pTopicTitle, pDateTime, pPost)); } } return true; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java index 3c084dd5..33a892f4 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java @@ -8,9 +8,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; -import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; import androidx.fragment.app.Fragment; @@ -43,7 +41,7 @@ import javax.net.ssl.SSLHandshakeException; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.base.BaseActivity; -import me.zhanghai.android.materialprogressbar.MaterialProgressBar; +import gr.thmmy.mthmmy.utils.parsing.ParseException; import okhttp3.Request; import okhttp3.Response; import timber.log.Timber; @@ -56,7 +54,6 @@ public class StatsFragment extends Fragment { private String profileUrl; private ProfileStatsTask profileStatsTask; private LinearLayout mainContent; - private MaterialProgressBar progressBar; private boolean userHasPosts = true; private String generalStatisticsTitle = "", generalStatistics = "", postingActivityByTimeTitle = "", mostPopularBoardsByPostsTitle = "", mostPopularBoardsByActivityTitle = ""; @@ -64,6 +61,8 @@ public class StatsFragment extends Fragment { private final List mostPopularBoardsByPosts = new ArrayList<>(), mostPopularBoardsByActivity = new ArrayList<>(); private final ArrayList mostPopularBoardsByPostsLabels = new ArrayList<>(), mostPopularBoardsByActivityLabels = new ArrayList<>(); + private OnLoadingListener onLoadingListener; + public StatsFragment() { // Required empty public constructor } @@ -94,7 +93,6 @@ public class StatsFragment extends Fragment { Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.fragment_profile_stats, container, false); mainContent = rootView.findViewById(R.id.main_content); - progressBar = rootView.findViewById(R.id.progressBar); if (profileStatsTask!=null && profileStatsTask.getStatus() == AsyncTask.Status.FINISHED) populateLayout(); return rootView; @@ -117,6 +115,14 @@ public class StatsFragment extends Fragment { profileStatsTask.cancel(true); } + public interface OnLoadingListener { + void onLoadingStats(boolean loading); + } + + public void setOnLoadingListener(OnLoadingListener onLoadingListener) { + this.onLoadingListener = onLoadingListener; + } + /** * An {@link AsyncTask} that handles asynchronous parsing of a profile page's data. * {@link AsyncTask#onPostExecute(Object) OnPostExecute} method calls {@link #()} @@ -129,7 +135,7 @@ public class StatsFragment extends Fragment { @Override protected void onPreExecute() { - progressBar.setVisibility(ProgressBar.VISIBLE); + onLoadingListener.onLoadingStats(true); } @Override @@ -148,94 +154,80 @@ public class StatsFragment extends Fragment { return false; } - //TODO: better parse error handling (ParseException etc.) @Override protected void onPostExecute(Boolean result) { - if (!result) { //Parse failed! - Timber.d("Parse failed!"); - Toast.makeText(getContext() - , "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show(); - getActivity().finish(); - } - //Parse was successful - populateLayout(); + onLoadingListener.onLoadingStats(false); + if (!result) + Timber.e(new ParseException("Parsing failed (user stats)"),"ParseException"); //TODO: This is inaccurate (e.g. can also have an I/O cause) + else + populateLayout(); } + //TODO: better parse error handling (ParseException etc.) private boolean parseStats(Document statsPage) { //Doesn't go through all the parsing if this user has no posts - if (!statsPage.select("td:contains(No posts to speak of!)").isEmpty()) { - userHasPosts = false; - } - if (!statsPage.select("td:contains(Δεν υπάρχει καμία αποστολή μηνύματος!)").isEmpty()) { + if (!statsPage.select("td:contains(No posts to speak of!), td:contains(Δεν υπάρχει καμία αποστολή μηνύματος!)").isEmpty()) userHasPosts = false; - } + if (statsPage.select("table.bordercolor[align]>tbody>tr").size() != 6) return false; - { - Elements titleRows = statsPage.select("table.bordercolor[align]>tbody>tr.titlebg"); - generalStatisticsTitle = titleRows.first().text(); - Pattern pattern = Pattern.compile("(.+)\\s-"); - Matcher matcher = pattern.matcher(generalStatisticsTitle); - if (matcher.find()) - generalStatisticsTitle = matcher.group(1); - - if (userHasPosts) { - postingActivityByTimeTitle = titleRows.get(1).text(); - mostPopularBoardsByPostsTitle = titleRows.last().select("td").first().text(); - mostPopularBoardsByActivityTitle = titleRows.last().select("td").last().text(); - } + + Elements titleRows = statsPage.select("table.bordercolor[align]>tbody>tr.titlebg"); + generalStatisticsTitle = titleRows.first().text(); + Pattern pattern = Pattern.compile("(.+)\\s-"); + Matcher matcher = pattern.matcher(generalStatisticsTitle); + if (matcher.find()) + generalStatisticsTitle = matcher.group(1); + + if (userHasPosts) { + postingActivityByTimeTitle = titleRows.get(1).text(); + mostPopularBoardsByPostsTitle = titleRows.last().select("td").first().text(); + mostPopularBoardsByActivityTitle = titleRows.last().select("td").last().text(); } - { - Elements statsRows = statsPage.select("table.bordercolor[align]>tbody>tr:not(.titlebg)"); - { - Elements generalStatisticsRows = statsRows.first().select("tbody>tr"); - for (Element generalStatisticsRow : generalStatisticsRows) - generalStatistics += generalStatisticsRow.text() + "\n"; - generalStatistics = generalStatistics.trim(); + + Elements statsRows = statsPage.select("table.bordercolor[align]>tbody>tr:not(.titlebg)"); + Elements generalStatisticsRows = statsRows.first().select("tbody>tr"); + for (Element generalStatisticsRow : generalStatisticsRows) + generalStatistics += generalStatisticsRow.text() + "\n"; + generalStatistics = generalStatistics.trim(); + + if (userHasPosts) { + Elements postingActivityByTimeCols = statsRows.get(1).select(">td").last() + .select("tr").first().select("td[width=4%]"); + int i = -1; + for (Element postingActivityByTimeColumn : postingActivityByTimeCols) + postingActivityByTime.add(new Entry(++i, Float.parseFloat(postingActivityByTimeColumn + .select("img").first().attr("height")))); + + Elements mostPopularBoardsByPostsRows = statsRows.last().select(">td").get(1) + .select(">table>tbody>tr"); + i = mostPopularBoardsByPostsRows.size(); + for (Element mostPopularBoardsByPostsRow : mostPopularBoardsByPostsRows) { + Elements dataCols = mostPopularBoardsByPostsRow.select("td"); + mostPopularBoardsByPosts.add(new BarEntry(--i, + Integer.parseInt(dataCols.last().text()))); + mostPopularBoardsByPostsLabels.add(dataCols.first().text()); } - if (userHasPosts) { - { - Elements postingActivityByTimeCols = statsRows.get(1).select(">td").last() - .select("tr").first().select("td[width=4%]"); - int i = -1; - for (Element postingActivityByTimeColumn : postingActivityByTimeCols) { - postingActivityByTime.add(new Entry(++i, Float.parseFloat(postingActivityByTimeColumn - .select("img").first().attr("height")))); - } - } - { - Elements mostPopularBoardsByPostsRows = statsRows.last().select(">td").get(1) - .select(">table>tbody>tr"); - int i = mostPopularBoardsByPostsRows.size(); - for (Element mostPopularBoardsByPostsRow : mostPopularBoardsByPostsRows) { - Elements dataCols = mostPopularBoardsByPostsRow.select("td"); - mostPopularBoardsByPosts.add(new BarEntry(--i, - Integer.parseInt(dataCols.last().text()))); - mostPopularBoardsByPostsLabels.add(dataCols.first().text()); - } - Collections.reverse(mostPopularBoardsByPostsLabels); - } - { - Elements mostPopularBoardsByActivityRows = statsRows.last().select(">td").last() - .select(">table>tbody>tr"); - int i = mostPopularBoardsByActivityRows.size(); - for (Element mostPopularBoardsByActivityRow : mostPopularBoardsByActivityRows) { - Elements dataCols = mostPopularBoardsByActivityRow.select("td"); - String tmp = dataCols.last().text(); - mostPopularBoardsByActivity.add(new BarEntry(--i, - Float.parseFloat(tmp.substring(0, tmp.indexOf("%"))))); - mostPopularBoardsByActivityLabels.add(dataCols.first().text()); - } - Collections.reverse(mostPopularBoardsByActivityLabels); - } + Collections.reverse(mostPopularBoardsByPostsLabels); + + Elements mostPopularBoardsByActivityRows = statsRows.last().select(">td").last() + .select(">table>tbody>tr"); + i = mostPopularBoardsByActivityRows.size(); + for (Element mostPopularBoardsByActivityRow : mostPopularBoardsByActivityRows) { + Elements dataCols = mostPopularBoardsByActivityRow.select("td"); + String tmp = dataCols.last().text(); + mostPopularBoardsByActivity.add(new BarEntry(--i, + Float.parseFloat(tmp.substring(0, tmp.indexOf("%"))))); + mostPopularBoardsByActivityLabels.add(dataCols.first().text()); } + Collections.reverse(mostPopularBoardsByActivityLabels); } return true; } } private void populateLayout() { - progressBar.setVisibility(ProgressBar.VISIBLE); + onLoadingListener.onLoadingStats(true);; ((TextView) mainContent.findViewById(R.id.general_statistics_title)) .setText(generalStatisticsTitle); ((TextView) mainContent.findViewById(R.id.general_statistics)) @@ -243,7 +235,7 @@ public class StatsFragment extends Fragment { if (!userHasPosts) { mainContent.removeViews(2, mainContent.getChildCount() - 2); - //mainContent.removeViews(2, 6); + onLoadingListener.onLoadingStats(false); return; } @@ -361,7 +353,7 @@ public class StatsFragment extends Fragment { mostPopularBoardsByActivityData.setValueTextColor(Color.WHITE); mostPopularBoardsByActivityChart.setData(mostPopularBoardsByActivityData); mostPopularBoardsByActivityChart.invalidate(); - progressBar.setVisibility(ProgressBar.INVISIBLE); + onLoadingListener.onLoadingStats(false); } private class MyXAxisValueFormatter implements IAxisValueFormatter { @@ -373,7 +365,10 @@ public class StatsFragment extends Fragment { @Override public String getFormattedValue(float value, AxisBase axis) { - return mValues.get((int) value); + if (((int) value) < mValues.size()) + return mValues.get((int) value); + else + return "0"; } } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java index cf41e751..d58112ea 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java @@ -25,7 +25,6 @@ import java.util.Objects; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.utils.parsing.ParseHelpers; import gr.thmmy.mthmmy.views.ReactiveWebView; -import timber.log.Timber; /** * Use the {@link SummaryFragment#newInstance} factory method to create an instance of this fragment. @@ -69,7 +68,7 @@ public class SummaryFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - profileSummaryDocument = Jsoup.parse(getArguments().getString(PROFILE_DOCUMENT)); + profileSummaryDocument = Jsoup.parse(requireArguments().getString(PROFILE_DOCUMENT)); parsedProfileSummaryData = new ArrayList<>(); } @@ -90,7 +89,6 @@ public class SummaryFragment extends Fragment { summaryTask = new SummaryTask(); summaryTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, profileSummaryDocument); } - Timber.d("onActivityCreated"); } @Override @@ -145,6 +143,7 @@ public class SummaryFragment extends Fragment { //Add stuff to make it work in WebView //style.css pHtml = ("\n" + + "\n" + "
\n" + pHtml + "\n
"); } else if (!rowText.contains("Name") && !rowText.contains("Όνομα")) { //Doesn't add username twice if (Objects.equals(summaryRow.select("td").get(1).text(), "")) @@ -189,13 +188,11 @@ public class SummaryFragment extends Fragment { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) entry.setTextColor(getResources().getColor(R.color.primary_text, null)); else - //noinspection deprecation entry.setTextColor(getResources().getColor(R.color.primary_text)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { entry.setText(Html.fromHtml(profileSummaryRow, Html.FROM_HTML_MODE_LEGACY)); } else { - //noinspection deprecation entry.setText(Html.fromHtml(profileSummaryRow)); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxFragment.java index e776423f..d6ab6cfd 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/shoutbox/ShoutboxFragment.java @@ -142,7 +142,7 @@ public class ShoutboxFragment extends Fragment { shoutboxViewModel.loadShoutbox(true); } else if (resultCode == NetworkResultCodes.NETWORK_ERROR) { Timber.w("Failed to send shout"); - Toast.makeText(getContext(), "NetworkError", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "NetworkError", Toast.LENGTH_SHORT).show(); } } @@ -154,10 +154,10 @@ public class ShoutboxFragment extends Fragment { editorView.setVisibility(View.VISIBLE); } else if (resultCode == NetworkResultCodes.NETWORK_ERROR) { Timber.w("Failed to retreive shoutbox due to network error"); - Toast.makeText(getContext(), "NetworkError", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "NetworkError", Toast.LENGTH_SHORT).show(); } else { Timber.wtf("Failed to retreive shoutbox due to unknown error"); - Toast.makeText(getContext(), "Failed to retrieve shoutbox, please contact mthmmy developer team", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Failed to retrieve shoutbox, please contact mthmmy developer team", Toast.LENGTH_LONG).show(); } } 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 3621057f..1bc7da95 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 @@ -150,7 +150,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo Uri.parse(topicPageUrl)); if (!target.is(ThmmyPage.PageCategory.TOPIC)) { Timber.e("Bundle came with a non topic url!\nUrl: %s", topicPageUrl); - Toast.makeText(this, "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show(); finish(); } @@ -516,7 +516,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo viewModel.reloadPage(); } else { Timber.w("Failed to delete post"); - Toast.makeText(getBaseContext(), "Delete failed!", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Delete failed!", Toast.LENGTH_SHORT).show(); } }); viewModel.setReplyFinishListener(new ReplyTask.ReplyTaskCallbacks() { @@ -579,7 +579,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo break; default: Timber.w("Post reply unsuccessful"); - Toast.makeText(getBaseContext(), "Post failed!", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Post failed!", Toast.LENGTH_SHORT).show(); recyclerView.getChildAt(recyclerView.getChildCount() - 1).setAlpha(1f); recyclerView.getChildAt(recyclerView.getChildCount() - 1).setEnabled(true); } @@ -623,7 +623,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo viewModel.reloadPage(); } else { Timber.i("Post edit unsuccessful"); - Toast.makeText(getBaseContext(), "Edit failed!", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Edit failed!", Toast.LENGTH_SHORT).show(); recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setAlpha(1); recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setEnabled(true); } @@ -649,7 +649,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo } else { Timber.w("Failed to send vote"); - Toast.makeText(this, "Failed to send vote", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Failed to send vote", Toast.LENGTH_LONG).show(); } }); viewModel.setRemoveVoteTaskStartedListener(() -> progressBar.setVisibility(ProgressBar.VISIBLE)); @@ -661,7 +661,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo } else { Timber.w("Failed to remove vote"); - Toast.makeText(this, "Failed to remove vote", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Failed to remove vote", Toast.LENGTH_LONG).show(); } }); // observe the changes in data @@ -770,7 +770,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo default: //Parse failed - should never happen Timber.wtf("Parse failed!"); //TODO report ParseException!!! - Toast.makeText(getBaseContext(), "Fatal Error", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Fatal Error", Toast.LENGTH_SHORT).show(); finish(); break; } @@ -824,7 +824,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo //Make a toast to inform the user that the url was copied Toast.makeText( - TopicActivity.this, + BaseApplication.getInstance().getApplicationContext(), TopicActivity.this.getString(R.string.link_copied_msg), Toast.LENGTH_SHORT).show(); } 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 55f3f16e..ea3975d9 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 @@ -268,11 +268,11 @@ public class UploadActivity extends BaseActivity { shouldReturn = true; } if (filesList.isEmpty()) { - Toast.makeText(view.getContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show(); shouldReturn = true; } if (categorySelected.equals("-1")) { - Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose category first", Toast.LENGTH_SHORT).show(); shouldReturn = true; } if (!filesList.isEmpty()) { @@ -282,7 +282,7 @@ public class UploadActivity extends BaseActivity { } if (totalFilesSize > MAX_FILE_SIZE_SUPPORTED) { - Toast.makeText(view.getContext(), "Your files are too powerful for thmmy. Reduce size or split!", Toast.LENGTH_LONG).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Your files are too powerful for thmmy. Reduce size or split!", Toast.LENGTH_LONG).show(); shouldReturn = true; } } @@ -338,7 +338,7 @@ public class UploadActivity extends BaseActivity { if (!storage.rename(uploadFile.getPhotoFile().getAbsolutePath(), destinationFilename)) { //Something went wrong, abort - Toast.makeText(this, "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show(); progressBar.setVisibility(View.GONE); return; } @@ -385,7 +385,7 @@ public class UploadActivity extends BaseActivity { : tempFileUri)) { finish(); } else { - Toast.makeText(this, "Couldn't initiate upload.", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't initiate upload.", Toast.LENGTH_SHORT).show(); } }); @@ -580,7 +580,7 @@ public class UploadActivity extends BaseActivity { zipTask.execute(filesListArray); finish(); } else { - Toast.makeText(this, "Please retry uploading.", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please retry uploading.", Toast.LENGTH_SHORT).show(); } break; } @@ -746,7 +746,7 @@ public class UploadActivity extends BaseActivity { Timber.d("Uploading a file with properties: \nTitle: %s\nCategory: %s\nDescription: %s\nIcon: %s\nUploader: %s", uploadTitleText, categorySelected, uploadDescriptionText, fileIcon, uploaderProfileIndex); multipartUploadRequest.startUpload(); - Toast.makeText(context, "Uploading file(s) in the background...", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Uploading file(s) in the background...", Toast.LENGTH_SHORT).show(); return true; } catch (Exception exception) { Timber.e(exception, "AndroidUploadService: %s", exception.getMessage()); @@ -1041,7 +1041,7 @@ public class UploadActivity extends BaseActivity { @Override protected void onPreExecute() { assert weakActivity != null; - Toast.makeText(weakActivity.get(), "Zipping files", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Zipping files", Toast.LENGTH_SHORT).show(); } @Override @@ -1068,7 +1068,7 @@ public class UploadActivity extends BaseActivity { return; if (!result) { - Toast.makeText(weakActivity.get(), "Couldn't create zip!", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't create zip!", Toast.LENGTH_SHORT).show(); return; } @@ -1077,7 +1077,7 @@ public class UploadActivity extends BaseActivity { getConfigForUpload(weakActivity.get(), uploadID, zipFilename), categorySelected, uploadTitleText, uploadDescriptionText, fileIcon, uploaderProfileIndex, zipFileUri)) { - Toast.makeText(weakActivity.get(), "Couldn't initiate upload.", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't initiate upload.", Toast.LENGTH_SHORT).show(); } } } 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 2ea58fee..8e75b979 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 @@ -17,6 +17,7 @@ import java.util.Calendar; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.base.BaseActivity; +import gr.thmmy.mthmmy.base.BaseApplication; import timber.log.Timber; public class UploadFieldsBuilderActivity extends BaseActivity { @@ -76,7 +77,7 @@ public class UploadFieldsBuilderActivity extends BaseActivity { courseGreeklishName = extras.getString(BUNDLE_UPLOAD_FIELD_BUILDER_COURSE_GREEKLISH_NAME); semester = extras.getString(BUNDLE_UPLOAD_FIELD_BUILDER_SEMESTER); if (courseName == null || courseName.equals("") || semester == null || semester.equals("")) { - Toast.makeText(this, "Something went wrong!", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Something went wrong!", Toast.LENGTH_SHORT).show(); Timber.e("Bundle came empty in %s", UploadFieldsBuilderActivity.class.getSimpleName()); Intent returnIntent = new Intent(); @@ -119,13 +120,13 @@ public class UploadFieldsBuilderActivity extends BaseActivity { int typeId = typeRadio.getCheckedRadioButtonId(), semesterId = semesterRadio.getCheckedRadioButtonId(); if (typeId == -1) { - Toast.makeText(view.getContext(), "Please choose a type for the upload", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose a type for the upload", Toast.LENGTH_SHORT).show(); return; } else if (semesterChooserLinear.getVisibility() == View.VISIBLE && semesterId == -1) { - Toast.makeText(view.getContext(), "Please choose a semester for the upload", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose a semester for the upload", Toast.LENGTH_SHORT).show(); return; } else if (year.getText().toString().isEmpty() || !isValidYear) { - Toast.makeText(view.getContext(), "Please choose a valid year for the upload", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please choose a valid year for the upload", Toast.LENGTH_SHORT).show(); return; } 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 92b71cb0..4bc71490 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 @@ -21,6 +21,7 @@ import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.utils.FileUtils; import timber.log.Timber; @@ -41,7 +42,7 @@ public class UploadsHelper { if (!tempDirectory.exists() && !tempDirectory.mkdirs()) { Timber.w("Temporary directory build returned false in %s", UploadActivity.class.getSimpleName()); - Toast.makeText(context, "Couldn't create temporary directory", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't create temporary directory", Toast.LENGTH_SHORT).show(); return null; } 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 733e12b8..be9ec059 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -569,11 +569,11 @@ public abstract class BaseActivity extends AppCompatActivity { if (thisPageBookmark.matchExists(topicsBookmarked)) { thisPageBookmarkMenuButton.setIcon(R.drawable.ic_bookmark_false_accent_24dp); toggleTopicToBookmarks(thisPageBookmark); - Toast.makeText(getBaseContext(), "Bookmark removed", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show(); } else { thisPageBookmarkMenuButton.setIcon(R.drawable.ic_bookmark_true_accent_24dp); toggleTopicToBookmarks(thisPageBookmark); - Toast.makeText(getBaseContext(), "Bookmark added", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark added", Toast.LENGTH_SHORT).show(); } } @@ -586,10 +586,10 @@ public abstract class BaseActivity extends AppCompatActivity { thisPageBookmarkImageButton.setOnClickListener(view -> { if (thisPageBookmark.matchExists(boardsBookmarked)) { thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_false_accent_24dp); - Toast.makeText(getBaseContext(), "Bookmark removed", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark removed", Toast.LENGTH_SHORT).show(); } else { thisPageBookmarkImageButton.setImageResource(R.drawable.ic_bookmark_true_accent_24dp); - Toast.makeText(getBaseContext(), "Bookmark added", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Bookmark added", Toast.LENGTH_SHORT).show(); } toggleBoardToBookmarks(thisPageBookmark); }); @@ -771,7 +771,7 @@ public abstract class BaseActivity extends AppCompatActivity { BaseActivity.this.startActivity(intent); } catch (Exception e) { Timber.e(e, "Couldn't open downloaded file..."); - Toast.makeText(getBaseContext(), "Couldn't open file...", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't open file...", Toast.LENGTH_SHORT).show(); } }); diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java index c2c1a578..0fd18e5c 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseFragment.java @@ -28,13 +28,11 @@ public abstract class BaseFragment extends Fragment { @Override public void onAttach(Context context) { super.onAttach(context); - if (context instanceof FragmentInteractionListener) { + if (context instanceof FragmentInteractionListener) fragmentInteractionListener = (FragmentInteractionListener) context; - - } else { + else throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); - } } @Override diff --git a/app/src/main/res/layout/fragment_profile_latest_posts.xml b/app/src/main/res/layout/fragment_profile_latest_posts.xml index c44fee77..6827530d 100644 --- a/app/src/main/res/layout/fragment_profile_latest_posts.xml +++ b/app/src/main/res/layout/fragment_profile_latest_posts.xml @@ -1,26 +1,16 @@ + android:layout_height="match_parent" + android:background="@color/background_lighter"> - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_profile_latest_posts_row.xml b/app/src/main/res/layout/fragment_profile_latest_posts_row.xml index 23412289..bf992123 100644 --- a/app/src/main/res/layout/fragment_profile_latest_posts_row.xml +++ b/app/src/main/res/layout/fragment_profile_latest_posts_row.xml @@ -1,61 +1,82 @@ - + android:layout_marginBottom="2dp"> - - - - - - - - + android:layout_height="match_parent" + android:layout_gravity="center" + android:foreground="?android:attr/selectableItemBackground" + card_view:cardBackgroundColor="@color/background" + card_view:cardCornerRadius="5dp" + card_view:cardElevation="2dp" + card_view:cardPreventCornerOverlap="false" + card_view:cardUseCompatPadding="true"> - + android:layout_height="wrap_content"> - - - - \ No newline at end of file + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:paddingTop="8dp"> + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_profile_stats.xml b/app/src/main/res/layout/fragment_profile_stats.xml index cf7eefe1..745ef986 100644 --- a/app/src/main/res/layout/fragment_profile_stats.xml +++ b/app/src/main/res/layout/fragment_profile_stats.xml @@ -1,19 +1,17 @@ + android:layout_height="match_parent"> + android:paddingTop="4dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingBottom="4dp" + android:background="@color/background_lighter"> - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_profile_summary.xml b/app/src/main/res/layout/fragment_profile_summary.xml index 67aaaeb8..098cad5a 100644 --- a/app/src/main/res/layout/fragment_profile_summary.xml +++ b/app/src/main/res/layout/fragment_profile_summary.xml @@ -4,7 +4,7 @@ android:id="@+id/nested_scroll" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/background_light" + android:background="@color/background_lighter" android:paddingEnd="16dp" android:paddingStart="16dp" android:scrollbars="none"> diff --git a/app/src/main/res/layout/fragment_shoutbox.xml b/app/src/main/res/layout/fragment_shoutbox.xml index 69a2649c..a3982068 100644 --- a/app/src/main/res/layout/fragment_shoutbox.xml +++ b/app/src/main/res/layout/fragment_shoutbox.xml @@ -21,6 +21,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" + android:paddingBottom="8dp" tools:listitem="@layout/fragment_shoutbox_shout_row" /> #757575 #323232 #3C3F41 + #434649 #8B8B8B #FF9800 #FAA61A diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f881b88d..702b0fa8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -82,7 +82,6 @@ Username This user has no posts yet General Statistics - Statistics Posting Activity Most Popular Boards By Posts Most Popular Boards By Activity diff --git a/build.gradle b/build.gradle index 72da44f0..a861f527 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:4.0.1' classpath 'com.google.gms:google-services:4.3.3' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0' classpath 'org.ajoberstar.grgit:grgit-core:3.1.1' // Also change in app/gradle/grgit.gradle classpath "com.github.ben-manes:gradle-versions-plugin:0.21.0" }