Browse Source

Merge 7a0ec41349 into cd5fa4bdd9

pull/61/merge
oogee 6 years ago
committed by GitHub
parent
commit
fd02189bc5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/build.gradle
  2. 9
      app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java
  3. 39
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentAdapter.java
  4. 157
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java
  5. 1
      app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java
  6. 53
      app/src/main/java/gr/thmmy/mthmmy/model/RecentItem.java
  7. 31
      app/src/main/res/layout/fragment_recent.xml
  8. 2
      app/src/main/res/layout/fragment_recent_row.xml
  9. 2
      build.gradle
  10. 4
      gradle/wrapper/gradle-wrapper.properties

2
app/build.gradle

@ -72,6 +72,7 @@ dependencies {
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.google.firebase:firebase-core:16.0.6'
implementation 'com.google.firebase:firebase-messaging:17.3.4'
implementation 'com.google.firebase:firebase-firestore:18.1.0'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
@ -89,6 +90,7 @@ dependencies {
implementation 'ru.noties:markwon:2.0.0'
implementation 'net.gotev:uploadservice:3.4.2'
implementation 'net.gotev:uploadservice-okhttp:3.4.2'
implementation 'com.github.curioustechizen.android-ago:library:1.4.0'
implementation 'com.itkacher.okhttpprofiler:okhttpprofiler:1.0.4' //Plugin: https://plugins.jetbrains.com/plugin/11249-okhttp-profiler
}

9
app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java

@ -31,6 +31,7 @@ import gr.thmmy.mthmmy.activities.settings.SettingsActivity;
import gr.thmmy.mthmmy.activities.topic.TopicActivity;
import gr.thmmy.mthmmy.base.BaseActivity;
import gr.thmmy.mthmmy.model.Board;
import gr.thmmy.mthmmy.model.RecentItem;
import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.model.TopicSummary;
import timber.log.Timber;
@ -144,10 +145,12 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
}
@Override
public void onRecentFragmentInteraction(TopicSummary topicSummary) {
public void onRecentFragmentInteraction(RecentItem recentItem) {
Intent i = new Intent(MainActivity.this, TopicActivity.class);
i.putExtra(BUNDLE_TOPIC_URL, topicSummary.getTopicUrl());
i.putExtra(BUNDLE_TOPIC_TITLE, topicSummary.getSubject());
//TODO: Improve this shit with a thmmy url class in model probably
i.putExtra(BUNDLE_TOPIC_URL, "https://www.thmmy.gr/smf/index.php?topic=" +
recentItem.getTopicId() + ".msg" + recentItem.getPostId() + ";topicseen#new");
i.putExtra(BUNDLE_TOPIC_TITLE, recentItem.getTopicTitle());
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
}

39
app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentAdapter.java

@ -6,12 +6,15 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.github.curioustechizen.ago.RelativeTimeTextView;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseFragment;
import gr.thmmy.mthmmy.model.RecentItem;
import gr.thmmy.mthmmy.model.TopicSummary;
@ -21,12 +24,13 @@ import gr.thmmy.mthmmy.model.TopicSummary;
*/
class RecentAdapter extends RecyclerView.Adapter<RecentAdapter.ViewHolder> {
private final Context context;
private final List<TopicSummary> recentList;
private final List<RecentItem> recentItems;
private final RecentFragment.RecentFragmentInteractionListener mListener;
RecentAdapter(Context context, @NonNull List<TopicSummary> topicSummaryList, BaseFragment.FragmentInteractionListener listener) {
RecentAdapter(Context context, @NonNull List<RecentItem> recentItems, BaseFragment.FragmentInteractionListener listener) {
this.context = context;
this.recentList = topicSummaryList;
this.recentItems = recentItems;
mListener = (RecentFragment.RecentFragmentInteractionListener) listener;
}
@ -41,38 +45,33 @@ class RecentAdapter extends RecyclerView.Adapter<RecentAdapter.ViewHolder> {
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.mTitleView.setText(recentList.get(position).getSubject());
holder.mDateTimeView.setText(recentList.get(position).getDateTimeModified());
holder.mUserView.setText(recentList.get(position).getLastUser());
holder.topic = recentList.get(position);
RecentItem recentItem = recentItems.get(position);
holder.mTitleView.setText(recentItem.getTopicTitle());
holder.mDateTimeView.setReferenceTime(recentItem.getTimestamp());
holder.mUserView.setText(recentItem.getPoster());
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.mView.setOnClickListener(v -> {
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onRecentFragmentInteraction(holder.topic); //?
}
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onRecentFragmentInteraction(recentItems.get(holder.getAdapterPosition())); //?
}
});
}
@Override
public int getItemCount() {
return recentList.size();
return recentItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
final TextView mTitleView;
final TextView mUserView;
final TextView mDateTimeView;
public TopicSummary topic;
final RelativeTimeTextView mDateTimeView;
ViewHolder(View view) {
super(view);

157
app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java

@ -1,6 +1,5 @@
package gr.thmmy.mthmmy.activities.main.recent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -9,27 +8,22 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Toast;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.ListenerRegistration;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.HashMap;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseFragment;
import gr.thmmy.mthmmy.model.TopicSummary;
import gr.thmmy.mthmmy.session.SessionManager;
import gr.thmmy.mthmmy.model.RecentItem;
import gr.thmmy.mthmmy.utils.CustomRecyclerView;
import gr.thmmy.mthmmy.utils.NetworkResultCodes;
import gr.thmmy.mthmmy.utils.parsing.NewParseTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import okhttp3.Response;
import timber.log.Timber;
@ -46,15 +40,16 @@ public class RecentFragment extends BaseFragment {
// Fragment initialization parameters, e.g. ARG_SECTION_NUMBER
private MaterialProgressBar progressBar;
private SwipeRefreshLayout swipeRefreshLayout;
private RecentAdapter recentAdapter;
private List<TopicSummary> topicSummaries;
private ArrayList<RecentItem> recentItems = new ArrayList<>();
private RecentTask recentTask;
private ListenerRegistration recentSnapshotListener;
// Required empty public constructor
public RecentFragment() {}
public RecentFragment() {
}
/**
* Use ONLY this factory method to create a new instance of
@ -74,20 +69,34 @@ public class RecentFragment extends BaseFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
topicSummaries = new ArrayList<>();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (topicSummaries.isEmpty()) {
recentTask = new RecentTask(this::onRecentTaskStarted, this::onRecentTaskFinished);
recentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.indexUrl.toString());
}
Timber.d("onActivityCreated");
DocumentReference docRef = FirebaseFirestore.getInstance()
.collection("recent_posts")
.document("recent");
docRef.get().addOnCompleteListener(task -> {
progressBar.setVisibility(ProgressBar.INVISIBLE);
if (task.isSuccessful()) onNewDocumentSnapshot(task.getResult());
else Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
});
recentSnapshotListener = docRef.addSnapshotListener((documentSnapshot, e) -> {
Timber.i("New doc");
onNewDocumentSnapshot(documentSnapshot);
}
);
progressBar.setVisibility(ProgressBar.VISIBLE);
}
@Override
public void onDestroy() {
super.onDestroy();
recentSnapshotListener.remove();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -98,7 +107,7 @@ public class RecentFragment extends BaseFragment {
// Set the adapter
if (rootView instanceof RelativeLayout) {
progressBar = rootView.findViewById(R.id.progressBar);
recentAdapter = new RecentAdapter(getActivity(), topicSummaries, fragmentInteractionListener);
recentAdapter = new RecentAdapter(getActivity(), recentItems, fragmentInteractionListener);
CustomRecyclerView recyclerView = rootView.findViewById(R.id.list);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(recyclerView.getContext());
@ -107,107 +116,23 @@ public class RecentFragment extends BaseFragment {
linearLayoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setAdapter(recentAdapter);
swipeRefreshLayout = rootView.findViewById(R.id.swiperefresh);
swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.primary);
swipeRefreshLayout.setColorSchemeResources(R.color.accent);
swipeRefreshLayout.setOnRefreshListener(() -> {
if (!recentTask.isRunning()) {
recentTask = new RecentTask(this::onRecentTaskStarted, this::onRecentTaskFinished);
recentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, SessionManager.indexUrl.toString());
}
}
);
}
return rootView;
}
@Override
public void onDestroy() {
super.onDestroy();
if (recentTask.isRunning())
recentTask.cancel(true);
}
public interface RecentFragmentInteractionListener extends FragmentInteractionListener {
void onRecentFragmentInteraction(TopicSummary topicSummary);
}
private void onRecentTaskStarted() {
progressBar.setVisibility(ProgressBar.VISIBLE);
}
private void onRecentTaskFinished(int resultCode, ArrayList<TopicSummary> fetchedRecent) {
if (resultCode == NetworkResultCodes.SUCCESSFUL) {
topicSummaries.clear();
topicSummaries.addAll(fetchedRecent);
recentAdapter.notifyDataSetChanged();
} else if (resultCode == NetworkResultCodes.NETWORK_ERROR) {
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "Unexpected error," +
" please contact the developers with the details", Toast.LENGTH_LONG).show();
public void onNewDocumentSnapshot(DocumentSnapshot recentDocument) {
recentItems.clear();
ArrayList<HashMap<String, Object>> posts = (ArrayList<HashMap<String, Object>>) recentDocument.get("posts");
for (HashMap<String, Object> map : posts) {
RecentItem recentItem = new RecentItem(map);
recentItems.add(recentItem);
}
progressBar.setVisibility(ProgressBar.INVISIBLE);
swipeRefreshLayout.setRefreshing(false);
recentAdapter.notifyDataSetChanged();
}
//---------------------------------------ASYNC TASK-----------------------------------
private class RecentTask extends NewParseTask<ArrayList<TopicSummary>> {
RecentTask(OnTaskStartedListener onTaskStartedListener,
OnNetworkTaskFinishedListener<ArrayList<TopicSummary>> onParseTaskFinishedListener) {
super(onTaskStartedListener, onParseTaskFinishedListener);
}
@Override
protected ArrayList<TopicSummary> parse(Document document, Response response) throws ParseException {
ArrayList<TopicSummary> fetchedRecent = new ArrayList<>();
Elements recent = document.select("#block8 :first-child div");
if (!recent.isEmpty()) {
for (int i = 0; i < recent.size(); i += 3) {
String link = recent.get(i).child(0).attr("href");
String title = recent.get(i).child(0).attr("title");
title = title.trim();
String lastUser = recent.get(i + 1).text();
Pattern pattern = Pattern.compile("\\b (.*)");
Matcher matcher = pattern.matcher(lastUser);
if (matcher.find())
lastUser = matcher.group(1);
else
throw new ParseException("Parsing failed (lastUser)");
String dateTime = recent.get(i + 2).text();
pattern = Pattern.compile("\\[(.*)]");
matcher = pattern.matcher(dateTime);
if (matcher.find()) {
dateTime = matcher.group(1);
if (dateTime.contains(" am") || dateTime.contains(" pm") ||
dateTime.contains(" πμ") || dateTime.contains(" μμ")) {
dateTime = dateTime.replaceAll(":[0-5][0-9] ", " ");
} else {
dateTime = dateTime.substring(0, dateTime.lastIndexOf(":"));
}
if (!dateTime.contains(",")) {
dateTime = dateTime.replaceAll(".+? ([0-9])", "$1");
}
} else
throw new ParseException("Parsing failed (dateTime)");
fetchedRecent.add(new TopicSummary(link, title, lastUser, dateTime));
}
return fetchedRecent;
}
throw new ParseException("Parsing failed");
}
@Override
protected int getResultCode(Response response, ArrayList<TopicSummary> data) {
return NetworkResultCodes.SUCCESSFUL;
}
public interface RecentFragmentInteractionListener extends FragmentInteractionListener {
void onRecentFragmentInteraction(RecentItem topicSummary);
}
}

1
app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java

@ -16,6 +16,7 @@ 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.google.firebase.firestore.FirebaseFirestore;
import com.itkacher.okhttpprofiler.OkHttpProfilerInterceptor;
import com.jakewharton.picasso.OkHttp3Downloader;
import com.mikepenz.fontawesome_typeface_library.FontAwesome;

53
app/src/main/java/gr/thmmy/mthmmy/model/RecentItem.java

@ -0,0 +1,53 @@
package gr.thmmy.mthmmy.model;
import java.util.Date;
import java.util.Map;
public class RecentItem {
private int boardId, postId, topicId, posterId;
private String boardTitle, topicTitle, poster;
private long timestamp;
public RecentItem(Map<String, Object> map) {
this.boardId = ((Long) map.get("boardId")).intValue();
this.postId = ((Long) map.get("postId")).intValue();
this.poster = String.valueOf(map.get("poster"));
this.posterId = ((Long) map.get("posterId")).intValue();
this.topicId = ((Long) map.get("topicId")).intValue();
this.boardTitle = String.valueOf(map.get("boardTitle"));
this.topicTitle = String.valueOf(map.get("topicTitle"));
this.timestamp = (long)(map.get("timestamp")) * 1000;
}
public long getTimestamp() {
return timestamp;
}
public int getBoardId() {
return boardId;
}
public int getPosterId() {
return posterId;
}
public int getPostId() {
return postId;
}
public int getTopicId() {
return topicId;
}
public String getBoardTitle() {
return boardTitle;
}
public String getPoster() {
return poster;
}
public String getTopicTitle() {
return topicTitle;
}
}

31
app/src/main/res/layout/fragment_recent.xml

@ -1,28 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swiperefresh"
<gr.thmmy.mthmmy.utils.CustomRecyclerView
android:id="@+id/list"
android:name="gr.thmmy.mthmmy.sections.recent.RecentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
<gr.thmmy.mthmmy.utils.CustomRecyclerView
android:id="@+id/list"
android:name="gr.thmmy.mthmmy.sections.recent.RecentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:paddingBottom="4dp"
android:paddingTop="4dp"
app:layoutManager="LinearLayoutManager"
tools:context=".activities.main.recent.RecentFragment"
tools:listitem="@layout/fragment_recent_row"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
android:layout_height="match_parent"
android:background="@color/background"
android:paddingTop="4dp"
android:paddingBottom="4dp"
app:layoutManager="LinearLayoutManager"
tools:context=".activities.main.recent.RecentFragment"
tools:listitem="@layout/fragment_recent_row" />
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/progressBar"
@ -33,5 +26,5 @@
android:indeterminate="true"
android:visibility="invisible"
app:mpb_indeterminateTint="@color/accent"
app:mpb_progressStyle="horizontal"/>
app:mpb_progressStyle="horizontal" />
</RelativeLayout>

2
app/src/main/res/layout/fragment_recent_row.xml

@ -32,7 +32,7 @@
android:layout_below="@+id/title"
android:layout_toEndOf="@+id/dateTime"/>
<TextView
<com.github.curioustechizen.ago.RelativeTimeTextView
android:id="@+id/dateTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

2
build.gradle

@ -8,7 +8,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'com.google.gms:google-services:4.2.0'
classpath 'io.fabric.tools:gradle:1.26.1'
classpath 'org.ajoberstar.grgit:grgit-core:3.0.0' // Also change in app/gradle/grgit.gradle

4
gradle/wrapper/gradle-wrapper.properties

@ -1,6 +1,6 @@
#Fri Sep 28 13:21:54 EEST 2018
#Sat Mar 02 17:05:57 EET 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip

Loading…
Cancel
Save