Browse Source

In-app link handling fixes, bigger progress bars, FABs and navBar behavior changes, attached files downloading fixes for internal storage.

pull/24/head
Apostolos Fanakis 8 years ago
parent
commit
d217c2ad00
  1. 4
      app/build.gradle
  2. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
  3. 21
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java
  4. 11
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  5. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  6. 71
      app/src/main/java/gr/thmmy/mthmmy/utils/FileManager/ThmmyFile.java
  7. 3
      app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java
  8. 8
      app/src/main/java/gr/thmmy/mthmmy/utils/ScrollAwareFABBehavior.java
  9. 9
      app/src/main/java/gr/thmmy/mthmmy/utils/ScrollAwareLinearBehavior.java
  10. 2
      app/src/main/res/layout-v21/activity_profile.xml
  11. 2
      app/src/main/res/layout/activity_board.xml
  12. 2
      app/src/main/res/layout/activity_profile.xml
  13. 2
      app/src/main/res/layout/activity_topic.xml
  14. 10
      app/src/main/res/layout/fragment_forum.xml
  15. 2
      app/src/main/res/layout/fragment_latest_posts.xml
  16. 10
      app/src/main/res/layout/fragment_recent.xml
  17. 2
      app/src/main/res/layout/fragment_stats.xml
  18. 1
      app/src/main/res/values-w820dp/dimens.xml
  19. 1
      app/src/main/res/values/dimens.xml

4
app/build.gradle

@ -9,8 +9,8 @@ android {
applicationId "gr.thmmy.mthmmy"
minSdkVersion 19
targetSdkVersion 25
versionCode 1
versionName "1.0.0"
versionCode 2
versionName "1.0.1"
archivesBaseName = "mTHMMY-v$versionName"
}

8
app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java

@ -2,6 +2,7 @@ package gr.thmmy.mthmmy.activities.board;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
@ -28,6 +29,7 @@ import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.LoginActivity;
import gr.thmmy.mthmmy.activities.base.BaseActivity;
import gr.thmmy.mthmmy.model.Board;
import gr.thmmy.mthmmy.model.LinkTarget;
import gr.thmmy.mthmmy.model.Topic;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import mthmmy.utils.Report;
@ -74,6 +76,12 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
Bundle extras = getIntent().getExtras();
boardTitle = extras.getString(BUNDLE_BOARD_TITLE);
boardUrl = extras.getString(BUNDLE_BOARD_URL);
LinkTarget.Target target = LinkTarget.resolveLinkTarget(Uri.parse(boardUrl));
if (!target.is(LinkTarget.Target.BOARD)) {
Report.e(TAG, "Bundle came with a non board url!\nUrl:\n" + boardUrl);
Toast.makeText(this, "An error has occurred\nAborting.", Toast.LENGTH_SHORT).show();
finish();
}
//Initializes graphics
toolbar = (Toolbar) findViewById(R.id.toolbar);

21
app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java

@ -2,6 +2,7 @@ package gr.thmmy.mthmmy.activities.profile;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
@ -38,6 +39,7 @@ import gr.thmmy.mthmmy.activities.profile.latestPosts.LatestPostsFragment;
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.model.LinkTarget;
import gr.thmmy.mthmmy.model.PostSummary;
import gr.thmmy.mthmmy.utils.CircleTransform;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
@ -86,6 +88,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
private String personalText;
private String profileUrl;
private String username;
private int tabSelect;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -162,6 +165,20 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
});
}
LinkTarget.Target target = LinkTarget.resolveLinkTarget(Uri.parse(profileUrl));
if (!target.is(LinkTarget.Target.PROFILE)) {
Report.e(TAG, "Bundle came with a non profile url!\nUrl:\n" + profileUrl);
Toast.makeText(this, "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show();
finish();
}
if (target.is(LinkTarget.Target.PROFILE_STATS)) {
profileUrl = profileUrl.substring(0, profileUrl.indexOf(";sa=statPanel"));
tabSelect = 2;
} else if (target.is(LinkTarget.Target.PROFILE_LATEST_POSTS)) {
profileUrl = profileUrl.substring(0, profileUrl.indexOf(";sa=showPosts"));
tabSelect = 1;
}
profileTask = new ProfileTask();
profileTask.execute(profileUrl); //Attempts data parsing
}
@ -258,6 +275,10 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
setupViewPager(viewPager, profilePage);
TabLayout tabLayout = (TabLayout) findViewById(R.id.profile_tabs);
tabLayout.setupWithViewPager(viewPager);
if (tabSelect != 0) {
TabLayout.Tab tab = tabLayout.getTabAt(tabSelect);
if (tab != null) tab.select();
}
}
}

11
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java

@ -2,6 +2,7 @@ package gr.thmmy.mthmmy.activities.topic;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
@ -28,6 +29,7 @@ import java.util.Objects;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.LoginActivity;
import gr.thmmy.mthmmy.activities.base.BaseActivity;
import gr.thmmy.mthmmy.model.LinkTarget;
import gr.thmmy.mthmmy.model.Post;
import gr.thmmy.mthmmy.utils.ParseHelpers;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
@ -99,7 +101,14 @@ public class TopicActivity extends BaseActivity {
setContentView(R.layout.activity_topic);
Bundle extras = getIntent().getExtras();
topicTitle = extras.getString("TOPIC_TITLE");
topicTitle = extras.getString(BUNDLE_TOPIC_TITLE);
LinkTarget.Target target = LinkTarget.resolveLinkTarget(
Uri.parse(extras.getString(BUNDLE_TOPIC_URL)));
if (!target.is(LinkTarget.Target.TOPIC)) {
Report.e(TAG, "Bundle came with a non topic url!\nUrl:\n" + extras.getString(BUNDLE_TOPIC_URL));
Toast.makeText(this, "An error has occurred\n Aborting.", Toast.LENGTH_SHORT).show();
finish();
}
//Initializes graphics
toolbar = (Toolbar) findViewById(R.id.toolbar);

8
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java

@ -16,6 +16,7 @@ import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@ -632,7 +633,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
@Override
protected String doInBackground(ThmmyFile... files) {
try {
File tempFile = files[0].download();
File tempFile = files[0].download(context);
if (tempFile != null) {
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
files[0].getExtension());
@ -646,6 +647,9 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
} catch (IOException e) {
Report.e(TAG, "Error while trying to download a file", e);
return e.toString();
} catch (OutOfMemoryError e) {
Report.e(TAG, "Error while trying to download a file", e);
return e.toString();
}
return null;
}
@ -654,7 +658,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
protected void onPostExecute(String result) {
mWakeLock.release();
if (result != null)
Toast.makeText(context, "Error! Download not complete.", Toast.LENGTH_SHORT).show();
Toast.makeText(context, result, Toast.LENGTH_SHORT).show();
else
Toast.makeText(context, "Download complete", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.INVISIBLE);

71
app/src/main/java/gr/thmmy/mthmmy/utils/FileManager/ThmmyFile.java

@ -1,6 +1,8 @@
package gr.thmmy.mthmmy.utils.FileManager;
import android.content.Context;
import android.os.Environment;
import android.os.StatFs;
import android.support.annotation.Nullable;
import android.webkit.MimeTypeMap;
@ -18,10 +20,7 @@ import static gr.thmmy.mthmmy.activities.base.BaseActivity.getClient;
/**
* Used for downloading and storing a file from the forum using {@link okhttp3}.
* <p>Class has one constructor: <ul><li>{@link #ThmmyFile(URL, String, String)}</li></ul>
* and the methods:<ul><li>getters</li>
* <li>{@link #download()}</li>
* <li>{@link #download()}</li></ul></p>
* <p>Class has one constructor, {@link #ThmmyFile(URL, String, String)}.
*/
public class ThmmyFile {
/**
@ -33,9 +32,22 @@ public class ThmmyFile {
private String extension, filePath;
private File file;
/**
* This constructor only creates a empty ThmmyFile object and <b>does not download</b> the file. To download
* the file use {@link #download(Context)} after setting file's url!
*/
public ThmmyFile() {
this.fileUrl = null;
this.filename = null;
this.fileInfo = null;
this.extension = null;
this.filePath = null;
this.file = null;
}
/**
* This constructor only creates a ThmmyFile object and <b>does not download</b> the file. To download
* the file use {@link #download()} or {@link #download()}!
* the file use {@link #download(Context)}!
*
* @param fileUrl {@link URL} object with file's url
* @param filename {@link String} with desired file name
@ -63,7 +75,7 @@ public class ThmmyFile {
}
/**
* This is null until {@link #download()} or {@link #download()} is called and has succeeded.
* This is null until {@link #download(Context)} is called and has succeeded.
*
* @return String with file's extension or null
*/
@ -73,7 +85,7 @@ public class ThmmyFile {
}
/**
* This is null until {@link #download()} or {@link #download()} is called and has succeeded.
* This is null until {@link #download(Context)} is called and has succeeded.
*
* @return String with file's path or null
*/
@ -83,7 +95,7 @@ public class ThmmyFile {
}
/**
* This is null until {@link #download()} or {@link #download()} is called and has succeeded.
* This is null until {@link #download(Context)} is called and has succeeded.
*
* @return {@link File} or null
*/
@ -112,7 +124,10 @@ public class ThmmyFile {
* @throws SecurityException if the requested file is not hosted by the forum.
*/
@Nullable
public File download() throws IOException, SecurityException {
public File download(Context context) throws IOException, SecurityException, OutOfMemoryError {
if (fileUrl == null) {
return null;
}
if (!Objects.equals(fileUrl.getHost(), "www.thmmy.gr"))
throw new SecurityException("Downloading files from other sources is not supported");
@ -122,7 +137,7 @@ public class ThmmyFile {
if (!response.isSuccessful()) {
throw new IOException("Failed to download file: " + response);
}
file = getOutputMediaFile(filename);
file = getOutputMediaFile(context, filename, fileInfo);
if (file == null) {
Report.d(TAG, "Error creating media file, check storage permissions!");
} else {
@ -138,24 +153,40 @@ public class ThmmyFile {
}
@Nullable
private static File getOutputMediaFile(String fileName) {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
private File getOutputMediaFile(Context context, String fileName, String fileInfo) throws OutOfMemoryError, IOException {
File mediaStorageDir;
String extState = Environment.getExternalStorageState();
if (Environment.isExternalStorageRemovable() &&
Objects.equals(extState, Environment.MEDIA_MOUNTED)) {
mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/gr.thmmy.mthmmy/"
+ "Downloads/");
} else {
mediaStorageDir = new File(context.getFilesDir(), "Downloads");
}
// This location works best if you want the created files to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
//Creates the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Report.d(TAG, "problem!");
return null;
throw new IOException("Error.\nCouldn't create the path!");
}
}
// Create a media file name
if (fileInfo != null) {
if (fileInfo.contains("KB")) {
float fileSize = Float.parseFloat(fileInfo
.substring(fileInfo.indexOf("(") + 1, fileInfo.indexOf("KB") - 1));
StatFs stat = new StatFs(mediaStorageDir.getPath());
long bytesAvailable = stat.getBlockSizeLong() * stat.getAvailableBlocksLong();
if ((bytesAvailable / 1024.f) < fileSize)
throw new OutOfMemoryError("There is not enough memory!");
}
}
//Creates a media file name
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator + fileName);
return mediaFile;

3
app/src/main/java/gr/thmmy/mthmmy/utils/ParseHelpers.java

@ -119,6 +119,9 @@ public class ParseHelpers {
if (warning.text().contains("The topic or board you are looking for appears " +
"to be either missing or off limits to you."))
return UNAUTHORIZED_OR_MISSING;
else if (warning.text().contains("Το θέμα ή πίνακας που ψάχνετε ή δεν υπάρχει ή " +
"δεν είναι προσβάσιμο από εσάς. "))
return UNAUTHORIZED_OR_MISSING;
}
}
return READY;

8
app/src/main/java/gr/thmmy/mthmmy/utils/ScrollAwareFABBehavior.java

@ -13,6 +13,8 @@ import android.view.View;
*/
@SuppressWarnings("WeakerAccess")
public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
String TAG = "ScrollAwareFABBehavior";
@SuppressWarnings("UnusedParameters")
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super();
@ -30,7 +32,8 @@ public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingA
final View target, final int dxConsumed, final int dyConsumed,
final int dxUnconsumed, final int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
if ((dyConsumed > 0 || (!target.canScrollVertically(-1) && dyConsumed == 0
&& dyUnconsumed < 40)) && child.getVisibility() == View.VISIBLE) {
child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
@Override
public void onHidden(FloatingActionButton fab) {
@ -38,7 +41,8 @@ public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingA
fab.setVisibility(View.INVISIBLE);
}
});
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
} else if ((dyConsumed < 0 || (!target.canScrollVertically(1) && dyConsumed == 0
&& dyUnconsumed > 40)) && child.getVisibility() != View.VISIBLE) {
child.show();
}
}

9
app/src/main/java/gr/thmmy/mthmmy/utils/ScrollAwareLinearBehavior.java

@ -6,6 +6,7 @@ import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewPropertyAnimator;
@ -32,15 +33,18 @@ public class ScrollAwareLinearBehavior extends CoordinatorLayout.Behavior<View>
int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, bottomNavBar, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0 && bottomNavBar.getVisibility() == View.VISIBLE) {
if ((dyConsumed > 0 || (!target.canScrollVertically(-1) && dyConsumed == 0
&& dyUnconsumed < 40)) && bottomNavBar.getVisibility() == View.VISIBLE) {
hide(bottomNavBar);
} else if (dyConsumed < 0 && bottomNavBar.getVisibility() != View.VISIBLE) {
} else if ((dyConsumed < 0 || (!target.canScrollVertically(1) && dyConsumed == 0
&& dyUnconsumed > 40)) && bottomNavBar.getVisibility() != View.VISIBLE) {
show(bottomNavBar);
}
}
/**
* Animates the hiding of a bottom navigation bar.
*
* @param bottomNavBar bottom navigation bar View
*/
private void hide(final View bottomNavBar) {
@ -73,6 +77,7 @@ public class ScrollAwareLinearBehavior extends CoordinatorLayout.Behavior<View>
/**
* Animates the showing of a bottom navigation bar.
*
* @param bottomNavBar bottom navigation bar View
*/
private void show(final View bottomNavBar) {

2
app/src/main/res/layout-v21/activity_profile.xml

@ -98,7 +98,7 @@
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:indeterminate="true"
android:visibility="invisible"
app:layout_anchor="@id/profile_tab_container"

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

@ -40,7 +40,7 @@
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:indeterminate="true"
android:visibility="invisible"
app:layout_anchor="@id/appbar"

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

@ -97,7 +97,7 @@
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:indeterminate="true"
android:visibility="invisible"
app:layout_anchor="@id/profile_tab_container"

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

@ -94,7 +94,7 @@
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:indeterminate="true"
android:visibility="invisible"
app:layout_anchor="@id/appbar"

10
app/src/main/res/layout/fragment_forum.xml

@ -20,13 +20,13 @@
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:layout_alignParentTop="true"
app:mpb_indeterminateTint="@color/accent"
android:visibility="invisible"
android:indeterminate="true"
app:mpb_progressStyle="horizontal"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" />
android:visibility="invisible"
app:mpb_indeterminateTint="@color/accent"
app:mpb_progressStyle="horizontal"/>
</RelativeLayout>

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

@ -17,7 +17,7 @@
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:layout_alignParentTop="true"
android:indeterminate="true"
android:visibility="invisible"

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

@ -26,13 +26,13 @@
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:layout_alignParentTop="true"
app:mpb_indeterminateTint="@color/accent"
android:visibility="invisible"
android:indeterminate="true"
app:mpb_progressStyle="horizontal"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" />
android:visibility="invisible"
app:mpb_indeterminateTint="@color/accent"
app:mpb_progressStyle="horizontal"/>
</RelativeLayout>

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

@ -91,7 +91,7 @@
android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/progress_bar_height"
android:layout_alignParentTop="true"
android:indeterminate="true"
android:visibility="invisible"

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

@ -8,4 +8,5 @@
<dimen name="thumbnail_size">176dp</dimen>
<dimen name="quote_button">144dp</dimen>
<dimen name="fab_margins">64dp</dimen>
<dimen name="progress_bar_height">40dp</dimen>
</resources>

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

@ -6,4 +6,5 @@
<dimen name="thumbnail_size">44dp</dimen>
<dimen name="quote_button">36dp</dimen>
<dimen name="fab_margins">16dp</dimen>
<dimen name="progress_bar_height">10dp</dimen>
</resources>

Loading…
Cancel
Save