First commit
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
52
.idea/assetWizardSettings.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WizardSettings">
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="imageWizard">
|
||||
<value>
|
||||
<PersistentState />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="vectorWizard">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="vectorAssetStep">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipartAsset">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="url" value="jar:file:/home/alex/Android%20Studio/plugins/android/lib/android.jar!/images/material_design_icons/file/ic_file_download_black_24dp.xml" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="ffffff" />
|
||||
<entry key="outputName" value="ic_file_download_white_24dp" />
|
||||
<entry key="sourceFile" value="$USER_HOME$" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
BIN
.idea/caches/build_file_checksums.ser
Normal file
29
.idea/codeStyles/Project.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<Objective-C-extensions>
|
||||
<file>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||
</file>
|
||||
<class>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||
</class>
|
||||
<extensions>
|
||||
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
</code_scheme>
|
||||
</component>
|
18
.idea/gradle.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
34
.idea/misc.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="5">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
9
.idea/modules.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Infinity.iml" filepath="$PROJECT_DIR$/Infinity.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
12
.idea/runConfigurations.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
1
app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
48
app/build.gradle
Normal file
@ -0,0 +1,48 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "ml.docilealligator.infinityforreddit"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "http://dl.bintray.com/rilixtech/maven"
|
||||
}
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
|
||||
implementation 'com.android.support:design:28.0.0-alpha3'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||
implementation 'com.android.support:support-v4:28.0.0-alpha3'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
implementation 'com.android.volley:volley:1.1.0'
|
||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||
implementation 'com.google.android.exoplayer:exoplayer:2.7.0'
|
||||
implementation 'com.google.android.exoplayer:exoplayer-dash:2.7.0'
|
||||
implementation 'com.android.support:customtabs:28.0.0-alpha3'
|
||||
implementation 'com.alexvasilkov:gesture-views:2.5.2'
|
||||
implementation 'com.android.support:cardview-v7:28.0.0-alpha3'
|
||||
implementation 'com.github.bumptech.glide:glide:4.6.1'
|
||||
implementation 'com.github.pwittchen:swipe-rx2:0.3.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'
|
||||
}
|
21
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@ -0,0 +1,26 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("ml.docilealligator.infinityforreddit", appContext.getPackageName());
|
||||
}
|
||||
}
|
44
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="ml.docilealligator.infinityforreddit">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="22" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
android:label="@string/login_activity_label"
|
||||
android:parentActivityName=".MainActivity" />
|
||||
<activity
|
||||
android:name=".ViewImageActivity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:theme="@style/Theme.AppCompat.Transparent" />
|
||||
<activity
|
||||
android:name=".ViewVideoActivity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:theme="@style/Theme.AppCompat.Transparent" />
|
||||
<activity
|
||||
android:name=".ViewPostDetailActivity"
|
||||
android:parentActivityName=".MainActivity" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,86 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by alex on 3/13/18.
|
||||
*/
|
||||
|
||||
class AcquireAccessToken {
|
||||
|
||||
interface AcquireAccessTokenListener {
|
||||
void onAcquireAccessTokenSuccess();
|
||||
void onAcquireAccessTokenFail();
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private AcquireAccessTokenListener mAcquireAccessTokenListener;
|
||||
|
||||
AcquireAccessToken(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
void refreshAccessToken(RequestQueue refreshQueue, AcquireAccessTokenListener acquireAccessTokenListener) {
|
||||
if(mContext != null) {
|
||||
mAcquireAccessTokenListener = acquireAccessTokenListener;
|
||||
final String refreshToken = mContext.getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.REFRESH_TOKEN_KEY, "");
|
||||
StringRequest newTokenRequest = new StringRequest(Request.Method.POST, RedditUtils.ACQUIRE_ACCESS_TOKEN_URL, new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(response);
|
||||
String newAccessToken = jsonObject.getString(RedditUtils.ACCESS_TOKEN_KEY);
|
||||
|
||||
SharedPreferences.Editor editor = mContext.getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).edit();
|
||||
editor.putString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, newAccessToken);
|
||||
editor.apply();
|
||||
|
||||
mAcquireAccessTokenListener.onAcquireAccessTokenSuccess();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
mAcquireAccessTokenListener.onAcquireAccessTokenFail();
|
||||
Toast.makeText(mContext, "Error parsing JSON object when getting the access token", Toast.LENGTH_SHORT).show();
|
||||
Log.i("main activity", "Error parsing JSON object when getting the access token");
|
||||
}
|
||||
}
|
||||
}, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
Toast.makeText(mContext, "Error getting the new access token", Toast.LENGTH_SHORT).show();
|
||||
mAcquireAccessTokenListener.onAcquireAccessTokenFail();
|
||||
Log.i("error get access token", error.getMessage());
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(RedditUtils.GRANT_TYPE_KEY, RedditUtils.GRANT_TYPE_REFRESH_TOKEN);
|
||||
params.put(RedditUtils.REFRESH_TOKEN_KEY, refreshToken);
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() {
|
||||
return RedditUtils.getHttpBasicAuthHeader();
|
||||
}
|
||||
};
|
||||
newTokenRequest.setTag(AcquireAccessToken.class);
|
||||
refreshQueue.add(newTokenRequest);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Created by alex on 3/1/18.
|
||||
*/
|
||||
|
||||
class BestPostData implements Parcelable {
|
||||
static final int TEXT_TYPE = 0;
|
||||
static final int IMAGE_TYPE = 1;
|
||||
static final int LINK_TYPE = 2;
|
||||
static final int VIDEO_TYPE = 3;
|
||||
static final int GIF_VIDEO_TYPE = 4;
|
||||
static final int NO_PREVIEW_LINK_TYPE = 5;
|
||||
|
||||
private String id;
|
||||
private String fullName;
|
||||
private String subredditName;
|
||||
private String postTime;
|
||||
private String title;
|
||||
private String selfText;
|
||||
private String previewUrl;
|
||||
private String url;
|
||||
private String videoUrl;
|
||||
private String gifOrVideoDownloadUrl;
|
||||
private String permalink;
|
||||
private int score;
|
||||
private int postType;
|
||||
private int voteType;
|
||||
private boolean nsfw;
|
||||
private boolean isDashVideo;
|
||||
private boolean isDownloadableGifOrVideo;
|
||||
|
||||
BestPostData(String id, String fullName, String subredditName, String postTime, String title, String previewUrl, String permalink, int score, int postType, int voteType, boolean nsfw, boolean isDashVideo) {
|
||||
this.id = id;
|
||||
this.fullName = fullName;
|
||||
this.subredditName = subredditName;
|
||||
this.postTime = postTime;
|
||||
this.title = title;
|
||||
this.previewUrl = previewUrl;
|
||||
this.permalink = RedditUtils.API_BASE_URI + permalink;
|
||||
this.score = score;
|
||||
this.postType = postType;
|
||||
this.voteType = voteType;
|
||||
this.nsfw = nsfw;
|
||||
this.isDashVideo = isDashVideo;
|
||||
}
|
||||
|
||||
BestPostData(String id, String fullName, String subredditName, String postTime, String title, String previewUrl, String url, String permalink, int score, int postType, int voteType, boolean nsfw) {
|
||||
this.id = id;
|
||||
this.fullName = fullName;
|
||||
this.subredditName = subredditName;
|
||||
this.postTime = postTime;
|
||||
this.title = title;
|
||||
this.previewUrl = previewUrl;
|
||||
this.url = url;
|
||||
this.permalink = RedditUtils.API_BASE_URI + permalink;
|
||||
this.score = score;
|
||||
this.postType = postType;
|
||||
this.voteType = voteType;
|
||||
this.nsfw = nsfw;
|
||||
}
|
||||
|
||||
BestPostData(String id, String fullName, String subredditName, String postTime, String title, String permalink, int score, int postType, int voteType, boolean nsfw) {
|
||||
this.id = id;
|
||||
this.fullName = fullName;
|
||||
this.subredditName = subredditName;
|
||||
this.postTime = postTime;
|
||||
this.title = title;
|
||||
this.permalink = RedditUtils.API_BASE_URI + permalink;
|
||||
this.score = score;
|
||||
this.postType = postType;
|
||||
this.voteType = voteType;
|
||||
this.nsfw = nsfw;
|
||||
}
|
||||
|
||||
protected BestPostData(Parcel in) {
|
||||
id = in.readString();
|
||||
fullName = in.readString();
|
||||
subredditName = in.readString();
|
||||
postTime = in.readString();
|
||||
title = in.readString();
|
||||
selfText = in.readString();
|
||||
previewUrl = in.readString();
|
||||
url = in.readString();
|
||||
videoUrl = in.readString();
|
||||
gifOrVideoDownloadUrl = in.readString();
|
||||
permalink = in.readString();
|
||||
score = in.readInt();
|
||||
postType = in.readInt();
|
||||
voteType = in.readInt();
|
||||
nsfw = in.readByte() != 0;
|
||||
isDashVideo = in.readByte() != 0;
|
||||
isDownloadableGifOrVideo = in.readByte() != 0;
|
||||
}
|
||||
|
||||
public static final Creator<BestPostData> CREATOR = new Creator<BestPostData>() {
|
||||
@Override
|
||||
public BestPostData createFromParcel(Parcel in) {
|
||||
return new BestPostData(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BestPostData[] newArray(int size) {
|
||||
return new BestPostData[size];
|
||||
}
|
||||
};
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public String getSubredditName() {
|
||||
return subredditName;
|
||||
}
|
||||
|
||||
public String getPostTime() {
|
||||
return postTime;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setSelfText(String selfText) {
|
||||
this.selfText = selfText;
|
||||
}
|
||||
|
||||
public String getSelfText() {
|
||||
return selfText;
|
||||
}
|
||||
|
||||
public String getPreviewUrl() {
|
||||
return previewUrl;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setVideoUrl(String videoUrl) {
|
||||
this.videoUrl = videoUrl;
|
||||
}
|
||||
|
||||
public String getVideoUrl() {
|
||||
return videoUrl;
|
||||
}
|
||||
|
||||
public String getGifOrVideoDownloadUrl() {
|
||||
return gifOrVideoDownloadUrl;
|
||||
}
|
||||
|
||||
public void setGifOrVideoDownloadUrl(String gifOrVideoDownloadUrl) {
|
||||
this.gifOrVideoDownloadUrl = gifOrVideoDownloadUrl;
|
||||
}
|
||||
|
||||
public String getPermalink() {
|
||||
return permalink;
|
||||
}
|
||||
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public int getPostType() {
|
||||
return postType;
|
||||
}
|
||||
|
||||
public void setVoteType(int voteType) {
|
||||
this.voteType = voteType;
|
||||
}
|
||||
|
||||
public int getVoteType() {
|
||||
return voteType;
|
||||
}
|
||||
|
||||
public boolean getNSFW() {
|
||||
return nsfw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isDashVideo() {
|
||||
return isDashVideo;
|
||||
}
|
||||
|
||||
public void setDownloadableGifOrVideo(boolean isDownloadableGifOrVideo) {
|
||||
this.isDownloadableGifOrVideo = isDownloadableGifOrVideo;
|
||||
}
|
||||
|
||||
public boolean isDownloadableGifOrVideo() {
|
||||
return isDownloadableGifOrVideo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
parcel.writeString(id);
|
||||
parcel.writeString(fullName);
|
||||
parcel.writeString(subredditName);
|
||||
parcel.writeString(postTime);
|
||||
parcel.writeString(title);
|
||||
parcel.writeString(selfText);
|
||||
parcel.writeString(previewUrl);
|
||||
parcel.writeString(url);
|
||||
parcel.writeString(videoUrl);
|
||||
parcel.writeString(gifOrVideoDownloadUrl);
|
||||
parcel.writeString(permalink);
|
||||
parcel.writeInt(score);
|
||||
parcel.writeInt(postType);
|
||||
parcel.writeInt(voteType);
|
||||
parcel.writeByte((byte) (nsfw ? 1 : 0));
|
||||
parcel.writeByte((byte) (isDashVideo ? 1 : 0));
|
||||
parcel.writeByte((byte) (isDownloadableGifOrVideo ? 1 : 0));
|
||||
}
|
||||
}
|
@ -0,0 +1,245 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
*/
|
||||
public class BestPostFragment extends Fragment {
|
||||
|
||||
private CoordinatorLayout mCoordinatorLayout;
|
||||
private RecyclerView mBestPostRecyclerView;
|
||||
private LinearLayoutManager mLinearLayoutManager;
|
||||
private ProgressBar mProgressBar;
|
||||
private ArrayList<BestPostData> mBestPostData;
|
||||
private String mLastItem;
|
||||
private PaginationSynchronizer mPaginationSynchronizer;
|
||||
private BestPostRecyclerViewAdapter mAdapter;
|
||||
|
||||
private String bestPostDataParcelableState = "BPDPS";
|
||||
private String lastItemState = "LIS";
|
||||
private String paginationSynchronizerState = "PSS";
|
||||
|
||||
private RequestQueue mRequestQueue;
|
||||
private RequestQueue mPaginationRequestQueue;
|
||||
private RequestQueue mAcquireAccessTokenRequestQueue;
|
||||
private RequestQueue mVoteThingRequestQueue;
|
||||
|
||||
public BestPostFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if(savedInstanceState != null) {
|
||||
if(savedInstanceState.containsKey(bestPostDataParcelableState)) {
|
||||
mBestPostData = savedInstanceState.getParcelableArrayList(bestPostDataParcelableState);
|
||||
mLastItem = savedInstanceState.getString(lastItemState);
|
||||
mAdapter = new BestPostRecyclerViewAdapter(getActivity(), mBestPostData, mPaginationSynchronizer, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue);
|
||||
mBestPostRecyclerView.setAdapter(mAdapter);
|
||||
mBestPostRecyclerView.addOnScrollListener(new BestPostPaginationScrollListener(getActivity(), mLinearLayoutManager, mAdapter, mLastItem, mBestPostData, mPaginationSynchronizer,
|
||||
mAcquireAccessTokenRequestQueue, mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadSuccess()));
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
queryBestPost(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
if(mRequestQueue != null) {
|
||||
mRequestQueue.cancelAll(this);
|
||||
}
|
||||
|
||||
if(mAcquireAccessTokenRequestQueue != null) {
|
||||
mAcquireAccessTokenRequestQueue.cancelAll(AcquireAccessToken.class);
|
||||
}
|
||||
|
||||
if(mVoteThingRequestQueue != null) {
|
||||
mVoteThingRequestQueue.cancelAll(VoteThing.class);
|
||||
}
|
||||
|
||||
if(mPaginationRequestQueue != null) {
|
||||
mPaginationRequestQueue.cancelAll(BestPostPaginationScrollListener.class);
|
||||
}
|
||||
|
||||
if(mBestPostData != null) {
|
||||
outState.putParcelableArrayList(bestPostDataParcelableState, mBestPostData);
|
||||
outState.putString(lastItemState, mLastItem);
|
||||
outState.putParcelable(paginationSynchronizerState, mPaginationSynchronizer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if(mAdapter != null) {
|
||||
mAdapter.setCanStartActivity(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View rootView = inflater.inflate(R.layout.fragment_best_post, container, false);
|
||||
mCoordinatorLayout = rootView.findViewById(R.id.coordinator_layout_best_post_fragment);
|
||||
mBestPostRecyclerView = rootView.findViewById(R.id.recycler_view_best_post_fragment);
|
||||
mLinearLayoutManager = new LinearLayoutManager(getActivity());
|
||||
mBestPostRecyclerView.setLayoutManager(mLinearLayoutManager);
|
||||
mProgressBar = rootView.findViewById(R.id.progress_bar_best_post_fragment);
|
||||
FloatingActionButton fab = rootView.findViewById(R.id.fab_best_post_fragment);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
}
|
||||
});
|
||||
|
||||
mRequestQueue = Volley.newRequestQueue(getActivity());
|
||||
mAcquireAccessTokenRequestQueue = Volley.newRequestQueue(getActivity());
|
||||
mVoteThingRequestQueue = Volley.newRequestQueue(getActivity());
|
||||
|
||||
if(savedInstanceState != null && savedInstanceState.getParcelable(paginationSynchronizerState) != null) {
|
||||
mPaginationSynchronizer = savedInstanceState.getParcelable(paginationSynchronizerState);
|
||||
} else {
|
||||
mPaginationSynchronizer = new PaginationSynchronizer();
|
||||
queryBestPost(1);
|
||||
}
|
||||
|
||||
LastItemSynchronizer lastItemSynchronizer = new LastItemSynchronizer() {
|
||||
@Override
|
||||
public void lastItemChanged(String lastItem) {
|
||||
mLastItem = lastItem;
|
||||
}
|
||||
};
|
||||
mPaginationSynchronizer.setLastItemSynchronizer(lastItemSynchronizer);
|
||||
|
||||
PaginationRequestQueueSynchronizer paginationRequestQueueSynchronizer = new PaginationRequestQueueSynchronizer() {
|
||||
@Override
|
||||
public void passQueue(RequestQueue q) {
|
||||
mPaginationRequestQueue = q;
|
||||
}
|
||||
};
|
||||
mPaginationSynchronizer.setPaginationRequestQueueSynchronizer(paginationRequestQueueSynchronizer);
|
||||
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void queryBestPost(final int refreshTime) {
|
||||
if(refreshTime < 0) {
|
||||
showErrorSnackbar();
|
||||
return;
|
||||
}
|
||||
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
|
||||
StringRequest bestPostRequest = new StringRequest(Request.Method.GET, RedditUtils.OAUTH_API_BASE_URI + RedditUtils.BEST_POST_SUFFIX, new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
if(getActivity() != null) {
|
||||
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("response", response);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
//new ParseBestPostDataAsyncTask(response, accessToken).execute();
|
||||
new ParseBestPost(getActivity(), new ParseBestPost.ParseBestPostListener() {
|
||||
@Override
|
||||
public void onParseBestPostSuccess(ArrayList<BestPostData> bestPostData, String lastItem) {
|
||||
mBestPostData = bestPostData;
|
||||
mLastItem = lastItem;
|
||||
mAdapter = new BestPostRecyclerViewAdapter(getActivity(), bestPostData, mPaginationSynchronizer, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue);
|
||||
|
||||
mBestPostRecyclerView.setAdapter(mAdapter);
|
||||
mBestPostRecyclerView.addOnScrollListener(new BestPostPaginationScrollListener(getActivity(), mLinearLayoutManager, mAdapter, lastItem, bestPostData, mPaginationSynchronizer,
|
||||
mAcquireAccessTokenRequestQueue, mPaginationSynchronizer.isLoading(), mPaginationSynchronizer.isLoadSuccess()));
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBestPostFail() {
|
||||
Toast.makeText(getActivity(), "Error parsing data", Toast.LENGTH_SHORT).show();
|
||||
Log.i("Best post fetch error", "Error parsing data");
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
}
|
||||
}).parseBestPost(response, null);
|
||||
}
|
||||
}
|
||||
}, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error instanceof AuthFailureError) {
|
||||
// Error indicating that there was an Authentication Failure while performing the request
|
||||
// Access token expired
|
||||
new AcquireAccessToken(getActivity()).refreshAccessToken(mAcquireAccessTokenRequestQueue,
|
||||
new AcquireAccessToken.AcquireAccessTokenListener() {
|
||||
@Override
|
||||
public void onAcquireAccessTokenSuccess() {
|
||||
queryBestPost(refreshTime - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAcquireAccessTokenFail() {}
|
||||
});
|
||||
} else {
|
||||
Log.i("best post fetch error", error.toString());
|
||||
showErrorSnackbar();
|
||||
}
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public Map<String, String> getHeaders() {
|
||||
String accessToken = getActivity().getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
|
||||
return RedditUtils.getOAuthHeader(accessToken);
|
||||
}
|
||||
};
|
||||
bestPostRequest.setTag(BestPostFragment.class);
|
||||
mRequestQueue.add(bestPostRequest);
|
||||
}
|
||||
|
||||
private void showErrorSnackbar() {
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, "Error getting best post", Snackbar.LENGTH_INDEFINITE);
|
||||
snackbar.setAction(R.string.retry, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
queryBestPost(1);
|
||||
}
|
||||
});
|
||||
snackbar.show();
|
||||
}
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by alex on 3/12/18.
|
||||
*/
|
||||
|
||||
class BestPostPaginationScrollListener extends RecyclerView.OnScrollListener {
|
||||
private Context mContext;
|
||||
private LinearLayoutManager mLayoutManager;
|
||||
private BestPostRecyclerViewAdapter mAdapter;
|
||||
private ArrayList<BestPostData> mBestPostData;
|
||||
private PaginationSynchronizer mPaginationSynchronizer;
|
||||
private PaginationRetryNotifier mPaginationRetryNotifier;
|
||||
private LastItemSynchronizer mLastItemSynchronizer;
|
||||
private PaginationRequestQueueSynchronizer mPaginationRequestQueueSynchronizer;
|
||||
|
||||
private boolean isLoading;
|
||||
private boolean loadSuccess;
|
||||
private String mLastItem;
|
||||
private RequestQueue mRequestQueue;
|
||||
private RequestQueue mAcquireAccessTokenRequestQueue;
|
||||
|
||||
BestPostPaginationScrollListener(Context context, LinearLayoutManager layoutManager, BestPostRecyclerViewAdapter adapter, String lastItem, ArrayList<BestPostData> bestPostData, PaginationSynchronizer paginationSynchronizer,
|
||||
RequestQueue acquireAccessTokenRequestQueue, boolean isLoading, boolean loadSuccess) {
|
||||
if(context != null) {
|
||||
this.mContext = context;
|
||||
this.mLayoutManager = layoutManager;
|
||||
this.mAdapter = adapter;
|
||||
this.mLastItem = lastItem;
|
||||
this.mBestPostData = bestPostData;
|
||||
this.mPaginationSynchronizer = paginationSynchronizer;
|
||||
this.mAcquireAccessTokenRequestQueue = acquireAccessTokenRequestQueue;
|
||||
this.isLoading = isLoading;
|
||||
this.loadSuccess = loadSuccess;
|
||||
|
||||
mRequestQueue = Volley.newRequestQueue(mContext);
|
||||
mAcquireAccessTokenRequestQueue = Volley.newRequestQueue(mContext);
|
||||
mPaginationRetryNotifier = new PaginationRetryNotifier() {
|
||||
@Override
|
||||
public void retry() {
|
||||
fetchBestPost(1);
|
||||
}
|
||||
};
|
||||
mPaginationSynchronizer.setPaginationRetryNotifier(mPaginationRetryNotifier);
|
||||
mLastItemSynchronizer = mPaginationSynchronizer.getLastItemSynchronizer();
|
||||
mPaginationRequestQueueSynchronizer = mPaginationSynchronizer.getPaginationRequestQueueSynchronizer();
|
||||
mPaginationRequestQueueSynchronizer.passQueue(mRequestQueue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
if(!isLoading && loadSuccess) {
|
||||
int visibleItemCount = mLayoutManager.getChildCount();
|
||||
int totalItemCount = mLayoutManager.getItemCount();
|
||||
int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if((visibleItemCount + firstVisibleItemPosition >= totalItemCount) && firstVisibleItemPosition >= 0) {
|
||||
fetchBestPost(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void fetchBestPost(final int refreshTime) {
|
||||
if(refreshTime < 0) {
|
||||
loadFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
loadSuccess = false;
|
||||
mPaginationSynchronizer.setLoading(true);
|
||||
|
||||
StringRequest bestPostRequest = new StringRequest(Request.Method.GET, RedditUtils.OAUTH_API_BASE_URI + RedditUtils.BEST_POST_SUFFIX + "&" + RedditUtils.AFTER_KEY + "=" + mLastItem, new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("response", response);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
new ParseBestPost(mContext, new ParseBestPost.ParseBestPostListener() {
|
||||
@Override
|
||||
public void onParseBestPostSuccess(ArrayList<BestPostData> bestPostData, String lastItem) {
|
||||
mAdapter.notifyDataSetChanged();
|
||||
mLastItem = lastItem;
|
||||
mLastItemSynchronizer.lastItemChanged(mLastItem);
|
||||
|
||||
isLoading = false;
|
||||
loadSuccess = true;
|
||||
mPaginationSynchronizer.setLoading(false);
|
||||
mPaginationSynchronizer.setLoadingState(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBestPostFail() {
|
||||
Toast.makeText(mContext, "Error parsing data", Toast.LENGTH_SHORT).show();
|
||||
Log.i("Best post", "Error parsing data");
|
||||
loadFailed();
|
||||
}
|
||||
}).parseBestPost(response, mBestPostData);
|
||||
}
|
||||
}, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error instanceof AuthFailureError) {
|
||||
//Access token expired
|
||||
new AcquireAccessToken(mContext).refreshAccessToken(mAcquireAccessTokenRequestQueue,
|
||||
new AcquireAccessToken.AcquireAccessTokenListener() {
|
||||
@Override
|
||||
public void onAcquireAccessTokenSuccess() {
|
||||
fetchBestPost(refreshTime - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAcquireAccessTokenFail() {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Toast.makeText(mContext, "Error getting best post", Toast.LENGTH_SHORT).show();
|
||||
Log.i("best post", error.toString());
|
||||
loadFailed();
|
||||
}
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public Map<String, String> getHeaders() {
|
||||
String accessToken = mContext.getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
|
||||
return RedditUtils.getOAuthHeader(accessToken);
|
||||
}
|
||||
};
|
||||
bestPostRequest.setTag(BestPostPaginationScrollListener.class);
|
||||
mRequestQueue.add(bestPostRequest);
|
||||
}
|
||||
|
||||
private void loadFailed() {
|
||||
isLoading = false;
|
||||
loadSuccess = false;
|
||||
mPaginationSynchronizer.setLoading(false);
|
||||
mPaginationSynchronizer.setLoadingState(false);
|
||||
}
|
||||
}
|
@ -0,0 +1,527 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
|
||||
/**
|
||||
* Created by alex on 2/25/18.
|
||||
*/
|
||||
|
||||
class BestPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
private ArrayList<BestPostData> bestPostData;
|
||||
private Context mContext;
|
||||
private PaginationSynchronizer mPaginationSynchronizer;
|
||||
private RequestQueue mVoteThingRequestQueue;
|
||||
private RequestQueue mAcquireAccessTokenRequestQueue;
|
||||
private RequestManager glide;
|
||||
private boolean isLoadingMorePostSuccess;
|
||||
private boolean canStartActivity;
|
||||
|
||||
private static final int VIEW_TYPE_DATA = 0;
|
||||
private static final int VIEW_TYPE_LOADING = 1;
|
||||
|
||||
|
||||
BestPostRecyclerViewAdapter(Context context, ArrayList<BestPostData> bestPostData, PaginationSynchronizer paginationSynchronizer,
|
||||
RequestQueue voteThingRequestQueue, RequestQueue acquireAccessTokenRequestQueue) {
|
||||
if(context != null) {
|
||||
mContext = context;
|
||||
this.bestPostData = bestPostData;
|
||||
mPaginationSynchronizer = paginationSynchronizer;
|
||||
mVoteThingRequestQueue = voteThingRequestQueue;
|
||||
mAcquireAccessTokenRequestQueue = acquireAccessTokenRequestQueue;
|
||||
isLoadingMorePostSuccess = true;
|
||||
canStartActivity = true;
|
||||
glide = Glide.with(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
void setCanStartActivity(boolean canStartActivity) {
|
||||
this.canStartActivity = canStartActivity;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if(viewType == VIEW_TYPE_DATA) {
|
||||
CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_best_post, parent, false);
|
||||
return new DataViewHolder(cardView);
|
||||
} else {
|
||||
LinearLayout linearLayout = (LinearLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_progress_bar, parent, false);
|
||||
return new LoadingViewHolder(linearLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
|
||||
if(holder instanceof DataViewHolder) {
|
||||
if(bestPostData.get(position) == null) {
|
||||
Log.i("is null", Integer.toString(position));
|
||||
} else {
|
||||
final String id = bestPostData.get(position).getFullName();
|
||||
final String subredditName = bestPostData.get(position).getSubredditName();
|
||||
final String postTime = bestPostData.get(position).getPostTime();
|
||||
final String title = bestPostData.get(position).getTitle();
|
||||
final String permalink = bestPostData.get(position).getPermalink();
|
||||
int voteType = bestPostData.get(position).getVoteType();
|
||||
boolean nsfw = bestPostData.get(position).getNSFW();
|
||||
|
||||
((DataViewHolder) holder).cardView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if(canStartActivity) {
|
||||
canStartActivity = false;
|
||||
Intent intent = new Intent(mContext, ViewPostDetailActivity.class);
|
||||
intent.putExtra(ViewPostDetailActivity.EXTRA_TITLE, title);
|
||||
intent.putExtra(ViewPostDetailActivity.EXTRA_POST_DATA, bestPostData.get(position));
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
((DataViewHolder) holder).subredditNameTextView.setText(subredditName);
|
||||
((DataViewHolder) holder).postTimeTextView.setText(postTime);
|
||||
((DataViewHolder) holder).titleTextView.setText(title);
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore()));
|
||||
|
||||
if(nsfw) {
|
||||
((DataViewHolder) holder).nsfwTextView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
switch (voteType) {
|
||||
case 1:
|
||||
//Upvote
|
||||
((DataViewHolder) holder).plusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
break;
|
||||
case -1:
|
||||
//Downvote
|
||||
((DataViewHolder) holder).minusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
break;
|
||||
}
|
||||
|
||||
if(bestPostData.get(position).getPostType() != BestPostData.TEXT_TYPE && bestPostData.get(position).getPostType() != BestPostData.NO_PREVIEW_LINK_TYPE) {
|
||||
((DataViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE);
|
||||
((DataViewHolder) holder).progressBar.setVisibility(View.VISIBLE);
|
||||
((DataViewHolder) holder).imageView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
switch (bestPostData.get(position).getPostType()) {
|
||||
case BestPostData.IMAGE_TYPE:
|
||||
((DataViewHolder) holder).typeTextView.setText("IMAGE");
|
||||
final String previewImageUrl = bestPostData.get(position).getPreviewUrl();
|
||||
final String imageUrl = bestPostData.get(position).getUrl();
|
||||
glide.load(previewImageUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
((DataViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(((DataViewHolder) holder).imageView);
|
||||
((DataViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(mContext, ViewImageActivity.class);
|
||||
intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, imageUrl);
|
||||
intent.putExtra(ViewImageActivity.TITLE_KEY, title);
|
||||
intent.putExtra(ViewImageActivity.SUBREDDIT_KEY, subredditName);
|
||||
intent.putExtra(ViewImageActivity.ID_KEY, id);
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.LINK_TYPE:
|
||||
((DataViewHolder) holder).typeTextView.setText("LINK");
|
||||
String linkPreviewUrl = bestPostData.get(position).getPreviewUrl();
|
||||
glide.load(linkPreviewUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
((DataViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(((DataViewHolder) holder).imageView);
|
||||
final String linkUrl = bestPostData.get(position).getUrl();
|
||||
((DataViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
||||
// add share action to menu list
|
||||
builder.addDefaultShareMenuItem();
|
||||
builder.setToolbarColor(mContext.getResources().getColor(R.color.colorPrimary));
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
customTabsIntent.launchUrl(mContext, Uri.parse(linkUrl));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.GIF_VIDEO_TYPE:
|
||||
((DataViewHolder) holder).typeTextView.setText("GIF");
|
||||
String gifVideoPreviewUrl = bestPostData.get(position).getPreviewUrl();
|
||||
glide.load(gifVideoPreviewUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
((DataViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(((DataViewHolder) holder).imageView);
|
||||
|
||||
String gifVideoUrl = bestPostData.get(position).getVideoUrl();
|
||||
final Uri gifVideoUri = Uri.parse(gifVideoUrl);
|
||||
|
||||
((DataViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(mContext, ViewVideoActivity.class);
|
||||
intent.setData(gifVideoUri);
|
||||
intent.putExtra(ViewVideoActivity.TITLE_KEY, title);
|
||||
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, bestPostData.get(position).isDashVideo());
|
||||
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, bestPostData.get(position).isDownloadableGifOrVideo());
|
||||
if(bestPostData.get(position).isDownloadableGifOrVideo()) {
|
||||
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, bestPostData.get(position).getGifOrVideoDownloadUrl());
|
||||
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName);
|
||||
intent.putExtra(ViewVideoActivity.ID_KEY, id);
|
||||
}
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.VIDEO_TYPE:
|
||||
((DataViewHolder) holder).typeTextView.setText("VIDEO");
|
||||
String videoPreviewUrl = bestPostData.get(position).getPreviewUrl();
|
||||
glide.load(videoPreviewUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
((DataViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(((DataViewHolder) holder).imageView);
|
||||
|
||||
String videoUrl = bestPostData.get(position).getVideoUrl();
|
||||
final Uri videoUri = Uri.parse(videoUrl);
|
||||
|
||||
((DataViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(mContext, ViewVideoActivity.class);
|
||||
intent.setData(videoUri);
|
||||
intent.putExtra(ViewVideoActivity.TITLE_KEY, title);
|
||||
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, bestPostData.get(position).isDashVideo());
|
||||
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, bestPostData.get(position).isDownloadableGifOrVideo());
|
||||
if(bestPostData.get(position).isDownloadableGifOrVideo()) {
|
||||
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, bestPostData.get(position).getGifOrVideoDownloadUrl());
|
||||
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, subredditName);
|
||||
intent.putExtra(ViewVideoActivity.ID_KEY, id);
|
||||
}
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.NO_PREVIEW_LINK_TYPE:
|
||||
((DataViewHolder) holder).typeTextView.setText("LINK");
|
||||
final String noPreviewLinkUrl = bestPostData.get(position).getUrl();
|
||||
((DataViewHolder) holder).noPreviewLinkImageView.setVisibility(View.VISIBLE);
|
||||
((DataViewHolder) holder).noPreviewLinkImageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
||||
// add share action to menu list
|
||||
builder.addDefaultShareMenuItem();
|
||||
builder.setToolbarColor(mContext.getResources().getColor(R.color.colorPrimary));
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
customTabsIntent.launchUrl(mContext, Uri.parse(noPreviewLinkUrl));
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
((DataViewHolder) holder).typeTextView.setText("TEXT");
|
||||
}
|
||||
|
||||
((DataViewHolder) holder).plusButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
final boolean isDownvotedBefore = ((DataViewHolder) holder).minusButton.getColorFilter() != null;
|
||||
((DataViewHolder) holder).minusButton.clearColorFilter();
|
||||
|
||||
if (((DataViewHolder) holder).plusButton.getColorFilter() == null) {
|
||||
((DataViewHolder) holder).plusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
if(isDownvotedBefore) {
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore() + 2));
|
||||
} else {
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore() + 1));
|
||||
}
|
||||
|
||||
new VoteThing(mContext, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue).votePost(new VoteThing.VoteThingListener() {
|
||||
@Override
|
||||
public void onVoteThingSuccess(int position) {
|
||||
bestPostData.get(position).setVoteType(1);
|
||||
if(isDownvotedBefore) {
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore() + 2);
|
||||
} else {
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVoteThingFail(int position) {
|
||||
Toast.makeText(mContext, "Cannot upvote this post", Toast.LENGTH_SHORT).show();
|
||||
((DataViewHolder) holder).plusButton.clearColorFilter();
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore()));
|
||||
((DataViewHolder) holder).minusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
}, id, RedditUtils.DIR_UPVOTE, ((DataViewHolder) holder).getAdapterPosition(), 1);
|
||||
} else {
|
||||
//Upvoted before
|
||||
((DataViewHolder) holder).plusButton.clearColorFilter();
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore() - 1));
|
||||
|
||||
new VoteThing(mContext, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue).votePost(new VoteThing.VoteThingListener() {
|
||||
@Override
|
||||
public void onVoteThingSuccess(int position) {
|
||||
bestPostData.get(position).setVoteType(0);
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVoteThingFail(int position) {
|
||||
Toast.makeText(mContext, "Cannot unvote this post", Toast.LENGTH_SHORT).show();
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore() + 1));
|
||||
((DataViewHolder) holder).plusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore() + 1);
|
||||
}
|
||||
}, id, RedditUtils.DIR_UNVOTE, ((DataViewHolder) holder).getAdapterPosition(), 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
((DataViewHolder) holder).minusButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
final boolean isUpvotedBefore = ((DataViewHolder) holder).plusButton.getColorFilter() != null;
|
||||
|
||||
((DataViewHolder) holder).plusButton.clearColorFilter();
|
||||
if (((DataViewHolder) holder).minusButton.getColorFilter() == null) {
|
||||
((DataViewHolder) holder).minusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
if (isUpvotedBefore) {
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore() - 2));
|
||||
} else {
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore() - 1));
|
||||
}
|
||||
|
||||
new VoteThing(mContext, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue).votePost(new VoteThing.VoteThingListener() {
|
||||
@Override
|
||||
public void onVoteThingSuccess(int position) {
|
||||
bestPostData.get(position).setVoteType(-1);
|
||||
if(isUpvotedBefore) {
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore() - 2);
|
||||
} else {
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVoteThingFail(int position) {
|
||||
Toast.makeText(mContext, "Cannot downvote this post", Toast.LENGTH_SHORT).show();
|
||||
((DataViewHolder) holder).minusButton.clearColorFilter();
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore()));
|
||||
((DataViewHolder) holder).plusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.colorPrimary), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
}, id, RedditUtils.DIR_DOWNVOTE, holder.getAdapterPosition(), 1);
|
||||
} else {
|
||||
//Down voted before
|
||||
((DataViewHolder) holder).minusButton.clearColorFilter();
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore() + 1));
|
||||
|
||||
new VoteThing(mContext, mVoteThingRequestQueue, mAcquireAccessTokenRequestQueue).votePost(new VoteThing.VoteThingListener() {
|
||||
@Override
|
||||
public void onVoteThingSuccess(int position) {
|
||||
bestPostData.get(position).setVoteType(0);
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVoteThingFail(int position) {
|
||||
Toast.makeText(mContext, "Cannot unvote this post", Toast.LENGTH_SHORT).show();
|
||||
((DataViewHolder) holder).minusButton.setColorFilter(ContextCompat.getColor(mContext, R.color.minusButtonColor), android.graphics.PorterDuff.Mode.SRC_IN);
|
||||
((DataViewHolder) holder).scoreTextView.setText(Integer.toString(bestPostData.get(position).getScore()));
|
||||
bestPostData.get(position).setScore(bestPostData.get(position).getScore());
|
||||
}
|
||||
}, id, RedditUtils.DIR_UNVOTE, holder.getAdapterPosition(), 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
((DataViewHolder) holder).shareButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
String extraText = title + "\n" + permalink;
|
||||
intent.putExtra(Intent.EXTRA_TEXT, extraText);
|
||||
mContext.startActivity(Intent.createChooser(intent, "Share"));
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if(holder instanceof LoadingViewHolder) {
|
||||
((LoadingViewHolder) holder).retryButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
mPaginationSynchronizer.getPaginationRetryNotifier().retry();
|
||||
((LoadingViewHolder) holder).progressBar.setVisibility(View.VISIBLE);
|
||||
((LoadingViewHolder) holder).relativeLayout.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
PaginationNotifier mPaginationNotifier = new PaginationNotifier() {
|
||||
@Override
|
||||
public void LoadMorePostSuccess() {
|
||||
isLoadingMorePostSuccess = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void LoadMorePostFail() {
|
||||
((LoadingViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
((LoadingViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE);
|
||||
isLoadingMorePostSuccess = false;
|
||||
}
|
||||
};
|
||||
|
||||
mPaginationSynchronizer.setPaginationNotifier(mPaginationNotifier);
|
||||
|
||||
if(!mPaginationSynchronizer.isLoadSuccess()) {
|
||||
((LoadingViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
((LoadingViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return bestPostData.size() + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return (position >= bestPostData.size() ? VIEW_TYPE_LOADING : VIEW_TYPE_DATA);
|
||||
}
|
||||
|
||||
class DataViewHolder extends RecyclerView.ViewHolder {
|
||||
private CardView cardView;
|
||||
private CircleImageView subredditImageView;
|
||||
private TextView subredditNameTextView;
|
||||
private TextView postTimeTextView;
|
||||
private TextView titleTextView;
|
||||
private TextView typeTextView;
|
||||
private TextView nsfwTextView;
|
||||
private RelativeLayout relativeLayout;
|
||||
private ProgressBar progressBar;
|
||||
private ImageView imageView;
|
||||
private ImageView noPreviewLinkImageView;
|
||||
private ImageView plusButton;
|
||||
private TextView scoreTextView;
|
||||
private ImageView minusButton;
|
||||
private ImageView shareButton;
|
||||
|
||||
DataViewHolder(CardView itemView) {
|
||||
super(itemView);
|
||||
cardView = itemView.findViewById(R.id.card_view_view_post_detail);
|
||||
subredditImageView = itemView.findViewById(R.id.subreddit_icon_circle_image_view_best_post_item);
|
||||
subredditNameTextView = itemView.findViewById(R.id.subreddit_text_view_best_post_item);
|
||||
postTimeTextView = itemView.findViewById(R.id.post_time_text_view_best_post_item);
|
||||
titleTextView = itemView.findViewById(R.id.title_text_view_best_post_item);
|
||||
typeTextView = itemView.findViewById(R.id.type_text_view_item_best_post);
|
||||
nsfwTextView = itemView.findViewById(R.id.nsfw_text_view_item_best_post);
|
||||
relativeLayout = itemView.findViewById(R.id.image_view_wrapper_item_best_post);
|
||||
progressBar = itemView.findViewById(R.id.progress_bar_best_post_item);
|
||||
imageView = itemView.findViewById(R.id.image_view_best_post_item);
|
||||
noPreviewLinkImageView = itemView.findViewById(R.id.image_view_no_preview_link_best_post_item);
|
||||
|
||||
plusButton = itemView.findViewById(R.id.plus_button_item_best_post);
|
||||
scoreTextView = itemView.findViewById(R.id.score_text_view_item_best_post);
|
||||
minusButton = itemView.findViewById(R.id.minus_button_item_best_post);
|
||||
shareButton = itemView.findViewById(R.id.share_button_item_best_post);
|
||||
}
|
||||
}
|
||||
|
||||
class LoadingViewHolder extends RecyclerView.ViewHolder {
|
||||
private ProgressBar progressBar;
|
||||
private RelativeLayout relativeLayout;
|
||||
private Button retryButton;
|
||||
|
||||
LoadingViewHolder(LinearLayout itemView) {
|
||||
super(itemView);
|
||||
progressBar = itemView.findViewById(R.id.progress_bar_footer_progress_bar_item);
|
||||
relativeLayout = itemView.findViewById(R.id.relative_layout_footer_progress_bar_item);
|
||||
retryButton = itemView.findViewById(R.id.retry_button_footer_progress_bar_item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
|
||||
if(holder instanceof DataViewHolder) {
|
||||
glide.clear(((DataViewHolder) holder).imageView);
|
||||
((DataViewHolder) holder).relativeLayout.setVisibility(View.GONE);
|
||||
((DataViewHolder) holder).nsfwTextView.setVisibility(View.GONE);
|
||||
((DataViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
((DataViewHolder) holder).imageView.setVisibility(View.GONE);
|
||||
((DataViewHolder) holder).noPreviewLinkImageView.setVisibility(View.GONE);
|
||||
((DataViewHolder) holder).plusButton.clearColorFilter();
|
||||
((DataViewHolder) holder).minusButton.clearColorFilter();
|
||||
} else if(holder instanceof LoadingViewHolder) {
|
||||
if(isLoadingMorePostSuccess) {
|
||||
((LoadingViewHolder) holder).relativeLayout.setVisibility(View.GONE);
|
||||
((LoadingViewHolder) holder).progressBar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((LoadingViewHolder) holder).relativeLayout.setVisibility(View.VISIBLE);
|
||||
((LoadingViewHolder) holder).progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
class CommentData {
|
||||
private String id;
|
||||
private String author;
|
||||
private String commentTime;
|
||||
private String commentContent;
|
||||
private int score;
|
||||
private boolean isSubmitter;
|
||||
private String permalink;
|
||||
private int depth;
|
||||
private boolean collapsed;
|
||||
private boolean hasReply;
|
||||
private boolean scoreHidden;
|
||||
|
||||
CommentData(String id, String author, String commentTime, String commentContent, int score,
|
||||
boolean isSubmitter, String permalink, int depth, boolean collapsed, boolean hasReply,
|
||||
boolean scoreHidden) {
|
||||
this.id = id;
|
||||
this.author = author;
|
||||
this.commentTime = commentTime;
|
||||
this.commentContent = commentContent;
|
||||
this.score = score;
|
||||
this.isSubmitter = isSubmitter;
|
||||
this.permalink = RedditUtils.API_BASE_URI + permalink;
|
||||
this.depth = depth;
|
||||
this.collapsed = collapsed;
|
||||
this.hasReply = hasReply;
|
||||
this.scoreHidden = scoreHidden;
|
||||
}
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public String getCommentTime() {
|
||||
return commentTime;
|
||||
}
|
||||
|
||||
public String getCommentContent() {
|
||||
return commentContent;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(int score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public boolean isSubmitter() {
|
||||
return isSubmitter;
|
||||
}
|
||||
|
||||
public String getPermalink() {
|
||||
return permalink;
|
||||
}
|
||||
|
||||
public int getDepth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
public boolean isCollapsed() {
|
||||
return collapsed;
|
||||
}
|
||||
|
||||
public boolean isHasReply() {
|
||||
return hasReply;
|
||||
}
|
||||
|
||||
public void setHasReply(boolean hasReply) {
|
||||
this.hasReply = hasReply;
|
||||
}
|
||||
|
||||
public boolean isScoreHidden() {
|
||||
return scoreHidden;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.volley.RequestQueue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
class CommentRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
private Context mContext;
|
||||
private ArrayList<CommentData> mCommentData;
|
||||
private RequestQueue mVoteThingRequestQueue;
|
||||
|
||||
CommentRecyclerViewAdapter(Context context, ArrayList<CommentData> commentData,
|
||||
RequestQueue voteThingRequestQueue) {
|
||||
mContext = context;
|
||||
mCommentData = commentData;
|
||||
mVoteThingRequestQueue = voteThingRequestQueue;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new CommentViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post_comment, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
((CommentViewHolder) holder).authorTextView.setText(mCommentData.get(position).getAuthor());
|
||||
((CommentViewHolder) holder).commentTimeTextView.setText(mCommentData.get(position).getCommentTime());
|
||||
((CommentViewHolder) holder).commentTextView.setText(mCommentData.get(position).getCommentContent());
|
||||
((CommentViewHolder) holder).scoreTextView.setText(Integer.toString(mCommentData.get(position).getScore()));
|
||||
((CommentViewHolder) holder).upvoteButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
}
|
||||
});
|
||||
((CommentViewHolder) holder).downvoteButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mCommentData.size();
|
||||
}
|
||||
|
||||
private class CommentViewHolder extends RecyclerView.ViewHolder {
|
||||
private TextView authorTextView;
|
||||
private TextView commentTimeTextView;
|
||||
private TextView commentTextView;
|
||||
private ImageView upvoteButton;
|
||||
private ImageView downvoteButton;
|
||||
private TextView scoreTextView;
|
||||
private ImageView replyButton;
|
||||
|
||||
public CommentViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
authorTextView = itemView.findViewById(R.id.author_text_view_item_post_comment);
|
||||
commentTimeTextView = itemView.findViewById(R.id.comment_time_text_view_item_post_comment);
|
||||
commentTextView = itemView.findViewById(R.id.comment_text_view_item_post_comment);
|
||||
upvoteButton = itemView.findViewById(R.id.plus_button_item_post_comment);
|
||||
downvoteButton = itemView.findViewById(R.id.minus_button_item_post_comment);
|
||||
scoreTextView = itemView.findViewById(R.id.score_text_view_item_post_comment);
|
||||
replyButton = itemView.findViewById(R.id.reply_button_item_post_comment);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
|
||||
class FetchComment {
|
||||
interface FetchCommentListener {
|
||||
void onFetchCommentSuccess(String response);
|
||||
void onFetchCommentFail();
|
||||
}
|
||||
|
||||
private RequestQueue requestQueue;
|
||||
private String subredditName;
|
||||
private String article;
|
||||
private FetchCommentListener mFetchCommentListener;
|
||||
|
||||
FetchComment(RequestQueue requestQueue, String subredditName, String article) {
|
||||
this.requestQueue = requestQueue;
|
||||
this.subredditName = subredditName;
|
||||
this.article = article;
|
||||
}
|
||||
|
||||
void queryComment(FetchCommentListener fetchCommentListener) {
|
||||
mFetchCommentListener = fetchCommentListener;
|
||||
StringRequest commentRequest = new StringRequest(Request.Method.GET, RedditUtils.getQueryCommentURI(subredditName, article), new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
mFetchCommentListener.onFetchCommentSuccess(response);
|
||||
}
|
||||
}, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
mFetchCommentListener.onFetchCommentFail();
|
||||
}
|
||||
}) {};
|
||||
commentRequest.setTag(FetchComment.class);
|
||||
requestQueue.add(commentRequest);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
class FetchSubscribedSubreddits {
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
class FetchUserInfo {
|
||||
interface FetchUserInfoListener {
|
||||
void onFetchUserInfoSuccess(String response);
|
||||
void onFetchUserInfoFail();
|
||||
}
|
||||
|
||||
private Context context;
|
||||
private RequestQueue requestQueue;
|
||||
private FetchUserInfoListener mFetchUserInfoListener;
|
||||
|
||||
FetchUserInfo(Context context, RequestQueue requestQueue) {
|
||||
this.context = context;
|
||||
this.requestQueue = requestQueue;
|
||||
}
|
||||
|
||||
void queryUserInfo(FetchUserInfoListener fetchUserInfoListener, final int refreshTime) {
|
||||
if(refreshTime < 0) {
|
||||
mFetchUserInfoListener.onFetchUserInfoFail();
|
||||
return;
|
||||
}
|
||||
|
||||
mFetchUserInfoListener = fetchUserInfoListener;
|
||||
StringRequest commentRequest = new StringRequest(Request.Method.GET, RedditUtils.OAUTH_API_BASE_URI + RedditUtils.USER_INFO_SUFFIX, new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
mFetchUserInfoListener.onFetchUserInfoSuccess(response);
|
||||
|
||||
}
|
||||
}, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if(error instanceof AuthFailureError) {
|
||||
new AcquireAccessToken(context).refreshAccessToken(requestQueue, new AcquireAccessToken.AcquireAccessTokenListener() {
|
||||
@Override
|
||||
public void onAcquireAccessTokenSuccess() {
|
||||
queryUserInfo(mFetchUserInfoListener, refreshTime - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAcquireAccessTokenFail() {}
|
||||
});
|
||||
} else {
|
||||
mFetchUserInfoListener.onFetchUserInfoFail();
|
||||
}
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public Map<String, String> getHeaders() {
|
||||
String accessToken = context.getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
|
||||
return RedditUtils.getOAuthHeader(accessToken);
|
||||
}
|
||||
};
|
||||
commentRequest.setTag(FetchComment.class);
|
||||
requestQueue.add(commentRequest);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
/**
|
||||
* Created by alex on 2/25/18.
|
||||
*/
|
||||
|
||||
class JSONUtils {
|
||||
static final String DATA_KEY = "data";
|
||||
static final String AFTER_KEY = "after";
|
||||
static final String MODHASH_KEY = "modhash";
|
||||
static final String CHILDREN_KEY = "children";
|
||||
static final String COUNT_KEY = "count";
|
||||
static final String TITLE_KEY = "title";
|
||||
static final String NAME_KEY = "name";
|
||||
static final String SUBREDDIT_NAME_PREFIX_KEY = "subreddit_name_prefixed";
|
||||
static final String SELF_TEXT_KEY = "selftext";
|
||||
static final String AUTHOR_KEY = "author";
|
||||
static final String DOMAIN_KEY = "domain";
|
||||
static final String LINK_FLAIR_TEXT_KEY = "link_flair_text";
|
||||
static final String NUM_CROSSPOST_KEY = "num_crossposts";
|
||||
static final String CAN_MOD_POST_KEY = "can_mod_post";
|
||||
static final String SCORE_KEY = "score";
|
||||
static final String LIKES_KEY = "likes";
|
||||
static final String NSFW_KEY = "over_18";
|
||||
static final String GILDED_KEY = "gilded";
|
||||
static final String POST_HINT_KEY = "post_hint";
|
||||
static final String PERMALINK_KEY = "permalink";
|
||||
static final String CREATED_UTC_KEY = "created_utc";
|
||||
static final String PREVIEW_KEY = "preview";
|
||||
static final String IMAGES_KEY = "images";
|
||||
static final String WIDTH_KEY = "width";
|
||||
static final String HEIGHT_KEY = "height";
|
||||
static final String VARIANTS_KEY = "variants";
|
||||
static final String GIF_KEY = "gif";
|
||||
static final String MP4_KEY = "mp4";
|
||||
static final String SOURCE_KEY = "source";
|
||||
static final String URL_KEY = "url";
|
||||
static final String MEDIA_KEY = "media";
|
||||
static final String REDDIT_VIDEO_KEY = "reddit_video";
|
||||
static final String FALLBACK_URL_KEY = "fallback_url";
|
||||
static final String DASH_URL_KEY = "dash_url";
|
||||
static final String IS_VIDEO_KEY = "is_video";
|
||||
static final String CROSSPOST_PARENT_LIST = "crosspost_parent_list";
|
||||
static final String REDDIT_VIDEO_PREVIEW_KEY = "reddit_video_preview";
|
||||
static final String IS_REDDIT_MEDIA_DOMAIN = "is_reddit_media_domain";
|
||||
static final String STICKIED_KEY = "stickied";
|
||||
static final String BODY_KEY = "body";
|
||||
static final String COLLAPSED_KEY = "collapsed";
|
||||
static final String IS_SUBMITTER_KEY = "is_submitter";
|
||||
static final String REPLIES_KEY = "replies";
|
||||
static final String DEPTH_KEY = "depth";
|
||||
static final String ID_KEY = "id";
|
||||
static final String SCORE_HIDDEN_KEY = "score_hidden";
|
||||
static final String SUBREDDIT_KEY = "subreddit";
|
||||
static final String BANNER_IMG_KEY = "banner_img";
|
||||
static final String ICON_IMG_KEY = "icon_img";
|
||||
static final String LINK_KARMA_KEY = "link_karma";
|
||||
static final String COMMENT_KARMA_KEY = "comment_karma";
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
interface LastItemSynchronizer {
|
||||
void lastItemChanged(String lastItem);
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LoginActivity extends AppCompatActivity {
|
||||
|
||||
private String authCode;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
WebView webView = findViewById(R.id.webview_login_activity);
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
|
||||
Uri baseUri = Uri.parse(RedditUtils.OAUTH_URL);
|
||||
Uri.Builder uriBuilder = baseUri.buildUpon();
|
||||
uriBuilder.appendQueryParameter(RedditUtils.CLIENT_ID_KEY, RedditUtils.CLIENT_ID);
|
||||
uriBuilder.appendQueryParameter(RedditUtils.RESPONSE_TYPE_KEY, RedditUtils.RESPONSE_TYPE);
|
||||
uriBuilder.appendQueryParameter(RedditUtils.STATE_KEY, RedditUtils.STATE);
|
||||
uriBuilder.appendQueryParameter(RedditUtils.REDIRECT_URI_KEY, RedditUtils.REDIRECT_URI);
|
||||
uriBuilder.appendQueryParameter(RedditUtils.DURATION_KEY, RedditUtils.DURATION);
|
||||
uriBuilder.appendQueryParameter(RedditUtils.SCOPE_KEY, RedditUtils.SCOPE);
|
||||
|
||||
String url = uriBuilder.toString();
|
||||
|
||||
webView.loadUrl(url);
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
view.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
super.onPageStarted(view, url, favicon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
if(url.contains("&code=") || url.contains("?code=")) {
|
||||
Uri uri = Uri.parse(url);
|
||||
String state = uri.getQueryParameter("state");
|
||||
if(state.equals(RedditUtils.STATE)) {
|
||||
authCode = uri.getQueryParameter("code");
|
||||
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
||||
intent.putExtra("authCode", authCode);
|
||||
|
||||
final SharedPreferences.Editor editor = getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).edit();
|
||||
editor.putString(SharedPreferencesUtils.AUTH_CODE_KEY, authCode);
|
||||
editor.apply();
|
||||
|
||||
RequestQueue queue = Volley.newRequestQueue(LoginActivity.this);
|
||||
String tokenRetrievalUrl = "https://www.reddit.com/api/v1/access_token";
|
||||
StringRequest requestToken = new StringRequest(Request.Method.POST, tokenRetrievalUrl, new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
try {
|
||||
JSONObject responseJSON = new JSONObject(response);
|
||||
String accessToken = responseJSON.getString(RedditUtils.ACCESS_TOKEN_KEY);
|
||||
String refreshToken = responseJSON.getString(RedditUtils.REFRESH_TOKEN_KEY);
|
||||
|
||||
editor.putString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, accessToken);
|
||||
editor.putString(SharedPreferencesUtils.REFRESH_TOKEN_KEY, refreshToken);
|
||||
editor.apply();
|
||||
finish();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(LoginActivity.this, "Error occurred when parsing the JSON response", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
Toast.makeText(LoginActivity.this, "Error Retrieving the token", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}){
|
||||
@Override
|
||||
protected Map<String, String> getParams() throws AuthFailureError {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(RedditUtils.GRANT_TYPE_KEY, "authorization_code");
|
||||
params.put("code", authCode);
|
||||
params.put("redirect_uri", RedditUtils.REDIRECT_URI);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
return RedditUtils.getHttpBasicAuthHeader();
|
||||
}
|
||||
};
|
||||
|
||||
queue.add(requestToken);
|
||||
} else {
|
||||
Toast.makeText(LoginActivity.this, "Something went wrong. Try again later.", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
} else if (url.contains("error=access_denied")) {
|
||||
Toast.makeText(LoginActivity.this, "Access denied", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
|
||||
public class MainActivity extends AppCompatActivity
|
||||
implements NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
private String nameState = "NS";
|
||||
private String profileImageUrlState = "PIUS";
|
||||
private String bannerImageUrlState = "BIUS";
|
||||
private String karmaState = "KS";
|
||||
|
||||
private TextView mNameTextView;
|
||||
private TextView mKarmaTextView;
|
||||
private CircleImageView mProfileImageView;
|
||||
private ImageView mBannerImageView;
|
||||
|
||||
private Fragment mFragment;
|
||||
private RequestManager glide;
|
||||
|
||||
private String mName;
|
||||
private String mProfileImageUrl;
|
||||
private String mBannerImageUrl;
|
||||
private String mKarma;
|
||||
private boolean mFetchUserInfoSuccess;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
|
||||
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
||||
drawer.addDrawerListener(toggle);
|
||||
toggle.syncState();
|
||||
|
||||
NavigationView navigationView = findViewById(R.id.nav_view);
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
|
||||
View header = navigationView.getHeaderView(0);
|
||||
mNameTextView = header.findViewById(R.id.name_text_view_nav_header_main);
|
||||
mKarmaTextView = header.findViewById(R.id.karma_text_view_nav_header_main);
|
||||
mProfileImageView = header.findViewById(R.id.profile_image_view_nav_header_main);
|
||||
mBannerImageView = header.findViewById(R.id.banner_image_view_nav_header_main);
|
||||
|
||||
mName = getSharedPreferences(SharedPreferencesUtils.USER_INFO_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.USER_KEY, "");
|
||||
mProfileImageUrl = getSharedPreferences(SharedPreferencesUtils.USER_INFO_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.PROFILE_IMAGE_URL_KEY, "");
|
||||
mBannerImageUrl = getSharedPreferences(SharedPreferencesUtils.USER_INFO_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.BANNER_IMAGE_URL_KEY, "");
|
||||
mKarma = getSharedPreferences(SharedPreferencesUtils.USER_INFO_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.KARMA_KEY, "");
|
||||
|
||||
mNameTextView.setText(mName);
|
||||
mKarmaTextView.setText(mKarma);
|
||||
glide = Glide.with(this);
|
||||
if(!mProfileImageUrl.equals("")) {
|
||||
glide.load(mProfileImageUrl).into(mProfileImageView);
|
||||
}
|
||||
if(!mBannerImageUrl.equals("")) {
|
||||
glide.load(mBannerImageUrl).into(mBannerImageView);
|
||||
}
|
||||
|
||||
String accessToken = getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
|
||||
if(accessToken.equals("")) {
|
||||
Intent loginIntent = new Intent(this, LoginActivity.class);
|
||||
startActivity(loginIntent);
|
||||
} else {
|
||||
if(savedInstanceState == null) {
|
||||
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
|
||||
mFragment = new BestPostFragment();
|
||||
fragmentTransaction.replace(R.id.frame_layout_content_main, mFragment).commit();
|
||||
} else {
|
||||
mFragment = getFragmentManager().getFragment(savedInstanceState, "outStateFragment");
|
||||
getFragmentManager().beginTransaction().replace(R.id.frame_layout_content_main, mFragment).commit();
|
||||
}
|
||||
}
|
||||
|
||||
if(savedInstanceState == null && !mFetchUserInfoSuccess) {
|
||||
new FetchUserInfo(this, Volley.newRequestQueue(this)).queryUserInfo(new FetchUserInfo.FetchUserInfoListener() {
|
||||
@Override
|
||||
public void onFetchUserInfoSuccess(String response) {
|
||||
new ParseUserInfo().parseUserInfo(MainActivity.this, response, new ParseUserInfo.ParseUserInfoListener() {
|
||||
@Override
|
||||
public void onParseUserInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma) {
|
||||
mNameTextView.setText(name);
|
||||
if(!mProfileImageUrl.equals("")) {
|
||||
glide.load(profileImageUrl).into(mProfileImageView);
|
||||
}
|
||||
if(!mBannerImageUrl.equals("")) {
|
||||
glide.load(bannerImageUrl).into(mBannerImageView);
|
||||
}
|
||||
|
||||
mName = name;
|
||||
mProfileImageUrl = profileImageUrl;
|
||||
mBannerImageUrl = bannerImageUrl;
|
||||
mKarma = getString(R.string.karma_info, karma);
|
||||
|
||||
mKarmaTextView.setText(mKarma);
|
||||
|
||||
SharedPreferences.Editor editor = getSharedPreferences(SharedPreferencesUtils.USER_INFO_FILE_KEY, Context.MODE_PRIVATE).edit();
|
||||
editor.putString(SharedPreferencesUtils.USER_KEY, name);
|
||||
editor.putString(SharedPreferencesUtils.PROFILE_IMAGE_URL_KEY, profileImageUrl);
|
||||
editor.putString(SharedPreferencesUtils.BANNER_IMAGE_URL_KEY, bannerImageUrl);
|
||||
editor.putString(SharedPreferencesUtils.KARMA_KEY, mKarma);
|
||||
editor.apply();
|
||||
mFetchUserInfoSuccess = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseUserInfoFail() {
|
||||
mFetchUserInfoSuccess = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFetchUserInfoFail() {
|
||||
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||
drawer.closeDrawer(GravityCompat.START);
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_settings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(MenuItem item) {
|
||||
// Handle navigation view item clicks here.
|
||||
int id = item.getItemId();
|
||||
|
||||
if (id == R.id.nav_camera) {
|
||||
// Handle the camera action
|
||||
} else if (id == R.id.nav_gallery) {
|
||||
|
||||
} else if (id == R.id.nav_slideshow) {
|
||||
|
||||
} else if (id == R.id.nav_manage) {
|
||||
|
||||
} else if (id == R.id.nav_share) {
|
||||
|
||||
} else if (id == R.id.nav_send) {
|
||||
|
||||
}
|
||||
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
drawer.closeDrawer(GravityCompat.START);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if(mFragment != null) {
|
||||
getFragmentManager().putFragment(outState, "outStateFragment", mFragment);
|
||||
}
|
||||
outState.putString(nameState, mName);
|
||||
outState.putString(profileImageUrlState, mProfileImageUrl);
|
||||
outState.putString(bannerImageUrlState, mBannerImageUrl);
|
||||
outState.putString(karmaState, mKarma);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
mName = savedInstanceState.getString(nameState);
|
||||
mProfileImageUrl = savedInstanceState.getString(profileImageUrlState);
|
||||
mBannerImageUrl = savedInstanceState.getString(bannerImageUrlState);
|
||||
mKarma = savedInstanceState.getString(karmaState);
|
||||
mNameTextView.setText(mName);
|
||||
mKarmaTextView.setText(mKarma);
|
||||
if(!mProfileImageUrl.equals("")) {
|
||||
glide.load(mProfileImageUrl).into(mProfileImageView);
|
||||
}
|
||||
if(!mBannerImageUrl.equals("")) {
|
||||
glide.load(mBannerImageUrl).into(mBannerImageView);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
interface PaginationNotifier {
|
||||
void LoadMorePostSuccess();
|
||||
void LoadMorePostFail();
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import com.android.volley.RequestQueue;
|
||||
|
||||
interface PaginationRequestQueueSynchronizer {
|
||||
void passQueue(RequestQueue q);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
interface PaginationRetryNotifier {
|
||||
void retry();
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
class PaginationSynchronizer implements Parcelable {
|
||||
private boolean loadingState;
|
||||
private boolean loadSuccess;
|
||||
private PaginationNotifier paginationNotifier;
|
||||
private PaginationRetryNotifier paginationRetryNotifier;
|
||||
private LastItemSynchronizer lastItemSynchronizer;
|
||||
private PaginationRequestQueueSynchronizer paginationRequestQueueSynchronizer;
|
||||
|
||||
PaginationSynchronizer() {
|
||||
loadingState = false;
|
||||
loadSuccess = true;
|
||||
}
|
||||
|
||||
protected PaginationSynchronizer(Parcel in) {
|
||||
loadingState = in.readByte() != 0;
|
||||
loadSuccess = in.readByte() != 0;
|
||||
}
|
||||
|
||||
public static final Creator<PaginationSynchronizer> CREATOR = new Creator<PaginationSynchronizer>() {
|
||||
@Override
|
||||
public PaginationSynchronizer createFromParcel(Parcel in) {
|
||||
return new PaginationSynchronizer(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaginationSynchronizer[] newArray(int size) {
|
||||
return new PaginationSynchronizer[size];
|
||||
}
|
||||
};
|
||||
|
||||
public void setLoading(boolean isLoading) {
|
||||
this.loadingState = isLoading;
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
return loadingState;
|
||||
}
|
||||
|
||||
public void setLoadingState(boolean state) {
|
||||
loadSuccess = state;
|
||||
if(loadSuccess) {
|
||||
paginationNotifier.LoadMorePostSuccess();
|
||||
} else {
|
||||
paginationNotifier.LoadMorePostFail();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLoadSuccess() {
|
||||
return loadSuccess;
|
||||
}
|
||||
|
||||
public void setPaginationNotifier(PaginationNotifier paginationNotifier) {
|
||||
this.paginationNotifier = paginationNotifier;
|
||||
}
|
||||
|
||||
public void setPaginationRetryNotifier(PaginationRetryNotifier paginationRetryNotifier) {
|
||||
this.paginationRetryNotifier = paginationRetryNotifier;
|
||||
}
|
||||
|
||||
public PaginationRetryNotifier getPaginationRetryNotifier() {
|
||||
return paginationRetryNotifier;
|
||||
}
|
||||
|
||||
public void setLastItemSynchronizer(LastItemSynchronizer lastItemSynchronizer) {
|
||||
this.lastItemSynchronizer = lastItemSynchronizer;
|
||||
}
|
||||
|
||||
public LastItemSynchronizer getLastItemSynchronizer() {
|
||||
return lastItemSynchronizer;
|
||||
}
|
||||
|
||||
public void setPaginationRequestQueueSynchronizer(PaginationRequestQueueSynchronizer paginationRequestQueueSynchronizer) {
|
||||
this.paginationRequestQueueSynchronizer = paginationRequestQueueSynchronizer;
|
||||
}
|
||||
|
||||
public PaginationRequestQueueSynchronizer getPaginationRequestQueueSynchronizer() {
|
||||
return paginationRequestQueueSynchronizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
parcel.writeByte((byte) (loadingState ? 1 : 0));
|
||||
parcel.writeByte((byte) (loadSuccess ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,304 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Created by alex on 3/21/18.
|
||||
*/
|
||||
|
||||
class ParseBestPost {
|
||||
|
||||
interface ParseBestPostListener {
|
||||
void onParseBestPostSuccess(ArrayList<BestPostData> bestPostData, String lastItem);
|
||||
void onParseBestPostFail();
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private ParseBestPostListener mParseBetPostListener;
|
||||
|
||||
ParseBestPost(Context context, ParseBestPostListener parseBestPostListener) {
|
||||
mContext = context;
|
||||
mParseBetPostListener = parseBestPostListener;
|
||||
}
|
||||
|
||||
void parseBestPost(String response, ArrayList<BestPostData> bestPostData) {
|
||||
new ParseBestPostDataAsyncTask(response, bestPostData).execute();
|
||||
}
|
||||
|
||||
private class ParseBestPostDataAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
private JSONObject jsonResponse;
|
||||
private ArrayList<BestPostData> bestPostData;
|
||||
private ArrayList<BestPostData> newBestPostData;
|
||||
private String lastItem;
|
||||
private boolean parseFailed;
|
||||
|
||||
ParseBestPostDataAsyncTask(String response, ArrayList<BestPostData> bestPostData) {
|
||||
try {
|
||||
jsonResponse = new JSONObject(response);
|
||||
this.bestPostData = bestPostData;
|
||||
newBestPostData = new ArrayList<>();
|
||||
parseFailed = false;
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(mContext, "Error converting response to JSON", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
try {
|
||||
JSONArray allData = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
|
||||
if(bestPostData == null) {
|
||||
bestPostData = new ArrayList<>();
|
||||
}
|
||||
|
||||
lastItem = jsonResponse.getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY);
|
||||
for(int i = 0; i < allData.length(); i++) {
|
||||
JSONObject data = allData.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY);
|
||||
String id = data.getString(JSONUtils.ID_KEY);
|
||||
String fullName = data.getString(JSONUtils.NAME_KEY);
|
||||
String subredditName = data.getString(JSONUtils.SUBREDDIT_NAME_PREFIX_KEY);
|
||||
long postTime = data.getLong(JSONUtils.CREATED_UTC_KEY) * 1000;
|
||||
String title = data.getString(JSONUtils.TITLE_KEY);
|
||||
int score = data.getInt(JSONUtils.SCORE_KEY);
|
||||
int voteType;
|
||||
boolean nsfw = data.getBoolean(JSONUtils.NSFW_KEY);
|
||||
|
||||
if(data.isNull(JSONUtils.LIKES_KEY)) {
|
||||
voteType = 0;
|
||||
} else {
|
||||
voteType = data.getBoolean(JSONUtils.LIKES_KEY) ? 1 : -1;
|
||||
}
|
||||
Calendar postTimeCalendar = Calendar.getInstance();
|
||||
postTimeCalendar.setTimeInMillis(postTime);
|
||||
String formattedPostTime = new SimpleDateFormat("MMM d, YYYY, HH:mm",
|
||||
mContext.getResources().getConfiguration().locale).format(postTimeCalendar.getTime());
|
||||
String permalink = data.getString(JSONUtils.PERMALINK_KEY);
|
||||
|
||||
String previewUrl = "";
|
||||
if(data.has(JSONUtils.PREVIEW_KEY)) {
|
||||
previewUrl = data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0)
|
||||
.getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY);
|
||||
}
|
||||
|
||||
if(data.has(JSONUtils.CROSSPOST_PARENT_LIST)) {
|
||||
//Cross post
|
||||
data = data.getJSONArray(JSONUtils.CROSSPOST_PARENT_LIST).getJSONObject(0);
|
||||
parseData(data, permalink, newBestPostData, id, fullName, subredditName,
|
||||
formattedPostTime, title, previewUrl, score, voteType, nsfw, i);
|
||||
} else {
|
||||
parseData(data, permalink, newBestPostData, id, fullName, subredditName,
|
||||
formattedPostTime, title, previewUrl, score, voteType, nsfw, i);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e("error", e.getMessage());
|
||||
Log.i("Best post", "Error parsing data");
|
||||
parseFailed = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
if(!parseFailed) {
|
||||
bestPostData.addAll(newBestPostData);
|
||||
mParseBetPostListener.onParseBestPostSuccess(bestPostData, lastItem);
|
||||
} else {
|
||||
mParseBetPostListener.onParseBestPostFail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseData(JSONObject data, String permalink, ArrayList<BestPostData> bestPostData,
|
||||
String id, String fullName, String subredditName, String formattedPostTime, String title,
|
||||
String previewUrl, int score, int voteType, boolean nsfw, int i) throws JSONException {
|
||||
boolean isVideo = data.getBoolean(JSONUtils.IS_VIDEO_KEY);
|
||||
String url = data.getString(JSONUtils.URL_KEY);
|
||||
|
||||
if(!data.has(JSONUtils.PREVIEW_KEY) && previewUrl.equals("")) {
|
||||
if(url.contains(permalink)) {
|
||||
//Text post
|
||||
Log.i("text", Integer.toString(i));
|
||||
int postType = BestPostData.TEXT_TYPE;
|
||||
BestPostData postData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, permalink, score, postType, voteType, nsfw);
|
||||
postData.setSelfText(data.getString(JSONUtils.SELF_TEXT_KEY).trim());
|
||||
bestPostData.add(postData);
|
||||
} else {
|
||||
//No preview link post
|
||||
Log.i("no preview link", Integer.toString(i));
|
||||
int postType = BestPostData.NO_PREVIEW_LINK_TYPE;
|
||||
BestPostData linkPostData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, url, permalink, score, postType, voteType, nsfw);
|
||||
bestPostData.add(linkPostData);
|
||||
}
|
||||
} else if(isVideo) {
|
||||
//Video post
|
||||
Log.i("video", Integer.toString(i));
|
||||
JSONObject redditVideoObject = data.getJSONObject(JSONUtils.MEDIA_KEY).getJSONObject(JSONUtils.REDDIT_VIDEO_KEY);
|
||||
int postType = BestPostData.VIDEO_TYPE;
|
||||
String videoUrl = redditVideoObject.getString(JSONUtils.DASH_URL_KEY);
|
||||
|
||||
BestPostData videoPostData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw, true);
|
||||
|
||||
videoPostData.setVideoUrl(videoUrl);
|
||||
videoPostData.setDownloadableGifOrVideo(false);
|
||||
|
||||
bestPostData.add(videoPostData);
|
||||
} else {
|
||||
JSONObject variations = data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0);
|
||||
if (variations.has(JSONUtils.VARIANTS_KEY) && variations.getJSONObject(JSONUtils.VARIANTS_KEY).has(JSONUtils.MP4_KEY)) {
|
||||
//Gif video post (MP4)
|
||||
Log.i("gif video mp4", Integer.toString(i));
|
||||
int postType = BestPostData.GIF_VIDEO_TYPE;
|
||||
String videoUrl = variations.getJSONObject(JSONUtils.VARIANTS_KEY).getJSONObject(JSONUtils.MP4_KEY).getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY);
|
||||
String gifDownloadUrl = variations.getJSONObject(JSONUtils.VARIANTS_KEY).getJSONObject(JSONUtils.GIF_KEY).getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY);
|
||||
BestPostData post = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw, false);
|
||||
|
||||
post.setVideoUrl(videoUrl);
|
||||
post.setDownloadableGifOrVideo(true);
|
||||
post.setGifOrVideoDownloadUrl(gifDownloadUrl);
|
||||
|
||||
bestPostData.add(post);
|
||||
} else if(data.getJSONObject(JSONUtils.PREVIEW_KEY).has(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY)) {
|
||||
//Gif video post (Dash)
|
||||
Log.i("gif video dash", Integer.toString(i));
|
||||
int postType = BestPostData.GIF_VIDEO_TYPE;
|
||||
String videoUrl = data.getJSONObject(JSONUtils.PREVIEW_KEY)
|
||||
.getJSONObject(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY).getString(JSONUtils.DASH_URL_KEY);
|
||||
|
||||
BestPostData post = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw, true);
|
||||
|
||||
post.setVideoUrl(videoUrl);
|
||||
post.setDownloadableGifOrVideo(false);
|
||||
|
||||
bestPostData.add(post);
|
||||
} else {
|
||||
if (url.endsWith("jpg") || url.endsWith("png")) {
|
||||
//Image post
|
||||
Log.i("image", Integer.toString(i));
|
||||
int postType = BestPostData.IMAGE_TYPE;
|
||||
bestPostData.add(new BestPostData(id, fullName, subredditName, formattedPostTime, title, url, url, permalink, score, postType, voteType, nsfw));
|
||||
} else {
|
||||
//Link post
|
||||
Log.i("link", Integer.toString(i));
|
||||
int postType = BestPostData.LINK_TYPE;
|
||||
BestPostData linkPostData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, url, permalink, score, postType, voteType, nsfw);
|
||||
bestPostData.add(linkPostData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*private void parseData(JSONObject data, String permalink, ArrayList<BestPostData> bestPostData,
|
||||
String id, String fullName, String subredditName, String formattedPostTime, String title,
|
||||
int score, int voteType, boolean nsfw, int i) throws JSONException {
|
||||
boolean isVideo = data.getBoolean(JSONUtils.IS_VIDEO_KEY);
|
||||
if(!data.has(JSONUtils.PREVIEW_KEY)) {
|
||||
String url = data.getString(JSONUtils.URL_KEY);
|
||||
if(url.contains(permalink)) {
|
||||
//Text post
|
||||
Log.i("text", Integer.toString(i));
|
||||
int postType = BestPostData.TEXT_TYPE;
|
||||
BestPostData postData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, permalink, score, postType, voteType, nsfw);
|
||||
postData.setSelfText(data.getString(JSONUtils.SELF_TEXT_KEY).trim());
|
||||
bestPostData.add(postData);
|
||||
} else {
|
||||
//No preview link post
|
||||
Log.i("no preview link", Integer.toString(i));
|
||||
int postType = BestPostData.NO_PREVIEW_LINK_TYPE;
|
||||
BestPostData post = new BestPostData(id, fullName, subredditName, formattedPostTime, title, permalink, score, postType, voteType, nsfw);
|
||||
post.setLinkUrl(url);
|
||||
bestPostData.add(post);
|
||||
}
|
||||
} else if (!isVideo) {
|
||||
JSONObject variations = data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0);
|
||||
String previewUrl = variations.getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY);
|
||||
if (variations.has(JSONUtils.VARIANTS_KEY)) {
|
||||
if (variations.getJSONObject(JSONUtils.VARIANTS_KEY).has(JSONUtils.MP4_KEY)) {
|
||||
//Gif video
|
||||
Log.i("gif video", Integer.toString(i));
|
||||
int postType = BestPostData.GIF_VIDEO_TYPE;
|
||||
String videoUrl = variations.getJSONObject(JSONUtils.VARIANTS_KEY).getJSONObject(JSONUtils.MP4_KEY).getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY);
|
||||
|
||||
BestPostData post = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw);
|
||||
post.setVideoUrl(videoUrl);
|
||||
bestPostData.add(post);
|
||||
} else if (variations.getJSONObject(JSONUtils.VARIANTS_KEY).has(JSONUtils.GIF_KEY)) {
|
||||
//Gif post
|
||||
Log.i("gif", Integer.toString(i));
|
||||
int postType = BestPostData.GIF_TYPE;
|
||||
String gifUrl = variations.getJSONObject(JSONUtils.VARIANTS_KEY).getJSONObject(JSONUtils.GIF_KEY).getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY);
|
||||
|
||||
BestPostData post = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw);
|
||||
post.setGifUrl(gifUrl);
|
||||
bestPostData.add(post);
|
||||
} else {
|
||||
if(data.getJSONObject(JSONUtils.PREVIEW_KEY).has(JSONUtils.REDDIT_VIDEO_PREVIEW_KEY)) {
|
||||
//Gif link post
|
||||
Log.i("gif link", Integer.toString(i));
|
||||
int postType = BestPostData.LINK_TYPE;
|
||||
String gifUrl = data.getString(JSONUtils.URL_KEY);
|
||||
BestPostData gifLinkPostData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw);
|
||||
gifLinkPostData.setLinkUrl(gifUrl);
|
||||
bestPostData.add(gifLinkPostData);
|
||||
} else {
|
||||
if(!data.isNull(JSONUtils.MEDIA_KEY)) {
|
||||
//Video link post
|
||||
Log.i("video link", Integer.toString(i));
|
||||
int postType = BestPostData.LINK_TYPE;
|
||||
String videoUrl = data.getString(JSONUtils.URL_KEY);
|
||||
BestPostData videoLinkPostData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw);
|
||||
videoLinkPostData.setLinkUrl(videoUrl);
|
||||
bestPostData.add(videoLinkPostData);
|
||||
} else {
|
||||
if(data.getBoolean(JSONUtils.IS_REDDIT_MEDIA_DOMAIN)) {
|
||||
//Image post
|
||||
Log.i("image", Integer.toString(i));
|
||||
int postType = BestPostData.IMAGE_TYPE;
|
||||
bestPostData.add(new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw));
|
||||
} else {
|
||||
//Link post
|
||||
Log.i("link", Integer.toString(i));
|
||||
int postType = BestPostData.LINK_TYPE;
|
||||
String linkUrl = data.getString(JSONUtils.URL_KEY);
|
||||
BestPostData linkPostData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw);
|
||||
linkPostData.setLinkUrl(linkUrl);
|
||||
bestPostData.add(linkPostData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Image post
|
||||
Toast.makeText(mContext, "Fixed post" + Integer.toString(i), Toast.LENGTH_SHORT).show();
|
||||
Log.i("fixed image", Integer.toString(i));
|
||||
int postType = BestPostData.IMAGE_TYPE;
|
||||
bestPostData.add(new BestPostData(id, fullName, subredditName, formattedPostTime, title, previewUrl, permalink, score, postType, voteType, nsfw));
|
||||
}
|
||||
} else {
|
||||
//Video post
|
||||
Log.i("video", Integer.toString(i));
|
||||
JSONObject redditVideoObject = data.getJSONObject(JSONUtils.MEDIA_KEY).getJSONObject(JSONUtils.REDDIT_VIDEO_KEY);
|
||||
int postType = BestPostData.VIDEO_TYPE;
|
||||
String videoUrl = redditVideoObject.getString(JSONUtils.DASH_URL_KEY);
|
||||
|
||||
String videoPreviewUrl = data.getJSONObject(JSONUtils.PREVIEW_KEY).getJSONArray(JSONUtils.IMAGES_KEY).getJSONObject(0).getJSONObject(JSONUtils.SOURCE_KEY).getString(JSONUtils.URL_KEY);
|
||||
|
||||
BestPostData videoPostData = new BestPostData(id, fullName, subredditName, formattedPostTime, title, videoPreviewUrl, permalink, score, postType, voteType, nsfw);
|
||||
videoPostData.setVideoUrl(videoUrl);
|
||||
|
||||
bestPostData.add(videoPostData);
|
||||
}
|
||||
}*/
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
|
||||
class ParseComment {
|
||||
interface ParseCommentListener {
|
||||
void onParseCommentSuccess(ArrayList<CommentData> commentData, int moreCommentCount);
|
||||
void onParseCommentFail();
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private ParseCommentListener mParseCommentListener;
|
||||
|
||||
void parseComment(Context context, String response, ArrayList<CommentData> commentData, ParseCommentListener parseCommentListener) {
|
||||
mParseCommentListener = parseCommentListener;
|
||||
mContext = context;
|
||||
new ParseCommentAsyncTask(response, commentData).execute();
|
||||
}
|
||||
|
||||
private class ParseCommentAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
private JSONArray jsonResponse;
|
||||
private ArrayList<CommentData> commentData;
|
||||
private ArrayList<CommentData> newcommentData;
|
||||
private boolean parseFailed;
|
||||
int moreCommentCount;
|
||||
|
||||
ParseCommentAsyncTask(String response, ArrayList<CommentData> commentData){
|
||||
try {
|
||||
jsonResponse = new JSONArray(response);
|
||||
this.commentData = commentData;
|
||||
newcommentData = new ArrayList<>();
|
||||
parseFailed = false;
|
||||
} catch (JSONException e) {
|
||||
Log.i("comment json error", e.getMessage());
|
||||
mParseCommentListener.onParseCommentFail();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
try {
|
||||
moreCommentCount = 0;
|
||||
int actualCommentLength;
|
||||
|
||||
JSONArray allComments = jsonResponse.getJSONObject(1).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY);
|
||||
JSONObject more = allComments.getJSONObject(allComments.length() - 1).getJSONObject(JSONUtils.DATA_KEY);
|
||||
|
||||
if(more.has(JSONUtils.COUNT_KEY)) {
|
||||
moreCommentCount = more.getInt(JSONUtils.COUNT_KEY);
|
||||
actualCommentLength = allComments.length() - 1;
|
||||
} else {
|
||||
actualCommentLength = allComments.length();
|
||||
}
|
||||
|
||||
for (int i = 0; i < actualCommentLength; i++) {
|
||||
JSONObject data = allComments.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY);
|
||||
String id = data.getString(JSONUtils.ID_KEY);
|
||||
String author = data.getString(JSONUtils.AUTHOR_KEY);
|
||||
boolean isSubmitter = data.getBoolean(JSONUtils.IS_SUBMITTER_KEY);
|
||||
String commentContent = data.getString(JSONUtils.BODY_KEY);
|
||||
String permalink = data.getString(JSONUtils.PERMALINK_KEY);
|
||||
int score = data.getInt(JSONUtils.SCORE_KEY);
|
||||
long submitTime = data.getLong(JSONUtils.CREATED_UTC_KEY) * 1000;
|
||||
boolean scoreHidden = data.getBoolean(JSONUtils.SCORE_HIDDEN_KEY);
|
||||
|
||||
Calendar submitTimeCalendar = Calendar.getInstance();
|
||||
submitTimeCalendar.setTimeInMillis(submitTime);
|
||||
String formattedSubmitTime = new SimpleDateFormat("MMM d, YYYY, HH:mm",
|
||||
mContext.getResources().getConfiguration().locale).format(submitTimeCalendar.getTime());
|
||||
|
||||
int depth = data.getInt(JSONUtils.DEPTH_KEY);
|
||||
boolean collapsed = data.getBoolean(JSONUtils.COLLAPSED_KEY);
|
||||
boolean hasReply = !(data.get(JSONUtils.REPLIES_KEY) instanceof String);
|
||||
|
||||
newcommentData.add(new CommentData(id, author, formattedSubmitTime, commentContent, score, isSubmitter, permalink, depth, collapsed, hasReply, scoreHidden));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
parseFailed = true;
|
||||
Log.i("parse comment error", e.getMessage());
|
||||
mParseCommentListener.onParseCommentFail();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
if(!parseFailed) {
|
||||
commentData.addAll(newcommentData);
|
||||
mParseCommentListener.onParseCommentSuccess(commentData, moreCommentCount);
|
||||
} else {
|
||||
mParseCommentListener.onParseCommentFail();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
class ParseSubscribedSubreddits {
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
class ParseUserInfo {
|
||||
interface ParseUserInfoListener {
|
||||
void onParseUserInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma);
|
||||
void onParseUserInfoFail();
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private ParseUserInfoListener mParseUserInfoListener;
|
||||
|
||||
void parseUserInfo(Context context, String response, ParseUserInfoListener parseUserInfoListener) {
|
||||
mParseUserInfoListener = parseUserInfoListener;
|
||||
mContext = context;
|
||||
new ParseUserInfo.ParseUserInfoAsyncTask(response).execute();
|
||||
}
|
||||
|
||||
private class ParseUserInfoAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
private JSONObject jsonResponse;
|
||||
private boolean parseFailed;
|
||||
|
||||
private String name;
|
||||
private String profileImageUrl;
|
||||
private String bannerImageUrl;
|
||||
private int karma;
|
||||
|
||||
ParseUserInfoAsyncTask(String response){
|
||||
try {
|
||||
jsonResponse = new JSONObject(response);
|
||||
parseFailed = false;
|
||||
} catch (JSONException e) {
|
||||
Log.i("user info json error", e.getMessage());
|
||||
mParseUserInfoListener.onParseUserInfoFail();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
try {
|
||||
name = jsonResponse.getString(JSONUtils.NAME_KEY);
|
||||
profileImageUrl = Html.fromHtml(jsonResponse.getString(JSONUtils.ICON_IMG_KEY)).toString();
|
||||
bannerImageUrl = Html.fromHtml(jsonResponse.getJSONObject(JSONUtils.SUBREDDIT_KEY).getString(JSONUtils.BANNER_IMG_KEY)).toString();
|
||||
int linkKarma = jsonResponse.getInt(JSONUtils.LINK_KARMA_KEY);
|
||||
int commentKarma = jsonResponse.getInt(JSONUtils.COMMENT_KARMA_KEY);
|
||||
karma = linkKarma + commentKarma;
|
||||
} catch (JSONException e) {
|
||||
parseFailed = true;
|
||||
Log.i("parse comment error", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
if(!parseFailed) {
|
||||
mParseUserInfoListener.onParseUserInfoSuccess(name, profileImageUrl, bannerImageUrl, karma);
|
||||
} else {
|
||||
mParseUserInfoListener.onParseUserInfoFail();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by alex on 2/23/18.
|
||||
*/
|
||||
|
||||
class RedditUtils {
|
||||
static final String OAUTH_URL ="https://www.reddit.com/api/v1/authorize.compact";
|
||||
static final String ACQUIRE_ACCESS_TOKEN_URL = "https://www.reddit.com/api/v1/access_token";
|
||||
static final String OAUTH_API_BASE_URI = "https://oauth.reddit.com";
|
||||
static final String API_BASE_URI = "https://www.reddit.com";
|
||||
static final String BEST_POST_SUFFIX = "/best?raw_json=1";
|
||||
static final String VOTE_SUFFIX = "/api/vote";
|
||||
static final String USER_INFO_SUFFIX = "/api/v1/me?raw_json=1";
|
||||
|
||||
static final String CLIENT_ID_KEY = "client_id";
|
||||
static final String CLIENT_ID = "";
|
||||
static final String RESPONSE_TYPE_KEY = "response_type";
|
||||
static final String RESPONSE_TYPE = "code";
|
||||
static final String STATE_KEY = "state";
|
||||
static final String STATE = "";
|
||||
static final String REDIRECT_URI_KEY = "redirect_uri";
|
||||
static final String REDIRECT_URI = "";
|
||||
static final String DURATION_KEY = "duration";
|
||||
static final String DURATION = "permanent";
|
||||
static final String SCOPE_KEY = "scope";
|
||||
static final String SCOPE = "identity edit flair history modconfig modflair modlog modposts modwiki mysubreddits privatemessages read report save submit subscribe vote wikiedit wikiread";
|
||||
static final String ACCESS_TOKEN_KEY = "access_token";
|
||||
static final String EXPIRES_IN_KEY = "expires_in";
|
||||
|
||||
static final String AUTHORIZATION_KEY = "Authorization";
|
||||
static final String AUTHORIZATION_BASE = "bearer ";
|
||||
static final String USER_AGENT_KEY = "User-Agent";
|
||||
static final String USER_AGENT = "";
|
||||
|
||||
static final String GRANT_TYPE_KEY = "grant_type";
|
||||
static final String GRANT_TYPE_REFRESH_TOKEN = "refresh_token";
|
||||
static final String REFRESH_TOKEN_KEY = "refresh_token";
|
||||
|
||||
static final String DIR_KEY = "dir";
|
||||
static final String ID_KEY = "id";
|
||||
static final String RANK_KEY = "rank";
|
||||
static final String DIR_UPVOTE = "1";
|
||||
static final String DIR_UNVOTE = "0";
|
||||
static final String DIR_DOWNVOTE = "-1";
|
||||
static final String RANK = "10";
|
||||
|
||||
static final String AFTER_KEY = "after";
|
||||
|
||||
static Map<String, String> getHttpBasicAuthHeader() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
String credentials = String.format("%s:%s", RedditUtils.CLIENT_ID, "");
|
||||
String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
|
||||
params.put(RedditUtils.AUTHORIZATION_KEY, auth);
|
||||
return params;
|
||||
}
|
||||
|
||||
static Map<String, String> getOAuthHeader(String accessToken) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(RedditUtils.AUTHORIZATION_KEY, RedditUtils.AUTHORIZATION_BASE + accessToken);
|
||||
params.put(RedditUtils.USER_AGENT_KEY, RedditUtils.USER_AGENT);
|
||||
return params;
|
||||
}
|
||||
|
||||
static String getQueryCommentURI(String subredditName, String article) {
|
||||
return API_BASE_URI + "/" + subredditName + "/comments/" + article + ".json";
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
/**
|
||||
* Created by alex on 2/23/18.
|
||||
*/
|
||||
|
||||
class SharedPreferencesUtils {
|
||||
static final String AUTH_CODE_FILE_KEY = "Auth_Code_Pref";
|
||||
static final String USER_INFO_FILE_KEY = "User_Info";
|
||||
static final String AUTH_CODE_KEY = "code";
|
||||
static final String ACCESS_TOKEN_KEY = "accessToken";
|
||||
static final String REFRESH_TOKEN_KEY = "refreshToken";
|
||||
static final String QUERY_ACCESS_TOKEN_TIME_KEY = "queryAccessTokenTime";
|
||||
static final String ACCESS_TOKEN_EXPIRE_TIME_KEY = "accessTokenExpireTime";
|
||||
static final String MODHASH_KEY = "modhash";
|
||||
static final String USER_KEY = "user";
|
||||
static final String PROFILE_IMAGE_URL_KEY = "profileImageUrl";
|
||||
static final String BANNER_IMAGE_URL_KEY = "bannerImageUrl";
|
||||
static final String KARMA_KEY = "karma";
|
||||
}
|
@ -0,0 +1,425 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.Manifest;
|
||||
import android.animation.Animator;
|
||||
import android.animation.ArgbEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.alexvasilkov.gestures.views.GestureImageView;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.github.pwittchen.swipe.library.rx2.SimpleSwipeListener;
|
||||
import com.github.pwittchen.swipe.library.rx2.Swipe;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class ViewImageActivity extends AppCompatActivity {
|
||||
|
||||
private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0;
|
||||
|
||||
static final String TITLE_KEY = "TK";
|
||||
static final String IMAGE_URL_KEY = "IUK";
|
||||
static final String SUBREDDIT_KEY = "SK";
|
||||
static final String ID_KEY = "IK";
|
||||
|
||||
private boolean isActionBarHidden = false;
|
||||
private boolean isDownloading = false;
|
||||
|
||||
private Menu mMenu;
|
||||
private Swipe swipe;
|
||||
|
||||
private String mImageUrl;
|
||||
private String mImageFileName;
|
||||
|
||||
private float totalLengthY = 0.0f;
|
||||
private float touchY = -1.0f;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_view_image);
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
final Drawable upArrow = getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp);
|
||||
actionBar.setHomeAsUpIndicator(upArrow);
|
||||
|
||||
Intent intent = getIntent();
|
||||
mImageUrl = intent.getExtras().getString(IMAGE_URL_KEY);
|
||||
String title = intent.getExtras().getString(TITLE_KEY);
|
||||
final Spannable text = new SpannableString(title);
|
||||
setTitle(text);
|
||||
|
||||
mImageFileName = intent.getExtras().getString(SUBREDDIT_KEY).substring(2) + "-" + intent.getExtras().getString(ID_KEY).substring(3);
|
||||
|
||||
final RelativeLayout relativeLayout = findViewById(R.id.parent_relative_layout_view_image_activity);
|
||||
final GestureImageView imageView = findViewById(R.id.image_view_view_image_activity);
|
||||
final ProgressBar progressBar = findViewById(R.id.progress_bar_view_image_activity);
|
||||
|
||||
final float pxHeight = getResources().getDisplayMetrics().heightPixels;
|
||||
|
||||
int activityColorFrom = getResources().getColor(android.R.color.black);
|
||||
int actionBarColorFrom = getResources().getColor(R.color.transparentActionBarColor);
|
||||
int actionBarElementColorFrom = getResources().getColor(android.R.color.white);
|
||||
int colorTo = getResources().getColor(android.R.color.transparent);
|
||||
|
||||
final ValueAnimator activityColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), activityColorFrom, colorTo);
|
||||
final ValueAnimator actionBarColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarColorFrom, colorTo);
|
||||
final ValueAnimator actionBarElementColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarElementColorFrom, colorTo);
|
||||
|
||||
activityColorAnimation.setDuration(300); // milliseconds
|
||||
actionBarColorAnimation.setDuration(300);
|
||||
actionBarElementColorAnimation.setDuration(300);
|
||||
|
||||
activityColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
relativeLayout.setBackgroundColor((int) valueAnimator.getAnimatedValue());
|
||||
}
|
||||
});
|
||||
|
||||
actionBarColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
actionBar.setBackgroundDrawable(new ColorDrawable((int) valueAnimator.getAnimatedValue()));
|
||||
}
|
||||
});
|
||||
|
||||
actionBarElementColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
text.setSpan(new ForegroundColorSpan((int) valueAnimator.getAnimatedValue()), 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
actionBar.setTitle(text);
|
||||
upArrow.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN);
|
||||
if(mMenu != null) {
|
||||
Drawable drawable = mMenu.getItem(0).getIcon();
|
||||
//drawable.mutate();
|
||||
drawable.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
swipe = new Swipe();
|
||||
swipe.setListener(new SimpleSwipeListener() {
|
||||
@Override
|
||||
public void onSwipingUp(final MotionEvent event) {
|
||||
float nowY = event.getY();
|
||||
float offset;
|
||||
if (touchY == -1.0f) {
|
||||
offset = 0.0f;
|
||||
} else {
|
||||
offset = nowY - touchY;
|
||||
}
|
||||
totalLengthY += offset;
|
||||
touchY = nowY;
|
||||
imageView.animate()
|
||||
.y(totalLengthY)
|
||||
.setDuration(0)
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSwipedUp(final MotionEvent event) {
|
||||
imageView.animate()
|
||||
.y(0)
|
||||
.setDuration(300)
|
||||
.start();
|
||||
|
||||
if (totalLengthY < -pxHeight / 8) {
|
||||
imageView.animate()
|
||||
.y(-pxHeight)
|
||||
.setDuration(300)
|
||||
.setListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
activityColorAnimation.start();
|
||||
actionBarColorAnimation.start();
|
||||
actionBarElementColorAnimation.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {
|
||||
}
|
||||
})
|
||||
.start();
|
||||
} else {
|
||||
imageView.animate()
|
||||
.y(0)
|
||||
.setDuration(300)
|
||||
.start();
|
||||
}
|
||||
|
||||
totalLengthY = 0.0f;
|
||||
touchY = -1.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipingDown(final MotionEvent event) {
|
||||
float nowY = event.getY();
|
||||
float offset;
|
||||
if (touchY == -1.0f) {
|
||||
offset = 0.0f;
|
||||
} else {
|
||||
offset = nowY - touchY;
|
||||
}
|
||||
totalLengthY += offset;
|
||||
touchY = nowY;
|
||||
imageView.animate()
|
||||
.y(totalLengthY)
|
||||
.setDuration(0)
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSwipedDown(final MotionEvent event) {
|
||||
if (totalLengthY > pxHeight / 8) {
|
||||
imageView.animate()
|
||||
.y(pxHeight)
|
||||
.setDuration(300)
|
||||
.setListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
activityColorAnimation.start();
|
||||
actionBarColorAnimation.start();
|
||||
actionBarElementColorAnimation.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {
|
||||
}
|
||||
})
|
||||
.start();
|
||||
} else {
|
||||
imageView.animate()
|
||||
.y(0)
|
||||
.setDuration(300)
|
||||
.start();
|
||||
}
|
||||
|
||||
totalLengthY = 0.0f;
|
||||
touchY = -1.0f;
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
imageView.getController().getSettings()
|
||||
.setPanEnabled(true)
|
||||
.setRotationEnabled(true)
|
||||
.setRestrictRotation(true);
|
||||
|
||||
Glide.with(this).load(mImageUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).apply(new RequestOptions().fitCenter()).into(imageView);
|
||||
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (isActionBarHidden) {
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
isActionBarHidden = false;
|
||||
} else {
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_IMMERSIVE);
|
||||
isActionBarHidden = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
mMenu = menu;
|
||||
getMenuInflater().inflate(R.menu.view_image, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
case R.id.action_download_view_image:
|
||||
if (isDownloading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
isDownloading = true;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
// Permission is not granted
|
||||
// No explanation needed; request the permission
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||
PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||
} else {
|
||||
// Permission has already been granted
|
||||
saveImage();
|
||||
}
|
||||
} else {
|
||||
saveImage();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
swipe.dispatchTouchEvent(ev);
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if(requestCode == PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE && grantResults.length > 0) {
|
||||
if(grantResults[0] == PackageManager.PERMISSION_DENIED) {
|
||||
Toast.makeText(this, "No storage permission to save this file", Toast.LENGTH_SHORT).show();
|
||||
} else if(grantResults[0] == PackageManager.PERMISSION_GRANTED && isDownloading) {
|
||||
saveImage();
|
||||
}
|
||||
isDownloading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveImage() {
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(mImageUrl)
|
||||
.into(new SimpleTarget<Bitmap>() {
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@Override
|
||||
public void onResourceReady(@NonNull final Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
private boolean saveSuccess = true;
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
super.onPostExecute(aVoid);
|
||||
isDownloading = false;
|
||||
if(saveSuccess) {
|
||||
Toast.makeText(ViewImageActivity.this, "Download completed", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(ViewImageActivity.this, "Download failed", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
try {
|
||||
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
|
||||
File directory = new File(path + "/Infinity/");
|
||||
if(!directory.exists()) {
|
||||
if(!directory.mkdir()) {
|
||||
saveSuccess = false;
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if(directory.isFile()) {
|
||||
if(!directory.delete() && !directory.mkdir()) {
|
||||
saveSuccess = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(path + "/Infinity/", mImageFileName + ".jpg");
|
||||
int postfix = 1;
|
||||
while(file.exists()) {
|
||||
file = new File(path + "/Infinity/", mImageFileName + "-" + postfix + ".jpg");
|
||||
}
|
||||
OutputStream outputStream = new FileOutputStream(file);
|
||||
|
||||
resource.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
|
||||
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
} catch (IOException e) {
|
||||
saveSuccess = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,342 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.engine.GlideException;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
|
||||
public class ViewPostDetailActivity extends AppCompatActivity {
|
||||
|
||||
static final String EXTRA_TITLE = "ET";
|
||||
static final String EXTRA_POST_DATA = "EPD";
|
||||
|
||||
private int orientation;
|
||||
private String orientationState = "OS";
|
||||
|
||||
private int mMoreCommentCount;
|
||||
private BestPostData mPostData;
|
||||
|
||||
private CoordinatorLayout mCoordinatorLayout;
|
||||
private ProgressBar mCommentProgressbar;
|
||||
private CardView mCommentCardView;
|
||||
private RecyclerView mRecyclerView;
|
||||
|
||||
private RequestQueue mVoteThingQueue;
|
||||
private RequestQueue mCommentQueue;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_view_post_detail);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
orientation = getResources().getConfiguration().orientation;
|
||||
|
||||
mPostData = getIntent().getExtras().getParcelable(EXTRA_POST_DATA);
|
||||
|
||||
TextView titleTextView = findViewById(R.id.title_text_view_view_post_detail);
|
||||
titleTextView.setText(mPostData.getTitle());
|
||||
|
||||
mCoordinatorLayout = findViewById(R.id.coordinator_layout_view_post_detail);
|
||||
|
||||
CircleImageView subredditImageView = findViewById(R.id.subreddit_icon_circle_image_view_view_post_detail);
|
||||
TextView postTimeTextView = findViewById(R.id.post_time_text_view_view_post_detail);
|
||||
TextView subredditTextView = findViewById(R.id.subreddit_text_view_view_post_detail);
|
||||
TextView contentTextView = findViewById(R.id.content_text_view_view_post_detail);
|
||||
TextView typeTextView = findViewById(R.id.type_text_view_view_post_detail);
|
||||
TextView nsfwTextView = findViewById(R.id.nsfw_text_view_view_post_detail);
|
||||
RelativeLayout relativeLayout = findViewById(R.id.image_view_wrapper_view_post_detail);
|
||||
final ProgressBar progressBar = findViewById(R.id.progress_bar_view_post_detail);
|
||||
ImageView imageView = findViewById(R.id.image_view_view_post_detail);
|
||||
ImageView noPreviewLinkImageView = findViewById(R.id.image_view_no_preview_link_view_post_detail);
|
||||
|
||||
ImageView plusButton = findViewById(R.id.plus_button_view_post_detail);
|
||||
TextView scoreTextView = findViewById(R.id.score_text_view_view_post_detail);
|
||||
ImageView minusButton = findViewById(R.id.minus_button_view_post_detail);
|
||||
ImageView shareButton = findViewById(R.id.share_button_view_post_detail);
|
||||
|
||||
mCommentProgressbar = findViewById(R.id.comment_progress_bar_view_post_detail);
|
||||
mCommentCardView = findViewById(R.id.comment_card_view_view_post_detail);
|
||||
mRecyclerView = findViewById(R.id.recycler_view_view_post_detail);
|
||||
|
||||
mRecyclerView.setNestedScrollingEnabled(false);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
|
||||
mVoteThingQueue = Volley.newRequestQueue(this);
|
||||
mCommentQueue = Volley.newRequestQueue(this);
|
||||
|
||||
subredditTextView.setText(mPostData.getSubredditName());
|
||||
postTimeTextView.setText(mPostData.getPostTime());
|
||||
if(mPostData.getNSFW()) {
|
||||
nsfwTextView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
scoreTextView.setText(Integer.toString(mPostData.getScore()));
|
||||
|
||||
shareButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
String extraText = mPostData.getTitle() + "\n" + mPostData.getPermalink();
|
||||
intent.putExtra(Intent.EXTRA_TEXT, extraText);
|
||||
startActivity(Intent.createChooser(intent, "Share"));
|
||||
}
|
||||
});
|
||||
|
||||
switch (mPostData.getPostType()) {
|
||||
case BestPostData.IMAGE_TYPE:
|
||||
typeTextView.setText("IMAGE");
|
||||
relativeLayout.setVisibility(View.VISIBLE);
|
||||
Glide.with(this).load(mPostData.getPreviewUrl()).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
//Need to be implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(imageView);
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(ViewPostDetailActivity.this, ViewImageActivity.class);
|
||||
intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, mPostData.getPreviewUrl());
|
||||
intent.putExtra(ViewImageActivity.TITLE_KEY, mPostData.getTitle());
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.LINK_TYPE:
|
||||
relativeLayout.setVisibility(View.VISIBLE);
|
||||
typeTextView.setText("LINK");
|
||||
String linkPreviewUrl = mPostData.getPreviewUrl();
|
||||
Glide.with(this).load(linkPreviewUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(imageView);
|
||||
final String linkUrl = mPostData.getUrl();
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
||||
// add share action to menu list
|
||||
builder.addDefaultShareMenuItem();
|
||||
builder.setToolbarColor(getResources().getColor(R.color.colorPrimary));
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
customTabsIntent.launchUrl(ViewPostDetailActivity.this, Uri.parse(linkUrl));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.GIF_VIDEO_TYPE:
|
||||
relativeLayout.setVisibility(View.VISIBLE);
|
||||
typeTextView.setText("VIDEO");
|
||||
String gifVideoPreviewUrl = mPostData.getPreviewUrl();
|
||||
Glide.with(this).load(gifVideoPreviewUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(imageView);
|
||||
|
||||
String gifVideoUrl = mPostData.getVideoUrl();
|
||||
final Uri gifVideoUri = Uri.parse(gifVideoUrl);
|
||||
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(ViewPostDetailActivity.this, ViewVideoActivity.class);
|
||||
intent.setData(gifVideoUri);
|
||||
intent.putExtra(ViewVideoActivity.TITLE_KEY, mPostData.getTitle());
|
||||
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.isDashVideo());
|
||||
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.isDownloadableGifOrVideo());
|
||||
if(mPostData.isDownloadableGifOrVideo()) {
|
||||
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.getGifOrVideoDownloadUrl());
|
||||
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPostData.getSubredditName());
|
||||
intent.putExtra(ViewVideoActivity.ID_KEY, mPostData.getId());
|
||||
}
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.VIDEO_TYPE:
|
||||
relativeLayout.setVisibility(View.VISIBLE);
|
||||
typeTextView.setText("VIDEO");
|
||||
String videoPreviewUrl = mPostData.getPreviewUrl();
|
||||
Glide.with(this).load(videoPreviewUrl).listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
}).into(imageView);
|
||||
|
||||
String videoUrl = mPostData.getVideoUrl();
|
||||
final Uri videoUri = Uri.parse(videoUrl);
|
||||
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(ViewPostDetailActivity.this, ViewVideoActivity.class);
|
||||
intent.setData(videoUri);
|
||||
intent.putExtra(ViewVideoActivity.TITLE_KEY, mPostData.getTitle());
|
||||
intent.putExtra(ViewVideoActivity.IS_DASH_VIDEO_KEY, mPostData.isDashVideo());
|
||||
intent.putExtra(ViewVideoActivity.IS_DOWNLOADABLE_KEY, mPostData.isDownloadableGifOrVideo());
|
||||
if(mPostData.isDownloadableGifOrVideo()) {
|
||||
intent.putExtra(ViewVideoActivity.DOWNLOAD_URL_KEY, mPostData.getGifOrVideoDownloadUrl());
|
||||
intent.putExtra(ViewVideoActivity.SUBREDDIT_KEY, mPostData.getSubredditName());
|
||||
intent.putExtra(ViewVideoActivity.ID_KEY, mPostData.getId());
|
||||
}
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.NO_PREVIEW_LINK_TYPE:
|
||||
typeTextView.setText("LINK");
|
||||
noPreviewLinkImageView.setVisibility(View.VISIBLE);
|
||||
noPreviewLinkImageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
||||
// add share action to menu list
|
||||
builder.addDefaultShareMenuItem();
|
||||
builder.setToolbarColor(getResources().getColor(R.color.colorPrimary));
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
customTabsIntent.launchUrl(ViewPostDetailActivity.this, Uri.parse(mPostData.getUrl()));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BestPostData.TEXT_TYPE:
|
||||
typeTextView.setText("TEXT");
|
||||
if(!mPostData.getSelfText().equals("")) {
|
||||
contentTextView.setVisibility(View.VISIBLE);
|
||||
contentTextView.setText(mPostData.getSelfText());
|
||||
}
|
||||
}
|
||||
queryComment();
|
||||
}
|
||||
|
||||
private void queryComment() {
|
||||
mCommentProgressbar.setVisibility(View.VISIBLE);
|
||||
new FetchComment(mCommentQueue, mPostData.getSubredditName(), mPostData.getId()).queryComment(new FetchComment.FetchCommentListener() {
|
||||
@Override
|
||||
public void onFetchCommentSuccess(String response) {
|
||||
new ParseComment().parseComment(ViewPostDetailActivity.this, response, new ArrayList<CommentData>(), new ParseComment.ParseCommentListener() {
|
||||
@Override
|
||||
public void onParseCommentSuccess(ArrayList<CommentData> commentData, int moreCommentCount) {
|
||||
mCommentProgressbar.setVisibility(View.GONE);
|
||||
mMoreCommentCount = moreCommentCount;
|
||||
if(commentData.size() > 0) {
|
||||
CommentRecyclerViewAdapter adapter = new CommentRecyclerViewAdapter(ViewPostDetailActivity.this, commentData, mVoteThingQueue);
|
||||
mRecyclerView.setAdapter(adapter);
|
||||
mCommentCardView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseCommentFail() {
|
||||
mCommentProgressbar.setVisibility(View.GONE);
|
||||
showRetrySnackbar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFetchCommentFail() {
|
||||
mCommentProgressbar.setVisibility(View.GONE);
|
||||
showRetrySnackbar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showRetrySnackbar() {
|
||||
Snackbar snackbar = Snackbar.make(mCoordinatorLayout, R.string.load_comment_failed, Snackbar.LENGTH_INDEFINITE);
|
||||
snackbar.setAction(R.string.retry, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
queryComment();
|
||||
}
|
||||
});
|
||||
snackbar.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(orientationState, orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
orientation = savedInstanceState.getInt(orientationState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if(orientation == getResources().getConfiguration().orientation) {
|
||||
super.onBackPressed();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,406 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.Manifest;
|
||||
import android.animation.Animator;
|
||||
import android.animation.ArgbEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.github.pwittchen.swipe.library.rx2.SimpleSwipeListener;
|
||||
import com.github.pwittchen.swipe.library.rx2.Swipe;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.source.dash.DashChunkSource;
|
||||
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
||||
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
|
||||
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelector;
|
||||
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||
import com.google.android.exoplayer2.ui.PlayerView;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
public class ViewVideoActivity extends AppCompatActivity {
|
||||
|
||||
private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0;
|
||||
|
||||
static final String TITLE_KEY = "TK";
|
||||
static final String IS_DASH_VIDEO_KEY = "IDVK";
|
||||
static final String IS_DOWNLOADABLE_KEY = "IDK";
|
||||
static final String DOWNLOAD_URL_KEY = "DUK";
|
||||
static final String SUBREDDIT_KEY = "SK";
|
||||
static final String ID_KEY = "IK";
|
||||
|
||||
private Uri mVideoUri;
|
||||
private SimpleExoPlayer player;
|
||||
|
||||
private Menu mMenu;
|
||||
private Swipe swipe;
|
||||
|
||||
private String mGifOrVideoFileName;
|
||||
private String mDownloadUrl;
|
||||
private boolean mIsDashVideo;
|
||||
private boolean wasPlaying;
|
||||
private boolean isDownloading = false;
|
||||
private float totalLengthY = 0.0f;
|
||||
private float touchY = -1.0f;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_view_video);
|
||||
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
final Drawable upArrow = getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp);
|
||||
getSupportActionBar().setHomeAsUpIndicator(upArrow);
|
||||
|
||||
//Set player controller margin bottom in order to display it above the navbar
|
||||
int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
LinearLayout controllerLinearLayout = findViewById(R.id.linear_layout_exo_playback_control_view);
|
||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) controllerLinearLayout.getLayoutParams();
|
||||
params.bottomMargin = getResources().getDimensionPixelSize(resourceId);
|
||||
|
||||
Intent intent = getIntent();
|
||||
mVideoUri = intent.getData();
|
||||
mIsDashVideo = intent.getExtras().getBoolean(IS_DASH_VIDEO_KEY);
|
||||
|
||||
String title = intent.getExtras().getString(TITLE_KEY);
|
||||
final Spannable text = new SpannableString(title);
|
||||
setTitle(text);
|
||||
|
||||
if(intent.getExtras().getBoolean(IS_DOWNLOADABLE_KEY)) {
|
||||
mGifOrVideoFileName = intent.getExtras().getString(SUBREDDIT_KEY).substring(2)
|
||||
+ "-" + intent.getExtras().getString(ID_KEY).substring(3) + ".gif";
|
||||
mDownloadUrl = intent.getExtras().getString(DOWNLOAD_URL_KEY);
|
||||
}
|
||||
|
||||
final RelativeLayout relativeLayout = findViewById(R.id.relative_layout_view_video_activity);
|
||||
final PlayerView videoPlayerView = findViewById(R.id.player_view_view_video_activity);
|
||||
|
||||
final float pxHeight = getResources().getDisplayMetrics().heightPixels;
|
||||
|
||||
int activityColorFrom = getResources().getColor(android.R.color.black);
|
||||
int actionBarColorFrom = getResources().getColor(R.color.transparentActionBarColor);
|
||||
int actionBarElementColorFrom = getResources().getColor(android.R.color.white);
|
||||
int colorTo = getResources().getColor(android.R.color.transparent);
|
||||
|
||||
final ValueAnimator activityColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), activityColorFrom, colorTo);
|
||||
final ValueAnimator actionBarColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarColorFrom, colorTo);
|
||||
final ValueAnimator actionBarElementColorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), actionBarElementColorFrom, colorTo);
|
||||
|
||||
activityColorAnimation.setDuration(300); // milliseconds
|
||||
actionBarColorAnimation.setDuration(300);
|
||||
actionBarElementColorAnimation.setDuration(300);
|
||||
|
||||
activityColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
relativeLayout.setBackgroundColor((int) valueAnimator.getAnimatedValue());
|
||||
}
|
||||
});
|
||||
|
||||
actionBarColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
actionBar.setBackgroundDrawable(new ColorDrawable((int) valueAnimator.getAnimatedValue()));
|
||||
}
|
||||
});
|
||||
|
||||
actionBarElementColorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
text.setSpan(new ForegroundColorSpan((int) valueAnimator.getAnimatedValue()), 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
actionBar.setTitle(text);
|
||||
upArrow.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN);
|
||||
if(mMenu != null) {
|
||||
Drawable drawable = mMenu.getItem(0).getIcon();
|
||||
drawable.setColorFilter((int) valueAnimator.getAnimatedValue(), PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
swipe = new Swipe();
|
||||
swipe.setListener(new SimpleSwipeListener() {
|
||||
@Override
|
||||
public void onSwipingUp(final MotionEvent event) {
|
||||
float nowY = event.getY();
|
||||
float offset;
|
||||
if(touchY == -1.0f) {
|
||||
offset = 0.0f;
|
||||
} else {
|
||||
offset = nowY - touchY;
|
||||
}
|
||||
totalLengthY += offset;
|
||||
touchY = nowY;
|
||||
videoPlayerView.animate()
|
||||
.y(totalLengthY)
|
||||
.setDuration(0)
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSwipedUp(final MotionEvent event) {
|
||||
videoPlayerView.animate()
|
||||
.y(0)
|
||||
.setDuration(300)
|
||||
.start();
|
||||
|
||||
if(totalLengthY < -pxHeight / 8) {
|
||||
videoPlayerView.animate()
|
||||
.y(-pxHeight)
|
||||
.setDuration(300)
|
||||
.setListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
activityColorAnimation.start();
|
||||
actionBarColorAnimation.start();
|
||||
actionBarElementColorAnimation.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {}
|
||||
})
|
||||
.start();
|
||||
} else {
|
||||
videoPlayerView.animate()
|
||||
.y(0)
|
||||
.setDuration(300)
|
||||
.start();
|
||||
}
|
||||
|
||||
totalLengthY = 0.0f;
|
||||
touchY = -1.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipingDown(final MotionEvent event) {
|
||||
float nowY = event.getY();
|
||||
float offset;
|
||||
if(touchY == -1.0f) {
|
||||
offset = 0.0f;
|
||||
} else {
|
||||
offset = nowY - touchY;
|
||||
}
|
||||
totalLengthY += offset;
|
||||
touchY = nowY;
|
||||
videoPlayerView.animate()
|
||||
.y(totalLengthY)
|
||||
.setDuration(0)
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSwipedDown(final MotionEvent event) {
|
||||
if(totalLengthY > pxHeight / 8) {
|
||||
videoPlayerView.animate()
|
||||
.y(pxHeight)
|
||||
.setDuration(300)
|
||||
.setListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
activityColorAnimation.start();
|
||||
actionBarColorAnimation.start();
|
||||
actionBarElementColorAnimation.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {}
|
||||
})
|
||||
.start();
|
||||
} else {
|
||||
videoPlayerView.animate()
|
||||
.y(0)
|
||||
.setDuration(300)
|
||||
.start();
|
||||
}
|
||||
|
||||
totalLengthY = 0.0f;
|
||||
touchY = -1.0f;
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
videoPlayerView.setControllerVisibilityListener(new PlayerControlView.VisibilityListener() {
|
||||
@Override
|
||||
public void onVisibilityChange(int visibility) {
|
||||
switch (visibility) {
|
||||
case View.GONE:
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_IMMERSIVE);
|
||||
break;
|
||||
case View.VISIBLE:
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
|
||||
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
||||
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
|
||||
videoPlayerView.setPlayer(player);
|
||||
// Produces DataSource instances through which media data is loaded.
|
||||
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
|
||||
Util.getUserAgent(this, "Infinity"), bandwidthMeter);
|
||||
|
||||
// Prepare the player with the source.
|
||||
if(mIsDashVideo) {
|
||||
DashChunkSource.Factory dashChunkSourceFactory = new DefaultDashChunkSource.Factory(dataSourceFactory);
|
||||
player.prepare(new DashMediaSource(mVideoUri, dataSourceFactory, dashChunkSourceFactory, null, null));
|
||||
} else {
|
||||
player.prepare(new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(mVideoUri));
|
||||
}
|
||||
player.setRepeatMode(Player.REPEAT_MODE_ALL);
|
||||
player.setPlayWhenReady(true);
|
||||
wasPlaying = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if(!mIsDashVideo) {
|
||||
getMenuInflater().inflate(R.menu.view_video, menu);
|
||||
mMenu = menu;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
swipe.dispatchTouchEvent(ev);
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
player.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
case R.id.action_download_view_video:
|
||||
isDownloading = true;
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
// Permission is not granted
|
||||
// No explanation needed; request the permission
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||
PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||
} else {
|
||||
// Permission has already been granted
|
||||
download();
|
||||
}
|
||||
} else {
|
||||
download();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if(wasPlaying) {
|
||||
player.setPlayWhenReady(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
wasPlaying = player.getPlayWhenReady();
|
||||
player.setPlayWhenReady(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if(requestCode == PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE && grantResults.length > 0) {
|
||||
if(grantResults[0] == PackageManager.PERMISSION_DENIED) {
|
||||
Toast.makeText(this, "No storage permission to save this file", Toast.LENGTH_SHORT).show();
|
||||
} else if(grantResults[0] == PackageManager.PERMISSION_GRANTED && isDownloading) {
|
||||
download();
|
||||
}
|
||||
isDownloading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void download() {
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(mDownloadUrl));
|
||||
request.setTitle(mGifOrVideoFileName);
|
||||
|
||||
request.allowScanningByMediaScanner();
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES + "/Infinity/", mGifOrVideoFileName);
|
||||
|
||||
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.enqueue(request);
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.StringRequest;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by alex on 3/14/18.
|
||||
*/
|
||||
|
||||
class VoteThing {
|
||||
|
||||
interface VoteThingListener {
|
||||
void onVoteThingSuccess(int position);
|
||||
void onVoteThingFail(int position);
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private VoteThingListener mVoteThingListener;
|
||||
private RequestQueue mQueue;
|
||||
private RequestQueue mAcquireAccessTokenRequestQueue;
|
||||
|
||||
VoteThing(Context context, RequestQueue queue, RequestQueue acquireAccessTokenRequestQueue) {
|
||||
mContext = context;
|
||||
mQueue = queue;
|
||||
mAcquireAccessTokenRequestQueue = acquireAccessTokenRequestQueue;
|
||||
}
|
||||
|
||||
void votePost(VoteThingListener voteThingListener, final String fullName, final String point, final int position, final int refreshTime) {
|
||||
if(mContext != null) {
|
||||
if(refreshTime < 0) {
|
||||
mVoteThingListener.onVoteThingFail(position);
|
||||
return;
|
||||
}
|
||||
mVoteThingListener = voteThingListener;
|
||||
StringRequest voteRequest = new StringRequest(Request.Method.POST, RedditUtils.OAUTH_API_BASE_URI + RedditUtils.VOTE_SUFFIX, new Response.Listener<String>() {
|
||||
@Override
|
||||
public void onResponse(String response) {
|
||||
mVoteThingListener.onVoteThingSuccess(position);
|
||||
}
|
||||
}, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
if (error instanceof AuthFailureError) {
|
||||
//Access token expired
|
||||
new AcquireAccessToken(mContext).refreshAccessToken(mAcquireAccessTokenRequestQueue,
|
||||
new AcquireAccessToken.AcquireAccessTokenListener() {
|
||||
@Override
|
||||
public void onAcquireAccessTokenSuccess() {
|
||||
votePost(mVoteThingListener, fullName, point, position, refreshTime - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAcquireAccessTokenFail() {}
|
||||
});
|
||||
} else {
|
||||
mVoteThingListener.onVoteThingFail(position);
|
||||
}
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
protected Map<String, String> getParams() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put(RedditUtils.DIR_KEY, point);
|
||||
params.put(RedditUtils.ID_KEY, fullName);
|
||||
params.put(RedditUtils.RANK_KEY, RedditUtils.RANK);
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getHeaders() {
|
||||
String accessToken = mContext.getSharedPreferences(SharedPreferencesUtils.AUTH_CODE_FILE_KEY, Context.MODE_PRIVATE).getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, "");
|
||||
return RedditUtils.getOAuthHeader(accessToken);
|
||||
}
|
||||
};
|
||||
voteRequest.setTag(VoteThing.class);
|
||||
mQueue.add(voteRequest);
|
||||
}
|
||||
}
|
||||
}
|
BIN
app/src/main/res/drawable-hdpi/baseline_add_white_24.png
Executable file
After Width: | Height: | Size: 138 B |
BIN
app/src/main/res/drawable-hdpi/ic_arrow_downward_black_24dp.png
Normal file
After Width: | Height: | Size: 185 B |
BIN
app/src/main/res/drawable-hdpi/ic_arrow_upward_black_24dp.png
Normal file
After Width: | Height: | Size: 197 B |
BIN
app/src/main/res/drawable-hdpi/ic_link.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
app/src/main/res/drawable-hdpi/ic_share_black_24dp.png
Normal file
After Width: | Height: | Size: 398 B |
BIN
app/src/main/res/drawable-mdpi/baseline_add_white_24.png
Executable file
After Width: | Height: | Size: 92 B |
BIN
app/src/main/res/drawable-mdpi/ic_arrow_downward_black_24dp.png
Normal file
After Width: | Height: | Size: 142 B |
BIN
app/src/main/res/drawable-mdpi/ic_arrow_upward_black_24dp.png
Normal file
After Width: | Height: | Size: 147 B |
BIN
app/src/main/res/drawable-mdpi/ic_link.png
Normal file
After Width: | Height: | Size: 299 B |
BIN
app/src/main/res/drawable-mdpi/ic_share_black_24dp.png
Normal file
After Width: | Height: | Size: 262 B |
12
app/src/main/res/drawable-v21/ic_menu_camera.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" />
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z" />
|
||||
</vector>
|
9
app/src/main/res/drawable-v21/ic_menu_gallery.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z" />
|
||||
</vector>
|
9
app/src/main/res/drawable-v21/ic_menu_manage.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z" />
|
||||
</vector>
|
9
app/src/main/res/drawable-v21/ic_menu_send.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z" />
|
||||
</vector>
|
9
app/src/main/res/drawable-v21/ic_menu_share.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" />
|
||||
</vector>
|
9
app/src/main/res/drawable-v21/ic_menu_slideshow.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z" />
|
||||
</vector>
|
34
app/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
BIN
app/src/main/res/drawable-xhdpi/baseline_add_white_24.png
Executable file
After Width: | Height: | Size: 97 B |
BIN
app/src/main/res/drawable-xhdpi/ic_arrow_downward_black_24dp.png
Normal file
After Width: | Height: | Size: 221 B |
BIN
app/src/main/res/drawable-xhdpi/ic_arrow_upward_black_24dp.png
Normal file
After Width: | Height: | Size: 204 B |
BIN
app/src/main/res/drawable-xhdpi/ic_link.png
Normal file
After Width: | Height: | Size: 476 B |
BIN
app/src/main/res/drawable-xhdpi/ic_share_black_24dp.png
Normal file
After Width: | Height: | Size: 483 B |
BIN
app/src/main/res/drawable-xxhdpi/baseline_add_white_24.png
Executable file
After Width: | Height: | Size: 97 B |
After Width: | Height: | Size: 283 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_arrow_upward_black_24dp.png
Normal file
After Width: | Height: | Size: 302 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_link.png
Normal file
After Width: | Height: | Size: 832 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_share_black_24dp.png
Normal file
After Width: | Height: | Size: 675 B |
BIN
app/src/main/res/drawable-xxxhdpi/baseline_add_white_24.png
Executable file
After Width: | Height: | Size: 102 B |
After Width: | Height: | Size: 376 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_arrow_upward_black_24dp.png
Normal file
After Width: | Height: | Size: 341 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_share_black_24dp.png
Normal file
After Width: | Height: | Size: 888 B |
5
app/src/main/res/drawable/ic_arrow_back_white_24dp.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
|
||||
</vector>
|
@ -0,0 +1,4 @@
|
||||
<vector android:height="12dp" android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0" android:width="12dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#010101" android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"/>
|
||||
</vector>
|
4
app/src/main/res/drawable/ic_arrow_upward_black_12dp.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<vector android:height="12dp" android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0" android:width="12dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M4,12l1.41,1.41L11,7.83V20h2V7.83l5.58,5.59L20,12l-8,-8 -8,8z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_comment_white_24dp.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M21.99,4c0,-1.1 -0.89,-2 -1.99,-2L4,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h14l4,4 -0.01,-18zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
|
||||
</vector>
|
170
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
4
app/src/main/res/drawable/ic_reply_black_12dp.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<vector android:height="12dp" android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0" android:width="12dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M10,9V5l-7,7 7,7v-4.1c5,0 8.5,1.6 11,5.1 -1,-5 -4,-10 -11,-11z"/>
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_send_black_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
16
app/src/main/res/drawable/nsfw_rounded_corner.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<!--<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/colorPrimary" />-->
|
||||
|
||||
<solid android:color="@color/colorAccent" />
|
||||
|
||||
<padding
|
||||
android:left="4dp"
|
||||
android:right="4dp"
|
||||
android:top="4dp"
|
||||
android:bottom="4dp"/>
|
||||
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
16
app/src/main/res/drawable/rounded_corner.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<!--<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/colorPrimary" />-->
|
||||
|
||||
<solid android:color="@color/colorPrimary" />
|
||||
|
||||
<padding
|
||||
android:left="4dp"
|
||||
android:right="4dp"
|
||||
android:top="4dp"
|
||||
android:bottom="4dp"/>
|
||||
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
9
app/src/main/res/drawable/side_nav_bar.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="135"
|
||||
android:centerColor="#1565C0"
|
||||
android:endColor="#0D47A1"
|
||||
android:startColor="#1976D2"
|
||||
android:type="linear" />
|
||||
</shape>
|
14
app/src/main/res/layout/activity_login.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout 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"
|
||||
tools:context="ml.docilealligator.infinityforreddit.LoginActivity">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webview_login_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
26
app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.DrawerLayout 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:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:openDrawer="start">
|
||||
|
||||
<include
|
||||
layout="@layout/app_bar_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<android.support.design.widget.NavigationView
|
||||
android:id="@+id/nav_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:fitsSystemWindows="true"
|
||||
app:headerLayout="@layout/nav_header_main"
|
||||
app:menu="@menu/activity_main_drawer" />
|
||||
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
23
app/src/main/res/layout/activity_view_image.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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"
|
||||
android:id="@+id/parent_relative_layout_view_image_activity"
|
||||
android:background="@android:color/black"
|
||||
tools:context="ml.docilealligator.infinityforreddit.ViewImageActivity">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar_view_image_activity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true" />
|
||||
|
||||
<com.alexvasilkov.gestures.views.GestureImageView
|
||||
android:id="@+id/image_view_view_image_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:gest_fillViewport="true" />
|
||||
|
||||
</RelativeLayout>
|
257
app/src/main/res/layout/activity_view_post_detail.xml
Normal file
@ -0,0 +1,257 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout 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:id="@+id/coordinator_layout_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ViewPostDetailActivity">
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:descendantFocusability="blocksDescendants">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/relative_view_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/subreddit_icon_circle_image_view_view_post_detail"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subreddit_text_view_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_toEndOf="@id/subreddit_icon_circle_image_view_view_post_detail"
|
||||
android:layout_toStartOf="@id/post_time_text_view_view_post_detail"
|
||||
android:textColor="#E91E63" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/post_time_text_view_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_text_view_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:textColor="#000000"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/content_text_view_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/type_text_view_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nsfw_text_view_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/nsfw_rounded_corner"
|
||||
android:textColor="@android:color/white"
|
||||
android:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/image_view_wrapper_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitStart"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_no_preview_link_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="150dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="#E0E0E0"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_link"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/plus_button_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_arrow_upward_black_24dp"
|
||||
android:tint="@android:color/tab_indicator_text" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/score_text_view_view_post_detail"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/plus_button_view_post_detail"
|
||||
android:gravity="center" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/minus_button_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/score_text_view_view_post_detail"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_arrow_downward_black_24dp"
|
||||
android:tint="@android:color/tab_indicator_text" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/share_button_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_share_black_24dp"
|
||||
android:tint="@android:color/tab_indicator_text" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/comment_progress_bar_view_post_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="16dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/comment_card_view_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:text="@string/comments"
|
||||
android:textColor="#000000"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_view_post_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
18
app/src/main/res/layout/activity_view_video.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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"
|
||||
android:background="@android:color/black"
|
||||
android:id="@+id/relative_layout_view_video_activity"
|
||||
android:keepScreenOn="true"
|
||||
tools:context="ml.docilealligator.infinityforreddit.ViewVideoActivity">
|
||||
|
||||
<com.google.android.exoplayer2.ui.PlayerView
|
||||
android:id="@+id/player_view_view_video_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:controller_layout_id="@layout/exo_playback_control_view"/>
|
||||
|
||||
</RelativeLayout>
|
25
app/src/main/res/layout/app_bar_main.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout 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"
|
||||
tools:context="ml.docilealligator.infinityforreddit.MainActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
10
app/src/main/res/layout/content_main.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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:id="@+id/frame_layout_content_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context="ml.docilealligator.infinityforreddit.MainActivity"
|
||||
tools:showIn="@layout/app_bar_main" />
|
66
app/src/main/res/layout/exo_playback_control_view.xml
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/linear_layout_exo_playback_control_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@color/transparentActionBarColor"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingTop="4dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton android:id="@id/exo_rew"
|
||||
style="@style/ExoMediaButton.Rewind"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_play"
|
||||
style="@style/ExoMediaButton.Play"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_pause"
|
||||
style="@style/ExoMediaButton.Pause"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_ffwd"
|
||||
style="@style/ExoMediaButton.FastForward"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView android:id="@id/exo_position"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:includeFontPadding="false"
|
||||
android:textColor="#FFBEBEBE"/>
|
||||
|
||||
<com.google.android.exoplayer2.ui.DefaultTimeBar
|
||||
android:id="@id/exo_progress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="26dp"/>
|
||||
|
||||
<TextView android:id="@id/exo_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:includeFontPadding="false"
|
||||
android:textColor="#FFBEBEBE"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
28
app/src/main/res/layout/fragment_best_post.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/coordinator_layout_best_post_fragment"
|
||||
tools:context="ml.docilealligator.infinityforreddit.BestPostFragment">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar_best_post_fragment"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_best_post_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_best_post_fragment"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:srcCompat="@drawable/baseline_add_white_24" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
179
app/src/main/res/layout/item_best_post.xml
Normal file
@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:id="@+id/card_view_view_post_detail">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/relative_view_item_best_post"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/subreddit_icon_circle_image_view_best_post_item"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subreddit_text_view_best_post_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_toEndOf="@id/subreddit_icon_circle_image_view_best_post_item"
|
||||
android:layout_centerVertical="true"
|
||||
android:textColor="#E91E63"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/post_time_text_view_best_post_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_text_view_best_post_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textSize="18sp"
|
||||
android:textColor="#000000"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/type_text_view_item_best_post"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nsfw_text_view_item_best_post"
|
||||
android:text="@string/nsfw"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/nsfw_rounded_corner"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/image_view_wrapper_item_best_post"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="350dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar_best_post_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_best_post_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_view_no_preview_link_best_post_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="150dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_link"
|
||||
android:background="#E0E0E0"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/plus_button_item_best_post"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_arrow_upward_black_24dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:tint="@android:color/tab_indicator_text"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/score_text_view_item_best_post"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/plus_button_item_best_post"
|
||||
android:gravity="center"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/minus_button_item_best_post"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/score_text_view_item_best_post"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_arrow_downward_black_24dp"
|
||||
android:tint="@android:color/tab_indicator_text"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/share_button_item_best_post"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_share_black_24dp"
|
||||
android:tint="@android:color/tab_indicator_text"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
46
app/src/main/res/layout/item_footer_progress_bar.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/linear_layout_footer_progress_bar_item"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar_footer_progress_bar_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/relative_layout_footer_progress_bar_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toStartOf="@id/retry_button_footer_progress_bar_item"
|
||||
android:layout_alignParentStart="true"
|
||||
android:text="@string/load_data_failed"
|
||||
android:textSize="18sp"
|
||||
android:layout_centerVertical="true" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/retry_button_footer_progress_bar_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="@string/retry" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
105
app/src/main/res/layout/item_post_comment.xml
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/linear_layout_item_post_comment"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/author_text_view_item_post_comment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/comment_time_text_view_item_post_comment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:layout_marginEnd="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/comment_text_view_item_post_comment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginRight="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:textColor="#000000"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/relative_layout_item_post_comment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginEnd="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/plus_button_item_post_comment"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_arrow_upward_black_12dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:tint="@android:color/tab_indicator_text"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/score_text_view_item_post_comment"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/plus_button_item_post_comment"
|
||||
android:gravity="center"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/minus_button_item_post_comment"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/score_text_view_item_post_comment"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_arrow_downward_black_12dp"
|
||||
android:tint="@android:color/tab_indicator_text"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/reply_button_item_post_comment"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:padding="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:src="@drawable/ic_reply_black_12dp"
|
||||
android:tint="@android:color/tab_indicator_text"
|
||||
android:background="?actionBarItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
44
app/src/main/res/layout/nav_header_main.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/nav_header_height"
|
||||
android:background="@drawable/side_nav_bar"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/banner_image_view_nav_header_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"/>
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/profile_image_view_nav_header_main"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name_text_view_nav_header_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/nav_header_vertical_spacing"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||
android:layout_below="@id/profile_image_view_nav_header_main"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/karma_text_view_nav_header_main"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_below="@id/name_text_view_nav_header_main"/>
|
||||
|
||||
</RelativeLayout>
|
38
app/src/main/res/menu/activity_main_drawer.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:showIn="navigation_view">
|
||||
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_camera"
|
||||
android:icon="@drawable/ic_menu_camera"
|
||||
android:title="Import" />
|
||||
<item
|
||||
android:id="@+id/nav_gallery"
|
||||
android:icon="@drawable/ic_menu_gallery"
|
||||
android:title="Gallery" />
|
||||
<item
|
||||
android:id="@+id/nav_slideshow"
|
||||
android:icon="@drawable/ic_menu_slideshow"
|
||||
android:title="Slideshow" />
|
||||
<item
|
||||
android:id="@+id/nav_manage"
|
||||
android:icon="@drawable/ic_menu_manage"
|
||||
android:title="Tools" />
|
||||
</group>
|
||||
|
||||
<item android:title="Communicate">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/nav_share"
|
||||
android:icon="@drawable/ic_menu_share"
|
||||
android:title="Share" />
|
||||
<item
|
||||
android:id="@+id/nav_send"
|
||||
android:icon="@drawable/ic_menu_send"
|
||||
android:title="Send" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
</menu>
|
9
app/src/main/res/menu/main.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
10
app/src/main/res/menu/view_image.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_download_view_image"
|
||||
android:orderInCategory="1"
|
||||
android:title="@string/action_download"
|
||||
android:icon="@drawable/ic_file_download_white_24dp"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|