diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f8ce186c..b1e421d3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -63,6 +63,8 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.main.MainActivity"/>
+
+
\ No newline at end of file
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 80a607a5..734eafff 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
@@ -186,6 +186,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
@SuppressWarnings("unused")
private static final String TAG = "BoardTask"; //Separate tag for AsyncTask
+ @Override
protected void onPreExecute() {
if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE);
if (newTopicFAB.getVisibility() != View.GONE) newTopicFAB.setEnabled(false);
@@ -207,6 +208,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
return false;
}
+ @Override
protected void onPostExecute(Boolean result) {
if (!result) { //Parse failed!
Report.d(TAG, "Parse failed!");
@@ -214,6 +216,8 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
, "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show();
finish();
}
+ if (boardTitle == null || Objects.equals(boardTitle, "")) toolbar.setTitle(boardTitle);
+
//Parse was successful
++pagesLoaded;
if (newTopicFAB.getVisibility() != View.GONE) newTopicFAB.setEnabled(true);
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
new file mode 100644
index 00000000..60d83b44
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
@@ -0,0 +1,274 @@
+package gr.thmmy.mthmmy.activities.downloads;
+
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v7.widget.DividerItemDecoration;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import gr.thmmy.mthmmy.R;
+import gr.thmmy.mthmmy.base.BaseActivity;
+import gr.thmmy.mthmmy.model.Download;
+import gr.thmmy.mthmmy.model.LinkTarget;
+import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
+import mthmmy.utils.Report;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.OnLoadMoreListener {
+ /**
+ * Debug Tag for logging debug output to LogCat
+ */
+ @SuppressWarnings("unused")
+ private static final String TAG = "DownloadsActivity";
+ /**
+ * The key to use when putting download's url String to {@link DownloadsActivity}'s Bundle.
+ */
+ public static final String BUNDLE_DOWNLOADS_URL = "DOWNLOADS_URL";
+ /**
+ * The key to use when putting download's title String to {@link DownloadsActivity}'s Bundle.
+ */
+ public static final String BUNDLE_DOWNLOADS_TITLE = "DOWNLOADS_TITLE";
+ private static final String downloadsIndexUrl = "https://www.thmmy.gr/smf/index.php?action=tpmod;dl;";
+ private String downloadsUrl;
+ String downloadsTitle;
+ private ArrayList parsedDownloads = new ArrayList<>();
+
+ private MaterialProgressBar progressBar;
+ private RecyclerView recyclerView;
+ private DownloadsAdapter downloadsAdapter;
+ private FloatingActionButton uploadFAB;
+
+ private ParseDownloadPageTask parseDownloadPageTask;
+ private int numberOfPages = -1;
+ private int pagesLoaded = 0;
+ private boolean isLoadingMore;
+ private static final int visibleThreshold = 5;
+ private int lastVisibleItem, totalItemCount;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_downloads);
+
+ Bundle extras = getIntent().getExtras();
+ downloadsTitle = extras.getString(BUNDLE_DOWNLOADS_TITLE);
+ if (downloadsTitle == null || Objects.equals(downloadsTitle, ""))
+ downloadsTitle = "Downloads";
+ downloadsUrl = extras.getString(BUNDLE_DOWNLOADS_URL);
+ if (downloadsUrl != null && !Objects.equals(downloadsUrl, "")) {
+ LinkTarget.Target target = LinkTarget.resolveLinkTarget(Uri.parse(downloadsUrl));
+ if (!target.is(LinkTarget.Target.DOWNLOADS)) {
+ Report.e(TAG, "Bundle came with a non board url!\nUrl:\n" + downloadsUrl);
+ Toast.makeText(this, "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show();
+ finish();
+ }
+ } else downloadsUrl = downloadsIndexUrl;
+
+ toolbar = (Toolbar) findViewById(R.id.toolbar);
+ toolbar.setTitle(downloadsTitle);
+ /*setSupportActionBar(toolbar);
+ if (getSupportActionBar() != null) {
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ }*/
+
+ createDrawer();
+
+ progressBar = (MaterialProgressBar) findViewById(R.id.progressBar);
+
+ recyclerView = (RecyclerView) findViewById(R.id.downloads_recycler_view);
+ recyclerView.setHasFixedSize(true);
+ final LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
+ recyclerView.setLayoutManager(layoutManager);
+ DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
+ layoutManager.getOrientation());
+ recyclerView.addItemDecoration(dividerItemDecoration);
+ downloadsAdapter = new DownloadsAdapter(getApplicationContext(), parsedDownloads);
+ recyclerView.setAdapter(downloadsAdapter);
+ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ super.onScrolled(recyclerView, dx, dy);
+ totalItemCount = layoutManager.getItemCount();
+ lastVisibleItem = layoutManager.findLastVisibleItemPosition();
+
+ if (!isLoadingMore && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
+ isLoadingMore = true;
+ onLoadMore();
+ }
+ }
+ });
+
+ uploadFAB = (FloatingActionButton) findViewById(R.id.download_fab);
+ uploadFAB.setEnabled(false);
+
+ parseDownloadPageTask = new ParseDownloadPageTask();
+ parseDownloadPageTask.execute(downloadsUrl);
+ }
+
+ @Override
+ public void onLoadMore() {
+ if (pagesLoaded < numberOfPages) {
+ parsedDownloads.add(null);
+ downloadsAdapter.notifyItemInserted(parsedDownloads.size());
+
+ //Load data
+ parseDownloadPageTask = new ParseDownloadPageTask();
+ if (downloadsUrl.contains("tpstart"))
+ parseDownloadPageTask.execute(downloadsUrl.substring(0
+ , downloadsUrl.lastIndexOf(";tpstart=")) + ";tpstart=" + pagesLoaded * 10);
+ else parseDownloadPageTask.execute(downloadsUrl + ";tpstart=" + pagesLoaded * 10);
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (drawer.isDrawerOpen()) {
+ drawer.closeDrawer();
+ return;
+ }
+ super.onBackPressed();
+ }
+
+ @Override
+ protected void onResume() {
+ drawer.setSelection(-1);
+ super.onResume();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ recyclerView.setAdapter(null);
+ if (parseDownloadPageTask != null && parseDownloadPageTask.getStatus() != AsyncTask.Status.RUNNING)
+ parseDownloadPageTask.cancel(true);
+ }
+
+ /**
+ * An {@link AsyncTask} that handles asynchronous fetching of a downloads page and parsing it's
+ * data. {@link AsyncTask#onPostExecute(Object) OnPostExecute} method calls {@link RecyclerView#swapAdapter}
+ * to build graphics.
+ *
+ *
Calling TopicTask's {@link AsyncTask#execute execute} method needs to have profile's url
+ * as String parameter!
+ */
+ class ParseDownloadPageTask extends AsyncTask {
+ /**
+ * Debug Tag for logging debug output to LogCat
+ */
+ private static final String TAG = "ParseDownloadPageTask"; //Separate tag for AsyncTask
+ private String thisPageUrl;
+
+ @Override
+ protected void onPreExecute() {
+ if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE);
+ if (uploadFAB.getVisibility() != View.GONE) uploadFAB.setEnabled(false);
+ }
+
+ @Override
+ protected Void doInBackground(String... downloadsUrl) {
+ thisPageUrl = downloadsUrl[0];
+ Request request = new Request.Builder()
+ .url(downloadsUrl[0])
+ .build();
+ try {
+ Response response = BaseActivity.getClient().newCall(request).execute();
+ parseDownloads(Jsoup.parse(response.body().string()));
+ } catch (SSLHandshakeException e) {
+ Report.w(TAG, "Certificate problem (please switch to unsafe connection).");
+ } catch (Exception e) {
+ Report.e("TAG", "ERROR", e);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void voids) {
+ if (downloadsTitle == null || Objects.equals(downloadsTitle, ""))
+ toolbar.setTitle(downloadsTitle);
+
+ ++pagesLoaded;
+ if (uploadFAB.getVisibility() != View.GONE) uploadFAB.setEnabled(true);
+ progressBar.setVisibility(ProgressBar.INVISIBLE);
+ downloadsAdapter.notifyDataSetChanged();
+ isLoadingMore = false;
+ }
+
+ private void parseDownloads(Document downloadPage) {
+ if (downloadsTitle == null || Objects.equals(downloadsTitle, ""))
+ downloadsTitle = downloadPage.select("div.nav>b>a.nav").last().text();
+
+ //Removes loading item
+ if (isLoadingMore) {
+ if (parsedDownloads.size() > 0) parsedDownloads.remove(parsedDownloads.size() - 1);
+ }
+
+ Download.DownloadItemType type;
+ if (LinkTarget.resolveLinkTarget(Uri.parse(thisPageUrl)).is(LinkTarget.
+ Target.DOWNLOADS_CATEGORY)) type = Download.DownloadItemType.DOWNLOADS_CATEGORY;
+ else type = Download.DownloadItemType.DOWNLOADS_FILE;
+
+ Elements pages = downloadPage.select("a.navPages");
+ if (pages != null) {
+ for (Element page : pages) {
+ int pageNumber = Integer.parseInt(page.text());
+ if (pageNumber > numberOfPages) numberOfPages = pageNumber;
+ }
+ } else numberOfPages = 1;
+
+ Elements rows = downloadPage.select("table.tborder>tbody>tr");
+ if (type == Download.DownloadItemType.DOWNLOADS_CATEGORY) {
+ Elements navigationLinks = downloadPage.select("div.nav>b");
+ for (Element row : rows) {
+ if (row.select("td").size() == 1) continue;
+
+ String url = row.select("b>a").first().attr("href"),
+ title = row.select("b>a").first().text(),
+ subtitle = row.select("div.smalltext:not(:has(a))").text();
+ if (!row.select("td").last().hasClass("windowbg2")) {
+ if (navigationLinks.size() < 4) {
+
+ parsedDownloads.add(new Download(type, url, title, subtitle, null,
+ true, null));
+ } else {
+ String stats = row.text();
+ stats = stats.replace(title, "").replace(subtitle, "").trim();
+ parsedDownloads.add(new Download(type, url, title, subtitle, stats,
+ false, null));
+ }
+ } else {
+ String stats = row.text();
+ stats = stats.replace(title, "").replace(subtitle, "").trim();
+ parsedDownloads.add(new Download(type, url, title, subtitle, stats,
+ false, null));
+ }
+ }
+ } else {
+ parsedDownloads.add(new Download(type,
+ rows.select("b>a").first().attr("href"),
+ rows.select("b>a").first().text(),
+ rows.select("div.smalltext:not(:has(a))").text(),
+ rows.select("span:not(:has(a))").first().text(),
+ false,
+ rows.select("span:has(a)").first().html()));
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
new file mode 100644
index 00000000..8abfdf55
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
@@ -0,0 +1,181 @@
+package gr.thmmy.mthmmy.activities.downloads;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+import gr.thmmy.mthmmy.R;
+import gr.thmmy.mthmmy.model.Download;
+import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
+
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
+import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
+
+class DownloadsAdapter extends RecyclerView.Adapter {
+ /**
+ * Debug Tag for logging debug output to LogCat
+ */
+ @SuppressWarnings("unused")
+ private static final String TAG = "DownloadsAdapter";
+ private final int VIEW_TYPE_DOWNLOAD = 0;
+ private final int VIEW_TYPE_LOADING = 1;
+
+ private final Context context;
+ private ArrayList parsedDownloads = new ArrayList<>();
+ private final ArrayList downloadExpandableVisibility = new ArrayList<>();
+
+ DownloadsAdapter(Context context, ArrayList parsedDownloads) {
+ this.context = context;
+ this.parsedDownloads = parsedDownloads;
+ }
+
+ interface OnLoadMoreListener {
+ void onLoadMore();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return (parsedDownloads.get(position) == null) ? VIEW_TYPE_LOADING : VIEW_TYPE_DOWNLOAD;
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (viewType == VIEW_TYPE_DOWNLOAD) {
+ View download = LayoutInflater.from(parent.getContext()).
+ inflate(R.layout.activity_downloads_row, parent, false);
+ return new DownloadViewHolder(download);
+ } else if (viewType == VIEW_TYPE_LOADING) {
+ View loading = LayoutInflater.from(parent.getContext()).
+ inflate(R.layout.recycler_loading_item, parent, false);
+ return new LoadingViewHolder(loading);
+ }
+ return null;
+ }
+
+ @Override
+ public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
+ if (holder instanceof DownloadViewHolder) {
+ final Download download = parsedDownloads.get(position);
+ final DownloadViewHolder downloadViewHolder = (DownloadViewHolder) holder;
+
+ if (downloadExpandableVisibility.size() != parsedDownloads.size()) {
+ for (int i = downloadExpandableVisibility.size(); i < parsedDownloads.size(); ++i)
+ downloadExpandableVisibility.add(false);
+ }
+
+ if (download.getType() == Download.DownloadItemType.DOWNLOADS_CATEGORY) {
+ downloadViewHolder.downloadRow.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(context, DownloadsActivity.class);
+ Bundle extras = new Bundle();
+ extras.putString(BUNDLE_DOWNLOADS_URL, download.getUrl());
+ extras.putString(BUNDLE_DOWNLOADS_TITLE, download.getTitle());
+ intent.putExtras(extras);
+ intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+ });
+
+ if (downloadExpandableVisibility.get(downloadViewHolder.getAdapterPosition())) {
+ downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
+ downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up);
+ } else {
+ downloadViewHolder.informationExpandable.setVisibility(View.GONE);
+ downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down);
+ }
+ downloadViewHolder.informationExpandableBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ final boolean visible = downloadExpandableVisibility.get(downloadViewHolder.
+ getAdapterPosition());
+ if (visible) {
+ downloadViewHolder.informationExpandable.setVisibility(View.GONE);
+ downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_down);
+ } else {
+ downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
+ downloadViewHolder.informationExpandableBtn.setImageResource(R.drawable.ic_arrow_drop_up);
+ }
+ downloadExpandableVisibility.set(downloadViewHolder.getAdapterPosition(), !visible);
+ }
+ });
+ downloadViewHolder.title.setTypeface(Typeface.createFromAsset(context.getAssets()
+ , "fonts/fontawesome-webfont.ttf"));
+ if (download.hasSubCategory()) {
+ String tmp = context.getResources().getString(R.string.fa_folder) + " "
+ + download.getTitle();
+ downloadViewHolder.title.setText(tmp);
+ } else {
+ String tmp = context.getResources().getString(R.string.fa_file) + " "
+ + download.getTitle();
+ downloadViewHolder.title.setText(tmp);
+ }
+ } else {
+ //TODO implement download on click
+
+ downloadViewHolder.upperLinear.setBackgroundColor(context.getResources().getColor(R.color.background));
+ downloadViewHolder.informationExpandable.setVisibility(View.VISIBLE);
+ downloadViewHolder.informationExpandableBtn.setVisibility(View.GONE);
+ downloadViewHolder.informationExpandableBtn.setEnabled(false);
+ downloadViewHolder.title.setText(download.getTitle());
+ }
+
+ downloadViewHolder.subTitle.setText(download.getSubTitle());
+ String tmp = download.getExtraInfo();
+ if (tmp != null && !Objects.equals(tmp, ""))
+ downloadViewHolder.extraInfo.setText(tmp);
+ else downloadViewHolder.extraInfo.setVisibility(View.GONE);
+ tmp = download.getStatNumbers();
+ if (tmp != null && !Objects.equals(tmp, ""))
+ downloadViewHolder.uploaderDate.setText(tmp);
+ else downloadViewHolder.uploaderDate.setVisibility(View.GONE);
+ } else if (holder instanceof LoadingViewHolder) {
+ LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
+ loadingViewHolder.progressBar.setIndeterminate(true);
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return parsedDownloads.size();
+ }
+
+ private static class DownloadViewHolder extends RecyclerView.ViewHolder {
+ final LinearLayout upperLinear, downloadRow, informationExpandable;
+ final TextView title, subTitle, extraInfo, uploaderDate;
+ final ImageButton informationExpandableBtn;
+
+ DownloadViewHolder(View download) {
+ super(download);
+ upperLinear = (LinearLayout) download.findViewById(R.id.upper_linear);
+ downloadRow = (LinearLayout) download.findViewById(R.id.download_row);
+ informationExpandable = (LinearLayout) download.findViewById(R.id.child_board_expandable);
+ title = (TextView) download.findViewById(R.id.download_title);
+ subTitle = (TextView) download.findViewById(R.id.download_sub_title);
+ extraInfo = (TextView) download.findViewById(R.id.download_extra_info);
+ uploaderDate = (TextView) download.findViewById(R.id.download_uploader_date);
+ informationExpandableBtn = (ImageButton) download.findViewById(R.id.download_information_button);
+ }
+ }
+
+ private static class LoadingViewHolder extends RecyclerView.ViewHolder {
+ final MaterialProgressBar progressBar;
+
+ LoadingViewHolder(View itemView) {
+ super(itemView);
+ progressBar = (MaterialProgressBar) itemView.findViewById(R.id.recycler_progress_bar);
+ }
+ }
+}
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 789bcfe4..d99f7d65 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
@@ -248,11 +248,13 @@ public class StatsFragment extends Fragment {
postingActivityByTimeChartXAxis.setGranularity(1f);
LineDataSet postingActivityByTimeDataSet = new LineDataSet(postingActivityByTime, null);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- postingActivityByTimeDataSet.setFillDrawable(getResources().getDrawable(R.drawable.line_chart_gradient, null));
- } else
- //noinspection deprecation
- postingActivityByTimeDataSet.setFillDrawable(getResources().getDrawable(R.drawable.line_chart_gradient));
+ if (isAdded()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ postingActivityByTimeDataSet.setFillDrawable(getResources().getDrawable(R.drawable.line_chart_gradient, null));
+ } else
+ //noinspection deprecation
+ postingActivityByTimeDataSet.setFillDrawable(getResources().getDrawable(R.drawable.line_chart_gradient));
+ }
postingActivityByTimeDataSet.setDrawFilled(true);
postingActivityByTimeDataSet.setDrawCircles(false);
postingActivityByTimeDataSet.setDrawValues(false);
@@ -285,11 +287,13 @@ public class StatsFragment extends Fragment {
mostPopularBoardsByPostsChartYAxis.setGranularity(1f);
BarDataSet mostPopularBoardsByPostsDataSet = new BarDataSet(mostPopularBoardsByPosts, null);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent, null));
- } else
- //noinspection deprecation
- mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent));
+ if (isAdded()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent, null));
+ } else
+ //noinspection deprecation
+ mostPopularBoardsByPostsDataSet.setColors(getResources().getColor(R.color.accent));
+ }
mostPopularBoardsByPostsDataSet.setDrawValues(false);
mostPopularBoardsByPostsDataSet.setValueTextColor(Color.WHITE);
@@ -324,11 +328,13 @@ public class StatsFragment extends Fragment {
mostPopularBoardsByActivityChartYAxis.setLabelCount(10, false);
BarDataSet mostPopularBoardsByActivityDataSet = new BarDataSet(mostPopularBoardsByActivity, null);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent, null));
- } else
- //noinspection deprecation
- mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent));
+ if (isAdded()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent, null));
+ } else
+ //noinspection deprecation
+ mostPopularBoardsByActivityDataSet.setColors(getResources().getColor(R.color.accent));
+ }
mostPopularBoardsByActivityDataSet.setDrawValues(false);
mostPopularBoardsByActivityDataSet.setValueTextColor(Color.WHITE);
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 c621f295..97d7f1e8 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
@@ -187,11 +187,12 @@ public class SummaryFragment extends Fragment {
}
TextView entry = new TextView(this.getContext());
- 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 (isAdded()) {
+ 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));
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 3da819cb..b940cda7 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
@@ -9,7 +9,6 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
@@ -63,7 +62,6 @@ public class TopicActivity extends BaseActivity {
*/
public static final String BUNDLE_TOPIC_TITLE = "TOPIC_TITLE";
private static final int PERMISSIONS_REQUEST_CODE = 69;
- static boolean readWriteAccepted;
private static TopicTask topicTask;
//About posts
private TopicAdapter topicAdapter;
@@ -213,7 +211,7 @@ public class TopicActivity extends BaseActivity {
topicTask.cancel(true);
}
- @Override
+ /*@Override
public void onRequestPermissionsResult(int permsRequestCode, @NonNull String[] permissions
, @NonNull int[] grantResults) {
switch (permsRequestCode) {
@@ -221,18 +219,20 @@ public class TopicActivity extends BaseActivity {
readWriteAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
break;
}
- }
+ }*/
- private void requestPerms() { //Runtime permissions for devices with API >= 23
+ boolean requestPerms() { //Runtime permissions request for devices with API >= 23
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
- checkSelfPermission(PERMISSIONS_STORAGE[0]);
- checkSelfPermission(PERMISSIONS_STORAGE[1]);
- requestPermissions(PERMISSIONS_STORAGE, PERMISSIONS_REQUEST_CODE);
- } else readWriteAccepted = true;
+ if (checkSelfPermission(PERMISSIONS_STORAGE[0]) == PackageManager.PERMISSION_DENIED ||
+ checkSelfPermission(PERMISSIONS_STORAGE[1]) == PackageManager.PERMISSION_DENIED) {
+ requestPermissions(PERMISSIONS_STORAGE, PERMISSIONS_REQUEST_CODE);
+ return false;
+ } else return true;
+ } else return true;
}
//--------------------------------------BOTTOM NAV BAR METHODS----------------------------------
@@ -365,6 +365,7 @@ public class TopicActivity extends BaseActivity {
private static final int OTHER_ERROR = 2;
private static final int SAME_PAGE = 3;
+ @Override
protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE);
paginationEnabled(false);
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
index 05a2779f..ad96703d 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
@@ -243,7 +243,7 @@ class TopicAdapter extends RecyclerView.Adapter {
attached.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- if (TopicActivity.readWriteAccepted) {
+ if (((TopicActivity) context).requestPerms()) {
downloadTask = new DownloadTask();
downloadTask.execute(attachedFile);
} else
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 8760198d..1f893856 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
@@ -24,18 +24,20 @@ import com.mikepenz.materialdrawer.model.interfaces.IProfile;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.AboutActivity;
import gr.thmmy.mthmmy.activities.LoginActivity;
+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.session.SessionManager;
import okhttp3.OkHttpClient;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
+import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_USERNAME;
-public abstract class BaseActivity extends AppCompatActivity
-{
+public abstract class BaseActivity extends AppCompatActivity {
// Client & Cookies
protected static OkHttpClient client;
@@ -49,10 +51,10 @@ public abstract class BaseActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if(client==null)
+ if (client == null)
client = BaseApplication.getInstance().getClient(); //must check every time - e.g.
// they become null when app restarts after crash
- if(sessionManager==null)
+ if (sessionManager == null)
sessionManager = BaseApplication.getInstance().getSessionManager();
}
@@ -65,27 +67,25 @@ public abstract class BaseActivity extends AppCompatActivity
@Override
protected void onPause() {
super.onPause();
- if(drawer!=null) //close drawer animation after returning to activity
+ if (drawer != null) //close drawer animation after returning to activity
drawer.closeDrawer();
}
- public static OkHttpClient getClient()
- {
+ public static OkHttpClient getClient() {
return client;
}
- public static SessionManager getSessionManager()
- {
+ public static SessionManager getSessionManager() {
return sessionManager;
}
//TODO: move stuff below (?)
//------------------------------------------DRAWER STUFF----------------------------------------
- protected static final int HOME_ID=0;
- protected static final int DOWNLOADS_ID=1;
- protected static final int LOG_ID =2;
- protected static final int ABOUT_ID=3;
+ protected static final int HOME_ID = 0;
+ protected static final int DOWNLOADS_ID = 1;
+ protected static final int LOG_ID = 2;
+ protected static final int ABOUT_ID = 3;
private AccountHeader accountHeader;
private ProfileDrawerItem profileDrawerItem;
@@ -96,42 +96,41 @@ public abstract class BaseActivity extends AppCompatActivity
/**
* Call only after initializing Toolbar
*/
- protected void createDrawer()
- {
+ protected void createDrawer() {
final int primaryColor = ContextCompat.getColor(this, R.color.iron);
final int selectedPrimaryColor = ContextCompat.getColor(this, R.color.primary_dark);
final int selectedSecondaryColor = ContextCompat.getColor(this, R.color.accent);
//Drawer Icons
- homeIcon =new IconicsDrawable(this)
+ homeIcon = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_home)
.color(primaryColor);
- homeIconSelected =new IconicsDrawable(this)
+ homeIconSelected = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_home)
.color(selectedSecondaryColor);
- downloadsIcon =new IconicsDrawable(this)
+ downloadsIcon = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_download)
.color(primaryColor);
- downloadsIconSelected =new IconicsDrawable(this)
+ downloadsIconSelected = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_download)
.color(selectedSecondaryColor);
- loginIcon =new IconicsDrawable(this)
+ loginIcon = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_sign_in)
.color(primaryColor);
- logoutIcon =new IconicsDrawable(this)
+ logoutIcon = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_sign_out)
.color(primaryColor);
- aboutIcon =new IconicsDrawable(this)
+ aboutIcon = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_info_circle)
.color(primaryColor);
- aboutIconSelected =new IconicsDrawable(this)
+ aboutIconSelected = new IconicsDrawable(this)
.icon(FontAwesome.Icon.faw_info_circle)
.color(selectedSecondaryColor);
@@ -146,7 +145,6 @@ public abstract class BaseActivity extends AppCompatActivity
.withSelectedIcon(homeIconSelected);
-
if (sessionManager.isLoggedIn()) //When logged in
{
loginLogoutItem = new PrimaryDrawerItem()
@@ -164,8 +162,7 @@ public abstract class BaseActivity extends AppCompatActivity
.withName(R.string.downloads)
.withIcon(downloadsIcon)
.withSelectedIcon(downloadsIconSelected);
- }
- else
+ } else
loginLogoutItem = new PrimaryDrawerItem()
.withTextColor(primaryColor)
.withSelectedColor(selectedSecondaryColor)
@@ -195,12 +192,11 @@ public abstract class BaseActivity extends AppCompatActivity
.withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
@Override
public boolean onProfileChanged(View view, IProfile profile, boolean currentProfile) {
- if(sessionManager.isLoggedIn())
- {
+ if (sessionManager.isLoggedIn()) {
Intent intent = new Intent(BaseActivity.this, ProfileActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, "https://www.thmmy.gr/smf/index.php?action=profile");
- if(!sessionManager.hasAvatar())
+ if (!sessionManager.hasAvatar())
extras.putString(BUNDLE_THUMBNAIL_URL, "");
else
extras.putString(BUNDLE_THUMBNAIL_URL, sessionManager.getAvatarLink());
@@ -220,44 +216,38 @@ public abstract class BaseActivity extends AppCompatActivity
DrawerBuilder drawerBuilder = new DrawerBuilder()
.withActivity(this)
.withToolbar(toolbar)
- .withDrawerWidthDp((int)BaseApplication.getInstance().getDpWidth()/2)
+ .withDrawerWidthDp((int) BaseApplication.getInstance().getDpWidth() / 2)
.withSliderBackgroundColor(ContextCompat.getColor(this, R.color.primary_light))
.withAccountHeader(accountHeader)
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
@Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
- if(drawerItem.equals(HOME_ID))
- {
- if(!(BaseActivity.this instanceof MainActivity))
- {
+ if (drawerItem.equals(HOME_ID)) {
+ if (!(BaseActivity.this instanceof MainActivity)) {
Intent i = new Intent(BaseActivity.this, MainActivity.class);
startActivity(i);
}
- }
-// else if(drawerItem.equals(DOWNLOADS_ID))
-// {
-// if (sessionManager.isLoggedIn()) //When logged out or if user is guest
-// {
-// Intent i = new Intent(BaseActivity.this, DownloadsActivity.class);
-// startActivity(i);
-// }
-// }
- else if(drawerItem.equals(LOG_ID))
- {
+ } else if (drawerItem.equals(DOWNLOADS_ID)) {
+ if (sessionManager.isLoggedIn()) //When logged out or if user is guest
+ {
+ Intent i = new Intent(BaseActivity.this, DownloadsActivity.class);
+ Bundle extras = new Bundle();
+ extras.putString(BUNDLE_DOWNLOADS_URL, "");
+ extras.putString(BUNDLE_DOWNLOADS_TITLE, null);
+ i.putExtras(extras);
+ startActivity(i);
+ }
+ } else if (drawerItem.equals(LOG_ID)) {
if (!sessionManager.isLoggedIn()) //When logged out or if user is guest
{
Intent intent = new Intent(BaseActivity.this, LoginActivity.class);
startActivity(intent);
finish();
overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out);
- }
- else
+ } else
new LogoutTask().execute();
- }
- else if(drawerItem.equals(ABOUT_ID))
- {
- if(!(BaseActivity.this instanceof AboutActivity))
- {
+ } else if (drawerItem.equals(ABOUT_ID)) {
+ if (!(BaseActivity.this instanceof AboutActivity)) {
Intent i = new Intent(BaseActivity.this, AboutActivity.class);
startActivity(i);
}
@@ -269,10 +259,10 @@ public abstract class BaseActivity extends AppCompatActivity
}
});
- if(sessionManager.isLoggedIn())
- drawerBuilder.addDrawerItems(homeItem,downloadsItem,loginLogoutItem,aboutItem);
+ if (sessionManager.isLoggedIn())
+ drawerBuilder.addDrawerItems(homeItem, downloadsItem, loginLogoutItem, aboutItem);
else
- drawerBuilder.addDrawerItems(homeItem,loginLogoutItem,aboutItem);
+ drawerBuilder.addDrawerItems(homeItem, loginLogoutItem, aboutItem);
drawer = drawerBuilder.build();
@@ -286,10 +276,8 @@ public abstract class BaseActivity extends AppCompatActivity
});
}
- protected void updateDrawer()
- {
- if(drawer!=null)
- {
+ protected void updateDrawer() {
+ if (drawer != null) {
if (!sessionManager.isLoggedIn()) //When logged out or if user is guest
{
drawer.removeItem(DOWNLOADS_ID);
@@ -299,9 +287,7 @@ public abstract class BaseActivity extends AppCompatActivity
.paddingDp(10)
.color(ContextCompat.getColor(this, R.color.primary_light))
.backgroundColor(ContextCompat.getColor(this, R.color.primary)));
- }
- else
- {
+ } else {
loginLogoutItem.withName(R.string.logout).withIcon(logoutIcon); //Swap login with logout
profileDrawerItem.withName(sessionManager.getUsername()).withIcon(sessionManager.getAvatarLink());
}
@@ -313,9 +299,10 @@ public abstract class BaseActivity extends AppCompatActivity
//-------------------------------------------LOGOUT-------------------------------------------------
+
/**
- * Result toast will always display a success, because when user chooses logout all data are
- * cleared regardless of the actual outcome
+ * Result toast will always display a success, because when user chooses logout all data are
+ * cleared regardless of the actual outcome
*/
protected class LogoutTask extends AsyncTask { //Attempt logout
ProgressDialog progressDialog;
@@ -324,8 +311,7 @@ public abstract class BaseActivity extends AppCompatActivity
return sessionManager.logout();
}
- protected void onPreExecute()
- { //Show a progress dialog until done
+ protected void onPreExecute() { //Show a progress dialog until done
progressDialog = new ProgressDialog(BaseActivity.this,
R.style.AppTheme_Dark_Dialog);
progressDialog.setCancelable(false);
@@ -334,8 +320,7 @@ public abstract class BaseActivity extends AppCompatActivity
progressDialog.show();
}
- protected void onPostExecute(Integer result)
- {
+ protected void onPostExecute(Integer result) {
Toast.makeText(getBaseContext(), "Logged out successfully!", Toast.LENGTH_LONG).show();
updateDrawer();
progressDialog.dismiss();
diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/Download.java b/app/src/main/java/gr/thmmy/mthmmy/model/Download.java
new file mode 100644
index 00000000..5216fea4
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/model/Download.java
@@ -0,0 +1,58 @@
+package gr.thmmy.mthmmy.model;
+
+public class Download {
+ public enum DownloadItemType {DOWNLOADS_CATEGORY, DOWNLOADS_FILE}
+
+ private final String url, title, subTitle, statNumbers, extraInfo;
+ private final boolean hasSubCategory;
+ private final DownloadItemType type;
+
+ public Download() {
+ type = null;
+ url = null;
+ title = null;
+ subTitle = null;
+ statNumbers = null;
+ hasSubCategory = false;
+ extraInfo = null;
+ }
+
+ public Download(DownloadItemType type, String url, String title, String subTitle,
+ String statNumbers, boolean hasSubCategory, String extraInfo) {
+ this.type = type;
+ this.url = url;
+ this.title = title;
+ this.subTitle = subTitle;
+ this.statNumbers = statNumbers;
+ this.hasSubCategory = hasSubCategory;
+ this.extraInfo = extraInfo;
+ }
+
+ public DownloadItemType getType() {
+ return type;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getSubTitle() {
+ return subTitle;
+ }
+
+ public String getStatNumbers() {
+ return statNumbers;
+ }
+
+ public String getExtraInfo() {
+ return extraInfo;
+ }
+
+ public boolean hasSubCategory() {
+ return hasSubCategory;
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java b/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java
index 4a112d2a..991c79bb 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/model/LinkTarget.java
@@ -72,7 +72,19 @@ public class LinkTarget {
/**
* Link points to a profile.
*/
- PROFILE;
+ PROFILE,
+ /**
+ * Link points to a download.
+ */
+ DOWNLOADS_CATEGORY,
+ /**
+ * Link points to a download category.
+ */
+ DOWNLOADS_FILE,
+ /**
+ * Link points to downloads.
+ */
+ DOWNLOADS;
/**
* This method defines a custom equality check for {@link Target} enums. It does not check
@@ -81,19 +93,23 @@ public class LinkTarget {
* cases described below, false otherwise.
* - (Everything but {@link #NOT_THMMY}).is({@link #THMMY}) returns true
* - {@link #PROFILE_SUMMARY}.is({@link #PROFILE}) returns true
- * - {@link #PROFILE_LATEST_POSTS}.is({@link #PROFILE}) returns true
- * - {@link #PROFILE_STATS}.is({@link #PROFILE}) returns true
* - {@link #PROFILE}.is({@link #PROFILE_SUMMARY}) returns false
+ * - {@link #PROFILE_LATEST_POSTS}.is({@link #PROFILE}) returns true
* - {@link #PROFILE}.is({@link #PROFILE_LATEST_POSTS}) returns false
- * - {@link #PROFILE}.is({@link #PROFILE_STATS}) returns false
+ * {@link #PROFILE_STATS}.is({@link #PROFILE}) returns true
+ * {@link #PROFILE}.is({@link #PROFILE_STATS}) returns false
+ * {@link #DOWNLOADS_CATEGORY}.is({@link #DOWNLOADS}) returns true
+ * {@link #DOWNLOADS}.is({@link #DOWNLOADS_CATEGORY}) returns false
+ * {@link #DOWNLOADS_FILE}.is({@link #DOWNLOADS}) returns true
+ * {@link #DOWNLOADS}.is({@link #DOWNLOADS_FILE}) returns false
*
* @param other another Target
* @return true if enums are equal, false otherwise
*/
public boolean is(Target other) {
- return (this == PROFILE_LATEST_POSTS ||
- this == PROFILE_STATS ||
- this == PROFILE_SUMMARY) && other == PROFILE
+ return ((this == PROFILE_LATEST_POSTS || this == PROFILE_STATS || this == PROFILE_SUMMARY)
+ && other == PROFILE)
+ || ((this == DOWNLOADS_FILE || this == DOWNLOADS_CATEGORY) && other == DOWNLOADS)
|| (this != NOT_THMMY && other == THMMY)
|| this == other;
}
@@ -130,6 +146,10 @@ public class LinkTarget {
else return Target.PROFILE_SUMMARY;
} else if (uriString.contains("action=unread"))
return Target.UNREAD_POSTS;
+ else if (uriString.contains("action=tpmod;dl=item"))
+ return Target.DOWNLOADS_FILE;
+ else if (uriString.contains("action=tpmod;dl"))
+ return Target.DOWNLOADS_CATEGORY;
Report.v(TAG, "Unknown thmmy link found, link: " + uriString);
return Target.UNKNOWN_THMMY;
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/FileManager/ThmmyFile.java b/app/src/main/java/gr/thmmy/mthmmy/utils/FileManager/ThmmyFile.java
index 5de8cbc8..eed84689 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/utils/FileManager/ThmmyFile.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/utils/FileManager/ThmmyFile.java
@@ -164,7 +164,6 @@ public class ThmmyFile {
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
} catch (IllegalStateException e) {
Report.d(TAG, "External directory not available!", e);
- Log.d(TAG, "External directory not available!", e);
throw e;
}
diff --git a/app/src/main/res/drawable/ic_file_upload.xml b/app/src/main/res/drawable/ic_file_upload.xml
new file mode 100644
index 00000000..74f3b4ca
--- /dev/null
+++ b/app/src/main/res/drawable/ic_file_upload.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/layout/activity_downloads.xml b/app/src/main/res/layout/activity_downloads.xml
new file mode 100644
index 00000000..3547d5ea
--- /dev/null
+++ b/app/src/main/res/layout/activity_downloads.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_downloads_row.xml b/app/src/main/res/layout/activity_downloads_row.xml
new file mode 100644
index 00000000..f4fd93b5
--- /dev/null
+++ b/app/src/main/res/layout/activity_downloads_row.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2b469a93..dccbf7e3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -81,4 +81,5 @@
+